evm
Version:
An ethereum virtual machine (EVM) bytecode decompiler
90 lines (85 loc) • 3.09 kB
text/typescript
import EVM from '../classes/evm.class';
import Opcode from '../interfaces/opcode.interface';
import { MLOAD } from './mload';
import * as eventHashes from '../../data/eventHashes.json';
import * as BigNumber from '../../node_modules/big-integer';
export class LOG {
readonly name: string;
readonly type?: string;
readonly wrapped: boolean;
readonly memoryStart?: any;
readonly memoryLength?: any;
readonly items?: any;
readonly topics: any;
readonly eventName?: string;
constructor(topics: any, items?: any, memoryStart?: any, memoryLength?: any) {
this.name = 'LOG';
this.wrapped = true;
this.topics = topics;
if (
this.topics.length > 0 &&
BigNumber.isInstance(this.topics[0]) &&
this.topics[0].toString(16) in eventHashes
) {
this.eventName = (eventHashes as any)[this.topics[0].toString(16)].split('(')[0];
this.topics.shift();
}
if (this.memoryStart && this.memoryLength) {
this.memoryStart = memoryStart;
this.memoryLength = memoryLength;
} else {
this.items = items;
}
}
toString() {
if (this.eventName) {
return (
'emit ' + this.eventName + '(' + [...this.topics, ...this.items].join(', ') + ')'
);
} else {
return 'log(' + [...this.topics, ...this.items].join(', ') + ')';
}
}
}
export default (opcode: Opcode, state: EVM): void => {
const topicsCount = parseInt(opcode.name.replace('LOG', ''), 10);
const memoryStart = state.stack.pop();
const memoryLength = state.stack.pop();
const topics = [];
for (let i = 0; i < topicsCount; i++) {
topics.push(state.stack.pop());
}
if (topics.length > 0) {
const eventTopic = topics[0].toString(16);
if (!(eventTopic in state.events)) {
state.events[eventTopic] = {};
state.events[eventTopic].indexedCount = topics.length - 1;
if (eventTopic in eventHashes) {
state.events[eventTopic].label = (eventHashes as any)[eventTopic];
}
}
}
if (BigNumber.isInstance(memoryStart) && BigNumber.isInstance(memoryLength)) {
const items = [];
for (
let i = memoryStart.toJSNumber();
i < memoryStart.add(memoryLength).toJSNumber();
i += 32
) {
if (i in state.memory) {
items.push(state.memory[i]);
} else {
items.push(new MLOAD(i));
}
}
if (topics.length === 0) {
if (!('anonymous' in state.events)) {
state.events.anonymous = [];
}
state.events.anonymous.push({ items });
}
state.instructions.push(new LOG(topics, items));
} else {
state.instructions.push(new LOG(topics, [], memoryStart, memoryLength));
}
};