Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
8c2c906
fix: asset validation on `mintFeeShares` (#1070)
yan-man Dec 19, 2025
a6f379c
fix: Add safecast on MathUtils::signedSub function (#1071)
yan-man Jan 5, 2026
396eb72
fix: setSelfAsPositionManager consistency (#1064)
DhairyaSethi Jan 6, 2026
c72806f
fix: allow `reportDeficit` even if spoke is paused (#1050)
yan-man Jan 7, 2026
90b06bc
fix: Refactor calculate premium delta helper in Spoke (#1084)
CheyenneAtapour Jan 8, 2026
2dc23ce
chore: reorder gov updates (#1093)
DhairyaSethi Jan 9, 2026
42ab417
fix: add safecast for sanity check contructor input in UnitPriceFeed …
yan-man Jan 13, 2026
2e04a96
chore: migrate EIP712Types to relevant interfaces (#1112)
DhairyaSethi Jan 13, 2026
c84804c
fix: consistent naming on constants (#1108)
yan-man Jan 13, 2026
6f718fa
fix: Add spoke address setter in AaveOracle (#1074)
yan-man Jan 14, 2026
fd5abdf
feat: abstract intent consumption (#1065)
DhairyaSethi Jan 14, 2026
3738224
feat: update oz deps to 5.5 (#1116)
DhairyaSethi Jan 14, 2026
4a0efac
chore: fix lint (#1114)
DhairyaSethi Jan 14, 2026
0f187ea
feat: add compiler profiles to use via-IR (#893)
Kogaroshi Jan 15, 2026
174b759
feat: Add support for additional tracking facilities in AccessManager…
Kogaroshi Jan 15, 2026
ab9d1cb
feat: Add reentrancy locks in Spoke and NativeTokenGateway (#1073)
avniculae Jan 16, 2026
ab2fe27
feat: add array support for setUserPositionManagerWithSig in Spoke (#…
DhairyaSethi Jan 19, 2026
a973fd7
fix: Fix paused state check on Hub functions (#1075)
yan-man Jan 20, 2026
85cb93d
fix: Fixes funds transfer flow on reclaim for consistency across Hub …
DhairyaSethi Jan 20, 2026
77cafd4
fix: eliminate deficit zero check (#1126)
DhairyaSethi Jan 20, 2026
521e38a
fix: Add storage layout namespace to NoncesKeyed (#1128)
Kogaroshi Jan 20, 2026
3644423
feat: extsloads (#1101)
DhairyaSethi Jan 20, 2026
c70e261
fix: Add restricted modifier to Hub eliminateDeficit function (#1067)
DhairyaSethi Jan 21, 2026
b360e6a
opt: unsafe memory opt on etxsload (#1104)
DhairyaSethi Jan 21, 2026
11f830e
test: Fix `vm.random*` behavior (#1125)
avniculae Jan 21, 2026
7b7db47
fix: rename Spoke `paused` flag to `halted` in Hub (#1131)
yan-man Jan 22, 2026
a9bac16
feat: Adds AccessManaged authority contract on HubConfigurator and Sp…
DhairyaSethi Jan 27, 2026
5624eda
fix: Fixes intent struct onBehalfOf param name on SignatureGateway an…
miguelmtzinf Jan 27, 2026
233d741
fix: Add storage layout namespace to NoncesKeyed (#1138)
DhairyaSethi Jan 27, 2026
e8baf12
fix: allow reportDeficit even if spoke is paused (#1150)
DhairyaSethi Jan 27, 2026
ba5cc25
feat: Add getter for assetId by underlying asset address on Hub (#1133)
Kogaroshi Jan 27, 2026
31afa65
chore: v0.5.7 release (#1151)
miguelmtzinf Jan 27, 2026
a742d0f
fix: Removes liquidatable flag on Spoke (#1106)
Kogaroshi Jan 27, 2026
3e96c1d
fix: natspec clean up; remove unneeded imports (#1136)
Kogaroshi Jan 29, 2026
b15540a
feat: Impose limit on number of collateral and borrow reserves a user…
CheyenneAtapour Jan 30, 2026
b81c390
fix: consistent rounding on risk premium computation (#1142)
DhairyaSethi Jan 30, 2026
187aa8d
fix: revert back to 512 bit shares math (#1143)
DhairyaSethi Jan 30, 2026
676afc2
chore: separate out spoke storage (#1145)
DhairyaSethi Jan 30, 2026
ac7e6d4
chore: reduce via-ir optimization runs for Spoke (#1132)
Kogaroshi Jan 30, 2026
bf1f37a
chore: rebase dev against 0.5.7 release (#1152)
DhairyaSethi Feb 1, 2026
885def0
fix: Add event emission for immutables on Spoke (#1167)
CheyenneAtapour Feb 1, 2026
f39b8a8
test: fix skipped accrue interest test (#1130)
CheyenneAtapour Feb 2, 2026
318def7
chore: merge in 0.5.7 release
DhairyaSethi Feb 3, 2026
cbe6cd9
fix: Move reportDeficit to external lib in favor of Spoke bytecode si…
miguelmtzinf Feb 3, 2026
e615510
feat: Increase Health Factor & Liquidations Precision (#1134)
avniculae Feb 5, 2026
48f886a
fix: increase size of dynamicConfigKey to uint32 (#1189)
yan-man Feb 6, 2026
0bcf3e6
fix: rename hubConfigurator methods; add analogous spokeConfigurator …
yan-man Feb 6, 2026
d94444a
feat: Add new getter for reserveId by Hub and AssetId (#1141)
Kogaroshi Feb 6, 2026
5c2b8fa
chore: reorder rp update on deficit (#1078)
DhairyaSethi Feb 7, 2026
730af06
fix: natspec docs (#1051)
yan-man Feb 8, 2026
1d1f16a
opt: key value list (#1119)
DhairyaSethi Feb 8, 2026
8ff664b
fix: Add getter to compute last asset drawn rate on Hub (#1199)
DhairyaSethi Feb 9, 2026
fd57c0f
chore: prepare v0.5.8 release (#1076)
miguelmtzinf Feb 9, 2026
f1b6294
fix: natspec; Hub validation consistency (#1206)
yan-man Feb 10, 2026
cf4331d
chore: v0.5.8 release (#1207)
miguelmtzinf Feb 10, 2026
4ffe2a4
feat: Add TokenisationSpoke (#1029)
DhairyaSethi Feb 10, 2026
a74e979
opt: position manager update hash (#1185)
DhairyaSethi Feb 10, 2026
9ae1341
fix: tracking role members on AccessManager _revokeRole internal meth…
Kogaroshi Feb 10, 2026
ad9105b
fix: max deposit rounding on tokenization spoke (#1201)
DhairyaSethi Feb 10, 2026
c3b9287
chore: v0.5.9 release (#1209)
miguelmtzinf Feb 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 0 additions & 85 deletions .github/workflows/mirror.yml

This file was deleted.

3 changes: 2 additions & 1 deletion .github/workflows/tests-merge.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ on:
push:
branches:
- main
- dev

jobs:
lint:
Expand All @@ -21,7 +22,7 @@ jobs:
- name: Run Foundry setup
uses: bgd-labs/github-workflows/.github/actions/foundry-setup@main
with:
FOUNDRY_VERSION: stable
FOUNDRY_VERSION: nightly

- name: Run Forge size
uses: bgd-labs/github-workflows/.github/actions/foundry-size@main
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/tests-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
- name: Run Foundry setup
uses: bgd-labs/github-workflows/.github/actions/foundry-setup@main
with:
FOUNDRY_VERSION: stable
FOUNDRY_VERSION: nightly

- name: Run Forge size
uses: bgd-labs/github-workflows/.github/actions/foundry-size@main
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ out/

package-lock.json
node_modules
__pycache__

# ignore foundry deploy artifacts
broadcast/
Expand All @@ -22,4 +23,4 @@ lcov*
report/

.DS_Store
.venv/
.venv/
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[submodule "lib/forge-std"]
path = lib/forge-std
url = https://github.com/foundry-rs/forge-std
[submodule "lib/erc4626-tests"]
path = lib/erc4626-tests
url = https://github.com/a16z/erc4626-tests
1 change: 1 addition & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"plugins": ["prettier-plugin-solidity"],
"overrides": [
{
"files": "*.sol",
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ git-diff :
gas-report :; forge test --mp 'tests/gas/**'

# Coverage
coverage-base :; forge coverage --fuzz-runs 50 --report lcov --no-match-coverage "(scripts|tests|deployments|mocks)"
coverage-base :; FOUNDRY_PROFILE=coverage forge coverage --report lcov --no-match-coverage "(scripts|tests|deployments|mocks)"
coverage-clean :; lcov --rc derive_function_end_line=0 --remove ./lcov.info -o ./lcov.info.p --ignore-errors inconsistent 'src/dependencies/*'
coverage-report :; genhtml ./lcov.info.p -o report --branch-coverage --rc derive_function_end_line=0
coverage-badge :; coverage=$$(awk -F '[<>]' '/headerCovTableEntryHi/{print $3}' ./report/index.html | sed 's/[^0-9.]//g' | head -n 1); \
Expand Down
16 changes: 8 additions & 8 deletions docs/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,9 @@ This represents the principal liquidity provided by the Hub to the Spoke on the

Over time, the base debt accrues interest at the Hub’s base borrow rate strategy $R_{sbase,i}$. This means that as time progresses, the accrued base interest is added to the user’s base debt, increasing the amount the user owes to the protocol’s liquidity providers for that particular asset.

$D_{u,i} = D_{u,ibase} + R_{sbase,i}D_{u,ibase}$
$D_{u,ibase}(t) = D_{u,ibase} (t-1) + R_{sbase,i}D_{u,ibase}(t-1)$

$R_{sbase,i}D_{u,ibase} = ΔD_{u,ibase}$
$ΔD_{u,ibase} = R_{sbase,i}D_{u,ibase}$

## Premium Debt

Expand All @@ -169,15 +169,15 @@ $D_{u,premium}$ is a running total of the extra interest accrued on user u

Unlike base debt, premium debt does not originate from an actual asset withdrawal from the Hub; instead, it is a bookkeeping entry that tracks how much extra the user owes because of the User Risk Premium.

$D_{u,premium}= D_{u,premium} + R_{sbase,i}RP_uD_{u,ibase}$
$D_{u,premium}(t)= D_{u,premium}(t-1) + R_{sbase,i}RP_uD_{u,ibase}(t-1)$

$R_{sbase,i}RP_uD_{u,ibase} = ΔD_{u,premium}$
$ΔD_{u,premium} = R_{sbase,i}RP_uD_{u,ibase}$

# Dynamic Risk Configuration

One of the major risk‑side limitations of V3 lies in its single, global risk configuration per asset. This design creates significant governance overhead and potential user harm through unexpected liquidations, as any parameter change, in particular lowering the liquidation threshold, immediately affects every open position.

V4 makes it possible for multiple risk configurations to exist side‑by‑side. Whenever the Governor adjusts collateralization parameters (currently the Collateral Factor (CF), Liquidation Bonus (LB) or Protocol Fee (PF)), the protocol adds a new configuration instead of replacing the old one. Earlier configurations continue to govern positions opened under them while updated parameters apply to new positions. In particular cases where there could be a negative impact to the protocol, the Governor may decide to permissioned trigger an update of existing positions to the latest parameters.
V4 makes it possible for multiple risk configurations to exist side‑by‑side. Whenever the Governor adjusts collateralization parameters (currently the Collateral Factor (CF), Liquidation Bonus (LB) or Protocol Fee (PF)), the protocol adds a new configuration instead of replacing the old one. Earlier configurations continue to govern positions opened under them while updated parameters apply to new positions. In particular cases where there could be a negative impact to the protocol, the Governor may decide to trigger an authorized update of existing positions to the latest parameters.

Every time the Governor adjusts the collateralization parameters, it corresponds to a new configuration. These configurations are stored in a bounded dictionary of up to 16M entries (2^24) identified by incremental keys, with each reserve holding the key that points to the current active configuration.

Expand Down Expand Up @@ -235,9 +235,9 @@ Aave V4 exposes several configurable parameters that influence liquidation:
| **Parameter** **Description** **Constraints** | | |
| --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ |
| `TargetHealthFactor` | A spoke‑wide value set by the Governor representing the HF to which a borrower should be restored after liquidation. Liquidators repay only enough debt to reach this HF under normal circumstances that do not result in dust collateral or debt remaining. | Must be ≥ the `HEALTH_FACTOR_LIQUIDATION_THRESHOLD` constant. |
| `DUST_LIQUIDATION_THRESHOLD` | Hard‑coded threshold used to prevent extremely small leftover debt. The maximum debt that can be liquidated is increased to ensure that debt or collateral dust less than this threshold does not remain unless the corresponding respective collateral or debt reserve is fully liquidated. | Hard‑coded constant set to 1_000 USD in base units. |
| `DUST_LIQUIDATION_THRESHOLD` | Hard‑coded threshold used to prevent extremely small leftover debt. The maximum debt that can be liquidated is increased to ensure that debt or collateral dust less than this threshold does not remain unless the respective collateral or debt reserve is fully liquidated. | Hard‑coded constant set to 1_000 USD in base units. |
| `maxLiquidationBonus` | Per reserve defined maximum liquidation bonus for a collateral, expressed in basis points (BPS). A value of 105_00 means there is 5_00 extra seized collateral over the amount of debt repaid in base currency. | Must be ≥ 100_00 |
| `healthFactorForMaxBonus` | Spoke‑wide value expressed in WAD units defining the HF below which the max bonus applies. It must be less than or equal to `HEALTH_FACTOR_LIQUIDATION_THRESHOLD` to avoid division‑by‑zero. | `healthFactorForMaxBonus` < `HEALTH_FACTOR_LIQUIDATION_THRESHOLD`. |
| `healthFactorForMaxBonus` | Spoke‑wide value expressed in WAD units defining the HF below which the max bonus applies. It must be less than `HEALTH_FACTOR_LIQUIDATION_THRESHOLD` to avoid division‑by‑zero. | `healthFactorForMaxBonus` < `HEALTH_FACTOR_LIQUIDATION_THRESHOLD`. |
| `liquidationBonusFactor` | Spoke‑wide percentage (expressed in BPS) specifying the fraction of the max bonus earned at the threshold `HEALTH_FACTOR_LIQUIDATION_THRESHOLD`. It defines the minimum bonus; e.g., a factor of 80_00 yields a bonus equal to 80% of the max bonus when HF equals the liquidation threshold. | liquidationBonusFactor must be ≤ 100_00 |

## Liquidation Process in V4
Expand All @@ -257,7 +257,7 @@ V4 introduces a dynamic dust prevention mechanism. If the debt remaining after a

Due to rounding effects and the creation of negligible interest premiums during liquidations, the borrower’s final health factor after liquidation may not exactly match the `TargetHealthFactor`. In rare cases the final HF may be slightly above or below the target.

A deficit is only reported if, after liquidation, the borrower has no more collateral left across any of his reserves and debt still remains.
A deficit is only reported if, after liquidation, the borrower has no more collateral left across any of their reserves and debt still remains.

## Dutch‑Auction Style Liquidation Bonus

Expand Down
6 changes: 6 additions & 0 deletions foundry.lock
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
{
"lib/erc4626-tests": {
"tag": {
"name": "v0.1.1",
"rev": "232ff9ba8194e406967f52ecc5cb52ed764209e9"
}
},
"lib/forge-std": {
"rev": "60acb7aaadcce2d68e52986a0a66fe79f07d138f"
}
Expand Down
25 changes: 23 additions & 2 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,27 @@ fs_permissions = [{ access = "read", path = "tests/mocks/JsonBindings.sol" }]
solc_version = "0.8.28"
evm_version = "cancun"
optimizer = true
optimizer_runs = 200
optimizer_runs = 444444444444
bytecode_hash = "none"
gas_snapshot_check = false
gas_limit = 1099511627776
dynamic_test_linking = true

additional_compiler_profiles = [
{ name = "hub", optimizer = true, via_ir = true, optimizer_runs = 22_300 },
{ name = "spoke", optimizer = true, via_ir = true, optimizer_runs = 750 },
{ name = "tests", optimizer = true, via_ir = false, optimizer_runs = 444444444444 },
]

compilation_restrictions = [
{ paths = "src/hub/Hub.sol", optimizer = true, via_ir = true, optimizer_runs = 22_300 },
{ paths = "src/spoke/instances/SpokeInstance.sol", optimizer = true, via_ir = true, optimizer_runs = 750 },
{ paths = "tests/**", optimizer = true, via_ir = false, optimizer_runs = 444444444444 },
]

[bind_json]
out = "tests/mocks/JsonBindings.sol"
include = ["src/libraries/types/EIP712Types.sol"]
include = ["tests/mocks/EIP712Types.sol"]

[lint]
ignore = ["src/dependencies/**/*", "tests/**/*"]
Expand All @@ -35,6 +48,14 @@ gas_snapshot_check = true
test = 'tests/gas'
isolate = true

[profile.coverage]
optimizer = true
optimizer_runs = 444444444444
via_ir = false
fuzz.runs = 50
additional_compiler_profiles = []
compilation_restrictions = []

[rpc_endpoints]
mainnet = "${RPC_MAINNET}"
optimism = "${RPC_OPTIMISM}"
Expand Down
1 change: 1 addition & 0 deletions lib/erc4626-tests
Submodule erc4626-tests added at 232ff9
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "aave-v4",
"version": "0.5.6",
"version": "0.5.9",
"scripts": {
"lint": "prettier . --check",
"lint:fix": "prettier . --write",
Expand All @@ -19,8 +19,8 @@
"devDependencies": {
"husky": "9.1.7",
"lint-staged": "16.2.3",
"prettier": "3.6.2",
"prettier-plugin-solidity": "2.1.0"
"prettier": "3.7.4",
"prettier-plugin-solidity": "2.2.1"
},
"lint-staged": {
"*.{sol,md,py,ts}": "prettier . --write"
Expand Down
2 changes: 2 additions & 0 deletions remappings.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
erc4626-tests/=lib/erc4626-tests/
forge-std/=lib/forge-std/src/
32 changes: 16 additions & 16 deletions snapshots/Hub.Operations.json
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
{
"add": "88006",
"add: with transfer": "109613",
"draw": "105931",
"eliminateDeficit: full": "59781",
"eliminateDeficit: partial": "69429",
"mintFeeShares": "84007",
"payFee": "72302",
"refreshPremium": "71999",
"remove: full": "76993",
"remove: partial": "81640",
"reportDeficit": "115225",
"restore: full": "80471",
"restore: full - with transfer": "173377",
"restore: partial": "89137",
"restore: partial - with transfer": "147400",
"transferShares": "71192"
"add": "86692",
"add: with transfer": "107989",
"draw": "104148",
"eliminateDeficit: full": "72567",
"eliminateDeficit: partial": "82172",
"mintFeeShares": "82741",
"payFee": "70805",
"refreshPremium": "70362",
"remove: full": "75596",
"remove: partial": "80734",
"reportDeficit": "111882",
"restore: full": "76552",
"restore: full - with transfer": "169161",
"restore: partial": "85262",
"restore: partial - with transfer": "143242",
"transferShares": "69619"
}
12 changes: 6 additions & 6 deletions snapshots/NativeTokenGateway.Operations.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"borrowNative": "229316",
"repayNative": "168024",
"supplyAsCollateralNative": "160373",
"supplyNative": "136476",
"withdrawNative: full": "125620",
"withdrawNative: partial": "136825"
"borrowNative": "228557",
"repayNative": "166460",
"supplyAsCollateralNative": "160122",
"supplyNative": "135753",
"withdrawNative: full": "125548",
"withdrawNative: partial": "136735"
}
16 changes: 8 additions & 8 deletions snapshots/SignatureGateway.Operations.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"borrowWithSig": "215605",
"repayWithSig": "188872",
"setSelfAsUserPositionManagerWithSig": "75402",
"setUsingAsCollateralWithSig": "85053",
"supplyWithSig": "153205",
"updateUserDynamicConfigWithSig": "62769",
"updateUserRiskPremiumWithSig": "61579",
"withdrawWithSig": "131696"
"borrowWithSig": "213790",
"repayWithSig": "186732",
"setSelfAsUserPositionManagerWithSig": "75118",
"setUsingAsCollateralWithSig": "85387",
"supplyWithSig": "151985",
"updateUserDynamicConfigWithSig": "63120",
"updateUserRiskPremiumWithSig": "62090",
"withdrawWithSig": "130803"
}
10 changes: 5 additions & 5 deletions snapshots/Spoke.Getters.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"getUserAccountData: supplies: 0, borrows: 0": "11937",
"getUserAccountData: supplies: 1, borrows: 0": "48600",
"getUserAccountData: supplies: 2, borrows: 0": "80378",
"getUserAccountData: supplies: 2, borrows: 1": "100166",
"getUserAccountData: supplies: 2, borrows: 2": "118596"
"getUserAccountData: supplies: 0, borrows: 0": "13014",
"getUserAccountData: supplies: 1, borrows: 0": "49426",
"getUserAccountData: supplies: 2, borrows: 0": "81102",
"getUserAccountData: supplies: 2, borrows: 1": "101454",
"getUserAccountData: supplies: 2, borrows: 2": "120714"
}
Loading
Loading