Skip to content

Commit

Permalink
Merge pull request #68 from shazow/improve-zero-selector
Browse files Browse the repository at this point in the history
Improve zero selector
  • Loading branch information
shazow authored Dec 21, 2023
2 parents fbe2c2b + aee6f9e commit c21c8de
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 9 deletions.
3 changes: 2 additions & 1 deletion examples/bytecode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { ethers } from "ethers";
import { readFileSync } from "fs";

import { withCache } from "../src/internal/filecache.js";
import { bytecodeToString, bytecodeToStringConfig } from '../src/internal/debug.js';
import { bytecodeToString } from '../src/internal/debug.js';
import type { bytecodeToStringConfig } from '../src/internal/debug.js';

const { INFURA_API_KEY, OPCODES_JSON } = process.env;
const provider = INFURA_API_KEY ? (new ethers.InfuraProvider("homestead", INFURA_API_KEY)) : ethers.getDefaultProvider("homestead");
Expand Down
4 changes: 3 additions & 1 deletion src/__tests__/__fixtures__/proxies.ts
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export const ZEPPELINOS_USDC = "608060405234801561001057600080fd5b50604051602080610b2983398101806040528101908080519060200190929190505050808060405180807f6f72672e7a657070656c696e6f732e70726f78792e696d706c656d656e74617481526020017f696f6e000000000000000000000000000000000000000000000000000000000081525060230190506040518091039020600019167f7050c9e0f4ca769c69bd3a8ef740bc37934f8e2c036e5a723fd8ee048ed3f8c3600102600019161415156100c657fe5b6100de81610169640100000000026401000000009004565b5060405180807f6f72672e7a657070656c696e6f732e70726f78792e61646d696e000000000000815250601a0190506040518091039020600019167f10d6a54a4754c8869d6886b5f5d7fbfa5b4522237ea5c60d11bc4e7a1ff9390b6001026000191614151561014a57fe5b6101623361024e640100000000026401000000009004565b5050610290565b60006101878261027d6401000000000261084b176401000000009004565b1515610221576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603b8152602001807f43616e6e6f742073657420612070726f787920696d706c656d656e746174696f81526020017f6e20746f2061206e6f6e2d636f6e74726163742061646472657373000000000081525060400191505060405180910390fd5b7f7050c9e0f4ca769c69bd3a8ef740bc37934f8e2c036e5a723fd8ee048ed3f8c360010290508181555050565b60007f10d6a54a4754c8869d6886b5f5d7fbfa5b4522237ea5c60d11bc4e7a1ff9390b60010290508181555050565b600080823b905060008111915050919050565b61088a8061029f6000396000f30060806040526004361061006d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633659cfe6146100775780634f1ef286146100ba5780635c60da1b146101085780638f2839701461015f578063f851a440146101a2575b6100756101f9565b005b34801561008357600080fd5b506100b8600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610213565b005b610106600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001908201803590602001919091929391929390505050610268565b005b34801561011457600080fd5b5061011d610308565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561016b57600080fd5b506101a0600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610360565b005b3480156101ae57600080fd5b506101b761051e565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610201610576565b61021161020c610651565b610682565b565b61021b6106a8565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561025c57610257816106d9565b610265565b6102646101f9565b5b50565b6102706106a8565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614156102fa576102ac836106d9565b3073ffffffffffffffffffffffffffffffffffffffff163483836040518083838082843782019150509250505060006040518083038185875af19250505015156102f557600080fd5b610303565b6103026101f9565b5b505050565b60006103126106a8565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614156103545761034d610651565b905061035d565b61035c6101f9565b5b90565b6103686106a8565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561051257600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614151515610466576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260368152602001807f43616e6e6f74206368616e6765207468652061646d696e206f6620612070726f81526020017f787920746f20746865207a65726f20616464726573730000000000000000000081525060400191505060405180910390fd5b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f61048f6106a8565b82604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a161050d81610748565b61051b565b61051a6101f9565b5b50565b60006105286106a8565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561056a576105636106a8565b9050610573565b6105726101f9565b5b90565b61057e6106a8565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151515610647576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260328152602001807f43616e6e6f742063616c6c2066616c6c6261636b2066756e6374696f6e20667281526020017f6f6d207468652070726f78792061646d696e000000000000000000000000000081525060400191505060405180910390fd5b61064f610777565b565b6000807f7050c9e0f4ca769c69bd3a8ef740bc37934f8e2c036e5a723fd8ee048ed3f8c36001029050805491505090565b3660008037600080366000845af43d6000803e80600081146106a3573d6000f35b3d6000fd5b6000807f10d6a54a4754c8869d6886b5f5d7fbfa5b4522237ea5c60d11bc4e7a1ff9390b6001029050805491505090565b6106e281610779565b7fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b81604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b60007f10d6a54a4754c8869d6886b5f5d7fbfa5b4522237ea5c60d11bc4e7a1ff9390b60010290508181555050565b565b60006107848261084b565b151561081e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603b8152602001807f43616e6e6f742073657420612070726f787920696d706c656d656e746174696f81526020017f6e20746f2061206e6f6e2d636f6e74726163742061646472657373000000000081525060400191505060405180910390fd5b7f7050c9e0f4ca769c69bd3a8ef740bc37934f8e2c036e5a723fd8ee048ed3f8c360010290508181555050565b600080823b9050600081119150509190505600a165627a7a72305820a4a547cfc7202c5acaaae74d428e988bc62ad5024eb0165532d3a8f91db4ed2400290000000000000000000000000882477e7895bdc5cea7cb1552ed914ab157fe56"
export const ZEPPELINOS_USDC = "608060405234801561001057600080fd5b50604051602080610b2983398101806040528101908080519060200190929190505050808060405180807f6f72672e7a657070656c696e6f732e70726f78792e696d706c656d656e74617481526020017f696f6e000000000000000000000000000000000000000000000000000000000081525060230190506040518091039020600019167f7050c9e0f4ca769c69bd3a8ef740bc37934f8e2c036e5a723fd8ee048ed3f8c3600102600019161415156100c657fe5b6100de81610169640100000000026401000000009004565b5060405180807f6f72672e7a657070656c696e6f732e70726f78792e61646d696e000000000000815250601a0190506040518091039020600019167f10d6a54a4754c8869d6886b5f5d7fbfa5b4522237ea5c60d11bc4e7a1ff9390b6001026000191614151561014a57fe5b6101623361024e640100000000026401000000009004565b5050610290565b60006101878261027d6401000000000261084b176401000000009004565b1515610221576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603b8152602001807f43616e6e6f742073657420612070726f787920696d706c656d656e746174696f81526020017f6e20746f2061206e6f6e2d636f6e74726163742061646472657373000000000081525060400191505060405180910390fd5b7f7050c9e0f4ca769c69bd3a8ef740bc37934f8e2c036e5a723fd8ee048ed3f8c360010290508181555050565b60007f10d6a54a4754c8869d6886b5f5d7fbfa5b4522237ea5c60d11bc4e7a1ff9390b60010290508181555050565b600080823b905060008111915050919050565b61088a8061029f6000396000f30060806040526004361061006d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633659cfe6146100775780634f1ef286146100ba5780635c60da1b146101085780638f2839701461015f578063f851a440146101a2575b6100756101f9565b005b34801561008357600080fd5b506100b8600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610213565b005b610106600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001908201803590602001919091929391929390505050610268565b005b34801561011457600080fd5b5061011d610308565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561016b57600080fd5b506101a0600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610360565b005b3480156101ae57600080fd5b506101b761051e565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610201610576565b61021161020c610651565b610682565b565b61021b6106a8565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561025c57610257816106d9565b610265565b6102646101f9565b5b50565b6102706106a8565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614156102fa576102ac836106d9565b3073ffffffffffffffffffffffffffffffffffffffff163483836040518083838082843782019150509250505060006040518083038185875af19250505015156102f557600080fd5b610303565b6103026101f9565b5b505050565b60006103126106a8565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614156103545761034d610651565b905061035d565b61035c6101f9565b5b90565b6103686106a8565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561051257600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614151515610466576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260368152602001807f43616e6e6f74206368616e6765207468652061646d696e206f6620612070726f81526020017f787920746f20746865207a65726f20616464726573730000000000000000000081525060400191505060405180910390fd5b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f61048f6106a8565b82604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a161050d81610748565b61051b565b61051a6101f9565b5b50565b60006105286106a8565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561056a576105636106a8565b9050610573565b6105726101f9565b5b90565b61057e6106a8565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151515610647576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260328152602001807f43616e6e6f742063616c6c2066616c6c6261636b2066756e6374696f6e20667281526020017f6f6d207468652070726f78792061646d696e000000000000000000000000000081525060400191505060405180910390fd5b61064f610777565b565b6000807f7050c9e0f4ca769c69bd3a8ef740bc37934f8e2c036e5a723fd8ee048ed3f8c36001029050805491505090565b3660008037600080366000845af43d6000803e80600081146106a3573d6000f35b3d6000fd5b6000807f10d6a54a4754c8869d6886b5f5d7fbfa5b4522237ea5c60d11bc4e7a1ff9390b6001029050805491505090565b6106e281610779565b7fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b81604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b60007f10d6a54a4754c8869d6886b5f5d7fbfa5b4522237ea5c60d11bc4e7a1ff9390b60010290508181555050565b565b60006107848261084b565b151561081e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603b8152602001807f43616e6e6f742073657420612070726f787920696d706c656d656e746174696f81526020017f6e20746f2061206e6f6e2d636f6e74726163742061646472657373000000000081525060400191505060405180910390fd5b7f7050c9e0f4ca769c69bd3a8ef740bc37934f8e2c036e5a723fd8ee048ed3f8c360010290508181555050565b600080823b9050600081119150509190505600a165627a7a72305820a4a547cfc7202c5acaaae74d428e988bc62ad5024eb0165532d3a8f91db4ed2400290000000000000000000000000882477e7895bdc5cea7cb1552ed914ab157fe56";

export const WANDERWING = "0x60806040523661000b57005b60007fbec77a503c47907b093281e779d211f6b514083b5f8064a268e3b9dcae86aa87546040517fc2c95814000000000000000000000000000000000000000000000000000000008152600080357fffffffff0000000000000000000000000000000000000000000000000000000016600483015273ffffffffffffffffffffffffffffffffffffffff9092169250829063c2c9581490602401602060405180830381865afa1580156100c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100e6919061010f565b90503660008037600080366000845af43d6000803e808015610107573d6000f35b3d6000fd5b90565b60006020828403121561012157600080fd5b815173ffffffffffffffffffffffffffffffffffffffff8116811461014557600080fd5b939250505056fea2646970667358221220eb78d73a79b6dd591ef8d70f3f61a662e4117947412c92af1f5fd19080a7852364736f6c63430008120033";
13 changes: 13 additions & 0 deletions src/__tests__/edges.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,16 @@ test('issue 42', () => {
expect(r).toEqual([
]);
});

import { WANDERWING } from './__fixtures__/proxies';
test('issue 67', () => {
const bytecode = WANDERWING;
const r = selectorsFromBytecode(bytecode);
expect(r).toEqual([
]);
});

// Addresses with false positive zero selectors:
// 0x99aa182ed0e2b6c47132e95686d2c73cdeff307f
// 0xb1116d0a09f06d3e22a264c0c233d80e93abec10
// 0xb60e36e2d67a34b4eae678cad779e281e4c6d58c
6 changes: 5 additions & 1 deletion src/__tests__/env.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { test } from 'vitest';
import { test, describe } from 'vitest';

import { ethers } from "ethers";
import { createPublicClient, http } from 'viem';
Expand Down Expand Up @@ -33,6 +33,10 @@ function testerWithContext(tester: ItConcurrent, context: any): TestWithContext
return (name, fn, timeout) => tester(name, () => fn(context), timeout);
}

export function describe_cached(d: string, fn: (context: any) => void) {
return describe(d, () => fn({ provider, env, withCache }));
}

// TODO: Port this to context-aware wrapper
export const online_test = testerWithContext(process.env["ONLINE"] ? test : test.skip, { provider, env });
export const cached_test = testerWithContext(!process.env["SKIP_CACHED"] ? test : test.skip, { provider, env, withCache });
Expand Down
8 changes: 7 additions & 1 deletion src/__tests__/proxies.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { disasm } from '../disasm';
import { addSlotOffset, readArray, joinSlot } from "../slots.js";
import * as proxies from '../proxies';

import { ZEPPELINOS_USDC } from './__fixtures__/proxies'
import { ZEPPELINOS_USDC, WANDERWING } from './__fixtures__/proxies'

// TODO: Test for proxy factories to not match

Expand Down Expand Up @@ -62,6 +62,12 @@ describe('proxy detection', () => {
const program = disasm(bytecode);
expect(program.proxies[0]).toBeInstanceOf(proxies.ZeppelinOSProxyResolver);
});

test('EIP-1967 Proxy: Wanderwing', async () => {
const bytecode = WANDERWING;
const program = disasm(bytecode);
expect(program.proxies[0]).toBeInstanceOf(proxies.EIP1967ProxyResolver);
});
});

describe('known proxy resolving', () => {
Expand Down
29 changes: 27 additions & 2 deletions src/__tests__/selectors.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { expect } from 'vitest';
import { expect, test } from 'vitest';

import { selectorsFromBytecode } from '../index';

import { cached_test } from "./env";
import { cached_test, describe_cached } from "./env";


cached_test('cached online: selectorsFromBytecode for Uniswap v2 Router', async ({ provider, withCache }) => {
Expand Down Expand Up @@ -38,3 +38,28 @@ cached_test('cached online: selectorsFromBytecode for 0x00000000 method', async
const r = selectorsFromBytecode(code);
expect(r).toEqual(expect.arrayContaining(['0x00000000', '0xf04f2707']))
});

describe_cached("detecting zero selector", async ({ provider, withCache}) => {
// Check positive cases
test.each([
{address: "0x000000000000Df8c944e775BDe7Af50300999283"},
])("check presence: $address", async ({address}) => {
const code = await withCache(`${address}_code`, provider.getCode.bind(provider, address))
const r = selectorsFromBytecode(code);
expect(r).toEqual(expect.arrayContaining(['0x00000000']))
});

// Check negative cases
test.each([
{address: "0x99aa182ed0e2b6c47132e95686d2c73cdeff307f"},
{address: "0xb1116d0a09f06d3e22a264c0c233d80e93abec10"},
{address: "0xb60e36e2d67a34b4eae678cad779e281e4c6d58c"},
])("check absence: $address", async ({address}) => {
const code = await withCache(`${address}_code`, provider.getCode.bind(provider, address))
const r = selectorsFromBytecode(code);
expect(r).to.not.equal(expect.arrayContaining(['0x00000000']))
});
});

cached_test('cached online: selectorsFromBytecode that had 0x000000000 false positives', async({ provider, withCache }) => {
});
8 changes: 6 additions & 2 deletions src/disasm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -430,11 +430,15 @@ export function disasm(bytecode: string): Program {

// In some cases, the sequence can get optimized such as for 0x00000000:
// DUP1 ISZERO PUSHN <OFFSET> JUMPI
// But need to avoid CALLVALUE being checked ahead
// FIXME: Need a better heuristic to descriminate the preceding value. This is hacky. :(
if (
code.at(-3) === opcodes.ISZERO &&
code.at(-4) === opcodes.DUP1 &&
code.at(-5) !== opcodes.CALLVALUE
( code.at(-5) === opcodes.CALLDATASIZE ||
code.at(-5) === opcodes.CALLDATALOAD ||
code.at(-5) === opcodes.JUMPDEST ||
code.at(-5) === opcodes.SHR
)
) {
const selector = "0x00000000";
p.selectors[selector] = offsetDest;
Expand Down
3 changes: 2 additions & 1 deletion src/internal/debug.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { mnemonics, OpCode, isPush } from "../opcodes.js";
import { mnemonics, isPush } from "../opcodes.js";
import type { OpCode } from "../opcodes.js";
import { BytecodeIter } from "../disasm.js";
import { bytesToHex } from "../utils.js";

Expand Down

0 comments on commit c21c8de

Please sign in to comment.