Function Annotations
Function specifications are used to specify the behaviour of a single function.
Last updated
Was this helpful?
Function specifications are used to specify the behaviour of a single function.
Last updated
Was this helpful?
Scribble currently has a single type of function specification, called if_succeeds
. Using if_succeeds, annotations you can assert properties that you expect to hold if (and only if) the annotated function successfully terminates.
These annotations have the following structure & are placed right above a function declaration:
The following is a simple example property, where we check that the function always returns 0.
Note that as of Scribble 0.4.0 you can also specify an if_succeeds
annotation at the contract level. See the .
Pre- and postconditions are frequently used concepts in verification languages.
A precondition is what should be true before a function is executed.
A postcondition is what should be true after the function, if the precondition was true.
In it's simplest form if_succeeds
allows you to write postconditions (i.e. properties over the state after the function is done).
We expect that a selfdestruct function only succeeds if the transaction sender is the owner of the contract.
Functions can have multiple behaviors depending on the inputs and contract state. Take the following example of a simple calculator function implementing multiplication and addition.
In this case, there are two distinct behaviors: multiplication and addition. Writing two separate post-conditions wouldn't work, since scribble
checks the conjunction of all function annotations.
Luckily, you can use the implication operator here to describe the conditions under which each behavior holds:
As of Scribble 0.4.0 you can also specify an if_succeeds
annotation at the contract level. A contract-level if_succeeds
is automatically applied to all public and external functions in the annotated contract, and all inheriting contracts. For example, in the below sample the annotation x > 0
will be applied to the functions A.pubFun
, A.externFun
and B.pubFunB
. Note that pure
and view
functions are skipped. So in the below example A.pubViewFun
will not be annotated.
Note that since the same expression needs to hold for an unknown set of functions, when writing a contract-level if_succeeds
function you can only talk about the contract's state vars, and other global transaction state. You cannot refer to function arguments/returns (even if all functions in the contract have the same arguments or returns).
However, if_succeeds is quite versatile and you can use it to check preconditions as well. You'd do so by using the .