def make_simple_code(): instruction_table = instruction_tables["byzantium"] return [ assemble_one("PUSH20 0x10"), assemble_one("PUSH1 0x00"), instruction_table["MSTORE"], assemble_one("PUSH1 0x20"), assemble_one("PUSH1 0x00"), instruction_table["RETURN"], ]
def make_evm_ext_code(op, address): instruction_table = instruction_tables["byzantium"] return [ assemble_one("PUSH20 " + address), op, assemble_one("PUSH1 0x00"), instruction_table["MSTORE"], assemble_one("PUSH1 0x20"), assemble_one("PUSH1 0x00"), instruction_table["RETURN"], ]
def make_evm_ext_code(op, address): instruction_table = instruction_tables['byzantium'] return [ assemble_one("PUSH20 " + address), op, assemble_one("PUSH1 0x00"), instruction_table['MSTORE'], assemble_one("PUSH1 0x20"), assemble_one("PUSH1 0x00"), instruction_table['RETURN'], ]
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''')
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""")
def make_evm_transfer_code(address, amount): instruction_table = instruction_tables["byzantium"] return [ assemble_one("PUSH1 0x00"), assemble_one("PUSH1 0x00"), assemble_one("PUSH1 0x00"), assemble_one("PUSH1 0x00"), assemble_one("PUSH32 " + eth_utils.to_hex(amount)), assemble_one("PUSH20 " + address), assemble_one("PUSH1 0x20"), instruction_table["CALL"], assemble_one("PUSH1 0x00"), instruction_table["MSTORE"], assemble_one("PUSH1 0x20"), assemble_one("PUSH1 0x00"), instruction_table["RETURN"], ]
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_assemble_LOGX_regression(self): inst_table = EVMAsm.instruction_tables[EVMAsm.DEFAULT_FORK] log0_opcode = 0xa0 for n in range(5): opcode = log0_opcode + n self.assertTrue(opcode in inst_table, "{!r} not in instruction_table".format(opcode)) asm = "LOG" + str(n) self.assertTrue(asm in inst_table, "{!r} not in instruction_table".format(asm)) insn = EVMAsm.assemble_one(asm) self.assertEqual(insn.mnemonic, asm) self.assertEqual(insn.opcode, opcode)
def make_evm_codecopy_code(offset, length, address): return_data_size = ((length + 31) // 32) * 32 + 64 instruction_table = instruction_tables["byzantium"] return [ assemble_one("PUSH32 0x" + length.to_bytes(32, byteorder="big").hex()), # length assemble_one("PUSH32 0x" + offset.to_bytes(32, byteorder="big").hex()), # offset assemble_one("PUSH32 0x40"), # destOffset assemble_one("PUSH20 " + address), instruction_table["EXTCODECOPY"], assemble_one("PUSH32 0x20"), assemble_one("PUSH1 0x00"), instruction_table["MSTORE"], assemble_one("PUSH32 0x" + length.to_bytes(32, byteorder="big").hex()), assemble_one("PUSH1 0x20"), instruction_table["MSTORE"], assemble_one("PUSH32 0x" + return_data_size.to_bytes(32, byteorder="big").hex()), assemble_one("PUSH1 0x00"), instruction_table["RETURN"], ]
def assemble_one(assembler: str, pc: int = 0, fork=pyevmasm.DEFAULT_FORK) -> EVMInstruction: ''' Assemble one EVM instruction from its textual representation. :param assembler: assembler code for one instruction :param pc: program counter of the instruction in the bytecode (optional) :return: An Instruction object Example use:: >>> print evm.EVMAsm.assemble_one('LT') ''' instruction = pyevmasm.assemble_one(assembler, pc, fork) return EVMAsm.convert_instruction_to_evminstruction(instruction)
def test_assemble_DUP1_regression(self): insn = EVMAsm.assemble_one("DUP1") self.assertEqual(insn.mnemonic, "DUP1") self.assertEqual(insn.opcode, 0x80)
def make_evm_clone_code(address): instruction_table = instruction_tables["byzantium"] return [ assemble_one("PUSH32 " + "0x474ED9C0" + "00" * 8 + address[2:]), # length assemble_one("PUSH1 0x00"), instruction_table["MSTORE"], assemble_one("PUSH1 0x20"), assemble_one("PUSH1 0x40"), assemble_one("PUSH1 0x24"), assemble_one("PUSH1 0x00"), assemble_one("PUSH1 0x00"), assemble_one("PUSH20 " + contract_templates.ARBSYS_ADDRESS_STRING), assemble_one("PUSH1 0x20"), instruction_table["CALL"], assemble_one("PUSH1 0x20"), assemble_one("PUSH1 0x40"), instruction_table["RETURN"], ]
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 MSTORE PUSH1 0x2 PUSH2 0x100
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 MSTORE PUSH1 0x2