UNPKG

evm

Version:

An ethereum virtual machine (EVM) bytecode decompiler

67 lines (62 loc) 2.37 kB
import EVM from '../classes/evm.class'; import Opcode from '../interfaces/opcode.interface'; import * as BigNumber from '../../node_modules/big-integer'; import stringify from '../utils/stringify'; export class JUMP { readonly name: string; readonly type?: string; readonly wrapped: boolean; readonly valid: boolean; readonly location: any; constructor(location: any, bad?: boolean) { this.name = 'JUMP'; this.wrapped = false; this.location = location; this.valid = true; if (bad) { this.valid = false; } } toString() { if (!this.valid) { return "revert(\"Bad jump destination\");"; } else { return 'goto(' + stringify(this.location) + ');'; } } } export default (opcode: Opcode, state: EVM): void => { const jumpLocation = state.stack.pop(); if (!BigNumber.isInstance(jumpLocation)) { state.halted = true; state.instructions.push(new JUMP(jumpLocation, true)); } else { const opcodes = state.getOpcodes(); const jumpLocationData = opcodes.find((o: any) => o.pc === jumpLocation.toJSNumber()); if (!jumpLocationData) { state.halted = true; state.instructions.push(new JUMP(jumpLocation, true)); } else { const jumpIndex = opcodes.indexOf(jumpLocationData); if (!(opcode.pc + ':' + jumpLocation.toJSNumber() in state.jumps)) { if (!jumpLocationData || jumpLocationData.name !== 'JUMPDEST') { state.halted = true; state.instructions.push(new JUMP(jumpLocation, true)); } else if ( jumpLocationData && jumpIndex >= 0 && jumpLocationData.name === 'JUMPDEST' ) { state.jumps[opcode.pc + ':' + jumpLocation.toJSNumber()] = true; state.pc = jumpIndex; } else { state.halted = true; state.instructions.push(new JUMP(jumpLocation, true)); } } else { state.halted = true; state.instructions.push(new JUMP(jumpLocation)); } } } };