Thanks to visit codestin.com
Credit goes to github.com

Skip to content

symbolic storage variables are not included in the counterexample model #577

@0xkarmacoma

Description

@0xkarmacoma
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;

import "forge-std/Test.sol";
import {console2} from "forge-std/console2.sol";

import {SymTest} from "halmos-cheatcodes/SymTest.sol";

contract Counter {
    uint256 public number;

    function increment() public {
        number++;
    }
}

contract CounterHalmosTest is Test, SymTest {
    Counter public counter;

    function setUp () public {
        counter = new Counter();
        svm.enableSymbolicStorage(address(counter));
    }


    function check_isIncrementFeasible() public {
        vm.assume(counter.number() != 2);
        counter.increment();
        assertTrue(!(counter.number() == 2), "number is 2");
    }
}

Running halmos on this function returns:

Counterexample: ∅
[FAIL] check_isIncrementFeasible() (paths: 3, time: 0.14s, bounds: [])

Ideally we would see the number value that results in the counterexample.

Investigation

We can see what's happening by inspecting the smt output, for instance:

halmos --function check_isIncrementFeasible --dump-smt-queries --solver z3 -vv        

# <snip>

Executing check_isIncrementFeasible
Found potential path with path_id=2 (fail flag set) VmAssertion(cond=Not(storage_0x00000000000000000000000000000000aaaa0002_256_00[0] == 1), msg='number is 2')
Checking path condition path_id=2
# of potential paths involving assertion violations: 1 / 3 (--solver-threads 20)
  Checking with external solver process
    /usr/local/bin/z3 /var/folders/p9/s6g8495n6dqdjq3nn8hkdn840000gn/T/check_isIncrementFeasible-r3_713gv/2.smt2 > /var/folders/p9/s6g8495n6dqdjq3nn8hkdn840000gn/T/check_isIncrementFeasible-r3_713gv/2.smt2.out
cat /var/folders/p9/s6g8495n6dqdjq3nn8hkdn840000gn/T/check_isIncrementFeasible-r3_713gv/2.smt2.out     
sat
(
  (define-fun storage_0x00000000000000000000000000000000aaaa0002_256_00 () (Array (_ BitVec 256) (_ BitVec 256))
    ((as const (Array (_ BitVec 256) (_ BitVec 256)))
  #x0000000000000000000000000000000000000000000000000000000000000001))
  (define-fun storage_0x7fa9385be102ac3eac297483dd6233d62b3e1496_256_00 () (Array (_ BitVec 256) (_ BitVec 256))
    ((as const (Array (_ BitVec 256) (_ BitVec 256)))
  #x0000000000000000000000000000000000000000000000000000000000000000))
  (define-fun storage_0x7fa9385be102ac3eac297483dd6233d62b3e1496_256_da8f873_01 () (Array (_ BitVec 256) (_ BitVec 256))
    (store ((as const (Array (_ BitVec 256) (_ BitVec 256)))
         #x0000000000000000000000000000000000000000000000000000000000000000)
       #x000000000000000000000000000000000000000000000000000000000000000c
       #x0000000000000000000000000000000000000000000000000000000000000001))
  (define-fun storage_0x00000000000000000000000000000000aaaa0002_256_2940072_04 () (Array (_ BitVec 256) (_ BitVec 256))
    (store ((as const (Array (_ BitVec 256) (_ BitVec 256)))
         #x0000000000000000000000000000000000000000000000000000000000000001)
       #x0000000000000000000000000000000000000000000000000000000000000000
       #x0000000000000000000000000000000000000000000000000000000000000002))
  (define-fun storage_0x7fa9385be102ac3eac297483dd6233d62b3e1496_256_af2032d_03 () (Array (_ BitVec 256) (_ BitVec 256))
    (store (store ((as const (Array (_ BitVec 256) (_ BitVec 256)))
                #x0000000000000000000000000000000000000000000000000000000000000000)
              #x000000000000000000000000000000000000000000000000000000000000000c
              #x0000000000000000000000000000000000000000000000000000000000000001)
       #x000000000000000000000000000000000000000000000000000000000000001f
       #x000000000000000000000000000000000000000000000000000000aaaa000201))
  (define-fun balance_00 () (Array (_ BitVec 160) (_ BitVec 256))
    ((as const (Array (_ BitVec 160) (_ BitVec 256)))
  #x0000000000000000000000000000000000000000000000000000000000000000))
  (define-fun balance_99ac464_01 () (Array (_ BitVec 160) (_ BitVec 256))
    (store ((as const (Array (_ BitVec 160) (_ BitVec 256)))
         #x0000000000000000000000000000000000000000000000000000000000000000)
       #x7fa9385be102ac3eac297483dd6233d62b3e1496
       #x0000000000000000000000000000000000000000ffffffffffffffffffffffff))
  (define-fun storage_0x7fa9385be102ac3eac297483dd6233d62b3e1496_256_1bfa2a2_02 () (Array (_ BitVec 256) (_ BitVec 256))
    (store (store ((as const (Array (_ BitVec 256) (_ BitVec 256)))
                #x0000000000000000000000000000000000000000000000000000000000000000)
              #x000000000000000000000000000000000000000000000000000000000000000c
              #x0000000000000000000000000000000000000000000000000000000000000001)
       #x000000000000000000000000000000000000000000000000000000000000001f
       #x0000000000000000000000000000000000000000000000000000000000000001))
)

The important bit is that storage_0x00000000000000000000000000000000aaaa0002_256_00 has value #x0000000000000000000000000000000000000000000000000000000000000001, but it's not captured by the halmos_var_pattern regex in solve.py.

Also note that there is plenty of other stuff in the output that would likely just add noise to the model.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions