Skip to content

Commit

Permalink
feat(tracer): fix one more of the tests
Browse files Browse the repository at this point in the history
  • Loading branch information
0xfourzerofour committed Sep 8, 2023
1 parent 120711b commit e3f0993
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 7 deletions.
21 changes: 21 additions & 0 deletions src/common/simulation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,27 @@ where
ViolationOpCode(opcode),
));
}

for (addr, opcode) in &phase.ext_code_access_info {
if *addr == self.entry_point.address() {
violations.push(SimulationViolation::UsedForbiddenOpcode(
entity,
*addr,
ViolationOpCode(*opcode),
));
}
}

for (addr, size) in &phase.contract_size {
if *addr != context.entity_infos.sender_address() && size.contract_size <= 2 {
violations.push(SimulationViolation::UsedForbiddenOpcode(
entity,
*addr,
ViolationOpCode(size.opcode),
));
}
}

for precompile in &phase.forbidden_precompiles_used {
let (contract, precompile) = parse_combined_tracer_str(precompile)?;
violations.push(SimulationViolation::UsedForbiddenPrecompile(
Expand Down
11 changes: 10 additions & 1 deletion src/common/tracer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::{
};

use anyhow::Context;
use ethers::types::{transaction::eip2718::TypedTransaction, Address, BlockId, U256};
use ethers::types::{transaction::eip2718::TypedTransaction, Address, BlockId, Opcode, U256};
use serde::{de::DeserializeOwned, Deserialize, Serialize};

use super::{
Expand Down Expand Up @@ -36,6 +36,8 @@ pub struct Phase {
pub called_non_entry_point_with_value: bool,
pub ran_out_of_gas: bool,
pub undeployed_contract_accesses: Vec<Address>,
pub contract_size: HashMap<Address, ContractSize>,
pub ext_code_access_info: HashMap<Address, Opcode>,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
Expand All @@ -45,6 +47,13 @@ pub struct StorageAccess {
pub slots: Vec<U256>,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ContractSize {
pub contract_size: u64,
pub opcode: Opcode,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct AssociatedSlotsByAddress(HashMap<Address, BTreeSet<U256>>);

Expand Down
60 changes: 54 additions & 6 deletions tracer/src/validationTracer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,26 +23,39 @@ interface Phase {
calledNonEntryPointWithValue: boolean;
ranOutOfGas: boolean;
undeployedContractAccesses: string[];
contractSize: Record<string, ContractSize>;
extCodeAccessInfo: { [addr: string]: string }
}

interface StorageAccess {
address: string;
slots: string[];
}

interface ContractSize {
contractSize: number;
opcode: string;
}

interface RelevantStepData {
opcode: string
stackTop3: any[]
}
type InternalPhase = Omit<
Phase,
| "forbiddenOpcodesUsed"
| "forbiddenPrecompilesUsed"
| "storageAccesses"
| "addressesCallingWithValue"
| "undeployedContractAccesses"
| "contractSize"
> & {
forbiddenOpcodesUsed: StringSet;
forbiddenPrecompilesUsed: StringSet;
storageAccesses: Record<string, StringSet>;
addressesCallingWithValue: StringSet;
undeployedContractAccesses: StringSet;
contractSize: Record<string, ContractSize>;
};

type StringSet = Record<string, boolean | undefined>;
Expand Down Expand Up @@ -108,7 +121,7 @@ type StringSet = Record<string, boolean | undefined>;
let entryPointAddress = "";
let justCalledGas = false;
let pendingKeccakAddress = "";
let lastThreeOpcodes: string[] = [];
let lastThreeOpcodes: RelevantStepData[] = [];

function newInternalPhase(): InternalPhase {
return {
Expand All @@ -120,6 +133,9 @@ type StringSet = Record<string, boolean | undefined>;
calledNonEntryPointWithValue: false,
ranOutOfGas: false,
undeployedContractAccesses: {},
contractSize: {},
extCodeAccessInfo: {},

};
}

Expand All @@ -128,6 +144,8 @@ type StringSet = Record<string, boolean | undefined>;
calledBannedEntryPointMethod,
calledNonEntryPointWithValue,
ranOutOfGas,
contractSize,
extCodeAccessInfo,
} = currentPhase;
const forbiddenOpcodesUsed = Object.keys(currentPhase.forbiddenOpcodesUsed);
const forbiddenPrecompilesUsed = Object.keys(
Expand All @@ -154,10 +172,11 @@ type StringSet = Record<string, boolean | undefined>;
calledNonEntryPointWithValue,
ranOutOfGas,
undeployedContractAccesses,
contractSize,
extCodeAccessInfo,
};
phases.push(phase);
currentPhase = newInternalPhase();
lastThreeOpcodes = [];
}

function bigIntToNumber(n: BigInt): number {
Expand Down Expand Up @@ -237,22 +256,30 @@ type StringSet = Record<string, boolean | undefined>;
)[keccakResult] = true;
pendingKeccakAddress = "";
}
const opcode = log.op.toString();

lastThreeOpcodes.push(opcode);
const opcode = log.op.toString()

const stackSize = log.stack.length()
const stackTop3 = []
for (let i = 0; i < 3 && i < stackSize; i++) {
stackTop3.push(log.stack.peek(i))
}

lastThreeOpcodes.push({ opcode, stackTop3 })

if (lastThreeOpcodes.length > 3) {
lastThreeOpcodes.shift();
lastThreeOpcodes.shift()
}

const entryPointIsExecuting = log.getDepth() === 1;
if (entryPointIsExecuting) {
if (opcode === "NUMBER") {
concludePhase();
} else if (opcode === "REVERT") {
} else if (opcode === "REVERT" || opcode == "RETURN") {
const offset = bigIntToNumber(log.stack.peek(0));
const length = bigIntToNumber(log.stack.peek(1));
revertData = toHex(log.memory.slice(offset, offset + length));
lastThreeOpcodes = [];
}
} else {
// The entry point is allowed to freely call `GAS`, but otherwise we
Expand All @@ -272,6 +299,19 @@ type StringSet = Record<string, boolean | undefined>;

}
}

const lastOpInfo = lastThreeOpcodes[lastThreeOpcodes.length - 2]
// store all addresses touched by EXTCODE* opcodes
if (lastOpInfo?.opcode?.match(/^(EXT.*)$/) != null) {
const addr = toAddress(lastOpInfo.stackTop3[0].toString(16))
const addrHex = toHex(addr)
const last3opcodesString = lastThreeOpcodes.map(x => x.opcode).join(' ')
// only store the last EXTCODE* opcode per address - could even be a boolean for our current use-case
if (last3opcodesString.match(/^(\w+) EXTCODESIZE ISZERO$/) == null) {
currentPhase.extCodeAccessInfo[addrHex] = opcode
}
}

if (opcode === "CREATE2") {
if (phases.length === 0) {
// In factory phase.
Expand Down Expand Up @@ -323,6 +363,14 @@ type StringSet = Record<string, boolean | undefined>;
const index = EXT_OPCODES[opcode] ? 0 : 1;
const address = toAddress(log.stack.peek(index).toString(16));
const addressHex = toHex(address);

if (currentPhase.contractSize[addressHex] == null && !PRECOMPILE_WHILTELIST[addressHex]) {
currentPhase.contractSize[addressHex] = {
contractSize: db.getCode(address).length,
opcode
}
}

if (!isPrecompiled(address)) {
if (
!accessedContractAddresses[addressHex] ||
Expand Down

0 comments on commit e3f0993

Please sign in to comment.