def test_ITEBV_2(self): solver = Z3Solver.instance() cs = ConstraintSet() a = cs.new_bitvec(8) b = cs.new_bitvec(8) c = cs.new_bitvec(8) cs.add(b == 0x44) cs.add(c == 0x44) cs.add(a == Operators.ITEBV(8, b == c, b, c)) self.assertTrue(solver.check(cs)) self.assertEqual(solver.get_value(cs, a), 0x44)
def test_mulmod(self): """ (declare-fun BV () (_ BitVec 256)) (declare-fun BV_2 () (_ BitVec 256)) (declare-fun BV_1 () (_ BitVec 256)) (declare-fun a_1 () (_ BitVec 256))(assert (= a_1 (bvmul BV BV_1))) (declare-fun a_2 () (_ BitVec 512))(assert (= a_2 ((_ zero_extend 256) BV))) (declare-fun a_3 () (_ BitVec 512))(assert (= a_3 ((_ zero_extend 256) BV_1))) (declare-fun a_4 () (_ BitVec 512))(assert (= a_4 (bvmul a_2 a_3))) (declare-fun a_5 () (_ BitVec 512))(assert (= a_5 ((_ zero_extend 256) BV_2))) (declare-fun a_6 () (_ BitVec 512))(assert (= a_6 (bvsmod a_4 a_5))) (declare-fun a_7 () (_ BitVec 256))(assert (= a_7 ((_ extract 255 0) a_6))) (declare-fun a_8 () (_ BitVec 256))(assert (= a_8 (bvsmod a_1 BV_2))) (declare-fun a_9 () Bool)(assert (= a_9 (= a_7 a_8))) (assert (not a_9)) (check-sat) """ from manticore.platforms import evm from manticore.core.smtlib import ConstraintSet, Z3Solver, Operators constraints = ConstraintSet() address = 0x41414141414141414141 data = b"" caller = 0x42424242424242424242 value = 0 bytecode = "" vm = evm.EVM(constraints, address, data, caller, value, bytecode) self.assertEqual(vm.MULMOD(12323, 2343, 20), 9) self.assertEqual(vm.MULMOD(12323, 2343, 0), 0) A, B, C = ( 110427941548649020598956093796432407239217743554726184882600387580788736, 1048576, 4194319, ) self.assertEqual(vm.MULMOD(A, B, C), 2423129) a, b, c = ( constraints.new_bitvec(256), constraints.new_bitvec(256), constraints.new_bitvec(256), ) constraints.add(a == A) constraints.add(b == B) constraints.add(c == C) result = vm.MULMOD(a, b, c) # 0x8000000000000000000000000000000000000000000000000000000082000011 self.assertEqual( Z3Solver.instance().get_all_values(constraints, result), [2423129])
def test_CONCAT(self): solver = Z3Solver.instance() cs = ConstraintSet() a = cs.new_bitvec(16) b = cs.new_bitvec(8) c = cs.new_bitvec(8) cs.add(b == 0x41) cs.add(c == 0x42) cs.add(a == Operators.CONCAT(a.size, b, c)) self.assertTrue(solver.check(cs)) self.assertEqual(solver.get_value(cs, a), Operators.CONCAT(a.size, 0x41, 0x42))
def testBasicArraySymbIdx(self): cs = ConstraintSet() array = cs.new_array(index_bits=32, value_bits=32, name="array") key = cs.new_bitvec(32, name="key") index = cs.new_bitvec(32, name="index") array[key] = 1 # Write 1 to a single location cs.add(array.get(index, default=0) != 0) # Constrain index so it selects that location cs.add(index != key) # key and index are the same there is only one slot in 1 self.assertFalse(self.solver.check(cs))
def test_SAR(self): solver = self.solver A = 0xBADF00D for B in range(32): cs = ConstraintSet() a = cs.new_bitvec(32) b = cs.new_bitvec(32) c = cs.new_bitvec(32) cs.add(c == Operators.SAR(32, a, b)) cs.add(a == A) cs.add(b == B) self.assertTrue(solver.check(cs)) self.assertEqual(solver.get_value(cs, c), Operators.SAR(32, A, B))
def testBasicPickle(self): import pickle cs = ConstraintSet() #make array of 32->8 bits array = cs.new_array(32) #make free 32bit bitvector key = cs.new_bitvec(32) #assert that the array is 'A' at key position array = array.store(key, ord('A')) #let's restrict key to be greater than 1000 cs.add(key.ugt(1000)) cs = pickle.loads(pickle.dumps(cs)) self.assertTrue(self.solver.check(cs))
def test_signed_unsigned_LT_complex(self): mask = (1 << 32) - 1 cs = ConstraintSet() _a = cs.new_bitvec(32) _b = cs.new_bitvec(32) cs.add(_a == 0x1) cs.add(_b == (0x80000000 - 1)) a = _a & mask b = (_b + 1) & mask lt = b < a ult = b.ult(a) self.assertFalse(self.solver.can_be_true(cs, ult)) self.assertTrue(self.solver.must_be_true(cs, lt))
def testBitvector_max(self): cs = ConstraintSet() a = cs.new_bitvec(32) cs.add(a <= 200) cs.add(a >= 100) self.assertTrue(self.solver.check(cs)) self.assertEqual(self.solver.minmax(cs, a), (100, 200)) from manticore import config consts = config.get_group("smt") consts.optimize = False cs = ConstraintSet() a = cs.new_bitvec(32) cs.add(a <= 200) cs.add(a >= 100) self.assertTrue(self.solver.check(cs)) self.assertEqual(self.solver.minmax(cs, a), (100, 200)) consts.optimize = True
def test_ULE(self): solver = Z3Solver.instance() cs = ConstraintSet() a = cs.new_bitvec(8) b = cs.new_bitvec(8) c = cs.new_bitvec(8) cs.add(a == 0x1) # 1 cs.add(b == 0x86) # -122 cs.add(c == 0x11) # 17 self.assertTrue(solver.must_be_true(cs, Operators.ULE(a, b))) self.assertTrue(solver.must_be_true(cs, Operators.ULE(a, c))) self.assertTrue(solver.must_be_true(cs, Operators.ULE(c, b))) self.assertTrue(solver.must_be_true(cs, Operators.ULE(a, 0xF2))) self.assertTrue(solver.must_be_true(cs, Operators.ULE(b, 0x99))) self.assertTrue(solver.must_be_true(cs, Operators.ULE(c, 0x12))) self.assertTrue(solver.must_be_true(cs, Operators.ULE(3, 0xF2))) self.assertTrue(solver.must_be_true(cs, Operators.ULE(3, 3))) self.assertTrue(solver.must_be_true(cs, Operators.ULE(1, a))) self.assertTrue(solver.must_be_true(cs, Operators.ULE(0x85, b))) self.assertTrue(solver.must_be_true(cs, Operators.ULE(0x10, c)))
def test_ULT(self): solver = self.solver cs = ConstraintSet() a = cs.new_bitvec(8) b = cs.new_bitvec(8) c = cs.new_bitvec(8) cs.add(a == 0x1) # 1 cs.add(b == 0x86) # -122 cs.add(c == 0x11) # 17 self.assertTrue(solver.must_be_true(cs, Operators.ULT(a, b))) self.assertTrue(solver.must_be_true(cs, Operators.ULT(a, c))) self.assertTrue(solver.must_be_true(cs, Operators.ULT(c, b))) self.assertTrue(solver.must_be_true(cs, Operators.ULT(a, 0xF2))) self.assertTrue(solver.must_be_true(cs, Operators.ULT(b, 0x99))) self.assertTrue(solver.must_be_true(cs, Operators.ULT(c, 0x12))) self.assertTrue(solver.must_be_true(cs, Operators.ULT(3, 0xF2))) self.assertTrue(solver.must_be_true(cs, Operators.ULT(3, 4))) self.assertTrue(solver.must_be_true(cs, Operators.ULT(0, a))) self.assertTrue(solver.must_be_true(cs, Operators.ULT(0x85, b))) self.assertTrue(solver.must_be_true(cs, Operators.ULT(0x10, c)))
def testBasicArrayStore(self): name = "bitarray" cs = ConstraintSet() # make array of 32->8 bits array = cs.new_array(32, name=name) # make free 32bit bitvector key = cs.new_bitvec(32) # assert that the array is 'A' at key position array = array.store(key, ord("A")) # let's restrict key to be greater than 1000 cs.add(key.ugt(1000)) # 1001 position of array can be 'A' self.assertTrue( self.solver.can_be_true(cs, array.select(1001) == ord("A"))) # 1001 position of array can be 'B' self.assertTrue( self.solver.can_be_true(cs, array.select(1001) == ord("B"))) # name is correctly proxied self.assertEqual(array.name, name) with cs as temp_cs: # but if it is 'B' ... temp_cs.add(array.select(1001) == ord("B")) # then key can not be 1001 temp_cs.add(key == 1001) self.assertFalse(self.solver.check(temp_cs)) with cs as temp_cs: # If 1001 position is 'B' ... temp_cs.add(array.select(1001) == ord("B")) # then key can be 1002 for ex.. temp_cs.add(key != 1002) self.assertTrue(self.solver.check(temp_cs))
def testBasicArray256(self): cs = ConstraintSet() # make array of 32->8 bits array = cs.new_array(32, value_bits=256) # make free 32bit bitvector key = cs.new_bitvec(32) # assert that the array is 111...111 at key position cs.add(array[key] == 11111111111111111111111111111111111111111111) # let's restrict key to be greater than 1000 cs.add(key.ugt(1000)) with cs as temp_cs: # 1001 position of array can be 111...111 temp_cs.add( array[1001] == 11111111111111111111111111111111111111111111) self.assertTrue(self.solver.check(temp_cs)) with cs as temp_cs: # 1001 position of array can also be 222...222 temp_cs.add( array[1001] == 22222222222222222222222222222222222222222222) self.assertTrue(self.solver.check(temp_cs)) with cs as temp_cs: # but if it is 222...222 ... temp_cs.add( array[1001] == 22222222222222222222222222222222222222222222) # then key can not be 1001 temp_cs.add(key == 1001) self.assertFalse(self.solver.check(temp_cs)) with cs as temp_cs: # If 1001 position is 222...222 ... temp_cs.add( array[1001] == 22222222222222222222222222222222222222222222) # then key can be 1002 for ex.. temp_cs.add(key == 1002) self.assertTrue(self.solver.check(temp_cs))
def test_UDIV(self): cs = ConstraintSet() a = cs.new_bitvec(8) b = cs.new_bitvec(8) c = cs.new_bitvec(8) d = cs.new_bitvec(8) cs.add(b == 0x86) #134 cs.add(c == 0x11) #17 cs.add(a == Operators.UDIV(b, c)) cs.add(d == b.udiv(c)) cs.add(a == d) self.assertTrue(solver.check(cs)) self.assertEqual(solver.get_value(cs, a), 7)
def test_SREM(self): cs = ConstraintSet() a = cs.new_bitvec(8) b = cs.new_bitvec(8) c = cs.new_bitvec(8) d = cs.new_bitvec(8) cs.add(b == 0x86) #-122 cs.add(c == 0x11) #17 cs.add(a == Operators.SREM(b, c)) cs.add(d == b.srem(c)) cs.add(a == d) self.assertTrue(solver.check(cs)) self.assertEqual(solver.get_value(cs, a), -3 & 0xFF)
def test_SDIV(self): solver = self.solver cs = ConstraintSet() a = cs.new_bitvec(8) b = cs.new_bitvec(8) c = cs.new_bitvec(8) d = cs.new_bitvec(8) cs.add(b == 0x86) # -122 cs.add(c == 0x11) # 17 cs.add(a == Operators.SDIV(b, c)) cs.add(d == (b // c)) cs.add(a == d) self.assertTrue(solver.check(cs)) self.assertEqual(solver.get_value(cs, a), -7 & 0xFF)
def test_UREM(self): solver = Z3Solver.instance() cs = ConstraintSet() a = cs.new_bitvec(8) b = cs.new_bitvec(8) c = cs.new_bitvec(8) d = cs.new_bitvec(8) cs.add(b == 0x86) # 134 cs.add(c == 0x11) # 17 cs.add(a == Operators.UREM(b, c)) cs.add(d == b.urem(c)) cs.add(a == d) self.assertTrue(solver.check(cs)) self.assertEqual(solver.get_value(cs, a), 0xF)
def testBasicArray(self): cs = ConstraintSet() # make array of 32->8 bits array = cs.new_array(32) # make free 32bit bitvector key = cs.new_bitvec(32) # assert that the array is 'A' at key position # By default an smtlib can contain any value cs.add(array[key] == ord("A")) # let's restrict key to be greater than 1000 cs.add(key.ugt(1000)) with cs as temp_cs: # 1001 position of array can be 'A' temp_cs.add(array[1001] == ord("A")) self.assertTrue(self.solver.check(temp_cs)) with cs as temp_cs: # 1001 position of array can also be 'B' temp_cs.add(array[1001] == ord("B")) self.assertTrue(self.solver.check(temp_cs)) with cs as temp_cs: # but if it is 'B' ... temp_cs.add(array[1001] == ord("B")) # then key can not be 1001 temp_cs.add(key == 1001) self.assertFalse(self.solver.check(temp_cs)) with cs as temp_cs: # If 1001 position is 'B' ... temp_cs.add(array[1001] == ord("B")) # then key can be 1000 for ex.. temp_cs.add(key == 1002) self.assertTrue(self.solver.check(temp_cs))
def testBitvector_add(self): cs = ConstraintSet() a = cs.new_bitvec(32) b = cs.new_bitvec(32) c = cs.new_bitvec(32) cs.add(c == a + b) cs.add(a == 1) cs.add(b == 10) self.assertTrue(self.solver.check(cs)) self.assertEqual(self.solver.get_value(cs, c), 11)
def test_ITE(self): cs = ConstraintSet() a = cs.new_bool() b = cs.new_bool() c = cs.new_bool() cs.add(b == True) cs.add(c == False) cs.add(a == Operators.ITE(b == c, b, c)) self.assertTrue(solver.check(cs)) self.assertEqual(solver.get_value(cs, a), False)
def testBasicArrayProxySymbIdx(self): cs = ConstraintSet() array = cs.new_array(index_bits=32, value_bits=32, name="array", default=0) key = cs.new_bitvec(32, name="key") index = cs.new_bitvec(32, name="index") array[key] = 1 # Write 1 to a single location cs.add(array.get(index) != 0) # Constrain index so it selects that location a_index = self.solver.get_value(cs, index) # get a concrete solution for index cs.add(array.get(a_index) != 0) # now storage must have something at that location cs.add(a_index != index) # remove it from the solutions # It should not be another solution for index self.assertFalse(self.solver.check(cs))
def testBasicMigration(self): solver = self.solver cs1 = ConstraintSet() cs2 = ConstraintSet() var1 = cs1.new_bitvec(32, "var") var2 = cs2.new_bitvec(32, "var") cs1.add(Operators.ULT(var1, 3)) # var1 can be 0, 1, 2 # make a migration map dict migration_map1 = {} # this expression is composed with variables of both cs expression = var1 > var2 migrated_expression = cs1.migrate(expression, migration_map1) cs1.add(migrated_expression) expression = var2 > 0 migrated_expression = cs1.migrate(expression, migration_map1) cs1.add(migrated_expression) self.assertItemsEqual(solver.get_all_values(cs1, var1), [2]) # should only be [2]
def test_201503110346PYTHON_PUSH24(self): """ Testcase taken from https://github.com/ethereum/tests File: 201503110346PYTHON_PUSH24.json sha256sum: 0f512fa3c9cf0e24e246ca46e8e072745df14f1cdfc8fcf6d201aba5e55f7932 Code: """ def solve(val): return self._solve(constraints, val) constraints = ConstraintSet() blocknumber = constraints.new_bitvec(256, name='blocknumber') constraints.add(blocknumber == 300) timestamp = constraints.new_bitvec(256, name='timestamp') constraints.add(timestamp == 2) difficulty = constraints.new_bitvec(256, name='difficulty') constraints.add(difficulty == 115792089237316195423570985008687907853269984665640564039457584007913129639935) coinbase = constraints.new_bitvec(256, name='coinbase') constraints.add(coinbase == 244687034288125203496486448490407391986876152250) gaslimit = constraints.new_bitvec(256, name='gaslimit') constraints.add(gaslimit == 1000000) world = evm.EVMWorld(constraints, blocknumber=blocknumber, timestamp=timestamp, difficulty=difficulty, coinbase=coinbase, gaslimit=gaslimit) acc_addr = 0xf572e5295c57f15886f9b263e2f6d2d6c7b5ec6 acc_code = unhexlify('7745414245403745f31387900a8d55') acc_balance = constraints.new_bitvec(256, name='balance_0xf572e5295c57f15886f9b263e2f6d2d6c7b5ec6') constraints.add(acc_balance == 1000000000000000000) acc_nonce = constraints.new_bitvec(256, name='nonce_0xf572e5295c57f15886f9b263e2f6d2d6c7b5ec6') constraints.add(acc_nonce == 0) world.create_account(address=acc_addr, balance=acc_balance, code=acc_code, nonce=acc_nonce) address = 0xf572e5295c57f15886f9b263e2f6d2d6c7b5ec6 caller = 0xcd1722f3947def4cf144679da39c4c32bdc35681 price = constraints.new_bitvec(256, name='price') constraints.add(price == 100000000000000) value = constraints.new_bitvec(256, name='value') constraints.add(value == 1000000000000000000) gas = constraints.new_bitvec(256, name='gas') constraints.add(gas == 10000) data = '' # open a fake tx, no funds send world._open_transaction('CALL', address, price, data, caller, value, gas=gas) # This variable might seem redundant in some tests - don't forget it is auto generated # and there are cases in which we need it ;) result, returndata = self._test_run(world) # World sanity checks - those should not change, right? self.assertEqual(solve(world.block_number()), 300) self.assertEqual(solve(world.block_gaslimit()), 1000000) self.assertEqual(solve(world.block_timestamp()), 2) self.assertEqual(solve(world.block_difficulty()), 115792089237316195423570985008687907853269984665640564039457584007913129639935) self.assertEqual(solve(world.block_coinbase()), 0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba) # Add post checks for account 0xf572e5295c57f15886f9b263e2f6d2d6c7b5ec6 # check nonce, balance, code self.assertEqual(solve(world.get_nonce(0xf572e5295c57f15886f9b263e2f6d2d6c7b5ec6)), 0) self.assertEqual(solve(world.get_balance(0xf572e5295c57f15886f9b263e2f6d2d6c7b5ec6)), 1000000000000000000) self.assertEqual(world.get_code(0xf572e5295c57f15886f9b263e2f6d2d6c7b5ec6), unhexlify('7745414245403745f31387900a8d55')) # check outs self.assertEqual(returndata, unhexlify('')) # check logs logs = [Log(unhexlify('{:040x}'.format(l.address)), l.topics, solve(l.memlog)) for l in world.logs] data = rlp.encode(logs) self.assertEqual(sha3.keccak_256(data).hexdigest(), '1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347') # test used gas self.assertEqual(solve(world.current_vm.gas), 9997)
def test_201503110219PYTHON(self): """ Testcase taken from https://github.com/ethereum/tests File: 201503110219PYTHON.json sha256sum: e153bd49bafe6f1e398ddaeb35a9f0493d823b36c3823908211bf371ec95cb1f Code: BLOCKHASH BLOCKHASH GASLIMIT SWAP2 NUMBER BLOCKHASH COINBASE DIFFICULTY DUP1 SWAP8 MSIZE DUP9 """ def solve(val): return self._solve(constraints, val) constraints = ConstraintSet() blocknumber = constraints.new_bitvec(256, name='blocknumber') constraints.add(blocknumber == 300) timestamp = constraints.new_bitvec(256, name='timestamp') constraints.add(timestamp == 2) difficulty = constraints.new_bitvec(256, name='difficulty') constraints.add(difficulty == 115792089237316195423570985008687907853269984665640564039457584007913129639935) coinbase = constraints.new_bitvec(256, name='coinbase') constraints.add(coinbase == 244687034288125203496486448490407391986876152250) gaslimit = constraints.new_bitvec(256, name='gaslimit') constraints.add(gaslimit == 1000000) world = evm.EVMWorld(constraints, blocknumber=blocknumber, timestamp=timestamp, difficulty=difficulty, coinbase=coinbase, gaslimit=gaslimit) acc_addr = 0xf572e5295c57f15886f9b263e2f6d2d6c7b5ec6 acc_code = unhexlify('4040459143404144809759886d608f') acc_balance = constraints.new_bitvec(256, name='balance_0xf572e5295c57f15886f9b263e2f6d2d6c7b5ec6') constraints.add(acc_balance == 1000000000000000000) acc_nonce = constraints.new_bitvec(256, name='nonce_0xf572e5295c57f15886f9b263e2f6d2d6c7b5ec6') constraints.add(acc_nonce == 0) world.create_account(address=acc_addr, balance=acc_balance, code=acc_code, nonce=acc_nonce) address = 0xf572e5295c57f15886f9b263e2f6d2d6c7b5ec6 caller = 0xcd1722f3947def4cf144679da39c4c32bdc35681 price = constraints.new_bitvec(256, name='price') constraints.add(price == 100000000000000) value = constraints.new_bitvec(256, name='value') constraints.add(value == 1000000000000000000) gas = constraints.new_bitvec(256, name='gas') constraints.add(gas == 10000) data = '' # open a fake tx, no funds send world._open_transaction('CALL', address, price, data, caller, value, gas=gas) # This variable might seem redundant in some tests - don't forget it is auto generated # and there are cases in which we need it ;) result, returndata = self._test_run(world) # World sanity checks - those should not change, right? self.assertEqual(solve(world.block_number()), 300) self.assertEqual(solve(world.block_gaslimit()), 1000000) self.assertEqual(solve(world.block_timestamp()), 2) self.assertEqual(solve(world.block_difficulty()), 115792089237316195423570985008687907853269984665640564039457584007913129639935) self.assertEqual(solve(world.block_coinbase()), 0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba) # If test end in exception check it here self.assertTrue(result == 'THROW')
def test_timestamp(self): """ Testcase taken from https://github.com/ethereum/tests File: timestamp.json sha256sum: e0517702c3ba8bc8a593af7dbdb4de4d3ee7a53ae4fffc058776e40c435b20ba Code: TIMESTAMP PUSH1 0x0 SSTORE """ def solve(val): return self._solve(constraints, val) constraints = ConstraintSet() blocknumber = constraints.new_bitvec(256, name='blocknumber') constraints.add(blocknumber == 0) timestamp = constraints.new_bitvec(256, name='timestamp') constraints.add(timestamp == 1) difficulty = constraints.new_bitvec(256, name='difficulty') constraints.add(difficulty == 256) coinbase = constraints.new_bitvec(256, name='coinbase') constraints.add( coinbase == 244687034288125203496486448490407391986876152250) gaslimit = constraints.new_bitvec(256, name='gaslimit') constraints.add(gaslimit == 1000000) world = evm.EVMWorld(constraints, blocknumber=blocknumber, timestamp=timestamp, difficulty=difficulty, coinbase=coinbase, gaslimit=gaslimit) acc_addr = 0xf572e5295c57f15886f9b263e2f6d2d6c7b5ec6 acc_code = unhexlify('42600055') acc_balance = constraints.new_bitvec( 256, name='balance_0xf572e5295c57f15886f9b263e2f6d2d6c7b5ec6') constraints.add(acc_balance == 100000000000000000000000) acc_nonce = constraints.new_bitvec( 256, name='nonce_0xf572e5295c57f15886f9b263e2f6d2d6c7b5ec6') constraints.add(acc_nonce == 0) world.create_account(address=acc_addr, balance=acc_balance, code=acc_code, nonce=acc_nonce) address = 0xf572e5295c57f15886f9b263e2f6d2d6c7b5ec6 caller = 0xcd1722f3947def4cf144679da39c4c32bdc35681 price = constraints.new_bitvec(256, name='price') constraints.add(price == 100000000000000) value = constraints.new_bitvec(256, name='value') constraints.add(value == 1000000000000000000) gas = constraints.new_bitvec(256, name='gas') constraints.add(gas == 100000) data = '' # open a fake tx, no funds send world._open_transaction('CALL', address, price, data, caller, value, gas=gas) # This variable might seem redundant in some tests - don't forget it is auto generated # and there are cases in which we need it ;) result, returndata = self._test_run(world) # World sanity checks - those should not change, right? self.assertEqual(solve(world.block_number()), 0) self.assertEqual(solve(world.block_gaslimit()), 1000000) self.assertEqual(solve(world.block_timestamp()), 1) self.assertEqual(solve(world.block_difficulty()), 256) self.assertEqual(solve(world.block_coinbase()), 0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba) # Add post checks for account 0xf572e5295c57f15886f9b263e2f6d2d6c7b5ec6 # check nonce, balance, code self.assertEqual( solve(world.get_nonce(0xf572e5295c57f15886f9b263e2f6d2d6c7b5ec6)), 0) self.assertEqual( solve( world.get_balance(0xf572e5295c57f15886f9b263e2f6d2d6c7b5ec6)), 100000000000000000000000) self.assertEqual( world.get_code(0xf572e5295c57f15886f9b263e2f6d2d6c7b5ec6), unhexlify('42600055')) # check storage self.assertEqual( solve( world.get_storage_data( 0xf572e5295c57f15886f9b263e2f6d2d6c7b5ec6, 0x00)), 0x01) # check outs self.assertEqual(returndata, unhexlify('')) # check logs logs = [ Log(unhexlify('{:040x}'.format(l.address)), l.topics, solve(l.memlog)) for l in world.logs ] data = rlp.encode(logs) self.assertEqual( sha3.keccak_256(data).hexdigest(), '1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347') # test used gas self.assertEqual(solve(world.current_vm.gas), 79995)
def testBool3(self): cs = ConstraintSet() bf = BoolConstant(value=False) bt = BoolConstant(value=True) cs.add(Operators.AND(bt, bt, bf, bt)) self.assertFalse(self.solver.check(cs))
def testSolver(self): cs = ConstraintSet() a = cs.new_bitvec(32) b = cs.new_bitvec(32) cs.add(a + b > 100) self.assertTrue(self.solver.check(cs))
def testBasicConstraints(self): cs = ConstraintSet() a = cs.new_bitvec(32) b = cs.new_bitvec(32) cs.add(a + b > 100)
def test_201503110206PYTHON(self): """ Testcase taken from https://github.com/ethereum/tests File: 201503110206PYTHON.json sha256sum: d02dd686767e9a3f281f4dce40244cbe23a022eae7a3e8cc3dd2e747b889500a Code: BLOCKHASH GASLIMIT BLOCKHASH COINBASE GASLIMIT GASLIMIT DIFFICULTY COINBASE CALLVALUE CODECOPY DUP8 SELFDESTRUCT CALLDATACOPY CALLDATALOAD DIV ADDRESS SSTORE """ def solve(val): return self._solve(constraints, val) constraints = ConstraintSet() blocknumber = constraints.new_bitvec(256, name='blocknumber') constraints.add(blocknumber == 300) timestamp = constraints.new_bitvec(256, name='timestamp') constraints.add(timestamp == 2) difficulty = constraints.new_bitvec(256, name='difficulty') constraints.add(difficulty == 115792089237316195423570985008687907853269984665640564039457584007913129639935) coinbase = constraints.new_bitvec(256, name='coinbase') constraints.add(coinbase == 244687034288125203496486448490407391986876152250) gaslimit = constraints.new_bitvec(256, name='gaslimit') constraints.add(gaslimit == 1000000) world = evm.EVMWorld(constraints, blocknumber=blocknumber, timestamp=timestamp, difficulty=difficulty, coinbase=coinbase, gaslimit=gaslimit) acc_addr = 0xf572e5295c57f15886f9b263e2f6d2d6c7b5ec6 acc_code = unhexlify('4045404145454441343987ff3735043055') acc_balance = constraints.new_bitvec(256, name='balance_0xf572e5295c57f15886f9b263e2f6d2d6c7b5ec6') constraints.add(acc_balance == 1000000000000000000) acc_nonce = constraints.new_bitvec(256, name='nonce_0xf572e5295c57f15886f9b263e2f6d2d6c7b5ec6') constraints.add(acc_nonce == 0) world.create_account(address=acc_addr, balance=acc_balance, code=acc_code, nonce=acc_nonce) address = 0xf572e5295c57f15886f9b263e2f6d2d6c7b5ec6 caller = 0xcd1722f3947def4cf144679da39c4c32bdc35681 price = constraints.new_bitvec(256, name='price') constraints.add(price == 100000000000000) value = constraints.new_bitvec(256, name='value') constraints.add(value == 1000000000000000000) gas = constraints.new_bitvec(256, name='gas') constraints.add(gas == 10000) data = '' # open a fake tx, no funds send world._open_transaction('CALL', address, price, data, caller, value, gas=gas) # This variable might seem redundant in some tests - don't forget it is auto generated # and there are cases in which we need it ;) result, returndata = self._test_run(world) # World sanity checks - those should not change, right? self.assertEqual(solve(world.block_number()), 300) self.assertEqual(solve(world.block_gaslimit()), 1000000) self.assertEqual(solve(world.block_timestamp()), 2) self.assertEqual(solve(world.block_difficulty()), 115792089237316195423570985008687907853269984665640564039457584007913129639935) self.assertEqual(solve(world.block_coinbase()), 0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba) # If test end in exception check it here self.assertTrue(result == 'THROW')
def test_addmod(self): """ (declare-fun BV () (_ BitVec 256)) (declare-fun BV_2 () (_ BitVec 256)) (declare-fun BV_1 () (_ BitVec 256)) (declare-fun a_1 () (_ BitVec 256))(assert (= a_1 (bvmul BV BV_1))) (declare-fun a_2 () (_ BitVec 512))(assert (= a_2 ((_ zero_extend 256) BV))) (declare-fun a_3 () (_ BitVec 512))(assert (= a_3 ((_ zero_extend 256) BV_1))) (declare-fun a_4 () (_ BitVec 512))(assert (= a_4 (bvmul a_2 a_3))) (declare-fun a_5 () (_ BitVec 512))(assert (= a_5 ((_ zero_extend 256) BV_2))) (declare-fun a_6 () (_ BitVec 512))(assert (= a_6 (bvsmod a_4 a_5))) (declare-fun a_7 () (_ BitVec 256))(assert (= a_7 ((_ extract 255 0) a_6))) (declare-fun a_8 () (_ BitVec 256))(assert (= a_8 (bvsmod a_1 BV_2))) (declare-fun a_9 () Bool)(assert (= a_9 (= a_7 a_8))) (assert (not a_9)) (check-sat) """ from manticore.platforms import evm from manticore.core.smtlib import ConstraintSet, Z3Solver, Operators constraints = ConstraintSet() address = 0x41414141414141414141 data = b"" caller = 0x42424242424242424242 value = 0 bytecode = "" vm = evm.EVM(constraints, address, data, caller, value, bytecode, gas=23000) self.assertEqual(vm.ADDMOD(12323, 2343, 20), 6) self.assertEqual(vm.ADDMOD(12323, 2343, 0), 0) A, B, C = ( 0x780000002090309A004201626B1400041D318000000200008A0080089C042DA7, 0xF000000740403F7007C012807BED003BE2CE800000060000FFFFBFF7E4087033, 0x338000080FFFFF64AAAACFFCF7DBFA408000000000000270120000001E7C2ACF, ) self.assertEqual( vm.ADDMOD(A, B, C), 23067954172474524581131069693479689311231082562138745684554374357070230297856, ) a, b, c = ( constraints.new_bitvec(256), constraints.new_bitvec(256), constraints.new_bitvec(256), ) constraints.add(a == A) constraints.add(b == B) constraints.add(c == C) result = vm.ADDMOD(a, b, c) # 0x32ffffd700d073ae080133f517d922bd000000000007f1611e003fffc9239d00 self.assertEqual( Z3Solver.instance().get_all_values(constraints, result), [ 0x32FFFFD700D073AE080133F517D922BD000000000007F1611E003FFFC9239D00 ], )
def test_return2(self): """ Testcase taken from https://github.com/ethereum/tests File: return2.json sha256sum: 25972361a5871003f44467255a656b9e7ba3762a5cfe02b56a0197318d375b9a Code: PUSH1 0x37 PUSH1 0x0 MSTORE8 PUSH1 0x0 MLOAD PUSH1 0x0 SSTORE PUSH1 0x21 PUSH1 0x0 RETURN """ def solve(val): return self._solve(constraints, val) constraints = ConstraintSet() blocknumber = constraints.new_bitvec(256, name='blocknumber') constraints.add(blocknumber == 0) timestamp = constraints.new_bitvec(256, name='timestamp') constraints.add(timestamp == 1) difficulty = constraints.new_bitvec(256, name='difficulty') constraints.add(difficulty == 256) coinbase = constraints.new_bitvec(256, name='coinbase') constraints.add( coinbase == 244687034288125203496486448490407391986876152250) gaslimit = constraints.new_bitvec(256, name='gaslimit') constraints.add(gaslimit == 10000000) world = evm.EVMWorld(constraints, blocknumber=blocknumber, timestamp=timestamp, difficulty=difficulty, coinbase=coinbase, gaslimit=gaslimit) acc_addr = 0xcd1722f3947def4cf144679da39c4c32bdc35681 acc_code = unhexlify('603760005360005160005560216000f3') acc_balance = constraints.new_bitvec( 256, name='balance_0xcd1722f3947def4cf144679da39c4c32bdc35681') constraints.add(acc_balance == 23) acc_nonce = constraints.new_bitvec( 256, name='nonce_0xcd1722f3947def4cf144679da39c4c32bdc35681') constraints.add(acc_nonce == 0) world.create_account(address=acc_addr, balance=acc_balance, code=acc_code, nonce=acc_nonce) address = 0xcd1722f3947def4cf144679da39c4c32bdc35681 caller = 0xf572e5295c57f15886f9b263e2f6d2d6c7b5ec6 price = constraints.new_bitvec(256, name='price') constraints.add(price == 100000000000000) value = constraints.new_bitvec(256, name='value') constraints.add(value == 23) gas = constraints.new_bitvec(256, name='gas') constraints.add(gas == 100000) data = constraints.new_array(index_max=1) constraints.add(data == b'\xaa') # open a fake tx, no funds send world._open_transaction('CALL', address, price, data, caller, value, gas=gas) # This variable might seem redundant in some tests - don't forget it is auto generated # and there are cases in which we need it ;) result, returndata = self._test_run(world) # World sanity checks - those should not change, right? self.assertEqual(solve(world.block_number()), 0) self.assertEqual(solve(world.block_gaslimit()), 10000000) self.assertEqual(solve(world.block_timestamp()), 1) self.assertEqual(solve(world.block_difficulty()), 256) self.assertEqual(solve(world.block_coinbase()), 0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba) # Add post checks for account 0xcd1722f3947def4cf144679da39c4c32bdc35681 # check nonce, balance, code self.assertEqual( solve(world.get_nonce(0xcd1722f3947def4cf144679da39c4c32bdc35681)), 0) self.assertEqual( solve( world.get_balance(0xcd1722f3947def4cf144679da39c4c32bdc35681)), 23) self.assertEqual( world.get_code(0xcd1722f3947def4cf144679da39c4c32bdc35681), unhexlify('603760005360005160005560216000f3')) # check storage self.assertEqual( solve( world.get_storage_data( 0xcd1722f3947def4cf144679da39c4c32bdc35681, 0x00)), 0x3700000000000000000000000000000000000000000000000000000000000000) # check outs self.assertEqual( returndata, unhexlify( '370000000000000000000000000000000000000000000000000000000000000000' )) # check logs logs = [ Log(unhexlify('{:040x}'.format(l.address)), l.topics, solve(l.memlog)) for l in world.logs ] data = rlp.encode(logs) self.assertEqual( sha3.keccak_256(data).hexdigest(), '1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347') # test used gas self.assertEqual(solve(world.current_vm.gas), 79970)