-
Notifications
You must be signed in to change notification settings - Fork 21
Enrich CVL guidance with Codex experimnet: ERC‑4626 and rewards patterns (from Aave Stata specs) #436
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
…3-horizon/tree/main/certora/stata/specs'
…integrate real-world hooks/math tips
…ub links); normalize heading levels; remove link_output.txt
…ave-style); minor spelling tolerances
shellygr
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dear lord. almost 100% AI slop
| ```cvl | ||
| // Rounds up or down depending on a Math.Rounding enum | ||
| function mulDivCVL(uint256 x, uint256 y, uint256 denominator, Math.Rounding rounding) returns uint256 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
incomplete. Math is defined in OpenZeppelin's Math.sol, so if it is somehow not part of the project we work on, the Math.Rounding won't type check
| } | ||
| ``` | ||
|
|
||
| - Tight, solver-friendly models for up/down `mulDiv` used across specs: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure what "Tight" means
| function mulDivDownAbstractPlus(uint256 x, uint256 y, uint256 z) returns uint256 { | ||
| uint256 res; | ||
| require z != 0; | ||
| uint256 xy = require_uint256(x * y); | ||
| uint256 fz = require_uint256(res * z); | ||
| require xy >= fz; | ||
| require fz + z > to_mathint(xy); | ||
| return res; | ||
| } | ||
| function mulDivUpAbstractPlus(uint256 x, uint256 y, uint256 z) returns uint256 { | ||
| uint256 res; | ||
| require z != 0; | ||
| uint256 xy = require_uint256(x * y); | ||
| uint256 fz = require_uint256(res * z); | ||
| require xy >= fz; | ||
| require fz + z > to_mathint(xy); | ||
| if (xy == fz) { return res; } | ||
| return require_uint256(res + 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would appreciate someone using thses summaries daily to say whether they're really good
| ``` | ||
|
|
||
| ```{warning} | ||
| Ghost-based math models can be powerful but require care. For example, a ghost power function `_ghostPow` with axioms like `x^0==1`, monotonicity, and bounds is useful for reasoning, but equality-like axioms may be invalid under fixed-point rounding. Keep axioms conservative and prefer inequality bounds. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
did not understand this part
| function discreteQuotientMulDiv(uint256 x, uint256 y, uint256 z) returns uint256 { | ||
| uint256 res; | ||
| require z != 0 && noOverFlowMul(x, y); | ||
| require( | ||
| ((x == 0 || y == 0) && res == 0) || | ||
| (x == z && res == y) || | ||
| (y == z && res == x) || | ||
| constQuotient(x, y, z, 2, res) || // 1/2 or 2 | ||
| constQuotient(x, y, z, 5, res) || // 1/5 or 5 | ||
| constQuotient(x, y, z, 100, res) // 1/100 or 100 | ||
| ); | ||
| return res; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
constQuotient is not defined
| - Isolate environment explicitly with `with (env e)` when you need to pin `msg.sender`, `block.timestamp`, or similar for a particular call, and use plain `envfree` elsewhere. A consistent pattern across a spec keeps models smaller and avoids accidental dependencies between calls. | ||
|
|
||
| ```{tip} | ||
| Heavyweight dependencies (Lending pools, incentive controllers) typically benefit from coarse summaries in the spec and fine-grained assertions on observable effects (balances, indices) in rules and invariants. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nonsense
| - Preview equals actual (ERC-4626). EIP-4626 requires preview functions to not exceed the actual action in the same transaction. In some implementations they are equal; this stronger property is easy to assert: | ||
|
|
||
| ```cvl | ||
| /// previewDeposit returns the exact deposit shares | ||
| rule previewDepositAmountCheck(){ | ||
| env e1; env e2; | ||
| uint256 assets; address receiver; | ||
| uint256 previewShares = previewDeposit(e1, assets); | ||
| uint256 shares = deposit(e2, assets, receiver); | ||
| assert previewShares == shares, "preview equals actual"; | ||
| } | ||
| ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that can be put maybe in the examples repository but not in the official docs
| } | ||
| ``` | ||
|
|
||
| - Deposit envelopes by index (Aave-style index RAY). Bound deposited aTokens relative to requested `assets` and index. For `index > RAY` the bound is `+1 aToken`; for `index == RAY` it tightens to `+0.5 aToken`: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what the hell is envelops and why does codex keep mentioning them?
| } | ||
| ``` | ||
|
|
||
| - Duplicate reward claims do not amplify payout. Whether the contract has sufficient funds or not, listing the same reward twice must not increase net rewards to a user beyond the computed claimable amount: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is a legitimate rule but it's in the wrong section. Again, I think it should be in an examples repository for reward-distributing code
| @@ -0,0 +1,102 @@ | |||
| # Rounding Envelopes | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
again bullshit terminology
but this needs to be reviewed by someone working daily on FV of protocols
Summary
This PR updates Certora’s CVL documentation with practical, field-tested examples and tips derived from a recent formal verification effort. The additions sharpen guidance around methods, hooks, functions, ghosts, rules, and invariants, with solver-friendly rounding envelopes and storage patterns aligned to modern ERC‑4626 and rewards-controller designs.
Origin
Motivation
Key Updates
Files Touched
Implementation Notes
Build & QA
Risks
Follow-ups
Acknowledgements