-
Notifications
You must be signed in to change notification settings - Fork 43
Niv/fix sanity failure #183
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: cli-beta
Are you sure you want to change the base?
Conversation
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.
Minor nits and questions - looks ok for me.
// invariant version is getting SANITY_FAILURE using the below rule instead | ||
// invariant lockStatusDontChange() | ||
// !contract_lock_status; |
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.
Which sanity failure did you receive on this invariant?
I couldn't find a link to a failing job here:
https://certora.atlassian.net/browse/CERT-9252
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.
would also like to know what was wrong with the invariant, it looks ok and we still want such invariants. do you have a link to the original spec with the sanity failures
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.
../repo/CVLByExample/TransientStorage/Hooks/runTransientStorage.conf
https://vaas-stg.certora.com/output/52759/0105a027db864c0bb9897978e361037d?anonymousKey=6f78ed30dd77d25d27ec6cefcbf5ad358a62efe9
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 reverted the change by Niv and make this invariant working again.
The issue here is / was that there is a hook on tload/tstore within the constructor and the hooks call out to external solidity function of the same contract which isn't allowed within the constructor (the contract hasn't been created yet). In my fix, I removed all calls that are applied in the hook and changed the accesses to constants that are declared in CVL. This is the only solution I could find here.
@@ -129,12 +129,6 @@ hook Sstore _customers[KEY address user].accounts.length uint256 newLength { | |||
numOfAccounts[user] = newLength; | |||
} | |||
|
|||
/** | |||
An internal step check to verify that our ghost works as expected, it should mirror the number of accounts. | |||
Once the sload is defined, this invariant becomes a tautology |
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.
Once the sload is defined, this invariant becomes a tautology
Is sload now defined nowadays, so is this why we see the sanity failure for trivial post condition of the invariant?
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.
After reviewing, I suggest we indeed remove this invariant as it fails on SANITY due to the tautology check.
CERT-9252 | Fix sanity failures in induction base for major version 8
// invariant version is getting SANITY_FAILURE using the below rule instead | ||
// invariant lockStatusDontChange() | ||
// !contract_lock_status; |
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.
would also like to know what was wrong with the invariant, it looks ok and we still want such invariants. do you have a link to the original spec with the sanity failures
@@ -1,14 +1,11 @@ | |||
invariant isUnlocked(env e) | |||
getLock(e) == 0; | |||
|
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 was the sanity failure? we prefer invariant as the requireinvariant is safer
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.
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.
The issue here was that a few functions (repay, borrow, callback) use a modifier onlyLocked
that contract with the actual invariant and cause vacuity. I filtered them for this invariant.
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.
@nd-certora @yoav-el-certora please re-review.
- The issue with
lockStatusDontChange
was that a hook in the constructor called an external method on the same contract - this causes vacuity as the contract doesn't exist yet. This is also not allowed in solidity itself. - I added a new function
changeLock
which shows that the invariant fails forlockStatusDontChange
. This is expected, @yoav-el-certora. Please update output.json expectedly. - For
isUnlocked
a filter for a few function was needed.
@@ -129,12 +129,6 @@ hook Sstore _customers[KEY address user].accounts.length uint256 newLength { | |||
numOfAccounts[user] = newLength; | |||
} | |||
|
|||
/** | |||
An internal step check to verify that our ghost works as expected, it should mirror the number of accounts. | |||
Once the sload is defined, this invariant becomes a tautology |
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.
After reviewing, I suggest we indeed remove this invariant as it fails on SANITY due to the tautology check.
@@ -4,5 +4,6 @@ | |||
], | |||
"verify": "MockMutexer:./Mutexer.spec", | |||
"solc": "solc8.24", | |||
"solc_evm_version": "cancun" | |||
"solc_evm_version": "cancun", | |||
"prover_args": ["-enableStorageSplitting false"] |
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 was needed here as we got storage splitting failures otherwise. @christiane-certora do you know if this is expected here?
The contract defines a constant slot via keccak256("Mutexer.CONTRACT_LOCK")
and then in spec uses alltload/alltstore.
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.
If the contract uses ALLTLOAD or ALLTSTORE, you should get an error that storage splitting must be disabled, these hook types are not compatible with it (same as the non-transient versions of them).
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.
So should we instead rather use TLOAD and TSTORE here directly (now that we support them?)
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.
It looks like we could, yeah, although the currently used way of course also still works.
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.
But maybe it is not so bad to leave this example, since there are still a lot of patterns with transient storage where we will fail the storage analysis (when the slot accessed is just a parameter, typically), so in that case it could be useful to still see how it can be worked with without.
@@ -1,14 +1,11 @@ | |||
invariant isUnlocked(env e) | |||
getLock(e) == 0; | |||
|
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.
The issue here was that a few functions (repay, borrow, callback) use a modifier onlyLocked
that contract with the actual invariant and cause vacuity. I filtered them for this invariant.
uint256 key = CONTRACT_LOCK; | ||
assembly { | ||
value := tload(key) | ||
} | ||
return value == Mutex.Locked; |
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 should actually be _tload()
which is private in the parent contract and cannot be called here.
No description provided.