Closed fubuloubu closed 5 years ago
+1 for #invariant
I support this. Examples of things that this could be useful for:
issue
affects the total supplyx
can only decrease in a function call if msg.sender = x
I'd love to see a longer list of motivating examples put together to help point anyone trying to make fuzz testing, model checking, symbolic execution or formal verification tools in the right direction.
For 4. (balance can only decrease in a function call for a given address x) how does a syntax like this look?
#invariant self.balance[x] >= funName(sender=x) then self.balance[x], where x = any(address)
#invariant a.balance < any(method) then a.balance, where a not in [x, y, z]
Where any(method)
just means any callable function inside the contract, and assume a
is the sender.
I think 5 and 6 would be a job for an interactive theorem prover. @pirapira you're interested in proving dapp level correctness properties, right? Or are you focused on compiler correctness?
@fubuloubu is this the issue you suggested making for the should
keyword? It seems to have expanded to a larger scope.
As I imagined it, should
is a very user friendly and easy to implement, but relatively limited way of communicating intent to any theorem prover. The syntax is exactly the same as assert
, except you restrict the expression to be side effect free. To a theorem prover it is a goal and, once proved, a lemma.
A major use would be to express some complex precondition on a private helper function that can't be expressed using the type system.
Could also be used for optimization. A concrete (but trivial) example from one of the few contracts I've written, our suggested fix for the delegating voting example (still untested): the function forward_weight
gets called both internally/privately (by delegate
) and externally/publicly (forgive me for not knowing the Solidity terminology). For the internal call, the two assert
statements could be skipped. Communicate that to the compiler by expressing both assertions as invariants before the call to forward_weight
on line 103.
I first want a Viper interpreter in a theorem prover. Then I can test the Viper definition in the theorem provers against their actual behavior.
Deprecated in favor of #711
It would be really awesome if Viper had some sort of internal auditing capabilities that could warn you if/when/under what conditions certain methods could fail. Additionally, to be able to add rules to the source file (that do not get compiled) dictating what non-exceptional scenarios constitute a failure. Suggested keyword (from #370) is
should
, but I think#invariant
or#assume
would be better.As an example, the
company.v.py
example has two different scenarios I could envision this working with:might produce something like this:
Adding a
#invariant
should check if that condition is ever possiblewhich might produce something like:
Alerting you to the fact that you should add an assertion to
transfer_stock()
to ensuretransfer_order
is never negative, which has the additional side effect of allowing someone to steal stock from another person (this is not necessarily caught in this example, but the fact the Audit Module caught one weird scenario can help alert you to the bigger problem).While this is not a good substitute for an audit by a human for potential functional issues (like being able to steal stock), it does provide a cool guarentee that you can audit code written in variable against commonly employed attacks (basically whatever we build in to the Audit Module). Viper is currently simple enough (no inheritance, limited support for arrays, limited types, etc.) that this is possible to implement, and it can also help alert us to issues in the underlying compiler over time.