diff --git a/benchmarks/perp-cost-slope.yml b/benchmarks/perp-cost-slope.yml index 540d9279..ad0bf70a 100644 --- a/benchmarks/perp-cost-slope.yml +++ b/benchmarks/perp-cost-slope.yml @@ -9,7 +9,7 @@ subtitle: "Ratio of all-in opening cost at $1,000,000 vs $1,000 notional, per ve category: Trading status: live metric: "Cost slope ($1M / $1k)" -unit: count +unit: x higher_is_better: false seo_intro: | diff --git a/benchmarks/perp-exit-custody.yml b/benchmarks/perp-exit-custody.yml new file mode 100644 index 00000000..092b6483 --- /dev/null +++ b/benchmarks/perp-exit-custody.yml @@ -0,0 +1,187 @@ +# OpenChainBench. Bench 123 + +slug: perp-exit-custody +number: "123" +title: "Perp DEX exit custody: worst-case hours to withdraw without operator help, live" +seo_title: "Perp DEX custody risk 2026" +seo_description: "Lighter leads perp DEX exit independence at 336h worst-case (14-day Desert Mode, self-provable ZK exit). Ostium 720h (public tryNewSettlement() fallback). gains.trade, GMX, Hyperliquid and Aster have no permissionless exit path. Withdrawal depends on operator liveness. Live settlement age monitored." +subtitle: "Worst-case hours a user must wait to withdraw funds without any operator or validator cooperation. Lower is better. Venues with no permissionless exit path are ranked last. Settlement freshness monitored live via RPC for venues with on-chain settlement mechanisms." +category: Trading +status: live +metric: Worst-case exit hours (no operator) +unit: count +higher_is_better: false + +disclaimer: | + Worst-case exit hours: if the protocol operator (keeper, sequencer, validator set) went offline permanently, how long until a user can withdraw without any cooperation? Venues with no permissionless path are marked infinity. This is a custody-risk metric, not a UX metric. In normal operation all venues process withdrawals faster. Evidence tier (bytecode/documented) noted per venue. + +seo_intro: | + The standard perp DEX comparison covers fees, speed and liquidity. It + almost never covers the question that matters most for large capital: + if the team disappeared tomorrow, could you get your money out? + This benchmark measures the worst-case hours to permissionless + withdrawal for seven major perp venues: gains.trade, GMX v2, Ostium, + Vertex, Hyperliquid, Lighter and Aster, using on-chain source code + analysis (Slither, cast) and official documentation as evidence. + + The results are not intuitive. The protocol with the most + censorship-resistant LP exit on Arbitrum is Ostium, not through + any design claim, but because its vault source code contains a + public function, tryNewSettlement(), that anyone can call once + the maxSettlementInterval elapses. gains.trade and GMX v2 have + no equivalent: gains LP withdrawals require oracle epochs to + advance (oracle-triggered, not time-triggered), and GMX withdrawals + require keeper execution with the CONTROLLER role. Hyperliquid, + the volume leader, has no escape hatch: the bridge contract on + Arbitrum is upgradeable by a single EOA with no timelock, and + withdrawals require 2/3 validator co-signature with no user override. + The only venue with a formally bounded exit window under operator + failure is Lighter, via a 14-day Desert Mode triggered from the + Ethereum priority queue. + +abstract: | + The harness combines two layers. The first is a static registry + (registry.yaml) encoding the exit architecture per venue: whether + a permissionless exit path exists, what its trigger mechanism is, + and the worst-case duration in hours. This registry is derived from + verified smart contract source code (via deficollective/permission-scanner + with Slither) for EVM venues and from official documentation plus + L2Beat for non-EVM venues. The confidence tier (bytecode/onchain/documented) + is stored per field. + + The second layer is a live RPC/HTTP probe that runs every 5 minutes + and emits fresh metrics for venues with on-chain settlement mechanisms. + For Ostium the harness reads lastSettlementTs and maxSettlementInterval + from the OstiumVault proxy to compute settlement age in seconds and + a flag for whether tryNewSettlement() is currently callable. For + gains.trade the harness reads currentEpoch() and currentEpochStart() + from each gToken vault to track epoch freshness. + + The worst-case exit hours for each venue: + gains.trade: infinity (oracle must advance epochs; no time-based override). + GMX v2: infinity (keeper CONTROLLER role required to execute withdrawals; no override). + Ostium: 720h (3 settlements x 30-day maxSettlementInterval; tryNewSettlement() public). + Vertex: unknown (implementation contracts not verified on Arbiscan; architecture opaque). + Hyperliquid: infinity (2/3 validator co-sign required; no escape hatch; bridge upgradeable by EOA). + Lighter: 336h (14-day Desert Mode from priority queue; self-provable ZK exit; circuits open source). + Aster: infinity (2/3 internal validator co-sign required; no escape hatch documented). + +methodology: + - "Static architecture: contract source code downloaded via Etherscan API v2 for EVM venues; analyzed with deficollective/permission-scanner (Slither). Evidence tier noted per field: bytecode (from verified source), onchain (from direct RPC read), documented (from official docs or L2Beat)." + - "gains.trade (gToken vaults, solc 0.8.9): withdraw()/redeem() have no admin modifier (ERC4626 checks only), but maxWithdraw(holder) = 0 for real holders. Mandatory 2-step: makeWithdrawRequest() then wait 3 oracle epochs then withdraw(). Epochs advance via openTradesPnlFeed oracle callback, not by time. If oracle stops, epochs freeze indefinitely. Current epoch: {{metric:perp_exit_epoch_number{venue=gains}}}." + - "GMX v2 (DataStore solc 0.8.18, Timelock solc 0.8.18): scanner found 39 DataStore functions gated onlyController. Withdrawals via WithdrawalHandler require keeper bots with CONTROLLER role. cancelWithdrawal() lets users recover pending requests but not execute them. Worst-case: keepers offline, no exit. Custom Timelock TIMELOCK_ADMIN held by 2 plain EOAs among 4 holders." + - "Ostium (OstiumVault impl solc 0.8.24): requestWithdraw has checks modifier; claimWithdraw has none. Settlement: (a) operator calls _settlement(); (b) anyone calls tryNewSettlement() PUBLIC once maxSettlementInterval (30 days, changed from 24h by gov) elapses. withdrawSettlementDelay=2 means 3 settlements needed. Worst-case: 3x30 = 90 days. Live: settlement age {{metric:perp_exit_settlement_age_hours{venue=ostium}}}h, callable: {{metric:perp_exit_settlement_callable{venue=ostium}}}." + - "Vertex (Arbitrum, Endpoint proxy solc 0.8.2): ALL implementation contracts (Endpoint impl 0x91ffc8, Clearinghouse impl 0x63a497, SpotEngine 0x32d91a, PerpEngine 0xb74c78, OffchainExchange 0xa43698) are NOT verified on Arbiscan. GitHub repo documents submitSlowModeTransaction() slow-mode mechanism but bytecode cannot be compared to repo. Worst-case: unknown. Displayed as infinity." + - "Hyperliquid (bridge on Arbitrum 0x2Df1c5, verified): L2Beat confirmed bridge upgradeable by EOA with no timelock delay. Withdrawals require 2/3+ staking-weighted validator co-signature (~27 nodes, historically team-controlled). No escape hatch documented. Worst-case: infinity. L2Beat: no window for users to exit since contracts are instantly upgradeable. Category: Other (not rated as L2)." + - "Lighter (Ethereum mainnet, ZkLighter 0x3B4D79, verified, L2Beat Stage 0): Desert Mode triggers when sequencer ignores priority queue for 14 days. Rollup freezes; user self-generates ZK proof of balance from Ethereum blob data and exits directly from contract. Prover circuits open source at github.com/elliottech/lighter-prover, audited by ZKSecurity. UpgradeGatekeeper has no delay, concurrent risk. Worst-case: 14 days = 336h." + - "Aster (multi-chain: BNB primary, ETH, ARB, SOL): cross-chain withdrawals require 2-of-3 internal validator co-signature. No forced exit or escape hatch documented. Core chain (Aster PoSA L1, March 2026) closed source. Upgrade key management not disclosed. Worst-case: infinity. Tier: documented (bridge contracts not independently verified at measurement time)." + - "Live probe cadence: every 5 minutes. Ostium: cast call OstiumVault lastSettlementTs() and maxSettlementInterval() on Arbitrum. gains: cast call gDAI currentEpoch() and currentEpochStart(). Hyperliquid: bridge USDC balance on Arbitrum (sanity check). RPC: public Arbitrum One and Ethereum endpoints." + +findings: + - "Lighter is the only venue in the cohort with a formally bounded worst-case exit: 336 hours (14 days) via Desert Mode, requiring only a self-generated ZK proof from public on-chain data. No operator cooperation needed after the 14-day window." + - "Ostium is the only EVM venue on Arbitrum with a permissionless exit fallback: tryNewSettlement() is a PUBLIC function anyone can call once maxSettlementInterval (currently 30 days) elapses. Worst-case: 3 settlements x 30 days = 90 days. Settlement age live: {{metric:perp_exit_settlement_age_hours{venue=ostium}}}h." + - "gains.trade LP exit has no admin permission gate (withdraw/redeem use ERC4626 checks modifier) but requires 3 oracle epoch advances. Epochs are triggered by openTradesPnlFeed oracle callbacks, not by time. If the oracle stops, epochs freeze indefinitely. Worst-case: infinity. Current epoch: {{metric:perp_exit_epoch_number{venue=gains}}}." + - "GMX v2 withdrawals require keeper bots with the CONTROLLER role to execute. No user override exists. Worst-case: infinity. Additional finding: 2 of 4 TIMELOCK_ADMIN holders in GMX custom Timelock are plain EOAs (single private key, no multisig)." + - "Hyperliquid bridge (Arbitrum 0x2Df1c5) is upgradeable by a single EOA with no timelock (L2Beat CRITICAL flag). Withdrawals require 2/3+ validator co-signature. No escape hatch. Worst-case: infinity." + - "Vertex implementation contracts (Endpoint, Clearinghouse, SpotEngine, PerpEngine, OffchainExchange) are NOT verified on Arbiscan. The GitHub repo documents a slow-mode exit but bytecode cannot be confirmed to match. Worst-case: unknown." + - "Aster cross-chain withdrawals require 2-of-3 internal validator co-sign. No forced exit documented. Core chain closed source. Worst-case: infinity. Tier: documented only." + +source: https://github.com/ChainBench/OpenChainBench/tree/main/harnesses/permissions-scan + +prometheus: + window: 24h + expected_freshness_seconds: 600 + freshness_metric: perp_exit_settlement_age_seconds + +faq: + - q: "What does 'worst-case exit hours' mean?" + a: "The hours a user would wait to withdraw all funds if the protocol operator (keeper, sequencer, validator set) went permanently offline right now, with no operator cooperation. Venues with no permissionless path are marked infinity. In normal operation all venues process withdrawals much faster." + - q: "Why does Ostium rank better than gains.trade for LP custody?" + a: "Ostium's OstiumVault has tryNewSettlement(), a public function anyone can call once maxSettlementInterval (30 days currently) has passed since the last settlement. After it fires, claimWithdraw() has no permission modifier and executes immediately. gains.trade gToken epochs advance only when the openTradesPnlFeed oracle provides a new value; there is no time-based override. If the oracle stops, gains LP withdrawals are frozen with no user override." + - q: "Does 'no admin gate on withdraw()' mean permissionless exit?" + a: "Not necessarily. The Slither permission scanner only reports modifier-level access control. It does not detect state-based locks: epoch locks (gains), settlement delays (ostium), keeper-required execution (GMX), or time-gated queues. maxWithdraw(holder) returning 0 for real holders with positive balances is the concrete on-chain test. This bench tested real gDAI holders and confirmed maxWithdraw = 0 in all cases; meaning withdraw() would revert despite having no onlyOwner modifier." + - q: "Why is Lighter rated Stage 0 if it has an escape hatch?" + a: "L2Beat's Stage 1 requires no security council or upgrade delay. Lighter's UpgradeGatekeeper EOA can upgrade the contract instantly with no delay. An instant-upgrade key can drain funds before Desert Mode would ever trigger. Stage 0 correctly reflects that the upgrade risk exists regardless of the Desert Mode mechanism." + - q: "Why are Hyperliquid's implementation contracts not on Arbitrum?" + a: "Hyperliquid runs its own L1 (HyperBFT). Only the USDC bridge is on Arbitrum. User funds are escrowed on Arbitrum; the trading logic runs on the Hyperliquid L1, which is closed source." + - q: "Why is Vertex shown as unknown rather than infinity?" + a: "Unknown is distinct from infinity. Infinity means we know no permissionless exit exists. Unknown means the bytecode of the deployed contracts is not verifiable (implementation contracts are not verified on Arbiscan), so we cannot determine from on-chain evidence whether a slow-mode exit exists in the deployed code. The GitHub repo documents one, but the repo describes intent, not the deployed system." + - q: "Is Ostium's tryNewSettlement() guaranteed to work if I call it after 30 days?" + a: "It is permissionless once the time condition is met, but it has a dependency: _updateAccPnlPerTokenUsed() is called internally, which reads from the oracle price. If the oracle feed is stale or reverts, the settlement may fail. The permissionless path is time-gated, not fully oracle-independent." + - q: "How often is this data updated?" + a: "Live metrics (settlement age, epoch number) are updated every 5 minutes via RPC probes. Architecture findings (worst-case exit hours, ownership chain, upgrade delay) are derived from versioned scanner output and updated when a governance action or contract upgrade changes the architecture. The measurement block and timestamp are stored in harnesses/permissions-scan/out/*.json." + +providers: + - slug: gains + name: gains.trade + tag: EVM Arbitrum — gToken vaults — bytecode verified + confidence_tier: bytecode + worst_case_exit_hours: .inf + formula: "Worst-case exit: infinity. Oracle must advance epochs (withdrawEpochsTimelock=3 oracle cycles). Live: perp_exit_epoch_number{venue=gains} from gDAI.currentEpoch() on Arbitrum." + queries: + current: perp_exit_epoch_number{venue="gains"} + epoch_age_hours: perp_exit_epoch_age_hours{venue="gains"} + settlement_callable: perp_exit_settlement_callable{venue="gains"} + series: perp_exit_epoch_age_hours{venue="gains"} + + - slug: gmx + name: GMX v2 + tag: EVM Arbitrum — WithdrawalHandler keeper — bytecode verified + confidence_tier: bytecode + worst_case_exit_hours: .inf + formula: "Worst-case exit: infinity. Keeper CONTROLLER role required to execute withdrawals; no user override. Live: no recurrent settlement metric (operator-gated)." + queries: + current: perp_exit_worst_case_hours{venue="gmx"} + series: perp_exit_worst_case_hours{venue="gmx"} + + - slug: ostium + name: Ostium + tag: EVM Arbitrum — tryNewSettlement() public — bytecode verified + confidence_tier: bytecode + worst_case_exit_hours: 720 + formula: "Worst-case: 3x maxSettlementInterval (30 days = 720h per round). tryNewSettlement() is public; callable by anyone once interval passes. Live: perp_exit_settlement_age_hours{venue=ostium}." + queries: + current: perp_exit_settlement_age_hours{venue="ostium"} + settlement_callable: perp_exit_settlement_callable{venue="ostium"} + last_settlement_id: perp_exit_last_settlement_id{venue="ostium"} + series: perp_exit_settlement_age_hours{venue="ostium"} + + - slug: vertex + name: Vertex + tag: EVM Arbitrum — impl unverified — unknown + confidence_tier: unknown + worst_case_exit_hours: .inf + formula: "Worst-case exit: unknown. Endpoint impl, Clearinghouse impl, SpotEngine, PerpEngine, OffchainExchange are NOT verified on Arbiscan. GitHub repo documents slow-mode but bytecode cannot be confirmed." + queries: + current: perp_exit_worst_case_hours{venue="vertex"} + series: perp_exit_worst_case_hours{venue="vertex"} + + - slug: hyperliquid + name: Hyperliquid + tag: Custom L1 HyperBFT — ARB bridge EOA-upgradeable — documented + confidence_tier: documented + worst_case_exit_hours: .inf + formula: "Worst-case exit: infinity. 2/3+ validator co-sign required. Bridge upgradeable by single EOA with no timelock. No escape hatch. L2Beat CRITICAL flag. Live: perp_exit_bridge_balance_usd{venue=hyperliquid}." + queries: + current: perp_exit_bridge_balance_usd{venue="hyperliquid"} + series: perp_exit_bridge_balance_usd{venue="hyperliquid"} + + - slug: lighter + name: Lighter + tag: ETH ZK-rollup — Desert Mode 14d — documented + confidence_tier: documented + worst_case_exit_hours: 336 + formula: "Worst-case: 336h (14 days). Desert Mode triggers from Ethereum priority queue after sequencer ignores for 14 days. User self-generates ZK proof and exits. Prover open source. UpgradeGatekeeper EOA has no delay; concurrent risk." + queries: + current: perp_exit_worst_case_hours{venue="lighter"} + series: perp_exit_worst_case_hours{venue="lighter"} + + - slug: aster + name: Aster + tag: Multi-chain BNB/ETH/ARB/SOL — 2/3 internal validators — documented + confidence_tier: documented + worst_case_exit_hours: .inf + formula: "Worst-case exit: infinity. 2/3 internal validator co-sign required. No forced exit or escape hatch documented. Core chain closed source." + queries: + current: perp_exit_worst_case_hours{venue="aster"} + series: perp_exit_worst_case_hours{venue="aster"} diff --git a/harnesses/permissions-scan/coverage.md b/harnesses/permissions-scan/coverage.md new file mode 100644 index 00000000..e96fdd59 --- /dev/null +++ b/harnesses/permissions-scan/coverage.md @@ -0,0 +1,167 @@ +# Coverage Report — Perp DEX Exit Rights Scan + +**EVM measured:** 2026-08-02T19:08:53Z — block 490,422,447 (Arbitrum One) +**Non-EVM measured:** 2026-08-02T21:00:00Z +**Tooling:** cast (foundry 1.5.1), permission-scanner (deficollective/permission-scanner), L2Beat, Etherscan/Arbiscan API v2, source code review + +--- + +## Statut scanner + +Permission-scanner **complété** pour gains, gmx-v2, ostium. Clé Etherscan v2 récupérée depuis le VPS (variable d'environnement conteneur Docker). Scanner lancé via `python3 src/main.py` dans `/tmp/permission-scanner/` avec `contracts.json` de chaque cible. + +**Vertex : scanner non lancé** — tous les contrats d'implémentation de Vertex (Endpoint impl, Clearinghouse impl, SpotEngine, PerpEngine, OffchainExchange, Querier) ne sont PAS vérifiés sur Arbiscan. L'API Etherscan v2 retourne "Contract source code not verified" pour toutes ces adresses. Seuls les proxy wrappers (TransparentUpgradeableProxy) sont vérifiés. Le scanner ne peut pas tourner sans code source. + +--- + +## Tableau de couverture + +### EVM — Arbitrum One + +| Champ | gains | gmx-v2 | ostium | vertex | +|---|---|---|---|---| +| `contracts_list` | ✅ bytecode | ✅ bytecode | ✅ bytecode | ✅ onchain | +| `proxy_impl_resolved` | ✅ EIP-1967 + EIP-2535 | n/a | ✅ oLP + Trading | ✅ Endpoint + CH | +| `upgrade_delay_seconds` | ✅ 14j (onchain) | ✅ 1j (onchain) | ✅ 18h (onchain) | unknown — pas de Timelock | +| `owner_type` | ✅ TimelockController | ✅ GovTimelock + ProtocolGovernor + custom Timelock | ✅ Safe 4/8 → Timelock 18h | ✅ Safe 4/6 via proxy | +| `owner_addresses` | ✅ Safe 4/7 + Safe 2/4 (onchain events) | ✅ TIMELOCK_MULTISIG=Safe 5/8, ADMIN=Safe+2×EOA | ✅ Safe 4/8 owners listés | ✅ Safe 4/6 owners listés | +| `permissions_functions` | ✅ scanner (bytecode) | ✅ scanner (bytecode) | ✅ scanner (bytecode) | unknown — impls non vérifiées | +| `contracts_verified` | ✅ true | ✅ true | ✅ true | ⚠️ partial (proxies seulement) | +| `chain_l2beat_stage` | Stage 1 | Stage 1 | Stage 1 | Stage 1 | +| `lp_exit` | ❌ false — 3 oracle-epochs, maxWithdraw=0 testé | ❌ false — keeper requis | ✅ true — tryNewSettlement() public, max 90j | unknown | +| `trader_exit` | ❌ false — oracle requis | ❌ false — keeper requis | ❌ false — oracle Stork requis | unknown | +| `can_user_exit_unilaterally` | ❌ false | ❌ false | ✅ true (délai, risque gov) | unknown | +| `exit_depends_on` | oracle (epoch callbacks) | keeper CONTROLLER | gov (contrôle interval) | sequencer (bytecode inconnu) | +| `forced_inclusion` | n/a | n/a | n/a | n/a | + +### Non-EVM + +| Champ | hyperliquid | lighter | aster | +|---|---|---|---| +| `chain` | Custom L1 HyperBFT + ARB bridge | ETH ZK-rollup | Multi-chain (BNB/ETH/ARB/SOL + PoSA) | +| `funds_contract` | ✅ 0x2Df1c5 (ARB, verified) | ✅ 0x3B4D79 (ETH, verified) | documented only (unverified) | +| `contracts_verified` | partial (bridge oui, L1 fermé) | true (+ prover open source) | unknown | +| `l2beat_stage` | "Other" — non-L2 | Stage 0 Appchain | n/a | +| `upgrade_delay_seconds` | 0 — EOA sans timelock (CRITIQUE) | 0 — UpgradeGatekeeper sans délai (CRITIQUE) | unknown | +| `lp_exit` | ❌ false — validateurs requis | documented only | ❌ false — 2/3 validateurs internes | +| `trader_exit` | ❌ false — validateurs requis | ✅ true — Desert Mode 14j | ❌ false — 2/3 validateurs internes | +| `can_user_exit_unilaterally` | ❌ false | ✅ true (14j + ZK proof) | ❌ false | +| `exit_depends_on` | ~27 validateurs + EOA upgrade | séquenceur + UpgradeGatekeeper EOA | 2/3 validateurs internes | +| `forced_inclusion` | none | Desert Mode (14j) | none documenté | +| `tier_confidence` | documented | documented | documented | + +--- + +## Détail par cible + +### gains (gTrade) + +**Mesuré :** +- GNSMultiCollatDiamond proxy `0xFF162c...` + impl `0xff84c4...` (EIP-1967 + EIP-2535 Diamond) +- ProxyAdmin `0xe18be0...` → owner = GNSTimelockOwner `0x5f5E48...` +- GNSTimelockOwner `getMinDelay()` = 1 209 600 s (14 jours) — confirmé on-chain +- GNSTimelockManager `getMinDelay()` = 259 200 s (3 jours) — confirmé on-chain +- 4 gToken vaults (gDAI, gGNS, gETH, gUSDC) — contrats publics confirmés avec bytecode +- Source officielle : https://docs.gains.trade/what-is-gains-network/contract-addresses/arbitrum-mainnet + +**Scanner (complété) :** +- GToken `withdraw()` et `redeem()` : modifier `checks` (gate ERC4626 standard — vérifie les balances, PAS une restriction admin). LP peut retirer directement. +- GToken `mint()` / `burn()` : modifier `onlyOwner` (GNSTimelockOwner = 14 jours). Seul le protocole peut créer/détruire des shares. +- Diamond `diamondCut()` : modifier `onlyRoles(ROLES_MANAGER_ROLE)`. Upgrades de facets contrôlés par rôle. +- `contracts_verified` : true — GNSMultiCollatDiamond proxy (solc 0.8.9), impl (solc 0.8.23), gTokens (solc 0.8.9), timelocks (solc 0.8.17) — tous vérifiés Arbiscan. +- `can_user_exit_unilaterally` : **true** pour les LP (redeem/withdraw directs sur gToken). Traders : oracle requis pour `closeTradeMarket()`. + +**Unknown / raisons :** +- `GNSTimelockOwner_proposer` : AccessControl non-enumerable. Résolution nécessite scan d'events `RoleGranted` ou Etherscan. +- `version_confirmed` : EIP-2535 ne stocke pas de version. "v10.3" non confirmable on-chain. +- `alternative_frontend` : non vérifié. + +--- + +### gmx-v2 + +**Mesuré :** +- 12 contrats depuis `github.com/gmx-io/gmx-synthetics/deployments/arbitrum/` (JSON officiels) +- ExchangeRouter `0x602b805...` confirmé on-chain via `dataStore()` → DataStore address +- GovTimelockController `getMinDelay()` = 86 400 s (1 jour) +- GovTimelockController PROPOSER = ProtocolGovernor (confirmé `hasRole()`) +- GovTimelockController EXECUTOR = ProtocolGovernor (confirmé `hasRole()`) +- ProtocolGovernor : `proposalThreshold()` = 30 000 GovToken, `votingDelay()` = 86 400 blocs +- Custom Timelock delay = 86 400 s (slot de storage 1 = 0x15180) +- Source: `github.com/gmx-io/gmx-synthetics/tree/main/deployments/arbitrum` + +**Scanner (complété) :** +- DataStore : 39 fonctions setter toutes gated `onlyController`. Les keepers (bots) détiennent le rôle CONTROLLER dans RoleStore. +- RoleStore : `grantRole`/`revokeRole` gated `onlyRoleAdmin`. +- Custom Timelock : découverte de deux rôles non-standard — `onlyTimelockMultisig` (signalement/propose) et `onlyTimelockAdmin` (exécution/finalisation). Schéma à deux clés. +- `contracts_verified` : true — tous les 12 contrats vérifiés Arbiscan (solc 0.8.18/0.8.20). + +**Unknown / raisons :** +- `custom_Timelock_admin` / `custom_Timelock_multisig` : `gov()`, `owner()`, `timelockAdmin()` répondent par revert. Les détenteurs des rôles `onlyTimelockMultisig` et `onlyTimelockAdmin` ne sont pas résolus. Scan d'events ou lecture storage avancée requis. +- `alternative_frontend` : non vérifié. + +--- + +### ostium + +**Mesuré :** +- oLP vault proxy `0x20d419...` + impl `0x1E20E4...` (EIP-1967) +- Trading proxy `0x6d0ba1...` + impl `0x8cbb5b...` (EIP-1967) +- ProxyAdmin `0x083f97...` → owner = TimelockOwner `0xeb85dc...` (confirmé on-chain) +- TimelockOwner `getMinDelay()` = 64 800 s (18 heures) — confirmé on-chain +- PROPOSER_ROLE grantee = `0x1cd84f9b...` (Gnosis Safe 4/8, 8 owners listés) — confirmé via events `RoleGranted` + appels `getThreshold()` / `getOwners()` +- EXECUTOR_ROLE grantee = `0x1cd84f9b...` (même Safe) — confirmé via events +- Source adresses : `ostium-labs.gitbook.io/ostium-docs` (deprecated) + Arbiscan labels + +**Avertissement source :** Les adresses Ostium viennent de la doc dépréciée + Arbiscan labels, non d'une page de déploiement officielle active. La cohérence a été vérifiée (bytecode présent sur chaque adresse, ProxyAdmin → Timelock chain cohérente). Mais l'absence de source primaire documentée officielle est un risque de qualité. + +**Scanner (complété) :** +- OstiumVault : pattern async confirmé — `requestWithdraw(uint256)` → opérateur `settle()` → `claimWithdraw(uint256)`. Le `settle()` a modifier `onlyGov` : sans l'opérateur, les fonds sont bloqués après `requestWithdraw`. +- `pause()`/`unpause()` sur OstiumVault : `onlyGov`. L'opérateur peut geler les retraits. +- OstiumTrading : 22 fonctions `onlyGov` — ouverture/fermeture de positions entièrement contrôlées par gov. +- `contracts_verified` : true — proxies (solc 0.8.9), impls (solc 0.8.24), TimelockOwner (solc 0.8.24) — tous vérifiés. +- `can_user_exit_unilaterally` : **false** — retrait nécessite `settle()` opérateur entre `requestWithdraw` et `claimWithdraw`. + +**Unknown / raisons :** +- `PairInfos_impl`, `PairsStorage_impl` : slots impl non lus pour ces deux proxies. +- `alternative_frontend` : non vérifié. + +--- + +### vertex + +**Mesuré :** +- Endpoint proxy `0xbbee07...` + impl `0x91ffc8...` (EIP-1967) +- Clearinghouse proxy `0xae1ec2...` + impl `0x63a497...` (EIP-1967) +- SpotEngine, PerpEngine, OffchainExchange, Querier : bytecode présent, non-proxy +- Endpoint `owner()` = `0x2BC1F3...` (proxy lui-même, EIP-1967 impl = `0xb7eb64...`) +- `0x2BC1F3...` `owner()` = `0xC6B129...` (Gnosis Safe 4/6, 6 owners listés) +- `submitSlowModeTransaction()` dans le source GitHub de l'Endpoint : mécanisme d'exit unilatéral documenté +- Source adresses : Arbiscan search results (label "Vertex Protocol: Endpoint", etc.) + +**Scanner : non lancé (bloquer architectural) :** +- TOUS les contrats d'implémentation Vertex (Endpoint impl 0x91ffc8, Clearinghouse impl 0x63a497, SpotEngine 0x32d91a, PerpEngine 0xb74c78, OffchainExchange 0xa43698, Querier 0x169327) ne sont PAS vérifiés sur Arbiscan. +- Seuls les proxy wrappers (TransparentUpgradeableProxy) sont vérifiés — sans le code des impls, Slither ne peut pas analyser les permissions réelles. +- `contracts_verified` : **partial** — proxies vérifiés, impls non vérifiées. La surface de permission du code déployé est opaque. + +**Unknown / raisons :** +- `permissions_functions` : scanner non lancé (impls non vérifiées). +- `upgrade_delay_seconds` : aucun Timelock détecté dans la chaîne de propriété. Si le Safe 4/6 peut upgrader directement, le délai effectif est 0. +- `slowMode_timeout_seconds` : `slowModeConfig()` reverts on-chain. Valeur exacte du timeout non mesurée. +- `alternative_frontend` : non vérifié. + +--- + +## Limites méthodologiques générales + +1. **permission-scanner complété pour gains/gmx-v2/ostium** : fonctions permissionnées listées dans `out/.json`. Vertex non scannable (impls non vérifiées). + +2. **contracts_verified** : mesuré via Etherscan API v2. Résultats : gains=true, gmx-v2=true, ostium=true, vertex=partial (proxies vérifiés, impls non). + +3. **AccessControl non-enumerable (gains, GMX)** : `getRoleMember()` reverts. Le proposer du GNSTimelockOwner (gains) et les détenteurs des rôles `onlyTimelockMultisig`/`onlyTimelockAdmin` (GMX custom Timelock) ne sont pas résolus. Scan d'events `RoleGranted` requis. + +4. **Diamond (gains) : version non confirmable** : EIP-2535 ne stocke pas de numéro de version. "v10.3" ne peut pas être lu d'un slot. + +5. **Vertex impls non vérifiées** : finding architectural. Le code déployé en production (Endpoint impl, Clearinghouse impl, moteurs) n'est pas auditable depuis Arbiscan. La surface de permission réelle est inconnue. Source GitHub peut ne pas correspondre au bytecode déployé. + +6. **Ostium source primaire manquante** : la doc officielle Ostium est inaccessible (ECONNREFUSED). Les adresses viennent d'une doc dépréciée + Arbiscan labels. Risque modéré d'adresses obsolètes. La cohérence on-chain (ProxyAdmin → Timelock chain) a été vérifiée. diff --git a/harnesses/permissions-scan/out/aster.json b/harnesses/permissions-scan/out/aster.json new file mode 100644 index 00000000..ddfdb9dd --- /dev/null +++ b/harnesses/permissions-scan/out/aster.json @@ -0,0 +1,126 @@ +{ + "project": "aster", + "measured_at": "2026-08-02T21:00:00Z", + "chain": "multi-chain (BNB primary, ETH, ARB, SOL + Aster Chain PoSA)", + "architecture": "Multi-chain perp DEX. Born from Astherus + APX Finance merger (late 2024), rebranded Aster March 2025. Not a rollup. Launched 'Aster Chain' (PoSA L1) March 2026 but main trading still on BNB/ETH/ARB/SOL.", + + "contracts": { + "bridge_bnb": { + "value": "0x128463A60784c4D3f46c23Af3f65Ed859Ba87974", + "chain": "bnb", + "source": "https://docs.asterdex.com/overview/what-is-aster/our-smart-contracts", + "tier": "documented", + "verified": "unknown" + }, + "bridge_ethereum": { + "value": "0x604DD02d620633Ae427888d41bfd15e38483736E", + "chain": "ethereum", + "source": "https://docs.asterdex.com/overview/what-is-aster/our-smart-contracts", + "tier": "documented", + "verified": "unknown" + }, + "bridge_arbitrum": { + "value": "0x9E36CB86a159d479cEd94Fa05036f235Ac40E1d5", + "chain": "arbitrum", + "source": "https://docs.asterdex.com/overview/what-is-aster/our-smart-contracts", + "tier": "documented", + "verified": "unknown" + }, + "bridge_solana": { + "value": "EhUtRgu9iEbZXXRpEvDj6n1wnQRjMi2SERDo3c6bmN2c", + "chain": "solana", + "source": "https://docs.asterdex.com/overview/what-is-aster/our-smart-contracts", + "tier": "documented", + "verified": "unknown" + }, + "aster_chain_contracts": { + "value": "unknown", + "note": "Aster Chain (PoSA) core contracts not disclosed. Docs state 'not open-sourced.'", + "tier": "unknown" + } + }, + + "owners": { + "cross_chain_withdrawal_signers": { + "value": "2-of-3 internal validator set", + "type": "internal_multisig", + "tier": "documented", + "source": "https://docs.asterdex.com" + }, + "upgrade_key": { + "value": "unknown", + "note": "Upgrade key management not publicly disclosed. Confirmed not disclosed in official docs.", + "tier": "unknown" + }, + "oracles": { + "value": "Chainlink + Pyth", + "tier": "documented", + "source": "https://docs.asterdex.com" + } + }, + + "exit": { + "funds_location": { + "value": "public_contract", + "note": "Per-chain bridge contracts on BNB, ETH, ARB, SOL. Not on a single chain.", + "tier": "documented", + "source": "https://docs.asterdex.com/overview/what-is-aster/our-smart-contracts" + }, + "funds_contract": { + "value": "BNB: 0x128463... | ETH: 0x604DD0... | ARB: 0x9E36CB... | SOL: EhUtRgu...", + "tier": "documented", + "source": "https://docs.asterdex.com/overview/what-is-aster/our-smart-contracts" + }, + "contracts_verified": { + "value": "unknown", + "note": "Docs state bridge contracts 'will be publicly disclosed.' Core chain not open-sourced. No independent verification performed at time of measurement.", + "tier": "unknown" + }, + "chain_l2beat_stage": { + "value": "n/a", + "note": "Not tracked by L2Beat. Not a rollup or L2.", + "tier": "documented" + }, + "upgrade_delay_seconds": { + "value": "unknown", + "note": "Upgrade key management not disclosed. No timelock documented.", + "tier": "unknown" + }, + "lp_exit": { + "note": "Aster uses an LP pool model. Early exit from staking incurs penalties of 2-60%. Cross-chain LP withdrawals require 2-of-3 internal validator co-signature.", + "can_exit_without_validators": false, + "tier": "documented", + "source": "https://docs.asterdex.com" + }, + "trader_exit": { + "mechanism": "Close position on-chain → cross-chain withdrawal requires 2-of-3 internal validator co-signature → USDC to user wallet", + "can_exit_without_validators": false, + "tier": "documented", + "source": "https://docs.asterdex.com" + }, + "can_user_exit_unilaterally": { + "value": false, + "qualifier": "Cross-chain withdrawals require internal 2-of-3 validator sign-off. No forced exit or escape hatch documented.", + "tier": "documented", + "source": "https://docs.asterdex.com" + }, + "exit_function": { + "value": "unknown", + "note": "No permissionless forced exit documented.", + "tier": "unknown" + }, + "exit_depends_on": { + "value": "2-of-3 internal validators + Chainlink/Pyth oracles + off-chain matching engine", + "tier": "documented" + }, + "forced_inclusion": { + "value": false, + "note": "No forced exit mechanism documented.", + "tier": "documented" + }, + "alternative_frontend": { + "value": "unknown", + "note": "Core chain closed source. No permissionless alternative documented." + } + } +} diff --git a/harnesses/permissions-scan/out/gains.json b/harnesses/permissions-scan/out/gains.json new file mode 100644 index 00000000..5b0811ca --- /dev/null +++ b/harnesses/permissions-scan/out/gains.json @@ -0,0 +1,224 @@ +{ + "project": "gains", + "measured_at": "2026-08-02T19:08:53Z", + "block": 490422447, + "chain_id": 42161, + "rpc_used": "https://arb1.arbitrum.io/rpc", + "version_note": "Contract address from official docs (https://docs.gains.trade/what-is-gains-network/contract-addresses/arbitrum-mainnet). Page does not explicitly state v10.3. The user context indicates current version is v10.3. Diamond facet set verified on-chain via facets() call (14 facets returned). Version cannot be confirmed from a storage slot or on-chain constant.", + "contracts": { + "GNSMultiCollatDiamond": { + "value": "0xFF162c694eAA571f685030649814282eA457f169", + "source": "https://docs.gains.trade/what-is-gains-network/contract-addresses/arbitrum-mainnet", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "Diamond_impl": { + "value": "0xff84c4a0d639d598af2088e2ffb76cdbdf1de0ed", + "source": "cast storage diamond EIP-1967-impl-slot", + "block": 490419994, + "measured_at": "2026-08-02T18:58:36Z" + }, + "ProxyAdmin": { + "value": "0xe18be0113c38c91b3B429d04fDeb84359fBCb2eB", + "source": "https://docs.gains.trade/what-is-gains-network/contract-addresses/arbitrum-mainnet", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "GNSTimelockOwner_14d": { + "value": "0x5f5E4892BAB94d94DC57a3edeA3c138167c4DF0F", + "source": "https://docs.gains.trade/what-is-gains-network/contract-addresses/arbitrum-mainnet", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "GNSTimelockManager_3d": { + "value": "0x1632C38cB208df8409753729dBfbA5c58626F637", + "source": "https://docs.gains.trade/what-is-gains-network/contract-addresses/arbitrum-mainnet", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + } + }, + "owners": { + "ProxyAdmin_owner": { + "value": "0x5f5E4892BAB94d94DC57a3edeA3c138167c4DF0F", + "source": "cast call ProxyAdmin owner()", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z", + "resolved": { + "type": "timelock", + "label": "GNSTimelockOwner", + "min_delay_seconds": 1209600, + "min_delay_days": 14, + "source": "cast call GNSTimelockOwner getMinDelay()", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + } + }, + "GNSTimelockOwner_proposer_1": { + "value": "0xc07eed650ab255190ca9766162cfb47cfdf72f3a", + "source": "RoleGranted event PROPOSER_ROLE on GNSTimelockOwner at block 262437221. hasRole() confirmed true at block 490422447.", + "resolved": { + "type": "safe", + "threshold": 4, + "total_owners": 7, + "owner_addresses": [ + "0x44C590465402Bc56F401dE4F699680559aB4b1E4", + "0x211999E5eE74Af3E8dAcBCd5c4e608CD7D8086FA", + "0xdDF3a49F0eA3C53112D8eC058421EB24902dCbfc", + "0x994805c5FaC2FAb30077003143368F9243F02B7e", + "0x6a9fe023F2D5930249081EBfa1909350CEbe1605", + "0x9cdfe21adfa1038318321e1729a2de2251A0803A", + "0xB608c15A9a7b30304fB0763a1d6C66354423985d" + ], + "source": "cast call getThreshold()=4, getOwners()=[7 addresses]", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + } + }, + "GNSTimelockOwner_proposer_2": { + "value": "0xe8997c502fcd0729b462fca19a50cf0daea0cab5", + "source": "RoleGranted event PROPOSER_ROLE on GNSTimelockOwner at block 262437553. hasRole() confirmed true at block 490422447.", + "resolved": { + "type": "safe", + "threshold": 2, + "total_owners": 4, + "owner_addresses": [ + "0x80fd0accC8Da81b0852d2Dca17b5DDab68f22253", + "0x211999E5eE74Af3E8dAcBCd5c4e608CD7D8086FA", + "0x727695E7888853af9e673EA66F30F26a791DdfB0", + "0x52a722BC2B0D8ce869a478956865744D7C3beBd3" + ], + "source": "cast call getThreshold()=2, getOwners()=[4 addresses]", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + } + }, + "GNSTimelockManager_proposer": { + "value": "unknown", + "source": "Not queried \u2014 event scan limited to GNSTimelockOwner. Separate scan on 0x1632C38cB208df8409753729dBfbA5c58626F637 required.", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + } + }, + "permissions": { + "scanner_result": "completed", + "scanner_tool": "deficollective/permission-scanner (crytic-compile + Slither)", + "scanner_ran_at": "2026-08-02T19:08:53Z", + "key_permissioned_functions": [ + "GNSMultiCollatDiamond.diamondCut(IDiamondCut.FacetCut[],address,bytes) \u2014 modifier: onlyRoles (ROLES_MANAGER_ROLE)", + "GNSMultiCollatDiamond.initialize(uint8,IGNSDiamond.InitParams) \u2014 modifier: initializer", + "GNSMultiCollatDiamond.setRoles(address[],IGNSAccessControl.Role[],bool[]) \u2014 modifier: onlyRoles (ROLES_MANAGER_ROLE)", + "GToken.withdraw(uint256,address,address) \u2014 modifier: checks (NOT onlyOwner; standard ERC4626 gate)", + "GToken.redeem(uint256,address,address) \u2014 modifier: checks (NOT onlyOwner; standard ERC4626 gate)", + "GToken.mint(uint256,address) \u2014 modifier: checks (ERC4626 standard; user-callable deposit-by-shares)", + "GToken.deposit(uint256,address) \u2014 modifier: checks (ERC4626 standard; user-callable)", + "GNSTimelockOwner.schedule(...) \u2014 modifier: onlyRoleOrOpenRole(PROPOSER_ROLE)", + "GNSTimelockOwner.execute(...) \u2014 modifier: onlyRoleOrOpenRole(EXECUTOR_ROLE)", + "GNSTimelockOwner.grantRole(bytes32,address) \u2014 modifier: onlyRole(TIMELOCK_ADMIN_ROLE)" + ], + "manual_observations": [ + "Diamond uses EIP-2535 + EIP-1967 upgradeable pattern. DiamondCut facet additions/replacements controlled by ROLES_MANAGER_ROLE.", + "ProxyAdmin owner = GNSTimelockOwner (14-day timelock). Major upgrades require 14-day delay.", + "GNSTimelockManager (3-day) controls routine management functions.", + "KEY FINDING: GToken withdraw() and redeem() use 'checks' modifier (ERC4626 standard gating) \u2014 NOT onlyOwner. LP can call redeem/withdraw directly without admin permission.", + "GToken deposit/mint/withdraw/redeem all use 'checks' \u2014 fully ERC4626 standard, all user-callable. Admin functions (updateManager, updatePnlHandler, etc.) are onlyOwner but do not gate user flows." + ] + }, + "exit": { + "funds_location": { + "value": "public_contract", + "source": "gToken vaults (gDAI, gETH, gGNS, gUSDC) are public ERC4626-like contracts; traders' collateral held in these vaults", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z", + "tier": "onchain" + }, + "funds_contract": { + "value": "gDAI: 0xd85E038593d7A098614721EaE955EC2022B9B91B | gGNS: 0x4BeeF1113F968326905224D2Ca272f3032A9a9F4 | gETH: 0x5977A9682D7AF81D347CFc338c61692163a2784C | gUSDC: 0xd3443ee1e91aF28e5FB858Fbd0D72A63bA8046E0", + "source": "https://docs.gains.trade/what-is-gains-network/contract-addresses/arbitrum-mainnet", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z", + "tier": "onchain" + }, + "contracts_verified": { + "value": true, + "source": "Etherscan API v2 (chainid=42161): GNSMultiCollatDiamond proxy verified (solc 0.8.9), GNSMultiCollatDiamond impl verified (solc 0.8.23), GToken vaults verified (solc 0.8.9), GNSTimelockOwner verified (solc 0.8.17). All source code downloaded successfully by permission-scanner.", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z", + "tier": "onchain" + }, + "chain": { + "value": "arbitrum", + "chain_id": 42161, + "source": "https://docs.gains.trade/what-is-gains-network/contract-addresses/arbitrum-mainnet", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "chain_l2beat_stage": { + "value": 1, + "source": "https://l2beat.com/scaling/summary \u2014 Arbitrum One listed as Stage 1. Fetched 2026-08-02. Note: all Groupe A targets share this value as they are all on Arbitrum One.", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z", + "tier": "documented" + }, + "upgrade_delay_seconds": { + "value": 1209600, + "source": "cast call 0x5f5E4892BAB94d94DC57a3edeA3c138167c4DF0F getMinDelay() = 1209600. This is the delay for ProxyAdmin/Diamond upgrades. A separate 3-day timelock (0x1632C3..., getMinDelay()=259200) exists for management functions.", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z", + "tier": "onchain" + }, + "lp_exit": { + "mechanism": "2-step epoch-lock: makeWithdrawRequest(shares, owner) \u2192 wait withdrawEpochsTimelock (=3) epochs \u2192 withdraw()/redeem()", + "permission_gate": "none \u2014 withdraw/redeem use 'checks' modifier (ERC4626 balance gate only, no admin permission)", + "epoch_lock_gate": "CRITICAL: epochs advance via openTradesPnlFeed oracle callbacks (currentEpoch++ triggered by oracle). Epoch duration is oracle-driven, NOT time-based. If oracle stops, epochs stop, withdrawals locked indefinitely regardless of elapsed time.", + "maxWithdraw_test": "maxWithdraw(holder) = 0 for 4 real holders with positive balances \u2014 confirmed: users cannot withdraw without first calling makeWithdrawRequest and waiting 3 oracle epochs", + "can_exit_without_admin": true, + "can_exit_without_oracle": false, + "tier": "bytecode", + "source": "GToken.sol source (verified, solc 0.8.9). on-chain: maxWithdraw(0x5504e7...)=0 with balance=1.618e18. currentEpoch=428, withdrawEpochsTimelock=3, currentEpochStart=2026-07-31.", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "trader_exit": { + "mechanism": "closeTradeMarket(tradeIndex, collateralIndex, pairIndex) on GNSMultiCollatDiamond requires oracle price", + "can_exit_without_oracle": false, + "tier": "bytecode", + "source": "Diamond architecture: position closure requires price feed liveness (openTradesPnlFeed / oracle keepers).", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "can_user_exit_unilaterally": { + "value": false, + "reason": "LP: no admin gate but oracle-gated epoch lock (3 oracle cycles required). Trader: oracle required for position closure. Both paths depend on protocol oracle liveness.", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z", + "tier": "bytecode+onchain" + }, + "exit_function_candidate": { + "value": "redeem(uint256,address,address) on gToken vaults; closeTradeMarket(uint32,uint8,uint16) on Diamond", + "source": "ERC4626 interface + gains protocol docs", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "exit_depends_on": { + "value": "operator", + "source": "Oracle price feeds required for position management. OpenPnlFeed influences vault share price. These are operator-controlled off-chain components.", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z", + "tier": "bytecode" + }, + "forced_inclusion": { + "value": "n/a", + "source": "gains is a dApp on Arbitrum One, not a rollup. forced_inclusion refers to L1 inbox mechanism which is Arbitrum's feature, not gains'.", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z", + "tier": "n/a" + }, + "alternative_frontend": { + "value": "unknown", + "source": "Not verified. Contracts are public and ABI-accessible, so technically anyone can build a frontend.", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z", + "tier": "unknown" + } + } +} \ No newline at end of file diff --git a/harnesses/permissions-scan/out/gmx-v2.json b/harnesses/permissions-scan/out/gmx-v2.json new file mode 100644 index 00000000..8f425bb0 --- /dev/null +++ b/harnesses/permissions-scan/out/gmx-v2.json @@ -0,0 +1,298 @@ +{ + "project": "gmx-v2", + "measured_at": "2026-08-02T19:08:53Z", + "block": 490422447, + "chain_id": 42161, + "rpc_used": "https://arb1.arbitrum.io/rpc", + "contracts": { + "ExchangeRouter": { + "value": "0x602b805EedddBbD9ddff44A7dcBD46cb07849685", + "source": "Arbiscan label 'GMX: ExchangeRouter'; confirmed on-chain: dataStore() returns DataStore address 0xFD70de6b91282D8017aA4E741e9Ae325CAb992d8", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "DataStore": { + "value": "0xFD70de6b91282D8017aA4E741e9Ae325CAb992d8", + "source": "https://github.com/gmx-io/gmx-synthetics/blob/main/deployments/arbitrum/DataStore.json", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "RoleStore": { + "value": "0x3c3d99FD298f679DBC2CEcd132b4eC4d0F5e6e72", + "source": "https://github.com/gmx-io/gmx-synthetics/blob/main/deployments/arbitrum/RoleStore.json", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "EventEmitter": { + "value": "0xC8ee91A54287DB53897056e12D9819156D3822Fb", + "source": "https://github.com/gmx-io/gmx-synthetics/blob/main/deployments/arbitrum/EventEmitter.json", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "OrderVault": { + "value": "0x31eF83a530Fde1B38EE9A18093A333D8Bbbc40D5", + "source": "https://github.com/gmx-io/gmx-synthetics/blob/main/deployments/arbitrum/OrderVault.json", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "DepositVault": { + "value": "0xF89e77e8Dc11691C9e8757e84aaFbCD8A67d7A55", + "source": "https://github.com/gmx-io/gmx-synthetics/blob/main/deployments/arbitrum/DepositVault.json", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "WithdrawalVault": { + "value": "0x0628D46b5D145f183AdB6Ef1f2c97eD1C4701C55", + "source": "https://github.com/gmx-io/gmx-synthetics/blob/main/deployments/arbitrum/WithdrawalVault.json", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "MarketFactory": { + "value": "0xf5F30B10141E1F63FC11eD772931A8294a591996", + "source": "https://github.com/gmx-io/gmx-synthetics/blob/main/deployments/arbitrum/MarketFactory.json", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "OracleStore": { + "value": "0xA8AF9B86fC47deAde1bc66B12673706615E2B011", + "source": "https://github.com/gmx-io/gmx-synthetics/blob/main/deployments/arbitrum/OracleStore.json", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "GovTimelockController": { + "value": "0xFBEff82f2DD5E51B8AF34b57cf788b4b09d466F9", + "source": "https://github.com/gmx-io/gmx-synthetics/blob/main/deployments/arbitrum/GovTimelockController.json", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "Timelock_custom": { + "value": "0x7A967D114B8676874FA2cFC1C14F3095C88418Eb", + "source": "https://github.com/gmx-io/gmx-synthetics/blob/main/deployments/arbitrum/Timelock.json", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "ProtocolGovernor": { + "value": "0x03e8f708e9C85EDCEaa6AD7Cd06824CeB82A7E68", + "source": "https://github.com/gmx-io/gmx-synthetics/blob/main/deployments/arbitrum/ProtocolGovernor.json", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "GovToken": { + "value": "0x2A29D3a792000750807cc401806d6fd539928481", + "source": "https://github.com/gmx-io/gmx-synthetics/blob/main/deployments/arbitrum/GovToken.json", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + } + }, + "owners": { + "GovTimelockController_proposer": { + "value": "0x03e8f708e9C85EDCEaa6AD7Cd06824CeB82A7E68", + "source": "cast call GovTimelockController hasRole(PROPOSER_ROLE, ProtocolGovernor) = true", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z", + "resolved": { + "type": "governor", + "label": "ProtocolGovernor", + "proposal_threshold_tokens": "30000000000000000000000", + "voting_delay_blocks": 86400, + "source": "cast call ProtocolGovernor proposalThreshold() + votingDelay()" + } + }, + "GovTimelockController_executor": { + "value": "0x03e8f708e9C85EDCEaa6AD7Cd06824CeB82A7E68", + "source": "cast call GovTimelockController hasRole(EXECUTOR_ROLE, ProtocolGovernor) = true", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "GovTimelockController_min_delay": { + "value": 86400, + "source": "cast call GovTimelockController getMinDelay() = 86400", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "custom_Timelock_delay": { + "value": 86400, + "source": "cast storage Timelock slot 1 = 0x15180 = 86400. Standard functions (getMinDelay, admin) revert: non-OZ interface.", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "custom_Timelock_admin": { + "value": "resolved via RoleStore enumeration", + "source": "GMX Timelock inherits RoleModule \u2014 roles stored in RoleStore (0x3c3d99FD298f679DBC2CEcd132b4eC4d0F5e6e72). Role hashes: keccak256(abi.encode('TIMELOCK_ADMIN'))=0xf49b0c86..., keccak256(abi.encode('TIMELOCK_MULTISIG'))=0xe068a8d8...", + "TIMELOCK_MULTISIG": { + "count": 1, + "members": [ + { + "address": "0x8D1d2e24eC641eDC6a1ebe0F3aE7af0EBC573e0D", + "type": "safe", + "threshold": 5, + "total_owners": 8, + "owner_addresses": [ + "0xD7941C4Ca57a511F21853Bbc7FBF8149d5eCb398", + "0x32660E5Fe1C5d10330c019Df4eb522A78c1EC896", + "0x25B889f14B9E5bB65F97b456dcd1ce8a5ab0D855", + "0xd32b86F984254246005a1c1c5e0b6A48743Ddc93", + "0x49C9F377d48c417FEB1f4fb32BF2D9Eb04112Da3", + "0x9fCA624E05EfA27205e905a40f9cEE9cb455D890", + "0xeAA5600595a64a23480b2DF5FCA35A2867c912Ea", + "0xFbf5dC7C8911Bf3434e855374eC81414E44E2b12" + ] + } + ], + "source": "getRoleMemberCount(TIMELOCK_MULTISIG)=1, getRoleMembers()=[0x8D1d2e24]. getThreshold()=5, getOwners()=[8 addresses]", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "TIMELOCK_ADMIN": { + "count": 4, + "members": [ + { + "address": "0x8D1d2e24eC641eDC6a1ebe0F3aE7af0EBC573e0D", + "type": "safe_5_of_8" + }, + { + "address": "0x35ea3066F90Db13e737BBd41f1ED7B4bfF8323b3", + "type": "EOA", + "note": "plain EOA \u2014 single private key can execute TIMELOCK_ADMIN functions" + }, + { + "address": "0xE014cbD60A793901546178E1c16ad9132C927483", + "type": "EOA", + "note": "plain EOA \u2014 single private key" + }, + { + "address": "0x58F582455b54d7c83d03BCeed95FAf72B37fdDD7", + "type": "safe", + "threshold": 4, + "total_owners": 6 + } + ], + "finding": "2 of 4 TIMELOCK_ADMIN holders are plain EOAs. TIMELOCK_ADMIN can execute timelock admin functions (increaseTimelockDelay, setOracleProviderForToken, grantRole) with a single key. No multisig protection for these two holders.", + "source": "getRoleMemberCount(TIMELOCK_ADMIN)=4, getRoleMembers(0,4)=[4 addresses]. getThreshold() on each to determine type.", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + } + } + }, + "permissions": { + "scanner_result": "completed", + "scanner_tool": "deficollective/permission-scanner (crytic-compile + Slither)", + "scanner_ran_at": "2026-08-02T19:08:53Z", + "key_permissioned_functions": [ + "DataStore.setUint/setInt/setAddress/setBool/setBytes32/setString/setBytes(...) x39 \u2014 modifier: onlyController (CONTROLLER role in RoleStore)", + "RoleStore.grantRole(address,bytes32) \u2014 modifier: onlyRoleAdmin", + "RoleStore.revokeRole(address,bytes32) \u2014 modifier: onlyRoleAdmin", + "OrderVault.transferOut(address,address,uint256) x7 \u2014 modifier: onlyController", + "GovTimelockController.schedule/scheduleBatch/execute/executeBatch/cancel \u2014 OZ standard (PROPOSER/EXECUTOR roles)", + "Timelock.signalSetGov(address) \u2014 modifier: onlyTimelockMultisig", + "Timelock.setGov(address) \u2014 modifier: onlyTimelockAdmin", + "Timelock.signalSetHandler(address,address,bool) \u2014 modifier: onlyTimelockMultisig", + "Timelock.processMint(address,address,uint256) \u2014 modifier: onlyTimelockAdmin", + "Timelock.setMaxLeverage(address,uint256) \u2014 modifier: onlyTimelockAdmin" + ], + "new_discoveries": [ + "Custom Timelock uses two distinct roles: onlyTimelockMultisig (propose/signal) and onlyTimelockAdmin (execute/finalize). These are NOT standard OZ roles.", + "onlyTimelockMultisig holder: NOT resolved on-chain (gov()/owner()/timelockAdmin() revert on non-OZ interface). Requires event scan or Etherscan to identify.", + "onlyTimelockAdmin holder: NOT resolved on-chain. Same blocker.", + "DataStore is the central permission gate: all 39 setters gated by onlyController (= CONTROLLER role in RoleStore). Keeper bots hold CONTROLLER." + ], + "manual_observations": [ + "RoleStore controls all role-based access. CONTROLLER role gives full protocol access.", + "GovTimelockController (1-day delay) is the governance path for on-chain changes.", + "Custom Timelock (1-day delay): signals require onlyTimelockMultisig, finalization requires onlyTimelockAdmin. Two-key scheme for critical operations.", + "No proxy upgrade pattern detected \u2014 contracts appear non-upgradeable (direct deployments per GitHub)." + ] + }, + "exit": { + "funds_location": { + "value": "public_contract", + "source": "Funds flow through OrderVault/DepositVault/WithdrawalVault on Arbitrum. GM token liquidity in market pools. All are public contracts.", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z", + "tier": "documented" + }, + "funds_contract": { + "value": "OrderVault: 0x31eF83a530Fde1B38EE9A18093A333D8Bbbc40D5 | DepositVault: 0xF89e77e8Dc11691C9e8757e84aaFbCD8A67d7A55 | WithdrawalVault: 0x0628D46b5D145f183AdB6Ef1f2c97eD1C4701C55", + "source": "https://github.com/gmx-io/gmx-synthetics/tree/main/deployments/arbitrum", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z", + "tier": "documented" + }, + "contracts_verified": { + "value": true, + "source": "Etherscan API v2 (chainid=42161): all 12 GMX v2 contracts verified. ExchangeRouter, DataStore, RoleStore, EventEmitter verified (solc 0.8.18); GovTimelockController verified (solc 0.8.20); custom Timelock verified (solc 0.8.18). Source code downloaded successfully by permission-scanner.", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z", + "tier": "onchain" + }, + "chain": { + "value": "arbitrum", + "chain_id": 42161, + "source": "https://github.com/gmx-io/gmx-synthetics/tree/main/deployments/arbitrum", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "chain_l2beat_stage": { + "value": 1, + "source": "https://l2beat.com/scaling/summary \u2014 Arbitrum One listed as Stage 1. Fetched 2026-08-02.", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z", + "tier": "documented" + }, + "upgrade_delay_seconds": { + "value": 86400, + "source": "GovTimelockController.getMinDelay()=86400 (1 day). Governance path for protocol changes. Custom Timelock also has 86400s delay. Contracts appear to be non-upgradeable (no proxy pattern detected in GitHub deployment files).", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z", + "tier": "onchain" + }, + "can_user_exit_unilaterally": { + "value": false, + "source": "GM token withdrawal requires keeper execution (ExchangeRouter.createWithdrawal \u2192 keeper executes via WithdrawalHandler). Users CAN cancel pending requests (cancelWithdrawal), recovering tokens. But actual exit from positions requires keeper liveness. If keeper down, user can cancel but cannot execute their own withdrawal.", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z", + "tier": "bytecode" + }, + "exit_function_candidate": { + "value": "cancelWithdrawal(bytes32) on ExchangeRouter for pending request recovery; createWithdrawal() + keeper for actual exit", + "source": "GMX v2 architecture docs + contract ABI", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "exit_depends_on": { + "value": "operator", + "source": "Keeper bots (CONTROLLER role in RoleStore) required to execute withdrawals. Users cannot self-execute withdrawal orders.", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z", + "tier": "bytecode" + }, + "forced_inclusion": { + "value": "n/a", + "source": "GMX v2 is a dApp on Arbitrum One, not a rollup. N/A for forced inclusion.", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z", + "tier": "n/a" + }, + "alternative_frontend": { + "value": "unknown", + "source": "Not verified.", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z", + "tier": "unknown" + }, + "lp_exit": { + "mechanism": "createWithdrawal() on ExchangeRouter \u2192 keeper executes via WithdrawalHandler. Users cannot self-execute.", + "permission_gate": "CONTROLLER role (keeper bots) required to execute withdrawals via WithdrawalHandler", + "censorship_resistance": "cancelWithdrawal(bytes32) allows user to recover pending withdrawal request collateral if keeper doesn't execute. But actual exit from GM tokens requires keeper liveness.", + "can_exit_without_keeper": false, + "tier": "bytecode+onchain", + "source": "Scanner: DataStore 39 setters onlyController. Architecture confirmed via GitHub deployments + ExchangeRouter.dataStore() on-chain." + }, + "trader_exit": { + "mechanism": "createOrder()/cancelOrder() on ExchangeRouter. Execution requires ORDER_KEEPER role.", + "can_exit_without_keeper": false, + "tier": "bytecode", + "source": "Scanner: OrderVault 7 functions onlyController. Keeper required for order execution." + } + } +} \ No newline at end of file diff --git a/harnesses/permissions-scan/out/hyperliquid.json b/harnesses/permissions-scan/out/hyperliquid.json new file mode 100644 index 00000000..67cb6597 --- /dev/null +++ b/harnesses/permissions-scan/out/hyperliquid.json @@ -0,0 +1,115 @@ +{ + "project": "hyperliquid", + "measured_at": "2026-08-02T21:00:00Z", + "chain": "hyperliquid-l1 + arbitrum-bridge", + "chain_id_bridge": 42161, + "architecture": "custom L1 (HyperBFT consensus) + USDC bridge on Arbitrum One. Not an Ethereum L2.", + + "contracts": { + "HyperliquidBridge2_arbitrum": { + "value": "0x2Df1c51E09aECF9cacB7bc98cB1742757f163dF7", + "source": "https://arbiscan.io/address/0x2df1c51e09aecf9cacb7bc98cb1742757f163df7 — verified contract, label 'Hyperliquid: Bridge 2'", + "tier": "onchain", + "verified": true, + "upgradeable": true, + "upgrade_admin": "EOA — no timelock", + "note": "All user USDC is escrowed here on Arbitrum. Instant upgrade by single EOA = funds can be drained with one transaction and no delay." + }, + "L1_node_software": { + "value": "closed source", + "source": "L2Beat: https://l2beat.com/scaling/projects/hyperliquid — 'The node software is not open source.'", + "tier": "documented" + } + }, + + "owners": { + "bridge_upgrade_key": { + "value": "unknown EOA", + "type": "EOA", + "timelock": "none", + "tier": "documented", + "source": "L2Beat: 'Funds can be stolen if a contract receives a malicious code upgrade. There is no delay on code upgrades (CRITICAL).' https://l2beat.com/scaling/projects/hyperliquid" + }, + "validator_set": { + "value": "~25-27 nodes as of June 2026", + "description": "Partially externally staked but still heavily foundation-influenced. 4 hot-validator EOAs on Arbitrum historically submitted all withdrawal transactions.", + "tier": "documented", + "source": "ChainArgos: https://medium.com/chainargos/centralized-control-in-hyperliquid-3e9f7dd0d706 + L2Beat" + }, + "withdrawal_signers": { + "value": "2/3+ staking-weighted validator set required to co-sign withdrawals", + "type": "validator_multisig", + "tier": "documented", + "source": "https://hyperliquid.gitbook.io/hyperliquid-docs/hypercore/bridge" + } + }, + + "exit": { + "funds_location": { + "value": "public_contract", + "note": "On Arbitrum One bridge contract. USDC is held in escrow there.", + "tier": "onchain", + "source": "https://arbiscan.io/address/0x2df1c51e09aecf9cacb7bc98cb1742757f163df7" + }, + "funds_contract": { + "value": "0x2Df1c51E09aECF9cacB7bc98cB1742757f163dF7 (Arbitrum One)", + "tier": "onchain", + "source": "Arbiscan verified" + }, + "contracts_verified": { + "value": "partial", + "detail": "Bridge contract verified on Arbiscan. L1 node software closed source — no bytecode auditable.", + "tier": "onchain" + }, + "chain_l2beat_stage": { + "value": "other", + "note": "Not rated as Stage 0/1/2 — classified as 'Other' because it is not an Ethereum L2. L2Beat flags: invalid state roots permitted, data not published on Ethereum, contracts instantly upgradeable by EOA.", + "tier": "documented", + "source": "https://l2beat.com/scaling/projects/hyperliquid" + }, + "upgrade_delay_seconds": { + "value": 0, + "note": "Bridge contract upgradeable with no delay by a single EOA. Instant upgrade = instant fund loss risk.", + "tier": "documented", + "source": "L2Beat: 'There is no delay on code upgrades (CRITICAL).'" + }, + "lp_exit": { + "note": "Hyperliquid uses a vault model (HLP) for LP. HLP vault withdrawals go through the same bridge mechanism.", + "can_exit_without_validators": false, + "tier": "documented", + "source": "https://hyperliquid.gitbook.io/hyperliquid-docs/hypercore/bridge" + }, + "trader_exit": { + "mechanism": "Withdraw from Hyperliquid L1 account → bridge co-signed by 2/3+ validators → Arbitrum USDC transfer", + "can_exit_without_validators": false, + "tier": "documented", + "source": "https://hyperliquid.gitbook.io/hyperliquid-docs/hypercore/bridge" + }, + "can_user_exit_unilaterally": { + "value": false, + "reason": "Withdrawals require 2/3+ staking-weighted validator co-signature. Historically executed by ~4 team-controlled EOAs. No forced exit mechanism. Bridge upgradeable by single EOA with no delay.", + "tier": "documented", + "source": "L2Beat + ChainArgos + bridge docs" + }, + "exit_function": { + "value": "unknown", + "note": "No user-callable forced exit exists. Normal path: withdraw via HL UI → validators sign → Arbitrum settlement.", + "tier": "documented" + }, + "exit_depends_on": { + "value": "validator set (2/3+ staking weight) + bridge upgrade EOA", + "tier": "documented", + "source": "L2Beat + bridge docs" + }, + "forced_inclusion": { + "value": false, + "note": "No escape hatch. L2Beat: 'There is no window for users to exit in case of an unwanted upgrade since contracts are instantly upgradable.'", + "tier": "documented", + "source": "https://l2beat.com/scaling/projects/hyperliquid" + }, + "alternative_frontend": { + "value": "unknown", + "note": "L1 is closed source. No known permissionless alternative frontend for withdrawals." + } + } +} diff --git a/harnesses/permissions-scan/out/lighter.json b/harnesses/permissions-scan/out/lighter.json new file mode 100644 index 00000000..2743b74f --- /dev/null +++ b/harnesses/permissions-scan/out/lighter.json @@ -0,0 +1,121 @@ +{ + "project": "lighter", + "measured_at": "2026-08-02T21:00:00Z", + "chain": "ethereum-mainnet", + "chain_id": 1, + "architecture": "ZK-rollup on Ethereum mainnet. Custom Plonky2 circuits. Single centralized sequencer.", + + "contracts": { + "ZkLighter_core": { + "value": "0x3B4D794a66304F130a4Db8F2551B0070dfCf5ca7", + "source": "https://l2beat.com/scaling/projects/lighter + https://etherscan.io/address/0x3b4d794a66304f130a4db8f2551b0070dfcf5ca7", + "tier": "documented", + "verified": true, + "chain": "ethereum" + }, + "ZkLighter_verifier": { + "value": "0xac3Ce44B6ff4E402858C99D5699ff63131572BaA", + "source": "https://l2beat.com/scaling/projects/lighter", + "tier": "documented", + "verified": true, + "chain": "ethereum" + }, + "UpgradeGatekeeper": { + "value": "0x94da8A995D0D82Ef0fE7E509C6D76c22603B6f67", + "source": "https://l2beat.com/scaling/projects/lighter", + "tier": "documented", + "note": "Controls upgrades. L2Beat: no delay on upgrades — CRITICAL.", + "chain": "ethereum" + }, + "prover_source": { + "value": "https://github.com/elliottech/lighter-prover", + "note": "ZK prover and desert exit circuits open source. Audited by ZKSecurity.", + "tier": "documented" + } + }, + + "owners": { + "upgrade_gatekeeper": { + "value": "0x94da8A995D0D82Ef0fE7E509C6D76c22603B6f67", + "type": "unknown — EOA or contract", + "timelock": "none", + "tier": "documented", + "source": "L2Beat: 'Funds can be stolen if a contract receives a malicious code upgrade. There is no delay on code upgrades (CRITICAL).'" + }, + "sequencer": { + "value": "centralized — operated by Lighter team", + "type": "centralized", + "tier": "documented", + "source": "https://docs.lighter.xyz/about-lighter/technical-architecture-lighter-core" + } + }, + + "exit": { + "funds_location": { + "value": "public_contract", + "note": "User funds held in ZkLighter core contract on Ethereum mainnet.", + "tier": "documented", + "source": "https://etherscan.io/address/0x3b4d794a66304f130a4db8f2551b0070dfcf5ca7" + }, + "funds_contract": { + "value": "0x3B4D794a66304F130a4Db8F2551B0070dfCf5ca7 (Ethereum mainnet)", + "tier": "documented", + "source": "L2Beat + Etherscan" + }, + "contracts_verified": { + "value": true, + "note": "Core contracts verified on Etherscan. ZK prover and desert exit circuit code open source on GitHub.", + "tier": "documented" + }, + "chain_l2beat_stage": { + "value": "stage_0_appchain", + "note": "5 of required conditions met. Blocked from Stage 1 by no-delay upgrade key (UpgradeGatekeeper).", + "tier": "documented", + "source": "https://l2beat.com/scaling/projects/lighter" + }, + "upgrade_delay_seconds": { + "value": 0, + "note": "UpgradeGatekeeper has no timelock. Instant upgrade = instant fund loss risk.", + "tier": "documented", + "source": "L2Beat" + }, + "lp_exit": { + "note": "Lighter does not use a public LP vault model in the same sense as EVM perp DEXes. Maker/market-maker positions managed via centralized sequencer.", + "tier": "documented" + }, + "trader_exit": { + "mechanism": "Priority queue submission on Ethereum L1 → sequencer must process within 14 days or Desert Mode activates → user generates ZK proof of balance → withdraws directly from contract", + "normal_path_depends_on": "centralized sequencer", + "censorship_resistance": "Desert Mode: if sequencer ignores priority queue for 14 days, rollup freezes and users can exit with self-generated ZK proofs. Open source circuit code available at github.com/elliottech/lighter-prover.", + "can_exit_without_sequencer": true, + "can_exit_without_upgrade_key": false, + "tier": "documented", + "source": "https://docs.lighter.xyz/about-lighter/technical-architecture-lighter-core + L2Beat" + }, + "can_user_exit_unilaterally": { + "value": true, + "qualifier": "conditional — requires 14-day wait + self-generating a ZK proof of balance. Desert Mode is the mechanism. NOT instant. Upgrade key risk remains: if contract is upgraded before Desert Mode triggers, funds can be lost.", + "tier": "documented", + "source": "L2Beat + Lighter docs" + }, + "exit_function": { + "value": "Priority queue → Desert Mode withdrawal with self-generated ZK proof", + "tier": "documented", + "source": "https://github.com/elliottech/lighter-prover" + }, + "exit_depends_on": { + "value": "sequencer (normal), UpgradeGatekeeper EOA (critical risk), ZK circuit correctness (for desert exit)", + "tier": "documented" + }, + "forced_inclusion": { + "value": true, + "mechanism": "Desert Mode after 14-day sequencer non-response to priority queue", + "tier": "documented", + "source": "L2Beat + Lighter docs" + }, + "alternative_frontend": { + "value": "unknown", + "note": "Contracts are verified; technically a permissionless frontend is possible but none documented." + } + } +} diff --git a/harnesses/permissions-scan/out/ostium.json b/harnesses/permissions-scan/out/ostium.json new file mode 100644 index 00000000..b03f6a12 --- /dev/null +++ b/harnesses/permissions-scan/out/ostium.json @@ -0,0 +1,256 @@ +{ + "project": "ostium", + "measured_at": "2026-08-02T19:08:53Z", + "block": 490422447, + "chain_id": 42161, + "rpc_used": "https://arb1.arbitrum.io/rpc", + + "contracts": { + "oLP_vault_proxy": { + "value": "0x20d419a8e12c45f88fda7c5760bb6923cee27f98", + "source": "https://ostium-labs.gitbook.io/ostium-docs/security/smart-contract-audits + Arbiscan", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "oLP_vault_impl": { + "value": "0x1E20E46C92F0786889462F065BC9DA163AF6020D", + "source": "cast storage oLP-proxy EIP-1967-impl-slot", + "block": 490419994, + "measured_at": "2026-08-02T18:58:36Z" + }, + "Trading_proxy": { + "value": "0x6d0ba1f9996dbd8885827e1b2e8f6593e7702411", + "source": "https://ostium-labs.gitbook.io/ostium-docs/security/smart-contract-audits + Arbiscan", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "Trading_impl": { + "value": "0x8cbb5bd2b46f993078407cea26704af0a901515a", + "source": "cast storage Trading-proxy EIP-1967-impl-slot", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "Registry": { + "value": "0x799a139ae56e11f0476ace2f6118cfcaed9608d2", + "source": "Arbiscan label search", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "TradingCallbacks": { + "value": "0x7720fc8c8680bf4a1af99d44c6c265a74e9742a9", + "source": "Arbiscan label search", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "Verifier": { + "value": "0xccf233920e8cc9415ecf503b992881d69b6c47ad", + "source": "Arbiscan label search", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "PairInfos_proxy": { + "value": "0x3890243a8fc091c626ed26c087a028b46bc9d66c", + "source": "Arbiscan label search", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "PairsStorage_proxy": { + "value": "0x260e349f643f12797fdc6f8c9d3df211d5577823", + "source": "Arbiscan label search", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "TradingStorage": { + "value": "0xccd5891083a8acd2074690f65d3024e7d13d66e7", + "source": "Arbiscan label search", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "PriceRouter": { + "value": "0x4b0c3c77d398912491f192d265b237c8d4441ad7", + "source": "Arbiscan label search", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "TimelockOwner": { + "value": "0xeb85dc6095c74d36500c9cdcacc15ecdc223bbf7", + "source": "Arbiscan label search", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "ProxyAdmin": { + "value": "0x083f97babf33d4abc03151b5dec98170761f4025", + "source": "Arbiscan label search", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + } + }, + + "owners": { + "ProxyAdmin_owner": { + "value": "0xeb85dc6095c74d36500c9cdcacc15ecdc223bbf7", + "source": "cast call ProxyAdmin owner() = 0xeB85dC6095c74D36500C9cdcaCc15EcDC223Bbf7 (same as TimelockOwner)", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z", + "resolved": { + "type": "timelock", + "label": "TimelockOwner", + "min_delay_seconds": 64800, + "min_delay_hours": 18, + "source": "cast call TimelockOwner getMinDelay() = 64800" + } + }, + "TimelockOwner_proposer": { + "value": "0x1cd84f9b95d3fc7dbba5f7428fb17c4f2ee29e50", + "source": "RoleGranted event (topic PROPOSER_ROLE, grantee 0x1cd84f9b) from block 228313384 tx 0x2b8830d7. Verified via cast logs on TimelockOwner.", + "block": 228313384, + "measured_at": "2026-08-02T19:08:53Z", + "resolved": { + "type": "safe", + "threshold": 4, + "total_owners": 8, + "owner_addresses": [ + "0xAc7935dB621535b94a3D77b1a853B22db5D4F3aC", + "0x640EcDE463f2a54845251E2399068A80b12F488D", + "0x5C9E16750380072776fC39Daf59B20514d954a17", + "0x190628DEe27F8763b7ccDA0956493A87794d3637", + "0xe193d97f6b92712A4e9B947b23EF2F7569C950eb", + "0xAC40c7AAF02466D2358891e1e995801331173EAc", + "0x25d83C56f6a57bE4ce419694cBa98BEDc31E0b4b", + "0xb27f1880Bdf972BFb586EC486CB9348cADB0B71B" + ], + "source": "cast call 0x1cd84f9b95d3fc7dbba5f7428fb17c4f2ee29e50 getThreshold() = 4; getOwners() = [8 addresses]", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + } + }, + "TimelockOwner_executor": { + "value": "0x1cd84f9b95d3fc7dbba5f7428fb17c4f2ee29e50", + "source": "RoleGranted event (topic 0xfd643c72 = EXECUTOR_ROLE per OZ keccak, grantee 0x1cd84f9b) from block 228313384 same tx. The EXECUTOR_ROLE bytes32 = 0xd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e63.", + "block": 228313384, + "measured_at": "2026-08-02T19:08:53Z" + } + }, + + "permissions": { + "scanner_result": "completed", + "scanner_tool": "deficollective/permission-scanner (crytic-compile + Slither)", + "scanner_ran_at": "2026-08-02T19:08:53Z", + "key_permissioned_functions": [ + "OstiumVault.requestWithdraw(uint256) — no onlyOwner; user-callable BUT initiates async flow", + "OstiumVault.claimWithdraw(uint256) — no onlyOwner; user-callable ONLY after operator settles", + "OstiumVault.settle(uint256,uint256) — modifier: onlyGov (settlement gate; operator-only)", + "OstiumVault.setGov(address) — modifier: onlyGov", + "OstiumVault.pause()/unpause() — modifier: onlyGov", + "OstiumTrading.openTrade(...) x22 — modifier: onlyGov", + "OstiumTrading.setGov(address) — modifier: onlyGov", + "OstiumTradingCallbacks.updateTp/updateSl/closeTrade x16 — modifier: onlyGov", + "OstiumTradingStorage.setGov(address)/addSupportedToken(address) x34 — modifier: onlyGov", + "OstiumTimelockOwner.schedule/execute/grantRole — OZ standard (PROPOSER/EXECUTOR/ADMIN)" + ], + "manual_observations": [ + "ProxyAdmin controls upgrades for oLP vault, Trading, PairInfos, PairsStorage proxies.", + "ProxyAdmin owner = TimelockOwner (18h delay) which is itself proposer/executor = Gnosis Safe 4/8.", + "Full governance path: Safe 4/8 → Timelock 18h → ProxyAdmin → proxy upgrades.", + "KEY FINDING: tryNewSettlement() is PUBLIC — anyone can advance the settlement counter after maxSettlementInterval has elapsed. No admin permission required for the fallback. This is the censorship-resistance mechanism.", + "forceSettlement: onlyGov is an emergency override (bypasses interval check), not the required path for normal withdrawals.", + "maxSettlementInterval: gov changed from 24h (init) to 30 days. Last settlement was 19 days ago (2026-07-14). tryNewSettlement() not yet callable. withdrawSettlementDelay=2 means 3 settlements needed for a complete withdrawal.", + "Governance risk: updateMaxSettlementInterval(onlyGov) and updateWithdrawSettlementDelay(onlyGov) both expand the maximum lock period. Current worst-case: 90 days.", + "Pause is on OstiumTrading/OstiumTradingCallbacks (onlyManager) — does NOT affect OstiumVault LP withdrawals.", + "Ostium uses Stork + Chainlink price feeds; oracle is an operator dependency for trade settlement." + ] + }, + + "exit": { + "funds_location": { + "value": "public_contract", + "source": "User funds (LP deposits) held in oLP vault proxy (0x20d419...). Trader collateral also in vault.", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "funds_contract": { + "value": "0x20d419a8e12c45f88fda7c5760bb6923cee27f98", + "source": "https://ostium-labs.gitbook.io/ostium-docs/security/smart-contract-audits + Arbiscan", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "contracts_verified": { + "value": true, + "source": "Etherscan API v2 (chainid=42161): oLP vault proxy verified (TransparentUpgradeableProxy, solc 0.8.9), oLP vault impl verified (OstiumVault, solc 0.8.24), Trading proxy verified (solc 0.8.9), Trading impl verified (OstiumTrading, solc 0.8.24), TimelockOwner verified (solc 0.8.24). Source code downloaded successfully by permission-scanner.", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "chain": { + "value": "arbitrum", + "chain_id": 42161, + "source": "Arbiscan confirms all addresses on Arbitrum One", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "chain_l2beat_stage": { + "value": 1, + "source": "https://l2beat.com/scaling/summary — Arbitrum One listed as Stage 1. Fetched 2026-08-02.", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "upgrade_delay_seconds": { + "value": 64800, + "source": "TimelockOwner.getMinDelay() = 64800 (18 hours). This gates ProxyAdmin which controls proxy upgrades.", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "lp_exit": { + "mechanism": "3-step: requestWithdraw(shares) → wait withdrawSettlementDelay (=2) settlements to pass → claimWithdraw(settlementId)", + "permission_gate": "none — claimWithdraw has no modifier. requestWithdraw uses checks (balance gate only).", + "settlement_advancement": "CRITICAL: settlements advance two ways — (a) operator calls _settlement() via normal protocol flow; (b) anyone calls tryNewSettlement() PUBLIC function after maxSettlementInterval has elapsed. Fallback exists, no admin permission to use it.", + "current_state": { + "lastSettlementId": 125, + "lastSettlementTs": "2026-07-14T23:39:08Z", + "days_since_last_settlement": 19, + "maxSettlementInterval_seconds": 2592000, + "maxSettlementInterval_days": 30, + "withdrawSettlementDelay": 2, + "tryNewSettlement_callable_in_days": 11, + "worst_case_exit_days": 90, + "note": "maxSettlementInterval was initialized at 24h but gov changed it to 30 days. Last settlement 19 days ago — tryNewSettlement() not yet callable. User requesting withdrawal today needs 3 settlements; each at most 30 days apart: worst-case 90-day lock." + }, + "can_exit_without_operator": "true with delay — fallback tryNewSettlement() allows anyone to trigger after maxSettlementInterval. But gov controls that interval (currently 30 days, was 24h).", + "governance_risk": "updateMaxSettlementInterval onlyGov: if gov increases interval to max, effective max lock increases proportionally. updateWithdrawSettlementDelay onlyGov: adding settlement IDs multiplies the wait.", + "tier": "bytecode + onchain", + "source": "OstiumVault.sol source (verified solc 0.8.24). tryNewSettlement() public function confirmed. On-chain reads: lastSettlementId=125, lastSettlementTs=1784072348 (2026-07-14), maxSettlementInterval=2592000, withdrawSettlementDelay=2.", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "can_user_exit_unilaterally": { + "value": true, + "qualifier": "time-gated with public fallback — worst-case 90 days if protocol goes dark (3 × 30-day interval). No admin approval required but gov controls interval length.", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "exit_function": { + "value": "requestWithdraw(uint256 shares) then claimWithdraw(uint32 settlementId) on OstiumVault 0x20d419a8e12c45f88fda7c5760bb6923cee27f98", + "tier": "bytecode", + "source": "OstiumVault impl 0x1E20E46C92F0786889462F065BC9DA163AF6020D (solc 0.8.24)", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "exit_depends_on": { + "value": "operator", + "source": "Stork + Chainlink oracle feeds required for trade settlement. TradingCallbacks contract processes order outcomes. Without oracle liveness, settlement is blocked.", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "forced_inclusion": { + "value": "n/a", + "source": "Ostium is a dApp on Arbitrum One, not a rollup.", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "alternative_frontend": { + "value": "unknown", + "source": "Not verified.", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + } + } +} diff --git a/harnesses/permissions-scan/out/vertex.json b/harnesses/permissions-scan/out/vertex.json new file mode 100644 index 00000000..46148e9e --- /dev/null +++ b/harnesses/permissions-scan/out/vertex.json @@ -0,0 +1,217 @@ +{ + "project": "vertex", + "measured_at": "2026-08-02T19:08:53Z", + "block": 490422447, + "chain_id": 42161, + "rpc_used": "https://arb1.arbitrum.io/rpc", + "contracts": { + "Endpoint_proxy": { + "value": "0xbbee07b3e8121227afcfe1e2b82772246226128e", + "source": "https://arbiscan.io/search?q=vertex+endpoint \u2014 label 'Vertex Protocol: Endpoint'; confirmed on-chain (bytecode present)", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "Endpoint_impl": { + "value": "0x91ffc881837ffb3eec0c62e19675425ee3a38c74", + "source": "cast storage Endpoint EIP-1967-impl-slot", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "Clearinghouse_proxy": { + "value": "0xae1ec28d6225dce2ff787dcb8ce11cf6d3ae064f", + "source": "https://arbiscan.io/search?q=vertex+endpoint \u2014 label 'Vertex Protocol: Clearinghouse'", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "Clearinghouse_impl": { + "value": "0x63a49718d19d8182bf20fc135372c2f84a0586bf", + "source": "cast storage Clearinghouse EIP-1967-impl-slot", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "SpotEngine": { + "value": "0x32d91af2b17054d575a7bf1acfa7615f41ccefab", + "source": "https://arbiscan.io/search?q=vertex+endpoint \u2014 label 'Vertex Protocol: Spot Engine'", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "PerpEngine": { + "value": "0xb74c78cca0fadafbee52b2f48a67ee8c834b5fd1", + "source": "https://arbiscan.io/search?q=vertex+endpoint \u2014 label 'Vertex Protocol: Perp Engine'", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "OffchainExchange": { + "value": "0xa4369d8e3dc847aedf17f4125f1abb1bc18fc060", + "source": "https://arbiscan.io/search?q=vertex+endpoint \u2014 label 'Vertex Protocol: Offchain Exchange'", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "Querier": { + "value": "0x1693273b443699bee277ecbc60e2c8027e91995d", + "source": "https://arbiscan.io/search?q=vertex+endpoint \u2014 label 'Vertex Protocol: Querier'", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + } + }, + "owners": { + "Endpoint_owner_proxy": { + "value": "0x2BC1F3512C372F54D987B1de7A6EB72DFdF61533", + "source": "cast call Endpoint owner() = 0x2BC1F3512C372F54D987B1de7A6EB72DFdF61533", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z", + "note": "This address is itself a proxy (EIP-1967 impl: 0xb7eb64ae8cfa83f66b19da0522d672f6adcb7529). Not a direct Safe." + }, + "Endpoint_owner_proxy_owner": { + "value": "0xC6B129179B68F9dF026AFA3914ef504C498c5bC4", + "source": "cast call 0x2BC1F3512C372F54D987B1de7A6EB72DFdF61533 owner() = 0xC6B129179B68F9dF026AFA3914ef504C498c5bC4", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z", + "resolved": { + "type": "safe", + "threshold": 4, + "total_owners": 6, + "owner_addresses": [ + "0x277B19c67467572107f69Be8Cb2fa343F118dB81", + "0x0B63fEF1926E85507B36A85C44e90f15E096cc25", + "0xEC25E025D9A12C68B8f3549a80C0eF73C83F35b3", + "0x7BeD83895e9BDA34Cd50eF88C082099c82293a6A", + "0x5BeEc2EFEBf648e0Fed309AF1e654f2F92c8939b", + "0xABFc5C9f5afAbFb909bFD8C0ba74E355825C223D" + ], + "source": "cast call 0xC6B129179B68F9dF026AFA3914ef504C498c5bC4 getThreshold() = 4; getOwners() = [6 addresses]", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + } + }, + "upgrade_path": { + "value": "Safe 4/6 (0xC6B129...) \u2192 owner proxy (0x2BC1F3...) \u2192 Endpoint (0xbbee07...)", + "source": "chained owner() calls on-chain", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "upgrade_delay_seconds": { + "value": "unknown", + "source": "No Timelock detected in ownership chain. Safe 4/6 directly (via proxy) controls the Endpoint. No getMinDelay() found in the chain. If no timelock, effective delay = 0.", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + } + }, + "permissions": { + "scanner_result": "not_run", + "scanner_failure_reason": "Vertex implementation contracts (Endpoint impl 0x91ffc8..., Clearinghouse impl 0x63a497..., SpotEngine 0x32d91a..., PerpEngine 0xb74c78..., OffchainExchange 0xa43698...) are NOT verified on Arbiscan. Etherscan API v2 returns 'Contract source code not verified' for all implementation addresses. Only proxy wrappers (TransparentUpgradeableProxy) are verified. Static analysis cannot proceed without source code.", + "contracts_verified_detail": { + "Endpoint_proxy": "verified (TransparentUpgradeableProxy)", + "Endpoint_impl": "NOT verified", + "Clearinghouse_proxy": "verified (TransparentUpgradeableProxy)", + "Clearinghouse_impl": "NOT verified", + "SpotEngine": "NOT verified", + "PerpEngine": "NOT verified", + "OffchainExchange": "NOT verified", + "Querier": "NOT verified" + }, + "manual_observations": [ + "Vertex uses an off-chain sequencer (OffchainExchange) for order matching.", + "On-chain settlement occurs via Endpoint. Clearinghouse holds TVL.", + "SpotEngine and PerpEngine hold position state.", + "Owner of Endpoint is a proxy whose underlying implementation owner is a Gnosis Safe 4/6. No timelock detected between Safe and Endpoint.", + "Slow-mode mechanism: Endpoint.submitSlowModeTransaction() exists in source code (github.com/vertex-protocol/vertex-contracts/blob/main/core/contracts/Endpoint.sol). Allows users to submit transactions directly if sequencer is unresponsive, executable after a configurable timeout.", + "slowModeConfig() and nonce() calls on Endpoint reverted \u2014 exact parameter names in deployed ABI differ from test call signatures.", + "CRITICAL: All implementation contracts are unverified. The permission surface of the actual deployed code is opaque \u2014 source on GitHub may not match deployed bytecode." + ] + }, + "exit": { + "funds_location": { + "value": "public_contract", + "source": "Clearinghouse (0xae1ec2...) holds TVL. Users deposit to Endpoint which routes to Clearinghouse.", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z", + "tier": "onchain" + }, + "funds_contract": { + "value": "0xae1ec28d6225dce2ff787dcb8ce11cf6d3ae064f", + "source": "https://arbiscan.io (label: Vertex Protocol: Clearinghouse)", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z", + "tier": "onchain" + }, + "contracts_verified": { + "value": "partial", + "source": "Etherscan API v2 (chainid=42161) queried with valid key. Proxy wrappers (Endpoint proxy, Clearinghouse proxy) verified as TransparentUpgradeableProxy. ALL implementation contracts (Endpoint impl 0x91ffc8..., Clearinghouse impl 0x63a497..., SpotEngine 0x32d91a..., PerpEngine 0xb74c78..., OffchainExchange 0xa43698..., Querier 0x169327...) return 'Contract source code not verified'. Vertex deploys unverified implementation contracts on Arbitrum.", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z", + "tier": "onchain" + }, + "chain": { + "value": "arbitrum", + "chain_id": 42161, + "source": "Arbiscan confirms all addresses on Arbitrum One", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "chain_l2beat_stage": { + "value": 1, + "source": "https://l2beat.com/scaling/summary \u2014 Arbitrum One listed as Stage 1. Fetched 2026-08-02.", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z", + "tier": "documented" + }, + "upgrade_delay_seconds": { + "value": "unknown", + "source": "Safe 4/6 controls Endpoint via a proxy wrapper, no Timelock detected in chain. If no timelock exists, effective upgrade delay = 0. Requires deeper investigation of the owner proxy contract to confirm absence of timelock.", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z", + "tier": "onchain" + }, + "can_user_exit_unilaterally": { + "value": "unknown", + "implementation_verified": false, + "source_repo_claims_slow_mode": true, + "bytecode_matches_repo": "unverified", + "source": "Endpoint impl 0x91ffc8 is NOT verified on Arbiscan. GitHub repo (vertex-protocol/vertex-contracts) documents submitSlowModeTransaction() but the deployed bytecode cannot be compared to the repo. The repo describes an intent, the bytecode describes the system. No statement can be made about the actual deployed contract behavior.", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "exit_function": { + "value": "unknown \u2014 bytecode unverified", + "tier": "documented", + "repo_claim": "submitSlowModeTransaction(IEndpoint.SlowModeTx) on Endpoint per github.com/vertex-protocol/vertex-contracts", + "source": "GitHub repo only. Not derivable from deployed bytecode (implementation not verified on Arbiscan).", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z" + }, + "exit_depends_on": { + "value": "sequencer", + "source": "Normal operations require sequencer (OffchainExchange) to process orders. However, slow-mode bypasses sequencer after timeout. Dependency is on sequencer for normal exit; slow-mode provides sequencer-independent fallback.", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z", + "tier": "documented" + }, + "forced_inclusion": { + "value": "n/a", + "source": "Vertex is a dApp on Arbitrum One, not a rollup. The slow-mode mechanism is Vertex-native, not an L1 forced inclusion mechanism.", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z", + "tier": "n/a" + }, + "alternative_frontend": { + "value": "unknown", + "source": "Not verified.", + "block": 490422447, + "measured_at": "2026-08-02T19:08:53Z", + "tier": "unknown" + }, + "lp_exit": { + "note": "Vertex does not use an LP vault model in the same sense. Clearinghouse holds collateral. Withdrawal path is via Endpoint.", + "tier": "onchain", + "source": "Architecture from Arbiscan labels and GitHub repo structure." + }, + "trader_exit": { + "mechanism": "submitSlowModeTransaction() after sequencer timeout \u2014 per GitHub source", + "permission_gate": "unknown \u2014 implementation not verified on Arbiscan", + "can_exit_without_sequencer_if_slow_mode": "unknown \u2014 bytecode unverified", + "tier": "documented", + "source": "github.com/vertex-protocol/vertex-contracts only. Bytecode NOT verified." + } + } +} \ No newline at end of file diff --git a/harnesses/permissions-scan/targets/gains/contracts.json b/harnesses/permissions-scan/targets/gains/contracts.json new file mode 100644 index 00000000..fa388dea --- /dev/null +++ b/harnesses/permissions-scan/targets/gains/contracts.json @@ -0,0 +1,95 @@ +{ + "chain": "arbi", + "project": "gains", + "addresses": [ + "0xFF162c694eAA571f685030649814282eA457f169", + "0xe18be0113c38c91b3B429d04fDeb84359fBCb2eB", + "0x5f5E4892BAB94d94DC57a3edeA3c138167c4DF0F", + "0x1632C38cB208df8409753729dBfbA5c58626F637", + "0x7edDE7e5900633F698EaB0Dbc97DE640fC5dC015", + "0xd85E038593d7A098614721EaE955EC2022B9B91B", + "0x4BeeF1113F968326905224D2Ca272f3032A9a9F4", + "0x5977A9682D7AF81D347CFc338c61692163a2784C", + "0xd3443ee1e91aF28e5FB858Fbd0D72A63bA8046E0" + ], + "sources": [ + { + "address": "0xFF162c694eAA571f685030649814282eA457f169", + "label": "GNSMultiCollatDiamond", + "found_at": "https://docs.gains.trade/what-is-gains-network/contract-addresses/arbitrum-mainnet", + "consulted_at": "2026-08-02T19:08:53Z", + "is_proxy": true, + "proxy_type": "EIP-2535 Diamond + EIP-1967", + "implementation": "0xff84c4a0d639d598af2088e2ffb76cdbdf1de0ed", + "impl_slot_read": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc", + "admin_slot_read": "0xe18be0113c38c91b3b429d04fdeb84359fbcb2eb" + }, + { + "address": "0xe18be0113c38c91b3B429d04fDeb84359fBCb2eB", + "label": "ProxyAdmin", + "found_at": "https://docs.gains.trade/what-is-gains-network/contract-addresses/arbitrum-mainnet", + "consulted_at": "2026-08-02T19:08:53Z", + "is_proxy": false, + "implementation": null, + "note": "OZ ProxyAdmin; getProxyImplementation(diamond) returns 0xff84c4... confirmed on-chain" + }, + { + "address": "0x5f5E4892BAB94d94DC57a3edeA3c138167c4DF0F", + "label": "GNSTimelockOwner (14-day)", + "found_at": "https://docs.gains.trade/what-is-gains-network/contract-addresses/arbitrum-mainnet", + "consulted_at": "2026-08-02T19:08:53Z", + "is_proxy": false, + "implementation": null, + "note": "TimelockController; getMinDelay() = 1209600 confirmed on-chain; owner of ProxyAdmin" + }, + { + "address": "0x1632C38cB208df8409753729dBfbA5c58626F637", + "label": "GNSTimelockManager (3-day)", + "found_at": "https://docs.gains.trade/what-is-gains-network/contract-addresses/arbitrum-mainnet", + "consulted_at": "2026-08-02T19:08:53Z", + "is_proxy": false, + "implementation": null, + "note": "TimelockController; getMinDelay() = 259200 confirmed on-chain" + }, + { + "address": "0x7edDE7e5900633F698EaB0Dbc97DE640fC5dC015", + "label": "GNSStaking", + "found_at": "https://docs.gains.trade/what-is-gains-network/contract-addresses/arbitrum-mainnet", + "consulted_at": "2026-08-02T19:08:53Z", + "is_proxy": false, + "implementation": null + }, + { + "address": "0xd85E038593d7A098614721EaE955EC2022B9B91B", + "label": "gDAI vault (ERC4626)", + "found_at": "https://docs.gains.trade/what-is-gains-network/contract-addresses/arbitrum-mainnet", + "consulted_at": "2026-08-02T19:08:53Z", + "is_proxy": false, + "implementation": null + }, + { + "address": "0x4BeeF1113F968326905224D2Ca272f3032A9a9F4", + "label": "gGNS vault (ERC4626)", + "found_at": "https://docs.gains.trade/what-is-gains-network/contract-addresses/arbitrum-mainnet", + "consulted_at": "2026-08-02T19:08:53Z", + "is_proxy": false, + "implementation": null + }, + { + "address": "0x5977A9682D7AF81D347CFc338c61692163a2784C", + "label": "gETH vault (ERC4626)", + "found_at": "https://docs.gains.trade/what-is-gains-network/contract-addresses/arbitrum-mainnet", + "consulted_at": "2026-08-02T19:08:53Z", + "is_proxy": false, + "implementation": null + }, + { + "address": "0xd3443ee1e91aF28e5FB858Fbd0D72A63bA8046E0", + "label": "gUSDC vault (ERC4626)", + "found_at": "https://docs.gains.trade/what-is-gains-network/contract-addresses/arbitrum-mainnet", + "consulted_at": "2026-08-02T19:08:53Z", + "is_proxy": false, + "implementation": null + } + ] +} diff --git a/harnesses/permissions-scan/targets/gains/permissions.json b/harnesses/permissions-scan/targets/gains/permissions.json new file mode 100644 index 00000000..4ac60595 --- /dev/null +++ b/harnesses/permissions-scan/targets/gains/permissions.json @@ -0,0 +1,1652 @@ +{ + "GNSMultiCollatDiamond": { + "Implementation_Address": "0xff84c4a0d639d598af2088e2ffb76cdbdf1de0ed", + "Proxy_Address": "0xFF162c694eAA571f685030649814282eA457f169", + "proxy_permissions": { + "Contract_Name": "TransparentUpgradeableProxy", + "Functions": [ + { + "Function": "fallback", + "Modifiers": [], + "msg.sender_conditions": [ + "msg.sender == _getAdmin()" + ], + "state_variables_read": [ + "_IMPLEMENTATION_SLOT", + "_ADMIN_SLOT" + ], + "state_variables_written": [] + }, + { + "Function": "receive", + "Modifiers": [], + "msg.sender_conditions": [ + "msg.sender == _getAdmin()" + ], + "state_variables_read": [ + "_IMPLEMENTATION_SLOT", + "_ADMIN_SLOT" + ], + "state_variables_written": [] + }, + { + "Function": "_fallback", + "Modifiers": [], + "msg.sender_conditions": [ + "msg.sender == _getAdmin()" + ], + "state_variables_read": [ + "_IMPLEMENTATION_SLOT", + "_ADMIN_SLOT" + ], + "state_variables_written": [] + } + ] + }, + "permissions": { + "Contract_Name": "GNSMultiCollatDiamond", + "Functions": [ + { + "Function": "diamondCut", + "Modifiers": [ + "onlyRoles" + ], + "msg.sender_conditions": [ + "! hasRoles(msg.sender,_roleA,_roleB)" + ], + "state_variables_read": [ + "_account", + "msg.sender", + "addressStore", + "_roleA", + "_roleB" + ], + "state_variables_written": [], + "addressStore": "00000000000000000000000018c11fd286c5ec11c3b683caa813b77f5163a122" + }, + { + "Function": "initialize", + "Modifiers": [ + "initializer" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "this", + "AddressUpgradeable", + "_initialized", + "_initializing", + "isTopLevelCall", + "addressStore", + "account", + "TMP_27" + ], + "state_variables_written": [ + "_initialized", + "addressStore", + "_initializing" + ], + "_initialized": 26, + "_initializing": false, + "addressStore": "00000000000000000000000018c11fd286c5ec11c3b683caa813b77f5163a122" + }, + { + "Function": "initializeGovEmergencyTimelock", + "Modifiers": [ + "reinitializer" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "version", + "_initializing", + "addressStore", + "_initialized" + ], + "state_variables_written": [ + "_initialized", + "addressStore", + "_initializing" + ], + "_initialized": 26, + "_initializing": false, + "addressStore": "00000000000000000000000018c11fd286c5ec11c3b683caa813b77f5163a122" + }, + { + "Function": "setRoles", + "Modifiers": [ + "onlyRoles" + ], + "msg.sender_conditions": [ + "! hasRoles(msg.sender,_roleA,_roleB)", + "_roles[i] == Role.GOV_TIMELOCK && _accounts[i] == msg.sender" + ], + "state_variables_read": [ + "_account", + "msg.sender", + "addressStore", + "_roleA", + "_roleB" + ], + "state_variables_written": [ + "addressStore" + ], + "addressStore": "00000000000000000000000018c11fd286c5ec11c3b683caa813b77f5163a122" + }, + { + "Function": "_enforceRole", + "Modifiers": [], + "msg.sender_conditions": [ + "! hasRole(msg.sender,_role)" + ], + "state_variables_read": [ + "addressStore" + ], + "state_variables_written": [], + "addressStore": "00000000000000000000000018c11fd286c5ec11c3b683caa813b77f5163a122" + }, + { + "Function": "_enforceRoles", + "Modifiers": [], + "msg.sender_conditions": [ + "! hasRoles(msg.sender,_roleA,_roleB)" + ], + "state_variables_read": [ + "addressStore" + ], + "state_variables_written": [], + "addressStore": "00000000000000000000000018c11fd286c5ec11c3b683caa813b77f5163a122" + } + ], + "storage_values": { + "_initialized": 26, + "_initializing": false, + "addressStore": "00000000000000000000000018c11fd286c5ec11c3b683caa813b77f5163a122" + } + } + }, + "GNSTimelockOwner": { + "Address": "0x5f5E4892BAB94d94DC57a3edeA3c138167c4DF0F", + "permissions": { + "Contract_Name": "GNSTimelockOwner", + "Functions": [ + { + "Function": "schedule", + "Modifiers": [ + "onlyRole" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "PROPOSER_ROLE", + "_minDelay", + "role", + "length", + "_ADDRESS_LENGTH", + "msg.sender", + "_SYMBOLS", + "addr", + "buffer", + "i", + "_roles", + "account", + "Strings", + "value", + "_timestamps" + ], + "state_variables_written": [ + "_timestamps" + ], + "immutables_and_constants": [ + { + "name": "PROPOSER_ROLE", + "slot": "keccak256(bytes)(PROPOSER_ROLE)" + } + ], + "_roles": "0000000000000000000000000000000000000000000000000000000000000000", + "_timestamps": 0, + "_minDelay": 1209600 + }, + { + "Function": "scheduleBatch", + "Modifiers": [ + "onlyRole" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "PROPOSER_ROLE", + "_minDelay", + "role", + "length", + "_ADDRESS_LENGTH", + "msg.sender", + "_SYMBOLS", + "addr", + "buffer", + "i", + "_roles", + "account", + "Strings", + "value", + "_timestamps" + ], + "state_variables_written": [ + "_timestamps" + ], + "immutables_and_constants": [ + { + "name": "PROPOSER_ROLE", + "slot": "keccak256(bytes)(PROPOSER_ROLE)" + } + ], + "_roles": "0000000000000000000000000000000000000000000000000000000000000000", + "_timestamps": 0, + "_minDelay": 1209600 + }, + { + "Function": "cancel", + "Modifiers": [ + "onlyRole" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "role", + "CANCELLER_ROLE", + "length", + "_ADDRESS_LENGTH", + "msg.sender", + "_SYMBOLS", + "addr", + "buffer", + "i", + "_DONE_TIMESTAMP", + "_roles", + "account", + "Strings", + "value", + "_timestamps" + ], + "state_variables_written": [ + "_timestamps" + ], + "immutables_and_constants": [ + { + "name": "CANCELLER_ROLE", + "slot": "keccak256(bytes)(CANCELLER_ROLE)" + }, + { + "name": "_DONE_TIMESTAMP", + "slot": "uint256(1)" + } + ], + "_roles": "0000000000000000000000000000000000000000000000000000000000000000", + "_timestamps": 0 + }, + { + "Function": "execute", + "Modifiers": [ + "onlyRoleOrOpenRole" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "role", + "length", + "_ADDRESS_LENGTH", + "msg.sender", + "_SYMBOLS", + "addr", + "buffer", + "i", + "EXECUTOR_ROLE", + "_roles", + "account", + "_DONE_TIMESTAMP", + "Strings", + "value", + "_timestamps" + ], + "state_variables_written": [ + "_timestamps" + ], + "immutables_and_constants": [ + { + "name": "EXECUTOR_ROLE", + "slot": "keccak256(bytes)(EXECUTOR_ROLE)" + }, + { + "name": "_DONE_TIMESTAMP", + "slot": "uint256(1)" + } + ], + "_roles": "0000000000000000000000000000000000000000000000000000000000000000", + "_timestamps": 0 + }, + { + "Function": "executeBatch", + "Modifiers": [ + "onlyRoleOrOpenRole" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "role", + "length", + "_ADDRESS_LENGTH", + "msg.sender", + "_SYMBOLS", + "addr", + "buffer", + "i", + "EXECUTOR_ROLE", + "_roles", + "account", + "_DONE_TIMESTAMP", + "Strings", + "value", + "_timestamps" + ], + "state_variables_written": [ + "_timestamps" + ], + "immutables_and_constants": [ + { + "name": "EXECUTOR_ROLE", + "slot": "keccak256(bytes)(EXECUTOR_ROLE)" + }, + { + "name": "_DONE_TIMESTAMP", + "slot": "uint256(1)" + } + ], + "_roles": "0000000000000000000000000000000000000000000000000000000000000000", + "_timestamps": 0 + }, + { + "Function": "updateDelay", + "Modifiers": [], + "msg.sender_conditions": [ + "require(bool,string)(msg.sender == address(this),TimelockController: caller must be timelock)" + ], + "state_variables_read": [ + "_minDelay" + ], + "state_variables_written": [ + "_minDelay" + ], + "_minDelay": 1209600 + }, + { + "Function": "grantRole", + "Modifiers": [ + "getRoleAdmin", + "onlyRole" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "role", + "length", + "_ADDRESS_LENGTH", + "msg.sender", + "_SYMBOLS", + "addr", + "buffer", + "i", + "_roles", + "account", + "Strings", + "value" + ], + "state_variables_written": [ + "_roles" + ], + "_roles": "0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "Function": "revokeRole", + "Modifiers": [ + "getRoleAdmin", + "onlyRole" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "role", + "length", + "_ADDRESS_LENGTH", + "msg.sender", + "_SYMBOLS", + "addr", + "buffer", + "i", + "_roles", + "account", + "Strings", + "value" + ], + "state_variables_written": [ + "_roles" + ], + "_roles": "0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "storage_values": { + "_roles": "0000000000000000000000000000000000000000000000000000000000000000", + "_timestamps": 0, + "_minDelay": 1209600 + } + } + }, + "GNSTimelockManager": { + "Address": "0x1632C38cB208df8409753729dBfbA5c58626F637", + "permissions": { + "Contract_Name": "GNSTimelockManager", + "Functions": [ + { + "Function": "schedule", + "Modifiers": [ + "onlyRole" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "PROPOSER_ROLE", + "_minDelay", + "role", + "length", + "_ADDRESS_LENGTH", + "msg.sender", + "_SYMBOLS", + "buffer", + "addr", + "i", + "_roles", + "account", + "Strings", + "value", + "_timestamps" + ], + "state_variables_written": [ + "_timestamps" + ], + "immutables_and_constants": [ + { + "name": "PROPOSER_ROLE", + "slot": "keccak256(bytes)(PROPOSER_ROLE)" + } + ], + "_roles": "0000000000000000000000000000000000000000000000000000000000000000", + "_timestamps": 0, + "_minDelay": 259200 + }, + { + "Function": "scheduleBatch", + "Modifiers": [ + "onlyRole" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "PROPOSER_ROLE", + "_minDelay", + "role", + "length", + "_ADDRESS_LENGTH", + "msg.sender", + "_SYMBOLS", + "buffer", + "addr", + "i", + "_roles", + "account", + "Strings", + "value", + "_timestamps" + ], + "state_variables_written": [ + "_timestamps" + ], + "immutables_and_constants": [ + { + "name": "PROPOSER_ROLE", + "slot": "keccak256(bytes)(PROPOSER_ROLE)" + } + ], + "_roles": "0000000000000000000000000000000000000000000000000000000000000000", + "_timestamps": 0, + "_minDelay": 259200 + }, + { + "Function": "cancel", + "Modifiers": [ + "onlyRole" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "role", + "CANCELLER_ROLE", + "length", + "_ADDRESS_LENGTH", + "msg.sender", + "_SYMBOLS", + "buffer", + "addr", + "i", + "_DONE_TIMESTAMP", + "_roles", + "account", + "Strings", + "value", + "_timestamps" + ], + "state_variables_written": [ + "_timestamps" + ], + "immutables_and_constants": [ + { + "name": "CANCELLER_ROLE", + "slot": "keccak256(bytes)(CANCELLER_ROLE)" + }, + { + "name": "_DONE_TIMESTAMP", + "slot": "uint256(1)" + } + ], + "_roles": "0000000000000000000000000000000000000000000000000000000000000000", + "_timestamps": 0 + }, + { + "Function": "execute", + "Modifiers": [ + "onlyRoleOrOpenRole" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "role", + "length", + "_ADDRESS_LENGTH", + "msg.sender", + "_SYMBOLS", + "buffer", + "addr", + "i", + "EXECUTOR_ROLE", + "_roles", + "account", + "_DONE_TIMESTAMP", + "Strings", + "value", + "_timestamps" + ], + "state_variables_written": [ + "_timestamps" + ], + "immutables_and_constants": [ + { + "name": "EXECUTOR_ROLE", + "slot": "keccak256(bytes)(EXECUTOR_ROLE)" + }, + { + "name": "_DONE_TIMESTAMP", + "slot": "uint256(1)" + } + ], + "_roles": "0000000000000000000000000000000000000000000000000000000000000000", + "_timestamps": 0 + }, + { + "Function": "executeBatch", + "Modifiers": [ + "onlyRoleOrOpenRole" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "role", + "length", + "_ADDRESS_LENGTH", + "msg.sender", + "_SYMBOLS", + "buffer", + "addr", + "i", + "EXECUTOR_ROLE", + "_roles", + "account", + "_DONE_TIMESTAMP", + "Strings", + "value", + "_timestamps" + ], + "state_variables_written": [ + "_timestamps" + ], + "immutables_and_constants": [ + { + "name": "EXECUTOR_ROLE", + "slot": "keccak256(bytes)(EXECUTOR_ROLE)" + }, + { + "name": "_DONE_TIMESTAMP", + "slot": "uint256(1)" + } + ], + "_roles": "0000000000000000000000000000000000000000000000000000000000000000", + "_timestamps": 0 + }, + { + "Function": "updateDelay", + "Modifiers": [], + "msg.sender_conditions": [ + "require(bool,string)(msg.sender == address(this),TimelockController: caller must be timelock)" + ], + "state_variables_read": [ + "_minDelay" + ], + "state_variables_written": [ + "_minDelay" + ], + "_minDelay": 259200 + }, + { + "Function": "grantRole", + "Modifiers": [ + "getRoleAdmin", + "onlyRole" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "role", + "length", + "_ADDRESS_LENGTH", + "msg.sender", + "_SYMBOLS", + "buffer", + "addr", + "i", + "_roles", + "account", + "Strings", + "value" + ], + "state_variables_written": [ + "_roles" + ], + "_roles": "0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "Function": "revokeRole", + "Modifiers": [ + "getRoleAdmin", + "onlyRole" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "role", + "length", + "_ADDRESS_LENGTH", + "msg.sender", + "_SYMBOLS", + "buffer", + "addr", + "i", + "_roles", + "account", + "Strings", + "value" + ], + "state_variables_written": [ + "_roles" + ], + "_roles": "0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "storage_values": { + "_roles": "0000000000000000000000000000000000000000000000000000000000000000", + "_timestamps": 0, + "_minDelay": 259200 + } + } + }, + "GToken": { + "Implementation_Address": "0xeb754588eff264793bb80be65866d11bc8d6cbdd", + "Proxy_Address": "0xd3443ee1e91aF28e5FB858Fbd0D72A63bA8046E0", + "proxy_permissions": { + "Contract_Name": "TransparentUpgradeableProxy", + "Functions": [ + { + "Function": "fallback", + "Modifiers": [], + "msg.sender_conditions": [ + "msg.sender == _getAdmin()" + ], + "state_variables_read": [ + "_IMPLEMENTATION_SLOT", + "_ADMIN_SLOT" + ], + "state_variables_written": [] + }, + { + "Function": "receive", + "Modifiers": [], + "msg.sender_conditions": [ + "msg.sender == _getAdmin()" + ], + "state_variables_read": [ + "_IMPLEMENTATION_SLOT", + "_ADMIN_SLOT" + ], + "state_variables_written": [] + }, + { + "Function": "_fallback", + "Modifiers": [], + "msg.sender_conditions": [ + "msg.sender == _getAdmin()" + ], + "state_variables_read": [ + "_IMPLEMENTATION_SLOT", + "_ADMIN_SLOT" + ], + "state_variables_written": [] + } + ] + }, + "permissions": { + "Contract_Name": "GToken", + "Functions": [ + { + "Function": "__Ownable_init", + "Modifiers": [ + "onlyInitializing" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "_initializing", + "_owner" + ], + "state_variables_written": [ + "_owner" + ], + "_initializing": false, + "_owner": "0x5f5E4892BAB94d94DC57a3edeA3c138167c4DF0F" + }, + { + "Function": "__Ownable_init_unchained", + "Modifiers": [ + "onlyInitializing" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "_initializing", + "_owner" + ], + "state_variables_written": [ + "_owner" + ], + "_initializing": false, + "_owner": "0x5f5E4892BAB94d94DC57a3edeA3c138167c4DF0F" + }, + { + "Function": "renounceOwnership", + "Modifiers": [ + "onlyOwner" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "_owner", + "msg.sender" + ], + "state_variables_written": [ + "_owner" + ], + "_owner": "0x5f5E4892BAB94d94DC57a3edeA3c138167c4DF0F" + }, + { + "Function": "transferOwnership", + "Modifiers": [ + "onlyOwner" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "_owner", + "msg.sender" + ], + "state_variables_written": [ + "_owner" + ], + "_owner": "0x5f5E4892BAB94d94DC57a3edeA3c138167c4DF0F" + }, + { + "Function": "__Context_init", + "Modifiers": [ + "onlyInitializing" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "_initializing" + ], + "state_variables_written": [], + "_initializing": false + }, + { + "Function": "__Context_init_unchained", + "Modifiers": [ + "onlyInitializing" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "_initializing" + ], + "state_variables_written": [], + "_initializing": false + }, + { + "Function": "__ERC4626_init", + "Modifiers": [ + "onlyInitializing" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "_initializing" + ], + "state_variables_written": [ + "_asset", + "_underlyingDecimals" + ], + "_initializing": false + }, + { + "Function": "__ERC4626_init_unchained", + "Modifiers": [ + "onlyInitializing" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "_initializing" + ], + "state_variables_written": [ + "_asset", + "_underlyingDecimals" + ], + "_initializing": false + }, + { + "Function": "__ERC20_init", + "Modifiers": [ + "onlyInitializing" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "_initializing" + ], + "state_variables_written": [ + "_name", + "_symbol" + ], + "_initializing": false + }, + { + "Function": "__ERC20_init_unchained", + "Modifiers": [ + "onlyInitializing" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "_initializing" + ], + "state_variables_written": [ + "_name", + "_symbol" + ], + "_initializing": false + }, + { + "Function": "initialize", + "Modifiers": [ + "initializer", + "onlyInitializing" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "PRECISION_18", + "AddressUpgradeable", + "_owner", + "_initialized", + "MAX_LOSSES_BURN_P", + "_initializing", + "isTopLevelCall", + "MAX_DISCOUNT_P", + "TMP_396", + "MAX_SUPPLY_INCREASE_DAILY_P", + "MIN_DAILY_ACC_PNL_DELTA", + "MAX_GNS_SUPPLY_MINT_DAILY_P", + "account", + "this" + ], + "state_variables_written": [ + "lossesBurnP", + "_initializing", + "maxGnsSupplyMintDailyP", + "maxDiscountP", + "_initialized", + "maxDiscountThresholdP", + "shareToAssetsPrice", + "MIN_LOCK_DURATION", + "gnsToken", + "lockedDepositNft", + "manager", + "_asset", + "WITHDRAW_EPOCHS_LOCKS", + "admin", + "_underlyingDecimals", + "currentEpoch", + "maxAccOpenPnlDelta", + "pnlHandler", + "currentEpochStart", + "_name", + "maxDailyAccPnlDelta", + "_symbol", + "openTradesPnlFeed", + "withdrawLockThresholdsP", + "gnsPriceProvider", + "maxSupplyIncreaseDailyP", + "_owner" + ], + "immutables_and_constants": [ + { + "name": "PRECISION_18", + "slot": "1e18", + "value": "0x0000000000000000000000000000000000000000" + }, + { + "name": "MIN_DAILY_ACC_PNL_DELTA", + "slot": "PRECISION_18 / 10" + }, + { + "name": "MAX_SUPPLY_INCREASE_DAILY_P", + "slot": "50 * PRECISION_18" + }, + { + "name": "MAX_LOSSES_BURN_P", + "slot": "25 * PRECISION_18" + }, + { + "name": "MAX_GNS_SUPPLY_MINT_DAILY_P", + "slot": "PRECISION_18 / 20" + }, + { + "name": "MAX_DISCOUNT_P", + "slot": "10 * PRECISION_18" + } + ], + "_initialized": 3, + "_initializing": false, + "_owner": "0x5f5E4892BAB94d94DC57a3edeA3c138167c4DF0F" + }, + { + "Function": "initializeV3", + "Modifiers": [ + "reinitializer" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "version", + "_initializing", + "_asset", + "_initialized" + ], + "state_variables_written": [ + "_initialized", + "collateralConfig", + "_initializing" + ], + "_initialized": 3, + "_initializing": false, + "_asset": "af88d065e77c8cc2239327c5edb3a432268e5831" + }, + { + "Function": "transferOwnership", + "Modifiers": [ + "onlyOwner" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "admin", + "manager", + "_owner", + "msg.sender" + ], + "state_variables_written": [ + "_owner" + ], + "_owner": "0x5f5E4892BAB94d94DC57a3edeA3c138167c4DF0F", + "manager": "0x1632C38cB208df8409753729dBfbA5c58626F637", + "admin": "0xe8997C502fCD0729B462FCA19A50cF0DAEA0cAB5" + }, + { + "Function": "updateManager", + "Modifiers": [ + "onlyOwner" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "admin", + "_owner", + "msg.sender" + ], + "state_variables_written": [ + "manager" + ], + "_owner": "0x5f5E4892BAB94d94DC57a3edeA3c138167c4DF0F", + "admin": "0xe8997C502fCD0729B462FCA19A50cF0DAEA0cAB5" + }, + { + "Function": "updateAdmin", + "Modifiers": [ + "onlyManager" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "manager", + "_owner", + "msg.sender" + ], + "state_variables_written": [ + "admin" + ], + "_owner": "0x5f5E4892BAB94d94DC57a3edeA3c138167c4DF0F", + "manager": "0x1632C38cB208df8409753729dBfbA5c58626F637" + }, + { + "Function": "updatePnlHandler", + "Modifiers": [ + "onlyOwner" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "_owner", + "msg.sender" + ], + "state_variables_written": [ + "pnlHandler" + ], + "_owner": "0x5f5E4892BAB94d94DC57a3edeA3c138167c4DF0F" + }, + { + "Function": "updateGnsPriceProvider", + "Modifiers": [ + "onlyManager" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "manager", + "msg.sender" + ], + "state_variables_written": [ + "gnsPriceProvider" + ], + "manager": "0x1632C38cB208df8409753729dBfbA5c58626F637" + }, + { + "Function": "updateOpenTradesPnlFeed", + "Modifiers": [ + "onlyOwner" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "_owner", + "msg.sender" + ], + "state_variables_written": [ + "openTradesPnlFeed" + ], + "_owner": "0x5f5E4892BAB94d94DC57a3edeA3c138167c4DF0F" + }, + { + "Function": "updateMaxAccOpenPnlDelta", + "Modifiers": [ + "onlyOwner" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "_owner", + "msg.sender" + ], + "state_variables_written": [ + "maxAccOpenPnlDelta" + ], + "_owner": "0x5f5E4892BAB94d94DC57a3edeA3c138167c4DF0F" + }, + { + "Function": "updateMaxDailyAccPnlDelta", + "Modifiers": [ + "onlyManager" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "manager", + "MIN_DAILY_ACC_PNL_DELTA", + "msg.sender" + ], + "state_variables_written": [ + "maxDailyAccPnlDelta" + ], + "immutables_and_constants": [ + { + "name": "MIN_DAILY_ACC_PNL_DELTA", + "slot": "PRECISION_18 / 10" + } + ], + "manager": "0x1632C38cB208df8409753729dBfbA5c58626F637" + }, + { + "Function": "updateWithdrawLockThresholdsP", + "Modifiers": [ + "onlyOwner" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "_owner", + "msg.sender" + ], + "state_variables_written": [ + "withdrawLockThresholdsP" + ], + "_owner": "0x5f5E4892BAB94d94DC57a3edeA3c138167c4DF0F" + }, + { + "Function": "updateMaxSupplyIncreaseDailyP", + "Modifiers": [ + "onlyManager" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "MAX_SUPPLY_INCREASE_DAILY_P", + "manager", + "msg.sender" + ], + "state_variables_written": [ + "maxSupplyIncreaseDailyP" + ], + "immutables_and_constants": [ + { + "name": "MAX_SUPPLY_INCREASE_DAILY_P", + "slot": "50 * PRECISION_18" + } + ], + "manager": "0x1632C38cB208df8409753729dBfbA5c58626F637" + }, + { + "Function": "updateLossesBurnP", + "Modifiers": [ + "onlyManager" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "manager", + "MAX_LOSSES_BURN_P", + "msg.sender" + ], + "state_variables_written": [ + "lossesBurnP" + ], + "immutables_and_constants": [ + { + "name": "MAX_LOSSES_BURN_P", + "slot": "25 * PRECISION_18" + } + ], + "manager": "0x1632C38cB208df8409753729dBfbA5c58626F637" + }, + { + "Function": "updateMaxGnsSupplyMintDailyP", + "Modifiers": [ + "onlyManager" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "MAX_GNS_SUPPLY_MINT_DAILY_P", + "manager", + "msg.sender" + ], + "state_variables_written": [ + "maxGnsSupplyMintDailyP" + ], + "immutables_and_constants": [ + { + "name": "MAX_GNS_SUPPLY_MINT_DAILY_P", + "slot": "PRECISION_18 / 20" + } + ], + "manager": "0x1632C38cB208df8409753729dBfbA5c58626F637" + }, + { + "Function": "updateMaxDiscountP", + "Modifiers": [ + "onlyManager" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "manager", + "MAX_DISCOUNT_P", + "msg.sender" + ], + "state_variables_written": [ + "maxDiscountP" + ], + "immutables_and_constants": [ + { + "name": "MAX_DISCOUNT_P", + "slot": "10 * PRECISION_18" + } + ], + "manager": "0x1632C38cB208df8409753729dBfbA5c58626F637" + }, + { + "Function": "updateMaxDiscountThresholdP", + "Modifiers": [ + "onlyManager" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "PRECISION_18", + "manager", + "msg.sender" + ], + "state_variables_written": [ + "maxDiscountThresholdP" + ], + "immutables_and_constants": [ + { + "name": "PRECISION_18", + "slot": "1e18", + "value": "0x0000000000000000000000000000000000000000" + } + ], + "manager": "0x1632C38cB208df8409753729dBfbA5c58626F637" + }, + { + "Function": "deposit", + "Modifiers": [ + "checks" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "totalDeposited", + "PRECISION_18", + "totalLiability", + "shareToAssetsPrice", + "_totalSupply", + "currentMaxSupply", + "accPnlPerToken", + "accPnlPerTokenUsed", + "assetsOrShares", + "_balances", + "_asset" + ], + "state_variables_written": [ + "totalDeposited", + "_totalSupply", + "_balances", + "accPnlPerToken", + "totalLiability" + ], + "immutables_and_constants": [ + { + "name": "PRECISION_18", + "slot": "1e18", + "value": "0x0000000000000000000000000000000000000000" + } + ], + "_balances": 0, + "_totalSupply": 4778056705811, + "_asset": "af88d065e77c8cc2239327c5edb3a432268e5831", + "shareToAssetsPrice": 1283060153927987052, + "accPnlPerTokenUsed": 31414041566567400, + "accPnlPerToken": 32549236854273370, + "currentMaxSupply": 5016959541101, + "totalDeposited": 6089418839799, + "totalLiability": 315362608430 + }, + { + "Function": "mint", + "Modifiers": [ + "checks" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "totalDeposited", + "PRECISION_18", + "totalLiability", + "shareToAssetsPrice", + "_totalSupply", + "currentMaxSupply", + "accPnlPerToken", + "accPnlPerTokenUsed", + "assetsOrShares", + "_balances", + "_asset" + ], + "state_variables_written": [ + "totalDeposited", + "_totalSupply", + "_balances", + "accPnlPerToken", + "totalLiability" + ], + "immutables_and_constants": [ + { + "name": "PRECISION_18", + "slot": "1e18", + "value": "0x0000000000000000000000000000000000000000" + } + ], + "_balances": 0, + "_totalSupply": 4778056705811, + "_asset": "af88d065e77c8cc2239327c5edb3a432268e5831", + "shareToAssetsPrice": 1283060153927987052, + "accPnlPerTokenUsed": 31414041566567400, + "accPnlPerToken": 32549236854273370, + "currentMaxSupply": 5016959541101, + "totalDeposited": 6089418839799, + "totalLiability": 315362608430 + }, + { + "Function": "withdraw", + "Modifiers": [ + "checks" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "TESTNET", + "ARBITRUM_MAINNET", + "_totalSupply", + "openTradesPnlFeed", + "accPnlPerToken", + "ARBITRUM_MAINNET_WETH", + "assetsOrShares", + "totalDeposited", + "POLYGON_MAINNET_WMATIC", + "BASE_MAINNET_WETH", + "BASE_MAINNET", + "ARBITRUM_SEPOLIA_WETH", + "APECHAIN_MAINNET_WAPE", + "POLYGON_MAINNET", + "MAX_NATIVE_TRANSFER_GAS_LIMIT", + "PRECISION_18", + "currentEpoch", + "_balances", + "_allowances", + "ARBITRUM_SEPOLIA", + "totalLiability", + "APECHAIN_MAINNET", + "shareToAssetsPrice", + "withdrawRequests", + "_asset" + ], + "state_variables_written": [ + "totalDeposited", + "_totalSupply", + "_balances", + "_allowances", + "withdrawRequests", + "accPnlPerToken", + "totalLiability" + ], + "immutables_and_constants": [ + { + "name": "PRECISION_18", + "slot": "1e18", + "value": "0x0000000000000000000000000000000000000000" + }, + { + "name": "MAX_NATIVE_TRANSFER_GAS_LIMIT", + "slot": "40_000" + } + ], + "_balances": 0, + "_allowances": 0, + "_totalSupply": 4778056705811, + "_asset": "af88d065e77c8cc2239327c5edb3a432268e5831", + "openTradesPnlFeed": "bf55c78132ab06a2b217040b7a7f20b5cbd47982", + "shareToAssetsPrice": 1283060153927987052, + "accPnlPerToken": 32549236854273370, + "currentEpoch": 307, + "withdrawRequests": 0, + "totalDeposited": 6089418839799, + "totalLiability": 315362608430 + }, + { + "Function": "redeem", + "Modifiers": [ + "checks" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "TESTNET", + "ARBITRUM_MAINNET", + "_totalSupply", + "openTradesPnlFeed", + "accPnlPerToken", + "ARBITRUM_MAINNET_WETH", + "assetsOrShares", + "totalDeposited", + "POLYGON_MAINNET_WMATIC", + "BASE_MAINNET_WETH", + "BASE_MAINNET", + "ARBITRUM_SEPOLIA_WETH", + "APECHAIN_MAINNET_WAPE", + "POLYGON_MAINNET", + "MAX_NATIVE_TRANSFER_GAS_LIMIT", + "PRECISION_18", + "currentEpoch", + "_balances", + "_allowances", + "ARBITRUM_SEPOLIA", + "totalLiability", + "APECHAIN_MAINNET", + "shareToAssetsPrice", + "withdrawRequests", + "_asset" + ], + "state_variables_written": [ + "totalDeposited", + "_totalSupply", + "_balances", + "_allowances", + "withdrawRequests", + "accPnlPerToken", + "totalLiability" + ], + "immutables_and_constants": [ + { + "name": "PRECISION_18", + "slot": "1e18", + "value": "0x0000000000000000000000000000000000000000" + }, + { + "name": "MAX_NATIVE_TRANSFER_GAS_LIMIT", + "slot": "40_000" + } + ], + "_balances": 0, + "_allowances": 0, + "_totalSupply": 4778056705811, + "_asset": "af88d065e77c8cc2239327c5edb3a432268e5831", + "openTradesPnlFeed": "bf55c78132ab06a2b217040b7a7f20b5cbd47982", + "shareToAssetsPrice": 1283060153927987052, + "accPnlPerToken": 32549236854273370, + "currentEpoch": 307, + "withdrawRequests": 0, + "totalDeposited": 6089418839799, + "totalLiability": 315362608430 + }, + { + "Function": "depositWithDiscountAndLock", + "Modifiers": [ + "checks", + "validDiscount" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "MIN_LOCK_DURATION", + "_totalSupply", + "totalDiscounts", + "accPnlPerToken", + "MAX_LOCK_DURATION", + "assetsOrShares", + "totalDeposited", + "currentMaxSupply", + "maxDiscountP", + "maxDiscountThresholdP", + "accRewardsPerToken", + "PRECISION_18", + "lockedDepositsCount", + "_balances", + "lockDuration", + "lockedDeposits", + "totalLockedDiscounts", + "totalLiability", + "shareToAssetsPrice", + "accPnlPerTokenUsed", + "_asset", + "lockedDepositNft" + ], + "state_variables_written": [ + "totalDeposited", + "_totalSupply", + "_balances", + "totalLockedDiscounts", + "totalDiscounts", + "lockedDepositsCount", + "accPnlPerToken", + "totalLiability" + ], + "immutables_and_constants": [ + { + "name": "PRECISION_18", + "slot": "1e18", + "value": "0x0000000000000000000000000000000000000000" + }, + { + "name": "MAX_LOCK_DURATION", + "slot": "31536000", + "value": "0x0000000000000000000000000000000000000000" + } + ], + "_balances": 0, + "_totalSupply": 4778056705811, + "_asset": "af88d065e77c8cc2239327c5edb3a432268e5831", + "lockedDepositNft": "d846b17a07e26f9832f8de940101c5f764df3804", + "MIN_LOCK_DURATION": 1209600, + "maxDiscountP": 5000000000000000000, + "maxDiscountThresholdP": 100000000000000000000, + "shareToAssetsPrice": 1283060153927987052, + "accPnlPerTokenUsed": 31414041566567400, + "accPnlPerToken": 32549236854273370, + "accRewardsPerToken": 314474195494554452, + "currentMaxSupply": 5016959541101, + "lockedDepositsCount": 596, + "lockedDeposits": 0, + "totalDeposited": 6089418839799, + "totalLiability": 315362608430, + "totalLockedDiscounts": 39974383745, + "totalDiscounts": 182787032523 + }, + { + "Function": "mintWithDiscountAndLock", + "Modifiers": [ + "checks", + "validDiscount" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "MIN_LOCK_DURATION", + "_totalSupply", + "totalDiscounts", + "accPnlPerToken", + "MAX_LOCK_DURATION", + "assetsOrShares", + "totalDeposited", + "currentMaxSupply", + "maxDiscountP", + "maxDiscountThresholdP", + "accRewardsPerToken", + "PRECISION_18", + "lockedDepositsCount", + "_balances", + "lockDuration", + "lockedDeposits", + "totalLockedDiscounts", + "totalLiability", + "shareToAssetsPrice", + "accPnlPerTokenUsed", + "_asset", + "lockedDepositNft" + ], + "state_variables_written": [ + "totalDeposited", + "_totalSupply", + "_balances", + "totalLockedDiscounts", + "totalDiscounts", + "lockedDepositsCount", + "accPnlPerToken", + "totalLiability" + ], + "immutables_and_constants": [ + { + "name": "PRECISION_18", + "slot": "1e18", + "value": "0x0000000000000000000000000000000000000000" + }, + { + "name": "MAX_LOCK_DURATION", + "slot": "31536000", + "value": "0x0000000000000000000000000000000000000000" + } + ], + "_balances": 0, + "_totalSupply": 4778056705811, + "_asset": "af88d065e77c8cc2239327c5edb3a432268e5831", + "lockedDepositNft": "d846b17a07e26f9832f8de940101c5f764df3804", + "MIN_LOCK_DURATION": 1209600, + "maxDiscountP": 5000000000000000000, + "maxDiscountThresholdP": 100000000000000000000, + "shareToAssetsPrice": 1283060153927987052, + "accPnlPerTokenUsed": 31414041566567400, + "accPnlPerToken": 32549236854273370, + "accRewardsPerToken": 314474195494554452, + "currentMaxSupply": 5016959541101, + "lockedDepositsCount": 596, + "lockedDeposits": 0, + "totalDeposited": 6089418839799, + "totalLiability": 315362608430, + "totalLockedDiscounts": 39974383745, + "totalDiscounts": 182787032523 + } + ], + "storage_values": { + "_initialized": 3, + "_initializing": false, + "_balances": 0, + "_allowances": 0, + "_totalSupply": 4778056705811, + "_asset": "af88d065e77c8cc2239327c5edb3a432268e5831", + "_owner": "0x5f5E4892BAB94d94DC57a3edeA3c138167c4DF0F", + "lockedDepositNft": "d846b17a07e26f9832f8de940101c5f764df3804", + "manager": "0x1632C38cB208df8409753729dBfbA5c58626F637", + "admin": "0xe8997C502fCD0729B462FCA19A50cF0DAEA0cAB5", + "openTradesPnlFeed": "bf55c78132ab06a2b217040b7a7f20b5cbd47982", + "MIN_LOCK_DURATION": 1209600, + "maxDiscountP": 5000000000000000000, + "maxDiscountThresholdP": 100000000000000000000, + "shareToAssetsPrice": 1283060153927987052, + "accPnlPerTokenUsed": 31414041566567400, + "accPnlPerToken": 32549236854273370, + "accRewardsPerToken": 314474195494554452, + "currentEpoch": 307, + "currentMaxSupply": 5016959541101, + "withdrawRequests": 0, + "lockedDepositsCount": 596, + "lockedDeposits": 0, + "totalDeposited": 6089418839799, + "totalLiability": 315362608430, + "totalLockedDiscounts": 39974383745, + "totalDiscounts": 182787032523 + } + } + } +} \ No newline at end of file diff --git a/harnesses/permissions-scan/targets/gmx-v2/contracts.json b/harnesses/permissions-scan/targets/gmx-v2/contracts.json new file mode 100644 index 00000000..4dd625af --- /dev/null +++ b/harnesses/permissions-scan/targets/gmx-v2/contracts.json @@ -0,0 +1,129 @@ +{ + "chain": "arbi", + "project": "gmx-v2", + "addresses": [ + "0x602b805EedddBbD9ddff44A7dcBD46cb07849685", + "0xFD70de6b91282D8017aA4E741e9Ae325CAb992d8", + "0x3c3d99FD298f679DBC2CEcd132b4eC4d0F5e6e72", + "0xC8ee91A54287DB53897056e12D9819156D3822Fb", + "0x31eF83a530Fde1B38EE9A18093A333D8Bbbc40D5", + "0xF89e77e8Dc11691C9e8757e84aaFbCD8A67d7A55", + "0x0628D46b5D145f183AdB6Ef1f2c97eD1C4701C55", + "0xf5F30B10141E1F63FC11eD772931A8294a591996", + "0xA8AF9B86fC47deAde1bc66B12673706615E2B011", + "0xFBEff82f2DD5E51B8AF34b57cf788b4b09d466F9", + "0x7A967D114B8676874FA2cFC1C14F3095C88418Eb", + "0x03e8f708e9C85EDCEaa6AD7Cd06824CeB82A7E68", + "0x2A29D3a792000750807cc401806d6fd539928481" + ], + "sources": [ + { + "address": "0x602b805EedddBbD9ddff44A7dcBD46cb07849685", + "label": "ExchangeRouter", + "found_at": "arbiscan.io (label: GMX: ExchangeRouter); confirmed on-chain: dataStore() returns DataStore address", + "consulted_at": "2026-08-02T19:08:53Z", + "is_proxy": false, + "implementation": null, + "note": "Not present in github.com/gmx-io/gmx-synthetics/deployments/arbitrum/ExchangeRouter.json (file exists but parsing issue). Confirmed via on-chain dataStore() call." + }, + { + "address": "0xFD70de6b91282D8017aA4E741e9Ae325CAb992d8", + "label": "DataStore", + "found_at": "https://github.com/gmx-io/gmx-synthetics/blob/main/deployments/arbitrum/DataStore.json", + "consulted_at": "2026-08-02T19:08:53Z", + "is_proxy": false, + "implementation": null + }, + { + "address": "0x3c3d99FD298f679DBC2CEcd132b4eC4d0F5e6e72", + "label": "RoleStore", + "found_at": "https://github.com/gmx-io/gmx-synthetics/blob/main/deployments/arbitrum/RoleStore.json", + "consulted_at": "2026-08-02T19:08:53Z", + "is_proxy": false, + "implementation": null + }, + { + "address": "0xC8ee91A54287DB53897056e12D9819156D3822Fb", + "label": "EventEmitter", + "found_at": "https://github.com/gmx-io/gmx-synthetics/blob/main/deployments/arbitrum/EventEmitter.json", + "consulted_at": "2026-08-02T19:08:53Z", + "is_proxy": false, + "implementation": null + }, + { + "address": "0x31eF83a530Fde1B38EE9A18093A333D8Bbbc40D5", + "label": "OrderVault", + "found_at": "https://github.com/gmx-io/gmx-synthetics/blob/main/deployments/arbitrum/OrderVault.json", + "consulted_at": "2026-08-02T19:08:53Z", + "is_proxy": false, + "implementation": null + }, + { + "address": "0xF89e77e8Dc11691C9e8757e84aaFbCD8A67d7A55", + "label": "DepositVault", + "found_at": "https://github.com/gmx-io/gmx-synthetics/blob/main/deployments/arbitrum/DepositVault.json", + "consulted_at": "2026-08-02T19:08:53Z", + "is_proxy": false, + "implementation": null + }, + { + "address": "0x0628D46b5D145f183AdB6Ef1f2c97eD1C4701C55", + "label": "WithdrawalVault", + "found_at": "https://github.com/gmx-io/gmx-synthetics/blob/main/deployments/arbitrum/WithdrawalVault.json", + "consulted_at": "2026-08-02T19:08:53Z", + "is_proxy": false, + "implementation": null + }, + { + "address": "0xf5F30B10141E1F63FC11eD772931A8294a591996", + "label": "MarketFactory", + "found_at": "https://github.com/gmx-io/gmx-synthetics/blob/main/deployments/arbitrum/MarketFactory.json", + "consulted_at": "2026-08-02T19:08:53Z", + "is_proxy": false, + "implementation": null + }, + { + "address": "0xA8AF9B86fC47deAde1bc66B12673706615E2B011", + "label": "OracleStore", + "found_at": "https://github.com/gmx-io/gmx-synthetics/blob/main/deployments/arbitrum/OracleStore.json", + "consulted_at": "2026-08-02T19:08:53Z", + "is_proxy": false, + "implementation": null + }, + { + "address": "0xFBEff82f2DD5E51B8AF34b57cf788b4b09d466F9", + "label": "GovTimelockController", + "found_at": "https://github.com/gmx-io/gmx-synthetics/blob/main/deployments/arbitrum/GovTimelockController.json", + "consulted_at": "2026-08-02T19:08:53Z", + "is_proxy": false, + "implementation": null, + "note": "OZ TimelockController (non-enumerable AccessControl). getMinDelay()=86400s on-chain. PROPOSER=ProtocolGovernor confirmed. EXECUTOR=ProtocolGovernor confirmed." + }, + { + "address": "0x7A967D114B8676874FA2cFC1C14F3095C88418Eb", + "label": "Timelock (custom GMX)", + "found_at": "https://github.com/gmx-io/gmx-synthetics/blob/main/deployments/arbitrum/Timelock.json", + "consulted_at": "2026-08-02T19:08:53Z", + "is_proxy": false, + "implementation": null, + "note": "Custom GMX timelock. Storage slot 1 = 86400 (1-day delay). getMinDelay/admin functions revert: non-standard ABI." + }, + { + "address": "0x03e8f708e9C85EDCEaa6AD7Cd06824CeB82A7E68", + "label": "ProtocolGovernor", + "found_at": "https://github.com/gmx-io/gmx-synthetics/blob/main/deployments/arbitrum/ProtocolGovernor.json", + "consulted_at": "2026-08-02T19:08:53Z", + "is_proxy": false, + "implementation": null, + "note": "On-chain governor. proposalThreshold()=30000e18 GMX tokens. votingDelay()=86400 blocks. Holds PROPOSER+EXECUTOR roles in GovTimelockController." + }, + { + "address": "0x2A29D3a792000750807cc401806d6fd539928481", + "label": "GovToken", + "found_at": "https://github.com/gmx-io/gmx-synthetics/blob/main/deployments/arbitrum/GovToken.json", + "consulted_at": "2026-08-02T19:08:53Z", + "is_proxy": false, + "implementation": null + } + ] +} diff --git a/harnesses/permissions-scan/targets/gmx-v2/permissions.json b/harnesses/permissions-scan/targets/gmx-v2/permissions.json new file mode 100644 index 00000000..8e548007 --- /dev/null +++ b/harnesses/permissions-scan/targets/gmx-v2/permissions.json @@ -0,0 +1,2746 @@ +{ + "DataStore": { + "Address": "0xFD70de6b91282D8017aA4E741e9Ae325CAb992d8", + "permissions": { + "Contract_Name": "DataStore", + "Functions": [ + { + "Function": "_validateRole", + "Modifiers": [], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "roleStore" + ], + "state_variables_written": [], + "immutables_and_constants": [ + { + "name": "roleStore" + } + ] + }, + { + "Function": "setUint", + "Modifiers": [ + "onlyController" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "msg.sender", + "roleName", + "Role", + "role", + "roleStore" + ], + "state_variables_written": [ + "uintValues" + ], + "immutables_and_constants": [ + { + "name": "roleStore" + } + ] + }, + { + "Function": "removeUint", + "Modifiers": [ + "onlyController" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "uintValues", + "msg.sender", + "roleName", + "Role", + "role", + "roleStore" + ], + "state_variables_written": [ + "uintValues" + ], + "immutables_and_constants": [ + { + "name": "roleStore" + } + ], + "uintValues": 0 + }, + { + "Function": "applyDeltaToUint", + "Modifiers": [ + "onlyController" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "uintValues", + "msg.sender", + "roleName", + "Role", + "role", + "roleStore" + ], + "state_variables_written": [ + "uintValues" + ], + "immutables_and_constants": [ + { + "name": "roleStore" + } + ], + "uintValues": 0 + }, + { + "Function": "applyDeltaToUint", + "Modifiers": [ + "onlyController" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "uintValues", + "msg.sender", + "roleName", + "Role", + "role", + "roleStore" + ], + "state_variables_written": [ + "uintValues" + ], + "immutables_and_constants": [ + { + "name": "roleStore" + } + ], + "uintValues": 0 + }, + { + "Function": "applyBoundedDeltaToUint", + "Modifiers": [ + "onlyController" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "uintValues", + "msg.sender", + "roleName", + "Role", + "role", + "roleStore" + ], + "state_variables_written": [ + "uintValues" + ], + "immutables_and_constants": [ + { + "name": "roleStore" + } + ], + "uintValues": 0 + }, + { + "Function": "incrementUint", + "Modifiers": [ + "onlyController" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "uintValues", + "msg.sender", + "roleName", + "Role", + "role", + "roleStore" + ], + "state_variables_written": [ + "uintValues" + ], + "immutables_and_constants": [ + { + "name": "roleStore" + } + ], + "uintValues": 0 + }, + { + "Function": "decrementUint", + "Modifiers": [ + "onlyController" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "uintValues", + "msg.sender", + "roleName", + "Role", + "role", + "roleStore" + ], + "state_variables_written": [ + "uintValues" + ], + "immutables_and_constants": [ + { + "name": "roleStore" + } + ], + "uintValues": 0 + }, + { + "Function": "setInt", + "Modifiers": [ + "onlyController" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "msg.sender", + "roleName", + "Role", + "role", + "roleStore" + ], + "state_variables_written": [ + "intValues" + ], + "immutables_and_constants": [ + { + "name": "roleStore" + } + ] + }, + { + "Function": "removeInt", + "Modifiers": [ + "onlyController" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "intValues", + "msg.sender", + "roleName", + "Role", + "role", + "roleStore" + ], + "state_variables_written": [ + "intValues" + ], + "immutables_and_constants": [ + { + "name": "roleStore" + } + ], + "intValues": 0 + }, + { + "Function": "applyDeltaToInt", + "Modifiers": [ + "onlyController" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "intValues", + "msg.sender", + "roleName", + "Role", + "role", + "roleStore" + ], + "state_variables_written": [ + "intValues" + ], + "immutables_and_constants": [ + { + "name": "roleStore" + } + ], + "intValues": 0 + }, + { + "Function": "incrementInt", + "Modifiers": [ + "onlyController" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "intValues", + "msg.sender", + "roleName", + "Role", + "role", + "roleStore" + ], + "state_variables_written": [ + "intValues" + ], + "immutables_and_constants": [ + { + "name": "roleStore" + } + ], + "intValues": 0 + }, + { + "Function": "decrementInt", + "Modifiers": [ + "onlyController" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "intValues", + "msg.sender", + "roleName", + "Role", + "role", + "roleStore" + ], + "state_variables_written": [ + "intValues" + ], + "immutables_and_constants": [ + { + "name": "roleStore" + } + ], + "intValues": 0 + }, + { + "Function": "setAddress", + "Modifiers": [ + "onlyController" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "msg.sender", + "roleName", + "Role", + "role", + "roleStore" + ], + "state_variables_written": [ + "addressValues" + ], + "immutables_and_constants": [ + { + "name": "roleStore" + } + ] + }, + { + "Function": "removeAddress", + "Modifiers": [ + "onlyController" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "addressValues", + "msg.sender", + "roleName", + "Role", + "role", + "roleStore" + ], + "state_variables_written": [ + "addressValues" + ], + "immutables_and_constants": [ + { + "name": "roleStore" + } + ], + "addressValues": 0 + }, + { + "Function": "setBool", + "Modifiers": [ + "onlyController" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "msg.sender", + "roleName", + "Role", + "role", + "roleStore" + ], + "state_variables_written": [ + "boolValues" + ], + "immutables_and_constants": [ + { + "name": "roleStore" + } + ] + }, + { + "Function": "removeBool", + "Modifiers": [ + "onlyController" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "msg.sender", + "roleName", + "Role", + "role", + "roleStore", + "boolValues" + ], + "state_variables_written": [ + "boolValues" + ], + "immutables_and_constants": [ + { + "name": "roleStore" + } + ], + "boolValues": false + }, + { + "Function": "setString", + "Modifiers": [ + "onlyController" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "msg.sender", + "roleName", + "Role", + "role", + "roleStore" + ], + "state_variables_written": [ + "stringValues" + ], + "immutables_and_constants": [ + { + "name": "roleStore" + } + ] + }, + { + "Function": "removeString", + "Modifiers": [ + "onlyController" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "msg.sender", + "roleName", + "stringValues", + "Role", + "role", + "roleStore" + ], + "state_variables_written": [ + "stringValues" + ], + "immutables_and_constants": [ + { + "name": "roleStore" + } + ], + "stringValues": "" + }, + { + "Function": "setBytes32", + "Modifiers": [ + "onlyController" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "msg.sender", + "roleName", + "Role", + "role", + "roleStore" + ], + "state_variables_written": [ + "bytes32Values" + ], + "immutables_and_constants": [ + { + "name": "roleStore" + } + ] + }, + { + "Function": "removeBytes32", + "Modifiers": [ + "onlyController" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "bytes32Values", + "msg.sender", + "roleName", + "Role", + "role", + "roleStore" + ], + "state_variables_written": [ + "bytes32Values" + ], + "immutables_and_constants": [ + { + "name": "roleStore" + } + ], + "bytes32Values": "0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "Function": "setUintArray", + "Modifiers": [ + "onlyController" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "msg.sender", + "roleName", + "Role", + "role", + "roleStore" + ], + "state_variables_written": [ + "uintArrayValues" + ], + "immutables_and_constants": [ + { + "name": "roleStore" + } + ] + }, + { + "Function": "removeUintArray", + "Modifiers": [ + "onlyController" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "uintArrayValues", + "msg.sender", + "roleName", + "Role", + "role", + "roleStore" + ], + "state_variables_written": [ + "uintArrayValues" + ], + "immutables_and_constants": [ + { + "name": "roleStore" + } + ], + "uintArrayValues": 0 + }, + { + "Function": "setIntArray", + "Modifiers": [ + "onlyController" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "msg.sender", + "roleName", + "Role", + "role", + "roleStore" + ], + "state_variables_written": [ + "intArrayValues" + ], + "immutables_and_constants": [ + { + "name": "roleStore" + } + ] + }, + { + "Function": "removeIntArray", + "Modifiers": [ + "onlyController" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "intArrayValues", + "msg.sender", + "roleName", + "Role", + "role", + "roleStore" + ], + "state_variables_written": [ + "intArrayValues" + ], + "immutables_and_constants": [ + { + "name": "roleStore" + } + ], + "intArrayValues": 0 + }, + { + "Function": "setAddressArray", + "Modifiers": [ + "onlyController" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "msg.sender", + "roleName", + "Role", + "role", + "roleStore" + ], + "state_variables_written": [ + "addressArrayValues" + ], + "immutables_and_constants": [ + { + "name": "roleStore" + } + ] + }, + { + "Function": "removeAddressArray", + "Modifiers": [ + "onlyController" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "addressArrayValues", + "msg.sender", + "roleName", + "Role", + "role", + "roleStore" + ], + "state_variables_written": [ + "addressArrayValues" + ], + "immutables_and_constants": [ + { + "name": "roleStore" + } + ], + "addressArrayValues": 0 + }, + { + "Function": "setBoolArray", + "Modifiers": [ + "onlyController" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "msg.sender", + "roleName", + "Role", + "role", + "roleStore" + ], + "state_variables_written": [ + "boolArrayValues" + ], + "immutables_and_constants": [ + { + "name": "roleStore" + } + ] + }, + { + "Function": "removeBoolArray", + "Modifiers": [ + "onlyController" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "boolArrayValues", + "msg.sender", + "roleName", + "Role", + "role", + "roleStore" + ], + "state_variables_written": [ + "boolArrayValues" + ], + "immutables_and_constants": [ + { + "name": "roleStore" + } + ], + "boolArrayValues": false + }, + { + "Function": "setStringArray", + "Modifiers": [ + "onlyController" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "msg.sender", + "roleName", + "Role", + "role", + "roleStore" + ], + "state_variables_written": [ + "stringArrayValues" + ], + "immutables_and_constants": [ + { + "name": "roleStore" + } + ] + }, + { + "Function": "removeStringArray", + "Modifiers": [ + "onlyController" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "msg.sender", + "roleName", + "Role", + "role", + "stringArrayValues", + "roleStore" + ], + "state_variables_written": [ + "stringArrayValues" + ], + "immutables_and_constants": [ + { + "name": "roleStore" + } + ], + "stringArrayValues": "" + }, + { + "Function": "setBytes32Array", + "Modifiers": [ + "onlyController" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "msg.sender", + "roleName", + "Role", + "role", + "roleStore" + ], + "state_variables_written": [ + "bytes32ArrayValues" + ], + "immutables_and_constants": [ + { + "name": "roleStore" + } + ] + }, + { + "Function": "removeBytes32Array", + "Modifiers": [ + "onlyController" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "msg.sender", + "roleName", + "Role", + "role", + "bytes32ArrayValues", + "roleStore" + ], + "state_variables_written": [ + "bytes32ArrayValues" + ], + "immutables_and_constants": [ + { + "name": "roleStore" + } + ], + "bytes32ArrayValues": "0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "Function": "addBytes32", + "Modifiers": [ + "onlyController" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "bytes32Sets", + "msg.sender", + "roleName", + "Role", + "role", + "roleStore" + ], + "state_variables_written": [], + "immutables_and_constants": [ + { + "name": "roleStore" + } + ], + "bytes32Sets": "0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "Function": "removeBytes32", + "Modifiers": [ + "onlyController" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "bytes32Sets", + "msg.sender", + "roleName", + "Role", + "role", + "roleStore" + ], + "state_variables_written": [], + "immutables_and_constants": [ + { + "name": "roleStore" + } + ], + "bytes32Sets": "0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "Function": "addAddress", + "Modifiers": [ + "onlyController" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "msg.sender", + "roleName", + "Role", + "role", + "addressSets", + "roleStore" + ], + "state_variables_written": [], + "immutables_and_constants": [ + { + "name": "roleStore" + } + ], + "addressSets": "0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "Function": "removeAddress", + "Modifiers": [ + "onlyController" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "msg.sender", + "roleName", + "Role", + "role", + "addressSets", + "roleStore" + ], + "state_variables_written": [], + "immutables_and_constants": [ + { + "name": "roleStore" + } + ], + "addressSets": "0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "Function": "addUint", + "Modifiers": [ + "onlyController" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "msg.sender", + "roleName", + "Role", + "role", + "uintSets", + "roleStore" + ], + "state_variables_written": [], + "immutables_and_constants": [ + { + "name": "roleStore" + } + ], + "uintSets": 0 + }, + { + "Function": "removeUint", + "Modifiers": [ + "onlyController" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "msg.sender", + "roleName", + "Role", + "role", + "uintSets", + "roleStore" + ], + "state_variables_written": [], + "immutables_and_constants": [ + { + "name": "roleStore" + } + ], + "uintSets": 0 + } + ], + "storage_values": { + "uintValues": 0, + "intValues": 0, + "addressValues": 0, + "boolValues": false, + "stringValues": "", + "bytes32Values": "0000000000000000000000000000000000000000000000000000000000000000", + "uintArrayValues": 0, + "intArrayValues": 0, + "addressArrayValues": 0, + "boolArrayValues": false, + "stringArrayValues": "", + "bytes32ArrayValues": "0000000000000000000000000000000000000000000000000000000000000000", + "bytes32Sets": "0000000000000000000000000000000000000000000000000000000000000000", + "addressSets": "0000000000000000000000000000000000000000000000000000000000000000", + "uintSets": 0 + } + } + }, + "RoleStore": { + "Address": "0x3c3d99FD298f679DBC2CEcd132b4eC4d0F5e6e72", + "permissions": { + "Contract_Name": "RoleStore", + "Functions": [ + { + "Function": "grantRole", + "Modifiers": [ + "onlyRoleAdmin" + ], + "msg.sender_conditions": [ + "! hasRole(msg.sender,Role.ROLE_ADMIN)", + "! hasRole(msg.sender,Role.ROLE_ADMIN)" + ], + "state_variables_read": [ + "account", + "roleKey", + "roleMembers", + "msg.sender", + "roleCache", + "roles", + "Role" + ], + "state_variables_written": [ + "roleCache" + ], + "roles": "0000000000000000000000000000000000000000000000000000000000000013", + "roleMembers": "0000000000000000000000000000000000000000000000000000000000000000", + "roleCache": false + }, + { + "Function": "revokeRole", + "Modifiers": [ + "onlyRoleAdmin" + ], + "msg.sender_conditions": [ + "! hasRole(msg.sender,Role.ROLE_ADMIN)", + "! hasRole(msg.sender,Role.ROLE_ADMIN)" + ], + "state_variables_read": [ + "account", + "roleKey", + "roleMembers", + "msg.sender", + "roleCache", + "Role" + ], + "state_variables_written": [ + "roleCache" + ], + "roleMembers": "0000000000000000000000000000000000000000000000000000000000000000", + "roleCache": false + } + ], + "storage_values": { + "roles": "0000000000000000000000000000000000000000000000000000000000000013", + "roleMembers": "0000000000000000000000000000000000000000000000000000000000000000", + "roleCache": false + } + } + }, + "OrderVault": { + "Address": "0x31eF83a530Fde1B38EE9A18093A333D8Bbbc40D5", + "permissions": { + "Contract_Name": "OrderVault", + "Functions": [ + { + "Function": "recordTransferIn", + "Modifiers": [ + "onlyController" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "tokenBalances", + "msg.sender", + "roleName", + "Role", + "role", + "roleStore" + ], + "state_variables_written": [ + "tokenBalances" + ], + "immutables_and_constants": [ + { + "name": "roleStore" + } + ], + "tokenBalances": 0 + }, + { + "Function": "syncTokenBalance", + "Modifiers": [ + "onlyController" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "msg.sender", + "roleName", + "Role", + "role", + "roleStore" + ], + "state_variables_written": [ + "tokenBalances" + ], + "immutables_and_constants": [ + { + "name": "roleStore" + } + ] + }, + { + "Function": "receive", + "Modifiers": [], + "msg.sender_conditions": [ + "msg.sender != wnt" + ], + "state_variables_read": [ + "dataStore" + ], + "state_variables_written": [], + "immutables_and_constants": [ + { + "name": "dataStore" + } + ] + }, + { + "Function": "transferOut", + "Modifiers": [ + "onlyController" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "TOKEN_TRANSFER_GAS_LIMIT", + "msg.sender", + "roleName", + "Role", + "role", + "roleStore", + "dataStore" + ], + "state_variables_written": [ + "tokenBalances" + ], + "immutables_and_constants": [ + { + "name": "roleStore" + }, + { + "name": "dataStore" + } + ] + }, + { + "Function": "transferOut", + "Modifiers": [ + "onlyController" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "TOKEN_TRANSFER_GAS_LIMIT", + "msg.sender", + "roleName", + "Role", + "role", + "roleStore", + "dataStore" + ], + "state_variables_written": [ + "tokenBalances" + ], + "immutables_and_constants": [ + { + "name": "roleStore" + }, + { + "name": "dataStore" + } + ] + }, + { + "Function": "transferOutNativeToken", + "Modifiers": [ + "onlyController" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "TOKEN_TRANSFER_GAS_LIMIT", + "msg.sender", + "roleName", + "Role", + "role", + "roleStore", + "dataStore" + ], + "state_variables_written": [ + "tokenBalances" + ], + "immutables_and_constants": [ + { + "name": "roleStore" + }, + { + "name": "dataStore" + } + ] + }, + { + "Function": "_validateRole", + "Modifiers": [], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "roleStore" + ], + "state_variables_written": [], + "immutables_and_constants": [ + { + "name": "roleStore" + } + ] + } + ], + "storage_values": { + "tokenBalances": 0 + } + } + }, + "GovTimelockController": { + "Address": "0xFBEff82f2DD5E51B8AF34b57cf788b4b09d466F9", + "permissions": { + "Contract_Name": "GovTimelockController", + "Functions": [ + { + "Function": "schedule", + "Modifiers": [ + "onlyRole" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "PROPOSER_ROLE", + "_roles", + "account", + "i", + "addr", + "msg.sender", + "value", + "length", + "_ADDRESS_LENGTH", + "role", + "_timestamps", + "_minDelay", + "buffer", + "_SYMBOLS", + "Strings" + ], + "state_variables_written": [ + "_timestamps" + ], + "immutables_and_constants": [ + { + "name": "PROPOSER_ROLE", + "slot": "keccak256(bytes)(PROPOSER_ROLE)" + } + ], + "_roles": "0000000000000000000000000000000000000000000000000000000000000000", + "_timestamps": 0, + "_minDelay": 86400 + }, + { + "Function": "scheduleBatch", + "Modifiers": [ + "onlyRole" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "PROPOSER_ROLE", + "_roles", + "account", + "i", + "addr", + "msg.sender", + "value", + "length", + "_ADDRESS_LENGTH", + "role", + "_timestamps", + "_minDelay", + "buffer", + "_SYMBOLS", + "Strings" + ], + "state_variables_written": [ + "_timestamps" + ], + "immutables_and_constants": [ + { + "name": "PROPOSER_ROLE", + "slot": "keccak256(bytes)(PROPOSER_ROLE)" + } + ], + "_roles": "0000000000000000000000000000000000000000000000000000000000000000", + "_timestamps": 0, + "_minDelay": 86400 + }, + { + "Function": "cancel", + "Modifiers": [ + "onlyRole" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "_roles", + "account", + "i", + "addr", + "msg.sender", + "value", + "length", + "_ADDRESS_LENGTH", + "_DONE_TIMESTAMP", + "role", + "_timestamps", + "CANCELLER_ROLE", + "buffer", + "_SYMBOLS", + "Strings" + ], + "state_variables_written": [ + "_timestamps" + ], + "immutables_and_constants": [ + { + "name": "CANCELLER_ROLE", + "slot": "keccak256(bytes)(CANCELLER_ROLE)" + }, + { + "name": "_DONE_TIMESTAMP", + "slot": "uint256(1)" + } + ], + "_roles": "0000000000000000000000000000000000000000000000000000000000000000", + "_timestamps": 0 + }, + { + "Function": "execute", + "Modifiers": [ + "onlyRoleOrOpenRole" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "_roles", + "account", + "i", + "addr", + "msg.sender", + "value", + "length", + "_ADDRESS_LENGTH", + "_DONE_TIMESTAMP", + "role", + "_timestamps", + "buffer", + "_SYMBOLS", + "EXECUTOR_ROLE", + "Strings" + ], + "state_variables_written": [ + "_timestamps" + ], + "immutables_and_constants": [ + { + "name": "EXECUTOR_ROLE", + "slot": "keccak256(bytes)(EXECUTOR_ROLE)" + }, + { + "name": "_DONE_TIMESTAMP", + "slot": "uint256(1)" + } + ], + "_roles": "0000000000000000000000000000000000000000000000000000000000000000", + "_timestamps": 0 + }, + { + "Function": "executeBatch", + "Modifiers": [ + "onlyRoleOrOpenRole" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "_roles", + "account", + "i", + "addr", + "msg.sender", + "value", + "length", + "_ADDRESS_LENGTH", + "_DONE_TIMESTAMP", + "role", + "_timestamps", + "buffer", + "_SYMBOLS", + "EXECUTOR_ROLE", + "Strings" + ], + "state_variables_written": [ + "_timestamps" + ], + "immutables_and_constants": [ + { + "name": "EXECUTOR_ROLE", + "slot": "keccak256(bytes)(EXECUTOR_ROLE)" + }, + { + "name": "_DONE_TIMESTAMP", + "slot": "uint256(1)" + } + ], + "_roles": "0000000000000000000000000000000000000000000000000000000000000000", + "_timestamps": 0 + }, + { + "Function": "updateDelay", + "Modifiers": [], + "msg.sender_conditions": [ + "require(bool,string)(msg.sender == address(this),TimelockController: caller must be timelock)" + ], + "state_variables_read": [ + "_minDelay" + ], + "state_variables_written": [ + "_minDelay" + ], + "_minDelay": 86400 + }, + { + "Function": "grantRole", + "Modifiers": [ + "getRoleAdmin", + "onlyRole" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "_roles", + "account", + "i", + "addr", + "msg.sender", + "value", + "length", + "_ADDRESS_LENGTH", + "role", + "buffer", + "_SYMBOLS", + "Strings" + ], + "state_variables_written": [ + "_roles" + ], + "_roles": "0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "Function": "revokeRole", + "Modifiers": [ + "getRoleAdmin", + "onlyRole" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "_roles", + "account", + "i", + "addr", + "msg.sender", + "value", + "length", + "_ADDRESS_LENGTH", + "role", + "buffer", + "_SYMBOLS", + "Strings" + ], + "state_variables_written": [ + "_roles" + ], + "_roles": "0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "storage_values": { + "_roles": "0000000000000000000000000000000000000000000000000000000000000000", + "_timestamps": 0, + "_minDelay": 86400 + } + } + }, + "Timelock": { + "Address": "0x7A967D114B8676874FA2cFC1C14F3095C88418Eb", + "permissions": { + "Contract_Name": "Timelock", + "Functions": [ + { + "Function": "_validateRole", + "Modifiers": [], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "roleStore" + ], + "state_variables_written": [], + "immutables_and_constants": [ + { + "name": "roleStore" + } + ] + }, + { + "Function": "revokeRole", + "Modifiers": [ + "nonReentrant", + "onlyTimelockMultisig" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "_ENTERED", + "_status", + "msg.sender", + "eventEmitter", + "roleName", + "Role", + "role", + "_NOT_ENTERED", + "roleStore" + ], + "state_variables_written": [ + "_status" + ], + "immutables_and_constants": [ + { + "name": "_NOT_ENTERED", + "slot": "1", + "value": "0x0000000000000000000000000000000000015180" + }, + { + "name": "_ENTERED", + "slot": "2", + "value": "0x0000000000000000000000000000000000000000" + }, + { + "name": "roleStore" + }, + { + "name": "eventEmitter" + } + ], + "_status": 1 + }, + { + "Function": "increaseTimelockDelay", + "Modifiers": [ + "nonReentrant", + "onlyTimelockAdmin" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "_ENTERED", + "_status", + "timelockDelay", + "msg.sender", + "eventEmitter", + "roleName", + "Role", + "role", + "MAX_TIMELOCK_DELAY", + "_NOT_ENTERED", + "roleStore" + ], + "state_variables_written": [ + "timelockDelay", + "_status" + ], + "immutables_and_constants": [ + { + "name": "_NOT_ENTERED", + "slot": "1", + "value": "0x0000000000000000000000000000000000015180" + }, + { + "name": "_ENTERED", + "slot": "2", + "value": "0x0000000000000000000000000000000000000000" + }, + { + "name": "roleStore" + }, + { + "name": "MAX_TIMELOCK_DELAY", + "slot": "432000", + "value": "0x0000000000000000000000000000000000000000" + }, + { + "name": "eventEmitter" + } + ], + "_status": 1, + "timelockDelay": 86400 + }, + { + "Function": "setOracleProviderEnabled", + "Modifiers": [ + "nonReentrant", + "onlyTimelockMultisig" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "IS_ORACLE_PROVIDER_ENABLED", + "_ENTERED", + "_status", + "msg.sender", + "eventEmitter", + "roleName", + "Role", + "role", + "_NOT_ENTERED", + "roleStore", + "dataStore" + ], + "state_variables_written": [ + "_status" + ], + "immutables_and_constants": [ + { + "name": "_NOT_ENTERED", + "slot": "1", + "value": "0x0000000000000000000000000000000000015180" + }, + { + "name": "_ENTERED", + "slot": "2", + "value": "0x0000000000000000000000000000000000000000" + }, + { + "name": "roleStore" + }, + { + "name": "dataStore" + }, + { + "name": "eventEmitter" + } + ], + "_status": 1 + }, + { + "Function": "signalSetOracleProviderForToken", + "Modifiers": [ + "nonReentrant", + "onlyTimelockAdmin" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "_ENTERED", + "_status", + "timelockDelay", + "pendingActionsList", + "msg.sender", + "eventEmitter", + "roleName", + "Role", + "role", + "_NOT_ENTERED", + "roleStore", + "pendingActions" + ], + "state_variables_written": [ + "_status", + "pendingActions" + ], + "immutables_and_constants": [ + { + "name": "_NOT_ENTERED", + "slot": "1", + "value": "0x0000000000000000000000000000000000015180" + }, + { + "name": "_ENTERED", + "slot": "2", + "value": "0x0000000000000000000000000000000000000000" + }, + { + "name": "roleStore" + }, + { + "name": "eventEmitter" + } + ], + "_status": 1, + "timelockDelay": 86400, + "pendingActions": 0, + "pendingActionsList": "00000000000000000000000000000000000000000000000000000000000000f6" + }, + { + "Function": "setOracleProviderForTokenAfterSignal", + "Modifiers": [ + "nonReentrant", + "onlyTimelockAdmin" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "_ENTERED", + "_status", + "pendingActionsList", + "msg.sender", + "eventEmitter", + "roleName", + "Role", + "role", + "_NOT_ENTERED", + "ORACLE_PROVIDER_FOR_TOKEN", + "roleStore", + "dataStore", + "pendingActions" + ], + "state_variables_written": [ + "_status", + "pendingActions" + ], + "immutables_and_constants": [ + { + "name": "_NOT_ENTERED", + "slot": "1", + "value": "0x0000000000000000000000000000000000015180" + }, + { + "name": "_ENTERED", + "slot": "2", + "value": "0x0000000000000000000000000000000000000000" + }, + { + "name": "roleStore" + }, + { + "name": "dataStore" + }, + { + "name": "eventEmitter" + } + ], + "_status": 1, + "pendingActions": 0, + "pendingActionsList": "00000000000000000000000000000000000000000000000000000000000000f6" + }, + { + "Function": "signalSetOracleProviderEnabled", + "Modifiers": [ + "nonReentrant", + "onlyTimelockAdmin" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "_ENTERED", + "_status", + "timelockDelay", + "pendingActionsList", + "msg.sender", + "eventEmitter", + "roleName", + "Role", + "role", + "_NOT_ENTERED", + "roleStore", + "pendingActions" + ], + "state_variables_written": [ + "_status", + "pendingActions" + ], + "immutables_and_constants": [ + { + "name": "_NOT_ENTERED", + "slot": "1", + "value": "0x0000000000000000000000000000000000015180" + }, + { + "name": "_ENTERED", + "slot": "2", + "value": "0x0000000000000000000000000000000000000000" + }, + { + "name": "roleStore" + }, + { + "name": "eventEmitter" + } + ], + "_status": 1, + "timelockDelay": 86400, + "pendingActions": 0, + "pendingActionsList": "00000000000000000000000000000000000000000000000000000000000000f6" + }, + { + "Function": "setOracleProviderEnabledAfterSignal", + "Modifiers": [ + "nonReentrant", + "onlyTimelockAdmin" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "IS_ORACLE_PROVIDER_ENABLED", + "_ENTERED", + "_status", + "pendingActionsList", + "msg.sender", + "eventEmitter", + "roleName", + "Role", + "role", + "_NOT_ENTERED", + "roleStore", + "dataStore", + "pendingActions" + ], + "state_variables_written": [ + "_status", + "pendingActions" + ], + "immutables_and_constants": [ + { + "name": "_NOT_ENTERED", + "slot": "1", + "value": "0x0000000000000000000000000000000000015180" + }, + { + "name": "_ENTERED", + "slot": "2", + "value": "0x0000000000000000000000000000000000000000" + }, + { + "name": "roleStore" + }, + { + "name": "dataStore" + }, + { + "name": "eventEmitter" + } + ], + "_status": 1, + "pendingActions": 0, + "pendingActionsList": "00000000000000000000000000000000000000000000000000000000000000f6" + }, + { + "Function": "signalSetAtomicOracleProvider", + "Modifiers": [ + "nonReentrant", + "onlyTimelockAdmin" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "_ENTERED", + "_status", + "timelockDelay", + "pendingActionsList", + "msg.sender", + "eventEmitter", + "roleName", + "Role", + "role", + "_NOT_ENTERED", + "roleStore", + "pendingActions" + ], + "state_variables_written": [ + "_status", + "pendingActions" + ], + "immutables_and_constants": [ + { + "name": "_NOT_ENTERED", + "slot": "1", + "value": "0x0000000000000000000000000000000000015180" + }, + { + "name": "_ENTERED", + "slot": "2", + "value": "0x0000000000000000000000000000000000000000" + }, + { + "name": "roleStore" + }, + { + "name": "eventEmitter" + } + ], + "_status": 1, + "timelockDelay": 86400, + "pendingActions": 0, + "pendingActionsList": "00000000000000000000000000000000000000000000000000000000000000f6" + }, + { + "Function": "setAtomicOracleProviderAfterSignal", + "Modifiers": [ + "nonReentrant", + "onlyTimelockAdmin" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "_ENTERED", + "_status", + "pendingActionsList", + "msg.sender", + "eventEmitter", + "roleName", + "Role", + "role", + "IS_ATOMIC_ORACLE_PROVIDER", + "_NOT_ENTERED", + "roleStore", + "dataStore", + "pendingActions" + ], + "state_variables_written": [ + "_status", + "pendingActions" + ], + "immutables_and_constants": [ + { + "name": "_NOT_ENTERED", + "slot": "1", + "value": "0x0000000000000000000000000000000000015180" + }, + { + "name": "_ENTERED", + "slot": "2", + "value": "0x0000000000000000000000000000000000000000" + }, + { + "name": "roleStore" + }, + { + "name": "dataStore" + }, + { + "name": "eventEmitter" + } + ], + "_status": 1, + "pendingActions": 0, + "pendingActionsList": "00000000000000000000000000000000000000000000000000000000000000f6" + }, + { + "Function": "signalAddOracleSigner", + "Modifiers": [ + "nonReentrant", + "onlyTimelockAdmin" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "_ENTERED", + "_status", + "timelockDelay", + "pendingActionsList", + "msg.sender", + "eventEmitter", + "roleName", + "Role", + "role", + "_NOT_ENTERED", + "roleStore", + "pendingActions" + ], + "state_variables_written": [ + "_status", + "pendingActions" + ], + "immutables_and_constants": [ + { + "name": "_NOT_ENTERED", + "slot": "1", + "value": "0x0000000000000000000000000000000000015180" + }, + { + "name": "_ENTERED", + "slot": "2", + "value": "0x0000000000000000000000000000000000000000" + }, + { + "name": "roleStore" + }, + { + "name": "eventEmitter" + } + ], + "_status": 1, + "timelockDelay": 86400, + "pendingActions": 0, + "pendingActionsList": "00000000000000000000000000000000000000000000000000000000000000f6" + }, + { + "Function": "addOracleSignerAfterSignal", + "Modifiers": [ + "nonReentrant", + "onlyTimelockAdmin" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "_ENTERED", + "_status", + "oracleStore", + "pendingActionsList", + "msg.sender", + "eventEmitter", + "roleName", + "Role", + "role", + "_NOT_ENTERED", + "roleStore", + "pendingActions" + ], + "state_variables_written": [ + "_status", + "pendingActions" + ], + "immutables_and_constants": [ + { + "name": "_NOT_ENTERED", + "slot": "1", + "value": "0x0000000000000000000000000000000000015180" + }, + { + "name": "_ENTERED", + "slot": "2", + "value": "0x0000000000000000000000000000000000000000" + }, + { + "name": "roleStore" + }, + { + "name": "eventEmitter" + }, + { + "name": "oracleStore" + } + ], + "_status": 1, + "pendingActions": 0, + "pendingActionsList": "00000000000000000000000000000000000000000000000000000000000000f6" + }, + { + "Function": "signalRemoveOracleSigner", + "Modifiers": [ + "nonReentrant", + "onlyTimelockAdmin" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "_ENTERED", + "_status", + "timelockDelay", + "pendingActionsList", + "msg.sender", + "eventEmitter", + "roleName", + "Role", + "role", + "_NOT_ENTERED", + "roleStore", + "pendingActions" + ], + "state_variables_written": [ + "_status", + "pendingActions" + ], + "immutables_and_constants": [ + { + "name": "_NOT_ENTERED", + "slot": "1", + "value": "0x0000000000000000000000000000000000015180" + }, + { + "name": "_ENTERED", + "slot": "2", + "value": "0x0000000000000000000000000000000000000000" + }, + { + "name": "roleStore" + }, + { + "name": "eventEmitter" + } + ], + "_status": 1, + "timelockDelay": 86400, + "pendingActions": 0, + "pendingActionsList": "00000000000000000000000000000000000000000000000000000000000000f6" + }, + { + "Function": "removeOracleSignerAfterSignal", + "Modifiers": [ + "nonReentrant", + "onlyTimelockAdmin" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "_ENTERED", + "_status", + "oracleStore", + "pendingActionsList", + "msg.sender", + "eventEmitter", + "roleName", + "Role", + "role", + "_NOT_ENTERED", + "roleStore", + "pendingActions" + ], + "state_variables_written": [ + "_status", + "pendingActions" + ], + "immutables_and_constants": [ + { + "name": "_NOT_ENTERED", + "slot": "1", + "value": "0x0000000000000000000000000000000000015180" + }, + { + "name": "_ENTERED", + "slot": "2", + "value": "0x0000000000000000000000000000000000000000" + }, + { + "name": "roleStore" + }, + { + "name": "eventEmitter" + }, + { + "name": "oracleStore" + } + ], + "_status": 1, + "pendingActions": 0, + "pendingActionsList": "00000000000000000000000000000000000000000000000000000000000000f6" + }, + { + "Function": "signalSetFeeReceiver", + "Modifiers": [ + "nonReentrant", + "onlyTimelockAdmin" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "_ENTERED", + "_status", + "timelockDelay", + "pendingActionsList", + "msg.sender", + "eventEmitter", + "roleName", + "Role", + "role", + "_NOT_ENTERED", + "roleStore", + "pendingActions" + ], + "state_variables_written": [ + "_status", + "pendingActions" + ], + "immutables_and_constants": [ + { + "name": "_NOT_ENTERED", + "slot": "1", + "value": "0x0000000000000000000000000000000000015180" + }, + { + "name": "_ENTERED", + "slot": "2", + "value": "0x0000000000000000000000000000000000000000" + }, + { + "name": "roleStore" + }, + { + "name": "eventEmitter" + } + ], + "_status": 1, + "timelockDelay": 86400, + "pendingActions": 0, + "pendingActionsList": "00000000000000000000000000000000000000000000000000000000000000f6" + }, + { + "Function": "setFeeReceiverAfterSignal", + "Modifiers": [ + "nonReentrant", + "onlyTimelockAdmin" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "_ENTERED", + "_status", + "pendingActionsList", + "msg.sender", + "eventEmitter", + "roleName", + "Role", + "role", + "_NOT_ENTERED", + "roleStore", + "dataStore", + "pendingActions" + ], + "state_variables_written": [ + "_status", + "pendingActions" + ], + "immutables_and_constants": [ + { + "name": "_NOT_ENTERED", + "slot": "1", + "value": "0x0000000000000000000000000000000000015180" + }, + { + "name": "_ENTERED", + "slot": "2", + "value": "0x0000000000000000000000000000000000000000" + }, + { + "name": "roleStore" + }, + { + "name": "dataStore" + }, + { + "name": "eventEmitter" + } + ], + "_status": 1, + "pendingActions": 0, + "pendingActionsList": "00000000000000000000000000000000000000000000000000000000000000f6" + }, + { + "Function": "signalGrantRole", + "Modifiers": [ + "nonReentrant", + "onlyTimelockAdmin" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "_ENTERED", + "_status", + "timelockDelay", + "pendingActionsList", + "msg.sender", + "eventEmitter", + "roleName", + "Role", + "role", + "_NOT_ENTERED", + "roleStore", + "pendingActions" + ], + "state_variables_written": [ + "_status", + "pendingActions" + ], + "immutables_and_constants": [ + { + "name": "_NOT_ENTERED", + "slot": "1", + "value": "0x0000000000000000000000000000000000015180" + }, + { + "name": "_ENTERED", + "slot": "2", + "value": "0x0000000000000000000000000000000000000000" + }, + { + "name": "roleStore" + }, + { + "name": "eventEmitter" + } + ], + "_status": 1, + "timelockDelay": 86400, + "pendingActions": 0, + "pendingActionsList": "00000000000000000000000000000000000000000000000000000000000000f6" + }, + { + "Function": "grantRoleAfterSignal", + "Modifiers": [ + "nonReentrant", + "onlyTimelockAdmin" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "_ENTERED", + "_status", + "pendingActionsList", + "msg.sender", + "eventEmitter", + "roleName", + "Role", + "role", + "_NOT_ENTERED", + "roleStore", + "pendingActions" + ], + "state_variables_written": [ + "_status", + "pendingActions" + ], + "immutables_and_constants": [ + { + "name": "_NOT_ENTERED", + "slot": "1", + "value": "0x0000000000000000000000000000000000015180" + }, + { + "name": "_ENTERED", + "slot": "2", + "value": "0x0000000000000000000000000000000000000000" + }, + { + "name": "roleStore" + }, + { + "name": "eventEmitter" + } + ], + "_status": 1, + "pendingActions": 0, + "pendingActionsList": "00000000000000000000000000000000000000000000000000000000000000f6" + }, + { + "Function": "signalRevokeRole", + "Modifiers": [ + "nonReentrant", + "onlyTimelockAdmin" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "_ENTERED", + "_status", + "timelockDelay", + "pendingActionsList", + "msg.sender", + "eventEmitter", + "roleName", + "Role", + "role", + "_NOT_ENTERED", + "roleStore", + "pendingActions" + ], + "state_variables_written": [ + "_status", + "pendingActions" + ], + "immutables_and_constants": [ + { + "name": "_NOT_ENTERED", + "slot": "1", + "value": "0x0000000000000000000000000000000000015180" + }, + { + "name": "_ENTERED", + "slot": "2", + "value": "0x0000000000000000000000000000000000000000" + }, + { + "name": "roleStore" + }, + { + "name": "eventEmitter" + } + ], + "_status": 1, + "timelockDelay": 86400, + "pendingActions": 0, + "pendingActionsList": "00000000000000000000000000000000000000000000000000000000000000f6" + }, + { + "Function": "revokeRoleAfterSignal", + "Modifiers": [ + "nonReentrant", + "onlyTimelockAdmin" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "_ENTERED", + "_status", + "pendingActionsList", + "msg.sender", + "eventEmitter", + "roleName", + "Role", + "role", + "_NOT_ENTERED", + "roleStore", + "pendingActions" + ], + "state_variables_written": [ + "_status", + "pendingActions" + ], + "immutables_and_constants": [ + { + "name": "_NOT_ENTERED", + "slot": "1", + "value": "0x0000000000000000000000000000000000015180" + }, + { + "name": "_ENTERED", + "slot": "2", + "value": "0x0000000000000000000000000000000000000000" + }, + { + "name": "roleStore" + }, + { + "name": "eventEmitter" + } + ], + "_status": 1, + "pendingActions": 0, + "pendingActionsList": "00000000000000000000000000000000000000000000000000000000000000f6" + }, + { + "Function": "signalSetPriceFeed", + "Modifiers": [ + "nonReentrant", + "onlyTimelockAdmin" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "_ENTERED", + "_status", + "timelockDelay", + "pendingActionsList", + "msg.sender", + "eventEmitter", + "roleName", + "Role", + "role", + "_NOT_ENTERED", + "roleStore", + "pendingActions" + ], + "state_variables_written": [ + "_status", + "pendingActions" + ], + "immutables_and_constants": [ + { + "name": "_NOT_ENTERED", + "slot": "1", + "value": "0x0000000000000000000000000000000000015180" + }, + { + "name": "_ENTERED", + "slot": "2", + "value": "0x0000000000000000000000000000000000000000" + }, + { + "name": "roleStore" + }, + { + "name": "eventEmitter" + } + ], + "_status": 1, + "timelockDelay": 86400, + "pendingActions": 0, + "pendingActionsList": "00000000000000000000000000000000000000000000000000000000000000f6" + }, + { + "Function": "setPriceFeedAfterSignal", + "Modifiers": [ + "nonReentrant", + "onlyTimelockAdmin" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "PRICE_FEED", + "_ENTERED", + "_status", + "PRICE_FEED_HEARTBEAT_DURATION", + "STABLE_PRICE", + "pendingActionsList", + "msg.sender", + "PRICE_FEED_MULTIPLIER", + "roleName", + "eventEmitter", + "Role", + "role", + "_NOT_ENTERED", + "roleStore", + "dataStore", + "pendingActions" + ], + "state_variables_written": [ + "_status", + "pendingActions" + ], + "immutables_and_constants": [ + { + "name": "_NOT_ENTERED", + "slot": "1", + "value": "0x0000000000000000000000000000000000015180" + }, + { + "name": "_ENTERED", + "slot": "2", + "value": "0x0000000000000000000000000000000000000000" + }, + { + "name": "roleStore" + }, + { + "name": "dataStore" + }, + { + "name": "eventEmitter" + } + ], + "_status": 1, + "pendingActions": 0, + "pendingActionsList": "00000000000000000000000000000000000000000000000000000000000000f6" + }, + { + "Function": "signalSetDataStream", + "Modifiers": [ + "nonReentrant", + "onlyTimelockAdmin" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "_ENTERED", + "_status", + "timelockDelay", + "pendingActionsList", + "msg.sender", + "eventEmitter", + "roleName", + "Role", + "role", + "_NOT_ENTERED", + "roleStore", + "pendingActions" + ], + "state_variables_written": [ + "_status", + "pendingActions" + ], + "immutables_and_constants": [ + { + "name": "_NOT_ENTERED", + "slot": "1", + "value": "0x0000000000000000000000000000000000015180" + }, + { + "name": "_ENTERED", + "slot": "2", + "value": "0x0000000000000000000000000000000000000000" + }, + { + "name": "roleStore" + }, + { + "name": "eventEmitter" + } + ], + "_status": 1, + "timelockDelay": 86400, + "pendingActions": 0, + "pendingActionsList": "00000000000000000000000000000000000000000000000000000000000000f6" + }, + { + "Function": "setDataStreamAfterSignal", + "Modifiers": [ + "nonReentrant", + "onlyTimelockAdmin" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "DATA_STREAM_ID", + "_ENTERED", + "_status", + "DATA_STREAM_MULTIPLIER", + "pendingActionsList", + "msg.sender", + "eventEmitter", + "roleName", + "Role", + "role", + "_NOT_ENTERED", + "roleStore", + "dataStore", + "pendingActions" + ], + "state_variables_written": [ + "_status", + "pendingActions" + ], + "immutables_and_constants": [ + { + "name": "_NOT_ENTERED", + "slot": "1", + "value": "0x0000000000000000000000000000000000015180" + }, + { + "name": "_ENTERED", + "slot": "2", + "value": "0x0000000000000000000000000000000000000000" + }, + { + "name": "roleStore" + }, + { + "name": "dataStore" + }, + { + "name": "eventEmitter" + } + ], + "_status": 1, + "pendingActions": 0, + "pendingActionsList": "00000000000000000000000000000000000000000000000000000000000000f6" + }, + { + "Function": "cancelAction", + "Modifiers": [ + "nonReentrant", + "onlyTimelockAdmin" + ], + "msg.sender_conditions": [ + "! roleStore.hasRole(msg.sender,role)" + ], + "state_variables_read": [ + "_ENTERED", + "_status", + "pendingActionsList", + "msg.sender", + "eventEmitter", + "roleName", + "Role", + "role", + "_NOT_ENTERED", + "roleStore", + "pendingActions" + ], + "state_variables_written": [ + "_status", + "pendingActions" + ], + "immutables_and_constants": [ + { + "name": "_NOT_ENTERED", + "slot": "1", + "value": "0x0000000000000000000000000000000000015180" + }, + { + "name": "_ENTERED", + "slot": "2", + "value": "0x0000000000000000000000000000000000000000" + }, + { + "name": "roleStore" + }, + { + "name": "eventEmitter" + } + ], + "_status": 1, + "pendingActions": 0, + "pendingActionsList": "00000000000000000000000000000000000000000000000000000000000000f6" + } + ], + "storage_values": { + "_status": 1, + "timelockDelay": 86400, + "pendingActions": 0, + "pendingActionsList": "00000000000000000000000000000000000000000000000000000000000000f6" + } + } + } +} \ No newline at end of file diff --git a/harnesses/permissions-scan/targets/ostium/contracts.json b/harnesses/permissions-scan/targets/ostium/contracts.json new file mode 100644 index 00000000..5138e024 --- /dev/null +++ b/harnesses/permissions-scan/targets/ostium/contracts.json @@ -0,0 +1,116 @@ +{ + "chain": "arbi", + "project": "ostium", + "addresses": [ + "0x20d419a8e12c45f88fda7c5760bb6923cee27f98", + "0x6d0ba1f9996dbd8885827e1b2e8f6593e7702411", + "0x799a139ae56e11f0476ace2f6118cfcaed9608d2", + "0x7720fc8c8680bf4a1af99d44c6c265a74e9742a9", + "0xccf233920e8cc9415ecf503b992881d69b6c47ad", + "0x3890243a8fc091c626ed26c087a028b46bc9d66c", + "0x260e349f643f12797fdc6f8c9d3df211d5577823", + "0xccd5891083a8acd2074690f65d3024e7d13d66e7", + "0x4b0c3c77d398912491f192d265b237c8d4441ad7", + "0xeb85dc6095c74d36500c9cdcacc15ecdc223bbf7", + "0x083f97babf33d4abc03151b5dec98170761f4025" + ], + "sources": [ + { + "address": "0x20d419a8e12c45f88fda7c5760bb6923cee27f98", + "label": "oLP vault proxy", + "found_at": "https://ostium-labs.gitbook.io/ostium-docs/security/smart-contract-audits + Arbiscan", + "consulted_at": "2026-08-02T19:08:53Z", + "is_proxy": true, + "proxy_type": "EIP-1967", + "implementation": "0x1E20E46C92F0786889462F065BC9DA163AF6020D", + "impl_slot_read": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + }, + { + "address": "0x6d0ba1f9996dbd8885827e1b2e8f6593e7702411", + "label": "Trading proxy", + "found_at": "https://ostium-labs.gitbook.io/ostium-docs/security/smart-contract-audits + Arbiscan", + "consulted_at": "2026-08-02T19:08:53Z", + "is_proxy": true, + "proxy_type": "EIP-1967", + "implementation": "0x8cbb5bd2b46f993078407cea26704af0a901515a", + "impl_slot_read": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + }, + { + "address": "0x799a139ae56e11f0476ace2f6118cfcaed9608d2", + "label": "Registry", + "found_at": "Arbiscan label search", + "consulted_at": "2026-08-02T19:08:53Z", + "is_proxy": false, + "implementation": null + }, + { + "address": "0x7720fc8c8680bf4a1af99d44c6c265a74e9742a9", + "label": "TradingCallbacks", + "found_at": "Arbiscan label search", + "consulted_at": "2026-08-02T19:08:53Z", + "is_proxy": false, + "implementation": null + }, + { + "address": "0xccf233920e8cc9415ecf503b992881d69b6c47ad", + "label": "Verifier", + "found_at": "Arbiscan label search", + "consulted_at": "2026-08-02T19:08:53Z", + "is_proxy": false, + "implementation": null + }, + { + "address": "0x3890243a8fc091c626ed26c087a028b46bc9d66c", + "label": "PairInfos proxy", + "found_at": "Arbiscan label search", + "consulted_at": "2026-08-02T19:08:53Z", + "is_proxy": true, + "proxy_type": "EIP-1967", + "implementation": "unknown", + "note": "impl slot not read for this specific contract" + }, + { + "address": "0x260e349f643f12797fdc6f8c9d3df211d5577823", + "label": "PairsStorage proxy", + "found_at": "Arbiscan label search", + "consulted_at": "2026-08-02T19:08:53Z", + "is_proxy": true, + "proxy_type": "EIP-1967", + "implementation": "unknown" + }, + { + "address": "0xccd5891083a8acd2074690f65d3024e7d13d66e7", + "label": "TradingStorage", + "found_at": "Arbiscan label search", + "consulted_at": "2026-08-02T19:08:53Z", + "is_proxy": false, + "implementation": null + }, + { + "address": "0x4b0c3c77d398912491f192d265b237c8d4441ad7", + "label": "PriceRouter", + "found_at": "Arbiscan label search", + "consulted_at": "2026-08-02T19:08:53Z", + "is_proxy": false, + "implementation": null + }, + { + "address": "0xeb85dc6095c74d36500c9cdcacc15ecdc223bbf7", + "label": "TimelockOwner", + "found_at": "Arbiscan label search + RoleGranted events on-chain", + "consulted_at": "2026-08-02T19:08:53Z", + "is_proxy": false, + "implementation": null, + "note": "OZ TimelockController (non-enumerable). getMinDelay()=64800s (18h) confirmed. PROPOSER=0x1cd84f9b (Gnosis Safe 4/8). ADMIN=itself (initial). ProxyAdmin owner=this." + }, + { + "address": "0x083f97babf33d4abc03151b5dec98170761f4025", + "label": "ProxyAdmin", + "found_at": "Arbiscan label search", + "consulted_at": "2026-08-02T19:08:53Z", + "is_proxy": false, + "implementation": null, + "note": "OZ ProxyAdmin. owner()=TimelockOwner (0xeb85dc...) confirmed on-chain." + } + ] +} diff --git a/harnesses/permissions-scan/targets/ostium/permissions.json b/harnesses/permissions-scan/targets/ostium/permissions.json new file mode 100644 index 00000000..e379e83a --- /dev/null +++ b/harnesses/permissions-scan/targets/ostium/permissions.json @@ -0,0 +1,3181 @@ +{ + "OstiumVault": { + "Implementation_Address": "0x1e20e46c92f0786889462f065bc9da163af6020d", + "Proxy_Address": "0x20d419a8e12c45f88fda7c5760bb6923cee27f98", + "proxy_permissions": { + "Contract_Name": "TransparentUpgradeableProxy", + "Functions": [ + { + "Function": "fallback", + "Modifiers": [], + "msg.sender_conditions": [ + "msg.sender == _getAdmin()" + ], + "state_variables_read": [ + "_IMPLEMENTATION_SLOT", + "_ADMIN_SLOT" + ], + "state_variables_written": [] + }, + { + "Function": "receive", + "Modifiers": [], + "msg.sender_conditions": [ + "msg.sender == _getAdmin()" + ], + "state_variables_read": [ + "_IMPLEMENTATION_SLOT", + "_ADMIN_SLOT" + ], + "state_variables_written": [] + }, + { + "Function": "_fallback", + "Modifiers": [], + "msg.sender_conditions": [ + "msg.sender == _getAdmin()" + ], + "state_variables_read": [ + "_IMPLEMENTATION_SLOT", + "_ADMIN_SLOT" + ], + "state_variables_written": [] + } + ] + }, + "permissions": { + "Contract_Name": "OstiumVault", + "Functions": [ + { + "Function": "__Multicall_init", + "Modifiers": [ + "onlyInitializing" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "INITIALIZABLE_STORAGE", + "TMP_1113", + "slot", + "$" + ], + "state_variables_written": [], + "immutables_and_constants": [ + { + "name": "INITIALIZABLE_STORAGE", + "slot": "0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00" + } + ] + }, + { + "Function": "__Multicall_init_unchained", + "Modifiers": [ + "onlyInitializing" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "INITIALIZABLE_STORAGE", + "TMP_1113", + "slot", + "$" + ], + "state_variables_written": [], + "immutables_and_constants": [ + { + "name": "INITIALIZABLE_STORAGE", + "slot": "0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00" + } + ] + }, + { + "Function": "multicall", + "Modifiers": [], + "msg.sender_conditions": [ + "msg.sender == _msgSender()" + ], + "state_variables_read": [], + "state_variables_written": [] + }, + { + "Function": "__Context_init", + "Modifiers": [ + "onlyInitializing" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "INITIALIZABLE_STORAGE", + "TMP_1113", + "slot", + "$" + ], + "state_variables_written": [], + "immutables_and_constants": [ + { + "name": "INITIALIZABLE_STORAGE", + "slot": "0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00" + } + ] + }, + { + "Function": "__Context_init_unchained", + "Modifiers": [ + "onlyInitializing" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "INITIALIZABLE_STORAGE", + "TMP_1113", + "slot", + "$" + ], + "state_variables_written": [], + "immutables_and_constants": [ + { + "name": "INITIALIZABLE_STORAGE", + "slot": "0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00" + } + ] + }, + { + "Function": "__ERC4626_init", + "Modifiers": [ + "onlyInitializing" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "$", + "INITIALIZABLE_STORAGE", + "ERC4626StorageLocation", + "TMP_1113", + "slot" + ], + "state_variables_written": [], + "immutables_and_constants": [ + { + "name": "INITIALIZABLE_STORAGE", + "slot": "0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00" + }, + { + "name": "ERC4626StorageLocation", + "slot": "0x0773e532dfede91f04b12a73d3d2acd361424f41f76b4fb79f090161e36b4e00" + } + ] + }, + { + "Function": "__ERC4626_init_unchained", + "Modifiers": [ + "onlyInitializing" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "$", + "INITIALIZABLE_STORAGE", + "ERC4626StorageLocation", + "TMP_1113", + "slot" + ], + "state_variables_written": [], + "immutables_and_constants": [ + { + "name": "INITIALIZABLE_STORAGE", + "slot": "0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00" + }, + { + "name": "ERC4626StorageLocation", + "slot": "0x0773e532dfede91f04b12a73d3d2acd361424f41f76b4fb79f090161e36b4e00" + } + ] + }, + { + "Function": "__ERC20_init", + "Modifiers": [ + "onlyInitializing" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "ERC20StorageLocation", + "$", + "INITIALIZABLE_STORAGE", + "TMP_1113", + "slot" + ], + "state_variables_written": [], + "immutables_and_constants": [ + { + "name": "INITIALIZABLE_STORAGE", + "slot": "0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00" + }, + { + "name": "ERC20StorageLocation", + "slot": "0x52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00" + } + ] + }, + { + "Function": "__ERC20_init_unchained", + "Modifiers": [ + "onlyInitializing" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "ERC20StorageLocation", + "$", + "INITIALIZABLE_STORAGE", + "TMP_1113", + "slot" + ], + "state_variables_written": [], + "immutables_and_constants": [ + { + "name": "INITIALIZABLE_STORAGE", + "slot": "0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00" + }, + { + "name": "ERC20StorageLocation", + "slot": "0x52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00" + } + ] + }, + { + "Function": "initialize", + "Modifiers": [ + "initializer", + "onlyInitializing" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "MAX_DISCOUNT_P", + "ERC20StorageLocation", + "$", + "INITIALIZABLE_STORAGE", + "construction", + "ERC4626StorageLocation", + "isTopLevelCall", + "MIN_DAILY_ACC_PNL_DELTA", + "PRECISION_2", + "PRECISION_18", + "TMP_1113", + "initialized", + "this", + "initialSetup", + "TMP_1733", + "slot" + ], + "state_variables_written": [ + "__DEPRECATED_withdrawLockThresholdsP", + "currentEpochStart", + "__DEPRECATED_maxDiscountP", + "maxAccOpenPnlDeltaPerToken", + "__DEPRECATED_maxDiscountThresholdP", + "shareToAssetsPrice", + "registry", + "maxDailyAccPnlDeltaPerToken", + "__DEPRECATED_maxSupplyIncreaseDailyP", + "__DEPRECATED_WITHDRAW_EPOCHS_LOCKS", + "currentEpoch" + ], + "immutables_and_constants": [ + { + "name": "INITIALIZABLE_STORAGE", + "slot": "0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00" + }, + { + "name": "ERC20StorageLocation", + "slot": "0x52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00" + }, + { + "name": "ERC4626StorageLocation", + "slot": "0x0773e532dfede91f04b12a73d3d2acd361424f41f76b4fb79f090161e36b4e00" + }, + { + "name": "PRECISION_18", + "slot": "1e18" + }, + { + "name": "MIN_DAILY_ACC_PNL_DELTA", + "slot": "1e13" + }, + { + "name": "MAX_DISCOUNT_P", + "slot": "5000" + }, + { + "name": "PRECISION_2", + "slot": "1e2" + } + ] + }, + { + "Function": "initializeV2", + "Modifiers": [ + "reinitializer" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "INITIALIZABLE_STORAGE", + "slot", + "version", + "$" + ], + "state_variables_written": [ + "__DEPRECATED_totalDeposited", + "__DEPRECATED_totalRewards", + "__DEPRECATED_totalLiability" + ], + "immutables_and_constants": [ + { + "name": "INITIALIZABLE_STORAGE", + "slot": "0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00" + } + ] + }, + { + "Function": "initializeV3", + "Modifiers": [ + "reinitializer" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "$", + "INITIALIZABLE_STORAGE", + "version", + "__DEPRECATED_currentEpochPositiveOpenPnl", + "slot" + ], + "state_variables_written": [ + "lastSettlementOpenPnl", + "maxSettlementInterval", + "__DEPRECATED_currentEpochPositiveOpenPnl" + ], + "immutables_and_constants": [ + { + "name": "INITIALIZABLE_STORAGE", + "slot": "0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00" + } + ], + "__DEPRECATED_currentEpochPositiveOpenPnl": 0 + }, + { + "Function": "initializeV4", + "Modifiers": [ + "reinitializer" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "ERC4626StorageLocation", + "version", + "totalAssetsToDeposit", + "PRECISION_18", + "lastSettlementTs", + "accPnlPerTokenUsed", + "shareToAssetsPrice", + "lastSettlementId", + "accRewardsPerToken", + "$", + "accPnlPerToken", + "accPnlPerTokenThreshold", + "lastSettlementOpenPnl", + "ERC20StorageLocation", + "INITIALIZABLE_STORAGE", + "supplyCap", + "PRECISION_6", + "slot", + "registry", + "totalSharesToWithdraw", + "totalClosedPnl", + "maxAccOpenPnlDeltaPerToken" + ], + "state_variables_written": [ + "marketMaker", + "settlementShareToAssetsPrice", + "settlementAllocationScaleP", + "accPnlPerToken", + "lastSettlementId", + "totalAssetsToDeposit", + "accPnlPerTokenUsed", + "shareToAssetsPrice", + "lastSettlementTs", + "accPnlPerTokenThreshold", + "totalSharesToWithdraw", + "lastSettlementOpenPnl" + ], + "immutables_and_constants": [ + { + "name": "INITIALIZABLE_STORAGE", + "slot": "0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00" + }, + { + "name": "ERC20StorageLocation", + "slot": "0x52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00" + }, + { + "name": "ERC4626StorageLocation", + "slot": "0x0773e532dfede91f04b12a73d3d2acd361424f41f76b4fb79f090161e36b4e00" + }, + { + "name": "PRECISION_18", + "slot": "1e18" + }, + { + "name": "PRECISION_6", + "slot": "1e6" + } + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "shareToAssetsPrice": 1150043034562485881, + "accRewardsPerToken": 277811703270106469, + "maxAccOpenPnlDeltaPerToken": 250000000000000000, + "accPnlPerToken": 838225531668519834, + "accPnlPerTokenUsed": 124663556686233273, + "totalClosedPnl": 17197379775851, + "lastSettlementId": 125, + "lastSettlementTs": 1784072348, + "lastSettlementOpenPnl": 115792089237316195423570985008687907853269984665640562661043148325116290223227, + "totalAssetsToDeposit": 0, + "totalSharesToWithdraw": 0, + "supplyCap": 1, + "accPnlPerTokenThreshold": 127768668707620588 + }, + { + "Function": "updateMaxAccOpenPnlDeltaPerToken", + "Modifiers": [ + "onlyGov" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "registry", + "a", + "msg.sender" + ], + "state_variables_written": [ + "maxAccOpenPnlDeltaPerToken" + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2" + }, + { + "Function": "updateMaxDailyAccPnlDeltaPerToken", + "Modifiers": [ + "onlyGov" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "registry", + "a", + "msg.sender", + "MIN_DAILY_ACC_PNL_DELTA" + ], + "state_variables_written": [ + "maxDailyAccPnlDeltaPerToken" + ], + "immutables_and_constants": [ + { + "name": "MIN_DAILY_ACC_PNL_DELTA", + "slot": "1e13" + } + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2" + }, + { + "Function": "updateMaxSettlementInterval", + "Modifiers": [ + "onlyGov" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "registry", + "a", + "msg.sender", + "MIN_SETTLEMENT_LENGTH", + "MAX_SETTLEMENT_LENGTH" + ], + "state_variables_written": [ + "maxSettlementInterval" + ], + "immutables_and_constants": [ + { + "name": "MAX_SETTLEMENT_LENGTH", + "slot": "2592000" + }, + { + "name": "MIN_SETTLEMENT_LENGTH", + "slot": "600" + } + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2" + }, + { + "Function": "updateWithdrawSettlementDelay", + "Modifiers": [ + "onlyGov" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "MAX_WITHDRAW_SETTLEMENT_DELAY", + "registry", + "a", + "msg.sender" + ], + "state_variables_written": [ + "withdrawSettlementDelay" + ], + "immutables_and_constants": [ + { + "name": "MAX_WITHDRAW_SETTLEMENT_DELAY", + "slot": "10" + } + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2" + }, + { + "Function": "updateSupplyCap", + "Modifiers": [ + "onlyGov" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "registry", + "a", + "msg.sender" + ], + "state_variables_written": [ + "supplyCap" + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2" + }, + { + "Function": "updateAccPnlPerTokenThreshold", + "Modifiers": [ + "onlyGov" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "accRewardsPerToken", + "registry", + "a", + "msg.sender", + "accPnlPerTokenThreshold", + "PRECISION_18", + "accPnlPerTokenUsed", + "shareToAssetsPrice" + ], + "state_variables_written": [ + "shareToAssetsPrice", + "accPnlPerTokenThreshold" + ], + "immutables_and_constants": [ + { + "name": "PRECISION_18", + "slot": "1e18" + } + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "shareToAssetsPrice": 1150043034562485881, + "accRewardsPerToken": 277811703270106469, + "accPnlPerTokenUsed": 124663556686233273, + "accPnlPerTokenThreshold": 127768668707620588 + }, + { + "Function": "forceSettlement", + "Modifiers": [ + "onlyGov" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "a", + "ERC4626StorageLocation", + "totalAssetsToDeposit", + "PRECISION_18", + "lastSettlementTs", + "accPnlPerTokenUsed", + "shareToAssetsPrice", + "lastSettlementId", + "accRewardsPerToken", + "accPnlPerToken", + "accPnlPerTokenThreshold", + "lastSettlementOpenPnl", + "ERC20StorageLocation", + "msg.sender", + "supplyCap", + "PRECISION_6", + "registry", + "totalSharesToWithdraw", + "totalClosedPnl", + "maxAccOpenPnlDeltaPerToken" + ], + "state_variables_written": [ + "settlementShareToAssetsPrice", + "settlementAllocationScaleP", + "accPnlPerToken", + "lastSettlementId", + "totalAssetsToDeposit", + "accPnlPerTokenUsed", + "shareToAssetsPrice", + "lastSettlementTs", + "totalSharesToWithdraw", + "lastSettlementOpenPnl" + ], + "immutables_and_constants": [ + { + "name": "ERC20StorageLocation", + "slot": "0x52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00" + }, + { + "name": "ERC4626StorageLocation", + "slot": "0x0773e532dfede91f04b12a73d3d2acd361424f41f76b4fb79f090161e36b4e00" + }, + { + "name": "PRECISION_18", + "slot": "1e18" + }, + { + "name": "PRECISION_6", + "slot": "1e6" + } + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "shareToAssetsPrice": 1150043034562485881, + "accRewardsPerToken": 277811703270106469, + "maxAccOpenPnlDeltaPerToken": 250000000000000000, + "accPnlPerToken": 838225531668519834, + "accPnlPerTokenUsed": 124663556686233273, + "totalClosedPnl": 17197379775851, + "lastSettlementId": 125, + "lastSettlementTs": 1784072348, + "lastSettlementOpenPnl": 115792089237316195423570985008687907853269984665640562661043148325116290223227, + "totalAssetsToDeposit": 0, + "totalSharesToWithdraw": 0, + "supplyCap": 1, + "accPnlPerTokenThreshold": 127768668707620588 + }, + { + "Function": "forceResetDailyAccPnlDelta", + "Modifiers": [ + "onlyGov" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "registry", + "a", + "msg.sender" + ], + "state_variables_written": [ + "dailyAccPnlDeltaPerToken", + "lastDailyAccPnlDeltaResetTs" + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2" + }, + { + "Function": "requestDeposit", + "Modifiers": [ + "checks" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "withdrawSettlementDelay", + "ERC4626StorageLocation", + "totalAssetsToDeposit", + "assetsOrShares", + "pendingDepositRequest", + "lastSettlementId" + ], + "state_variables_written": [ + "pendingDepositRequest", + "totalAssetsToDeposit" + ], + "immutables_and_constants": [ + { + "name": "ERC4626StorageLocation", + "slot": "0x0773e532dfede91f04b12a73d3d2acd361424f41f76b4fb79f090161e36b4e00" + } + ], + "lastSettlementId": 125, + "totalAssetsToDeposit": 0, + "pendingDepositRequest": 0, + "withdrawSettlementDelay": 2 + }, + { + "Function": "requestWithdraw", + "Modifiers": [ + "checks" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "totalSharesToWithdraw", + "ERC20StorageLocation", + "withdrawSettlementDelay", + "assetsOrShares", + "pendingWithdrawRequest", + "lastSettlementId" + ], + "state_variables_written": [ + "totalSharesToWithdraw", + "pendingWithdrawRequest" + ], + "immutables_and_constants": [ + { + "name": "ERC20StorageLocation", + "slot": "0x52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00" + } + ], + "lastSettlementId": 125, + "totalSharesToWithdraw": 0, + "pendingWithdrawRequest": 0, + "withdrawSettlementDelay": 2 + }, + { + "Function": "cancelRequestDeposit", + "Modifiers": [ + "checks" + ], + "msg.sender_conditions": [ + "require(bool)(getDepositStatus(msg.sender,settlementId) == RequestStatus.PENDING)", + "require(bool)(pendingDepositRequest[msg.sender][settlementId] >= assets)" + ], + "state_variables_read": [ + "ERC4626StorageLocation", + "totalAssetsToDeposit", + "assetsOrShares", + "pendingDepositRequest", + "lastSettlementId" + ], + "state_variables_written": [ + "pendingDepositRequest", + "totalAssetsToDeposit" + ], + "immutables_and_constants": [ + { + "name": "ERC4626StorageLocation", + "slot": "0x0773e532dfede91f04b12a73d3d2acd361424f41f76b4fb79f090161e36b4e00" + } + ], + "lastSettlementId": 125, + "totalAssetsToDeposit": 0, + "pendingDepositRequest": 0 + }, + { + "Function": "cancelRequestWithdraw", + "Modifiers": [ + "checks" + ], + "msg.sender_conditions": [ + "require(bool)(getWithdrawStatus(msg.sender,settlementId) == RequestStatus.PENDING)", + "require(bool)(pendingWithdrawRequest[msg.sender][settlementId] >= shares)" + ], + "state_variables_read": [ + "totalSharesToWithdraw", + "ERC20StorageLocation", + "assetsOrShares", + "pendingWithdrawRequest", + "lastSettlementId" + ], + "state_variables_written": [ + "totalSharesToWithdraw", + "pendingWithdrawRequest" + ], + "immutables_and_constants": [ + { + "name": "ERC20StorageLocation", + "slot": "0x52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00" + } + ], + "lastSettlementId": 125, + "totalSharesToWithdraw": 0, + "pendingWithdrawRequest": 0 + }, + { + "Function": "claimDeposit", + "Modifiers": [], + "msg.sender_conditions": [ + "getDepositStatus(msg.sender,settlementId) != RequestStatus.CLAIMABLE" + ], + "state_variables_read": [ + "ERC20StorageLocation", + "settlementAllocationScaleP", + "ERC4626StorageLocation", + "totalAssetsToDeposit", + "PRECISION_18", + "pendingDepositRequest", + "settlementShareToAssetsPrice", + "lastSettlementId" + ], + "state_variables_written": [ + "pendingDepositRequest" + ], + "immutables_and_constants": [ + { + "name": "ERC20StorageLocation", + "slot": "0x52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00" + }, + { + "name": "ERC4626StorageLocation", + "slot": "0x0773e532dfede91f04b12a73d3d2acd361424f41f76b4fb79f090161e36b4e00" + }, + { + "name": "PRECISION_18", + "slot": "1e18" + } + ], + "lastSettlementId": 125, + "totalAssetsToDeposit": 0, + "settlementShareToAssetsPrice": 0, + "pendingDepositRequest": 0, + "settlementAllocationScaleP": 0 + }, + { + "Function": "claimWithdraw", + "Modifiers": [], + "msg.sender_conditions": [ + "getWithdrawStatus(msg.sender,settlementId) != RequestStatus.CLAIMABLE" + ], + "state_variables_read": [ + "totalSharesToWithdraw", + "ERC4626StorageLocation", + "PRECISION_18", + "pendingWithdrawRequest", + "settlementShareToAssetsPrice", + "lastSettlementId" + ], + "state_variables_written": [ + "pendingWithdrawRequest" + ], + "immutables_and_constants": [ + { + "name": "ERC4626StorageLocation", + "slot": "0x0773e532dfede91f04b12a73d3d2acd361424f41f76b4fb79f090161e36b4e00" + }, + { + "name": "PRECISION_18", + "slot": "1e18" + } + ], + "lastSettlementId": 125, + "totalSharesToWithdraw": 0, + "settlementShareToAssetsPrice": 0, + "pendingWithdrawRequest": 0 + }, + { + "Function": "reclaimDeposit", + "Modifiers": [], + "msg.sender_conditions": [ + "getDepositStatus(msg.sender,settlementId) != RequestStatus.RECLAIMABLE" + ], + "state_variables_read": [ + "ERC4626StorageLocation", + "totalAssetsToDeposit", + "lastSettlementId", + "pendingDepositRequest" + ], + "state_variables_written": [ + "pendingDepositRequest" + ], + "immutables_and_constants": [ + { + "name": "ERC4626StorageLocation", + "slot": "0x0773e532dfede91f04b12a73d3d2acd361424f41f76b4fb79f090161e36b4e00" + } + ], + "lastSettlementId": 125, + "totalAssetsToDeposit": 0, + "pendingDepositRequest": 0 + }, + { + "Function": "reclaimWithdraw", + "Modifiers": [], + "msg.sender_conditions": [ + "getWithdrawStatus(msg.sender,settlementId) != RequestStatus.RECLAIMABLE" + ], + "state_variables_read": [ + "totalSharesToWithdraw", + "ERC20StorageLocation", + "pendingWithdrawRequest", + "lastSettlementId" + ], + "state_variables_written": [ + "pendingWithdrawRequest" + ], + "immutables_and_constants": [ + { + "name": "ERC20StorageLocation", + "slot": "0x52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00" + } + ], + "lastSettlementId": 125, + "totalSharesToWithdraw": 0, + "pendingWithdrawRequest": 0 + }, + { + "Function": "sendAssets", + "Modifiers": [ + "onlyCallbacks" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "a", + "ERC4626StorageLocation", + "totalAssetsToDeposit", + "PRECISION_18", + "lastSettlementTs", + "accPnlPerTokenUsed", + "shareToAssetsPrice", + "lastSettlementId", + "accRewardsPerToken", + "accPnlPerToken", + "maxDailyAccPnlDeltaPerToken", + "accPnlPerTokenThreshold", + "lastSettlementOpenPnl", + "maxSettlementInterval", + "ERC20StorageLocation", + "msg.sender", + "lastDailyAccPnlDeltaResetTs", + "supplyCap", + "PRECISION_6", + "registry", + "totalSharesToWithdraw", + "totalClosedPnl", + "dailyAccPnlDeltaPerToken", + "maxAccOpenPnlDeltaPerToken" + ], + "state_variables_written": [ + "settlementShareToAssetsPrice", + "settlementAllocationScaleP", + "accPnlPerToken", + "lastSettlementId", + "totalClosedPnl", + "totalAssetsToDeposit", + "accPnlPerTokenUsed", + "shareToAssetsPrice", + "lastDailyAccPnlDeltaResetTs", + "lastSettlementTs", + "totalSharesToWithdraw", + "dailyAccPnlDeltaPerToken", + "lastSettlementOpenPnl" + ], + "immutables_and_constants": [ + { + "name": "ERC20StorageLocation", + "slot": "0x52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00" + }, + { + "name": "ERC4626StorageLocation", + "slot": "0x0773e532dfede91f04b12a73d3d2acd361424f41f76b4fb79f090161e36b4e00" + }, + { + "name": "PRECISION_18", + "slot": "1e18" + }, + { + "name": "PRECISION_6", + "slot": "1e6" + } + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "lastDailyAccPnlDeltaResetTs": 1785686518, + "shareToAssetsPrice": 1150043034562485881, + "accRewardsPerToken": 277811703270106469, + "maxAccOpenPnlDeltaPerToken": 250000000000000000, + "maxDailyAccPnlDeltaPerToken": 60000000000000000, + "accPnlPerToken": 838225531668519834, + "accPnlPerTokenUsed": 124663556686233273, + "dailyAccPnlDeltaPerToken": 68804337193, + "totalClosedPnl": 17197379775851, + "lastSettlementId": 125, + "lastSettlementTs": 1784072348, + "lastSettlementOpenPnl": 115792089237316195423570985008687907853269984665640562661043148325116290223227, + "maxSettlementInterval": 2592000, + "totalAssetsToDeposit": 0, + "totalSharesToWithdraw": 0, + "supplyCap": 1, + "accPnlPerTokenThreshold": 127768668707620588 + }, + { + "Function": "setMarketMaker", + "Modifiers": [ + "onlyTimelock" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "registry", + "a", + "msg.sender", + "marketMaker" + ], + "state_variables_written": [ + "marketMaker" + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "marketMaker": "0xD8BD72EDD3451973Ce10855E2a73463648A3931d" + }, + { + "Function": "mmDeposit", + "Modifiers": [ + "onlyMM" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "a", + "ERC4626StorageLocation", + "totalAssetsToDeposit", + "PRECISION_18", + "lastSettlementTs", + "accPnlPerTokenUsed", + "shareToAssetsPrice", + "lastSettlementId", + "accRewardsPerToken", + "accPnlPerToken", + "accPnlPerTokenThreshold", + "lastSettlementOpenPnl", + "ERC20StorageLocation", + "msg.sender", + "supplyCap", + "PRECISION_6", + "registry", + "totalSharesToWithdraw", + "marketMaker", + "totalClosedPnl", + "maxAccOpenPnlDeltaPerToken" + ], + "state_variables_written": [ + "settlementShareToAssetsPrice", + "settlementAllocationScaleP", + "accPnlPerToken", + "lastSettlementId", + "totalAssetsToDeposit", + "accPnlPerTokenUsed", + "shareToAssetsPrice", + "lastSettlementTs", + "totalSharesToWithdraw", + "lastSettlementOpenPnl" + ], + "immutables_and_constants": [ + { + "name": "ERC20StorageLocation", + "slot": "0x52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00" + }, + { + "name": "ERC4626StorageLocation", + "slot": "0x0773e532dfede91f04b12a73d3d2acd361424f41f76b4fb79f090161e36b4e00" + }, + { + "name": "PRECISION_18", + "slot": "1e18" + }, + { + "name": "PRECISION_6", + "slot": "1e6" + } + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "shareToAssetsPrice": 1150043034562485881, + "accRewardsPerToken": 277811703270106469, + "maxAccOpenPnlDeltaPerToken": 250000000000000000, + "accPnlPerToken": 838225531668519834, + "accPnlPerTokenUsed": 124663556686233273, + "totalClosedPnl": 17197379775851, + "lastSettlementId": 125, + "lastSettlementTs": 1784072348, + "lastSettlementOpenPnl": 115792089237316195423570985008687907853269984665640562661043148325116290223227, + "totalAssetsToDeposit": 0, + "totalSharesToWithdraw": 0, + "supplyCap": 1, + "accPnlPerTokenThreshold": 127768668707620588, + "marketMaker": "0xD8BD72EDD3451973Ce10855E2a73463648A3931d" + }, + { + "Function": "mmWithdraw", + "Modifiers": [ + "onlyMM" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "a", + "ERC4626StorageLocation", + "totalAssetsToDeposit", + "PRECISION_18", + "lastSettlementTs", + "accPnlPerTokenUsed", + "shareToAssetsPrice", + "lastSettlementId", + "accRewardsPerToken", + "accPnlPerToken", + "accPnlPerTokenThreshold", + "lastSettlementOpenPnl", + "ERC20StorageLocation", + "msg.sender", + "supplyCap", + "PRECISION_6", + "registry", + "totalSharesToWithdraw", + "marketMaker", + "totalClosedPnl", + "maxAccOpenPnlDeltaPerToken" + ], + "state_variables_written": [ + "settlementShareToAssetsPrice", + "settlementAllocationScaleP", + "accPnlPerToken", + "lastSettlementId", + "totalAssetsToDeposit", + "accPnlPerTokenUsed", + "shareToAssetsPrice", + "lastSettlementTs", + "totalSharesToWithdraw", + "lastSettlementOpenPnl" + ], + "immutables_and_constants": [ + { + "name": "ERC20StorageLocation", + "slot": "0x52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00" + }, + { + "name": "ERC4626StorageLocation", + "slot": "0x0773e532dfede91f04b12a73d3d2acd361424f41f76b4fb79f090161e36b4e00" + }, + { + "name": "PRECISION_18", + "slot": "1e18" + }, + { + "name": "PRECISION_6", + "slot": "1e6" + } + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "shareToAssetsPrice": 1150043034562485881, + "accRewardsPerToken": 277811703270106469, + "maxAccOpenPnlDeltaPerToken": 250000000000000000, + "accPnlPerToken": 838225531668519834, + "accPnlPerTokenUsed": 124663556686233273, + "totalClosedPnl": 17197379775851, + "lastSettlementId": 125, + "lastSettlementTs": 1784072348, + "lastSettlementOpenPnl": 115792089237316195423570985008687907853269984665640562661043148325116290223227, + "totalAssetsToDeposit": 0, + "totalSharesToWithdraw": 0, + "supplyCap": 1, + "accPnlPerTokenThreshold": 127768668707620588, + "marketMaker": "0xD8BD72EDD3451973Ce10855E2a73463648A3931d" + } + ], + "storage_values": { + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "lastDailyAccPnlDeltaResetTs": 1785686518, + "shareToAssetsPrice": 1150043034562485881, + "accRewardsPerToken": 277811703270106469, + "maxAccOpenPnlDeltaPerToken": 250000000000000000, + "maxDailyAccPnlDeltaPerToken": 60000000000000000, + "__DEPRECATED_currentEpochPositiveOpenPnl": 0, + "accPnlPerToken": 838225531668519834, + "accPnlPerTokenUsed": 124663556686233273, + "dailyAccPnlDeltaPerToken": 68804337193, + "totalClosedPnl": 17197379775851, + "lastSettlementId": 125, + "lastSettlementTs": 1784072348, + "lastSettlementOpenPnl": 115792089237316195423570985008687907853269984665640562661043148325116290223227, + "maxSettlementInterval": 2592000, + "totalAssetsToDeposit": 0, + "totalSharesToWithdraw": 0, + "settlementShareToAssetsPrice": 0, + "pendingDepositRequest": 0, + "pendingWithdrawRequest": 0, + "withdrawSettlementDelay": 2, + "settlementAllocationScaleP": 0, + "supplyCap": 1, + "accPnlPerTokenThreshold": 127768668707620588, + "marketMaker": "0xD8BD72EDD3451973Ce10855E2a73463648A3931d" + } + } + }, + "OstiumTrading": { + "Implementation_Address": "0x8cbb5bd2b46f993078407cea26704af0a901515a", + "Proxy_Address": "0x6d0ba1f9996dbd8885827e1b2e8f6593e7702411", + "proxy_permissions": { + "Contract_Name": "TransparentUpgradeableProxy", + "Functions": [ + { + "Function": "fallback", + "Modifiers": [], + "msg.sender_conditions": [ + "msg.sender == _getAdmin()" + ], + "state_variables_read": [ + "_IMPLEMENTATION_SLOT", + "_ADMIN_SLOT" + ], + "state_variables_written": [] + }, + { + "Function": "receive", + "Modifiers": [], + "msg.sender_conditions": [ + "msg.sender == _getAdmin()" + ], + "state_variables_read": [ + "_IMPLEMENTATION_SLOT", + "_ADMIN_SLOT" + ], + "state_variables_written": [] + }, + { + "Function": "_fallback", + "Modifiers": [], + "msg.sender_conditions": [ + "msg.sender == _getAdmin()" + ], + "state_variables_read": [ + "_IMPLEMENTATION_SLOT", + "_ADMIN_SLOT" + ], + "state_variables_written": [] + } + ] + }, + "permissions": { + "Contract_Name": "OstiumTrading", + "Functions": [ + { + "Function": "removeDelegate", + "Modifiers": [], + "msg.sender_conditions": [ + "delegations[msg.sender] == address(0)" + ], + "state_variables_read": [ + "delegatableNonces", + "delegations" + ], + "state_variables_written": [ + "delegations", + "delegatableNonces" + ], + "delegations": 0, + "delegatableNonces": 0 + }, + { + "Function": "delegatedAction", + "Modifiers": [], + "msg.sender_conditions": [ + "delegations[trader] != msg.sender" + ], + "state_variables_read": [ + "senderOverride", + "delegations" + ], + "state_variables_written": [ + "senderOverride" + ], + "delegations": 0, + "senderOverride": "0x0000000000000000000000000000000000000000" + }, + { + "Function": "initialize", + "Modifiers": [ + "initializer" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "$", + "INITIALIZABLE_STORAGE", + "marketOrdersTimeout", + "construction", + "isTopLevelCall", + "TMP_1153", + "initialized", + "this", + "initialSetup", + "slot", + "triggerTimeout" + ], + "state_variables_written": [ + "registry", + "maxAllowedCollateral", + "marketOrdersTimeout", + "triggerTimeout" + ], + "immutables_and_constants": [ + { + "name": "INITIALIZABLE_STORAGE", + "slot": "0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00" + } + ], + "marketOrdersTimeout": 50, + "triggerTimeout": 50 + }, + { + "Function": "isGov", + "Modifiers": [], + "msg.sender_conditions": [ + "msg.sender != registry.gov()" + ], + "state_variables_read": [ + "registry" + ], + "state_variables_written": [], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2" + }, + { + "Function": "isManager", + "Modifiers": [], + "msg.sender_conditions": [ + "msg.sender != registry.manager()" + ], + "state_variables_read": [ + "registry" + ], + "state_variables_written": [], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2" + }, + { + "Function": "_onlyTradesUpKeep", + "Modifiers": [], + "msg.sender_conditions": [ + "msg.sender != address(registry.getContractAddress(bytes32(tradesUpKeep)))" + ], + "state_variables_read": [ + "registry" + ], + "state_variables_written": [], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2" + }, + { + "Function": "setMaxAllowedCollateral", + "Modifiers": [ + "onlyGov" + ], + "msg.sender_conditions": [ + "msg.sender != registry.gov()" + ], + "state_variables_read": [ + "registry", + "msg.sender" + ], + "state_variables_written": [ + "maxAllowedCollateral" + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2" + }, + { + "Function": "setMarketOrdersTimeout", + "Modifiers": [ + "onlyGov" + ], + "msg.sender_conditions": [ + "msg.sender != registry.gov()" + ], + "state_variables_read": [ + "registry", + "msg.sender", + "marketOrdersTimeout" + ], + "state_variables_written": [ + "marketOrdersTimeout" + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "marketOrdersTimeout": 50 + }, + { + "Function": "setTriggerTimeout", + "Modifiers": [ + "onlyGov" + ], + "msg.sender_conditions": [ + "msg.sender != registry.gov()" + ], + "state_variables_read": [ + "registry", + "msg.sender", + "triggerTimeout" + ], + "state_variables_written": [ + "triggerTimeout" + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "triggerTimeout": 50 + }, + { + "Function": "pause", + "Modifiers": [ + "onlyManager" + ], + "msg.sender_conditions": [ + "msg.sender != registry.manager()" + ], + "state_variables_read": [ + "registry", + "msg.sender", + "isPaused" + ], + "state_variables_written": [ + "isPaused" + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "isPaused": false + }, + { + "Function": "done", + "Modifiers": [ + "onlyGov" + ], + "msg.sender_conditions": [ + "msg.sender != registry.gov()" + ], + "state_variables_read": [ + "registry", + "msg.sender", + "isDone" + ], + "state_variables_written": [ + "isDone" + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "isDone": false + }, + { + "Function": "openTrade", + "Modifiers": [ + "notDone", + "notPaused", + "pairIndexListed" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "isPaused", + "registry", + "senderOverride", + "PERCENT_BASE", + "MAX_BUILDER_FEE_PERCENT", + "maxAllowedCollateral", + "pairIndex", + "isDone", + "PRECISION_6" + ], + "state_variables_written": [], + "immutables_and_constants": [ + { + "name": "PRECISION_6", + "slot": "1e6" + }, + { + "name": "PERCENT_BASE", + "slot": "100e2" + }, + { + "name": "MAX_BUILDER_FEE_PERCENT", + "slot": "500000" + } + ], + "senderOverride": "0x0000000000000000000000000000000000000000", + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "maxAllowedCollateral": 5000000000000, + "isPaused": false, + "isDone": false + }, + { + "Function": "closeTradeMarket", + "Modifiers": [ + "notDone" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "registry", + "ARBITRUM_MAINNET", + "senderOverride", + "PERCENT_BASE", + "ARBITRUM_SEPOLIA", + "isDone", + "ARBITRUM_GOERLI", + "triggerTimeout", + "ARB_SYS" + ], + "state_variables_written": [], + "immutables_and_constants": [ + { + "name": "PERCENT_BASE", + "slot": "100e2" + } + ], + "senderOverride": "0x0000000000000000000000000000000000000000", + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "triggerTimeout": 50, + "isDone": false + }, + { + "Function": "updateOpenLimitOrder", + "Modifiers": [ + "notDone" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "registry", + "ARBITRUM_MAINNET", + "senderOverride", + "ARBITRUM_SEPOLIA", + "isDone", + "ARBITRUM_GOERLI", + "triggerTimeout", + "ARB_SYS" + ], + "state_variables_written": [], + "senderOverride": "0x0000000000000000000000000000000000000000", + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "triggerTimeout": 50, + "isDone": false + }, + { + "Function": "cancelOpenLimitOrder", + "Modifiers": [ + "notDone" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "registry", + "ARBITRUM_MAINNET", + "senderOverride", + "ARBITRUM_SEPOLIA", + "isDone", + "ARBITRUM_GOERLI", + "triggerTimeout", + "ARB_SYS" + ], + "state_variables_written": [], + "senderOverride": "0x0000000000000000000000000000000000000000", + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "triggerTimeout": 50, + "isDone": false + }, + { + "Function": "updateTp", + "Modifiers": [ + "notDone" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "registry", + "ARBITRUM_MAINNET", + "senderOverride", + "MAX_GAIN_P", + "ARBITRUM_SEPOLIA", + "isDone", + "ARBITRUM_GOERLI", + "triggerTimeout", + "ARB_SYS" + ], + "state_variables_written": [], + "immutables_and_constants": [ + { + "name": "MAX_GAIN_P", + "slot": "900" + } + ], + "senderOverride": "0x0000000000000000000000000000000000000000", + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "triggerTimeout": 50, + "isDone": false + }, + { + "Function": "updateSl", + "Modifiers": [ + "notDone" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "registry", + "ARBITRUM_MAINNET", + "senderOverride", + "ARBITRUM_SEPOLIA", + "isDone", + "ARBITRUM_GOERLI", + "triggerTimeout", + "ARB_SYS" + ], + "state_variables_written": [], + "senderOverride": "0x0000000000000000000000000000000000000000", + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "triggerTimeout": 50, + "isDone": false + }, + { + "Function": "topUpCollateral", + "Modifiers": [ + "notDone" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "registry", + "ARBITRUM_MAINNET", + "senderOverride", + "ARBITRUM_SEPOLIA", + "maxAllowedCollateral", + "isDone", + "ARBITRUM_GOERLI", + "PRECISION_6", + "triggerTimeout", + "ARB_SYS" + ], + "state_variables_written": [], + "immutables_and_constants": [ + { + "name": "PRECISION_6", + "slot": "1e6" + } + ], + "senderOverride": "0x0000000000000000000000000000000000000000", + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "maxAllowedCollateral": 5000000000000, + "triggerTimeout": 50, + "isDone": false + }, + { + "Function": "removeCollateral", + "Modifiers": [ + "notDone", + "notPaused" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "isPaused", + "registry", + "ARBITRUM_MAINNET", + "senderOverride", + "ARBITRUM_SEPOLIA", + "isDone", + "ARBITRUM_GOERLI", + "PRECISION_6", + "triggerTimeout", + "ARB_SYS" + ], + "state_variables_written": [], + "immutables_and_constants": [ + { + "name": "PRECISION_6", + "slot": "1e6" + } + ], + "senderOverride": "0x0000000000000000000000000000000000000000", + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "triggerTimeout": 50, + "isPaused": false, + "isDone": false + }, + { + "Function": "executeAutomationOrder", + "Modifiers": [ + "notDone", + "onlyTradesUpKeep", + "pairIndexListed" + ], + "msg.sender_conditions": [ + "msg.sender != address(registry.getContractAddress(bytes32(tradesUpKeep)))" + ], + "state_variables_read": [ + "registry", + "isPaused", + "ARBITRUM_MAINNET", + "msg.sender", + "ARBITRUM_SEPOLIA", + "pairIndex", + "isDone", + "ARBITRUM_GOERLI", + "triggerTimeout", + "ARB_SYS" + ], + "state_variables_written": [], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "triggerTimeout": 50, + "isPaused": false, + "isDone": false + }, + { + "Function": "openTradeMarketTimeout", + "Modifiers": [ + "notDone" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "registry", + "ARBITRUM_MAINNET", + "senderOverride", + "marketOrdersTimeout", + "ARBITRUM_SEPOLIA", + "isDone", + "ARBITRUM_GOERLI", + "ARB_SYS" + ], + "state_variables_written": [], + "senderOverride": "0x0000000000000000000000000000000000000000", + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "marketOrdersTimeout": 50, + "isDone": false + }, + { + "Function": "closeTradeMarketTimeout", + "Modifiers": [ + "notDone" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "registry", + "ARBITRUM_MAINNET", + "senderOverride", + "marketOrdersTimeout", + "ARBITRUM_SEPOLIA", + "isDone", + "ARBITRUM_GOERLI", + "ARB_SYS" + ], + "state_variables_written": [], + "senderOverride": "0x0000000000000000000000000000000000000000", + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "marketOrdersTimeout": 50, + "isDone": false + } + ], + "storage_values": { + "delegations": 0, + "senderOverride": "0x0000000000000000000000000000000000000000", + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "maxAllowedCollateral": 5000000000000, + "marketOrdersTimeout": 50, + "triggerTimeout": 50, + "isPaused": false, + "isDone": false, + "delegatableNonces": 0 + } + } + }, + "OstiumTimelockOwner": { + "Address": "0xeb85dc6095c74d36500c9cdcacc15ecdc223bbf7", + "permissions": { + "Contract_Name": "OstiumTimelockOwner", + "Functions": [ + { + "Function": "schedule", + "Modifiers": [ + "onlyRole" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "_DONE_TIMESTAMP", + "PROPOSER_ROLE", + "msg.sender", + "_timestamps", + "_roles", + "_minDelay", + "role", + "account" + ], + "state_variables_written": [ + "_timestamps" + ], + "immutables_and_constants": [ + { + "name": "PROPOSER_ROLE", + "slot": "keccak256(bytes)(PROPOSER_ROLE)" + }, + { + "name": "_DONE_TIMESTAMP", + "slot": "uint256(1)" + } + ], + "_roles": "0000000000000000000000000000000000000000000000000000000000000000", + "_timestamps": 0, + "_minDelay": 64800 + }, + { + "Function": "scheduleBatch", + "Modifiers": [ + "onlyRole" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "_DONE_TIMESTAMP", + "PROPOSER_ROLE", + "msg.sender", + "_timestamps", + "_roles", + "_minDelay", + "role", + "account" + ], + "state_variables_written": [ + "_timestamps" + ], + "immutables_and_constants": [ + { + "name": "PROPOSER_ROLE", + "slot": "keccak256(bytes)(PROPOSER_ROLE)" + }, + { + "name": "_DONE_TIMESTAMP", + "slot": "uint256(1)" + } + ], + "_roles": "0000000000000000000000000000000000000000000000000000000000000000", + "_timestamps": 0, + "_minDelay": 64800 + }, + { + "Function": "cancel", + "Modifiers": [ + "onlyRole" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "_DONE_TIMESTAMP", + "CANCELLER_ROLE", + "msg.sender", + "_timestamps", + "_roles", + "role", + "account" + ], + "state_variables_written": [ + "_timestamps" + ], + "immutables_and_constants": [ + { + "name": "CANCELLER_ROLE", + "slot": "keccak256(bytes)(CANCELLER_ROLE)" + }, + { + "name": "_DONE_TIMESTAMP", + "slot": "uint256(1)" + } + ], + "_roles": "0000000000000000000000000000000000000000000000000000000000000000", + "_timestamps": 0 + }, + { + "Function": "execute", + "Modifiers": [ + "onlyRoleOrOpenRole" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "_DONE_TIMESTAMP", + "msg.sender", + "_timestamps", + "_roles", + "role", + "account", + "EXECUTOR_ROLE" + ], + "state_variables_written": [ + "_timestamps" + ], + "immutables_and_constants": [ + { + "name": "EXECUTOR_ROLE", + "slot": "keccak256(bytes)(EXECUTOR_ROLE)" + }, + { + "name": "_DONE_TIMESTAMP", + "slot": "uint256(1)" + } + ], + "_roles": "0000000000000000000000000000000000000000000000000000000000000000", + "_timestamps": 0 + }, + { + "Function": "executeBatch", + "Modifiers": [ + "onlyRoleOrOpenRole" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "_DONE_TIMESTAMP", + "msg.sender", + "_timestamps", + "_roles", + "role", + "account", + "EXECUTOR_ROLE" + ], + "state_variables_written": [ + "_timestamps" + ], + "immutables_and_constants": [ + { + "name": "EXECUTOR_ROLE", + "slot": "keccak256(bytes)(EXECUTOR_ROLE)" + }, + { + "name": "_DONE_TIMESTAMP", + "slot": "uint256(1)" + } + ], + "_roles": "0000000000000000000000000000000000000000000000000000000000000000", + "_timestamps": 0 + }, + { + "Function": "grantRole", + "Modifiers": [ + "getRoleAdmin", + "onlyRole" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "account", + "msg.sender", + "_roles", + "role" + ], + "state_variables_written": [ + "_roles" + ], + "_roles": "0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "Function": "revokeRole", + "Modifiers": [ + "getRoleAdmin", + "onlyRole" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "account", + "msg.sender", + "_roles", + "role" + ], + "state_variables_written": [ + "_roles" + ], + "_roles": "0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "storage_values": { + "_roles": "0000000000000000000000000000000000000000000000000000000000000000", + "_timestamps": 0, + "_minDelay": 64800 + } + } + }, + "OstiumTradingCallbacks": { + "Implementation_Address": "0x9214159e33a48a252203fb47ba513b272b888f7d", + "Proxy_Address": "0x7720fc8c8680bf4a1af99d44c6c265a74e9742a9", + "proxy_permissions": { + "Contract_Name": "TransparentUpgradeableProxy", + "Functions": [ + { + "Function": "fallback", + "Modifiers": [], + "msg.sender_conditions": [ + "msg.sender == _getAdmin()" + ], + "state_variables_read": [ + "_IMPLEMENTATION_SLOT", + "_ADMIN_SLOT" + ], + "state_variables_written": [] + }, + { + "Function": "receive", + "Modifiers": [], + "msg.sender_conditions": [ + "msg.sender == _getAdmin()" + ], + "state_variables_read": [ + "_IMPLEMENTATION_SLOT", + "_ADMIN_SLOT" + ], + "state_variables_written": [] + }, + { + "Function": "_fallback", + "Modifiers": [], + "msg.sender_conditions": [ + "msg.sender == _getAdmin()" + ], + "state_variables_read": [ + "_IMPLEMENTATION_SLOT", + "_ADMIN_SLOT" + ], + "state_variables_written": [] + } + ] + }, + "permissions": { + "Contract_Name": "OstiumTradingCallbacks", + "Functions": [ + { + "Function": "initialize", + "Modifiers": [ + "initializer" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "$", + "INITIALIZABLE_STORAGE", + "construction", + "TMP_1042", + "isTopLevelCall", + "initialized", + "this", + "initialSetup", + "slot" + ], + "state_variables_written": [ + "maxSl_P", + "registry" + ], + "immutables_and_constants": [ + { + "name": "INITIALIZABLE_STORAGE", + "slot": "0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00" + } + ] + }, + { + "Function": "isGov", + "Modifiers": [], + "msg.sender_conditions": [ + "msg.sender != registry.gov()" + ], + "state_variables_read": [ + "registry" + ], + "state_variables_written": [], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2" + }, + { + "Function": "isManager", + "Modifiers": [], + "msg.sender_conditions": [ + "msg.sender != registry.manager()" + ], + "state_variables_read": [ + "registry" + ], + "state_variables_written": [], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2" + }, + { + "Function": "isPriceUpKeep", + "Modifiers": [], + "msg.sender_conditions": [ + "msg.sender != registry.getContractAddress(bytes32(abi.encodePacked(priceUpkeepType,PriceUpkeep)))" + ], + "state_variables_read": [ + "registry" + ], + "state_variables_written": [], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2" + }, + { + "Function": "isTrading", + "Modifiers": [], + "msg.sender_conditions": [ + "msg.sender != registry.getContractAddress(trading)" + ], + "state_variables_read": [ + "registry" + ], + "state_variables_written": [], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2" + }, + { + "Function": "setMaxSl_P", + "Modifiers": [ + "onlyGov" + ], + "msg.sender_conditions": [ + "msg.sender != registry.gov()" + ], + "state_variables_read": [ + "registry", + "msg.sender" + ], + "state_variables_written": [ + "maxSl_P" + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2" + }, + { + "Function": "setCloseFeeParams", + "Modifiers": [ + "onlyGov" + ], + "msg.sender_conditions": [ + "msg.sender != registry.gov()" + ], + "state_variables_read": [ + "registry", + "CLOSE_FEE_WINDOW_MAX", + "closeFeeStartingP", + "msg.sender", + "CLOSE_FEE_P_MAX", + "closeFeeDecayWindow" + ], + "state_variables_written": [ + "closeFeeStartingP", + "closeFeeDecayWindow" + ], + "immutables_and_constants": [ + { + "name": "CLOSE_FEE_WINDOW_MAX", + "slot": "300" + }, + { + "name": "CLOSE_FEE_P_MAX", + "slot": "100e6" + } + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "closeFeeDecayWindow": 15, + "closeFeeStartingP": 400000 + }, + { + "Function": "setVaultMaxAllowance", + "Modifiers": [ + "onlyGov" + ], + "msg.sender_conditions": [ + "msg.sender != registry.gov()" + ], + "state_variables_read": [ + "registry", + "msg.sender" + ], + "state_variables_written": [], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2" + }, + { + "Function": "unsetVaultMaxAllowance", + "Modifiers": [ + "onlyGov" + ], + "msg.sender_conditions": [ + "msg.sender != registry.gov()" + ], + "state_variables_read": [ + "registry", + "msg.sender" + ], + "state_variables_written": [], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2" + }, + { + "Function": "pause", + "Modifiers": [ + "onlyManager" + ], + "msg.sender_conditions": [ + "msg.sender != registry.manager()" + ], + "state_variables_read": [ + "registry", + "msg.sender", + "isPaused" + ], + "state_variables_written": [ + "isPaused" + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "isPaused": false + }, + { + "Function": "done", + "Modifiers": [ + "onlyGov" + ], + "msg.sender_conditions": [ + "msg.sender != registry.gov()" + ], + "state_variables_read": [ + "registry", + "msg.sender", + "isDone" + ], + "state_variables_written": [ + "isDone" + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "isDone": false + }, + { + "Function": "openTradeMarketCallback", + "Modifiers": [ + "notDone" + ], + "msg.sender_conditions": [ + "msg.sender != registry.getContractAddress(bytes32(abi.encodePacked(priceUpkeepType,PriceUpkeep)))" + ], + "state_variables_read": [ + "PRECISION_10", + "isPaused", + "registry", + "MAX_GAIN_P", + "PRECISION_18", + "MAX_DECAY_FACTOR", + "isDone", + "PRECISION_27", + "PRECISION_6", + "maxSl_P" + ], + "state_variables_written": [], + "immutables_and_constants": [ + { + "name": "PRECISION_18", + "slot": "1e18" + }, + { + "name": "PRECISION_6", + "slot": "1e6" + } + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "maxSl_P": 100, + "isPaused": false, + "isDone": false + }, + { + "Function": "closeTradeMarketCallback", + "Modifiers": [ + "notDone" + ], + "msg.sender_conditions": [ + "msg.sender != registry.getContractAddress(bytes32(abi.encodePacked(priceUpkeepType,PriceUpkeep)))" + ], + "state_variables_read": [ + "PRECISION_10", + "CLOSE_FEE_SCALE_FACTOR", + "registry", + "closeFeeStartingP", + "MAX_GAIN_P", + "PRECISION_18", + "MAX_DECAY_FACTOR", + "isDone", + "PRECISION_27", + "PRECISION_6", + "closeFeeDecayWindow" + ], + "state_variables_written": [], + "immutables_and_constants": [ + { + "name": "PRECISION_18", + "slot": "1e18" + }, + { + "name": "PRECISION_6", + "slot": "1e6" + } + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "isDone": false, + "closeFeeDecayWindow": 15, + "closeFeeStartingP": 400000 + }, + { + "Function": "executeAutomationOpenOrderCallback", + "Modifiers": [ + "notDone" + ], + "msg.sender_conditions": [ + "msg.sender != registry.getContractAddress(bytes32(abi.encodePacked(priceUpkeepType,PriceUpkeep)))" + ], + "state_variables_read": [ + "PRECISION_10", + "isPaused", + "registry", + "MAX_GAIN_P", + "PRECISION_18", + "MAX_DECAY_FACTOR", + "isDone", + "PRECISION_27", + "PRECISION_6", + "maxSl_P" + ], + "state_variables_written": [], + "immutables_and_constants": [ + { + "name": "PRECISION_18", + "slot": "1e18" + }, + { + "name": "PRECISION_6", + "slot": "1e6" + } + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "maxSl_P": 100, + "isPaused": false, + "isDone": false + }, + { + "Function": "executeAutomationCloseOrderCallback", + "Modifiers": [ + "notDone" + ], + "msg.sender_conditions": [ + "msg.sender != registry.getContractAddress(bytes32(abi.encodePacked(priceUpkeepType,PriceUpkeep)))" + ], + "state_variables_read": [ + "PRECISION_10", + "CLOSE_FEE_SCALE_FACTOR", + "registry", + "closeFeeStartingP", + "MAX_GAIN_P", + "PRECISION_18", + "MAX_DECAY_FACTOR", + "isDone", + "PRECISION_27", + "PRECISION_6", + "closeFeeDecayWindow" + ], + "state_variables_written": [], + "immutables_and_constants": [ + { + "name": "PRECISION_18", + "slot": "1e18" + }, + { + "name": "PRECISION_6", + "slot": "1e6" + } + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "isDone": false, + "closeFeeDecayWindow": 15, + "closeFeeStartingP": 400000 + }, + { + "Function": "handleRemoveCollateral", + "Modifiers": [ + "notDone" + ], + "msg.sender_conditions": [ + "msg.sender != registry.getContractAddress(bytes32(abi.encodePacked(priceUpkeepType,PriceUpkeep)))" + ], + "state_variables_read": [ + "PRECISION_10", + "isPaused", + "registry", + "MAX_GAIN_P", + "PRECISION_18", + "MAX_DECAY_FACTOR", + "isDone", + "PRECISION_27", + "PRECISION_6", + "maxSl_P" + ], + "state_variables_written": [], + "immutables_and_constants": [ + { + "name": "PRECISION_18", + "slot": "1e18" + }, + { + "name": "PRECISION_6", + "slot": "1e6" + } + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "maxSl_P": 100, + "isPaused": false, + "isDone": false + } + ], + "storage_values": { + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "maxSl_P": 100, + "isPaused": false, + "isDone": false, + "closeFeeDecayWindow": 15, + "closeFeeStartingP": 400000 + } + } + }, + "OstiumTradingStorage": { + "Implementation_Address": "0xd40c55475d4fea67415cd12abc28c949fc7a7fee", + "Proxy_Address": "0xccd5891083a8acd2074690f65d3024e7d13d66e7", + "proxy_permissions": { + "Contract_Name": "TransparentUpgradeableProxy", + "Functions": [ + { + "Function": "fallback", + "Modifiers": [], + "msg.sender_conditions": [ + "msg.sender == _getAdmin()" + ], + "state_variables_read": [ + "_IMPLEMENTATION_SLOT", + "_ADMIN_SLOT" + ], + "state_variables_written": [] + }, + { + "Function": "receive", + "Modifiers": [], + "msg.sender_conditions": [ + "msg.sender == _getAdmin()" + ], + "state_variables_read": [ + "_IMPLEMENTATION_SLOT", + "_ADMIN_SLOT" + ], + "state_variables_written": [] + }, + { + "Function": "_fallback", + "Modifiers": [], + "msg.sender_conditions": [ + "msg.sender == _getAdmin()" + ], + "state_variables_read": [ + "_IMPLEMENTATION_SLOT", + "_ADMIN_SLOT" + ], + "state_variables_written": [] + } + ] + }, + "permissions": { + "Contract_Name": "OstiumTradingStorage", + "Functions": [ + { + "Function": "initialize", + "Modifiers": [ + "initializer" + ], + "msg.sender_conditions": [], + "state_variables_read": [ + "$", + "INITIALIZABLE_STORAGE", + "construction", + "isTopLevelCall", + "initialized", + "this", + "initialSetup", + "slot", + "TMP_607" + ], + "state_variables_written": [ + "maxTradesPerPair", + "maxPendingMarketOrders", + "usdc", + "registry" + ], + "immutables_and_constants": [ + { + "name": "INITIALIZABLE_STORAGE", + "slot": "0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00" + } + ] + }, + { + "Function": "_onlyGov", + "Modifiers": [], + "msg.sender_conditions": [ + "msg.sender != registry.gov()" + ], + "state_variables_read": [ + "registry" + ], + "state_variables_written": [], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2" + }, + { + "Function": "_onlyTrading", + "Modifiers": [], + "msg.sender_conditions": [ + "msg.sender != registry.getContractAddress(trading)" + ], + "state_variables_read": [ + "registry" + ], + "state_variables_written": [], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2" + }, + { + "Function": "_onlyCallbacks", + "Modifiers": [], + "msg.sender_conditions": [ + "msg.sender != registry.getContractAddress(callbacks)" + ], + "state_variables_read": [ + "registry" + ], + "state_variables_written": [], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2" + }, + { + "Function": "_onlyManager", + "Modifiers": [], + "msg.sender_conditions": [ + "msg.sender != registry.manager()" + ], + "state_variables_read": [ + "registry" + ], + "state_variables_written": [], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2" + }, + { + "Function": "_onlyTradingOrCallbacks", + "Modifiers": [], + "msg.sender_conditions": [ + "msg.sender != registry.getContractAddress(trading) && msg.sender != registry.getContractAddress(callbacks)" + ], + "state_variables_read": [ + "registry" + ], + "state_variables_written": [], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2" + }, + { + "Function": "setMaxTradesPerPair", + "Modifiers": [ + "onlyGov" + ], + "msg.sender_conditions": [ + "msg.sender != registry.gov()" + ], + "state_variables_read": [ + "registry", + "msg.sender" + ], + "state_variables_written": [ + "maxTradesPerPair" + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2" + }, + { + "Function": "setMaxPendingMarketOrders", + "Modifiers": [ + "onlyGov" + ], + "msg.sender_conditions": [ + "msg.sender != registry.gov()" + ], + "state_variables_read": [ + "registry", + "msg.sender" + ], + "state_variables_written": [ + "maxPendingMarketOrders" + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2" + }, + { + "Function": "setMaxOIKeeper", + "Modifiers": [ + "onlyManager" + ], + "msg.sender_conditions": [ + "msg.sender != registry.manager()" + ], + "state_variables_read": [ + "registry", + "msg.sender" + ], + "state_variables_written": [ + "maxOIKeeper" + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2" + }, + { + "Function": "setMaxOpenInterest", + "Modifiers": [ + "onlyManagerOrMaxOIKeeper" + ], + "msg.sender_conditions": [ + "msg.sender != maxOIKeeper && msg.sender != registry.manager()", + "msg.sender != maxOIKeeper && msg.sender != registry.manager()" + ], + "state_variables_read": [ + "registry", + "msg.sender", + "maxOIKeeper" + ], + "state_variables_written": [ + "openInterest" + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "maxOIKeeper": "0x8fD1694eA641F5E16749Ab6Ab17Dd9001AB2C1b0" + }, + { + "Function": "setMaxOpenInterestArray", + "Modifiers": [ + "onlyManagerOrMaxOIKeeper" + ], + "msg.sender_conditions": [ + "msg.sender != maxOIKeeper && msg.sender != registry.manager()", + "msg.sender != maxOIKeeper && msg.sender != registry.manager()" + ], + "state_variables_read": [ + "registry", + "msg.sender", + "maxOIKeeper" + ], + "state_variables_written": [ + "openInterest" + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "maxOIKeeper": "0x8fD1694eA641F5E16749Ab6Ab17Dd9001AB2C1b0" + }, + { + "Function": "storeTrade", + "Modifiers": [ + "onlyCallbacks" + ], + "msg.sender_conditions": [ + "msg.sender != registry.getContractAddress(callbacks)" + ], + "state_variables_read": [ + "registry", + "msg.sender", + "openTrades", + "openInterest", + "openTradesCount", + "maxTradesPerPair", + "totalOpenTradesCount", + "pairTraders" + ], + "state_variables_written": [ + "pairTraders", + "openTradesCount", + "pairTradersId", + "openTrades", + "totalOpenTradesCount", + "openTradesInfo" + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "totalOpenTradesCount": 1892, + "maxTradesPerPair": 100, + "openTrades": 0, + "openTradesCount": 0, + "pairTraders": 0, + "openInterest": 0 + }, + { + "Function": "unregisterTrade", + "Modifiers": [ + "onlyCallbacks" + ], + "msg.sender_conditions": [ + "msg.sender != registry.getContractAddress(callbacks)" + ], + "state_variables_read": [ + "registry", + "orderTriggerBlock", + "openTradesInfo", + "msg.sender", + "openTrades", + "openInterest", + "pairTradersId", + "openTradesCount", + "totalOpenTradesCount", + "pairTraders" + ], + "state_variables_written": [ + "openTradesCount", + "pairTradersId", + "openTrades", + "totalOpenTradesCount", + "openTradesInfo", + "orderTriggerBlock" + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "totalOpenTradesCount": 1892, + "openTrades": 0, + "openTradesInfo": 0, + "openTradesCount": 0, + "orderTriggerBlock": 0, + "pairTraders": 0, + "pairTradersId": 0, + "openInterest": 0 + }, + { + "Function": "storePendingMarketOrder", + "Modifiers": [ + "onlyTrading" + ], + "msg.sender_conditions": [ + "msg.sender != registry.getContractAddress(trading)" + ], + "state_variables_read": [ + "registry", + "ARBITRUM_MAINNET", + "pendingMarketCloseCount", + "pendingMarketOpenCount", + "msg.sender", + "pendingOrderIds", + "ARBITRUM_SEPOLIA", + "ARBITRUM_GOERLI", + "reqID_pendingMarketOrder", + "ARB_SYS" + ], + "state_variables_written": [ + "builderData", + "pendingOrderIds", + "pendingMarketOpenCount", + "reqID_pendingMarketOrder", + "pendingMarketCloseCount" + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "reqID_pendingMarketOrder": 0, + "pendingOrderIds": 0, + "pendingMarketOpenCount": 0, + "pendingMarketCloseCount": 0 + }, + { + "Function": "storePendingMarketCloseTradeId", + "Modifiers": [ + "onlyTrading" + ], + "msg.sender_conditions": [ + "msg.sender != registry.getContractAddress(trading)" + ], + "state_variables_read": [ + "registry", + "msg.sender" + ], + "state_variables_written": [ + "pendingMarketCloseTradeIds" + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2" + }, + { + "Function": "unregisterPendingMarketOrder", + "Modifiers": [ + "onlyTradingOrCallbacks" + ], + "msg.sender_conditions": [ + "msg.sender != registry.getContractAddress(trading) && msg.sender != registry.getContractAddress(callbacks)" + ], + "state_variables_read": [ + "registry", + "pendingMarketCloseCount", + "pendingMarketOpenCount", + "pendingMarketCloseTradeIds", + "msg.sender", + "pendingOrderIds", + "builderData", + "reqID_pendingMarketOrder" + ], + "state_variables_written": [ + "pendingMarketCloseTradeIds", + "builderData", + "pendingMarketOpenCount", + "reqID_pendingMarketOrder", + "pendingMarketCloseCount" + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "reqID_pendingMarketOrder": 0, + "pendingOrderIds": 0, + "pendingMarketOpenCount": 0, + "pendingMarketCloseCount": 0, + "builderData": 0, + "pendingMarketCloseTradeIds": 0 + }, + { + "Function": "storeOpenLimitOrder", + "Modifiers": [ + "onlyTrading" + ], + "msg.sender_conditions": [ + "msg.sender != registry.getContractAddress(trading)" + ], + "state_variables_read": [ + "registry", + "limitOrderIdCounter", + "pairLimitOrders", + "msg.sender", + "openLimitOrdersCount" + ], + "state_variables_written": [ + "builderData", + "pairLimitOrders", + "openLimitOrderIds", + "limitOrderIdCounter", + "openLimitOrdersCount", + "limitOrderIds" + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "openLimitOrdersCount": 0, + "pairLimitOrders": 0, + "limitOrderIdCounter": 21134 + }, + { + "Function": "updateOpenLimitOrder", + "Modifiers": [ + "onlyTrading" + ], + "msg.sender_conditions": [ + "msg.sender != registry.getContractAddress(trading)" + ], + "state_variables_read": [ + "registry", + "msg.sender", + "pairLimitOrders", + "openLimitOrderIds" + ], + "state_variables_written": [ + "pairLimitOrders" + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "openLimitOrderIds": 0, + "pairLimitOrders": 0 + }, + { + "Function": "unregisterOpenLimitOrder", + "Modifiers": [ + "onlyTradingOrCallbacks" + ], + "msg.sender_conditions": [ + "msg.sender != registry.getContractAddress(trading) && msg.sender != registry.getContractAddress(callbacks)" + ], + "state_variables_read": [ + "registry", + "limitOrderIds", + "pairLimitOrders", + "msg.sender", + "openLimitOrderIds", + "openLimitOrdersCount", + "builderData" + ], + "state_variables_written": [ + "builderData", + "pairLimitOrders", + "openLimitOrderIds", + "openLimitOrdersCount", + "limitOrderIds" + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "openLimitOrderIds": 0, + "openLimitOrdersCount": 0, + "pairLimitOrders": 0, + "builderData": 0, + "limitOrderIds": 0 + }, + { + "Function": "setTrigger", + "Modifiers": [ + "onlyTrading" + ], + "msg.sender_conditions": [ + "msg.sender != registry.getContractAddress(trading)" + ], + "state_variables_read": [ + "registry", + "ARBITRUM_MAINNET", + "msg.sender", + "ARBITRUM_SEPOLIA", + "ARBITRUM_GOERLI", + "ARB_SYS" + ], + "state_variables_written": [ + "orderTriggerBlock" + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2" + }, + { + "Function": "unregisterTrigger", + "Modifiers": [ + "onlyTradingOrCallbacks" + ], + "msg.sender_conditions": [ + "msg.sender != registry.getContractAddress(trading) && msg.sender != registry.getContractAddress(callbacks)" + ], + "state_variables_read": [ + "registry", + "msg.sender", + "orderTriggerBlock" + ], + "state_variables_written": [ + "orderTriggerBlock" + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "orderTriggerBlock": 0 + }, + { + "Function": "clearDeprecatedBeingMarketClosed", + "Modifiers": [ + "onlyTradingOrCallbacks" + ], + "msg.sender_conditions": [ + "msg.sender != registry.getContractAddress(trading) && msg.sender != registry.getContractAddress(callbacks)" + ], + "state_variables_read": [ + "registry", + "openTradesInfo", + "msg.sender" + ], + "state_variables_written": [ + "openTradesInfo" + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "openTradesInfo": 0 + }, + { + "Function": "storePendingAutomationOrder", + "Modifiers": [ + "onlyTrading" + ], + "msg.sender_conditions": [ + "msg.sender != registry.getContractAddress(trading)" + ], + "state_variables_read": [ + "registry", + "msg.sender" + ], + "state_variables_written": [ + "reqID_pendingAutomationOrder" + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2" + }, + { + "Function": "unregisterPendingAutomationOrder", + "Modifiers": [ + "onlyCallbacks" + ], + "msg.sender_conditions": [ + "msg.sender != registry.getContractAddress(callbacks)" + ], + "state_variables_read": [ + "registry", + "msg.sender", + "reqID_pendingAutomationOrder" + ], + "state_variables_written": [ + "reqID_pendingAutomationOrder" + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "reqID_pendingAutomationOrder": 0 + }, + { + "Function": "updateSl", + "Modifiers": [ + "onlyTrading" + ], + "msg.sender_conditions": [ + "msg.sender != registry.getContractAddress(trading)" + ], + "state_variables_read": [ + "registry", + "openTradesInfo", + "msg.sender", + "openTrades" + ], + "state_variables_written": [ + "openTrades", + "openTradesInfo" + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "openTrades": 0, + "openTradesInfo": 0 + }, + { + "Function": "updateTp", + "Modifiers": [ + "onlyTrading" + ], + "msg.sender_conditions": [ + "msg.sender != registry.getContractAddress(trading)" + ], + "state_variables_read": [ + "registry", + "openTradesInfo", + "msg.sender", + "openTrades" + ], + "state_variables_written": [ + "openTrades", + "openTradesInfo" + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "openTrades": 0, + "openTradesInfo": 0 + }, + { + "Function": "updateTrade", + "Modifiers": [ + "onlyTradingOrCallbacks" + ], + "msg.sender_conditions": [ + "msg.sender != registry.getContractAddress(trading) && msg.sender != registry.getContractAddress(callbacks)" + ], + "state_variables_read": [ + "registry", + "openTradesInfo", + "msg.sender", + "openTrades" + ], + "state_variables_written": [ + "openTrades", + "openTradesInfo" + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "openTrades": 0, + "openTradesInfo": 0 + }, + { + "Function": "handleOpeningFees", + "Modifiers": [ + "onlyCallbacks" + ], + "msg.sender_conditions": [ + "msg.sender != registry.getContractAddress(callbacks)" + ], + "state_variables_read": [ + "registry", + "devFees", + "msg.sender", + "PRECISION_18", + "openInterest" + ], + "state_variables_written": [ + "devFees" + ], + "immutables_and_constants": [ + { + "name": "PRECISION_18", + "slot": "1e18" + } + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "devFees": 245614979632, + "openInterest": 0 + }, + { + "Function": "handleOracleFee", + "Modifiers": [ + "onlyTradingOrCallbacks" + ], + "msg.sender_conditions": [ + "msg.sender != registry.getContractAddress(trading) && msg.sender != registry.getContractAddress(callbacks)" + ], + "state_variables_read": [ + "registry", + "msg.sender", + "devFees" + ], + "state_variables_written": [ + "devFees" + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "devFees": 245614979632 + }, + { + "Function": "refundOracleFee", + "Modifiers": [ + "onlyTradingOrCallbacks" + ], + "msg.sender_conditions": [ + "msg.sender != registry.getContractAddress(trading) && msg.sender != registry.getContractAddress(callbacks)" + ], + "state_variables_read": [ + "registry", + "msg.sender", + "devFees" + ], + "state_variables_written": [ + "devFees" + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "devFees": 245614979632 + }, + { + "Function": "claimFees", + "Modifiers": [ + "onlyGov" + ], + "msg.sender_conditions": [ + "msg.sender != registry.gov()" + ], + "state_variables_read": [ + "registry", + "msg.sender", + "devFees", + "usdc" + ], + "state_variables_written": [ + "devFees" + ], + "usdc": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831", + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "devFees": 245614979632 + }, + { + "Function": "transferUsdc", + "Modifiers": [ + "onlyTradingOrCallbacks" + ], + "msg.sender_conditions": [ + "msg.sender != registry.getContractAddress(trading) && msg.sender != registry.getContractAddress(callbacks)" + ], + "state_variables_read": [ + "registry", + "msg.sender", + "usdc" + ], + "state_variables_written": [], + "usdc": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831", + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2" + }, + { + "Function": "storePendingRemoveCollateral", + "Modifiers": [ + "onlyTrading" + ], + "msg.sender_conditions": [ + "msg.sender != registry.getContractAddress(trading)" + ], + "state_variables_read": [ + "registry", + "msg.sender" + ], + "state_variables_written": [ + "reqID_pendingRemoveCollateral" + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2" + }, + { + "Function": "unregisterPendingRemoveCollateral", + "Modifiers": [ + "onlyCallbacks" + ], + "msg.sender_conditions": [ + "msg.sender != registry.getContractAddress(callbacks)" + ], + "state_variables_read": [ + "registry", + "reqID_pendingRemoveCollateral", + "msg.sender" + ], + "state_variables_written": [ + "reqID_pendingRemoveCollateral" + ], + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "reqID_pendingRemoveCollateral": 0 + } + ], + "storage_values": { + "usdc": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831", + "registry": "799a139ae56e11f0476ace2f6118cfcaed9608d2", + "devFees": 245614979632, + "totalOpenTradesCount": 1892, + "maxTradesPerPair": 100, + "openTrades": 0, + "openTradesInfo": 0, + "openTradesCount": 0, + "openLimitOrderIds": 0, + "openLimitOrdersCount": 0, + "orderTriggerBlock": 0, + "pairLimitOrders": 0, + "reqID_pendingMarketOrder": 0, + "reqID_pendingAutomationOrder": 0, + "pendingOrderIds": 0, + "pendingMarketOpenCount": 0, + "pendingMarketCloseCount": 0, + "pairTraders": 0, + "pairTradersId": 0, + "openInterest": 0, + "reqID_pendingRemoveCollateral": 0, + "builderData": 0, + "limitOrderIdCounter": 21134, + "limitOrderIds": 0, + "pendingMarketCloseTradeIds": 0, + "maxOIKeeper": "0x8fD1694eA641F5E16749Ab6Ab17Dd9001AB2C1b0" + } + } + } +} \ No newline at end of file diff --git a/harnesses/permissions-scan/targets/vertex/contracts.json b/harnesses/permissions-scan/targets/vertex/contracts.json new file mode 100644 index 00000000..a51a1071 --- /dev/null +++ b/harnesses/permissions-scan/targets/vertex/contracts.json @@ -0,0 +1,77 @@ +{ + "chain": "arbi", + "project": "vertex", + "addresses": [ + "0xbbee07b3e8121227afcfe1e2b82772246226128e", + "0xae1ec28d6225dce2ff787dcb8ce11cf6d3ae064f", + "0x32d91af2b17054d575a7bf1acfa7615f41ccefab", + "0xb74c78cca0fadafbee52b2f48a67ee8c834b5fd1", + "0xa4369d8e3dc847aedf17f4125f1abb1bc18fc060", + "0x1693273b443699bee277ecbc60e2c8027e91995d", + "0x2BC1F3512C372F54D987B1de7A6EB72DFdF61533" + ], + "sources": [ + { + "address": "0xbbee07b3e8121227afcfe1e2b82772246226128e", + "label": "Endpoint", + "found_at": "https://arbiscan.io/search?q=vertex+endpoint (label: 'Vertex Protocol: Endpoint')", + "consulted_at": "2026-08-02T19:08:53Z", + "is_proxy": true, + "proxy_type": "EIP-1967", + "implementation": "0x91ffc881837ffb3eec0c62e19675425ee3a38c74", + "impl_slot_read": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + }, + { + "address": "0xae1ec28d6225dce2ff787dcb8ce11cf6d3ae064f", + "label": "Clearinghouse", + "found_at": "https://arbiscan.io/search?q=vertex+endpoint (label: 'Vertex Protocol: Clearinghouse')", + "consulted_at": "2026-08-02T19:08:53Z", + "is_proxy": true, + "proxy_type": "EIP-1967", + "implementation": "0x63a49718d19d8182bf20fc135372c2f84a0586bf", + "impl_slot_read": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + }, + { + "address": "0x32d91af2b17054d575a7bf1acfa7615f41ccefab", + "label": "SpotEngine", + "found_at": "https://arbiscan.io/search?q=vertex+endpoint (label: 'Vertex Protocol: Spot Engine')", + "consulted_at": "2026-08-02T19:08:53Z", + "is_proxy": false, + "implementation": null + }, + { + "address": "0xb74c78cca0fadafbee52b2f48a67ee8c834b5fd1", + "label": "PerpEngine", + "found_at": "https://arbiscan.io/search?q=vertex+endpoint (label: 'Vertex Protocol: Perp Engine')", + "consulted_at": "2026-08-02T19:08:53Z", + "is_proxy": false, + "implementation": null + }, + { + "address": "0xa4369d8e3dc847aedf17f4125f1abb1bc18fc060", + "label": "OffchainExchange", + "found_at": "https://arbiscan.io/search?q=vertex+endpoint (label: 'Vertex Protocol: Offchain Exchange')", + "consulted_at": "2026-08-02T19:08:53Z", + "is_proxy": false, + "implementation": null + }, + { + "address": "0x1693273b443699bee277ecbc60e2c8027e91995d", + "label": "Querier", + "found_at": "https://arbiscan.io/search?q=vertex+endpoint (label: 'Vertex Protocol: Querier')", + "consulted_at": "2026-08-02T19:08:53Z", + "is_proxy": false, + "implementation": null + }, + { + "address": "0x2BC1F3512C372F54D987B1de7A6EB72DFdF61533", + "label": "Endpoint owner (proxy, wraps Gnosis Safe)", + "found_at": "cast call Endpoint owner() on-chain", + "consulted_at": "2026-08-02T19:08:53Z", + "is_proxy": true, + "proxy_type": "EIP-1967", + "implementation": "0xb7eb64ae8cfa83f66b19da0522d672f6adcb7529", + "note": "This proxy wraps a contract whose owner() returns 0xC6B129179B68F9dF026AFA3914ef504C498c5bC4 (Gnosis Safe 4/6)." + } + ] +} diff --git a/src/lib/format.ts b/src/lib/format.ts index 7879d82c..db9efb00 100644 --- a/src/lib/format.ts +++ b/src/lib/format.ts @@ -73,6 +73,13 @@ export function fmtUnit(value: number, unit: string) { } return `${value.toFixed(0)} slots`; } + if (unit === "x") { + // Dimensionless ratio (e.g. cost-slope $1M / $1k). Show 2 decimal places + // for values < 10, 1 decimal for larger. + if (!Number.isFinite(value) || value === 0) return "1.00x"; + if (value < 10) return `${value.toFixed(2)}x`; + return `${value.toFixed(1)}x`; + } if (unit === "count") { // Sub-unit values are common when a "count" bench is measuring an // error or gap that converges toward zero (e.g. gas-oracle prediction @@ -164,6 +171,7 @@ export function unitSuffix(unit: string, value?: number): string { return " ms"; } if (unit === "slots") return " slots"; + if (unit === "x") return "x"; if (unit === "count") return ""; if (unit === "gwei") return " gwei"; if (unit === "usd") return ""; diff --git a/src/lib/spec-schema.ts b/src/lib/spec-schema.ts index 327774c1..b2d9018f 100644 --- a/src/lib/spec-schema.ts +++ b/src/lib/spec-schema.ts @@ -249,7 +249,7 @@ export const SpecSchema = z /* Metric */ metric: z.string().min(1).max(100), /** ms / s for latencies; pct for fees as percent of notional; bps for basis points; slots for Solana slot delta. */ - unit: z.enum(["ms", "s", "sec", "pct", "bps", "bp", "count", "slots", "usd", "gwei"]), + unit: z.enum(["ms", "s", "sec", "pct", "bps", "bp", "count", "slots", "usd", "gwei", "x"]), /** True when bigger numbers are better (coverage, count). Default false: * latency, fees, drift. every existing bench is "lower is better". */ higher_is_better: z.boolean().default(false), @@ -440,7 +440,7 @@ export const SpecSchema = z /** The PromQL label that holds each provider's slug. Defaults to * "builder"; other benches may use "provider", "venue", etc. */ label_key: z.string().min(1).max(40).default("builder"), - unit: z.enum(["ms", "s", "sec", "pct", "bps", "bp", "count", "slots", "usd", "gwei"]), + unit: z.enum(["ms", "s", "sec", "pct", "bps", "bp", "count", "slots", "usd", "gwei", "x"]), higher_is_better: z.boolean().default(false), /** When false the panel is data-only: it is loaded and can feed * ledger_columns window variants, but renders no chart tab. diff --git a/src/types/benchmark.ts b/src/types/benchmark.ts index b542d1a7..47b3f597 100644 --- a/src/types/benchmark.ts +++ b/src/types/benchmark.ts @@ -139,7 +139,7 @@ export type MetricPanel = { label: string; description?: string; metric: string; - unit: "ms" | "s" | "sec" | "pct" | "bps" | "bp" | "count" | "slots" | "usd" | "gwei"; + unit: "ms" | "s" | "sec" | "pct" | "bps" | "bp" | "count" | "slots" | "usd" | "gwei" | "x"; higherIsBetter: boolean; /** When false the panel is data-only (feeds ledger column window * variants) and renders no chart tab. */ @@ -233,7 +233,7 @@ export type Benchmark = { dataConfidence?: "healthy" | "low" | "insufficient"; abstract: string; metric: string; - unit: "ms" | "s" | "sec" | "pct" | "bps" | "bp" | "count" | "slots" | "usd" | "gwei"; + unit: "ms" | "s" | "sec" | "pct" | "bps" | "bp" | "count" | "slots" | "usd" | "gwei" | "x"; higherIsBetter: boolean; /** Optional drill-down dimensions exposed by the bench. When set, the * bench page renders one tab selector per dimension and the queries get @@ -313,7 +313,7 @@ export type LedgerColumn = { panel?: string; /** Display unit override; defaults to the panel's unit (panel columns) * or the bench unit (slot columns). */ - unit?: "ms" | "s" | "sec" | "pct" | "bps" | "bp" | "count" | "slots" | "usd" | "gwei"; + unit?: "ms" | "s" | "sec" | "pct" | "bps" | "bp" | "count" | "slots" | "usd" | "gwei" | "x"; /** Per-window value sources for the ledger's timeframe toggle: window * key to metric_panels id. Columns without a mapping keep their 24h * value when a longer window is selected. */