Exemple #1
0
 def test_istanbul_fork(self):
     insn = EVMAsm.disassemble_one(b'\x31', fork='istanbul')
     self.assertTrue(insn.mnemonic == 'BALANCE')
     self.assertTrue(insn.fee == 700)
     self.assertTrue(insn.pops == 1)
     self.assertTrue(insn.pushes == 1)
     insn = EVMAsm.disassemble_one(b'\x3f', fork='istanbul')
     self.assertTrue(insn.mnemonic == 'EXTCODEHASH')
     self.assertTrue(insn.fee == 700)
     self.assertTrue(insn.pops == 1)
     self.assertTrue(insn.pushes == 1)
     insn = EVMAsm.disassemble_one(b'\x46', fork='istanbul')
     self.assertTrue(insn.mnemonic == 'CHAINID')
     self.assertTrue(insn.fee == 2)
     self.assertTrue(insn.pops == 0)
     self.assertTrue(insn.pushes == 1)
     insn = EVMAsm.disassemble_one(b'\x47', fork='istanbul')
     self.assertTrue(insn.mnemonic == 'SELFBALANCE')
     self.assertTrue(insn.fee == 5)
     self.assertTrue(insn.pops == 0)
     self.assertTrue(insn.pushes == 1)
     insn = EVMAsm.disassemble_one(b'\x54', fork='istanbul')
     self.assertTrue(insn.mnemonic == 'SLOAD')
     self.assertTrue(insn.fee == 800)
     self.assertTrue(insn.pops == 1)
     self.assertTrue(insn.pushes == 1)
Exemple #2
0
 def test_istanbul_fork(self):
     insn = EVMAsm.disassemble_one(b"\x31", fork="istanbul")
     self.assertTrue(insn.mnemonic == "BALANCE")
     self.assertTrue(insn.fee == 700)
     self.assertTrue(insn.pops == 1)
     self.assertTrue(insn.pushes == 1)
     insn = EVMAsm.disassemble_one(b"\x3f", fork="istanbul")
     self.assertTrue(insn.mnemonic == "EXTCODEHASH")
     self.assertTrue(insn.fee == 700)
     self.assertTrue(insn.pops == 1)
     self.assertTrue(insn.pushes == 1)
     insn = EVMAsm.disassemble_one(b"\x46", fork="istanbul")
     self.assertTrue(insn.mnemonic == "CHAINID")
     self.assertTrue(insn.fee == 2)
     self.assertTrue(insn.pops == 0)
     self.assertTrue(insn.pushes == 1)
     insn = EVMAsm.disassemble_one(b"\x47", fork="istanbul")
     self.assertTrue(insn.mnemonic == "SELFBALANCE")
     self.assertTrue(insn.fee == 5)
     self.assertTrue(insn.pops == 0)
     self.assertTrue(insn.pushes == 1)
     insn = EVMAsm.disassemble_one(b"\x54", fork="istanbul")
     self.assertTrue(insn.mnemonic == "SLOAD")
     self.assertTrue(insn.fee == 800)
     self.assertTrue(insn.pops == 1)
     self.assertTrue(insn.pushes == 1)
Exemple #3
0
 def test_pre_byzantium(self):
     insn = EVMAsm.disassemble_one(b'\x57', fork='frontier')
     self.assertTrue(insn.mnemonic == 'JUMPI')
     self.assertTrue(insn.is_branch)
     insn = EVMAsm.disassemble_one(b'\xfa', fork='frontier')
     self.assertTrue(insn.mnemonic == 'INVALID')  # STATICCALL added in byzantium
     insn = EVMAsm.disassemble_one(b'\xfd', fork='frontier')
     self.assertTrue(insn.mnemonic == 'INVALID')  # REVERT added in byzantium
Exemple #4
0
 def test_pre_byzantium(self):
     insn = EVMAsm.disassemble_one(b"\x57", fork="frontier")
     self.assertTrue(insn.mnemonic == "JUMPI")
     self.assertTrue(insn.is_branch)
     insn = EVMAsm.disassemble_one(b"\xfa", fork="frontier")
     self.assertTrue(
         insn.mnemonic == "INVALID")  # STATICCALL added in byzantium
     insn = EVMAsm.disassemble_one(b"\xfd", fork="frontier")
     self.assertTrue(
         insn.mnemonic == "INVALID")  # REVERT added in byzantium
Exemple #5
0
 def test_constantinople_fork(self):
     insn = EVMAsm.disassemble_one(b'\x1b', fork='constantinople')
     self.assertTrue(insn.mnemonic == 'SHL')
     self.assertTrue(insn.is_arithmetic)
     insn = EVMAsm.disassemble_one(b'\x1c', fork='constantinople')
     self.assertTrue(insn.mnemonic == 'SHR')
     self.assertTrue(insn.is_arithmetic)
     insn = EVMAsm.disassemble_one(b'\x1d', fork='constantinople')
     self.assertTrue(insn.mnemonic == 'SAR')
     self.assertTrue(insn.is_arithmetic)
     insn = EVMAsm.disassemble_one(b'\x3f', fork='constantinople')
     self.assertTrue(insn.mnemonic == 'EXTCODEHASH')
     insn = EVMAsm.disassemble_one(b'\xf5', fork='constantinople')
     self.assertTrue(insn.mnemonic == 'CREATE2')
Exemple #6
0
 def test_constantinople_fork(self):
     insn = EVMAsm.disassemble_one(b"\x1b", fork="constantinople")
     self.assertTrue(insn.mnemonic == "SHL")
     self.assertTrue(insn.is_arithmetic)
     insn = EVMAsm.disassemble_one(b"\x1c", fork="constantinople")
     self.assertTrue(insn.mnemonic == "SHR")
     self.assertTrue(insn.is_arithmetic)
     insn = EVMAsm.disassemble_one(b"\x1d", fork="constantinople")
     self.assertTrue(insn.mnemonic == "SAR")
     self.assertTrue(insn.is_arithmetic)
     insn = EVMAsm.disassemble_one(b"\x3f", fork="constantinople")
     self.assertTrue(insn.mnemonic == "EXTCODEHASH")
     insn = EVMAsm.disassemble_one(b"\xf5", fork="constantinople")
     self.assertTrue(insn.mnemonic == "CREATE2")
Exemple #7
0
    def get_instruction_text(self, data, addr):
        instruction = disassemble_one(data, addr)

        tokens = []
        tokens.append(
            InstructionTextToken(
                InstructionTextTokenType.TextToken,
                "{:7} ".format(
                    instruction.name
                )
            )
        )

        if instruction.name.startswith('PUSH'):
            tokens.append(
                InstructionTextToken(
                    InstructionTextTokenType.IntegerToken,
                    '#{:0{i.operand_size}x}'.format(
                        instruction.operand, i=instruction
                    ),
                    instruction.operand
                )
            )

        return tokens, instruction.size
Exemple #8
0
    def test_ADD_1(self):
        instruction = EVMAsm.disassemble_one(b'\x60\x10')
        self.assertEqual(
            EVMAsm.Instruction(0x60, 'PUSH', 1, 0, 1, 0,
                               'Place 1 byte item on stack.', 16, 0),
            instruction)

        instruction = EVMAsm.assemble_one('PUSH1 0x10')
        EVMAsm.Instruction(0x60, 'PUSH', 1, 0, 1, 0,
                           'Place 1 byte item on stack.', 16, 0)

        instructions1 = EVMAsm.disassemble_all(b'\x30\x31')
        instructions2 = EVMAsm.assemble_all('ADDRESS\nBALANCE')
        self.assertTrue(
            all(a == b for a, b in zip(instructions1, instructions2)))

        # High level simple assembler/disassembler

        bytecode = EVMAsm.assemble_hex("""PUSH1 0x80
               BLOCKHASH
               MSTORE
               PUSH1 0x2
               PUSH2 0x100
            """)
        self.assertEqual(bytecode, '0x608040526002610100')

        asmcode = EVMAsm.disassemble_hex('0x608040526002610100')
        self.assertEqual(
            asmcode,
            '''PUSH1 0x80\nBLOCKHASH\nMSTORE\nPUSH1 0x2\nPUSH2 0x100''')
Exemple #9
0
 def test_codehash_contract(self):
     evm_code = make_evm_ext_code(
         disassemble_one(bytes.fromhex("3f")),
         "0x895521964D724c8362A36608AAf09A3D7d0A0445",
     )
     hex_code = assemble_hex(evm_code)
     code_hash = int.from_bytes(eth_utils.crypto.keccak(hexstr=hex_code),
                                byteorder="big")
     contract_a = make_contract(evm_code, "uint256")
     contracts = create_many_contracts(contract_a)
     vm = create_evm_vm(contracts, True, False)
     output_handler = create_output_handler(contracts)
     vm.env.messages = messagestack.addMessage(
         value.Tuple([]),
         value.Tuple(
             make_msg_val(
                 value.Tuple([0, 2345,
                              contract_a.testMethod(0,
                                                    0)])  # type  # sender
             )),
     )
     run_until_block(vm, self)
     self.assertEqual(len(vm.logs), 1)
     val = vm.logs[0]
     parsed_out = output_handler(val)
     self.assertIsInstance(parsed_out, EVMReturn)
     self.assertEqual(parsed_out.output_values[0], code_hash)
Exemple #10
0
    def get_instruction_low_level_il(self, data, addr, il):
        instruction = disassemble_one(data, addr)

        ill = insn_il.get(instruction.name, None)
        if ill is None:

            for i in range(instruction.pops):
                il.append(
                    il.set_reg(ADDR_SIZE, LLIL_TEMP(i), il.pop(ADDR_SIZE))
                )

            for i in range(instruction.pushes):
                il.append(il.push(ADDR_SIZE, il.unimplemented()))

            il.append(il.nop())

            return instruction.size

        ils = ill(il, addr, instruction.operand)
        if isinstance(ils, list):
            for i in ils:
                il.append(il)
        else:
            il.append(ils)

        return instruction.size
Exemple #11
0
    def test_ADD_1(self):
        instruction = EVMAsm.disassemble_one(b"\x60\x10")
        self.assertEqual(
            EVMAsm.Instruction(0x60, "PUSH", 1, 0, 1, 3,
                               "Place 1 byte item on stack.", 16, 0),
            instruction)

        instruction = EVMAsm.assemble_one("PUSH1 0x10")
        self.assertEqual(
            instruction,
            EVMAsm.Instruction(0x60, "PUSH", 1, 0, 1, 3,
                               "Place 1 byte item on stack.", 16, 0))

        instructions1 = EVMAsm.disassemble_all(b"\x30\x31")
        instructions2 = EVMAsm.assemble_all("ADDRESS\nBALANCE")
        self.assertTrue(
            all(a == b for a, b in zip(instructions1, instructions2)))

        # High level simple assembler/disassembler

        bytecode = EVMAsm.assemble_hex("""PUSH1 0x80
               BLOCKHASH
               MSTORE
               PUSH1 0x2
               PUSH2 0x100
            """)
        self.assertEqual(bytecode, "0x608040526002610100")

        asmcode = EVMAsm.disassemble_hex("0x608040526002610100")
        self.assertEqual(
            asmcode,
            """PUSH1 0x80\nBLOCKHASH\nMSTORE\nPUSH1 0x2\nPUSH2 0x100""")
Exemple #12
0
 def test_consistency_assembler_disassembler(self):
     """
     Tests whether every opcode that can be disassembled, can also be
     assembled again.
     """
     inst_table = EVMAsm.instruction_tables[EVMAsm.DEFAULT_FORK]
     for opcode in inst_table.keys():
         b = int_to_bytes(opcode) + b"\x00" * 32
         inst_dis = EVMAsm.disassemble_one(b)
         a = str(inst_dis)
         inst_as = EVMAsm.assemble_one(a)
         self.assertEqual(inst_dis, inst_as)
 def test_codehash_fail(self):
     evm_code = make_evm_ext_code(disassemble_one(bytes.fromhex('3f')),
                                  "0x9999")
     contract_a = make_contract(evm_code, "uint256")
     vm = create_many_contract_vm(contract_a)
     vm.env.send_message(
         [make_msg_val(contract_a.testMethod(4)), 2345, 0, 0])
     vm.env.deliver_pending()
     run_until_block(vm, self)
     self.assertEqual(len(vm.logs), 1)
     val = vm.logs[0]
     parsed_out = vm.output_handler(val)
     self.assertIsInstance(parsed_out, EVMInvalid)
Exemple #14
0
    def get_instruction_info(self, data, addr):
        instruction = disassemble_one(data, addr)

        result = InstructionInfo()
        result.length = instruction.size
        if instruction.name == "JUMP":
            result.add_branch(BranchType.UnresolvedBranch)
        elif instruction.name == "JUMPI":
            result.add_branch(BranchType.UnresolvedBranch)
            result.add_branch(BranchType.FalseBranch, addr + 1)
        elif instruction.name in ('RETURN', 'REVERT', 'SUICIDE', 'INVALID',
                                  'STOP', 'SELFDESTRUCT'):
            result.add_branch(BranchType.FunctionReturn)

        return result
Exemple #15
0
    def disassemble_one(bytecode: Iterable,
                        pc: int = 0,
                        fork=pyevmasm.DEFAULT_FORK) -> EVMInstruction:
        ''' Decode a single instruction from a bytecode

            :param bytecode: the bytecode stream
            :param pc: program counter of the instruction in the bytecode(optional)
            :type bytecode: iterator/sequence/str
            :return: an Instruction object

            Example use::

                >>> print EVMAsm.assemble_one('PUSH1 0x10')

        '''
        instruction = pyevmasm.disassemble_one(bytecode, pc, fork)
        return EVMAsm.convert_instruction_to_evminstruction(instruction)
 def test_codehash_succeed(self):
     evm_code = make_evm_ext_code(
         disassemble_one(bytes.fromhex('3f')),
         "0x895521964D724c8362A36608AAf09A3D7d0A0445")
     hex_code = assemble_hex(evm_code)
     code_hash = int.from_bytes(eth_utils.crypto.keccak(hexstr=hex_code),
                                byteorder="big")
     contract_a = make_contract(evm_code, "uint256")
     vm = create_many_contract_vm(contract_a)
     vm.env.send_message(
         [make_msg_val(contract_a.testMethod(4)), 2345, 0, 0])
     vm.env.deliver_pending()
     run_until_block(vm, self)
     self.assertEqual(len(vm.logs), 1)
     val = vm.logs[0]
     parsed_out = vm.output_handler(val)
     self.assertIsInstance(parsed_out, EVMCall)
     self.assertEqual(parsed_out.output_values[0], code_hash)
Exemple #17
0
 def test_byzantium_fork(self):
     insn = EVMAsm.disassemble_one(b'\x57', fork='byzantium')
     self.assertTrue(insn.mnemonic == 'JUMPI')
     self.assertTrue(insn.is_branch)
     insn = EVMAsm.disassemble_one(b'\x1b', fork='byzantium')
     self.assertTrue(insn.mnemonic == 'INVALID')  # SHL added in constantinople
     insn = EVMAsm.disassemble_one(b'\x1c', fork='byzantium')
     self.assertTrue(insn.mnemonic == 'INVALID')  # SHR added in constantinople
     insn = EVMAsm.disassemble_one(b'\x1d', fork='byzantium')
     self.assertTrue(insn.mnemonic == 'INVALID')  # SAR added in constantinople
     insn = EVMAsm.disassemble_one(b'\x3f', fork='byzantium')
     self.assertTrue(insn.mnemonic == 'INVALID')  # EXTCODEHASH added in constantinople
     insn = EVMAsm.disassemble_one(b'\xf5', fork='byzantium')
     self.assertTrue(insn.mnemonic == 'INVALID')  # CREATE2 added in constantinople
Exemple #18
0
 def test_codehash_empty(self):
     evm_code = make_evm_ext_code(disassemble_one(bytes.fromhex("3f")),
                                  "0x9999")
     contract_a = make_contract(evm_code, "uint256")
     contracts = create_many_contracts(contract_a)
     vm = create_evm_vm(contracts, True, False)
     output_handler = create_output_handler(contracts)
     vm.env.messages = messagestack.addMessage(
         value.Tuple([]),
         value.Tuple(
             make_msg_val(
                 value.Tuple([0, 2345,
                              contract_a.testMethod(0,
                                                    0)])  # type  # sender
             )),
     )
     run_until_block(vm, self)
     self.assertEqual(len(vm.logs), 1)
     val = vm.logs[0]
     parsed_out = output_handler(val)
     self.assertIsInstance(parsed_out, EVMReturn)
     self.assertEqual(parsed_out.output_values[0], 0)
Exemple #19
0
 def test_byzantium_fork(self):
     insn = EVMAsm.disassemble_one(b"\x57", fork="byzantium")
     self.assertTrue(insn.mnemonic == "JUMPI")
     self.assertTrue(insn.is_branch)
     insn = EVMAsm.disassemble_one(b"\x1b", fork="byzantium")
     self.assertTrue(
         insn.mnemonic == "INVALID")  # SHL added in constantinople
     insn = EVMAsm.disassemble_one(b"\x1c", fork="byzantium")
     self.assertTrue(
         insn.mnemonic == "INVALID")  # SHR added in constantinople
     insn = EVMAsm.disassemble_one(b"\x1d", fork="byzantium")
     self.assertTrue(
         insn.mnemonic == "INVALID")  # SAR added in constantinople
     insn = EVMAsm.disassemble_one(b"\x3f", fork="byzantium")
     self.assertTrue(
         insn.mnemonic == "INVALID")  # EXTCODEHASH added in constantinople
     insn = EVMAsm.disassemble_one(b"\xf5", fork="byzantium")
     self.assertTrue(
         insn.mnemonic == "INVALID")  # CREATE2 added in constantinople
Exemple #20
0
 def test_JUMPI(self):
     insn = EVMAsm.disassemble_one(b"\x57")
     self.assertTrue(insn.mnemonic == "JUMPI")
     self.assertTrue(insn.is_branch)
Exemple #21
0
 def test_STOP(self):
     insn = EVMAsm.disassemble_one(b"\x00")
     self.assertTrue(insn.mnemonic == "STOP")
Exemple #22
0
    print("\toperand_size:", instruction.operand_size)
    print("\toperand:", instruction.operand)
    print("\tsemantics:", instruction.semantics)
    print("\tpops:", instruction.pops)
    print("\tpushes:", instruction.pushes)
    print(f"\tbytes: 0x" + hexlify(instruction.bytes).decode())
    print("\twrites to stack:", instruction.writes_to_stack)
    print("\treads from stack:", instruction.reads_from_stack)
    print("\twrites to memory:", instruction.writes_to_memory)
    print("\treads from memory:", instruction.reads_from_memory)
    print("\twrites to storage:", instruction.writes_to_storage)
    print("\treads from storage:", instruction.reads_from_storage)
    print("\tis terminator", instruction.is_terminator)


instruction = ea.disassemble_one("\x60\x10")
printi(instruction)

instruction = ea.assemble_one("PUSH1 0x10")
printi(instruction)

for instruction in ea.disassemble_all("\x30\x31"):
    printi(instruction)

for instruction in ea.assemble_all("ADDRESS\nBALANCE"):
    printi(instruction)

# High level simple assembler/disassembler
print(
    ea.assemble_hex("""PUSH1 0x60
                           BLOCKHASH
Exemple #23
0
 def test_STOP(self):
     insn = EVMAsm.disassemble_one(b'\x00')
     self.assertTrue(insn.mnemonic == 'STOP')
Exemple #24
0
 def test_JUMPI(self):
     insn = EVMAsm.disassemble_one(b'\x57')
     self.assertTrue(insn.mnemonic == 'JUMPI')
     self.assertTrue(insn.is_branch)
Exemple #25
0
    print('\toperand_size:', instruction.operand_size)
    print('\toperand:', instruction.operand)
    print('\tsemantics:', instruction.semantics)
    print('\tpops:', instruction.pops)
    print('\tpushes:', instruction.pushes)
    print(f'\tbytes: 0x'+hexlify(instruction.bytes).decode())
    print('\twrites to stack:', instruction.writes_to_stack)
    print('\treads from stack:', instruction.reads_from_stack)
    print('\twrites to memory:', instruction.writes_to_memory)
    print('\treads from memory:', instruction.reads_from_memory)
    print('\twrites to storage:', instruction.writes_to_storage)
    print('\treads from storage:', instruction.reads_from_storage)
    print('\tis terminator', instruction.is_terminator)


instruction = ea.disassemble_one('\x60\x10')
printi(instruction)

instruction = ea.assemble_one('PUSH1 0x10')
printi(instruction)

for instruction in ea.disassemble_all('\x30\x31'):
    printi(instruction)

for instruction in ea.assemble_all('ADDRESS\nBALANCE'):
    printi(instruction)


#High level simple assembler/disassembler
print(ea.assemble_hex(
                        """PUSH1 0x60