2.5. Parametric rules¶
We continue with our ERC20 example, to demonstrate parametric rules.
The need¶
Many properties can be generalized for all the contract’s functions. For example, consider the property:
- Allowance integrity:
The
allowance
can only be changed by the owner.
This property should hold regardless of the contract method called. To do so, we introduce the notion of parametric rules.
Usage¶
Applying¶
To simulate the execution of all functions in the main contract we use a method variable
method f
, either as a parameter to the rule, or as a local variable.
The most common usage is to simulate any method on any arguments, using the following
syntax:
rule someParametricRule(method f) {
...
env e; // The env for f
calldataarg args; // Any possible arguments for f
f(e, args); // Calling the contract method f
...
}
Different functions in the contract might have different number or types of parameters.
Using a variable of CVL type calldataarg
solves this problem and ensures that
each simulated contract method gets valid input parameters.
Referring to particular methods¶
At times, we need to handle particular methods differently. For example we sometimes
wish to exclude certain methods from the rule. To differentiate between methods (or
values of method f
) use selector
and sig
, like so:
f.selector == sig:approve(address, uint).selector
The above evaluates to true
when f
is the method approve
with
the specified signature.
Here is a more complete example from Parametric.spec:
// Assert that if the allowance changed then `approve` or `increaseAllowance` was called.
assert (
allowance_after > allowance_before =>
(
f.selector == sig:approve(address, uint).selector ||
f.selector == sig:increaseAllowance(address, uint).selector
)
),
"only approve and increaseAllowance can increase allowances";
}
Example¶
Run the parametric rule from Parametric.spec:
certoraRun ERC20.sol --verify ERC20:Parametric.spec --solc solc8.0 --msg "Parametric rule"
The rule would have a check mark (i.e. passed verification) only if it was verified on all contract methods. An inner rule is created for every function in the main contract, as you can see in the report page. Click on the function name to see its counter-example.
This rule uncovers a bug in decreaseAllowance
method.
Can you understand the counter-example?
Conclusion¶
Parametric rules enable expressing reusable and concise correctness conditions. Note that they are not dependent on the implementation. So you can integrate them easily into the CI to verify changes to the code, including signature changes, new functions, and implementation changes.