sevm
Version:
A Symbolic Ethereum Virtual Machine (EVM) bytecode decompiler & analyzer library & CLI
212 lines • 7.07 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var _Local_memo;
Object.defineProperty(exports, "__esModule", { value: true });
exports.mem = exports.inline0 = exports.reduce = exports.Locali = exports.Local = exports.Val = exports.MOD_256 = exports.Tag = exports.Require = exports.CallSite = exports.If = exports.Throw = exports.evalE = exports.isInst = exports.isExpr = void 0;
const isExpr = (expr) => expr !== null && typeof expr === 'object' && 'tag' in expr;
exports.isExpr = isExpr;
const isInst = (inst) => inst !== null && typeof inst === 'object' && 'name' in inst;
exports.isInst = isInst;
const evalE = (expr) => expr.eval();
exports.evalE = evalE;
class Throw {
constructor(reason, opcode) {
this.reason = reason;
this.opcode = opcode;
this.name = 'Throw';
}
eval() {
return this;
}
}
exports.Throw = Throw;
// export class Assign {
// readonly name = 'Asign';
// constructor(readonly i: number, readonly phi: Phi) {}
// eval() {
// return this;
// }
// toString() {
// return `local${this.i} = ${this.phi.toString()};`;
// }
// }
class If {
constructor(condition, trueBlock, falseBlock) {
this.condition = condition;
this.trueBlock = trueBlock;
this.falseBlock = falseBlock;
this.name = 'If';
}
eval() {
return new If(this.condition.eval(), this.trueBlock ? reduce(this.trueBlock) : undefined, this.falseBlock ? reduce(this.falseBlock) : undefined);
}
}
exports.If = If;
class CallSite {
constructor(selector) {
this.selector = selector;
this.name = 'CallSite';
}
eval() {
return this;
}
}
exports.CallSite = CallSite;
class Require {
constructor(condition, selector, args) {
this.condition = condition;
this.selector = selector;
this.args = args;
this.name = 'Require';
}
eval() {
return new Require(this.condition.eval(), this.selector, this.args.map(exports.evalE));
}
}
exports.Require = Require;
class Tag {
constructor(depth, count) {
this.depth = depth;
this.count = count;
}
isVal() {
return this.tag === 'Val';
}
isZero() {
return this.isVal() && this.val === 0n;
}
isJumpDest() {
return this.isVal() && this.jumpDest !== null;
}
children() {
return Object.values(this).filter(value => value instanceof Tag);
}
unwrap() {
return this;
}
}
exports.Tag = Tag;
exports.MOD_256 = 1n << 0x100n;
class Val extends Tag {
constructor(val, pushStateId) {
if (val < 0 || val >= exports.MOD_256)
throw new Error(`Val is a not a valid unsigned 256-word: ${val}`);
super(0, 1);
this.val = val;
this.pushStateId = pushStateId;
this.tag = 'Val';
this.jumpDest = null;
}
eval() {
return new Val(this.val);
}
}
exports.Val = Val;
class Local extends Tag {
constructor(index, value) {
super(value.depth + 1, value.count + 1);
this.index = index;
this.value = value;
this.tag = 'Local';
this.nrefs = 0;
_Local_memo.set(this, undefined);
}
eval() {
if (__classPrivateFieldGet(this, _Local_memo, "f") === undefined)
__classPrivateFieldSet(this, _Local_memo, this.value.eval(), "f");
return __classPrivateFieldGet(this, _Local_memo, "f");
}
unwrap() {
return this.value;
}
}
exports.Local = Local;
_Local_memo = new WeakMap();
class Locali {
constructor(local) {
this.local = local;
this.name = 'Local';
}
eval() {
return this;
}
}
exports.Locali = Locali;
function reduce(stmts) {
return stmts?.flatMap(stmt => ['Local', 'MStore'].includes(stmt.name) ? [] : stmt.eval());
}
exports.reduce = reduce;
function inline0(stmts) {
const reachable = new WeakSet();
const result = [];
for (const stmt of stmts.reverse()) {
if (stmt.name === 'MStore') {
reach(stmt.location);
reach(stmt.data);
}
else if (stmt.name === 'Local' && reachable.has(stmt.local)) {
continue;
}
result.unshift(stmt);
}
return result;
function reach(expr) {
reachable.add(expr);
expr.children().forEach(reach);
}
}
exports.inline0 = inline0;
function mem(stmts) {
// const reachable = new WeakSet<Expr>();
const result = [];
for (const stmt of stmts.reverse()) {
if (stmt.name === 'MStore') {
reach(stmt.location);
reach(stmt.data);
// } else if (stmt.name === 'Local' && reachable.has(stmt.local)) {
// continue;
}
result.unshift(stmt);
}
return result;
function reach(expr) {
// reachable.add(expr);
if (expr.tag === 'Local') {
expr.nrefs--;
}
expr.children().forEach(reach);
}
}
exports.mem = mem;
__exportStar(require("./alu"), exports);
__exportStar(require("./flow"), exports);
__exportStar(require("./log"), exports);
__exportStar(require("./memory"), exports);
__exportStar(require("./special"), exports);
__exportStar(require("./storage"), exports);
__exportStar(require("./system"), exports);
//# sourceMappingURL=index.js.map