Skip to content

Commit 72e36e8

Browse files
committed
Merge branch 'main' into vishal/add_cadence_linter
2 parents 4bff0e3 + 6706158 commit 72e36e8

214 files changed

Lines changed: 18185 additions & 6097 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/cadence_tests.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ jobs:
2828
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
2929
restore-keys: |
3030
${{ runner.os }}-go-
31+
- uses: actions/cache@v4
32+
with:
33+
path: ./imports
34+
key: flow-deps-${{ hashFiles('flow.json') }}
3135
- name: Install Flow CLI
3236
env:
3337
FLOW_CLI_VERSION: v2.7.2

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ coverage.json
77
/.pr-body.md
88
/.github/pr_bodies/
99
lcov.info
10+
.flow-fork-cache

AGENTS.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# FlowALP Top-level Agent Instructions
2+
3+
This document provides top-level information to agents (Claude Code etc.).
4+
**It is loaded into context automatically for all sessions in this repo, so keep it concise!**
5+
6+
# Testing
7+
8+
All Cadence test files are located in:
9+
10+
```
11+
cadence/tests/*_test.cdc
12+
```
13+
14+
## IMPORTANT: Install Dependencies First
15+
16+
**On a fresh clone, you MUST init submodules and install Flow dependencies before running tests:**
17+
18+
```bash
19+
git submodule update --init --recursive
20+
flow deps install
21+
```
22+
23+
## Run All Tests
24+
25+
```bash
26+
./run_tests.sh
27+
```
28+
29+
## Run Individual Test Files
30+
31+
To run a specific test file:
32+
33+
```bash
34+
flow test <path/to/test_file.cdc>
35+
```
36+
37+
**Example:**
38+
```bash
39+
flow test cadence/tests/liquidation_phase1_test.cdc
40+
```
41+
42+
## Run Individual Tests by Name
43+
44+
**IMPORTANT**: To run a specific test function by name, you **must** specify the file path:
45+
46+
```bash
47+
flow test <path/to/test_file.cdc> --name <test_function_name>
48+
```
49+
50+
**Example:**
51+
```bash
52+
# Run a specific test from a multi-test file
53+
flow test cadence/tests/interest_accrual_integration_test.cdc --name test_combined_all_interest_scenarios
54+
```
55+
56+
### Find all tests in a file
57+
```bash
58+
grep "fun test" cadence/tests/interest_accrual_integration_test.cdc
59+
```

CLAUDE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
AGENTS.md

CONTRIBUTING.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# Contributing to the Flow Credit Market Smart Contracts
1+
# Contributing to FlowALP (FlowALP Contracts)
22

3-
The following is a set of guidelines for contributing to Flow Credit Market.
3+
The following is a set of guidelines for contributing to FlowALP (specifically the `FlowALPv0` implementation in this repo).
44
These are mostly guidelines, not rules.
55
Use your best judgment, and feel free to propose changes to this document in a pull request.
66

@@ -125,4 +125,4 @@ Before contributing, make sure to examine the project to get familiar with the p
125125

126126
### Additional Notes
127127

128-
Thank you for your interest in contributing to Flow Credit Market!
128+
Thank you for your interest in contributing to FlowALP!

CadenceTestingPatterns.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
## Cadence Testing Patterns & Best Practices
22

3-
This document distills the patterns, idioms, and general "know-how" exhibited by the experienced Cadence developer who authored the current test-suite for **FlowCreditMarket**. Use it as a practical checklist and style-guide when writing or reviewing Cadence tests.
3+
This document distills the patterns, idioms, and general "know-how" exhibited by the experienced Cadence developer who authored the current test-suite for **FlowALP**. Use it as a practical checklist and style-guide when writing or reviewing Cadence tests.
44

55
### 1. Harness, Organisation & Discovery
66

FlowActions

Submodule FlowActions updated 54 files

FlowVaultsMilestones.md

Lines changed: 0 additions & 106 deletions
This file was deleted.

FutureFeatures.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# FlowCreditMarket Future Features and Tests
1+
# FlowALP Future Features and Tests
22

3-
This document lists features that are not yet implemented in the FlowCreditMarket contract, organized by FlowVaults milestone phases with priority indicators:
3+
This document lists features that are not yet implemented in the `FlowALPv0` contract:
44

55
-**Must Have** - Critical features required for launch
66
- 💛 **Should Have** - Important features that significantly enhance the product
@@ -9,14 +9,16 @@ This document lists features that are not yet implemented in the FlowCreditMarke
99

1010
## Tracer Bullet Phase Features
1111

12-
### 1. ✅ Functional Sink/Source Hooks (Critical for FlowVaults Integration)
12+
### 1. ✅ Functional Sink/Source Hooks (Critical for Integration)
1313

1414
**Features to Implement:**
15+
1516
- Real Sink implementation for pushing tokens to yield strategies
1617
- Real Source implementation for pulling tokens from yield strategies
1718
- Basic rebalancing logic
1819

1920
**Tests to Add (E-series):**
21+
2022
```
2123
E-1: Push to sink on surplus
2224
- Provide StakeSink

PriceOracleArchitecture.md

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
# Price Oracle Architecture
2+
3+
This document describes the price oracle design for the ALP.
4+
How multiple sources are combined into a single trusted oracle interface, and how routing and aggregation are split across two contracts.
5+
6+
## Overview
7+
8+
The protocol depends on a **single trusted oracle** that returns either a valid price or `nil` when the price should not be used (e.g. liquidation or rebalancing should be skipped). The protocol does **not** validate prices; it only consumes the oracle’s result.
9+
10+
Two contracts implement this design:
11+
12+
| Contract | Role |
13+
|----------|------|
14+
| **PriceOracleAggregatorv1** | Combines multiple price sources for **one** market (e.g. several FLOW/USDC oracles). Returns a price only when sources agree within spread tolerance and short-term history is within `baseTolerance` + `driftExpansionRate` (stability). |
15+
| **PriceOracleRouterv1** | Exposes **one** `DeFiActions.PriceOracle` that routes by token type. Each token has its own oracle; typically each oracle is an aggregator. |
16+
17+
Typical usage: create one **aggregator** per market (same token pair, multiple sources), then register each aggregator in a **router** under the corresponding token type. The protocol then uses the router as its single oracle.
18+
19+
### Immutable Configuration
20+
21+
The **Aggregator** and **Router** are immutable by design to eliminate the risks associated with live production changes.
22+
23+
* **Eliminates "Testing in Prod":** Because parameters cannot be modified in place, you avoid the risk of breaking a live oracle. Instead, new configurations can be fully tested as a separate instance before deployment.
24+
* **Centralized Governance:** Changes can only be made by updating the oracle reference on the **ALP**. This makes it explicitly clear who holds governance authority over the system.
25+
* **Timelock Compatibility:** Since updates require a fresh deployment, it is easy to implement an "Escape Period" (Timelock). This introduces a mandatory delay before a new oracle address takes effect, giving users time to react or exit before the change goes live.
26+
* **Transparent Auditing:** Every change is recorded on-chain via the `PriceOracleUpdated` event, ensuring all shifts in logic or parameters are visible and expected.
27+
28+
## PriceOracleAggregatorv1
29+
30+
One aggregated oracle per “market” (e.g. FLOW in USDC). Multiple underlying oracles, single unit of account, fixed tolerances.
31+
- **Price flow:**
32+
1. Collect prices from all oracles for the requested token.
33+
2. If any oracle returns nil → emit `PriceNotAvailable`, return nil.
34+
3. Compute min/max; if spread > `maxSpread` → emit `PriceNotWithinSpreadTolerance`, return nil.
35+
4. Compute aggregated price as the arithmetic mean of all oracle prices.
36+
5. Check short-term stability: compare current price to recent history; for each history entry the allowed relative difference is `baseTolerance + driftExpansionRate * deltaTMinutes`; if any relative difference exceeds that → emit `PriceNotWithinHistoryTolerance`, return nil.
37+
6. Otherwise return the aggregated price.
38+
- **History:** An array of `(price, timestamp)` is maintained. Updates are permissionless via `tryAddPriceToHistory()` (idempotent); A FlowCron job should be created to call this regularly.
39+
Additionally every call to price() will also attempt to store the price in the history.
40+
41+
## Aggregate price (average)
42+
43+
The aggregator uses the **arithmetic mean** of all oracle prices:
44+
45+
- **Average:** `sum(prices) / count`. Same for any number of oracles (1, 2, 3+).
46+
47+
## Oracle spread (coherence)
48+
49+
A **pessimistic relative spread** is used: the distance between the most extreme oracle prices relative to the **minimum** price.
50+
51+
$$
52+
\text{Spread} = \frac{Price_{\max} - Price_{\min}}{Price_{\min}}
53+
$$
54+
55+
The price set is **coherent** only if:
56+
57+
$$
58+
\text{isCoherent} =
59+
\begin{cases}
60+
\text{true} & \text{if } \frac{Price_{\max} - Price_{\min}}{Price_{\min}} \le maxSpread \\
61+
\text{false} & \text{otherwise}
62+
\end{cases}
63+
$$
64+
65+
## Short-term stability (history tolerance)
66+
67+
The aggregator keeps an array of the last **n** aggregated prices (with timestamps), respecting `priceHistoryInterval` and `maxPriceHistoryAge`.
68+
69+
Stability is defined by two parameters:
70+
71+
- **baseTolerance** (n): fixed buffer to account for immediate market noise.
72+
- **driftExpansionRate** (m): additional allowance per minute to account for natural price drift.
73+
74+
For each historical point (i), the **allowed relative difference** between the current price and the history price grows with time:
75+
76+
$$
77+
\text{allowedRelativeDiff}_{i} = \text{baseTolerance} + \text{driftExpansionRate} \times \Delta t_{\text{minutes}}
78+
$$
79+
80+
where Delta t_minutes is the time in minutes from the history entry to now. The **actual relative difference** is:
81+
82+
$$
83+
\text{relativeDiff}_{i} = \frac{|Price_{\text{current}} - Price_{i}|}{\min(Price_{\text{current}}, Price_{i})}
84+
$$
85+
86+
The current price is **stable** only if **every** such relative difference (from each valid history entry to the current price) is at or below the allowed tolerance for that entry. If **any** exceeds it, the aggregator emits `PriceNotWithinHistoryTolerance(relativeDiff, deltaTMinutes, maxAllowedRelativeDiff)` and returns nil.
87+
88+
$$
89+
\text{isStable} =
90+
\begin{cases}
91+
\text{true} & \text{if } \text{relativeDiff}_{i} \le \text{allowedRelativeDiff}_{i} \text{ for all } i \\
92+
\text{false} & \text{otherwise (price invalid)}
93+
\end{cases}
94+
$$
95+
96+
Implementationally, entries older than `maxPriceHistoryAge` are ignored when evaluating stability.
97+
98+
**Parameter units:** `maxSpread`, `baseTolerance`, and `driftExpansionRate` are dimensionless relative values (e.g. `0.01` = 1%, `1.0` = 100%). All are bounded by the contract to ≤ 10000.0.
99+
100+
## PriceOracleRouterv1
101+
102+
Single oracle interface that routes by **token type**. Each token type maps to an oracle. This makes it easy to combine different aggregators without the need to supply different kinds of thresholds for individual token types.
103+
104+
- **Price flow:** `price(ofToken)` looks up the oracle for that token type; if none is registered, returns `nil`. All oracles must share the same `unitOfAccount` (enforced at router creation).
105+
- **Empty router:** If the oracle map is empty or a token type is not registered, `price(ofToken)` returns `nil`.

0 commit comments

Comments
 (0)