ethereum / solidity

Solidity, the Smart Contract Programming Language
https://soliditylang.org
GNU General Public License v3.0
23.42k stars 5.78k forks source link

[SMTChecker] Study Spacer's limits #10790

Closed leonardoalt closed 1 year ago

leonardoalt commented 3 years ago

Collecting some samples here where Spacer fails to prove/refute something, to try to understand why.

A few small but not necessarily simple examples from our own test suite: abi/abi_encode_with_selector_vs_sig.sol operators/compound_bitwise_or_uint_1.sol operators/slice_default_start.sol external_calls/external_inc.sol loops/for_1_fail.sol

blishko commented 3 years ago

Analysis of loops/for_1_fail.sol: This example is a relatively simple for loop where Spacer does not seem to be able to prove that increment insider the loop body does not overflow. This actually requires only integer reasoning and so Spacer should be able to deal with it. In fact, after Horn clauses produced by our encoding has been stripped off the unnecessary blockchain-related variables, Spacer immediately solved it.

Further investigation showed that the reason of divergence in this case are the transaction data. When that variable has been removed from the encoding, Spacer solved the problem. In fact, it is sufficient to remove only all constraints related to the transaction variable tx_0 and then Spacer probably figures out that it can slice the variable away and solves the problem.

This has been confirmed also directly: Changing the encoding so that SymbolicState::txConstraints returns smtutil::Expression(true) leads to successful proof that the overflow cannot happen in this example.

Running isoltest with disabled transaction constraints gave mixed results:

leonardoalt commented 1 year ago

Over time we learned that our heavy use of ADTs was a problem for Spacer. This has been improved in the solver since then.