-
Notifications
You must be signed in to change notification settings - Fork 36
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
SMT: Arithmetic bounds checking #109
Labels
enhancement
New feature or request
Comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
One of the major differences between the act language and EVM lies in the treatment of arithmetic. EVM arithmetic operates on 256 bit words with overflow, whereas act arithmetic operates on unbounded integers and never overflows.
In order to ensure that properties proved against the act specification are sound wrt to the implementation, we need to ensure that the specifications do not make claims about arithmetic expressions that would overflow if implemented in EVM, but do not when expressed as an act.
This analysis should be performed against the expressions in the
storage
,creates
andreturns
blocks only. Expressions in theiff
,ensures
andinvariants
blocks are making claims about the spec only, and so do not need to be expressible in EVM.Note that the presence of arbitrary preconditions over the expressions in question (in the
iff
block) would seem to preclude the possibility of a purely syntactic procedure, meaning we will need to rely on an SMT solver for an automatic analysis. As usual this will probably prove insufficient in the face of complex non-linear arithmetic. We may wish to consider allowing users to export problematic claims to Coq for manual proof if required.As an example consider the following spec:
One potential analysis would proceed by walking up the tree for each top level integer expression (in this case the expressions on the RHS of the updates to
c
innested
andnested1
), and asserting that the range of possible values at each intermediate node is within the range of auint256
or anint256
. This ensures that all subexpressions can be safely represented within an EVM word. The final assertion for the top node in the tree should check that the whole expression is within the range of the LHS of the assignment / update.Note that we probably want to introduce syntax that allows us to specify the expected type of the return value.
As a more specific example we can sketch the expected smt-lib that we would want to produce for the update:
c => (c * c) / (2 ^ 64)
:We would start by declaring all relevant storage variables, all predicates from the
iff
block, and the bounds derived from the types of the variables involved:And continue by asserting that
c * c
can be safely represented in EVM:If this is
unsat
, then we have a proof that the result ofc * c
can be safely represented in an evm word. We can then continue by:c * c
is within the range of an EVM wordc * c / 2 ^ 64
is within the range of anint64
(the type ofc
)If this second query returns
unsat
, then we have a proof that the expression as a whole cannot exceed the bounds of it's type (anint64
).One final consideration is expressions involving explicit calls to
mod
. In these cases, as along as the RHS of themod
would allow the result to fit within the relevant type bounds, then bounds checking can be ignored for the top node of the expression on the LHS of themod
. Note that we cannot safely ignore bounds checking for the nested subexpressions on the LHS as we still need to be sure that the result of each subexpression on the LHS can be safely represented in an EVM word. An example:In this case the assignment to
a
is safe (can never overflow), while the assignment tob
is unsafe and should result in an error.The text was updated successfully, but these errors were encountered: