You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
-`OracleSettings` is the single truth for configuration: CLI args > environment/`.env` > TOML (`tq-oracle.toml` or `$HOME/.config/tq-oracle/config.toml`). Secrets are rejected from TOML and wrapped in `SecretStr`.
29
30
- Network defaults come from `constants.py` (RPC URLs, OracleHelper contracts, and canonical asset maps for Mainnet, Sepolia, Base). Missing RPC/OracleHelper values are filled automatically; block numbers are resolved via Web3 when absent.
30
31
- The CLI enforces required params (vault address, RPC, Safe creds when `--no-dry-run`) and exposes `--show-config` for redacted inspection before dispatching to `pipeline.run_report()`.
31
32
32
33
### Pipeline Orchestration (`pipeline/run.py`)
34
+
33
35
`run_report()` builds a `PipelineContext` and executes the pipeline sequentially:
34
36
1.**Base asset discovery** – `_discover_base_asset()` walks Vault → FeeManager contracts on the target chain to retrieve the canonical base asset used for pricing.
35
37
2.**Preflight** – `pipeline/preflight.py` runs adapters with backoff/retry to ensure it is safe to proceed.
@@ -38,24 +40,33 @@ flowchart TD
38
40
5.**Report + publish** – packages results and either prints or submits to a Safe.
-**Safe state**: warns/blocks if no Safe configured or if duplicate/pending oracle reports exist (`safe_state.py`, `active_submit_report_proposal_check.py`).
43
+
44
+
-**Active proposal check**: blocks if a duplicate or pending oracle report already exists on the Safe (`active_submit_report_proposal_check.py`); can be bypassed via `--ignore-active-proposal-check`.
42
45
-**Timeout enforcement**: queries the Oracle contract for last report timestamps and security params; can be bypassed via `--ignore-timeout-check` (`timeout_check.py`).
43
46
- Each adapter returns a `CheckResult`, and `run_preflight()` retries failures up to `pre_check_retries` using `backoff` unless the adapter signals `retry_recommended=False`.
- Fetches subvault addresses via Vault ABI calls, validates `subvault_adapters` config entries, and optionally allows synthetic addresses when `skip_subvault_existence_check` is set.
47
-
- Runs the default `IdleBalancesAdapter` across the vault and every subvault (unless skipped per-subvault) to gather on-chain balances for supported assets defined in `OracleSettings.assets`.
48
-
- Additional adapters can be configured per subvault; each adapter inherits from `BaseAssetAdapter` and is registered in `ADAPTER_REGISTRY`.
51
+
- Three default adapters run automatically based on configuration:
52
+
-`IdleBalancesAdapter` – gathers on-chain token balances across vault and all subvaults (skippable per-subvault via `skip_idle_balances`).
53
+
-`StrETHAdapter` – fetches strETH positions (skippable via `skip_streth`).
54
+
-`StakeWiseAdapter` – fetches StakeWise vault positions when `stakewise_vault_addresses` is configured.
55
+
- Additional adapters can be configured per subvault via `additional_adapters`; each adapter inherits from `BaseAssetAdapter` and is registered in `ADAPTER_REGISTRY`.
49
56
- Results are combined asynchronously and folded into `AggregatedAssets` via `processors/asset_aggregator.py`.
- Price adapters are instantiated from `PRICE_ADAPTERS` (currently `CowSwapAdapter` for general assets and `ETHAdapter` for ETH/WETH;).
59
+
60
+
- Price adapters are instantiated from `PRICE_ADAPTERS`:
61
+
-`CowSwapAdapter` – fetches prices from CoW Protocol for general assets.
62
+
-`ETHAdapter` – handles ETH/WETH pricing.
53
63
- Each adapter updates a shared `PriceData` accumulator keyed by asset address (base asset must already be known).
54
-
-`run_price_validations()` invokes validators from `PRICE_VALIDATORS`. The active `PythValidator` re-fetches prices through the Pyth Hermes API, compares deviations against configurable warning/failure tolerances, and can be disabled via `pyth_enabled=False`.
64
+
-`run_price_validations()` invokes validators from `PRICE_VALIDATORS`. The active `PythValidator` re-fetches prices through the Pyth Hermes API and compares deviations against configurable warning/failure tolerances (`price_warning_tolerance_percentage`, `price_failure_tolerance_percentage`).
55
65
-`processors/total_assets.calculate_total_assets()` multiplies balances by prices (18-decimal math) and raises if any asset lacks a quote.
56
66
-`processors/oracle_helper.derive_final_prices()` submits the total asset figure plus encoded prices to the OracleHelper contract to obtain finalized per-asset values (respecting `ignore_empty_vault`).
57
67
58
68
### Reporting & Publishing (`report/*`)
69
+
59
70
-`report/generator.py` converts context data into an `OracleReport` dataclass.
60
71
-`report/encoder.py` encodes `submitReports(Report[] reports)` calldata sorted by address and forces the base asset price to zero, mirroring the Solidity helper expectations.
61
72
-`report/publisher.py`:
@@ -72,6 +83,7 @@ Key `OracleSettings` fields:
72
83
- Pricing knobs: `pyth_*` settings plus warning/failure tolerances.
3. TQ Oracle submits `Report[]` via `Oracle.submitReports()` through a Safe multisig.
205
+
4. Oracle contract validates price deviation and cooldown, then calls `Vault.handleReport()`.
206
+
5. Vault mints fee shares, updates FeeManager state, and propagates price to queues.
207
+
6. Queues convert pending deposits→shares and pending redemptions→assets at the reported price.
208
+
7. Users claim their shares or redeemed assets.
209
+
210
+
TQ Oracle is the off-chain price authority—it computes what the on-chain Oracle consumes. The on-chain Oracle enforces security invariants (max deviation, timeouts, suspicious-report flagging), but relies on TQ Oracle for accurate TVL calculation across all asset positions.
211
+
101
212
## Extension Points
102
213
-**Asset adapters**: Implement `BaseAssetAdapter`, register in `ADAPTER_REGISTRY`, and wire via `subvault_adapters`.
103
214
-**Price adapters**: Implement `BasePriceAdapter` and append to `PRICE_ADAPTERS` to join the pricing chain.
|`--network``-n`|`TQ_ORACLE_NETWORK`|`network`|`"mainnet"`| Network to report on (`mainnet`, `sepolia`, `base`) |
70
-
|`--block-number`|`TQ_ORACLE_BLOCK_NUMBER`|`block_number`| Latest block | Block number to snapshot vault state |
71
-
|`--vault-rpc`|`TQ_ORACLE_VAULT_RPC`|`vault_rpc`| Network default | RPC endpoint for the selected vault network |
72
-
|`--dry-run/--no-dry-run`|`TQ_ORACLE_DRY_RUN`|`dry_run`|`true`| Preview report without submitting a Safe transaction |
73
-
|`--ignore-empty-vault/--require-nonempty-vault`|`TQ_ORACLE_IGNORE_EMPTY_VAULT`|`ignore_empty_vault`|`false`| Skip failure when vault holds zero assets |
74
-
|`--ignore-timeout-check/--enforce-timeout-check`|`TQ_ORACLE_IGNORE_TIMEOUT_CHECK`|`ignore_timeout_check`|`false`| Skip minimum interval guard between reports |
75
-
|`--ignore-active-proposal-check/--enforce-active-proposal-check`|`TQ_ORACLE_IGNORE_ACTIVE_PROPOSAL_CHECK`|`ignore_active_proposal_check`|`false`| Skip duplicate active proposal guard |
├── processors/ # Data aggregation and TVL computation
117
+
├── checks/ # Pre-flight validation orchestration
118
+
├── report/ # Report encoding, generation, and publishing
119
+
├── abis/ # Contract ABIs (JSON)
120
+
└── tests/ # Mirrors src structure
168
121
```
169
122
170
-
## Pre-Flight Checks
171
-
172
-
Before processing TVL data, TQ Oracle runs automated pre-flight validation checks to ensure data integrity:
173
-
174
-
-**Safe State Validation**: Ensures no duplicate or pending reports exist
175
-
-**Check Retry Logic**: Automatically retries failed checks with exponential backoff when recommended
176
-
177
-
These checks prevent race conditions and ensure accurate TVL snapshots by detecting ongoing cross-chain transfers that could affect asset balances. You can bypass individual guards when needed via the CLI flags `--ignore-empty-vault`, `--ignore-timeout-check/--enforce-timeout-check`, and `--ignore-active-proposal-check/--enforce-active-proposal-check`.
178
-
179
-
## Adding New Adapters
180
-
181
-
### Asset Adapters
182
-
183
-
Asset adapters fetch asset holdings from specific protocols (e.g., Aave, Lido).
184
-
185
-
Quick overview:
186
-
187
-
1.**Create adapter file** in `src/tq_oracle/adapters/asset_adapters/` implementing `BaseAssetAdapter`
188
-
2.**Register adapter** in `src/tq_oracle/adapters/asset_adapters/__init__.py`'s `ADAPTER_REGISTRY`
189
-
3.**Write integration tests** in `tests/adapters/asset_adapters/`
190
-
4.**Add asset addresses** to `src/tq_oracle/constants.py` if needed
191
-
192
-
The adapter name in the registry is used in the `[[subvault_adapters]]` configuration's `additional_adapters` field.
193
-
194
-
### Price Adapters
195
-
196
-
Price adapters fetch USD prices for assets from price oracles (e.g., Pyth).
197
-
198
-
1.**Create adapter file** in `src/tq_oracle/adapters/price_adapters/` implementing `BasePriceAdapter`
199
-
2.**Register adapter** in `src/tq_oracle/adapters/price_adapters/__init__.py`'s `PRICE_ADAPTERS` list
200
-
3.**Implement async `fetch_prices()` method** to query oracle and return price data
201
-
4.**Write unit tests** in `tests/adapters/price_adapters/`
202
-
203
-
### Price Validators
204
-
205
-
Price validators cross-check prices from the main price adapters against reference sources to detect anomalies or manipulation. They run after price fetching and can issue warnings or halt execution if prices deviate beyond configured thresholds.
206
-
207
-
1.**Create validator file** in `src/tq_oracle/adapters/price_validators/` implementing `BasePriceValidator`
208
-
2.**Register validator** in `src/tq_oracle/adapters/price_validators/__init__.py`'s `PRICE_VALIDATORS` list
209
-
3.**Implement async `validate_prices()` method** to cross-check prices and return validation results
210
-
4.**Configure tolerance thresholds** in settings for warning and failure levels
211
-
5.**Write unit tests** in `tests/adapters/price_validators/`
212
-
213
-
Validators respect tolerance thresholds configured in `settings.py`:
0 commit comments