Skip to content

Conversation

@QGarchery
Copy link
Collaborator

@QGarchery QGarchery commented Oct 13, 2025

Based on #686

The motivation is to improve the rule sentinelCanDeallocate, by linking the corresponding adapters. So instead of summarizing the adapter.deallocate call, the underlying protocol withdrawal is summarized (inside adapter.deallocate). This allows to take into account the revert reasons that could potentially happen inside the function adapter.deallocate (other than the ones in the protocol withdrawal of course).

Also in this PR:

  • revamp sentinel liveness (document rules, format, explain assumptions)
  • link every deallocate requirement to a proven rule
    • underflows
    • overflow before
    • overflow after
    • unique ids
  • linked version to show that reverts only happen on the underlying protocol
  • remove VaultV2Harness

@QGarchery QGarchery changed the base branch from certora/import-chainsecurity-specs to feat/verif/allocations-alt October 13, 2025 08:39
}


function morphoMarketV1AdapterDeallocateWrapper(address adapter, env e, bytes data, uint256 assets, bytes4 selector, address sender) returns (bytes32[], int256) {
Copy link
Collaborator Author

@QGarchery QGarchery Oct 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 3 following requires give an upper limit to the allocation that is relative to max_int256.

  1. require MorphoMarketV1Adapter.allocation(marketParams) <= max_int256()
  2. require forall uint256 i. i < ids.length => currentContract.caps[ids[i]].allocation <= max_int256()
  3. require forall uint256 i. i < ids.length => currentContract.caps[ids[i]].allocation + change <= max_int256()

Weirdly they are all needed.
Require 2 is needed because VaultV2 does int256(_caps.allocation) + change, so _caps.allocation == 2**255 and change == -1 would yield a revert in the vault for example (even with require 1 & 3).
Require 3 is needed because VaultV2 does (int256(_caps.allocation) + change).toUint256();. Note that this require is not proven elsewhere, so it's an assumption of the rule, and it is added as such in the description of that rule.
Require 1 is needed as well but it's less intuitive why as it's a special case of require 2. The reason is that when your rule calls a function with @withrevert, the require that are written after the function call are not taken into account yet. In this case, the deallocate call of the adapter could revert when doing int256(newAllocation) - int256(oldAllocation), with newAllocation == 0 and oldAllocation == type(int256).min

@QGarchery QGarchery self-assigned this Oct 13, 2025
@QGarchery QGarchery marked this pull request as ready for review October 13, 2025 17:27
@QGarchery QGarchery changed the title [Certora] Revamp sentinel liveness (WIP) [Certora] Revamp sentinel liveness Oct 14, 2025
Base automatically changed from feat/verif/allocations-alt to main November 19, 2025 16:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants