In this chapter, we will review the pitfalls and different methods of verifying invariants over arrays.
Here we show that taking a naive approach will often fail.
Consider the Array
contract in Array.sol, and its
specification in Array.spec.
-
The
uniqueArray
invariant (in Array.spec) verifies on thepush()
method. However, thepush()
method does not ensure the elements inarrOfTokens
are unique. Do you understand why the invariant held - what is the mistake?Hint.
Recall that by default the Prover ignores reverting paths.
-
On the other hand, the
uniqueArrayUsingRevert
invariant fails to verify, but its failure is unrelated to the solidity code in Array.sol. Indeed this invariant is useless, do you understand why?Hint.
What is the value of
get@withrevert(i)
when the function does revert? -
Fix the
uniqueArray
invariant so it correctly verifies that elements in the array are unique (except perhaps foraddress(0)
). Check that the new invariant indeed fails on thepush()
method.Hint.
Use
getWithDefaultValue
method. A solution can be found in ArraySemiFixed.spec. -
A partial fix to the solidity code in Array.sol is found in ArrayImproved.sol. There, the code prevents pushing the same address twice, using a mapping indicating which addresses were pushed. Modify the
uniqueArray
invariant, and add additional invariants, souniqueArray
is verified on ArrayImproved.sol.Solution.
See Array.spec.
Take a look in ArrayUniqueBug.sol. Here the contract maintains a unique array of addresses by ensuring that the address to be pushed is not already in the array. We will see how to write invariants for this pattern.
-
The contract
ArrayUniqueBug
(from ArrayUniqueBug.sol) has bugs. It allows the array to become non-unique. Fix the contract by requiringfrequence(value) == 0
in the appropriate places. Save the fixed contract asArraySolution.sol
and name the contractArraySolution
. -
The
uniqueArray
invariant in ArrayUniqueBug.spec will identify the buggy methods in ArrayUniqueBug.sol. However, it will still fail on correct methods inArraySolution
(e.g.swap(uint256,uint256)
). Fix theuniqueArray
invariant, by usingrequireInvariant
. Verify thatArraySolution
passes without violation, whileArrayUniqueBug
still fails.Hint.
You must ensure that
frequency
does not get too high.