feat: consolidate per-protocol assertion examples under examples/#70
feat: consolidate per-protocol assertion examples under examples/#70makemake-kbo wants to merge 2 commits into
Conversation
Brings assertion examples from the per-protocol branches (aave, aerodrome, cap, curve, denaria, euler, nado, royco, safe, spark, symbiotic, tydro, uniswap, veda, zeroex) into examples/<protocol>/src/ on a single branch. Each protocol is compiled standalone via a new [profile.<protocol>] in foundry.toml that shares the root src/ (credible-std) and lib/ via the credible-std/ remapping — no nested foundry projects, no duplicated submodules. Imports in extracted files are rewritten to the credible-std/ remapping form. Root src/ is extended with the missing protection bases that examples depend on (access_control/*, perpetual/PerpetualBaseAssertion + IPerpetualProtectionSuite). AaveV3LikeOperationSafety is upgraded to the full version that exposes AaveV3LikeProtectionSuite. PhEvm gains the marketPrice precompile signature and IAaveV3LikeOracle gains BASE_CURRENCY / BASE_CURRENCY_UNIT. All 20 foundry profiles build clean.
|
Blocking concern: several new assertion examples appear to compile but never call
Can we either register the assertion spec in each concrete assertion constructor, or centralize it in the relevant base constructors where the trigger/target set is known? I would also add a small deployment/spec-recording test per affected example profile so this does not regress while the examples still compile. |
fredo
left a comment
There was a problem hiding this comment.
Constructor-time protocol reads need to be removed before these examples are deployable as Credible assertions.
| uint256 priceTolerance_ | ||
| ) { | ||
| amm = amm_; | ||
| borrowedToken = ICurveLlammaAMM(amm_).coins(0); |
There was a problem hiding this comment.
This constructor reads live AMM state (coins) and then token metadata (decimals) below. That has the same deployability problem documented in the ERC4626/Uniswap helpers: assertion construction runs in an isolated deploy context, so adopter/token reads can revert with EXTCODESIZE = 0. Please pass the borrowed token, collateral token, and precisions/decimals explicitly, or move reads to fork-time helpers using ph.staticcallAt.
|
|
||
| constructor(address controller_, uint256 maxLoansToScan_, uint256 debtTolerance_) { | ||
| controller = controller_; | ||
| amm = ICurveUsdController(controller_).amm(); |
There was a problem hiding this comment.
Same constructor-read issue here: controller_.amm() reaches into the protocol while the assertion is being constructed. Please pass the AMM address explicitly, or derive it later via a fork-aware read.
| address internal immutable controller; | ||
|
|
||
| constructor(address vault_) { | ||
| controller = ILlamaLendVault(vault_).controller(); |
There was a problem hiding this comment.
Same issue: this constructor reads vault_.controller() from the adopter/protocol. Constructors should only consume deployment args for this kind of dependency; pass the controller explicitly or read it later through the fork-aware helpers.
|
|
||
| constructor(address controller_, uint256 availableBalanceTolerance_) { | ||
| controller = controller_; | ||
| borrowedToken = ILlamaLendController(controller_).borrowed_token(); |
There was a problem hiding this comment.
Same constructor-read issue: controller_.borrowed_token() depends on live protocol code during assertion deployment. Please pass the borrowed token explicitly or defer this through ph.staticcallAt at assertion execution time.
|
|
||
| constructor(address kernel_) { | ||
| kernel = kernel_; | ||
| accountant = IRoycoKernel(kernel_).ACCOUNTANT(); |
There was a problem hiding this comment.
This constructor reads multiple values from the kernel (ACCOUNTANT, tranches, and assets). That can fail in the assertion-deploy runtime for the same reason as the other adopter reads. Please pass these dependencies explicitly or make them fork-time reads.
|
|
||
| constructor(address tranche_) { | ||
| tranche = tranche_; | ||
| kernel = IRoycoVaultTranche(tranche_).KERNEL(); |
There was a problem hiding this comment.
This constructor also reads protocol state from the tranche (KERNEL and TRANCHE_TYPE). Please avoid live protocol calls during construction; pass these values explicitly or defer them to fork-aware reads.
|
|
||
| pool = pool_; | ||
| oracle = oracle_; | ||
| baseCurrency = IAaveV3LikeOracle(oracle_).BASE_CURRENCY(); |
There was a problem hiding this comment.
This reads oracle configuration during construction (BASE_CURRENCY, and BASE_CURRENCY_UNIT on the next line). To keep the assertion deployable in the Credible runtime, these should be constructor arguments or fork-time reads rather than live oracle calls in the constructor.
| constructor(address vault_) { | ||
| require(vault_ != address(0), "SymbioticVaultBase: vault is zero"); | ||
| vault = vault_; | ||
| asset = ISymbioticVaultLike(vault_).collateral(); |
There was a problem hiding this comment.
This constructor reads vault_.collateral() from the protected vault. Please pass the collateral asset explicitly, or read it later through the fork-aware helper path, so assertion deployment does not depend on live adopter code being available in the constructor context.
|
Coverage/CI concern: the new protocol examples are effectively compile-only right now.
Related CI gap: this PR adds per-protocol Foundry profiles in Can we add a CI matrix that at least runs
Without that, these protections are hard to evaluate beyond syntax/compilation. |
Addresses PR #70 review comments from @fredo. Constructor-time protocol reads removed. Adopter/protocol state can revert with EXTCODESIZE = 0 in the Credible Layer's assertion-deploy runtime, so helpers now take all derived addresses and constants as explicit args: - CurveLlammaProtocol: borrowedToken, collateralToken, precisions - CurveUsdProtocol: amm - LlamaLendProtocol: controller (vault helper), borrowedToken (controller helper) - RoycoHelpers: accountant + tranches + assets (kernel), kernel + trancheType (tranche) - SparkLendOraclePriceGuardAssertion: baseCurrency + baseCurrencyUnit - SymbioticVaultBaseAssertion: asset Inheritance chains are updated to thread the new args through. registerAssertionSpec(AssertionSpec.Reshiram) added to every concrete leaf assertion that was missing one, including the protections flagged by the review (Denaria, Spark, LlamaLend, Euler, Royco, Symbiotic, Veda Boring Vault) and the other concrete leaves under examples/ for consistency.
|
Addressed the constructor-read and spec-registration items from this review in 9b3049a. Summary: Constructor-time protocol reads — pulled the live adopter reads out of every helper flagged here. Each now takes the derived addresses/constants as explicit constructor args, matching the existing
All concrete inheritors were updated to thread the new args through. Assertion spec registration — added Verification — all 20 foundry profiles still build clean, and Deferred to a follow-up: the CI matrix / per-protocol tests concern. That is a meaningful change in test scope and I didn't want to bundle it with this fix. Happy to open a separate PR that wires a |
Brings assertion examples from the per-protocol branches (aave, aerodrome, cap, curve, denaria, euler, nado, royco, safe, spark, symbiotic, tydro, uniswap, veda, zeroex) into examples//src/ on a single branch.
Each protocol is compiled standalone via a new [profile.] in foundry.toml that shares the root src/ (credible-std) and lib/ via the credible-std/ remapping — no nested foundry projects, no duplicated submodules. Imports in extracted files are rewritten to the credible-std/ remapping form.
Root src/ is extended with the missing protection bases that examples depend on (access_control/*, perpetual/PerpetualBaseAssertion + IPerpetualProtectionSuite). AaveV3LikeOperationSafety is upgraded to the full version that exposes AaveV3LikeProtectionSuite. PhEvm gains the marketPrice precompile signature and IAaveV3LikeOracle gains BASE_CURRENCY / BASE_CURRENCY_UNIT.
All 20 foundry profiles build clean.