TW
Tripwire
Find contracts. Test them. Review real vulns.

Analysis Run

019ba9bc-ec32-7329-bfc3-da15d78dd649

complete
Chain ID
1
Address
Block Number
Created
Sat, Jan 10, 2026 9:08 PM
Review Summary

What survived the funnel

Open this run to answer one question: is this real attacker-relevant behavior with real impact, or just normal contract plumbing?

Confirmed
0
Validated
0
Source
Bytecode only
Review Backing
Present
Best current signal
SELFDESTRUCT reachable
crit 0 high 0 direct contract
Review Checklist
1. Read the findings table first. Ignore raw jobs until the result looks real.
2. Confirm attacker control, not just the existence of a sink.
3. Confirm money or privilege impact.
4. Keep it if the behavior is real. Kill it if this is normal proxy, admin, or upgrade plumbing.

Processing Jobs

Status & attempts
ID Type Status Attempts Heartbeat
37720 artifact.fetch complete 1 / 3 3 months ago
37721 proxy.resolve complete 1 / 3 3 months ago
37722 tool.cast_disasm complete 1 / 3 3 months ago
37723 analysis.bundle complete 1 / 3 3 months ago
37724 capability.graph complete 1 / 3 3 months ago
37725 detector.run complete 1 / 3 3 months ago
37726 validation.fork complete 1 / 3 3 months ago
37895 report.consolidate complete 1 / 6 3 months ago

Artifact

Runtime bytecode: available
Creation TX:
Deployer:
Proxy: no not_proxy
Implementation:
Verified Source: no
Proxy evidence
{
    "status": "not_proxy"
}

Slither

tool.slither

No slither job recorded yet.

Codex

report.consolidate
Job Status
complete
Attempts
1 / 6
Findings
3
No findings?
no
Summary
Bytecode shows an owner-controlled SELFDESTRUCT path and multiple low-level CALLs with ETH value to computed targets (some owner-gated, one apparently user-accessible with effects-before-interactions). No delegatecall/proxy patterns detected in the bundle.
View stdout
{"no_findings":false,"summary":"Bytecode shows an owner-controlled SELFDESTRUCT path and multiple low-level CALLs with ETH value to computed targets (some owner-gated, one apparently user-accessible with effects-before-interactions). No delegatecall/proxy patterns detected in the bundle.","findings":[{"severity":"medium","category":"other","title":"Owner-reachable SELFDESTRUCT can permanently disable the contract","exploit_scenario":"If the owner key is compromised or misused, the SELFDESTRUCT path can be invoked to destroy the contract and send the remaining ETH to an arbitrary address, permanently disabling all functionality for users.","recommendation":"Remove SELFDESTRUCT or gate it behind a timelock/multisig and/or an irreversible disable after deployment. If it is intended, document the risk clearly.","evidence":"A SELFDESTRUCT opcode is reachable after an owner check (SLOAD slot0 masked vs CALLER). The path is invoked via the selector that jumps to pc 0x031c and culminates in SELFDESTRUCT at pc 0x0342.","locations":["selector:0xb9caebf4","pc:0x031d","pc:0x0342"]},{"severity":"medium","category":"access_control","title":"Privileged low-level CALLs with ETH to computed targets (centralization risk)","exploit_scenario":"An owner can trigger low-level CALLs that transfer ETH to computed targets (including a path that uses the contract balance), allowing full fund extraction or arbitrary external interactions if the owner is compromised or malicious.","recommendation":"If arbitrary execution is not required, restrict call targets/amounts or remove these calls. Otherwise, use a multisig + timelock and document the admin powers. Consider adding explicit allowlists or rate limits.","evidence":"Owner check occurs at pc 0x04c0 before two CALL sites that use computed targets/values (pc 0x0575 and pc 0x05b2). The sequence includes ADDRESS/BALANCE, implying ETH transfers under privileged control.","locations":["selector:0xf5bf7413","pc:0x04c0","pc:0x0575","pc:0x05b2"]},{"severity":"low","category":"reentrancy","title":"User-accessible CALL with value has no explicit reentrancy guard","exploit_scenario":"A user-invoked function performs a low-level CALL with value to a computed target. Although storage is updated before the call (effects-before-interactions), a malicious callee could reenter other functions that rely on transient invariants.","recommendation":"If any cross-function invariants exist, add a reentrancy guard to this call path or ensure all state updates are completed before external interaction. Document the intended reentrancy model.","evidence":"CALL at pc 0x066b occurs after an SSTORE at pc 0x0653 in the function reached by selector 0xfa89401a; no mutex/guard pattern is visible in the bytecode.","locations":["selector:0xfa89401a","pc:0x0653","pc:0x066b"]}]}
View stderr
OpenAI Codex v0.77.0 (research preview)
--------
workdir: /tmp/codex-o1lrvfrs
model: gpt-5.2-codex
provider: openai
approval: never
sandbox: read-only
reasoning effort: xhigh
reasoning summaries: auto
session id: 019ba9bd-a2ac-7342-a478-2af4e073c94a
--------
user
You are a security auditor. You ONLY have runtime bytecode + analysis artifacts.
You MUST read `BYTECODE_BUNDLE.json` before concluding; it contains the bytecode summary,
evidence bundle, callsites, storage slots, and detector findings.

Special cases when reasoning from bytecode (be explicit about uncertainty):
- Selector inference is best-effort; missing selectors are common.
- Fallback/receive paths may be the only entrypoints.
- CALL vs DELEGATECALL semantics differ; DELEGATECALL executes in caller storage.
- Proxy patterns (EIP-1967, minimal proxies, beacon) change which storage is authoritative.
- Storage slots are raw; mappings/arrays appear via keccak patterns, names are unknown.
- Guard detection is heuristic; absence of guards does NOT mean unguarded.
- Returndata checking is unknown unless explicitly shown in evidence.
- Precompiles (0x1..0x9) and common ERC20 transfer selectors may appear; do not over-claim.

Output MUST be valid JSON matching the provided schema.
- If you find nothing meaningful: set no_findings=true and findings=[].
- Otherwise: set no_findings=false and include findings with severity/category/title.
- Locations can be pc references like "pc:0x123" or selectors like "selector:0xa9059cbb".

Focus on: reentrancy, access control, upgradeability/proxy issues, signature validation,
accounting/invariant breaks, dangerous delegatecall, and untrusted external calls.
Be conservative: if evidence is weak, mark severity low/medium and explain why.
mcp startup: no servers

thinking
**Reading BYTECODE_BUNDLE.json**
exec
/bin/bash -lc ls in /tmp/codex-o1lrvfrs succeeded in 7ms:
BYTECODE_BUNDLE.json
codex-output-schema.json
exec
/bin/bash -lc 'cat BYTECODE_BUNDLE.json' in /tmp/codex-o1lrvfrs succeeded in 8ms:
{
  "analysis_artifact": {
    "address": "0xd32c59bdf5409842c0dec13a546a3916b7485694",
    "artifact_hash": "0x2bf44a9c729fa79ba25f4bea76b6b37b5caeb1a1715a6f0ff3eb42775aa1c852",
    "artifact_json": {
      "auth": {
        "guards": []
      },
      "basic_blocks": [
        {
          "end_pc": 12,
          "hash": "0x434198e72fc136da3a2e55595e8f204a47c8c94404eb84f07a7325db3defc927",
          "opcodes": [
            "PUSH1",
            "PUSH1",
            "MSTORE",
            "PUSH1",
            "CALLDATASIZE",
            "LT",
            "PUSH2",

thinking
**Analyzing bytecode bundle components**
exec
/bin/bash -lc 'rg -n "storage|slot|proxy|delegatecall|selfdestruct|upgrade|owner|admin|callsite|function" BYTECODE_BUNDLE.json' in /tmp/codex-o1lrvfrs succeeded in 25ms:
1887:      "callsites": [
2424:      "function_entries": [
2466:      "functions": [
2475:            "delegatecall": 0,
2476:            "selfdestruct": 1,
2479:          "storage": {
2481:            "slots": [
2485:                "slot": "0x0000000000000000000000000000000000000000000000000000000000000000"
2490:                "slot": "0x0000000000000000000000000000000000000000000000000000000000000002"
2495:                "slot": "0x0000000000000000000000000000000000000000000000000000000000000000"
2500:                "slot": "0x0000000000000000000000000000000000000000000000000000000000000002"
2505:                "slot": "0x0000000000000000000000000000000000000000000000000000000000000000"
2510:                "slot": "0x0000000000000000000000000000000000000000000000000000000000000002"
2515:                "slot": "0x0000000000000000000000000000000000000000000000000000000000000002"
2520:                "slot": "0x0000000000000000000000000000000000000000000000000000000000000000"
2525:                "slot": "0x0000000000000000000000000000000000000000000000000000000000000000"
2530:                "slot": "0x0000000000000000000000000000000000000000000000000000000000000002"
2535:                "slot": "0x0000000000000000000000000000000000000000000000000000000000000000"
2540:                "slot": "0x0000000000000000000000000000000000000000000000000000000000000000"
2545:                "slot": "0x0000000000000000000000000000000000000000000000000000000000000000"

thinking
**Inspecting callsites near line 1887**
exec
/bin/bash -lc "sed -n '1860,1945p' BYTECODE_BUNDLE.json" in /tmp/codex-o1lrvfrs succeeded in 20ms:
          "end_pc": 1760,
          "hash": "0xfb083f0d7f122d6daac0c7b2d8c7055723b97b6732419d2c1cdf79486b8b9238",
          "opcodes": [
            "OP_A1",
            "PUSH6",
            "SHA3",
            "OP_97",
            "OP_EA",
            "OP_E3",
            "CALLDATASIZE",
            "OP_92"
          ],
          "start_pc": 1747
        },
        {
          "end_pc": 1765,
          "hash": "0x38c3348b4b24dc8c07eb5b01006ec4f62e5cbc1b284008c78921fa846ae276a5",
          "opcodes": [
            "JUMPDEST",
            "EXTCODEHASH",

thinking
**Noting additional function entries**
exec
/bin/bash -lc "sed -n '2400,2525p' BYTECODE_BUNDLE.json" in /tmp/codex-o1lrvfrs succeeded in 6ms:
        },
        {
          "from": "bb:1569",
          "to": "bb:1655",
          "type": "control_flow_fallthrough"
        },
        {
          "from": "bb:1724",
          "to": "bb:1739",
          "type": "control_flow"
        },
        {
          "from": "bb:1724",
          "to": "bb:1738",
          "type": "control_flow_fallthrough"
        },
        {
          "from": "bb:1747",
          "to": "bb:1761",
          "type": "control_flow_fallthrough"

thinking
**Exploring further for write and self-destruct actions**
exec
/bin/bash -lc "sed -n '2525,2625p' BYTECODE_BUNDLE.json" in /tmp/codex-o1lrvfrs succeeded in 11ms:
                "slot": "0x0000000000000000000000000000000000000000000000000000000000000000"
              },
              {
                "op": "SLOAD",
                "pc": 838,
                "slot": "0x0000000000000000000000000000000000000000000000000000000000000002"
              },
              {
                "op": "SLOAD",
                "pc": 847,
                "slot": "0x0000000000000000000000000000000000000000000000000000000000000000"
              },
              {
                "op": "SLOAD",
                "pc": 895,
                "slot": "0x0000000000000000000000000000000000000000000000000000000000000000"
              },
              {
                "op": "SLOAD",
                "pc": 956,

thinking
**Investigating repeated function clones**
exec
/bin/bash -lc 'rg -n "SELFDESTRUCT" BYTECODE_BUNDLE.json' in /tmp/codex-o1lrvfrs succeeded in 7ms:
973:            "SELFDESTRUCT"
5608:        "sink": "SELFDESTRUCT"
5611:      "title": "SELFDESTRUCT reachable",
5620:        "sink": "SELFDESTRUCT",

thinking
**Checking opcode listing for SELFDESTRUCT**
exec
/bin/bash -lc "sed -n '930,1015p' BYTECODE_BUNDLE.json" in /tmp/codex-o1lrvfrs succeeded in 25ms:
          "opcodes": [
            "JUMPDEST",
            "PUSH1",
            "SLOAD",
            "CALLER",
            "PUSH1",
            "PUSH1",
            "PUSH1",
            "EXP",
            "SUB",
            "OP_90",
            "OP_81",
            "AND",
            "OP_91",
            "AND",
            "EQ",
            "PUSH2",
            "JUMPI"
          ],
          "start_pc": 796

thinking
**Analyzing proxy admin storage slots**
exec
/bin/bash -lc "python - <<'PY'
import hashlib

keys = [
    'eip1967.proxy.admin',
    'eip1967.proxy.implementation',
    'eip1967.proxy.beacon',
    'eip1967.proxy.rollback',
    'org.zeppelinos.proxy.admin',
    'eip1967.proxy.owner',
    'eip1967.proxy.operator',
    'eip1967.proxy.proxiable',
    'eip1967.proxy.masterCopy',
    'eip1967.proxy.logic',
    'openzeppelin.proxy.admin',
    'EIP1967.proxy.admin',
    'EIP1967.proxy.implementation',
    'eip1967.admin',
    'eip1967.proxy.implementation.v1',
]

for k in keys:
    h = hashlib.sha3_256(k.encode()).hexdigest()
    slot = int(h, 16) - 1
    print(k, hex(slot))

# check known 0x8be0079c...
print('target', '0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0')
PY" in /tmp/codex-o1lrvfrs succeeded in 30ms:
eip1967.proxy.admin 0x5846d050da0e75d43b6055ae3cd6c2c65e1941ccb45afff84b891ff0c7a8e50e
eip1967.proxy.implementation 0x169aa7877a62aec264f92a4c78812101abc42f65cbb20781a5cb4084c2d639d7
eip1967.proxy.beacon 0x79d0e26f0ed6a26bf96d37944c615e11aedbfafe56e064339e13dad9525cda31
eip1967.proxy.rollback 0x9918ff29762f88fdc924c0a0ba5589b288a6baef366b4981f9a6f4309baada55
org.zeppelinos.proxy.admin 0xe59ed60ca6e4e7df6bd875f45f3199fa50d18f9f8eab0cbc73f528c3bf38189c
eip1967.proxy.owner 0xa94ebdd3c074493cb52768014c2ef842da51c56ea919459168310621970ad9d0
eip1967.proxy.operator 0x1bc57950e7e87ddb2e1fd468be7d386f14341c4f58f2e1b5ae9bc5c7057c7c0
eip1967.proxy.proxiable 0x834da78d022446a4e60e568318d9bfed539f9142721d47ae308f5f5f520c8e3a
eip1967.proxy.masterCopy 0xa1149e0101cd350b4e18716dc87535187a546b6fdc78f1ed2eeaa57ace633d94
eip1967.proxy.logic 0xd9ddb2e122446356b04c14be4d42e1c40d02245a18b9c1a18102de7f6cfa4786
openzeppelin.proxy.admin 0xd740b40f0f3f50e6209ada64c25a33f107517eb2c05de7e3397bfbb0f6cdbaf6
EIP1967.proxy.admin 0xe8d64b2e1e492bb293a88fd27a38d7b94c1f32274a34112849ae01f1d971ba62
EIP1967.proxy.implementation 0xbe58c6578a4ab1ecf11345a15902a106ecb5df07e4b8d27696b57d59fd6ec1a3
eip1967.admin 0xe8a91ba9591a6b855bd0b916a706dbcf487665ff4db3dd9eee2bce1a3093eaeb
eip1967.proxy.implementation.v1 0xaa322e21c3a5a7bc08f27560df6580721f4992390573e13da995f8f847c1c01c
target 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0

thinking
**Investigating slot hashes and keccak differences**
exec
/bin/bash -lc "python - <<'PY'
try:
    import sha3
    print('sha3 module available')
    k = sha3.keccak_256()
    k.update(b'eip1967.proxy.admin')
    h = int(k.hexdigest(),16)-1
    print('admin slot', hex(h))
    k = sha3.keccak_256(); k.update(b'eip1967.proxy.implementation'); h=int(k.hexdigest(),16)-1
    print('impl slot', hex(h))
    k = sha3.keccak_256(); k.update(b'eip1967.proxy.beacon'); h=int(k.hexdigest(),16)-1
    print('beacon slot', hex(h))
    k = sha3.keccak_256(); k.update(b'eip1967.proxy.rollback'); h=int(k.hexdigest(),16)-1
    print('rollback', hex(h))
    k = sha3.keccak_256(); k.update(b'eip1967.proxy.owner'); h=int(k.hexdigest(),16)-1
    print('owner', hex(h))
    k = sha3.keccak_256(); k.update(b'org.zeppelinos.proxy.admin'); h=int(k.hexdigest(),16)-1
    print('zeppelin admin', hex(h))
    k = sha3.keccak_256(); k.update(b'eip1967.proxy.masterCopy'); h=int(k.hexdigest(),16)-1
    print('mastercopy', hex(h))
    k = sha3.keccak_256(); k.update(b'EIP1967.proxy.admin'); h=int(k.hexdigest(),16)-1
    print('cap admin', hex(h))
    k = sha3.keccak_256(); k.update(b'openzeppelin.proxy.admin'); h=int(k.hexdigest(),16)-1
    print('openzeppelin admin', hex(h))
    k = sha3.keccak_256(); k.update(b'eip1967.proxy.logic'); h=int(k.hexdigest(),16)-1
    print('logic', hex(h))
    k = sha3.keccak_256(); k.update(b'PROXIABLE'); h=int(k.hexdigest(),16)
    print('proxiable', hex(h))
    k = sha3.keccak_256(); k.update(b'AccessControl'); h=int(k.hexdigest(),16)
    print('accesscontrol', hex(h))
except Exception as e:
    print('error', e)
PY" in /tmp/codex-o1lrvfrs succeeded in 17ms:
error No module named 'sha3'

thinking
**Analyzing callsites and contract behavior**

I'm examining call targets that seem to be self-calls, which might indicate internal ETH transfers or reentrancy risks, though external untrusted calls seem unlikely from trace data. I'm parsing callsite PCs and corresponding opcode blocks to assess call targets, access control (notably owner checks for selfdestruct), and function mappings, aware that analysis artifacts show some uncertainties—like uniform sink counts for all functions—meaning function boundaries and call details may be imprecise. I'm exploring whether calls use computed addresses from calldata or storage to better understand potential vulnerabilities.
exec
/bin/bash -lc 'rg -n "evidence|disasm|instruction|opcodes_with_pc|pc_map|analysis" BYTECODE_BUNDLE.json' in /tmp/codex-o1lrvfrs succeeded in 15ms:
2:  "analysis_artifact": {
4006:      "version": "analysis_artifact_v1"
4014:    "version": "analysis_artifact_v1"
4016:  "analysis_run": {
4040:      "proxy_evidence": {
5499:      "evidence_json": {
5551:      "evidence_json": {
5603:      "evidence_json": {

thinking
**Inspecting analysis_run for evidence**
exec
/bin/bash -lc "sed -n '3980,4085p' BYTECODE_BUNDLE.json" in /tmp/codex-o1lrvfrs succeeded in 6ms:
            "pc": 1249,
            "slot": "0x0000000000000000000000000000000000000000000000000000000000000002"
          },
          {
            "op": "SLOAD",
            "pc": 1297,
            "slot": "0x0000000000000000000000000000000000000000000000000000000000000002"
          },
          {
            "op": "SLOAD",
            "pc": 1487,
            "slot": "0x0000000000000000000000000000000000000000000000000000000000000002"
          },
          {
            "op": "SLOAD",
            "pc": 1515,
            "slot": "0x0000000000000000000000000000000000000000000000000000000000000000"
          },
          {
            "op": "SLOAD",

thinking
**Decoding runtime bytecode**

I’m going to analyze the full runtime bytecode from the artifact by writing a Python script that disassembles the hex into EVM opcodes. I want to focus on key program counters such as known callsites and the selfdestruct opcode to better understand the contract’s functions and security aspects. This approach avoids relying on network tools and helps reveal the contract logic directly from the bytecode.
exec
/bin/bash -lc "python - <<'PY'
import json

# load runtime bytecode
with open('BYTECODE_BUNDLE.json','r') as f:
    data = json.load(f)
code_hex = data['artifact']['runtime_bytecode']['full']
assert code_hex.startswith('0x')
code = bytes.fromhex(code_hex[2:])

# EVM opcode table
opcodes = {i: f'OP_{i:02X}' for i in range(256)}
# fill known
names = {
0x00:'STOP',0x01:'ADD',0x02:'MUL',0x03:'SUB',0x04:'DIV',0x05:'SDIV',0x06:'MOD',0x07:'SMOD',0x08:'ADDMOD',0x09:'MULMOD',0x0a:'EXP',0x0b:'SIGNEXTEND',
0x10:'LT',0x11:'GT',0x12:'SLT',0x13:'SGT',0x14:'EQ',0x15:'ISZERO',0x16:'AND',0x17:'OR',0x18:'XOR',0x19:'NOT',0x1a:'BYTE',0x1b:'SHL',0x1c:'SHR',0x1d:'SAR',
0x20:'SHA3',
0x30:'ADDRESS',0x31:'BALANCE',0x32:'ORIGIN',0x33:'CALLER',0x34:'CALLVALUE',0x35:'CALLDATALOAD',0x36:'CALLDATASIZE',0x37:'CALLDATACOPY',0x38:'CODESIZE',0x39:'CODECOPY',0x3a:'GASPRICE',0x3b:'EXTCODESIZE',0x3c:'EXTCODECOPY',0x3d:'RETURNDATASIZE',0x3e:'RETURNDATACOPY',0x3f:'EXTCODEHASH',
0x40:'BLOCKHASH',0x41:'COINBASE',0x42:'TIMESTAMP',0x43:'NUMBER',0x44:'DIFFICULTY',0x45:'GASLIMIT',0x46:'CHAINID',0x47:'SELFBALANCE',0x48:'BASEFEE',
0x50:'POP',0x51:'MLOAD',0x52:'MSTORE',0x53:'MSTORE8',0x54:'SLOAD',0x55:'SSTORE',0x56:'JUMP',0x57:'JUMPI',0x58:'PC',0x59:'MSIZE',0x5a:'GAS',0x5b:'JUMPDEST',
0x60:'PUSH1',0x61:'PUSH2',0x62:'PUSH3',0x63:'PUSH4',0x64:'PUSH5',0x65:'PUSH6',0x66:'PUSH7',0x67:'PUSH8',0x68:'PUSH9',0x69:'PUSH10',0x6a:'PUSH11',0x6b:'PUSH12',0x6c:'PUSH13',0x6d:'PUSH14',0x6e:'PUSH15',0x6f:'PUSH16',
0x70:'PUSH17',0x71:'PUSH18',0x72:'PUSH19',0x73:'PUSH20',0x74:'PUSH21',0x75:'PUSH22',0x76:'PUSH23',0x77:'PUSH24',0x78:'PUSH25',0x79:'PUSH26',0x7a:'PUSH27',0x7b:'PUSH28',0x7c:'PUSH29',0x7d:'PUSH30',0x7e:'PUSH31',0x7f:'PUSH32',
0x80:'DUP1',0x81:'DUP2',0x82:'DUP3',0x83:'DUP4',0x84:'DUP5',0x85:'DUP6',0x86:'DUP7',0x87:'DUP8',0x88:'DUP9',0x89:'DUP10',0x8a:'DUP11',0x8b:'DUP12',0x8c:'DUP13',0x8d:'DUP14',0x8e:'DUP15',0x8f:'DUP16',
0x90:'SWAP1',0x91:'SWAP2',0x92:'SWAP3',0x93:'SWAP4',0x94:'SWAP5',0x95:'SWAP6',0x96:'SWAP7',0x97:'SWAP8',0x98:'SWAP9',0x99:'SWAP10',0x9a:'SWAP11',0x9b:'SWAP12',0x9c:'SWAP13',0x9d:'SWAP14',0x9e:'SWAP15',0x9f:'SWAP16',
0xa0:'LOG0',0xa1:'LOG1',0xa2:'LOG2',0xa3:'LOG3',0xa4:'LOG4',
0xf0:'CREATE',0xf1:'CALL',0xf2:'CALLCODE',0xf3:'RETURN',0xf4:'DELEGATECALL',0xf5:'CREATE2',0xfa:'STATICCALL',0xfd:'REVERT',0xfe:'INVALID',0xff:'SELFDESTRUCT',
}
opcodes.update(names)

# disassemble
instrs=[]
pc=0
while pc < len(code):
    op = code[pc]
    name = opcodes.get(op, f'OP_{op:02X}')
    if 0x60 <= op <= 0x7f:
        n = op - 0x5f
        data = code[pc+1:pc+1+n]
        instrs.append((pc, name, data.hex()))
        pc += 1 + n
    else:
        instrs.append((pc, name, None))
        pc += 1

# helper to print window around pc

def print_window(center, radius=20):
    # find index
    idx = next((i for i,(p,_,_) in enumerate(instrs) if p==center), None)
    if idx is None:
        # find nearest
        idx = max(i for i,(p,_,_) in enumerate(instrs) if p<center)
    start = max(0, idx-radius)
    end = min(len(instrs), idx+radius)
    for p,name,data in instrs[start:end]:
        if data is None:
            print(f\"{p:04x}: {name}\")
        else:
            print(f\"{p:04x}: {name} 0x{data}\")
    print('---')

for center in [823, 1397, 1458, 1643]:
    print('WINDOW', center)
    print_window(center, radius=25)

# also print function selectors table from dispatcher
# find sequences of PUSH4 (selector) and JUMPI near start
print('Dispatcher selectors:')
for i,(p,name,data) in enumerate(instrs[:200]):
    if name=='PUSH4':
        print(f\"{p:04x}: selector 0x{data}\")

PY" in /tmp/codex-o1lrvfrs succeeded in 32ms:
WINDOW 823
0317: EXP
0318: SUB
0319: AND
031a: DUP2
031b: JUMP
031c: JUMPDEST
031d: PUSH1 0x00
031f: SLOAD
0320: CALLER
0321: PUSH1 0x01
0323: PUSH1 0xa0
0325: PUSH1 0x02
0327: EXP
0328: SUB
0329: SWAP1
032a: DUP2
032b: AND
032c: SWAP2
032d: AND

thinking
**Analyzing dynamic call patterns and dispatch table**
exec
/bin/bash -lc "python - <<'PY'
import json

with open('BYTECODE_BUNDLE.json','r') as f:
    data = json.load(f)
code_hex = data['artifact']['runtime_bytecode']['full']
code = bytes.fromhex(code_hex[2:])

# opcode lengths
oplen = {**{i:1 for i in range(256)}, **{i:1 for i in range(0x60,0x80)}}
for i in range(0x60,0x80):
    oplen[i] = 1 + (i - 0x5f)

# disasm with pc and immediate values
instrs=[]
pc=0
while pc < len(code):
    op=code[pc]
    name = op
    if 0x60 <= op <= 0x7f:
        n=op-0x5f
        data=code[pc+1:pc+1+n]
        instrs.append((pc, op, data))
        pc += 1+n
    else:
        instrs.append((pc, op, None))
        pc += 1

# extract dispatcher entries: look for pattern PUSH4 sel, EQ, PUSH2 dest, JUMPI
entries=[]
for i in range(len(instrs)-3):
    p1,op1,data1 = instrs[i]
    p2,op2,_= instrs[i+1]
    p3,op3,data3 = instrs[i+2]
    p4,op4,_= instrs[i+3]
    if op1==0x63 and op2==0x14 and op3==0x61 and op4==0x57:
        sel = data1.hex()
        dest = int.from_bytes(data3, 'big')
        entries.append((sel, dest, p1))

print('Dispatcher entries:')
for sel, dest, p in entries:
    print(f\"selector 0x{sel} -> {dest} (at pc {p})\")

# map dest to first few instructions
opnames = {i: f'OP_{i:02X}' for i in range(256)}
name_map = {
0x00:'STOP',0x01:'ADD',0x02:'MUL',0x03:'SUB',0x04:'DIV',0x05:'SDIV',0x06:'MOD',0x07:'SMOD',0x08:'ADDMOD',0x09:'MULMOD',0x0a:'EXP',0x0b:'SIGNEXTEND',
0x10:'LT',0x11:'GT',0x12:'SLT',0x13:'SGT',0x14:'EQ',0x15:'ISZERO',0x16:'AND',0x17:'OR',0x18:'XOR',0x19:'NOT',0x1a:'BYTE',0x1b:'SHL',0x1c:'SHR',0x1d:'SAR',
0x20:'SHA3',
0x30:'ADDRESS',0x31:'BALANCE',0x32:'ORIGIN',0x33:'CALLER',0x34:'CALLVALUE',0x35:'CALLDATALOAD',0x36:'CALLDATASIZE',0x37:'CALLDATACOPY',0x38:'CODESIZE',0x39:'CODECOPY',0x3a:'GASPRICE',0x3b:'EXTCODESIZE',0x3c:'EXTCODECOPY',0x3d:'RETURNDATASIZE',0x3e:'RETURNDATACOPY',0x3f:'EXTCODEHASH',
0x40:'BLOCKHASH',0x41:'COINBASE',0x42:'TIMESTAMP',0x43:'NUMBER',0x44:'DIFFICULTY',0x45:'GASLIMIT',0x46:'CHAINID',0x47:'SELFBALANCE',0x48:'BASEFEE',
0x50:'POP',0x51:'MLOAD',0x52:'MSTORE',0x53:'MSTORE8',0x54:'SLOAD',0x55:'SSTORE',0x56:'JUMP',0x57:'JUMPI',0x58:'PC',0x59:'MSIZE',0x5a:'GAS',0x5b:'JUMPDEST',
0x60:'PUSH1',0x61:'PUSH2',0x62:'PUSH3',0x63:'PUSH4',0x64:'PUSH5',0x65:'PUSH6',0x66:'PUSH7',0x67:'PUSH8',0x68:'PUSH9',0x69:'PUSH10',0x6a:'PUSH11',0x6b:'PUSH12',0x6c:'PUSH13',0x6d:'PUSH14',0x6e:'PUSH15',0x6f:'PUSH16',
0x70:'PUSH17',0x71:'PUSH18',0x72:'PUSH19',0x73:'PUSH20',0x74:'PUSH21',0x75:'PUSH22',0x76:'PUSH23',0x77:'PUSH24',0x78:'PUSH25',0x79:'PUSH26',0x7a:'PUSH27',0x7b:'PUSH28',0x7c:'PUSH29',0x7d:'PUSH30',0x7e:'PUSH31',0x7f:'PUSH32',
0x80:'DUP1',0x81:'DUP2',0x82:'DUP3',0x83:'DUP4',0x84:'DUP5',0x85:'DUP6',0x86:'DUP7',0x87:'DUP8',0x88:'DUP9',0x89:'DUP10',0x8a:'DUP11',0x8b:'DUP12',0x8c:'DUP13',0x8d:'DUP14',0x8e:'DUP15',0x8f:'DUP16',
0x90:'SWAP1',0x91:'SWAP2',0x92:'SWAP3',0x93:'SWAP4',0x94:'SWAP5',0x95:'SWAP6',0x96:'SWAP7',0x97:'SWAP8',0x98:'SWAP9',0x99:'SWAP10',0x9a:'SWAP11',0x9b:'SWAP12',0x9c:'SWAP13',0x9d:'SWAP14',0x9e:'SWAP15',0x9f:'SWAP16',
0xa0:'LOG0',0xa1:'LOG1',0xa2:'LOG2',0xa3:'LOG3',0xa4:'LOG4',
0xf0:'CREATE',0xf1:'CALL',0xf2:'CALLCODE',0xf3:'RETURN',0xf4:'DELEGATECALL',0xf5:'CREATE2',0xfa:'STATICCALL',0xfd:'REVERT',0xfe:'INVALID',0xff:'SELFDESTRUCT',
}

# create map from pc to index
idx_by_pc = {p:i for i,(p,_,_) in enumerate(instrs)}

for sel, dest, p in entries:
    idx = idx_by_pc.get(dest)
    if idx is None:
        continue
    # print first 8 instructions from dest
    print(f\"\\nEntry 0x{sel} at pc {dest}\")
    for p2,op,data in instrs[idx:idx+10]:
        name = name_map.get(op,f'OP_{op:02X}')
        if data is None:
            print(f\"  {p2:04x}: {name}\")
        else:
            print(f\"  {p2:04x}: {name} 0x{data.hex()}\")
PY" in /tmp/codex-o1lrvfrs succeeded in 41ms:
Dispatcher entries:
selector 0x47fa061e -> 189 (at pc 65)
selector 0x8c52dc41 -> 244 (at pc 76)
selector 0x8da5cb5b -> 263 (at pc 87)
selector 0xb9caebf4 -> 310 (at pc 98)
selector 0xc19d93fb -> 341 (at pc 109)
selector 0xf2fde38b -> 396 (at pc 120)
selector 0xf340fa01 -> 427 (at pc 131)
selector 0xf5bf7413 -> 447 (at pc 142)
selector 0xfa89401a -> 487 (at pc 153)

Entry 0x47fa061e at pc 189
  00bd: JUMPDEST
  00be: CALLVALUE
  00bf: ISZERO
  00c0: PUSH2 0x00c8
  00c3: JUMPI
  00c4: PUSH1 0x00
  00c6: DUP1
  00c7: REVERT

thinking
**Investigating missing selector in dispatch**
exec
/bin/bash -lc "python - <<'PY'
import json
with open('BYTECODE_BUNDLE.json','r') as f:
    data=json.load(f)
code=bytes.fromhex(data['artifact']['runtime_bytecode']['full'][2:])

opnames={i:f'OP_{i:02X}' for i in range(256)}
# fill names same as before
names={0x00:'STOP',0x01:'ADD',0x02:'MUL',0x03:'SUB',0x04:'DIV',0x05:'SDIV',0x06:'MOD',0x07:'SMOD',0x08:'ADDMOD',0x09:'MULMOD',0x0a:'EXP',0x0b:'SIGNEXTEND',
0x10:'LT',0x11:'GT',0x12:'SLT',0x13:'SGT',0x14:'EQ',0x15:'ISZERO',0x16:'AND',0x17:'OR',0x18:'XOR',0x19:'NOT',0x1a:'BYTE',0x1b:'SHL',0x1c:'SHR',0x1d:'SAR',
0x20:'SHA3',
0x30:'ADDRESS',0x31:'BALANCE',0x32:'ORIGIN',0x33:'CALLER',0x34:'CALLVALUE',0x35:'CALLDATALOAD',0x36:'CALLDATASIZE',0x37:'CALLDATACOPY',0x38:'CODESIZE',0x39:'CODECOPY',0x3a:'GASPRICE',0x3b:'EXTCODESIZE',0x3c:'EXTCODECOPY',0x3d:'RETURNDATASIZE',0x3e:'RETURNDATACOPY',0x3f:'EXTCODEHASH',
0x40:'BLOCKHASH',0x41:'COINBASE',0x42:'TIMESTAMP',0x43:'NUMBER',0x44:'DIFFICULTY',0x45:'GASLIMIT',0x46:'CHAINID',0x47:'SELFBALANCE',0x48:'BASEFEE',
0x50:'POP',0x51:'MLOAD',0x52:'MSTORE',0x53:'MSTORE8',0x54:'SLOAD',0x55:'SSTORE',0x56:'JUMP',0x57:'JUMPI',0x58:'PC',0x59:'MSIZE',0x5a:'GAS',0x5b:'JUMPDEST',
0x60:'PUSH1',0x61:'PUSH2',0x62:'PUSH3',0x63:'PUSH4',0x64:'PUSH5',0x65:'PUSH6',0x66:'PUSH7',0x67:'PUSH8',0x68:'PUSH9',0x69:'PUSH10',0x6a:'PUSH11',0x6b:'PUSH12',0x6c:'PUSH13',0x6d:'PUSH14',0x6e:'PUSH15',0x6f:'PUSH16',
0x70:'PUSH17',0x71:'PUSH18',0x72:'PUSH19',0x73:'PUSH20',0x74:'PUSH21',0x75:'PUSH22',0x76:'PUSH23',0x77:'PUSH24',0x78:'PUSH25',0x79:'PUSH26',0x7a:'PUSH27',0x7b:'PUSH28',0x7c:'PUSH29',0x7d:'PUSH30',0x7e:'PUSH31',0x7f:'PUSH32',
0x80:'DUP1',0x81:'DUP2',0x82:'DUP3',0x83:'DUP4',0x84:'DUP5',0x85:'DUP6',0x86:'DUP7',0x87:'DUP8',0x88:'DUP9',0x89:'DUP10',0x8a:'DUP11',0x8b:'DUP12',0x8c:'DUP13',0x8d:'DUP14',0x8e:'DUP15',0x8f:'DUP16',
0x90:'SWAP1',0x91:'SWAP2',0x92:'SWAP3',0x93:'SWAP4',0x94:'SWAP5',0x95:'SWAP6',0x96:'SWAP7',0x97:'SWAP8',0x98:'SWAP9',0x99:'SWAP10',0x9a:'SWAP11',0x9b:'SWAP12',0x9c:'SWAP13',0x9d:'SWAP14',0x9e:'SWAP15',0x9f:'SWAP16',
0xa0:'LOG0',0xa1:'LOG1',0xa2:'LOG2',0xa3:'LOG3',0xa4:'LOG4',
0xf0:'CREATE',0xf1:'CALL',0xf2:'CALLCODE',0xf3:'RETURN',0xf4:'DELEGATECALL',0xf5:'CREATE2',0xfa:'STATICCALL',0xfd:'REVERT',0xfe:'INVALID',0xff:'SELFDESTRUCT'}

opnames.update(names)

pc=0
count=0
while pc < len(code) and count < 80:
    op=code[pc]
    name=opnames.get(op,f'OP_{op:02X}')
    if 0x60 <= op <= 0x7f:
        n=op-0x5f
        data=code[pc+1:pc+1+n]
        print(f\"{pc:04x}: {name} 0x{data.hex()}\")
        pc += 1+n
    else:
        print(f\"{pc:04x}: {name}\")
        pc += 1
    count+=1
PY" in /tmp/codex-o1lrvfrs succeeded in 28ms:
0000: PUSH1 0x60
0002: PUSH1 0x40
0004: MSTORE
0005: PUSH1 0x04
0007: CALLDATASIZE
0008: LT
0009: PUSH2 0x00a3
000c: JUMPI
000d: PUSH4 0xffffffff
0012: PUSH29 0x0100000000000000000000000000000000000000000000000000000000
0030: PUSH1 0x00
0032: CALLDATALOAD
0033: DIV
0034: AND
0035: PUSH4 0x1ef3755d
003a: DUP2
003b: EQ
003c: PUSH2 0x00a8
003f: JUMPI
0040: DUP1

thinking
**Analyzing function entries and control flow**

I'm parsing the bytecode to identify function selectors and their semantics, focusing on calls and access control by tracing jumps and function boundaries. I plan to disassemble each entry point, track internal jumps, and recognize typical return wrappers to understand the control flow and behaviors without source code or network access.
exec
/bin/bash -lc "python - <<'PY'
import json
with open('BYTECODE_BUNDLE.json','r') as f:
    data=json.load(f)
code=bytes.fromhex(data['artifact']['runtime_bytecode']['full'][2:])
# disasm function
opnames={i:f'OP_{i:02X}' for i in range(256)}
# add known names
names={0x00:'STOP',0x01:'ADD',0x02:'MUL',0x03:'SUB',0x04:'DIV',0x05:'SDIV',0x06:'MOD',0x07:'SMOD',0x08:'ADDMOD',0x09:'MULMOD',0x0a:'EXP',0x0b:'SIGNEXTEND',
0x10:'LT',0x11:'GT',0x12:'SLT',0x13:'SGT',0x14:'EQ',0x15:'ISZERO',0x16:'AND',0x17:'OR',0x18:'XOR',0x19:'NOT',0x1a:'BYTE',0x1b:'SHL',0x1c:'SHR',0x1d:'SAR',
0x20:'SHA3',
0x30:'ADDRESS',0x31:'BALANCE',0x32:'ORIGIN',0x33:'CALLER',0x34:'CALLVALUE',0x35:'CALLDATALOAD',0x36:'CALLDATASIZE',0x37:'CALLDATACOPY',0x38:'CODESIZE',0x39:'CODECOPY',0x3a:'GASPRICE',0x3b:'EXTCODESIZE',0x3c:'EXTCODECOPY',0x3d:'RETURNDATASIZE',0x3e:'RETURNDATACOPY',0x3f:'EXTCODEHASH',
0x40:'BLOCKHASH',0x41:'COINBASE',0x42:'TIMESTAMP',0x43:'NUMBER',0x44:'DIFFICULTY',0x45:'GASLIMIT',0x46:'CHAINID',0x47:'SELFBALANCE',0x48:'BASEFEE',
0x50:'POP',0x51:'MLOAD',0x52:'MSTORE',0x53:'MSTORE8',0x54:'SLOAD',0x55:'SSTORE',0x56:'JUMP',0x57:'JUMPI',0x58:'PC',0x59:'MSIZE',0x5a:'GAS',0x5b:'JUMPDEST',
0x60:'PUSH1',0x61:'PUSH2',0x62:'PUSH3',0x63:'PUSH4',0x64:'PUSH5',0x65:'PUSH6',0x66:'PUSH7',0x67:'PUSH8',0x68:'PUSH9',0x69:'PUSH10',0x6a:'PUSH11',0x6b:'PUSH12',0x6c:'PUSH13',0x6d:'PUSH14',0x6e:'PUSH15',0x6f:'PUSH16',
0x70:'PUSH17',0x71:'PUSH18',0x72:'PUSH19',0x73:'PUSH20',0x74:'PUSH21',0x75:'PUSH22',0x76:'PUSH23',0x77:'PUSH24',0x78:'PUSH25',0x79:'PUSH26',0x7a:'PUSH27',0x7b:'PUSH28',0x7c:'PUSH29',0x7d:'PUSH30',0x7e:'PUSH31',0x7f:'PUSH32',
0x80:'DUP1',0x81:'DUP2',0x82:'DUP3',0x83:'DUP4',0x84:'DUP5',0x85:'DUP6',0x86:'DUP7',0x87:'DUP8',0x88:'DUP9',0x89:'DUP10',0x8a:'DUP11',0x8b:'DUP12',0x8c:'DUP13',0x8d:'DUP14',0x8e:'DUP15',0x8f:'DUP16',
0x90:'SWAP1',0x91:'SWAP2',0x92:'SWAP3',0x93:'SWAP4',0x94:'SWAP5',0x95:'SWAP6',0x96:'SWAP7',0x97:'SWAP8',0x98:'SWAP9',0x99:'SWAP10',0x9a:'SWAP11',0x9b:'SWAP12',0x9c:'SWAP13',0x9d:'SWAP14',0x9e:'SWAP15',0x9f:'SWAP16',
0xa0:'LOG0',0xa1:'LOG1',0xa2:'LOG2',0xa3:'LOG3',0xa4:'LOG4',
0xf0:'CREATE',0xf1:'CALL',0xf2:'CALLCODE',0xf3:'RETURN',0xf4:'DELEGATECALL',0xf5:'CREATE2',0xfa:'STATICCALL',0xfd:'REVERT',0xfe:'INVALID',0xff:'SELFDESTRUCT'}

opnames.update(names)

# build mapping pc->(op,data)
instrs=[]
pc=0
while pc < len(code):
    op = code[pc]
    if 0x60 <= op <= 0x7f:
        n=op-0x5f
        data=code[pc+1:pc+1+n]
        instrs.append((pc, op, data))
        pc += 1+n
    else:
        instrs.append((pc, op, None))
        pc += 1

idx_by_pc = {p:i for i,(p,_,_) in enumerate(instrs)}

# print around 0x00bb
start=idx_by_pc[0x00bb]
for p,op,data in instrs[start:start+20]:
    name = opnames.get(op,f'OP_{op:02X}')
    if data is None:
        print(f\"{p:04x}: {name}\")
    else:
        print(f\"{p:04x}: {name} 0x{data.hex()}\")
PY" in /tmp/codex-o1lrvfrs succeeded in 28ms:
00bb: JUMPDEST
00bc: STOP
00bd: JUMPDEST
00be: CALLVALUE
00bf: ISZERO
00c0: PUSH2 0x00c8
00c3: JUMPI
00c4: PUSH1 0x00
00c6: DUP1
00c7: REVERT
00c8: JUMPDEST
00c9: PUSH2 0x00e2
00cc: PUSH1 0xff
00ce: PUSH1 0x04
00d0: CALLDATALOAD
00d1: AND
00d2: PUSH1 0x01
00d4: PUSH1 0xa0
00d6: PUSH1 0x02
00d8: EXP

thinking
**Tracing function callsites and STOP instruction**
exec
/bin/bash -lc "python - <<'PY'
import json
with open('BYTECODE_BUNDLE.json','r') as f:
    data=json.load(f)
code=bytes.fromhex(data['artifact']['runtime_bytecode']['full'][2:])

opnames={i:f'OP_{i:02X}' for i in range(256)}
# add names
names={0x00:'STOP',0x01:'ADD',0x02:'MUL',0x03:'SUB',0x04:'DIV',0x05:'SDIV',0x06:'MOD',0x07:'SMOD',0x08:'ADDMOD',0x09:'MULMOD',0x0a:'EXP',0x0b:'SIGNEXTEND',
0x10:'LT',0x11:'GT',0x12:'SLT',0x13:'SGT',0x14:'EQ',0x15:'ISZERO',0x16:'AND',0x17:'OR',0x18:'XOR',0x19:'NOT',0x1a:'BYTE',0x1b:'SHL',0x1c:'SHR',0x1d:'SAR',
0x20:'SHA3',
0x30:'ADDRESS',0x31:'BALANCE',0x32:'ORIGIN',0x33:'CALLER',0x34:'CALLVALUE',0x35:'CALLDATALOAD',0x36:'CALLDATASIZE',0x37:'CALLDATACOPY',0x38:'CODESIZE',0x39:'CODECOPY',0x3a:'GASPRICE',0x3b:'EXTCODESIZE',0x3c:'EXTCODECOPY',0x3d:'RETURNDATASIZE',0x3e:'RETURNDATACOPY',0x3f:'EXTCODEHASH',
0x40:'BLOCKHASH',0x41:'COINBASE',0x42:'TIMESTAMP',0x43:'NUMBER',0x44:'DIFFICULTY',0x45:'GASLIMIT',0x46:'CHAINID',0x47:'SELFBALANCE',0x48:'BASEFEE',
0x50:'POP',0x51:'MLOAD',0x52:'MSTORE',0x53:'MSTORE8',0x54:'SLOAD',0x55:'SSTORE',0x56:'JUMP',0x57:'JUMPI',0x58:'PC',0x59:'MSIZE',0x5a:'GAS',0x5b:'JUMPDEST',
0x60:'PUSH1',0x61:'PUSH2',0x62:'PUSH3',0x63:'PUSH4',0x64:'PUSH5',0x65:'PUSH6',0x66:'PUSH7',0x67:'PUSH8',0x68:'PUSH9',0x69:'PUSH10',0x6a:'PUSH11',0x6b:'PUSH12',0x6c:'PUSH13',0x6d:'PUSH14',0x6e:'PUSH15',0x6f:'PUSH16',
0x70:'PUSH17',0x71:'PUSH18',0x72:'PUSH19',0x73:'PUSH20',0x74:'PUSH21',0x75:'PUSH22',0x76:'PUSH23',0x77:'PUSH24',0x78:'PUSH25',0x79:'PUSH26',0x7a:'PUSH27',0x7b:'PUSH28',0x7c:'PUSH29',0x7d:'PUSH30',0x7e:'PUSH31',0x7f:'PUSH32',
0x80:'DUP1',0x81:'DUP2',0x82:'DUP3',0x83:'DUP4',0x84:'DUP5',0x85:'DUP6',0x86:'DUP7',0x87:'DUP8',0x88:'DUP9',0x89:'DUP10',0x8a:'DUP11',0x8b:'DUP12',0x8c:'DUP13',0x8d:'DUP14',0x8e:'DUP15',0x8f:'DUP16',
0x90:'SWAP1',0x91:'SWAP2',0x92:'SWAP3',0x93:'SWAP4',0x94:'SWAP5',0x95:'SWAP6',0x96:'SWAP7',0x97:'SWAP8',0x98:'SWAP9',0x99:'SWAP10',0x9a:'SWAP11',0x9b:'SWAP12',0x9c:'SWAP13',0x9d:'SWAP14',0x9e:'SWAP15',0x9f:'SWAP16',
0xa0:'LOG0',0xa1:'LOG1',0xa2:'LOG2',0xa3:'LOG3',0xa4:'LOG4',
0xf0:'CREATE',0xf1:'CALL',0xf2:'CALLCODE',0xf3:'RETURN',0xf4:'DELEGATECALL',0xf5:'CREATE2',0xfa:'STATICCALL',0xfd:'REVERT',0xfe:'INVALID',0xff:'SELFDESTRUCT'}

opnames.update(names)

# disasm
instrs=[]
pc=0
while pc < len(code):
    op=code[pc]
    if 0x60 <= op <= 0x7f:
        n=op-0x5f
        data=code[pc+1:pc+1+n]
        instrs.append((pc, op, data))
        pc += 1+n
    else:
        instrs.append((pc, op, None))
        pc += 1

idx_by_pc = {p:i for i,(p,_,_) in enumerate(instrs)}

start=idx_by_pc[0x01ab]
end=start+120
for p,op,data in instrs[start:end]:
    name = opnames.get(op,f'OP_{op:02X}')
    if data is None:
        print(f\"{p:04x}: {name}\")
    else:
        print(f\"{p:04x}: {name} 0x{data.hex()}\")
PY" in /tmp/codex-o1lrvfrs succeeded in 31ms:
01ab: JUMPDEST
01ac: PUSH2 0x00bb
01af: PUSH1 0x01
01b1: PUSH1 0xa0
01b3: PUSH1 0x02
01b5: EXP
01b6: SUB
01b7: PUSH1 0x04
01b9: CALLDATALOAD
01ba: AND
01bb: PUSH2 0x03e7
01be: JUMP
01bf: JUMPDEST
01c0: CALLVALUE
01c1: ISZERO
01c2: PUSH2 0x01ca
01c5: JUMPI
01c6: PUSH1 0x00
01c8: DUP1
01c9: REVERT

thinking
**Analyzing function entry points and events**

I'm piecing together which function selectors map to code locations and their roles, like deciding if they handle calls or state changes. I also confirmed the OwnershipTransferred event by matching its signature hash, and I'm sorting out some confusion between storage slots and event signature constants in the disassembly. There's a lot to untangle here!
exec
/bin/bash -lc "python - <<'PY'
import json
with open('BYTECODE_BUNDLE.json','r') as f:
    data=json.load(f)
code=bytes.fromhex(data['artifact']['runtime_bytecode']['full'][2:])

# quick disasm around 0x0360-0x03a0
opnames={i:f'OP_{i:02X}' for i in range(256)}
# names for key ops
names={0x00:'STOP',0x01:'ADD',0x02:'MUL',0x03:'SUB',0x04:'DIV',0x05:'SDIV',0x06:'MOD',0x07:'SMOD',0x08:'ADDMOD',0x09:'MULMOD',0x0a:'EXP',0x0b:'SIGNEXTEND',
0x10:'LT',0x11:'GT',0x12:'SLT',0x13:'SGT',0x14:'EQ',0x15:'ISZERO',0x16:'AND',0x17:'OR',0x18:'XOR',0x19:'NOT',0x1a:'BYTE',0x1b:'SHL',0x1c:'SHR',0x1d:'SAR',0x20:'SHA3',
0x30:'ADDRESS',0x31:'BALANCE',0x32:'ORIGIN',0x33:'CALLER',0x34:'CALLVALUE',0x35:'CALLDATALOAD',0x36:'CALLDATASIZE',0x37:'CALLDATACOPY',0x38:'CODESIZE',0x39:'CODECOPY',0x3a:'GASPRICE',0x3b:'EXTCODESIZE',0x3c:'EXTCODECOPY',0x3d:'RETURNDATASIZE',0x3e:'RETURNDATACOPY',0x3f:'EXTCODEHASH',
0x50:'POP',0x51:'MLOAD',0x52:'MSTORE',0x53:'MSTORE8',0x54:'SLOAD',0x55:'SSTORE',0x56:'JUMP',0x57:'JUMPI',0x58:'PC',0x59:'MSIZE',0x5a:'GAS',0x5b:'JUMPDEST',
0x60:'PUSH1',0x61:'PUSH2',0x62:'PUSH3',0x63:'PUSH4',0x64:'PUSH5',0x65:'PUSH6',0x66:'PUSH7',0x67:'PUSH8',0x68:'PUSH9',0x69:'PUSH10',0x6a:'PUSH11',0x6b:'PUSH12',0x6c:'PUSH13',0x6d:'PUSH14',0x6e:'PUSH15',0x6f:'PUSH16',
0x70:'PUSH17',0x71:'PUSH18',0x72:'PUSH19',0x73:'PUSH20',0x74:'PUSH21',0x75:'PUSH22',0x76:'PUSH23',0x77:'PUSH24',0x78:'PUSH25',0x79:'PUSH26',0x7a:'PUSH27',0x7b:'PUSH28',0x7c:'PUSH29',0x7d:'PUSH30',0x7e:'PUSH31',0x7f:'PUSH32',
0x80:'DUP1',0x81:'DUP2',0x82:'DUP3',0x83:'DUP4',0x84:'DUP5',0x85:'DUP6',0x86:'DUP7',0x87:'DUP8',0x88:'DUP9',0x89:'DUP10',0x8a:'DUP11',0x8b:'DUP12',0x8c:'DUP13',0x8d:'DUP14',0x8e:'DUP15',0x8f:'DUP16',
0x90:'SWAP1',0x91:'SWAP2',0x92:'SWAP3',0x93:'SWAP4',0x94:'SWAP5',0x95:'SWAP6',0x96:'SWAP7',0x97:'SWAP8',0x98:'SWAP9',0x99:'SWAP10',0x9a:'SWAP11',0x9b:'SWAP12',0x9c:'SWAP13',0x9d:'SWAP14',0x9e:'SWAP15',0x9f:'SWAP16',
0xa0:'LOG0',0xa1:'LOG1',0xa2:'LOG2',0xa3:'LOG3',0xa4:'LOG4',
0xf0:'CREATE',0xf1:'CALL',0xf2:'CALLCODE',0xf3:'RETURN',0xf4:'DELEGATECALL',0xf5:'CREATE2',0xfa:'STATICCALL',0xfd:'REVERT',0xfe:'INVALID',0xff:'SELFDESTRUCT'}

opnames.update(names)

# disasm window
pc=0x0340
while pc < 0x03b0:
    op=code[pc]
    name=opnames.get(op,f'OP_{op:02X}')
    if 0x60 <= op <= 0x7f:
        n=op-0x5f
        data=code[pc+1:pc+1+n]
        print(f\"{pc:04x}: {name} 0x{data.hex()}\")
        pc += 1+n
    else:
        print(f\"{pc:04x}: {name}\")
        pc += 1
PY" in /tmp/codex-o1lrvfrs succeeded in 75ms:
0340: SUB
0341: AND
0342: SELFDESTRUCT
0343: JUMPDEST
0344: PUSH1 0x02
0346: SLOAD
0347: PUSH1 0xff
0349: AND
034a: DUP2
034b: JUMP
034c: JUMPDEST
034d: PUSH1 0x00
034f: SLOAD
0350: CALLER
0351: PUSH1 0x01
0353: PUSH1 0xa0
0355: PUSH1 0x02
0357: EXP
0358: SUB
0359: SWAP1

thinking
**Continuing process**
exec
/bin/bash -lc "python - <<'PY'
import json
with open('BYTECODE_BUNDLE.json','r') as f:
    data=json.load(f)
code=bytes.fromhex(data['artifact']['runtime_bytecode']['full'][2:])

# simple disasm from 0x03ac to 0x0405
opnames={i:f'OP_{i:02X}' for i in range(256)}
# minimal names
names={0xa0:'LOG0',0xa1:'LOG1',0xa2:'LOG2',0xa3:'LOG3',0xa4:'LOG4',0x5b:'JUMPDEST',0x56:'JUMP',0x57:'JUMPI',0x54:'SLOAD',0x55:'SSTORE',0x52:'MSTORE',0x51:'MLOAD',0x60:'PUSH1',0x61:'PUSH2',0x7f:'PUSH32',0x73:'PUSH20',0x90:'SWAP1',0x91:'SWAP2',0x80:'DUP1',0x81:'DUP2',0x82:'DUP3',0x83:'DUP4',0xf3:'RETURN',0xfd:'REVERT'}
opnames.update(names)

pc=0x03a0
while pc < 0x0410:
    op=code[pc]
    name=opnames.get(op,f'OP_{op:02X}')
    if 0x60 <= op <= 0x7f:
        n=op-0x5f
        data=code[pc+1:pc+1+n]
        print(f\"{pc:04x}: {name} 0x{data.hex()}\")
        pc += 1+n
    else:
        print(f\"{pc:04x}: {name}\")
        pc += 1
PY" in /tmp/codex-o1lrvfrs succeeded in 26ms:
03a0: PUSH32 0x9722a3daafe3b4186f6b6457e060405160405180910390a36000805473ffffff
03c1: OP_FF
03c2: OP_FF
03c3: OP_FF
03c4: OP_FF
03c5: OP_FF
03c6: OP_FF
03c7: OP_FF
03c8: OP_FF
03c9: OP_FF
03ca: OP_FF
03cb: OP_FF
03cc: OP_FF
03cd: OP_FF
03ce: OP_FF
03cf: OP_FF
03d0: OP_FF
03d1: OP_FF
03d2: OP_19
03d3: OP_16

thinking
**Correcting disassembly start address**
exec
/bin/bash -lc "python - <<'PY'
import json
with open('BYTECODE_BUNDLE.json','r') as f:
    data=json.load(f)
code=bytes.fromhex(data['artifact']['runtime_bytecode']['full'][2:])

opnames={i:f'OP_{i:02X}' for i in range(256)}
# names minimal
names={0x00:'STOP',0x01:'ADD',0x02:'MUL',0x03:'SUB',0x04:'DIV',0x05:'SDIV',0x06:'MOD',0x07:'SMOD',0x08:'ADDMOD',0x09:'MULMOD',0x0a:'EXP',0x0b:'SIGNEXTEND',
0x10:'LT',0x11:'GT',0x12:'SLT',0x13:'SGT',0x14:'EQ',0x15:'ISZERO',0x16:'AND',0x17:'OR',0x18:'XOR',0x19:'NOT',0x1a:'BYTE',0x1b:'SHL',0x1c:'SHR',0x1d:'SAR',
0x20:'SHA3',
0x30:'ADDRESS',0x31:'BALANCE',0x32:'ORIGIN',0x33:'CALLER',0x34:'CALLVALUE',0x35:'CALLDATALOAD',0x36:'CALLDATASIZE',0x37:'CALLDATACOPY',0x38:'CODESIZE',0x39:'CODECOPY',0x3a:'GASPRICE',0x3b:'EXTCODESIZE',0x3c:'EXTCODECOPY',0x3d:'RETURNDATASIZE',0x3e:'RETURNDATACOPY',0x3f:'EXTCODEHASH',
0x50:'POP',0x51:'MLOAD',0x52:'MSTORE',0x53:'MSTORE8',0x54:'SLOAD',0x55:'SSTORE',0x56:'JUMP',0x57:'JUMPI',0x58:'PC',0x59:'MSIZE',0x5a:'GAS',0x5b:'JUMPDEST',
0x60:'PUSH1',0x61:'PUSH2',0x62:'PUSH3',0x63:'PUSH4',0x64:'PUSH5',0x65:'PUSH6',0x66:'PUSH7',0x67:'PUSH8',0x68:'PUSH9',0x69:'PUSH10',0x6a:'PUSH11',0x6b:'PUSH12',0x6c:'PUSH13',0x6d:'PUSH14',0x6e:'PUSH15',0x6f:'PUSH16',
0x70:'PUSH17',0x71:'PUSH18',0x72:'PUSH19',0x73:'PUSH20',0x74:'PUSH21',0x75:'PUSH22',0x76:'PUSH23',0x77:'PUSH24',0x78:'PUSH25',0x79:'PUSH26',0x7a:'PUSH27',0x7b:'PUSH28',0x7c:'PUSH29',0x7d:'PUSH30',0x7e:'PUSH31',0x7f:'PUSH32',
0x80:'DUP1',0x81:'DUP2',0x82:'DUP3',0x83:'DUP4',0x84:'DUP5',0x85:'DUP6',0x86:'DUP7',0x87:'DUP8',0x88:'DUP9',0x89:'DUP10',0x8a:'DUP11',0x8b:'DUP12',0x8c:'DUP13',0x8d:'DUP14',0x8e:'DUP15',0x8f:'DUP16',
0x90:'SWAP1',0x91:'SWAP2',0x92:'SWAP3',0x93:'SWAP4',0x94:'SWAP5',0x95:'SWAP6',0x96:'SWAP7',0x97:'SWAP8',0x98:'SWAP9',0x99:'SWAP10',0x9a:'SWAP11',0x9b:'SWAP12',0x9c:'SWAP13',0x9d:'SWAP14',0x9e:'SWAP15',0x9f:'SWAP16',
0xa0:'LOG0',0xa1:'LOG1',0xa2:'LOG2',0xa3:'LOG3',0xa4:'LOG4',
0xf0:'CREATE',0xf1:'CALL',0xf2:'CALLCODE',0xf3:'RETURN',0xf4:'DELEGATECALL',0xf5:'CREATE2',0xfa:'STATICCALL',0xfd:'REVERT',0xfe:'INVALID',0xff:'SELFDESTRUCT'}

opnames.update(names)

pc=0x038d
end=0x03f5
while pc < end:
    op=code[pc]
    name=opnames.get(op,f'OP_{op:02X}')
    if 0x60 <= op <= 0x7f:
        n=op-0x5f
        data=code[pc+1:pc+1+n]
        print(f\"{pc:04x}: {name} 0x{data.hex()}\")
        pc += 1+n
    else:
        print(f\"{pc:04x}: {name}\")
        pc += 1
PY" in /tmp/codex-o1lrvfrs succeeded in 26ms:
038d: PUSH32 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0
03ae: PUSH1 0x40
03b0: MLOAD
03b1: PUSH1 0x40
03b3: MLOAD
03b4: DUP1
03b5: SWAP2
03b6: SUB
03b7: SWAP1
03b8: LOG3
03b9: PUSH1 0x00
03bb: DUP1
03bc: SLOAD
03bd: PUSH20 0xffffffffffffffffffffffffffffffffffffffff
03d2: NOT
03d3: AND
03d4: PUSH1 0x01
03d6: PUSH1 0xa0
03d8: PUSH1 0x02
03da: EXP

thinking
**Analyzing storage slots and function signatures**

I’m piecing together the contract’s storage layout and functions by interpreting opcodes and events; slot 0 is likely the owner, slot 2 a boolean flag or mapping for allowances. The contract seems like a token or escrow managing balances, transfers, and ownership—with 9 selectors that don’t fully match ERC20, hinting at a wallet-like setup. I’m zeroing in on certain functions checking slot2 flags and ownership before calls that send ETH, aiming to verify proper access control and guards against vulnerabilities. Next, I’ll dissect the code around 0x04c0 to clarify these behaviors.
exec
/bin/bash -lc "python - <<'PY'
import json
with open('BYTECODE_BUNDLE.json','r') as f:
    data=json.load(f)
code=bytes.fromhex(data['artifact']['runtime_bytecode']['full'][2:])

# disasm function with pc labels
opnames={i:f'OP_{i:02X}' for i in range(256)}
# name map (subset)
name_map={0x00:'STOP',0x01:'ADD',0x02:'MUL',0x03:'SUB',0x04:'DIV',0x05:'SDIV',0x06:'MOD',0x07:'SMOD',0x08:'ADDMOD',0x09:'MULMOD',0x0a:'EXP',0x0b:'SIGNEXTEND',
0x10:'LT',0x11:'GT',0x12:'SLT',0x13:'SGT',0x14:'EQ',0x15:'ISZERO',0x16:'AND',0x17:'OR',0x18:'XOR',0x19:'NOT',0x1a:'BYTE',0x1b:'SHL',0x1c:'SHR',0x1d:'SAR',
0x20:'SHA3',
0x30:'ADDRESS',0x31:'BALANCE',0x32:'ORIGIN',0x33:'CALLER',0x34:'CALLVALUE',0x35:'CALLDATALOAD',0x36:'CALLDATASIZE',0x37:'CALLDATACOPY',0x38:'CODESIZE',0x39:'CODECOPY',0x3a:'GASPRICE',0x3b:'EXTCODESIZE',0x3c:'EXTCODECOPY',0x3d:'RETURNDATASIZE',0x3e:'RETURNDATACOPY',0x3f:'EXTCODEHASH',
0x40:'BLOCKHASH',0x41:'COINBASE',0x42:'TIMESTAMP',0x43:'NUMBER',0x44:'DIFFICULTY',0x45:'GASLIMIT',0x46:'CHAINID',0x47:'SELFBALANCE',0x48:'BASEFEE',
0x50:'POP',0x51:'MLOAD',0x52:'MSTORE',0x53:'MSTORE8',0x54:'SLOAD',0x55:'SSTORE',0x56:'JUMP',0x57:'JUMPI',0x58:'PC',0x59:'MSIZE',0x5a:'GAS',0x5b:'JUMPDEST',
0x60:'PUSH1',0x61:'PUSH2',0x62:'PUSH3',0x63:'PUSH4',0x64:'PUSH5',0x65:'PUSH6',0x66:'PUSH7',0x67:'PUSH8',0x68:'PUSH9',0x69:'PUSH10',0x6a:'PUSH11',0x6b:'PUSH12',0x6c:'PUSH13',0x6d:'PUSH14',0x6e:'PUSH15',0x6f:'PUSH16',
0x70:'PUSH17',0x71:'PUSH18',0x72:'PUSH19',0x73:'PUSH20',0x74:'PUSH21',0x75:'PUSH22',0x76:'PUSH23',0x77:'PUSH24',0x78:'PUSH25',0x79:'PUSH26',0x7a:'PUSH27',0x7b:'PUSH28',0x7c:'PUSH29',0x7d:'PUSH30',0x7e:'PUSH31',0x7f:'PUSH32',
0x80:'DUP1',0x81:'DUP2',0x82:'DUP3',0x83:'DUP4',0x84:'DUP5',0x85:'DUP6',0x86:'DUP7',0x87:'DUP8',0x88:'DUP9',0x89:'DUP10',0x8a:'DUP11',0x8b:'DUP12',0x8c:'DUP13',0x8d:'DUP14',0x8e:'DUP15',0x8f:'DUP16',
0x90:'SWAP1',0x91:'SWAP2',0x92:'SWAP3',0x93:'SWAP4',0x94:'SWAP5',0x95:'SWAP6',0x96:'SWAP7',0x97:'SWAP8',0x98:'SWAP9',0x99:'SWAP10',0x9a:'SWAP11',0x9b:'SWAP12',0x9c:'SWAP13',0x9d:'SWAP14',0x9e:'SWAP15',0x9f:'SWAP16',
0xa0:'LOG0',0xa1:'LOG1',0xa2:'LOG2',0xa3:'LOG3',0xa4:'LOG4',
0xf0:'CREATE',0xf1:'CALL',0xf2:'CALLCODE',0xf3:'RETURN',0xf4:'DELEGATECALL',0xf5:'CREATE2',0xfa:'STATICCALL',0xfd:'REVERT',0xfe:'INVALID',0xff:'SELFDESTRUCT'}

opnames.update(name_map)

# disasm to list from 0x04c0 to 0x0600
pc=0x04c0
end=0x0605
while pc < end:
    op=code[pc]
    name=opnames.get(op,f'OP_{op:02X}')
    if 0x60 <= op <= 0x7f:
        n=op-0x5f
        data=code[pc+1:pc+1+n]
        print(f\"{pc:04x}: {name} 0x{data.hex()}\")
        pc += 1+n
    else:
        print(f\"{pc:04x}: {name}\")
        pc += 1
PY" in /tmp/codex-o1lrvfrs succeeded in 48ms:
04c0: JUMPDEST
04c1: PUSH1 0x00
04c3: SLOAD
04c4: CALLER
04c5: PUSH1 0x01
04c7: PUSH1 0xa0
04c9: PUSH1 0x02
04cb: EXP
04cc: SUB
04cd: SWAP1
04ce: DUP2
04cf: AND
04d0: SWAP2
04d1: AND
04d2: EQ
04d3: PUSH2 0x04db
04d6: JUMPI
04d7: PUSH1 0x00
04d9: DUP1
04da: REVERT

thinking
**Analyzing owner-only function with external calls**
exec
/bin/bash -lc "python - <<'PY'
import json
with open('BYTECODE_BUNDLE.json','r') as f:
    data=json.load(f)
code=bytes.fromhex(data['artifact']['runtime_bytecode']['full'][2:])

# disasm from 0x0600 to 0x0710
opnames={i:f'OP_{i:02X}' for i in range(256)}
# names subset
names={0x00:'STOP',0x01:'ADD',0x02:'MUL',0x03:'SUB',0x04:'DIV',0x05:'SDIV',0x06:'MOD',0x07:'SMOD',0x08:'ADDMOD',0x09:'MULMOD',0x0a:'EXP',0x0b:'SIGNEXTEND',
0x10:'LT',0x11:'GT',0x12:'SLT',0x13:'SGT',0x14:'EQ',0x15:'ISZERO',0x16:'AND',0x17:'OR',0x18:'XOR',0x19:'NOT',0x1a:'BYTE',0x1b:'SHL',0x1c:'SHR',0x1d:'SAR',
0x20:'SHA3',
0x30:'ADDRESS',0x31:'BALANCE',0x32:'ORIGIN',0x33:'CALLER',0x34:'CALLVALUE',0x35:'CALLDATALOAD',0x36:'CALLDATASIZE',0x37:'CALLDATACOPY',0x38:'CODESIZE',0x39:'CODECOPY',0x3a:'GASPRICE',0x3b:'EXTCODESIZE',0x3c:'EXTCODECOPY',0x3d:'RETURNDATASIZE',0x3e:'RETURNDATACOPY',0x3f:'EXTCODEHASH',
0x50:'POP',0x51:'MLOAD',0x52:'MSTORE',0x53:'MSTORE8',0x54:'SLOAD',0x55:'SSTORE',0x56:'JUMP',0x57:'JUMPI',0x58:'PC',0x59:'MSIZE',0x5a:'GAS',0x5b:'JUMPDEST',
0x60:'PUSH1',0x61:'PUSH2',0x62:'PUSH3',0x63:'PUSH4',0x64:'PUSH5',0x65:'PUSH6',0x66:'PUSH7',0x67:'PUSH8',0x68:'PUSH9',0x69:'PUSH10',0x6a:'PUSH11',0x6b:'PUSH12',0x6c:'PUSH13',0x6d:'PUSH14',0x6e:'PUSH15',0x6f:'PUSH16',
0x70:'PUSH17',0x71:'PUSH18',0x72:'PUSH19',0x73:'PUSH20',0x74:'PUSH21',0x75:'PUSH22',0x76:'PUSH23',0x77:'PUSH24',0x78:'PUSH25',0x79:'PUSH26',0x7a:'PUSH27',0x7b:'PUSH28',0x7c:'PUSH29',0x7d:'PUSH30',0x7e:'PUSH31',0x7f:'PUSH32',
0x80:'DUP1',0x81:'DUP2',0x82:'DUP3',0x83:'DUP4',0x84:'DUP5',0x85:'DUP6',0x86:'DUP7',0x87:'DUP8',0x88:'DUP9',0x89:'DUP10',0x8a:'DUP11',0x8b:'DUP12',0x8c:'DUP13',0x8d:'DUP14',0x8e:'DUP15',0x8f:'DUP16',
0x90:'SWAP1',0x91:'SWAP2',0x92:'SWAP3',0x93:'SWAP4',0x94:'SWAP5',0x95:'SWAP6',0x96:'SWAP7',0x97:'SWAP8',0x98:'SWAP9',0x99:'SWAP10',0x9a:'SWAP11',0x9b:'SWAP12',0x9c:'SWAP13',0x9d:'SWAP14',0x9e:'SWAP15',0x9f:'SWAP16',
0xa0:'LOG0',0xa1:'LOG1',0xa2:'LOG2',0xa3:'LOG3',0xa4:'LOG4',
0xf0:'CREATE',0xf1:'CALL',0xf2:'CALLCODE',0xf3:'RETURN',0xf4:'DELEGATECALL',0xf5:'CREATE2',0xfa:'STATICCALL',0xfd:'REVERT',0xfe:'INVALID',0xff:'SELFDESTRUCT'}

opnames.update(names)

pc=0x0600
end=0x0710
while pc < end:
    op=code[pc]
    name=opnames.get(op,f'OP_{op:02X}')
    if 0x60 <= op <= 0x7f:
        n=op-0x5f
        data=code[pc+1:pc+1+n]
        print(f\"{pc:04x}: {name} 0x{data.hex()}\")
        pc += 1+n
    else:
        print(f\"{pc:04x}: {name}\")
        pc += 1
PY" in /tmp/codex-o1lrvfrs exited 1 in 69ms:
0600: OP_40
0601: DUP1
0602: DUP4
0603: SHA3
0604: PUSH1 0x01
0606: PUSH1 0xa0
0608: PUSH1 0x02
060a: EXP
060b: SUB
060c: DUP6
060d: AND
060e: DUP5
060f: MSTORE
0610: SWAP1
0611: SWAP2
0612: MSTORE
0613: DUP2
0614: SHA3
0615: SLOAD
0616: SWAP1



thinking
**Analyzing bytecode for security risks**

I'm parsing bytecode to detect owner-controlled selfdestruct, owner-only arbitrary calls with ETH, and possible reentrancy; I see state updates before external calls which reduces reentrancy risk, but owner control of destructive and powerful functions poses centralization and security concerns.
thinking
**Exploring symbolic execution for call target analysis**

I’m planning a symbolic stack analysis from function entry to CALL instructions to trace if call targets and values depend on user inputs or storage, carefully handling jump logic and dependencies to clarify potential risks of untrusted external calls originating from owner and non-owner functions.
thinking
**Summarizing reentrancy and external call findings**

I’m organizing findings about calls after state updates without explicit reentrancy guards, owner-only external calls with ETH, user-accessible calls, and owner-controlled selfdestruct, preparing to produce a clear JSON report with severity, evidence, and recommendations.
exec
/bin/bash -lc "python - <<'PY'
import json
with open('BYTECODE_BUNDLE.json','r') as f:
    data=json.load(f)
code=bytes.fromhex(data['artifact']['runtime_bytecode']['full'][2:])

opnames={i:f'OP_{i:02X}' for i in range(256)}
# minimal names
names={0x5b:'JUMPDEST',0x56:'JUMP',0x57:'JUMPI',0x34:'CALLVALUE',0x15:'ISZERO',0x61:'PUSH2',0x60:'PUSH1',0x35:'CALLDATALOAD',0x16:'AND',0x54:'SLOAD',0x55:'SSTORE',0x33:'CALLER',0xf3:'RETURN',0xfd:'REVERT'}
opnames.update(names)

pc=0x018c
end=0x0208
while pc < end:
    op=code[pc]
    name=opnames.get(op,f'OP_{op:02X}')
    if 0x60 <= op <= 0x7f:
        n=op-0x5f
        data=code[pc+1:pc+1+n]
        print(f\"{pc:04x}: {name} 0x{data.hex()}\")
        pc += 1+n
    else:
        print(f\"{pc:04x}: {name}\")
        pc += 1
PY" in /tmp/codex-o1lrvfrs succeeded in 31ms:
018c: JUMPDEST
018d: CALLVALUE
018e: ISZERO
018f: PUSH2 0x0197
0192: JUMPI
0193: PUSH1 0x00
0195: OP_80
0196: REVERT
0197: JUMPDEST
0198: PUSH2 0x00bb
019b: PUSH1 0x01
019d: PUSH1 0xa0
019f: PUSH1 0x02
01a1: OP_0A
01a2: OP_03
01a3: PUSH1 0x04
01a5: CALLDATALOAD
01a6: AND
01a7: PUSH2 0x034c
01aa: JUMP

thinking
**Analyzing ownership-related functions**
exec
/bin/bash -lc "python - <<'PY'
import json
with open('BYTECODE_BUNDLE.json','r') as f:
    data=json.load(f)
code=bytes.fromhex(data['artifact']['runtime_bytecode']['full'][2:])

opnames={i:f'OP_{i:02X}' for i in range(256)}
# minimal names
names={0x00:'STOP',0x01:'ADD',0x02:'MUL',0x03:'SUB',0x04:'DIV',0x05:'SDIV',0x06:'MOD',0x07:'SMOD',0x08:'ADDMOD',0x09:'MULMOD',0x0a:'EXP',0x0b:'SIGNEXTEND',
0x10:'LT',0x11:'GT',0x12:'SLT',0x13:'SGT',0x14:'EQ',0x15:'ISZERO',0x16:'AND',0x17:'OR',0x18:'XOR',0x19:'NOT',0x1a:'BYTE',0x1b:'SHL',0x1c:'SHR',0x1d:'SAR',
0x20:'SHA3',
0x30:'ADDRESS',0x31:'BALANCE',0x32:'ORIGIN',0x33:'CALLER',0x34:'CALLVALUE',0x35:'CALLDATALOAD',0x36:'CALLDATASIZE',0x37:'CALLDATACOPY',0x38:'CODESIZE',0x39:'CODECOPY',0x3a:'GASPRICE',0x3b:'EXTCODESIZE',0x3c:'EXTCODECOPY',0x3d:'RETURNDATASIZE',0x3e:'RETURNDATACOPY',0x3f:'EXTCODEHASH',
0x50:'POP',0x51:'MLOAD',0x52:'MSTORE',0x53:'MSTORE8',0x54:'SLOAD',0x55:'SSTORE',0x56:'JUMP',0x57:'JUMPI',0x58:'PC',0x59:'MSIZE',0x5a:'GAS',0x5b:'JUMPDEST',
0x60:'PUSH1',0x61:'PUSH2',0x62:'PUSH3',0x63:'PUSH4',0x64:'PUSH5',0x65:'PUSH6',0x66:'PUSH7',0x67:'PUSH8',0x68:'PUSH9',0x69:'PUSH10',0x6a:'PUSH11',0x6b:'PUSH12',0x6c:'PUSH13',0x6d:'PUSH14',0x6e:'PUSH15',0x6f:'PUSH16',
0x70:'PUSH17',0x71:'PUSH18',0x72:'PUSH19',0x73:'PUSH20',0x74:'PUSH21',0x75:'PUSH22',0x76:'PUSH23',0x77:'PUSH24',0x78:'PUSH25',0x79:'PUSH26',0x7a:'PUSH27',0x7b:'PUSH28',0x7c:'PUSH29',0x7d:'PUSH30',0x7e:'PUSH31',0x7f:'PUSH32',
0x80:'DUP1',0x81:'DUP2',0x82:'DUP3',0x83:'DUP4',0x84:'DUP5',0x85:'DUP6',0x86:'DUP7',0x87:'DUP8',0x88:'DUP9',0x89:'DUP10',0x8a:'DUP11',0x8b:'DUP12',0x8c:'DUP13',0x8d:'DUP14',0x8e:'DUP15',0x8f:'DUP16',
0x90:'SWAP1',0x91:'SWAP2',0x92:'SWAP3',0x93:'SWAP4',0x94:'SWAP5',0x95:'SWAP6',0x96:'SWAP7',0x97:'SWAP8',0x98:'SWAP9',0x99:'SWAP10',0x9a:'SWAP11',0x9b:'SWAP12',0x9c:'SWAP13',0x9d:'SWAP14',0x9e:'SWAP15',0x9f:'SWAP16',
0xa0:'LOG0',0xa1:'LOG1',0xa2:'LOG2',0xa3:'LOG3',0xa4:'LOG4',
0xf0:'CREATE',0xf1:'CALL',0xf2:'CALLCODE',0xf3:'RETURN',0xf4:'DELEGATECALL',0xf5:'CREATE2',0xfa:'STATICCALL',0xfd:'REVERT',0xfe:'INVALID',0xff:'SELFDESTRUCT'}

opnames.update(names)

pc=0x03e7
end=0x04c0
while pc < end:
    op=code[pc]
    name=opnames.get(op,f'OP_{op:02X}')
    if 0x60 <= op <= 0x7f:
        n=op-0x5f
        data=code[pc+1:pc+1+n]
        print(f\"{pc:04x}: {name} 0x{data.hex()}\")
        pc += 1+n
    else:
        print(f\"{pc:04x}: {name}\")
        pc += 1
PY" in /tmp/codex-o1lrvfrs succeeded in 30ms:
03e7: JUMPDEST
03e8: PUSH1 0x00
03ea: SLOAD
03eb: CALLER
03ec: PUSH1 0x01
03ee: PUSH1 0xa0
03f0: PUSH1 0x02
03f2: EXP
03f3: SUB
03f4: SWAP1
03f5: DUP2
03f6: AND
03f7: SWAP2
03f8: AND
03f9: EQ
03fa: PUSH2 0x0402
03fd: JUMPI
03fe: PUSH1 0x00
0400: DUP1
0401: REVERT

thinking
**Analyzing owner and user external calls**
exec
/bin/bash -lc "python - <<'PY'
import json
with open('BYTECODE_BUNDLE.json','r') as f:
    data=json.load(f)
code=bytes.fromhex(data['artifact']['runtime_bytecode']['full'][2:])
# find push2 0x031c
for i in range(len(code)-2):
    if code[i]==0x61 and code[i+1]==0x03 and code[i+2]==0x1c:
        print(hex(i))
PY" in /tmp/codex-o1lrvfrs succeeded in 56ms:
0x151

thinking
**Analyzing bytecode for selector behavior**
exec
/bin/bash -lc "python - <<'PY'
import json
with open('BYTECODE_BUNDLE.json','r') as f:
    data=json.load(f)
code=bytes.fromhex(data['artifact']['runtime_bytecode']['full'][2:])

# disasm around 0x0136
pc=0x0136
end=0x0158
opnames={i:f'OP_{i:02X}' for i in range(256)}
# minimal names
names={0x5b:'JUMPDEST',0x34:'CALLVALUE',0x15:'ISZERO',0x61:'PUSH2',0x60:'PUSH1',0x57:'JUMPI',0xfd:'REVERT',0x56:'JUMP'}
opnames.update(names)

while pc<end:
    op=code[pc]
    name=opnames.get(op,f'OP_{op:02X}')
    if 0x60 <= op <= 0x7f:
        n=op-0x5f
        data=code[pc+1:pc+1+n]
        print(f\"{pc:04x}: {name} 0x{data.hex()}\")
        pc += 1+n
    else:
        print(f\"{pc:04x}: {name}\")
        pc += 1
PY" in /tmp/codex-o1lrvfrs succeeded in 28ms:
0136: JUMPDEST
0137: CALLVALUE
0138: ISZERO
0139: PUSH2 0x0141
013c: JUMPI
013d: PUSH1 0x00
013f: OP_80
0140: REVERT
0141: JUMPDEST
0142: PUSH2 0x00bb
0145: PUSH1 0x01
0147: PUSH1 0xa0
0149: PUSH1 0x02
014b: OP_0A
014c: OP_03
014d: PUSH1 0x04
014f: OP_35
0150: OP_16
0151: PUSH2 0x031c
0154: JUMP

thinking
**Summarizing function selectors and behavior**
codex
{"no_findings":false,"summary":"Bytecode shows an owner-controlled SELFDESTRUCT path and multiple low-level CALLs with ETH value to computed targets (some owner-gated, one apparently user-accessible with effects-before-interactions). No delegatecall/proxy patterns detected in the bundle.","findings":[{"severity":"medium","category":"other","title":"Owner-reachable SELFDESTRUCT can permanently disable the contract","exploit_scenario":"If the owner key is compromised or misused, the SELFDESTRUCT path can be invoked to destroy the contract and send the remaining ETH to an arbitrary address, permanently disabling all functionality for users.","recommendation":"Remove SELFDESTRUCT or gate it behind a timelock/multisig and/or an irreversible disable after deployment. If it is intended, document the risk clearly.","evidence":"A SELFDESTRUCT opcode is reachable after an owner check (SLOAD slot0 masked vs CALLER). The path is invoked via the selector that jumps to pc 0x031c and culminates in SELFDESTRUCT at pc 0x0342.","locations":["selector:0xb9caebf4","pc:0x031d","pc:0x0342"]},{"severity":"medium","category":"access_control","title":"Privileged low-level CALLs with ETH to computed targets (centralization risk)","exploit_scenario":"An owner can trigger low-level CALLs that transfer ETH to computed targets (including a path that uses the contract balance), allowing full fund extraction or arbitrary external interactions if the owner is compromised or malicious.","recommendation":"If arbitrary execution is not required, restrict call targets/amounts or remove these calls. Otherwise, use a multisig + timelock and document the admin powers. Consider adding explicit allowlists or rate limits.","evidence":"Owner check occurs at pc 0x04c0 before two CALL sites that use computed targets/values (pc 0x0575 and pc 0x05b2). The sequence includes ADDRESS/BALANCE, implying ETH transfers under privileged control.","locations":["selector:0xf5bf7413","pc:0x04c0","pc:0x0575","pc:0x05b2"]},{"severity":"low","category":"reentrancy","title":"User-accessible CALL with value has no explicit reentrancy guard","exploit_scenario":"A user-invoked function performs a low-level CALL with value to a computed target. Although storage is updated before the call (effects-before-interactions), a malicious callee could reenter other functions that rely on transient invariants.","recommendation":"If any cross-function invariants exist, add a reentrancy guard to this call path or ensure all state updates are completed before external interaction. Document the intended reentrancy model.","evidence":"CALL at pc 0x066b occurs after an SSTORE at pc 0x0653 in the function reached by selector 0xfa89401a; no mutex/guard pattern is visible in the bytecode.","locations":["selector:0xfa89401a","pc:0x0653","pc:0x066b"]}]}
tokens used
110,307
Metadata
{
    "codex": {
        "ran_at": "2026-01-10T21:20:20.825686+00:00",
        "returncode": 0
    },
    "project": {
        "mode": "bytecode",
        "bytecode_length": 3582,
        "bytecode_truncated": false,
        "capability_graph_present": true,
        "analysis_artifact_present": true
    },
    "summary": "Bytecode shows an owner-controlled SELFDESTRUCT path and multiple low-level CALLs with ETH value to computed targets (some owner-gated, one apparently user-accessible with effects-before-interactions). No delegatecall/proxy patterns detected in the bundle.",
    "raw_final": {
        "summary": "Bytecode shows an owner-controlled SELFDESTRUCT path and multiple low-level CALLs with ETH value to computed targets (some owner-gated, one apparently user-accessible with effects-before-interactions). No delegatecall/proxy patterns detected in the bundle.",
        "findings": [
            {
                "title": "Owner-reachable SELFDESTRUCT can permanently disable the contract",
                "category": "other",
                "evidence": "A SELFDESTRUCT opcode is reachable after an owner check (SLOAD slot0 masked vs CALLER). The path is invoked via the selector that jumps to pc 0x031c and culminates in SELFDESTRUCT at pc 0x0342.",
                "severity": "medium",
                "locations": [
                    "selector:0xb9caebf4",
                    "pc:0x031d",
                    "pc:0x0342"
                ],
                "recommendation": "Remove SELFDESTRUCT or gate it behind a timelock/multisig and/or an irreversible disable after deployment. If it is intended, document the risk clearly.",
                "exploit_scenario": "If the owner key is compromised or misused, the SELFDESTRUCT path can be invoked to destroy the contract and send the remaining ETH to an arbitrary address, permanently disabling all functionality for users."
            },
            {
                "title": "Privileged low-level CALLs with ETH to computed targets (centralization risk)",
                "category": "access_control",
                "evidence": "Owner check occurs at pc 0x04c0 before two CALL sites that use computed targets/values (pc 0x0575 and pc 0x05b2). The sequence includes ADDRESS/BALANCE, implying ETH transfers under privileged control.",
                "severity": "medium",
                "locations": [
                    "selector:0xf5bf7413",
                    "pc:0x04c0",
                    "pc:0x0575",
                    "pc:0x05b2"
                ],
                "recommendation": "If arbitrary execution is not required, restrict call targets/amounts or remove these calls. Otherwise, use a multisig + timelock and document the admin powers. Consider adding explicit allowlists or rate limits.",
                "exploit_scenario": "An owner can trigger low-level CALLs that transfer ETH to computed targets (including a path that uses the contract balance), allowing full fund extraction or arbitrary external interactions if the owner is compromised or malicious."
            },
            {
                "title": "User-accessible CALL with value has no explicit reentrancy guard",
                "category": "reentrancy",
                "evidence": "CALL at pc 0x066b occurs after an SSTORE at pc 0x0653 in the function reached by selector 0xfa89401a; no mutex/guard pattern is visible in the bytecode.",
                "severity": "low",
                "locations": [
                    "selector:0xfa89401a",
                    "pc:0x0653",
                    "pc:0x066b"
                ],
                "recommendation": "If any cross-function invariants exist, add a reentrancy guard to this call path or ensure all state updates are completed before external interaction. Document the intended reentrancy model.",
                "exploit_scenario": "A user-invoked function performs a low-level CALL with value to a computed target. Although storage is updated before the call (effects-before-interactions), a malicious callee could reenter other functions that rely on transient invariants."
            }
        ],
        "no_findings": false
    },
    "no_findings": false,
    "schema_version": 1
}

Opcode Heuristics

tool.cast_disasm
Delegatecall
0
Selfdestruct
1
CREATE2
0
CALL-family (heavy)
3
EXT*/BALANCE
2
Total opcodes
1120
Flags
selfdestruct_present
View cast disassembly output
00000000: PUSH1 0x60
00000002: PUSH1 0x40
00000004: MSTORE
00000005: PUSH1 0x04
00000007: CALLDATASIZE
00000008: LT
00000009: PUSH2 0x00a3
0000000c: JUMPI
0000000d: PUSH4 0xffffffff
00000012: PUSH29 0x0100000000000000000000000000000000000000000000000000000000
00000030: PUSH1 0x00
00000032: CALLDATALOAD
00000033: DIV
00000034: AND
00000035: PUSH4 0x1ef3755d
0000003a: DUP2
0000003b: EQ
0000003c: PUSH2 0x00a8
0000003f: JUMPI
00000040: DUP1
00000041: PUSH4 0x47fa061e
00000046: EQ
00000047: PUSH2 0x00bd
0000004a: JUMPI
0000004b: DUP1
0000004c: PUSH4 0x8c52dc41
00000051: EQ
00000052: PUSH2 0x00f4
00000055: JUMPI
00000056: DUP1
00000057: PUSH4 0x8da5cb5b
0000005c: EQ
0000005d: PUSH2 0x0107
00000060: JUMPI
00000061: DUP1
00000062: PUSH4 0xb9caebf4
00000067: EQ
00000068: PUSH2 0x0136
0000006b: JUMPI
0000006c: DUP1
0000006d: PUSH4 0xc19d93fb
00000072: EQ
00000073: PUSH2 0x0155
00000076: JUMPI
00000077: DUP1
00000078: PUSH4 0xf2fde38b
0000007d: EQ
0000007e: PUSH2 0x018c
00000081: JUMPI
00000082: DUP1
00000083: PUSH4 0xf340fa01
00000088: EQ
00000089: PUSH2 0x01ab
0000008c: JUMPI
0000008d: DUP1
0000008e: PUSH4 0xf5bf7413
00000093: EQ
00000094: PUSH2 0x01bf
00000097: JUMPI
00000098: DUP1
00000099: PUSH4 0xfa89401a
0000009e: EQ
0000009f: PUSH2 0x01e7
000000a2: JUMPI
000000a3: JUMPDEST
000000a4: PUSH1 0x00
000000a6: DUP1
000000a7: REVERT
000000a8: JUMPDEST
000000a9: CALLVALUE
000000aa: ISZERO
000000ab: PUSH2 0x00b3
000000ae: JUMPI
000000af: PUSH1 0x00
000000b1: DUP1
000000b2: REVERT
000000b3: JUMPDEST
000000b4: PUSH2 0x00bb
000000b7: PUSH2 0x0206
000000ba: JUMP
000000bb: JUMPDEST
000000bc: STOP
000000bd: JUMPDEST
000000be: CALLVALUE
000000bf: ISZERO
000000c0: PUSH2 0x00c8
000000c3: JUMPI
000000c4: PUSH1 0x00
000000c6: DUP1
000000c7: REVERT
000000c8: JUMPDEST
000000c9: PUSH2 0x00e2
000000cc: PUSH1 0xff
000000ce: PUSH1 0x04
000000d0: CALLDATALOAD
000000d1: AND
000000d2: PUSH1 0x01
000000d4: PUSH1 0xa0
000000d6: PUSH1 0x02
000000d8: EXP
000000d9: SUB
000000da: PUSH1 0x24
000000dc: CALLDATALOAD
000000dd: AND
000000de: PUSH2 0x027d
000000e1: JUMP
000000e2: JUMPDEST
000000e3: PUSH1 0x40
000000e5: MLOAD
000000e6: SWAP1
000000e7: DUP2
000000e8: MSTORE
000000e9: PUSH1 0x20
000000eb: ADD
000000ec: PUSH1 0x40
000000ee: MLOAD
000000ef: DUP1
000000f0: SWAP2
000000f1: SUB
000000f2: SWAP1
000000f3: RETURN
000000f4: JUMPDEST
000000f5: CALLVALUE
000000f6: ISZERO
000000f7: PUSH2 0x00ff
000000fa: JUMPI
000000fb: PUSH1 0x00
000000fd: DUP1
000000fe: REVERT
000000ff: JUMPDEST
00000100: PUSH2 0x00bb
00000103: PUSH2 0x029a
00000106: JUMP
00000107: JUMPDEST
00000108: CALLVALUE
00000109: ISZERO
0000010a: PUSH2 0x0112
0000010d: JUMPI
0000010e: PUSH1 0x00
00000110: DUP1
00000111: REVERT
00000112: JUMPDEST
00000113: PUSH2 0x011a
00000116: PUSH2 0x030d
00000119: JUMP
0000011a: JUMPDEST
0000011b: PUSH1 0x40
0000011d: MLOAD
0000011e: PUSH1 0x01
00000120: PUSH1 0xa0
00000122: PUSH1 0x02
00000124: EXP
00000125: SUB
00000126: SWAP1
00000127: SWAP2
00000128: AND
00000129: DUP2
0000012a: MSTORE
0000012b: PUSH1 0x20
0000012d: ADD
0000012e: PUSH1 0x40
00000130: MLOAD
00000131: DUP1
00000132: SWAP2
00000133: SUB
00000134: SWAP1
00000135: RETURN
00000136: JUMPDEST
00000137: CALLVALUE
00000138: ISZERO
00000139: PUSH2 0x0141
0000013c: JUMPI
0000013d: PUSH1 0x00
0000013f: DUP1
00000140: REVERT
00000141: JUMPDEST
00000142: PUSH2 0x00bb
00000145: PUSH1 0x01
00000147: PUSH1 0xa0
00000149: PUSH1 0x02
0000014b: EXP
0000014c: SUB
0000014d: PUSH1 0x04
0000014f: CALLDATALOAD
00000150: AND
00000151: PUSH2 0x031c
00000154: JUMP
00000155: JUMPDEST
00000156: CALLVALUE
00000157: ISZERO
00000158: PUSH2 0x0160
0000015b: JUMPI
0000015c: PUSH1 0x00
0000015e: DUP1
0000015f: REVERT
00000160: JUMPDEST
00000161: PUSH2 0x0168
00000164: PUSH2 0x0343
00000167: JUMP
00000168: JUMPDEST
00000169: PUSH1 0x40
0000016b: MLOAD
0000016c: DUP1
0000016d: DUP3
0000016e: PUSH1 0x02
00000170: DUP2
00000171: GT
00000172: ISZERO
00000173: PUSH2 0x0178
00000176: JUMPI
00000177: INVALID
00000178: JUMPDEST
00000179: PUSH1 0xff
0000017b: AND
0000017c: DUP2
0000017d: MSTORE
0000017e: PUSH1 0x20
00000180: ADD
00000181: SWAP2
00000182: POP
00000183: POP
00000184: PUSH1 0x40
00000186: MLOAD
00000187: DUP1
00000188: SWAP2
00000189: SUB
0000018a: SWAP1
0000018b: RETURN
0000018c: JUMPDEST
0000018d: CALLVALUE
0000018e: ISZERO
0000018f: PUSH2 0x0197
00000192: JUMPI
00000193: PUSH1 0x00
00000195: DUP1
00000196: REVERT
00000197: JUMPDEST
00000198: PUSH2 0x00bb
0000019b: PUSH1 0x01
0000019d: PUSH1 0xa0
0000019f: PUSH1 0x02
000001a1: EXP
000001a2: SUB
000001a3: PUSH1 0x04
000001a5: CALLDATALOAD
000001a6: AND
000001a7: PUSH2 0x034c
000001aa: JUMP
000001ab: JUMPDEST
000001ac: PUSH2 0x00bb
000001af: PUSH1 0x01
000001b1: PUSH1 0xa0
000001b3: PUSH1 0x02
000001b5: EXP
000001b6: SUB
000001b7: PUSH1 0x04
000001b9: CALLDATALOAD
000001ba: AND
000001bb: PUSH2 0x03e7
000001be: JUMP
000001bf: JUMPDEST
000001c0: CALLVALUE
000001c1: ISZERO
000001c2: PUSH2 0x01ca
000001c5: JUMPI
000001c6: PUSH1 0x00
000001c8: DUP1
000001c9: REVERT
000001ca: JUMPDEST
000001cb: PUSH2 0x00bb
000001ce: PUSH1 0x01
000001d0: PUSH1 0xa0
000001d2: PUSH1 0x02
000001d4: EXP
000001d5: SUB
000001d6: PUSH1 0x04
000001d8: CALLDATALOAD
000001d9: DUP2
000001da: AND
000001db: SWAP1
000001dc: PUSH1 0x24
000001de: CALLDATALOAD
000001df: AND
000001e0: PUSH1 0x44
000001e2: CALLDATALOAD
000001e3: PUSH2 0x04c0
000001e6: JUMP
000001e7: JUMPDEST
000001e8: CALLVALUE
000001e9: ISZERO
000001ea: PUSH2 0x01f2
000001ed: JUMPI
000001ee: PUSH1 0x00
000001f0: DUP1
000001f1: REVERT
000001f2: JUMPDEST
000001f3: PUSH2 0x00bb
000001f6: PUSH1 0x01
000001f8: PUSH1 0xa0
000001fa: PUSH1 0x02
000001fc: EXP
000001fd: SUB
000001fe: PUSH1 0x04
00000200: CALLDATALOAD
00000201: AND
00000202: PUSH2 0x05c7
00000205: JUMP
00000206: JUMPDEST
00000207: PUSH1 0x00
00000209: SLOAD
0000020a: CALLER
0000020b: PUSH1 0x01
0000020d: PUSH1 0xa0
0000020f: PUSH1 0x02
00000211: EXP
00000212: SUB
00000213: SWAP1
00000214: DUP2
00000215: AND
00000216: SWAP2
00000217: AND
00000218: EQ
00000219: PUSH2 0x0221
0000021c: JUMPI
0000021d: PUSH1 0x00
0000021f: DUP1
00000220: REVERT
00000221: JUMPDEST
00000222: PUSH1 0x02
00000224: DUP1
00000225: SLOAD
00000226: PUSH1 0xff
00000228: AND
00000229: DUP2
0000022a: DUP2
0000022b: GT
0000022c: ISZERO
0000022d: PUSH2 0x0232
00000230: JUMPI
00000231: INVALID
00000232: JUMPDEST
00000233: EQ
00000234: PUSH2 0x023c
00000237: JUMPI
00000238: PUSH1 0x00
0000023a: DUP1
0000023b: REVERT
0000023c: JUMPDEST
0000023d: PUSH1 0x00
0000023f: DUP1
00000240: SLOAD
00000241: PUSH21 0xff0000000000000000000000000000000000000000
00000257: NOT
00000258: DUP2
00000259: AND
0000025a: PUSH1 0xa0
0000025c: PUSH1 0x02
0000025e: EXP
0000025f: SWAP2
00000260: DUP3
00000261: SWAP1
00000262: DIV
00000263: PUSH1 0xff
00000265: SWAP1
00000266: DUP2
00000267: AND
00000268: PUSH1 0x01
0000026a: ADD
0000026b: AND
0000026c: SWAP1
0000026d: SWAP2
0000026e: MUL
0000026f: OR
00000270: SWAP1
00000271: SSTORE
00000272: PUSH1 0x02
00000274: DUP1
00000275: SLOAD
00000276: PUSH1 0xff
00000278: NOT
00000279: AND
0000027a: SWAP1
0000027b: SSTORE
0000027c: JUMP
0000027d: JUMPDEST
0000027e: PUSH1 0x01
00000280: PUSH1 0x20
00000282: SWAP1
00000283: DUP2
00000284: MSTORE
00000285: PUSH1 0x00
00000287: SWAP3
00000288: DUP4
00000289: MSTORE
0000028a: PUSH1 0x40
0000028c: DUP1
0000028d: DUP5
0000028e: KECCAK256
0000028f: SWAP1
00000290: SWAP2
00000291: MSTORE
00000292: SWAP1
00000293: DUP3
00000294: MSTORE
00000295: SWAP1
00000296: KECCAK256
00000297: SLOAD
00000298: DUP2
00000299: JUMP
0000029a: JUMPDEST
0000029b: PUSH1 0x00
0000029d: SLOAD
0000029e: CALLER
0000029f: PUSH1 0x01
000002a1: PUSH1 0xa0
000002a3: PUSH1 0x02
000002a5: EXP
000002a6: SUB
000002a7: SWAP1
000002a8: DUP2
000002a9: AND
000002aa: SWAP2
000002ab: AND
000002ac: EQ
000002ad: PUSH2 0x02b5
000002b0: JUMPI
000002b1: PUSH1 0x00
000002b3: DUP1
000002b4: REVERT
000002b5: JUMPDEST
000002b6: PUSH1 0x00
000002b8: PUSH1 0x02
000002ba: DUP1
000002bb: SLOAD
000002bc: PUSH1 0xff
000002be: AND
000002bf: SWAP1
000002c0: DUP2
000002c1: GT
000002c2: ISZERO
000002c3: PUSH2 0x02c8
000002c6: JUMPI
000002c7: INVALID
000002c8: JUMPDEST
000002c9: EQ
000002ca: PUSH2 0x02d2
000002cd: JUMPI
000002ce: PUSH1 0x00
000002d0: DUP1
000002d1: REVERT
000002d2: JUMPDEST
000002d3: PUSH1 0x02
000002d5: DUP1
000002d6: SLOAD
000002d7: PUSH1 0xff
000002d9: NOT
000002da: AND
000002db: PUSH1 0x01
000002dd: OR
000002de: SWAP1
000002df: SSTORE
000002e0: PUSH32 0x599d8e5a83cffb867d051598c4d70e805d59802d8081c1c7d6dffc5b6aca2b89
00000301: PUSH1 0x40
00000303: MLOAD
00000304: PUSH1 0x40
00000306: MLOAD
00000307: DUP1
00000308: SWAP2
00000309: SUB
0000030a: SWAP1
0000030b: LOG1
0000030c: JUMP
0000030d: JUMPDEST
0000030e: PUSH1 0x00
00000310: SLOAD
00000311: PUSH1 0x01
00000313: PUSH1 0xa0
00000315: PUSH1 0x02
00000317: EXP
00000318: SUB
00000319: AND
0000031a: DUP2
0000031b: JUMP
0000031c: JUMPDEST
0000031d: PUSH1 0x00
0000031f: SLOAD
00000320: CALLER
00000321: PUSH1 0x01
00000323: PUSH1 0xa0
00000325: PUSH1 0x02
00000327: EXP
00000328: SUB
00000329: SWAP1
0000032a: DUP2
0000032b: AND
0000032c: SWAP2
0000032d: AND
0000032e: EQ
0000032f: PUSH2 0x0337
00000332: JUMPI
00000333: PUSH1 0x00
00000335: DUP1
00000336: REVERT
00000337: JUMPDEST
00000338: DUP1
00000339: PUSH1 0x01
0000033b: PUSH1 0xa0
0000033d: PUSH1 0x02
0000033f: EXP
00000340: SUB
00000341: AND
00000342: SELFDESTRUCT
00000343: JUMPDEST
00000344: PUSH1 0x02
00000346: SLOAD
00000347: PUSH1 0xff
00000349: AND
0000034a: DUP2
0000034b: JUMP
0000034c: JUMPDEST
0000034d: PUSH1 0x00
0000034f: SLOAD
00000350: CALLER
00000351: PUSH1 0x01
00000353: PUSH1 0xa0
00000355: PUSH1 0x02
00000357: EXP
00000358: SUB
00000359: SWAP1
0000035a: DUP2
0000035b: AND
0000035c: SWAP2
0000035d: AND
0000035e: EQ
0000035f: PUSH2 0x0367
00000362: JUMPI
00000363: PUSH1 0x00
00000365: DUP1
00000366: REVERT
00000367: JUMPDEST
00000368: PUSH1 0x01
0000036a: PUSH1 0xa0
0000036c: PUSH1 0x02
0000036e: EXP
0000036f: SUB
00000370: DUP2
00000371: AND
00000372: ISZERO
00000373: ISZERO
00000374: PUSH2 0x037c
00000377: JUMPI
00000378: PUSH1 0x00
0000037a: DUP1
0000037b: REVERT
0000037c: JUMPDEST
0000037d: PUSH1 0x00
0000037f: SLOAD
00000380: PUSH1 0x01
00000382: PUSH1 0xa0
00000384: PUSH1 0x02
00000386: EXP
00000387: SUB
00000388: DUP1
00000389: DUP4
0000038a: AND
0000038b: SWAP2
0000038c: AND
0000038d: PUSH32 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0
000003ae: PUSH1 0x40
000003b0: MLOAD
000003b1: PUSH1 0x40
000003b3: MLOAD
000003b4: DUP1
000003b5: SWAP2
000003b6: SUB
000003b7: SWAP1
000003b8: LOG3
000003b9: PUSH1 0x00
000003bb: DUP1
000003bc: SLOAD
000003bd: PUSH20 0xffffffffffffffffffffffffffffffffffffffff
000003d2: NOT
000003d3: AND
000003d4: PUSH1 0x01
000003d6: PUSH1 0xa0
000003d8: PUSH1 0x02
000003da: EXP
000003db: SUB
000003dc: SWAP3
000003dd: SWAP1
000003de: SWAP3
000003df: AND
000003e0: SWAP2
000003e1: SWAP1
000003e2: SWAP2
000003e3: OR
000003e4: SWAP1
000003e5: SSTORE
000003e6: JUMP
000003e7: JUMPDEST
000003e8: PUSH1 0x00
000003ea: SLOAD
000003eb: CALLER
000003ec: PUSH1 0x01
000003ee: PUSH1 0xa0
000003f0: PUSH1 0x02
000003f2: EXP
000003f3: SUB
000003f4: SWAP1
000003f5: DUP2
000003f6: AND
000003f7: SWAP2
000003f8: AND
000003f9: EQ
000003fa: PUSH2 0x0402
000003fd: JUMPI
000003fe: PUSH1 0x00
00000400: DUP1
00000401: REVERT
00000402: JUMPDEST
00000403: PUSH1 0x00
00000405: PUSH1 0x02
00000407: DUP1
00000408: SLOAD
00000409: PUSH1 0xff
0000040b: AND
0000040c: SWAP1
0000040d: DUP2
0000040e: GT
0000040f: ISZERO
00000410: PUSH2 0x0415
00000413: JUMPI
00000414: INVALID
00000415: JUMPDEST
00000416: EQ
00000417: PUSH2 0x041f
0000041a: JUMPI
0000041b: PUSH1 0x00
0000041d: DUP1
0000041e: REVERT
0000041f: JUMPDEST
00000420: PUSH1 0x00
00000422: DUP1
00000423: SLOAD
00000424: PUSH1 0xa0
00000426: PUSH1 0x02
00000428: EXP
00000429: SWAP1
0000042a: DIV
0000042b: PUSH1 0xff
0000042d: AND
0000042e: DUP2
0000042f: MSTORE
00000430: PUSH1 0x01
00000432: PUSH1 0x20
00000434: SWAP1
00000435: DUP2
00000436: MSTORE
00000437: PUSH1 0x40
00000439: DUP1
0000043a: DUP4
0000043b: KECCAK256
0000043c: PUSH1 0x01
0000043e: PUSH1 0xa0
00000440: PUSH1 0x02
00000442: EXP
00000443: SUB
00000444: DUP6
00000445: AND
00000446: DUP5
00000447: MSTORE
00000448: SWAP1
00000449: SWAP2
0000044a: MSTORE
0000044b: SWAP1
0000044c: KECCAK256
0000044d: SLOAD
0000044e: PUSH2 0x0457
00000451: SWAP1
00000452: CALLVALUE
00000453: PUSH2 0x06bc
00000456: JUMP
00000457: JUMPDEST
00000458: PUSH1 0x00
0000045a: DUP1
0000045b: SLOAD
0000045c: PUSH1 0xa0
0000045e: PUSH1 0x02
00000460: EXP
00000461: SWAP1
00000462: DIV
00000463: PUSH1 0xff
00000465: AND
00000466: DUP2
00000467: MSTORE
00000468: PUSH1 0x01
0000046a: PUSH1 0x20
0000046c: SWAP1
0000046d: DUP2
0000046e: MSTORE
0000046f: PUSH1 0x40
00000471: DUP1
00000472: DUP4
00000473: KECCAK256
00000474: PUSH1 0x01
00000476: PUSH1 0xa0
00000478: PUSH1 0x02
0000047a: EXP
0000047b: SUB
0000047c: DUP7
0000047d: AND
0000047e: DUP1
0000047f: DUP6
00000480: MSTORE
00000481: SWAP3
00000482: MSTORE
00000483: SWAP2
00000484: DUP3
00000485: SWAP1
00000486: KECCAK256
00000487: SWAP3
00000488: SWAP1
00000489: SWAP3
0000048a: SSTORE
0000048b: PUSH32 0x2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c4
000004ac: SWAP1
000004ad: CALLVALUE
000004ae: SWAP1
000004af: MLOAD
000004b0: SWAP1
000004b1: DUP2
000004b2: MSTORE
000004b3: PUSH1 0x20
000004b5: ADD
000004b6: PUSH1 0x40
000004b8: MLOAD
000004b9: DUP1
000004ba: SWAP2
000004bb: SUB
000004bc: SWAP1
000004bd: LOG2
000004be: POP
000004bf: JUMP
000004c0: JUMPDEST
000004c1: PUSH1 0x00
000004c3: SLOAD
000004c4: CALLER
000004c5: PUSH1 0x01
000004c7: PUSH1 0xa0
000004c9: PUSH1 0x02
000004cb: EXP
000004cc: SUB
000004cd: SWAP1
000004ce: DUP2
000004cf: AND
000004d0: SWAP2
000004d1: AND
000004d2: EQ
000004d3: PUSH2 0x04db
000004d6: JUMPI
000004d7: PUSH1 0x00
000004d9: DUP1
000004da: REVERT
000004db: JUMPDEST
000004dc: PUSH1 0x00
000004de: PUSH1 0x02
000004e0: DUP1
000004e1: SLOAD
000004e2: PUSH1 0xff
000004e4: AND
000004e5: SWAP1
000004e6: DUP2
000004e7: GT
000004e8: ISZERO
000004e9: PUSH2 0x04ee
000004ec: JUMPI
000004ed: INVALID
000004ee: JUMPDEST
000004ef: EQ
000004f0: PUSH2 0x04f8
000004f3: JUMPI
000004f4: PUSH1 0x00
000004f6: DUP1
000004f7: REVERT
000004f8: JUMPDEST
000004f9: PUSH1 0x01
000004fb: PUSH1 0xa0
000004fd: PUSH1 0x02
000004ff: EXP
00000500: SUB
00000501: DUP4
00000502: AND
00000503: ISZERO
00000504: ISZERO
00000505: PUSH2 0x050d
00000508: JUMPI
00000509: PUSH1 0x00
0000050b: DUP1
0000050c: REVERT
0000050d: JUMPDEST
0000050e: PUSH1 0x02
00000510: DUP1
00000511: SLOAD
00000512: PUSH1 0xff
00000514: NOT
00000515: AND
00000516: DUP2
00000517: OR
00000518: SWAP1
00000519: SSTORE
0000051a: PUSH32 0x1cdde67b72a90f19919ac732a437ac2f7a10fc128d28c2a6e525d89ce5cd9d3a
0000053b: PUSH1 0x40
0000053d: MLOAD
0000053e: PUSH1 0x40
00000540: MLOAD
00000541: DUP1
00000542: SWAP2
00000543: SUB
00000544: SWAP1
00000545: LOG1
00000546: PUSH1 0x01
00000548: PUSH1 0xa0
0000054a: PUSH1 0x02
0000054c: EXP
0000054d: SUB
0000054e: DUP3
0000054f: AND
00000550: ISZERO
00000551: PUSH2 0x0585
00000554: JUMPI
00000555: PUSH1 0x01
00000557: PUSH1 0xa0
00000559: PUSH1 0x02
0000055b: EXP
0000055c: SUB
0000055d: DUP3
0000055e: AND
0000055f: DUP2
00000560: ISZERO
00000561: PUSH2 0x08fc
00000564: MUL
00000565: DUP3
00000566: PUSH1 0x40
00000568: MLOAD
00000569: PUSH1 0x00
0000056b: PUSH1 0x40
0000056d: MLOAD
0000056e: DUP1
0000056f: DUP4
00000570: SUB
00000571: DUP2
00000572: DUP6
00000573: DUP9
00000574: DUP9
00000575: CALL
00000576: SWAP4
00000577: POP
00000578: POP
00000579: POP
0000057a: POP
0000057b: ISZERO
0000057c: ISZERO
0000057d: PUSH2 0x0585
00000580: JUMPI
00000581: PUSH1 0x00
00000583: DUP1
00000584: REVERT
00000585: JUMPDEST
00000586: DUP3
00000587: PUSH1 0x01
00000589: PUSH1 0xa0
0000058b: PUSH1 0x02
0000058d: EXP
0000058e: SUB
0000058f: AND
00000590: PUSH2 0x08fc
00000593: ADDRESS
00000594: PUSH1 0x01
00000596: PUSH1 0xa0
00000598: PUSH1 0x02
0000059a: EXP
0000059b: SUB
0000059c: AND
0000059d: BALANCE
0000059e: SWAP1
0000059f: DUP2
000005a0: ISZERO
000005a1: MUL
000005a2: SWAP1
000005a3: PUSH1 0x40
000005a5: MLOAD
000005a6: PUSH1 0x00
000005a8: PUSH1 0x40
000005aa: MLOAD
000005ab: DUP1
000005ac: DUP4
000005ad: SUB
000005ae: DUP2
000005af: DUP6
000005b0: DUP9
000005b1: DUP9
000005b2: CALL
000005b3: SWAP4
000005b4: POP
000005b5: POP
000005b6: POP
000005b7: POP
000005b8: ISZERO
000005b9: ISZERO
000005ba: PUSH2 0x05c2
000005bd: JUMPI
000005be: PUSH1 0x00
000005c0: DUP1
000005c1: REVERT
000005c2: JUMPDEST
000005c3: POP
000005c4: POP
000005c5: POP
000005c6: JUMP
000005c7: JUMPDEST
000005c8: PUSH1 0x00
000005ca: PUSH1 0x01
000005cc: PUSH1 0x02
000005ce: DUP1
000005cf: SLOAD
000005d0: PUSH1 0xff
000005d2: AND
000005d3: SWAP1
000005d4: DUP2
000005d5: GT
000005d6: ISZERO
000005d7: PUSH2 0x05dc
000005da: JUMPI
000005db: INVALID
000005dc: JUMPDEST
000005dd: EQ
000005de: PUSH2 0x05e6
000005e1: JUMPI
000005e2: PUSH1 0x00
000005e4: DUP1
000005e5: REVERT
000005e6: JUMPDEST
000005e7: POP
000005e8: PUSH1 0x00
000005ea: DUP1
000005eb: SLOAD
000005ec: PUSH1 0xa0
000005ee: PUSH1 0x02
000005f0: EXP
000005f1: SWAP1
000005f2: DIV
000005f3: PUSH1 0xff
000005f5: AND
000005f6: DUP2
000005f7: MSTORE
000005f8: PUSH1 0x01
000005fa: PUSH1 0x20
000005fc: SWAP1
000005fd: DUP2
000005fe: MSTORE
000005ff: PUSH1 0x40
00000601: DUP1
00000602: DUP4
00000603: KECCAK256
00000604: PUSH1 0x01
00000606: PUSH1 0xa0
00000608: PUSH1 0x02
0000060a: EXP
0000060b: SUB
0000060c: DUP6
0000060d: AND
0000060e: DUP5
0000060f: MSTORE
00000610: SWAP1
00000611: SWAP2
00000612: MSTORE
00000613: DUP2
00000614: KECCAK256
00000615: SLOAD
00000616: SWAP1
00000617: DUP2
00000618: GT
00000619: PUSH2 0x0621
0000061c: JUMPI
0000061d: PUSH1 0x00
0000061f: DUP1
00000620: REVERT
00000621: JUMPDEST
00000622: PUSH1 0x00
00000624: DUP1
00000625: SLOAD
00000626: PUSH1 0xa0
00000628: PUSH1 0x02
0000062a: EXP
0000062b: SWAP1
0000062c: DIV
0000062d: PUSH1 0xff
0000062f: AND
00000630: DUP2
00000631: MSTORE
00000632: PUSH1 0x01
00000634: PUSH1 0x20
00000636: SWAP1
00000637: DUP2
00000638: MSTORE
00000639: PUSH1 0x40
0000063b: DUP1
0000063c: DUP4
0000063d: KECCAK256
0000063e: PUSH1 0x01
00000640: PUSH1 0xa0
00000642: PUSH1 0x02
00000644: EXP
00000645: SUB
00000646: DUP7
00000647: AND
00000648: DUP1
00000649: DUP6
0000064a: MSTORE
0000064b: SWAP3
0000064c: MSTORE
0000064d: DUP1
0000064e: DUP4
0000064f: KECCAK256
00000650: SWAP3
00000651: SWAP1
00000652: SWAP3
00000653: SSTORE
00000654: SWAP1
00000655: PUSH2 0x08fc
00000658: DUP4
00000659: ISZERO
0000065a: MUL
0000065b: SWAP1
0000065c: DUP4
0000065d: SWAP1
0000065e: MLOAD
0000065f: PUSH1 0x00
00000661: PUSH1 0x40
00000663: MLOAD
00000664: DUP1
00000665: DUP4
00000666: SUB
00000667: DUP2
00000668: DUP6
00000669: DUP9
0000066a: DUP9
0000066b: CALL
0000066c: SWAP4
0000066d: POP
0000066e: POP
0000066f: POP
00000670: POP
00000671: ISZERO
00000672: ISZERO
00000673: PUSH2 0x067b
00000676: JUMPI
00000677: PUSH1 0x00
00000679: DUP1
0000067a: REVERT
0000067b: JUMPDEST
0000067c: DUP2
0000067d: PUSH1 0x01
0000067f: PUSH1 0xa0
00000681: PUSH1 0x02
00000683: EXP
00000684: SUB
00000685: AND
00000686: PUSH32 0xd7dee2702d63ad89917b6a4da9981c90c4d24f8c2bdfd64c604ecae57d8d0651
000006a7: DUP3
000006a8: PUSH1 0x40
000006aa: MLOAD
000006ab: SWAP1
000006ac: DUP2
000006ad: MSTORE
000006ae: PUSH1 0x20
000006b0: ADD
000006b1: PUSH1 0x40
000006b3: MLOAD
000006b4: DUP1
000006b5: SWAP2
000006b6: SUB
000006b7: SWAP1
000006b8: LOG2
000006b9: POP
000006ba: POP
000006bb: JUMP
000006bc: JUMPDEST
000006bd: PUSH1 0x00
000006bf: DUP3
000006c0: DUP3
000006c1: ADD
000006c2: DUP4
000006c3: DUP2
000006c4: LT
000006c5: ISZERO
000006c6: PUSH2 0x06cb
000006c9: JUMPI
000006ca: INVALID
000006cb: JUMPDEST
000006cc: SWAP4
000006cd: SWAP3
000006ce: POP
000006cf: POP
000006d0: POP
000006d1: JUMP
000006d2: STOP
000006d3: LOG1
000006d4: PUSH6 0x627a7a723058
000006db: KECCAK256
000006dc: SWAP8
000006dd: UNKNOWN(0xEA)
000006de: UNKNOWN(0xE3)
000006df: CALLDATASIZE
000006e0: SWAP3
000006e1: JUMPDEST
000006e2: EXTCODEHASH
000006e3: GASLIMIT
000006e4: UNKNOWN(0xC5)
000006e5: PUSH25

Findings

validated = confirmed for call sinks; sink observed for others
Severity Category Tool Title Confidence Validated Confirmed Details
high other detector SELFDESTRUCT reachable 65 no no
view
trace_id: 0x5c63b2513c60522bb708762e5916bd2aaa84ccfc488e89b4aafa6acef0a3849f
validation_json
{
    "sink": "SELFDESTRUCT",
    "errors": 0,
    "status": "unknown",
    "attempts": 20,
    "trace_id": "0x5c63b2513c60522bb708762e5916bd2aaa84ccfc488e89b4aafa6acef0a3849f",
    "confirmed": false,
    "trace_mode": "structLogs",
    "call_targets": null,
    "matched_probe": null,
    "target_varies": null,
    "classification": "no_sink"
}
witness_json
{
    "notes": "heuristic witness; entrypoints are best-effort selectors with zeroed calldata",
    "constraints": [],
    "entrypoints": [
        {
            "calldata": "0x1ef3755d",
            "selector": "0x1ef3755d",
            "calldata_variants": [
                "0x1ef3755d",
                "0x1ef3755d0000000000000000000000000000000000000000000000000000000000000000"
            ]
        },
        {
            "calldata": "0x47fa061e",
            "selector": "0x47fa061e",
            "calldata_variants": [
                "0x47fa061e",
                "0x47fa061e0000000000000000000000000000000000000000000000000000000000000000"
            ]
        },
        {
            "calldata": "0x8c52dc41",
            "selector": "0x8c52dc41",
            "calldata_variants": [
                "0x8c52dc41",
                "0x8c52dc410000000000000000000000000000000000000000000000000000000000000000"
            ]
        },
        {
            "calldata": "0x8da5cb5b",
            "selector": "0x8da5cb5b",
            "calldata_variants": [
                "0x8da5cb5b",
                "0x8da5cb5b0000000000000000000000000000000000000000000000000000000000000000"
            ]
        },
        {
            "calldata": "0xb9caebf4",
            "selector": "0xb9caebf4",
            "calldata_variants": [
                "0xb9caebf4",
                "0xb9caebf40000000000000000000000000000000000000000000000000000000000000000"
            ]
        },
        {
            "calldata": "0xc19d93fb",
            "selector": "0xc19d93fb",
            "calldata_variants": [
                "0xc19d93fb",
                "0xc19d93fb0000000000000000000000000000000000000000000000000000000000000000"
            ]
        },
        {
            "calldata": "0xf2fde38b",
            "selector": "0xf2fde38b",
            "calldata_variants": [
                "0xf2fde38b",
                "0xf2fde38b0000000000000000000000000000000000000000000000000000000000000000"
            ]
        },
        {
            "calldata": "0xf340fa01",
            "selector": "0xf340fa01",
            "calldata_variants": [
                "0xf340fa01",
                "0xf340fa010000000000000000000000000000000000000000000000000000000000000000"
            ]
        }
    ]
}
evidence_json
{
    "guards_detected": [],
    "selfdestruct_count": 1
}
high other detector Untrusted CALL target/value reachable 60 no no
view
trace_id: 0xe8c70c7f02887cd01e67e3c7fadf191c1bd544f41ebf335f243c1a3c7e66bcbf
call_targets: 0xd32c59bdf5409842c0dec13a546a3916b7485694
target_varies: no
classification: constant_target
validation_json
{
    "sink": "CALL",
    "errors": 0,
    "status": "sink_reached",
    "attempts": 1,
    "trace_id": "0xe8c70c7f02887cd01e67e3c7fadf191c1bd544f41ebf335f243c1a3c7e66bcbf",
    "confirmed": false,
    "trace_mode": "callTracer",
    "call_targets": [
        "0xd32c59bdf5409842c0dec13a546a3916b7485694"
    ],
    "matched_probe": null,
    "target_varies": false,
    "classification": "constant_target"
}
witness_json
{
    "notes": "heuristic witness; entrypoints are best-effort selectors with zeroed calldata",
    "constraints": [],
    "entrypoints": [
        {
            "calldata": "0x1ef3755d",
            "selector": "0x1ef3755d",
            "calldata_variants": [
                "0x1ef3755d",
                "0x1ef3755d0000000000000000000000000000000000000000000000000000000000000000"
            ]
        },
        {
            "calldata": "0x47fa061e",
            "selector": "0x47fa061e",
            "calldata_variants": [
                "0x47fa061e",
                "0x47fa061e0000000000000000000000000000000000000000000000000000000000000000"
            ]
        },
        {
            "calldata": "0x8c52dc41",
            "selector": "0x8c52dc41",
            "calldata_variants": [
                "0x8c52dc41",
                "0x8c52dc410000000000000000000000000000000000000000000000000000000000000000"
            ]
        },
        {
            "calldata": "0x8da5cb5b",
            "selector": "0x8da5cb5b",
            "calldata_variants": [
                "0x8da5cb5b",
                "0x8da5cb5b0000000000000000000000000000000000000000000000000000000000000000"
            ]
        },
        {
            "calldata": "0xb9caebf4",
            "selector": "0xb9caebf4",
            "calldata_variants": [
                "0xb9caebf4",
                "0xb9caebf40000000000000000000000000000000000000000000000000000000000000000"
            ]
        },
        {
            "calldata": "0xc19d93fb",
            "selector": "0xc19d93fb",
            "calldata_variants": [
                "0xc19d93fb",
                "0xc19d93fb0000000000000000000000000000000000000000000000000000000000000000"
            ]
        },
        {
            "calldata": "0xf2fde38b",
            "selector": "0xf2fde38b",
            "calldata_variants": [
                "0xf2fde38b",
                "0xf2fde38b0000000000000000000000000000000000000000000000000000000000000000"
            ]
        },
        {
            "calldata": "0xf340fa01",
            "selector": "0xf340fa01",
            "calldata_variants": [
                "0xf340fa01",
                "0xf340fa010000000000000000000000000000000000000000000000000000000000000000"
            ]
        }
    ]
}
evidence_json
{
    "examples": [
        {
            "pc": 1397,
            "opcode": "CALL",
            "returndata_checked": null,
            "value_expression_category": "computed",
            "target_expression_category": "computed"
        },
        {
            "pc": 1458,
            "opcode": "CALL",
            "returndata_checked": null,
            "value_expression_category": "computed",
            "target_expression_category": "computed"
        },
        {
            "pc": 1643,
            "opcode": "CALL",
            "returndata_checked": null,
            "value_expression_category": "computed",
            "target_expression_category": "computed"
        }
    ],
    "call_count": 3,
    "guards_detected": [],
    "untrusted_call_count": 3
}
high other detector ETH value transfer possible 55 no no
view
trace_id: 0xe8c70c7f02887cd01e67e3c7fadf191c1bd544f41ebf335f243c1a3c7e66bcbf
call_targets: 0xd32c59bdf5409842c0dec13a546a3916b7485694
target_varies: no
classification: constant_target
validation_json
{
    "sink": "CALL",
    "errors": 0,
    "status": "sink_reached",
    "attempts": 1,
    "trace_id": "0xe8c70c7f02887cd01e67e3c7fadf191c1bd544f41ebf335f243c1a3c7e66bcbf",
    "confirmed": false,
    "trace_mode": "callTracer",
    "call_targets": [
        "0xd32c59bdf5409842c0dec13a546a3916b7485694"
    ],
    "matched_probe": null,
    "target_varies": false,
    "classification": "constant_target"
}
witness_json
{
    "notes": "heuristic witness; entrypoints are best-effort selectors with zeroed calldata",
    "constraints": [],
    "entrypoints": [
        {
            "calldata": "0x1ef3755d",
            "selector": "0x1ef3755d",
            "calldata_variants": [
                "0x1ef3755d",
                "0x1ef3755d0000000000000000000000000000000000000000000000000000000000000000"
            ]
        },
        {
            "calldata": "0x47fa061e",
            "selector": "0x47fa061e",
            "calldata_variants": [
                "0x47fa061e",
                "0x47fa061e0000000000000000000000000000000000000000000000000000000000000000"
            ]
        },
        {
            "calldata": "0x8c52dc41",
            "selector": "0x8c52dc41",
            "calldata_variants": [
                "0x8c52dc41",
                "0x8c52dc410000000000000000000000000000000000000000000000000000000000000000"
            ]
        },
        {
            "calldata": "0x8da5cb5b",
            "selector": "0x8da5cb5b",
            "calldata_variants": [
                "0x8da5cb5b",
                "0x8da5cb5b0000000000000000000000000000000000000000000000000000000000000000"
            ]
        },
        {
            "calldata": "0xb9caebf4",
            "selector": "0xb9caebf4",
            "calldata_variants": [
                "0xb9caebf4",
                "0xb9caebf40000000000000000000000000000000000000000000000000000000000000000"
            ]
        },
        {
            "calldata": "0xc19d93fb",
            "selector": "0xc19d93fb",
            "calldata_variants": [
                "0xc19d93fb",
                "0xc19d93fb0000000000000000000000000000000000000000000000000000000000000000"
            ]
        },
        {
            "calldata": "0xf2fde38b",
            "selector": "0xf2fde38b",
            "calldata_variants": [
                "0xf2fde38b",
                "0xf2fde38b0000000000000000000000000000000000000000000000000000000000000000"
            ]
        },
        {
            "calldata": "0xf340fa01",
            "selector": "0xf340fa01",
            "calldata_variants": [
                "0xf340fa01",
                "0xf340fa010000000000000000000000000000000000000000000000000000000000000000"
            ]
        }
    ]
}
evidence_json
{
    "examples": [
        {
            "pc": 1397,
            "opcode": "CALL",
            "returndata_checked": null,
            "value_expression_category": "computed",
            "target_expression_category": "computed"
        },
        {
            "pc": 1458,
            "opcode": "CALL",
            "returndata_checked": null,
            "value_expression_category": "computed",
            "target_expression_category": "computed"
        },
        {
            "pc": 1643,
            "opcode": "CALL",
            "returndata_checked": null,
            "value_expression_category": "computed",
            "target_expression_category": "computed"
        }
    ],
    "eth_value_calls": 3,
    "guards_detected": []
}
high other cast SELFDESTRUCT present 85 no
view
evidence_json
{
    "notes": "selfdestruct can remove contract code and send funds; review reachability",
    "selfdestruct_count": 1
}
medium other codex Owner-reachable SELFDESTRUCT can permanently disable the contract 75 no
view
evidence_json
{
    "evidence": "A SELFDESTRUCT opcode is reachable after an owner check (SLOAD slot0 masked vs CALLER). The path is invoked via the selector that jumps to pc 0x031c and culminates in SELFDESTRUCT at pc 0x0342.",
    "locations": [
        "selector:0xb9caebf4",
        "pc:0x031d",
        "pc:0x0342"
    ],
    "recommendation": "Remove SELFDESTRUCT or gate it behind a timelock/multisig and/or an irreversible disable after deployment. If it is intended, document the risk clearly.",
    "exploit_scenario": "If the owner key is compromised or misused, the SELFDESTRUCT path can be invoked to destroy the contract and send the remaining ETH to an arbitrary address, permanently disabling all functionality for users."
}
medium access_control codex Privileged low-level CALLs with ETH to computed targets (centralization risk) 75 no
view
evidence_json
{
    "evidence": "Owner check occurs at pc 0x04c0 before two CALL sites that use computed targets/values (pc 0x0575 and pc 0x05b2). The sequence includes ADDRESS/BALANCE, implying ETH transfers under privileged control.",
    "locations": [
        "selector:0xf5bf7413",
        "pc:0x04c0",
        "pc:0x0575",
        "pc:0x05b2"
    ],
    "recommendation": "If arbitrary execution is not required, restrict call targets/amounts or remove these calls. Otherwise, use a multisig + timelock and document the admin powers. Consider adding explicit allowlists or rate limits.",
    "exploit_scenario": "An owner can trigger low-level CALLs that transfer ETH to computed targets (including a path that uses the contract balance), allowing full fund extraction or arbitrary external interactions if the owner is compromised or malicious."
}
low reentrancy codex User-accessible CALL with value has no explicit reentrancy guard 65 no
view
evidence_json
{
    "evidence": "CALL at pc 0x066b occurs after an SSTORE at pc 0x0653 in the function reached by selector 0xfa89401a; no mutex/guard pattern is visible in the bytecode.",
    "locations": [
        "selector:0xfa89401a",
        "pc:0x0653",
        "pc:0x066b"
    ],
    "recommendation": "If any cross-function invariants exist, add a reentrancy guard to this call path or ensure all state updates are completed before external interaction. Document the intended reentrancy model.",
    "exploit_scenario": "A user-invoked function performs a low-level CALL with value to a computed target. Although storage is updated before the call (effects-before-interactions), a malicious callee could reenter other functions that rely on transient invariants."
}