Skip to content

Commit

Permalink
Add test when code is optimized
Browse files Browse the repository at this point in the history
  • Loading branch information
acuarica committed Oct 7, 2023
1 parent 6bb2bd1 commit 3c8e505
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 28 deletions.
17 changes: 7 additions & 10 deletions src/sol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,9 @@ function solInst(inst: Inst): string {
case 'SigCase':
return `case when ${inst.condition} goto ${inst.offset} or fall ${inst.fallBranch.key}`;
case 'SStore': {
const isLoad = (value: Expr) =>
value.tag === 'SLoad' && solExpr(value.location) === solExpr(inst.location);

let varName = sol`storage[${inst.location}]`;
if (inst.location.isVal() && inst.location.val.toString() in inst.variables) {
const loc = inst.location.val.toString();
Expand All @@ -206,17 +209,11 @@ function solInst(inst: Inst): string {
varName = `var${Object.keys(inst.variables).indexOf(loc) + 1}`;
}
}
if (
inst.data.tag === 'Add' &&
inst.data.left.tag === 'SLoad' &&
solExpr(inst.data.left.location) === solExpr(inst.location)
) {
if (inst.data.tag === 'Add' && isLoad(inst.data.left)) {
return sol`${varName} += ${inst.data.right};`;
} else if (
inst.data.tag === 'Sub' &&
inst.data.left.tag === 'SLoad' &&
solExpr(inst.data.left.location) === solExpr(inst.location)
) {
} else if (inst.data.tag === 'Add' && isLoad(inst.data.right)) {
return sol`${varName} += ${inst.data.left};`;
} else if (inst.data.tag === 'Sub' && isLoad(inst.data.left)) {
return sol`${varName} -= ${inst.data.right};`;
} else {
return sol`${varName} = ${inst.data};`;
Expand Down
69 changes: 51 additions & 18 deletions test/evm/storage.test.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import { expect } from 'chai';

import { EVM, STEP, State, sol } from 'sevm';
import { EVM, STEP, State, sol, yul } from 'sevm';
import type { Expr, Inst } from 'sevm/ast';
import { Add, Info, MappingLoad, MappingStore, Msg, Stop, Sub, Val } from 'sevm/ast';

import { compile } from '../utils/solc';

describe('evm::storage', function () {
it('should store variable', function () {
// const store = { events: {}, variables: {}, mappings: {}, };
// const evm = STORAGE(store);
const step = STEP();

const state = new State<Inst, Expr>();
Expand All @@ -29,7 +27,7 @@ describe('evm::storage', function () {
val2 += 11;
}
}`;
const evm = new EVM(compile(src, '0.7.6', { context: this }).bytecode);
const evm = new EVM(compile(src, '0.7.6', this).bytecode);
const state = new State<Inst, Expr>();
evm.run(0, state);

Expand All @@ -42,45 +40,82 @@ describe('evm::storage', function () {
});

it.skip('should detect packed storage variable', function () {
const sol = `contract C {
const src = `contract C {
uint256 val1 = 0;
uint128 val2 = 7;
uint128 val3 = 11;
fallback() external payable {
function() external payable {
// unchecked {
val1 = block.number + 5;
val2 = uint128(block.number) + 7;
// val2 = uint128(block.number) + 7;
val3 = uint128(block.number) + 11;
// uint64 val4 = 9;
// }
}
}`;
const evm = new EVM(compile(sol, '0.7.6', { context: this }).bytecode);
const evm = new EVM(compile(src, '0.5.5', this).bytecode);
const state = new State<Inst, Expr>();
evm.run(0, state);

// state.stmts.forEach((stmt) => console.log(`${stmt.eval()}`));
// state.stmts.forEach(stmt => console.log(sol`${stmt.eval()}`));
// state.stmts.forEach(stmt => console.log(yul`${stmt.eval()}`));

expect(Object.keys(evm.variables)).to.be.have.length(3);
});

it.skip('should find storage struct', function () {
const sol = `contract C {
it.skip('should find storage struct when no optimized', function () {
const src = `contract Test {
struct T {
uint256 val1;
uint256 val2;
}
T t;
uint256 val3;
fallback() external payable {
t.val1 += 3;
t.val2 += 11;
val3 += 7;
}
}`;
const evm = new EVM(compile(sol, '0.7.6', { context: this }).bytecode);
evm.start();
const evm = new EVM(compile(src, '0.7.6', this, { enabled: false }).bytecode);
const state = new State<Inst, Expr>();
evm.run(0, state);
state.stmts.forEach(stmt => console.log(sol`${stmt}`));
state.stmts.forEach(stmt => console.log(yul`${stmt}`));

expect(evm.variables).to.be.have.keys('0x0', '0x1');
expect(evm.mappings).to.be.deep.equal({});
});

it('should not find storage struct when optimized', function () {
const src = `contract Test {
struct T { uint256 val1; uint256 val2; }
T t;
fallback() external payable {
t.val1 += 3;
t.val2 += 11;
}
}`;
const evm = new EVM(compile(src, '0.7.6', this, { enabled: true }).bytecode);
const state = new State<Inst, Expr>();
evm.run(0, state);

expect(state.stmts).to.be.have.length(3);

expect(sol`${state.stmts[0]}`).to.be.equal('var1 += 0x3;');
expect(sol`${state.stmts[1]}`).to.be.equal('var2 += 0xb;');
expect(sol`${state.stmts[2]}`).to.be.equal('return;');

expect(yul`${state.stmts[0]}`).to.be.equal('sstore(0x0, add(0x3, sload(0x0)))');
expect(yul`${state.stmts[1]}`).to.be.equal('sstore(0x1, add(0xb, sload(0x1)))');
expect(yul`${state.stmts[2]}`).to.be.equal('stop()');

expect(evm.variables).to.be.have.keys('0', '1');
expect(evm.mappings).to.be.deep.equal({});
});

describe('mappings', function () {
it('should find mapping loads and stores', function () {
const src = `contract C {
Expand All @@ -94,7 +129,7 @@ describe('evm::storage', function () {
allowance[address(this)][msg.sender] -= 11;
}
}`;
const evm = new EVM(compile(src, '0.7.6', { context: this }).bytecode);
const evm = new EVM(compile(src, '0.7.6', this).bytecode);
const state = new State<Inst, Expr>();
evm.run(0, state);

Expand Down Expand Up @@ -134,9 +169,7 @@ describe('evm::storage', function () {
expect(sol`${state.stmts[2]}`).to.be.equal(
'mapping3[address(this)][msg.sender] -= 0xb;'
);

expect(state.last).to.be.deep.equal(new Stop());

expect(evm.variables).to.be.empty;
});
});
Expand Down

0 comments on commit 3c8e505

Please sign in to comment.