Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
b8e7a5a
Certora/hub verification (#892)
nd-certora Oct 14, 2025
44a9ae3
fix: revert asset premium check removal
DhairyaSethi Oct 14, 2025
89416e6
fix: snapshots;
DhairyaSethi Oct 14, 2025
64ccf87
Merge remote-tracking branch 'origin' into certora
DhairyaSethi Oct 14, 2025
3d09049
fix: spec
DhairyaSethi Oct 14, 2025
fd6cf78
feat: rm nothingForZero_eliminateDeficit
DhairyaSethi Oct 14, 2025
b6762ed
Merge remote-tracking branch 'origin' into certora
DhairyaSethi Oct 14, 2025
cd58742
chore: helper script
DhairyaSethi Oct 14, 2025
033c174
Merge remote-tracking branch 'origin' into certora
DhairyaSethi Oct 16, 2025
3320b67
Merge remote-tracking branch 'origin' into certora
DhairyaSethi Oct 20, 2025
35a7d75
fix: support latest changes
DhairyaSethi Oct 20, 2025
fa01beb
feat: risk premium zero when underwater
DhairyaSethi Oct 21, 2025
3a83f93
Merge remote-tracking branch 'origin' into certora
DhairyaSethi Oct 21, 2025
07b4dc4
fix: start fixing tests
DhairyaSethi Oct 22, 2025
2400d84
Merge remote-tracking branch 'origin' into feat/rp-zero-when-underwater
DhairyaSethi Oct 22, 2025
8b7fbb5
fix: most remaining liq tests
DhairyaSethi Oct 22, 2025
ea90342
Merge remote-tracking branch 'origin' into certora
DhairyaSethi Oct 22, 2025
f72ac6b
Merge branch 'certora' into ci/feat/rp-zero-when-underwater
DhairyaSethi Oct 22, 2025
9f03adc
chore: run certora ci always
DhairyaSethi Oct 22, 2025
285db74
fix: revert solady safe transfer bc prover has difficulty proving it
DhairyaSethi Oct 22, 2025
b217424
erge branch 'certora' into ci/feat/rp-zero-when-underwater
DhairyaSethi Oct 22, 2025
e3068af
fix: adapt to latest
DhairyaSethi Oct 22, 2025
87812bd
Merge branch 'certora' into ci/feat/rp-zero-when-underwater
DhairyaSethi Oct 22, 2025
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
48 changes: 48 additions & 0 deletions .github/workflows/certora.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: Certora Prover Workflow

env:
CONFIGS: |
certora/conf/libs/LibBit.conf
certora/conf/libs/Math.conf
certora/conf/libs/SharesMath.conf
certora/conf/Hub.conf
certora/conf/HubAdditivity.conf
certora/conf/HubAccrueIntegrity.conf
certora/conf/HubAccrueUnrealizedFee.conf
certora/conf/HubIntegrity.conf
certora/conf/HubValidState.conf
on:
pull_request:
workflow_dispatch:

jobs:
verify:
runs-on: ubuntu-latest
permissions:
contents: read
statuses: write
pull-requests: write
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
submodules: recursive

# (Optional) Add installation steps for your project
- name: Setup Node.js
uses: actions/setup-node@v4
- name: Install dependencies
run: npm install

# Run Certora Prover
- uses: Certora/certora-run-action@v2
with:
# Add your configurations as lines, each line is separated.
# Specify additional options for each configuration by adding them after the configuration.
configurations: ${{ env.CONFIGS }}
solc-versions: 0.8.28
job-name: "Verified Rules"
certora-key: ${{ secrets.CERTORAKEY }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,8 @@ broadcast/
lcov*

report/

.DS_Store
π
# certora internal artifacts
.certora_internal/

7 changes: 7 additions & 0 deletions certora/compileAll.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash

for FILE in certora/conf/*.conf
do
echo ${FILE}
certoraRun ${FILE} --compilation_steps_only
done
18 changes: 18 additions & 0 deletions certora/conf/Hub.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"files": [
"src/hub/Hub.sol",
"tests/mocks/WadRayMathWrapper.sol" ,
"certora/harness/SummaryLibrary.sol"
],
"verify": "Hub:certora/spec/Hub.spec",
"optimistic_loop": true,
"loop_iter": "3",
"rule_sanity" : "basic",
"msg": "AAVE V4 Hub",
"parametric_contracts" : "Hub",
"solc_via_ir" : true,
"build_cache" : true,
"smt_timeout": "7200",
// rules that are timing out and processed separately
"exclude_rule": ["noChangeToOtherSpoke","supplyExchangeRateIsMonotonic"]
}
27 changes: 27 additions & 0 deletions certora/conf/HubAccrueIntegrity.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"files": [
"certora/harness/HubHarness.sol",
"tests/mocks/WadRayMathWrapper.sol",
"certora/harness/MathWrapper.sol",
],
"verify": "HubHarness:certora/spec/HubAccrueIntegrity.spec",
"optimistic_loop": true,
"loop_iter": "3",
"rule_sanity" : "basic",
"msg": "HubHarness - AccrueIntegrity",
"parametric_contracts" : ["HubHarness"],
"solc_via_ir" : true,
"prover_args": [
"-oldSplitParallel",
"true",
"-dontStopAtFirstSplitTimeout",
"true",
"-splitParallelTimelimit",
"7000",
"-splitParallelInitialDepth",
"3",
"-numOfParallelSplits",
"7"
],
"independent_satisfy" : true
}
28 changes: 28 additions & 0 deletions certora/conf/HubAccrueSupplyRate.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"files": [
"certora/harness/HubHarness.sol",
"tests/mocks/WadRayMathWrapper.sol",
"certora/harness/MathWrapper.sol"
],
"loop_iter": 3,
"msg": "HubAccrue supply rate",
"multi_assert_check": true,
"optimistic_loop": true,
"parametric_contracts": [
"HubHarness"
],
"prover_args": [
"-splitParallel",
"true",
"-dontStopAtFirstSplitTimeout",
"true"
],
"rule": [
"unrealizedFeeSharesSupplyRate"
],
// no need for sanity check as the rule ends in a satisfy command
"rule_sanity": "none",
"smt_timeout": 7200,
"solc_via_ir": true,
"verify": "HubHarness:certora/spec/HubAccrueSupplyRate.spec"
}
14 changes: 14 additions & 0 deletions certora/conf/HubAccrueUnrealizedFee.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"files": [
"certora/harness/HubHarness.sol",
"tests/mocks/WadRayMathWrapper.sol",
"certora/harness/MathWrapper.sol",
],
"verify": "HubHarness:certora/spec/HubAccrueUnrealizedFee.spec",
"optimistic_loop": true,
"loop_iter": "3",
"rule_sanity" : "basic",
"msg": "HubHarness - AccrueIntegrity Unrealized Fee",
"parametric_contracts" : ["HubHarness"],
"solc_via_ir" : true,
}
16 changes: 16 additions & 0 deletions certora/conf/HubAdditivity.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"files": [
"certora/harness/HubHarness.sol",
"tests/mocks/WadRayMathWrapper.sol",
"certora/harness/SummaryLibrary.sol"
],
"verify": "HubHarness:certora/spec/HubAdditivity.spec",
"optimistic_loop": true,
"loop_iter": "3",
"rule_sanity" : "basic",
"msg": "Hub Additivity",
"parametric_contracts" : "HubHarness",
"solc_via_ir" : true,
"independent_satisfy" : true,
"exclude_rule": ["drawAdditivity","restoreAdditivity","reportDeficitAdditivity"]
}
15 changes: 15 additions & 0 deletions certora/conf/HubIntegrity.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"files": [
"src/hub/Hub.sol",
"tests/mocks/WadRayMathWrapper.sol",
"certora/harness/SummaryLibrary.sol"
],
"verify": "Hub:certora/spec/HubIntegrityRules.spec",
"optimistic_loop": true,
"loop_iter": "3",
"rule_sanity" : "basic",
"msg": "Hub integrityRules",
"parametric_contracts" : "Hub",
"solc_via_ir" : true,
"independent_satisfy" : true
}
15 changes: 15 additions & 0 deletions certora/conf/HubValidState.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"files": [
"src/hub/Hub.sol",
"tests/mocks/WadRayMathWrapper.sol" ,
"certora/harness/SummaryLibrary.sol"
],
"verify": "Hub:certora/spec/HubValidState.spec",
"optimistic_loop": true,
"loop_iter": "3",
"rule_sanity" : "basic",
"msg": "AAVE V4 Hub - validState invariants",
"parametric_contracts" : "Hub",
"solc_via_ir" : true,
"build_cache" : true
}
13 changes: 13 additions & 0 deletions certora/conf/libs/LibBit.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"files": [
"certora/harness/LibBitHarness.sol"
],
"precise_bitwise_ops" : true,
"msg" : "LibBit library",
"verify": "LibBitHarness:certora/spec/libs/LibBit.spec",
"smt_timeout": "7200",
"prover_args": [
"-split",
"false"
]
}
8 changes: 8 additions & 0 deletions certora/conf/libs/Math.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"files": [
"certora/harness/MathWrapper.sol"
],
"verify": "MathWrapper:certora/spec/libs/Math.spec",
"rule_sanity" : "basic",
"msg": "Math function equivalence",
}
15 changes: 15 additions & 0 deletions certora/conf/libs/SharesMath.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"files": [
"certora/harness/HubHarness.sol",
"tests/mocks/WadRayMathWrapper.sol",
],
"verify": "HubHarness:certora/spec/libs/SharesMath.spec",
"optimistic_loop": true,
"loop_iter": "3",
"rule_sanity" : "basic",
"msg": "HubHarness - SharesMath",
"parametric_contracts" : ["HubHarness"],
"solc_via_ir" : true,
"independent_satisfy" : true,
"build_cache" : true
}
60 changes: 60 additions & 0 deletions certora/harness/HubHarness.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import '../../src/hub/Hub.sol';
import {AssetLogic} from 'src/hub/libraries/AssetLogic.sol';
import {SharesMath} from 'src/hub/libraries/SharesMath.sol';

pragma solidity ^0.8.0;

contract HubHarness is Hub {
using AssetLogic for Asset;

constructor(address authority_) Hub(authority_) {
// Intentionally left blank
}

function accrueInterest(uint256 assetId) external {
Asset storage asset = _assets[assetId];

asset.accrue(_spokes, assetId);
}

function toSharesDown(
uint256 assets,
uint256 totalAssets,
uint256 totalShares
) external pure returns (uint256) {
return SharesMath.toSharesDown(assets, totalAssets, totalShares);
}

function toAssetsDown(
uint256 shares,
uint256 totalAssets,
uint256 totalShares
) external pure returns (uint256) {
return SharesMath.toAssetsDown(shares, totalAssets, totalShares);
}

function toSharesUp(
uint256 assets,
uint256 totalAssets,
uint256 totalShares
) external pure returns (uint256) {
return SharesMath.toSharesUp(assets, totalAssets, totalShares);
}

function toAssetsUp(
uint256 shares,
uint256 totalAssets,
uint256 totalShares
) external pure returns (uint256) {
return SharesMath.toAssetsUp(shares, totalAssets, totalShares);
}

function getAssetSuppliedAmountUp(uint256 assetId) external view returns (uint256) {
return _assets[assetId].toAddedAssetsUp(_assets[assetId].addedShares);
}

function unrealizedFeeShares(uint256 assetId) external view returns (uint256) {
Asset storage asset = _assets[assetId];
return asset.unrealizedFeeShares();
}
}
25 changes: 25 additions & 0 deletions certora/harness/LibBitHarness.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import {LibBit} from '../../src/dependencies/solady/LibBit.sol';

pragma solidity ^0.8.0;

contract LibBitHarness {
function popCount(uint256 x) external pure returns (uint256 c) {
return LibBit.popCount(x);
}

function fls(uint256 x) external pure returns (uint256 r) {
return LibBit.fls(x);
}

function isBitTrue(uint256 x, uint16 pos) public pure returns (bool) {
return ((x >> pos) & 1) == 1;
}

function changeOneBit(uint256 x, uint16 pos) external pure returns (uint256 c) {
if (isBitTrue(x, pos)) {
return x & ~(1 << pos);
} else {
return x | (1 << pos);
}
}
}
Loading