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

Analysis Run

f3e7c777-190e-4408-a4ce-7e7b7bb1ab2c

complete
Chain ID
1
Address
Block Number
Created
Mon, Jan 5, 2026 9:59 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
Unprotected initializer allows attacker to set recipient and sweep ERC20 balances
crit 0 high 0 proxy context implementation known
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
31787 report.consolidate complete 1 / 1 3 months ago
96145 artifact.fetch complete 1 / 3 1 week ago
96146 tool.cast_disasm complete 1 / 3 1 week ago
96147 analysis.bundle complete 1 / 3 1 week ago
96148 capability.graph complete 1 / 3 1 week ago
96149 detector.run complete 1 / 3 1 week ago
96150 validation.fork complete 1 / 3 1 week ago

Artifact

Runtime bytecode: available
Creation TX:
Deployer:
Proxy: yes
Verified Source: no

Slither

tool.slither

No slither job recorded yet.

Codex

report.consolidate
Job Status
complete
Attempts
1 / 1
Findings
1
No findings?
no
Summary
Unprotected initializer lets the first caller set the payout recipient (slot 0x33) and then use the public token-sweep function to transfer any ERC20 balance to themselves if the contract is still uninitialized.
View stderr
[codex:546722] OpenAI Codex v0.77.0 (research preview)
[codex:546722] --------
[codex:546722] workdir: /tmp/codex-multi-8tm6gnag
[codex:546722] model: gpt-5.2-codex
[codex:546722] provider: openai
[codex:546722] approval: never
[codex:546722] sandbox: read-only
[codex:546722] reasoning effort: xhigh
[codex:546722] reasoning summaries: auto
[codex:546722] session id: 019b9024-6903-7ef2-a923-2309759783a5
[codex:546722] --------
[codex:546722] user
[codex:546722] You are a profit-focused exploit hunter analyzing EVM bytecode. Your ONLY goal is finding ways to extract value (ETH, tokens, NFTs) from this contract.
[codex:546722] 
[codex:546722] Read `BYTECODE_BUNDLE.txt` completely before concluding.
[codex:546722] 
[codex:546722] ONLY REPORT if you find a CONCRETE, EXPLOITABLE path to profit. We do NOT care about:
[codex:546722] - Gas inefficiency, code quality, or best practices
[codex:546722] - Theoretical vulnerabilities without a clear extraction path
[codex:546722] - Generic footguns (unchecked return values, etc.) unless they enable theft
[codex:546722] - Issues requiring social engineering or off-chain coordination
[codex:546722] 
[codex:546722] PATTERNS WORTH INVESTIGATING in bytecode:
[codex:546722] - CALL/DELEGATECALL with controllable destination or calldata
[codex:546722] - Value transfers (CALL with non-zero value) without prior CALLER/ORIGIN checks
[codex:546722] - SSTORE to low slots (0-10) that might be owner/admin storage
[codex:546722] - ecrecover (signature validation) - look for missing nonce/replay protection
[codex:546722] - External calls before state updates (reentrancy)
[codex:546722] - SELFDESTRUCT with controllable beneficiary
[codex:546722] - Proxy patterns (DELEGATECALL to storage slot) with unprotected upgrade paths
[codex:546722] 
[codex:546722] For each finding, you MUST explain:
[codex:546722] 1. The specific bytecode pattern/offsets that indicate the vulnerability
[codex:546722] 2. The concrete sequence of transactions to extract value
[codex:546722] 3. Why you believe this is exploitable (not just suspicious)
[codex:546722] 
[codex:546722] If you cannot identify a concrete profit path from bytecode alone: set no_findings=true.
[codex:546722] Do NOT hallucinate. Bytecode-only analysis is limited - be honest about uncertainty.
[codex:546722] 
[codex:546722] Output MUST be valid JSON matching the provided schema.
[codex:546722] - severity: info, low, medium, high, critical (use high/critical ONLY for clear extraction paths)
[codex:546722] - category: access_control, reentrancy, math, oracle, upgradeability, auth, other
[codex:546722] mcp startup: no servers
[codex:546722] 
[codex:546722] thinking
[codex:546722] **Reading bytecode file**
[codex:546722] exec
[codex:546722] /bin/bash -lc ls in /tmp/codex-multi-8tm6gnag succeeded in 5ms:
[codex:546722] BYTECODE_BUNDLE.txt
[codex:546722] codex-output-schema.json
[codex:546722] exec
[codex:546722] /bin/bash -lc 'cat BYTECODE_BUNDLE.txt' in /tmp/codex-multi-8tm6gnag succeeded in 5ms:
[codex:546722] Runtime bytecode bundle for best-effort auditing.
[codex:546722] Note: without verified source, conclusions are low-confidence unless a concrete pattern is visible.
[codex:546722] 
[codex:546722] FILE: runtime_bytecode.hex
[codex:546722] 0x60806040526004361061003f5760003560e01c80633ef13367146100f557806399e7d0561461012a578063c4d66de81461015b578063ca3254691461018e575b6033546040516001600160a01b03909116903480156108fc02916000818181858888f19350505050158015610078573d6000803e3d6000fd5b507f69b31548dea9b3b707b4dff357d326e3e9348b24e7a6080a218a6edeeec48f9b333460003660405180856001600160a01b03168152602001848152602001806020018281038252848482818152602001925080828437600083820152604051601f909101601f191690920182900397509095505050505050a1005b34801561010157600080fd5b506101286004803603602081101561011857600080fd5b50356001600160a01b03166101a3565b005b34801561013657600080fd5b5061013f6102b9565b604080516001600160a01b039092168252519081900360200190f35b34801561016757600080fd5b506101286004803603602081101561017e57600080fd5b50356001600160a01b03166102c8565b34801561019a57600080fd5b5061013f610386565b604080516370a0823160e01b8152306004820152905182916000916001600160a01b038416916370a08231916024808301926020929190829003018186803b1580156101ee57600080fd5b505afa158015610202573d6000803e3d6000fd5b505050506040513d602081101561021857600080fd5b50519050806102285750506102b6565b6033546040805163a9059cbb60e01b81526001600160a01b0392831660048201526024810184905290519184169163a9059cbb916044808201926020929091908290030181600087803b15801561027e57600080fd5b505af1158015610292573d6000803e3d6000fd5b505050506040513d60208110156102a857600080fd5b50516102b357600080fd5b50505b50565b6034546001600160a01b031681565b600054610100900460ff16806102e157506102e1610395565b806102ef575060005460ff16155b61032a5760405162461bcd60e51b815260040180806020018281038252602e81526020018061039c602e913960400191505060405180910390fd5b600054610100900460ff16158015610355576000805460ff1961ff0019909116610100171660011790555b603380546001600160a01b0319166001600160a01b0384161790558015610382576000805461ff00191690555b5050565b6033546001600160a01b031681565b303b159056fe436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564a2646970667358221220746b2b9a4e8b8fe1a0b26dd2df9a668323992ff2162fe13f14ce9985937a191a64736f6c634300060c0033
[codex:546722] 
[codex:546722] thinking
[codex:546722] **Analyzing EVM bytecode and fallback logic**
[codex:546722] 
[codex:546722] I'm starting to decode this EVM runtime bytecode to understand its functions and fallback behavior. The contract has four known function selectors and a fallback that likely performs a value transfer or delegate call using a storage slot. To interpret the suspicious fallback code, I'll manually disassemble key opcode sequences and may write a quick Python script to aid decoding since network tools aren't allowed. This will help identify potential exploit patterns like reentrancy or unauthorized ETH transfers.
[codex:546722] exec
[codex:546722] /bin/bash -lc "python3 - <<'PY'
[codex:546722] from eth_utils import decode_hex
[codex:546722] import sys, textwrap
[codex:546722] code=open('BYTECODE_BUNDLE.txt').read().split('0x',1)[1].split()[0]
[codex:546722] # first token after 0x is hex? We'll parse until newline maybe includes other text. We'll filter hex chars.
[codex:546722] import re
[codex:546722] m=re.search(r'0x([0-9a-fA-F]+)', open('BYTECODE_BUNDLE.txt').read())
[codex:546722] code=m.group(1)
[codex:546722] # remove any non-hex? but only hex.
[codex:546722] bytecode=bytes.fromhex(code)
[codex:546722] 
[codex:546722] # opcode table
[codex:546722] opcodes={
[codex:546722] 0x00:'STOP',0x01:'ADD',0x02:'MUL',0x03:'SUB',0x04:'DIV',0x05:'SDIV',0x06:'MOD',0x07:'SMOD',0x08:'ADDMOD',0x09:'MULMOD',0x0a:'EXP',0x0b:'SIGNEXTEND',
[codex:546722] 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',
[codex:546722] 0x20:'SHA3',
[codex:546722] 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',
[codex:546722] 0x40:'BLOCKHASH',0x41:'COINBASE',0x42:'TIMESTAMP',0x43:'NUMBER',0x44:'DIFFICULTY',0x45:'GASLIMIT',0x46:'CHAINID',0x47:'SELFBALANCE',0x48:'BASEFEE',
[codex:546722] 0x50:'POP',0x51:'MLOAD',0x52:'MSTORE',0x53:'MSTORE8',0x54:'SLOAD',0x55:'SSTORE',0x56:'JUMP',0x57:'JUMPI',0x58:'PC',0x59:'MSIZE',0x5a:'GAS',0x5b:'JUMPDEST',
[codex:546722] 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',
[codex:546722] 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',
[codex:546722] 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',
[codex:546722] 0xa0:'LOG0',0xa1:'LOG1',0xa2:'LOG2',0xa3:'LOG3',0xa4:'LOG4',
[codex:546722] 0xf0:'CREATE',0xf1:'CALL',0xf2:'CALLCODE',0xf3:'RETURN',0xf4:'DELEGATECALL',0xf5:'CREATE2',0xfa:'STATICCALL',0xfd:'REVERT',0xfe:'INVALID',0xff:'SELFDESTRUCT'
[codex:546722] }
[codex:546722] 
[codex:546722] pc=0
[codex:546722] out=[]
[codex:546722] while pc < len(bytecode):
[codex:546722]     op=bytecode[pc]
[codex:546722]     name=opcodes.get(op, f'UNKNOWN_{op:02x}')
[codex:546722]     if 0x60 <= op <= 0x7f:
[codex:546722]         n=op-0x5f
[codex:546722]         data=bytecode[pc+1:pc+1+n]
[codex:546722]         out.append((pc, f'{name} 0x{data.hex()}'))
[codex:546722]         pc+=1+n
[codex:546722]     else:
[codex:546722]         out.append((pc, name))
[codex:546722]         pc+=1
[codex:546722] 
[codex:546722] for pc, ins in out:
[codex:546722]     print(f'{pc:04x}: {ins}')
[codex:546722] PY" in /tmp/codex-multi-8tm6gnag succeeded in 217ms:
[codex:546722] 0000: PUSH1 0x80
[codex:546722] 0002: PUSH1 0x40
[codex:546722] 0004: MSTORE
[codex:546722] 0005: PUSH1 0x04
[codex:546722] 0007: CALLDATASIZE
[codex:546722] 0008: LT
[codex:546722] 0009: PUSH2 0x003f
[codex:546722] 000c: JUMPI
[codex:546722] 000d: PUSH1 0x00
[codex:546722] 000f: CALLDATALOAD
[codex:546722] 0010: PUSH1 0xe0
[codex:546722] 0012: SHR
[codex:546722] 0013: DUP1
[codex:546722] 0014: PUSH4 0x3ef13367
[codex:546722] 0019: EQ
[codex:546722] 001a: PUSH2 0x00f5
[codex:546722] 001d: JUMPI
[codex:546722] 001e: DUP1
[codex:546722] 001f: PUSH4 0x99e7d056
[codex:546722] 0024: EQ
[codex:546722] 
[codex:546722] thinking
[codex:546722] **Analyzing EVM fallback function and selectors**
[codex:546722] exec
[codex:546722] /bin/bash -lc "python3 - <<'PY'
[codex:546722] from collections import deque
[codex:546722] 
[codex:546722] # We'll simulate stack for fallback portion until CALL (pc 0x0062)
[codex:546722] ops = [
[codex:546722] ('PUSH1','0x33'),('SLOAD',),('PUSH1','0x40'),('MLOAD',),('PUSH1','0x01'),('PUSH1','0x01'),('PUSH1','0xa0'),('SHL',),('SUB',),('SWAP1',),('SWAP2',),('AND',),('SWAP1',),('CALLVALUE',),('DUP1',),('ISZERO',),('PUSH2','0x08fc'),('MUL',),('SWAP2',),('PUSH1','0x00'),('DUP2',),('DUP2',),('DUP2',),('DUP6',),('DUP9',),('DUP9',),('CALL',)
[codex:546722] ]
[codex:546722] 
[codex:546722] stack=[]
[codex:546722] 
[codex:546722] # helper to push symbolic
[codex:546722] counter=0
[codex:546722] 
[codex:546722] for op in ops:
[codex:546722]     name=op[0]
[codex:546722]     if name.startswith('PUSH'):
[codex:546722]         val=op[1]
[codex:546722]         stack.append(val)
[codex:546722]     elif name=='SLOAD':
[codex:546722]         v=stack.pop(); stack.append(f'SLOAD({v})')
[codex:546722]     elif name=='MLOAD':
[codex:546722]         v=stack.pop(); stack.append(f'MLOAD({v})')
[codex:546722]     elif name=='SHL':
[codex:546722]         shift=stack.pop(); val=stack.pop(); stack.append(f'SHL({val},{shift})')
[codex:546722]     elif name=='SUB':
[codex:546722]         a=stack.pop(); b=stack.pop(); stack.append(f'({a}-{b})')
[codex:546722]     elif name=='AND':
[codex:546722]         a=stack.pop(); b=stack.pop(); stack.append(f'({a}&{b})')
[codex:546722]     elif name=='SWAP1':
[codex:546722]         stack[-1], stack[-2] = stack[-2], stack[-1]
[codex:546722]     elif name=='SWAP2':
[codex:546722]         stack[-1], stack[-3] = stack[-3], stack[-1]
[codex:546722]     elif name=='CALLVALUE':
[codex:546722]         stack.append('CALLVALUE')
[codex:546722]     elif name=='DUP1':
[codex:546722]         stack.append(stack[-1])
[codex:546722]     elif name=='ISZERO':
[codex:546722]         v=stack.pop(); stack.append(f'ISZERO({v})')
[codex:546722]     elif name=='MUL':
[codex:546722]         a=stack.pop(); b=stack.pop(); stack.append(f'({a}*{b})')
[codex:546722]     elif name=='DUP2':
[codex:546722]         stack.append(stack[-2])
[codex:546722]     elif name=='DUP6':
[codex:546722]         stack.append(stack[-6])
[codex:546722]     elif name=='DUP9':
[codex:546722]         stack.append(stack[-9])
[codex:546722]     elif name=='CALL':
[codex:546722]         # stack before CALL: top is gas, then to, value, in_offset, in_size, out_offset, out_size
[codex:546722]         print('Stack before CALL (top last):')
[codex:546722]         for i, item in enumerate(reversed(stack),1):
[codex:546722]             print(i, item)
[codex:546722]         # pop 7
[codex:546722]         args=[stack.pop() for _ in range(7)]
[codex:546722]         stack.append('CALL('+', '.join(args)+')')
[codex:546722]     else:
[codex:546722]         raise SystemExit(name)
[codex:546722] 
[codex:546722] print('Final stack:', stack)
[codex:546722] PY" in /tmp/codex-multi-8tm6gnag succeeded in 23ms:
[codex:546722] Stack before CALL (top last):
[codex:546722] 1 (0x08fc*ISZERO(CALLVALUE))
[codex:546722] 2 (SLOAD(0x33)&(SHL(0x01,0xa0)-0x01))
[codex:546722] 3 CALLVALUE
[codex:546722] 4 MLOAD(0x40)
[codex:546722] 5 0x00
[codex:546722] 6 MLOAD(0x40)
[codex:546722] 7 0x00
[codex:546722] 8 MLOAD(0x40)
[codex:546722] 9 CALLVALUE
[codex:546722] 10 (0x08fc*ISZERO(CALLVALUE))
[codex:546722] 11 (SLOAD(0x33)&(SHL(0x01,0xa0)-0x01))
[codex:546722] Final stack: ['(SLOAD(0x33)&(SHL(0x01,0xa0)-0x01))', '(0x08fc*ISZERO(CALLVALUE))', 'CALLVALUE', 'MLOAD(0x40)', 'CALL((0x08fc*ISZERO(CALLVALUE)), (SLOAD(0x33)&(SHL(0x01,0xa0)-0x01)), CALLVALUE, MLOAD(0x40), 0x00, MLOAD(0x40), 0x00)']
[codex:546722] 
[codex:546722] thinking
[codex:546722] **Analyzing EVM CALL and function at 0x01a3**
[codex:546722] exec
[codex:546722] /bin/bash -lc "python3 - <<'PY'
[codex:546722] # Symbolic trace from 0x01a3 to 0x02b8
[codex:546722] import re
[codex:546722] 
[codex:546722] # parse bytecode and disassemble to list with pc and op
[codex:546722] code=open('BYTECODE_BUNDLE.txt').read();
[codex:546722] import re
[codex:546722] m=re.search(r'0x([0-9a-fA-F]+)', code)
[codex:546722] bytecode=bytes.fromhex(m.group(1))
[codex:546722] 
[codex:546722] opcodes={
[codex:546722] 0x00:'STOP',0x01:'ADD',0x02:'MUL',0x03:'SUB',0x04:'DIV',0x05:'SDIV',0x06:'MOD',0x07:'SMOD',0x08:'ADDMOD',0x09:'MULMOD',0x0a:'EXP',0x0b:'SIGNEXTEND',
[codex:546722] 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',
[codex:546722] 0x20:'SHA3',
[codex:546722] 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',
[codex:546722] 0x40:'BLOCKHASH',0x41:'COINBASE',0x42:'TIMESTAMP',0x43:'NUMBER',0x44:'DIFFICULTY',0x45:'GASLIMIT',0x46:'CHAINID',0x47:'SELFBALANCE',0x48:'BASEFEE',
[codex:546722] 0x50:'POP',0x51:'MLOAD',0x52:'MSTORE',0x53:'MSTORE8',0x54:'SLOAD',0x55:'SSTORE',0x56:'JUMP',0x57:'JUMPI',0x58:'PC',0x59:'MSIZE',0x5a:'GAS',0x5b:'JUMPDEST',
[codex:546722] 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',
[codex:546722] 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',
[codex:546722] 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',
[codex:546722] 0xa0:'LOG0',0xa1:'LOG1',0xa2:'LOG2',0xa3:'LOG3',0xa4:'LOG4',
[codex:546722] 0xf0:'CREATE',0xf1:'CALL',0xf2:'CALLCODE',0xf3:'RETURN',0xf4:'DELEGATECALL',0xf5:'CREATE2',0xfa:'STATICCALL',0xfd:'REVERT',0xfe:'INVALID',0xff:'SELFDESTRUCT'
[codex:546722] }
[codex:546722] 
[codex:546722] # disassemble to map pc->(op, imm)
[codex:546722] ops=[]
[codex:546722] pc=0
[codex:546722] while pc < len(bytecode):
[codex:546722]     op=bytecode[pc]
[codex:546722]     name=opcodes.get(op, f'UNK_{op:02x}')
[codex:546722]     if 0x60 <= op <= 0x7f:
[codex:546722]         n=op-0x5f
[codex:546722]         data=bytecode[pc+1:pc+1+n]
[codex:546722]         ops.append((pc,name,int.from_bytes(data,'big')))
[codex:546722]         pc+=1+n
[codex:546722]     else:
[codex:546722]         ops.append((pc,name,None))
[codex:546722]         pc+=1
[codex:546722] 
[codex:546722] ops_dict={pc:(name,imm) for pc,name,imm in ops}
[codex:546722] 
[codex:546722] start=0x01a3
[codex:546722] end=0x02b8
[codex:546722] 
[codex:546722] stack=['ret','arg']
[codex:546722] 
[codex:546722] def push(val):
[codex:546722]     stack.append(val)
[codex:546722] 
[codex:546722] def pop():
[codex:546722]     return stack.pop()
[codex:546722] 
[codex:546722] pc=start
[codex:546722] visited=set()
[codex:546722] 
[codex:546722] # We'll just linear step until end; ignoring jumps (except JUMPI maybe). We'll log at key points.
[codex:546722] 
[codex:546722] while pc <= end:
[codex:546722]     name,imm=ops_dict[pc]
[codex:546722]     # print each op? limit
[codex:546722]     if name.startswith('PUSH'):
[codex:546722]         push(hex(imm))
[codex:546722]     elif name.startswith('DUP'):
[codex:546722]         n=int(name[3:])
[codex:546722]         push(stack[-n])
[codex:546722]     elif name.startswith('SWAP'):
[codex:546722]         n=int(name[4:])
[codex:546722]         stack[-1], stack[-1-n] = stack[-1-n], stack[-1]
[codex:546722]     elif name=='POP':
[codex:546722]         pop()
[codex:546722]     elif name=='MLOAD':
[codex:546722]         a=pop(); push(f'MLOAD({a})')
[codex:546722]     elif name=='MSTORE':
[codex:546722]         a=pop(); b=pop(); push(f'store({b},{a})')
[codex:546722]     elif name=='CALLDATALOAD':
[codex:546722]         a=pop(); push(f'CALLDATALOAD({a})')
[codex:546722]     elif name=='AND':
[codex:546722]         a=pop(); b=pop(); push(f'({a}&{b})')
[codex:546722]     elif name=='OR':
[codex:546722]         a=pop(); b=pop(); push(f'({a}|{b})')
[codex:546722]     elif name=='SUB':
[codex:546722]         a=pop(); b=pop(); push(f'({a}-{b})')
[codex:546722]     elif name=='ADD':
[codex:546722]         a=pop(); b=pop(); push(f'({a}+{b})')
[codex:546722]     elif name=='SHL':
[codex:546722]         a=pop(); b=pop(); push(f'SHL({b},{a})')
[codex:546722]     elif name=='SHR':
[codex:546722]         a=pop(); b=pop(); push(f'SHR({b},{a})')
[codex:546722]     elif name=='ISZERO':
[codex:546722]         a=pop(); push(f'ISZERO({a})')
[codex:546722]     elif name=='EXTCODESIZE':
[codex:546722]         a=pop(); push(f'EXTCODESIZE({a})')
[codex:546722]     elif name=='STATICCALL':
[codex:546722]         # pop 6? Actually STATICCALL takes 6 args: gas, to, in_offset, in_size, out_offset, out_size
[codex:546722]         args=[pop() for _ in range(6)]
[codex:546722]         push(f'STATICCALL({args})')
[codex:546722]     elif name=='CALL':
[codex:546722]         args=[pop() for _ in range(7)]
[codex:546722]         push(f'CALL({args})')
[codex:546722]     elif name=='RETURNDATASIZE':
[codex:546722]         push('RETURNDATASIZE')
[codex:546722]     elif name=='RETURNDATACOPY':
[codex:546722]         a=pop(); b=pop(); c=pop(); push(f'RETURNDATACOPY({c},{b},{a})')
[codex:546722]     elif name=='GAS':
[codex:546722]         push('GAS')
[codex:546722]     elif name=='ADDRESS':
[codex:546722]         push('ADDRESS')
[codex:546722]     elif name=='JUMPI':
[codex:546722]         # not executing branch; just note
[codex:546722]         a=pop(); b=pop(); push(f'JUMPI({b},{a})')
[codex:546722]     elif name=='JUMP':
[codex:546722]         a=pop(); push(f'JUMP({a})')
[codex:546722]     elif name=='REVERT':
[codex:546722]         a=pop(); b=pop(); push(f'REVERT({b},{a})')
[codex:546722]     elif name=='RETURN':
[codex:546722]         a=pop(); b=pop(); push(f'RETURN({b},{a})')
[codex:546722]     elif name=='EQ':
[codex:546722]         a=pop(); b=pop(); push(f'EQ({b},{a})')
[codex:546722]     elif name=='LT':
[codex:546722]         a=pop(); b=pop(); push(f'LT({b},{a})')
[codex:546722]     elif name=='GT':
[codex:546722]         a=pop(); b=pop(); push(f'GT({b},{a})')
[codex:546722]     else:
[codex:546722]         # for other ops just push representation
[codex:546722]         pass
[codex:546722] 
[codex:546722]     if pc in [0x01a3,0x01ee,0x0202,0x0228,0x027e,0x0292,0x02b6,0x02b8]:
[codex:546722]         print(f'pc {pc:04x} {name}: stack size {len(stack)} top {stack[-3:]}')
[codex:546722]     pc = ops[ [i for i,(p,_,_) in enumerate(ops) if p==pc][0] + 1 ][0] if pc"'!=end else end+1
[codex:546722] 
[codex:546722] print('"'final stack', stack[-10:])
[codex:546722] PY" in /tmp/codex-multi-8tm6gnag succeeded in 36ms:
[codex:546722] pc 01a3 JUMPDEST: stack size 2 top ['ret', 'arg']
[codex:546722] pc 01ee JUMPDEST: stack size 17 top ['ISZERO(EXTCODESIZE((MLOAD(0x40)&(SHL(0x1,0xa0)-0x1))))', 'JUMPI(ISZERO(ISZERO(EXTCODESIZE((MLOAD(0x40)&(SHL(0x1,0xa0)-0x1))))),0x1ee)', 'REVERT(0x0,0x0)']
[codex:546722] pc 0202 JUMPDEST: stack size 15 top ["JUMPI(ISZERO(ISZERO(STATICCALL(['GAS', 'JUMPI(ISZERO(ISZERO(EXTCODESIZE((MLOAD(0x40)&(SHL(0x1,0xa0)-0x1))))),0x1ee)', 'ISZERO(EXTCODESIZE((MLOAD(0x40)&(SHL(0x1,0xa0)-0x1))))', '(MLOAD(0x40)&(SHL(0x1,0xa0)-0x1))', 'MLOAD(store(SHL(0x70a08231,0xe0),MLOAD(0x40)))', '((store(ADDRESS,(store(SHL(0x70a08231,0xe0),MLOAD(0x40))+0x4))-MLOAD(store(SHL(0x70a08231,0xe0),MLOAD(0x40))))+0x24)']))),0x202)", 'RETURNDATACOPY(RETURNDATASIZE,0x0,0x0)', 'REVERT(RETURNDATASIZE,0x0)']
[codex:546722] pc 0228 JUMPDEST: stack size 13 top ['MLOAD(store(SHL(0x70a08231,0xe0),MLOAD(0x40)))', 'MLOAD(0x40)', 'JUMP(0x2b6)']
[codex:546722] pc 027e JUMPDEST: stack size 28 top ['ISZERO(EXTCODESIZE(((SHL(0x1,0xa0)-0x1)&store(SHL(0xa9059cbb,0xe0),MLOAD(0x40)))))', 'JUMPI(ISZERO(ISZERO(EXTCODESIZE(((SHL(0x1,0xa0)-0x1)&store(SHL(0xa9059cbb,0xe0),MLOAD(0x40)))))),0x27e)', 'REVERT(0x0,0x0)']
[codex:546722] pc 0292 JUMPDEST: stack size 25 top ["JUMPI(ISZERO(ISZERO(CALL(['GAS', 'JUMPI(ISZERO(ISZERO(EXTCODESIZE(((SHL(0x1,0xa0)-0x1)&store(SHL(0xa9059cbb,0xe0),MLOAD(0x40)))))),0x27e)', 'ISZERO(EXTCODESIZE(((SHL(0x1,0xa0)-0x1)&store(SHL(0xa9059cbb,0xe0),MLOAD(0x40)))))', '((SHL(0x1,0xa0)-0x1)&store(SHL(0xa9059cbb,0xe0),MLOAD(0x40)))', '0x0', 'MLOAD(store(((SHL(0x1,0xa0)-0x1)&0x40),(store(SHL(0xa9059cbb,0xe0),MLOAD(0x40))+0x4)))', '((store((SHL(0x1,0xa0)-0x1),(store(((SHL(0x1,0xa0)-0x1)&0x40),(store(SHL(0xa9059cbb,0xe0),MLOAD(0x40))+0x4))+0x24))-MLOAD(store(((SHL(0x1,0xa0)-0x1)&0x40),(store(SHL(0xa9059cbb,0xe0),MLOAD(0x40))+0x4))))+0x44)']))),0x292)", 'RETURNDATACOPY(RETURNDATASIZE,0x0,0x0)', 'REVERT(RETURNDATASIZE,0x0)']
[codex:546722] pc 02b6 JUMPDEST: stack size 23 top ['MLOAD(store(((SHL(0x1,0xa0)-0x1)&0x40),(store(SHL(0xa9059cbb,0xe0),MLOAD(0x40))+0x4)))', 'MLOAD(0x40)', 'RETURNDATASIZE']
[codex:546722] pc 02b8 JUMP: stack size 22 top ['0x20', 'MLOAD(store(((SHL(0x1,0xa0)-0x1)&0x40),(store(SHL(0xa9059cbb,0xe0),MLOAD(0x40))+0x4)))', 'JUMP(MLOAD(0x40))']
[codex:546722] final stack ['JUMP(0x2b6)', '0x33', '(SHL(0x1,0xa0)-0x1)', 'MLOAD(0x40)', '((SHL(0x1,0xa0)-0x1)&store(SHL(0xa9059cbb,0xe0),MLOAD(0x40)))', '0xa9059cbb', '(store((SHL(0x1,0xa0)-0x1),(store(((SHL(0x1,0xa0)-0x1)&0x40),(store(SHL(0xa9059cbb,0xe0),MLOAD(0x40))+0x4))+0x24))+0x44)', '0x20', 'MLOAD(store(((SHL(0x1,0xa0)-0x1)&0x40),(store(SHL(0xa9059cbb,0xe0),MLOAD(0x40))+0x4)))', 'JUMP(MLOAD(0x40))']
[codex:546722] 
[codex:546722] thinking
[codex:546722] **Analyzing ERC20 sweep function bytecode**
[codex:546722] exec
[codex:546722] /bin/bash -lc "python3 - <<'PY'
[codex:546722] # Symbolic trace to get stack at 0x0228
[codex:546722] import re
[codex:546722] code=open('BYTECODE_BUNDLE.txt').read()
[codex:546722] m=re.search(r'0x([0-9a-fA-F]+)', code)
[codex:546722] bytecode=bytes.fromhex(m.group(1))
[codex:546722] 
[codex:546722] opcodes={
[codex:546722] 0x00:'STOP',0x01:'ADD',0x02:'MUL',0x03:'SUB',0x04:'DIV',0x05:'SDIV',0x06:'MOD',0x07:'SMOD',0x08:'ADDMOD',0x09:'MULMOD',0x0a:'EXP',0x0b:'SIGNEXTEND',
[codex:546722] 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',
[codex:546722] 0x20:'SHA3',
[codex:546722] 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',
[codex:546722] 0x40:'BLOCKHASH',0x41:'COINBASE',0x42:'TIMESTAMP',0x43:'NUMBER',0x44:'DIFFICULTY',0x45:'GASLIMIT',0x46:'CHAINID',0x47:'SELFBALANCE',0x48:'BASEFEE',
[codex:546722] 0x50:'POP',0x51:'MLOAD',0x52:'MSTORE',0x53:'MSTORE8',0x54:'SLOAD',0x55:'SSTORE',0x56:'JUMP',0x57:'JUMPI',0x58:'PC',0x59:'MSIZE',0x5a:'GAS',0x5b:'JUMPDEST',
[codex:546722] 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',
[codex:546722] 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',
[codex:546722] 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',
[codex:546722] 0xa0:'LOG0',0xa1:'LOG1',0xa2:'LOG2',0xa3:'LOG3',0xa4:'LOG4',
[codex:546722] 0xf0:'CREATE',0xf1:'CALL',0xf2:'CALLCODE',0xf3:'RETURN',0xf4:'DELEGATECALL',0xf5:'CREATE2',0xfa:'STATICCALL',0xfd:'REVERT',0xfe:'INVALID',0xff:'SELFDESTRUCT'
[codex:546722] }
[codex:546722] 
[codex:546722] # disassemble into list of (pc, name, imm)
[codex:546722] ops=[]
[codex:546722] pc=0
[codex:546722] while pc < len(bytecode):
[codex:546722]     op=bytecode[pc]
[codex:546722]     name=opcodes.get(op, f'UNK_{op:02x}')
[codex:546722]     if 0x60 <= op <= 0x7f:
[codex:546722]         n=op-0x5f
[codex:546722]         data=bytecode[pc+1:pc+1+n]
[codex:546722]         ops.append((pc,name,int.from_bytes(data,'big')))
[codex:546722]         pc+=1+n
[codex:546722]     else:
[codex:546722]         ops.append((pc,name,None))
[codex:546722]         pc+=1
[codex:546722] 
[codex:546722] ops_dict={pc:(name,imm) for pc,name,imm in ops}
[codex:546722] 
[codex:546722] # Build a pc->index map
[codex:546722] idx={pc:i for i,(pc,_,_) in enumerate(ops)}
[codex:546722] 
[codex:546722] start=0x01a3
[codex:546722] # We'll follow the path that succeeds staticcall and balance "'!=0.
[codex:546722] 
[codex:546722] stack=['"'ret','token']
[codex:546722] 
[codex:546722] pc=start
[codex:546722] while True:
[codex:546722]     name,imm=ops_dict[pc]
[codex:546722]     # print for debug maybe
[codex:546722]     #
[codex:546722]     if name.startswith('PUSH'):
[codex:546722]         stack.append(hex(imm))
[codex:546722]     elif name.startswith('DUP'):
[codex:546722]         n=int(name[3:])
[codex:546722]         stack.append(stack[-n])
[codex:546722]     elif name.startswith('SWAP'):
[codex:546722]         n=int(name[4:])
[codex:546722]         stack[-1], stack[-1-n] = stack[-1-n], stack[-1]
[codex:546722]     elif name=='POP':
[codex:546722]         stack.pop()
[codex:546722]     elif name=='MLOAD':
[codex:546722]         a=stack.pop(); stack.append(f'MLOAD({a})')
[codex:546722]     elif name=='MSTORE':
[codex:546722]         a=stack.pop(); b=stack.pop(); stack.append(f'MSTORE({b},{a})')
[codex:546722]     elif name=='AND':
[codex:546722]         a=stack.pop(); b=stack.pop(); stack.append(f'({a}&{b})')
[codex:546722]     elif name=='OR':
[codex:546722]         a=stack.pop(); b=stack.pop(); stack.append(f'({a}|{b})')
[codex:546722]     elif name=='ADD':
[codex:546722]         a=stack.pop(); b=stack.pop(); stack.append(f'({a}+{b})')
[codex:546722]     elif name=='SUB':
[codex:546722]         a=stack.pop(); b=stack.pop(); stack.append(f'({a}-{b})')
[codex:546722]     elif name=='SHL':
[codex:546722]         a=stack.pop(); b=stack.pop(); stack.append(f'SHL({b},{a})')
[codex:546722]     elif name=='ISZERO':
[codex:546722]         a=stack.pop(); stack.append(f'ISZERO({a})')
[codex:546722]     elif name=='EXTCODESIZE':
[codex:546722]         a=stack.pop(); stack.append(f'EXTCODESIZE({a})')
[codex:546722]     elif name=='STATICCALL':
[codex:546722]         # pops 6 args
[codex:546722]         args=[stack.pop() for _ in range(6)]
[codex:546722]         stack.append(f'STATICCALL({args})')
[codex:546722]     elif name=='RETURNDATASIZE':
[codex:546722]         stack.append('RETURNDATASIZE')
[codex:546722]     elif name=='RETURNDATACOPY':
[codex:546722]         a=stack.pop(); b=stack.pop(); c=stack.pop(); stack.append(f'RDCOPY({c},{b},{a})')
[codex:546722]     elif name=='ADDRESS':
[codex:546722]         stack.append('ADDRESS')
[codex:546722]     elif name=='JUMPI':
[codex:546722]         dest=stack.pop(); cond=stack.pop()
[codex:546722]         # choose branch: for pc 0x01e5 JUMPI to 0x01ee if cond true.
[codex:546722]         # At 0x01f4 JUMPI to 0x0202 if cond true.
[codex:546722]         # At 0x020f JUMPI to 0x0218 if cond true.
[codex:546722]         # At 0x021d JUMPI to 0x0228 if balance "'!=0 (cond is balance)
[codex:546722]         # We'"'ll force success path, so cond true.
[codex:546722]         if pc == 0x021d:
[codex:546722]             # This JUMPI uses cond=balance; we want non-zero -> jump
[codex:546722]             pc = 0x0228
[codex:546722]             # push a marker? we already popped dest and cond, so ok
[codex:546722]             continue
[codex:546722]         # other JUMPI -> jump to dest (true)
[codex:546722]         pc = int(dest,16) if isinstance(dest,str) and dest.startswith('0x') else dest
[codex:546722]         continue
[codex:546722]     elif name=='JUMP':
[codex:546722]         dest=stack.pop();
[codex:546722]         pc = int(dest,16) if isinstance(dest,str) and dest.startswith('0x') else dest
[codex:546722]         continue
[codex:546722]     elif name=='REVERT':
[codex:546722]         # stop
[codex:546722]         break
[codex:546722]     elif name=='CALL':
[codex:546722]         args=[stack.pop() for _ in range(7)]
[codex:546722]         stack.append(f'CALL({args})')
[codex:546722]     elif name=='GAS':
[codex:546722]         stack.append('GAS')
[codex:546722]     elif name=='MLOAD':
[codex:546722]         a=stack.pop(); stack.append(f'MLOAD({a})')
[codex:546722]     else:
[codex:546722]         # unhandled
[codex:546722]         pass
[codex:546722] 
[codex:546722]     if pc == 0x0228:
[codex:546722]         print('Stack at 0x0228:', stack)
[codex:546722]         break
[codex:546722] 
[codex:546722]     # next instruction
[codex:546722]     pc = ops[idx[pc]+1][0]
[codex:546722] 
[codex:546722] print('stack size', len(stack))
[codex:546722] PY" in /tmp/codex-multi-8tm6gnag succeeded in 27ms:
[codex:546722] Stack at 0x0228: ['ret', 'token', '0x40', 'MLOAD(0x40)', 'MLOAD(0x40)', '0x0', 'MLOAD(RETURNDATASIZE)']
[codex:546722] stack size 7
[codex:546722] 
[codex:546722] 
[codex:546722] thinking
[codex:546722] **Decoding initializer and token sweep logic**
[codex:546722] thinking
[codex:546722] **Investigating storage slot 0x34 usage**
[codex:546722] 
[codex:546722] I'll check whether slot 0x34 (likely token address) gets set anywhere in the bytecode since I didn’t spot it in the initializer—it might be set only in the constructor or missing entirely. I’ll scan for SSTORE instructions targeting slot 0x34 to confirm if it’s ever written at runtime.
[codex:546722] exec
[codex:546722] /bin/bash -lc "python3 - <<'PY'
[codex:546722] # find SSTORE occurrences and preceding push values
[codex:546722] import re
[codex:546722] code=open('BYTECODE_BUNDLE.txt').read()
[codex:546722] m=re.search(r'0x([0-9a-fA-F]+)', code)
[codex:546722] bytecode=bytes.fromhex(m.group(1))
[codex:546722] 
[codex:546722] opnames={0x55:'SSTORE',0x54:'SLOAD'}
[codex:546722] 
[codex:546722] # simple disasm with immediate
[codex:546722] pc=0
[codex:546722] ops=[]
[codex:546722] while pc < len(bytecode):
[codex:546722]     op=bytecode[pc]
[codex:546722]     name=None
[codex:546722]     if 0x60 <= op <= 0x7f:
[codex:546722]         n=op-0x5f
[codex:546722]         data=bytecode[pc+1:pc+1+n]
[codex:546722]         ops.append((pc, f'PUSH{n}', data.hex()))
[codex:546722]         pc+=1+n
[codex:546722]     else:
[codex:546722]         if op==0x55:
[codex:546722]             ops.append((pc,'SSTORE',''))
[codex:546722]         elif op==0x54:
[codex:546722]             ops.append((pc,'SLOAD',''))
[codex:546722]         else:
[codex:546722]             ops.append((pc,op,'') )
[codex:546722]         pc+=1
[codex:546722] 
[codex:546722] # print around SSTORE
[codex:546722] for i,(pc,op,imm) in enumerate(ops):
[codex:546722]     if op=='SSTORE':
[codex:546722]         ctx=ops[max(0,i-5):i+1]
[codex:546722]         print('SSTORE at',hex(pc))
[codex:546722]         for c in ctx:
[codex:546722]             print(' ',c)
[codex:546722]         print()
[codex:546722] PY" in /tmp/codex-multi-8tm6gnag succeeded in 25ms:
[codex:546722] SSTORE at 0x354
[codex:546722]   (846, 23, '')
[codex:546722]   (847, 22, '')
[codex:546722]   (848, 'PUSH1', '01')
[codex:546722]   (850, 23, '')
[codex:546722]   (851, 144, '')
[codex:546722]   (852, 'SSTORE', '')
[codex:546722] 
[codex:546722] SSTORE at 0x370
[codex:546722]   (875, 3, '')
[codex:546722]   (876, 132, '')
[codex:546722]   (877, 22, '')
[codex:546722]   (878, 23, '')
[codex:546722]   (879, 144, '')
[codex:546722]   (880, 'SSTORE', '')
[codex:546722] 
[codex:546722] SSTORE at 0x381
[codex:546722]   (890, 'SLOAD', '')
[codex:546722]   (891, 'PUSH2', 'ff00')
[codex:546722]   (894, 25, '')
[codex:546722] 
[codex:546722] 
[codex:546722] thinking
[codex:546722] **Analyzing concrete exploit paths**
[codex:546722] thinking
[codex:546722] **Preparing detailed vulnerability report**
[codex:546722] 
[codex:546722] I’m putting together a JSON report summarizing a high-severity access control bug: an unprotected initializer lets any caller set the recipient slot and then sweep ERC20 tokens to themselves. I’m capturing exact bytecode offsets for evidence, describing the conditional exploit path, and including clear recommendations for mitigation. This will meet the user’s schema requirements with precise, actionable details.
[codex:546722] codex
[codex:546722] {"no_findings":false,"summary":"Unprotected initializer lets the first caller set the payout recipient (slot 0x33) and then use the public token-sweep function to transfer any ERC20 balance to themselves if the contract is still uninitialized.","findings":[{"severity":"high","category":"access_control","title":"Unprotected initializer allows attacker to set recipient and sweep ERC20 balances","exploit_scenario":"If the contract has not been initialized yet (slot0 flags are zero), an attacker calls selector 0xc4d66de8 with their address. This writes the attacker address into slot 0x33. They then call selector 0x3ef13367 with a token address; the function queries balanceOf(address(this)) and calls transfer(slot0x33, balance), sending the entire ERC20 balance to the attacker. Future ETH sent to the contract will also be forwarded to slot 0x33 via the fallback CALL.","recommendation":"Restrict the initializer to an authorized caller or initialize in the deployment transaction (constructor or proxy setup) so no external account can set the recipient. If already deployed, ensure slot0 shows initialized and slot0x33 is the intended recipient.","evidence":"Initializer entry at 0x015b jumps to 0x02c8, which only checks initialization flags in slot0 and performs no CALLER/ORIGIN checks. At 0x0356-0x0370 it SSTOREs slot 0x33 with the user-supplied argument. The public sweep at 0x01a3 builds balanceOf(address(this)) and, if nonzero, calls transfer in 0x0228-0x0292 using SLOAD(0x33) as recipient.","locations":["`runtime_bytecode.hex:0x015b`","`runtime_bytecode.hex:0x02c8`","`runtime_bytecode.hex:0x0356`","`runtime_bytecode.hex:0x01a3`","`runtime_bytecode.hex:0x0228`"]}]}
[codex:546722] tokens used
[codex:546722] 72,032
[codex:546722] {"no_findings":false,"summary":"Unprotected initializer lets the first caller set the payout recipient (slot 0x33) and then use the public token-sweep function to transfer any ERC20 balance to themselves if the contract is still uninitialized.","findings":[{"severity":"high","category":"access_control","title":"Unprotected initializer allows attacker to set recipient and sweep ERC20 balances","exploit_scenario":"If the contract has not been initialized yet (slot0 flags are zero), an attacker calls selector 0xc4d66de8 with their address. This writes the attacker address into slot 0x33. They then call selector 0x3ef13367 with a token address; the function queries balanceOf(address(this)) and calls transfer(slot0x33, balance), sending the entire ERC20 balance to the attacker. Future ETH sent to the contract will also be forwarded to slot 0x33 via the fallback CALL.","recommendation":"Restrict the initializer to an authorized caller or initialize in the deployment transaction (constructor or proxy setup) so no external account can set the recipient. If already deployed, ensure slot0 shows initialized and slot0x33 is the intended recipient.","evidence":"Initializer entry at 0x015b jumps to 0x02c8, which only checks initialization flags in slot0 and performs no CALLER/ORIGIN checks. At 0x0356-0x0370 it SSTOREs slot 0x33 with the user-supplied argument. The public sweep at 0x01a3 builds balanceOf(address(this)) and, if nonzero, calls transfer in 0x0228-0x0292 using SLOAD(0x33) as recipient.","locations":["`runtime_bytecode.hex:0x015b`","`runtime_bytecode.hex:0x02c8`","`runtime_bytecode.hex:0x0356`","`runtime_bytecode.hex:0x01a3`","`runtime_bytecode.hex:0x0228`"]}]}
Metadata
{
    "codex": {
        "ran_at": "2026-01-05T21:59:12.079903+00:00",
        "returncode": 0
    },
    "summary": "Unprotected initializer lets the first caller set the payout recipient (slot 0x33) and then use the public token-sweep function to transfer any ERC20 balance to themselves if the contract is still uninitialized.",
    "raw_final": {
        "summary": "Unprotected initializer lets the first caller set the payout recipient (slot 0x33) and then use the public token-sweep function to transfer any ERC20 balance to themselves if the contract is still uninitialized.",
        "findings": [
            {
                "title": "Unprotected initializer allows attacker to set recipient and sweep ERC20 balances",
                "category": "access_control",
                "evidence": "Initializer entry at 0x015b jumps to 0x02c8, which only checks initialization flags in slot0 and performs no CALLER/ORIGIN checks. At 0x0356-0x0370 it SSTOREs slot 0x33 with the user-supplied argument. The public sweep at 0x01a3 builds balanceOf(address(this)) and, if nonzero, calls transfer in 0x0228-0x0292 using SLOAD(0x33) as recipient.",
                "severity": "high",
                "locations": [
                    "`runtime_bytecode.hex:0x015b`",
                    "`runtime_bytecode.hex:0x02c8`",
                    "`runtime_bytecode.hex:0x0356`",
                    "`runtime_bytecode.hex:0x01a3`",
                    "`runtime_bytecode.hex:0x0228`"
                ],
                "recommendation": "Restrict the initializer to an authorized caller or initialize in the deployment transaction (constructor or proxy setup) so no external account can set the recipient. If already deployed, ensure slot0 shows initialized and slot0x33 is the intended recipient.",
                "exploit_scenario": "If the contract has not been initialized yet (slot0 flags are zero), an attacker calls selector 0xc4d66de8 with their address. This writes the attacker address into slot 0x33. They then call selector 0x3ef13367 with a token address; the function queries balanceOf(address(this)) and calls transfer(slot0x33, balance), sending the entire ERC20 balance to the attacker. Future ETH sent to the contract will also be forwarded to slot 0x33 via the fallback CALL."
            }
        ],
        "no_findings": false
    },
    "no_findings": false,
    "schema_version": 1
}

Opcode Heuristics

tool.cast_disasm
Delegatecall
0
Selfdestruct
0
CREATE2
0
CALL-family (heavy)
3
EXT*/BALANCE
4
Total opcodes
671
Flags
No heuristic flags raised.
View cast disassembly output
00000000: PUSH1 0x80
00000002: PUSH1 0x40
00000004: MSTORE
00000005: PUSH1 0x04
00000007: CALLDATASIZE
00000008: LT
00000009: PUSH2 0x003f
0000000c: JUMPI
0000000d: PUSH1 0x00
0000000f: CALLDATALOAD
00000010: PUSH1 0xe0
00000012: SHR
00000013: DUP1
00000014: PUSH4 0x3ef13367
00000019: EQ
0000001a: PUSH2 0x00f5
0000001d: JUMPI
0000001e: DUP1
0000001f: PUSH4 0x99e7d056
00000024: EQ
00000025: PUSH2 0x012a
00000028: JUMPI
00000029: DUP1
0000002a: PUSH4 0xc4d66de8
0000002f: EQ
00000030: PUSH2 0x015b
00000033: JUMPI
00000034: DUP1
00000035: PUSH4 0xca325469
0000003a: EQ
0000003b: PUSH2 0x018e
0000003e: JUMPI
0000003f: JUMPDEST
00000040: PUSH1 0x33
00000042: SLOAD
00000043: PUSH1 0x40
00000045: MLOAD
00000046: PUSH1 0x01
00000048: PUSH1 0x01
0000004a: PUSH1 0xa0
0000004c: SHL
0000004d: SUB
0000004e: SWAP1
0000004f: SWAP2
00000050: AND
00000051: SWAP1
00000052: CALLVALUE
00000053: DUP1
00000054: ISZERO
00000055: PUSH2 0x08fc
00000058: MUL
00000059: SWAP2
0000005a: PUSH1 0x00
0000005c: DUP2
0000005d: DUP2
0000005e: DUP2
0000005f: DUP6
00000060: DUP9
00000061: DUP9
00000062: CALL
00000063: SWAP4
00000064: POP
00000065: POP
00000066: POP
00000067: POP
00000068: ISZERO
00000069: DUP1
0000006a: ISZERO
0000006b: PUSH2 0x0078
0000006e: JUMPI
0000006f: RETURNDATASIZE
00000070: PUSH1 0x00
00000072: DUP1
00000073: RETURNDATACOPY
00000074: RETURNDATASIZE
00000075: PUSH1 0x00
00000077: REVERT
00000078: JUMPDEST
00000079: POP
0000007a: PUSH32 0x69b31548dea9b3b707b4dff357d326e3e9348b24e7a6080a218a6edeeec48f9b
0000009b: CALLER
0000009c: CALLVALUE
0000009d: PUSH1 0x00
0000009f: CALLDATASIZE
000000a0: PUSH1 0x40
000000a2: MLOAD
000000a3: DUP1
000000a4: DUP6
000000a5: PUSH1 0x01
000000a7: PUSH1 0x01
000000a9: PUSH1 0xa0
000000ab: SHL
000000ac: SUB
000000ad: AND
000000ae: DUP2
000000af: MSTORE
000000b0: PUSH1 0x20
000000b2: ADD
000000b3: DUP5
000000b4: DUP2
000000b5: MSTORE
000000b6: PUSH1 0x20
000000b8: ADD
000000b9: DUP1
000000ba: PUSH1 0x20
000000bc: ADD
000000bd: DUP3
000000be: DUP2
000000bf: SUB
000000c0: DUP3
000000c1: MSTORE
000000c2: DUP5
000000c3: DUP5
000000c4: DUP3
000000c5: DUP2
000000c6: DUP2
000000c7: MSTORE
000000c8: PUSH1 0x20
000000ca: ADD
000000cb: SWAP3
000000cc: POP
000000cd: DUP1
000000ce: DUP3
000000cf: DUP5
000000d0: CALLDATACOPY
000000d1: PUSH1 0x00
000000d3: DUP4
000000d4: DUP3
000000d5: ADD
000000d6: MSTORE
000000d7: PUSH1 0x40
000000d9: MLOAD
000000da: PUSH1 0x1f
000000dc: SWAP1
000000dd: SWAP2
000000de: ADD
000000df: PUSH1 0x1f
000000e1: NOT
000000e2: AND
000000e3: SWAP1
000000e4: SWAP3
000000e5: ADD
000000e6: DUP3
000000e7: SWAP1
000000e8: SUB
000000e9: SWAP8
000000ea: POP
000000eb: SWAP1
000000ec: SWAP6
000000ed: POP
000000ee: POP
000000ef: POP
000000f0: POP
000000f1: POP
000000f2: POP
000000f3: LOG1
000000f4: STOP
000000f5: JUMPDEST
000000f6: CALLVALUE
000000f7: DUP1
000000f8: ISZERO
000000f9: PUSH2 0x0101
000000fc: JUMPI
000000fd: PUSH1 0x00
000000ff: DUP1
00000100: REVERT
00000101: JUMPDEST
00000102: POP
00000103: PUSH2 0x0128
00000106: PUSH1 0x04
00000108: DUP1
00000109: CALLDATASIZE
0000010a: SUB
0000010b: PUSH1 0x20
0000010d: DUP2
0000010e: LT
0000010f: ISZERO
00000110: PUSH2 0x0118
00000113: JUMPI
00000114: PUSH1 0x00
00000116: DUP1
00000117: REVERT
00000118: JUMPDEST
00000119: POP
0000011a: CALLDATALOAD
0000011b: PUSH1 0x01
0000011d: PUSH1 0x01
0000011f: PUSH1 0xa0
00000121: SHL
00000122: SUB
00000123: AND
00000124: PUSH2 0x01a3
00000127: JUMP
00000128: JUMPDEST
00000129: STOP
0000012a: JUMPDEST
0000012b: CALLVALUE
0000012c: DUP1
0000012d: ISZERO
0000012e: PUSH2 0x0136
00000131: JUMPI
00000132: PUSH1 0x00
00000134: DUP1
00000135: REVERT
00000136: JUMPDEST
00000137: POP
00000138: PUSH2 0x013f
0000013b: PUSH2 0x02b9
0000013e: JUMP
0000013f: JUMPDEST
00000140: PUSH1 0x40
00000142: DUP1
00000143: MLOAD
00000144: PUSH1 0x01
00000146: PUSH1 0x01
00000148: PUSH1 0xa0
0000014a: SHL
0000014b: SUB
0000014c: SWAP1
0000014d: SWAP3
0000014e: AND
0000014f: DUP3
00000150: MSTORE
00000151: MLOAD
00000152: SWAP1
00000153: DUP2
00000154: SWAP1
00000155: SUB
00000156: PUSH1 0x20
00000158: ADD
00000159: SWAP1
0000015a: RETURN
0000015b: JUMPDEST
0000015c: CALLVALUE
0000015d: DUP1
0000015e: ISZERO
0000015f: PUSH2 0x0167
00000162: JUMPI
00000163: PUSH1 0x00
00000165: DUP1
00000166: REVERT
00000167: JUMPDEST
00000168: POP
00000169: PUSH2 0x0128
0000016c: PUSH1 0x04
0000016e: DUP1
0000016f: CALLDATASIZE
00000170: SUB
00000171: PUSH1 0x20
00000173: DUP2
00000174: LT
00000175: ISZERO
00000176: PUSH2 0x017e
00000179: JUMPI
0000017a: PUSH1 0x00
0000017c: DUP1
0000017d: REVERT
0000017e: JUMPDEST
0000017f: POP
00000180: CALLDATALOAD
00000181: PUSH1 0x01
00000183: PUSH1 0x01
00000185: PUSH1 0xa0
00000187: SHL
00000188: SUB
00000189: AND
0000018a: PUSH2 0x02c8
0000018d: JUMP
0000018e: JUMPDEST
0000018f: CALLVALUE
00000190: DUP1
00000191: ISZERO
00000192: PUSH2 0x019a
00000195: JUMPI
00000196: PUSH1 0x00
00000198: DUP1
00000199: REVERT
0000019a: JUMPDEST
0000019b: POP
0000019c: PUSH2 0x013f
0000019f: PUSH2 0x0386
000001a2: JUMP
000001a3: JUMPDEST
000001a4: PUSH1 0x40
000001a6: DUP1
000001a7: MLOAD
000001a8: PUSH4 0x70a08231
000001ad: PUSH1 0xe0
000001af: SHL
000001b0: DUP2
000001b1: MSTORE
000001b2: ADDRESS
000001b3: PUSH1 0x04
000001b5: DUP3
000001b6: ADD
000001b7: MSTORE
000001b8: SWAP1
000001b9: MLOAD
000001ba: DUP3
000001bb: SWAP2
000001bc: PUSH1 0x00
000001be: SWAP2
000001bf: PUSH1 0x01
000001c1: PUSH1 0x01
000001c3: PUSH1 0xa0
000001c5: SHL
000001c6: SUB
000001c7: DUP5
000001c8: AND
000001c9: SWAP2
000001ca: PUSH4 0x70a08231
000001cf: SWAP2
000001d0: PUSH1 0x24
000001d2: DUP1
000001d3: DUP4
000001d4: ADD
000001d5: SWAP3
000001d6: PUSH1 0x20
000001d8: SWAP3
000001d9: SWAP2
000001da: SWAP1
000001db: DUP3
000001dc: SWAP1
000001dd: SUB
000001de: ADD
000001df: DUP2
000001e0: DUP7
000001e1: DUP1
000001e2: EXTCODESIZE
000001e3: ISZERO
000001e4: DUP1
000001e5: ISZERO
000001e6: PUSH2 0x01ee
000001e9: JUMPI
000001ea: PUSH1 0x00
000001ec: DUP1
000001ed: REVERT
000001ee: JUMPDEST
000001ef: POP
000001f0: GAS
000001f1: STATICCALL
000001f2: ISZERO
000001f3: DUP1
000001f4: ISZERO
000001f5: PUSH2 0x0202
000001f8: JUMPI
000001f9: RETURNDATASIZE
000001fa: PUSH1 0x00
000001fc: DUP1
000001fd: RETURNDATACOPY
000001fe: RETURNDATASIZE
000001ff: PUSH1 0x00
00000201: REVERT
00000202: JUMPDEST
00000203: POP
00000204: POP
00000205: POP
00000206: POP
00000207: PUSH1 0x40
00000209: MLOAD
0000020a: RETURNDATASIZE
0000020b: PUSH1 0x20
0000020d: DUP2
0000020e: LT
0000020f: ISZERO
00000210: PUSH2 0x0218
00000213: JUMPI
00000214: PUSH1 0x00
00000216: DUP1
00000217: REVERT
00000218: JUMPDEST
00000219: POP
0000021a: MLOAD
0000021b: SWAP1
0000021c: POP
0000021d: DUP1
0000021e: PUSH2 0x0228
00000221: JUMPI
00000222: POP
00000223: POP
00000224: PUSH2 0x02b6
00000227: JUMP
00000228: JUMPDEST
00000229: PUSH1 0x33
0000022b: SLOAD
0000022c: PUSH1 0x40
0000022e: DUP1
0000022f: MLOAD
00000230: PUSH4 0xa9059cbb
00000235: PUSH1 0xe0
00000237: SHL
00000238: DUP2
00000239: MSTORE
0000023a: PUSH1 0x01
0000023c: PUSH1 0x01
0000023e: PUSH1 0xa0
00000240: SHL
00000241: SUB
00000242: SWAP3
00000243: DUP4
00000244: AND
00000245: PUSH1 0x04
00000247: DUP3
00000248: ADD
00000249: MSTORE
0000024a: PUSH1 0x24
0000024c: DUP2
0000024d: ADD
0000024e: DUP5
0000024f: SWAP1
00000250: MSTORE
00000251: SWAP1
00000252: MLOAD
00000253: SWAP2
00000254: DUP5
00000255: AND
00000256: SWAP2
00000257: PUSH4 0xa9059cbb
0000025c: SWAP2
0000025d: PUSH1 0x44
0000025f: DUP1
00000260: DUP3
00000261: ADD
00000262: SWAP3
00000263: PUSH1 0x20
00000265: SWAP3
00000266: SWAP1
00000267: SWAP2
00000268: SWAP1
00000269: DUP3
0000026a: SWAP1
0000026b: SUB
0000026c: ADD
0000026d: DUP2
0000026e: PUSH1 0x00
00000270: DUP8
00000271: DUP1
00000272: EXTCODESIZE
00000273: ISZERO
00000274: DUP1
00000275: ISZERO
00000276: PUSH2 0x027e
00000279: JUMPI
0000027a: PUSH1 0x00
0000027c: DUP1
0000027d: REVERT
0000027e: JUMPDEST
0000027f: POP
00000280: GAS
00000281: CALL
00000282: ISZERO
00000283: DUP1
00000284: ISZERO
00000285: PUSH2 0x0292
00000288: JUMPI
00000289: RETURNDATASIZE
0000028a: PUSH1 0x00
0000028c: DUP1
0000028d: RETURNDATACOPY
0000028e: RETURNDATASIZE
0000028f: PUSH1 0x00
00000291: REVERT
00000292: JUMPDEST
00000293: POP
00000294: POP
00000295: POP
00000296: POP
00000297: PUSH1 0x40
00000299: MLOAD
0000029a: RETURNDATASIZE
0000029b: PUSH1 0x20
0000029d: DUP2
0000029e: LT
0000029f: ISZERO
000002a0: PUSH2 0x02a8
000002a3: JUMPI
000002a4: PUSH1 0x00
000002a6: DUP1
000002a7: REVERT
000002a8: JUMPDEST
000002a9: POP
000002aa: MLOAD
000002ab: PUSH2 0x02b3
000002ae: JUMPI
000002af: PUSH1 0x00
000002b1: DUP1
000002b2: REVERT
000002b3: JUMPDEST
000002b4: POP
000002b5: POP
000002b6: JUMPDEST
000002b7: POP
000002b8: JUMP
000002b9: JUMPDEST
000002ba: PUSH1 0x34
000002bc: SLOAD
000002bd: PUSH1 0x01
000002bf: PUSH1 0x01
000002c1: PUSH1 0xa0
000002c3: SHL
000002c4: SUB
000002c5: AND
000002c6: DUP2
000002c7: JUMP
000002c8: JUMPDEST
000002c9: PUSH1 0x00
000002cb: SLOAD
000002cc: PUSH2 0x0100
000002cf: SWAP1
000002d0: DIV
000002d1: PUSH1 0xff
000002d3: AND
000002d4: DUP1
000002d5: PUSH2 0x02e1
000002d8: JUMPI
000002d9: POP
000002da: PUSH2 0x02e1
000002dd: PUSH2 0x0395
000002e0: JUMP
000002e1: JUMPDEST
000002e2: DUP1
000002e3: PUSH2 0x02ef
000002e6: JUMPI
000002e7: POP
000002e8: PUSH1 0x00
000002ea: SLOAD
000002eb: PUSH1 0xff
000002ed: AND
000002ee: ISZERO
000002ef: JUMPDEST
000002f0: PUSH2 0x032a
000002f3: JUMPI
000002f4: PUSH1 0x40
000002f6: MLOAD
000002f7: PUSH3 0x461bcd
000002fb: PUSH1 0xe5
000002fd: SHL
000002fe: DUP2
000002ff: MSTORE
00000300: PUSH1 0x04
00000302: ADD
00000303: DUP1
00000304: DUP1
00000305: PUSH1 0x20
00000307: ADD
00000308: DUP3
00000309: DUP2
0000030a: SUB
0000030b: DUP3
0000030c: MSTORE
0000030d: PUSH1 0x2e
0000030f: DUP2
00000310: MSTORE
00000311: PUSH1 0x20
00000313: ADD
00000314: DUP1
00000315: PUSH2 0x039c
00000318: PUSH1 0x2e
0000031a: SWAP2
0000031b: CODECOPY
0000031c: PUSH1 0x40
0000031e: ADD
0000031f: SWAP2
00000320: POP
00000321: POP
00000322: PUSH1 0x40
00000324: MLOAD
00000325: DUP1
00000326: SWAP2
00000327: SUB
00000328: SWAP1
00000329: REVERT
0000032a: JUMPDEST
0000032b: PUSH1 0x00
0000032d: SLOAD
0000032e: PUSH2 0x0100
00000331: SWAP1
00000332: DIV
00000333: PUSH1 0xff
00000335: AND
00000336: ISZERO
00000337: DUP1
00000338: ISZERO
00000339: PUSH2 0x0355
0000033c: JUMPI
0000033d: PUSH1 0x00
0000033f: DUP1
00000340: SLOAD
00000341: PUSH1 0xff
00000343: NOT
00000344: PUSH2 0xff00
00000347: NOT
00000348: SWAP1
00000349: SWAP2
0000034a: AND
0000034b: PUSH2 0x0100
0000034e: OR
0000034f: AND
00000350: PUSH1 0x01
00000352: OR
00000353: SWAP1
00000354: SSTORE
00000355: JUMPDEST
00000356: PUSH1 0x33
00000358: DUP1
00000359: SLOAD
0000035a: PUSH1 0x01
0000035c: PUSH1 0x01
0000035e: PUSH1 0xa0
00000360: SHL
00000361: SUB
00000362: NOT
00000363: AND
00000364: PUSH1 0x01
00000366: PUSH1 0x01
00000368: PUSH1 0xa0
0000036a: SHL
0000036b: SUB
0000036c: DUP5
0000036d: AND
0000036e: OR
0000036f: SWAP1
00000370: SSTORE
00000371: DUP1
00000372: ISZERO
00000373: PUSH2 0x0382
00000376: JUMPI
00000377: PUSH1 0x00
00000379: DUP1
0000037a: SLOAD
0000037b: PUSH2 0xff00
0000037e: NOT
0000037f: AND
00000380: SWAP1
00000381: SSTORE
00000382: JUMPDEST
00000383: POP
00000384: POP
00000385: JUMP
00000386: JUMPDEST
00000387: PUSH1 0x33
00000389: SLOAD
0000038a: PUSH1 0x01
0000038c: PUSH1 0x01
0000038e: PUSH1 0xa0
00000390: SHL
00000391: SUB
00000392: AND
00000393: DUP2
00000394: JUMP
00000395: JUMPDEST
00000396: ADDRESS
00000397: EXTCODESIZE
00000398: ISZERO
00000399: SWAP1
0000039a: JUMP
0000039b: INVALID
0000039c: NUMBER
0000039d: PUSH16 0x6e747261637420696e7374616e636520
000003ae: PUSH9 0x617320616c72656164
000003b8: PUSH26 0x206265656e20696e697469616c697a6564a26469706673582212
000003d3: KECCAK256
000003d4: PUSH21 0x6b2b9a4e8b8fe1a0b26dd2df9a668323992ff2162f
000003ea: UNKNOWN(0xE1)
000003eb: EXTCODEHASH
000003ec: EQ
000003ed: UNKNOWN(0xCE)
000003ee: SWAP10
000003ef: DUP6
000003f0: SWAP4
000003f1: PUSH27

Findings

validated = confirmed for call sinks; sink observed for others
Severity Category Tool Title Confidence Validated Confirmed Details
high access_control codex Unprotected initializer allows attacker to set recipient and sweep ERC20 balances 85 no
view
evidence_json
{
    "evidence": "Initializer entry at 0x015b jumps to 0x02c8, which only checks initialization flags in slot0 and performs no CALLER/ORIGIN checks. At 0x0356-0x0370 it SSTOREs slot 0x33 with the user-supplied argument. The public sweep at 0x01a3 builds balanceOf(address(this)) and, if nonzero, calls transfer in 0x0228-0x0292 using SLOAD(0x33) as recipient.",
    "locations": [
        "`runtime_bytecode.hex:0x015b`",
        "`runtime_bytecode.hex:0x02c8`",
        "`runtime_bytecode.hex:0x0356`",
        "`runtime_bytecode.hex:0x01a3`",
        "`runtime_bytecode.hex:0x0228`"
    ],
    "recommendation": "Restrict the initializer to an authorized caller or initialize in the deployment transaction (constructor or proxy setup) so no external account can set the recipient. If already deployed, ensure slot0 shows initialized and slot0x33 is the intended recipient.",
    "exploit_scenario": "If the contract has not been initialized yet (slot0 flags are zero), an attacker calls selector 0xc4d66de8 with their address. This writes the attacker address into slot 0x33. They then call selector 0x3ef13367 with a token address; the function queries balanceOf(address(this)) and calls transfer(slot0x33, balance), sending the entire ERC20 balance to the attacker. Future ETH sent to the contract will also be forwarded to slot 0x33 via the fallback CALL."
}
high other detector Untrusted CALL target/value reachable 60 no no
view
trace_id: 0x5d1841d178de9ecca100bc6d25e6fa505e5c0feb43f6ee54d90e4faed3acf88b
call_targets: 0x0a7d5c98d8b83bf36700c1c2fa03b3f10d1df2e8
target_varies: no
classification: constant_target
validation_json
{
    "sink": "CALL",
    "errors": 0,
    "status": "sink_reached",
    "attempts": 1,
    "trace_id": "0x5d1841d178de9ecca100bc6d25e6fa505e5c0feb43f6ee54d90e4faed3acf88b",
    "confirmed": false,
    "trace_mode": "callTracer",
    "call_targets": [
        "0x0a7d5c98d8b83bf36700c1c2fa03b3f10d1df2e8"
    ],
    "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": "0x3ef13367",
            "selector": "0x3ef13367",
            "calldata_variants": [
                "0x3ef13367",
                "0x3ef133670000000000000000000000000000000000000000000000000000000000000000"
            ]
        },
        {
            "calldata": "0x99e7d056",
            "selector": "0x99e7d056",
            "calldata_variants": [
                "0x99e7d056",
                "0x99e7d0560000000000000000000000000000000000000000000000000000000000000000"
            ]
        },
        {
            "calldata": "0xc4d66de8",
            "selector": "0xc4d66de8",
            "calldata_variants": [
                "0xc4d66de8",
                "0xc4d66de80000000000000000000000000000000000000000000000000000000000000000"
            ]
        },
        {
            "calldata": "0xca325469",
            "selector": "0xca325469",
            "calldata_variants": [
                "0xca325469",
                "0xca3254690000000000000000000000000000000000000000000000000000000000000000"
            ]
        }
    ]
}
evidence_json
{
    "examples": [
        {
            "pc": 98,
            "opcode": "CALL",
            "returndata_checked": null,
            "value_expression_category": "computed",
            "target_expression_category": "computed"
        },
        {
            "pc": 641,
            "opcode": "CALL",
            "returndata_checked": null,
            "value_expression_category": "computed",
            "target_expression_category": "computed"
        }
    ],
    "call_count": 2,
    "guards_detected": [],
    "untrusted_call_count": 2
}
high other detector ETH value transfer possible 55 no no
view
trace_id: 0x5d1841d178de9ecca100bc6d25e6fa505e5c0feb43f6ee54d90e4faed3acf88b
call_targets: 0x0a7d5c98d8b83bf36700c1c2fa03b3f10d1df2e8
target_varies: no
classification: constant_target
validation_json
{
    "sink": "CALL",
    "errors": 0,
    "status": "sink_reached",
    "attempts": 1,
    "trace_id": "0x5d1841d178de9ecca100bc6d25e6fa505e5c0feb43f6ee54d90e4faed3acf88b",
    "confirmed": false,
    "trace_mode": "callTracer",
    "call_targets": [
        "0x0a7d5c98d8b83bf36700c1c2fa03b3f10d1df2e8"
    ],
    "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": "0x3ef13367",
            "selector": "0x3ef13367",
            "calldata_variants": [
                "0x3ef13367",
                "0x3ef133670000000000000000000000000000000000000000000000000000000000000000"
            ]
        },
        {
            "calldata": "0x99e7d056",
            "selector": "0x99e7d056",
            "calldata_variants": [
                "0x99e7d056",
                "0x99e7d0560000000000000000000000000000000000000000000000000000000000000000"
            ]
        },
        {
            "calldata": "0xc4d66de8",
            "selector": "0xc4d66de8",
            "calldata_variants": [
                "0xc4d66de8",
                "0xc4d66de80000000000000000000000000000000000000000000000000000000000000000"
            ]
        },
        {
            "calldata": "0xca325469",
            "selector": "0xca325469",
            "calldata_variants": [
                "0xca325469",
                "0xca3254690000000000000000000000000000000000000000000000000000000000000000"
            ]
        }
    ]
}
evidence_json
{
    "examples": [
        {
            "pc": 98,
            "opcode": "CALL",
            "returndata_checked": null,
            "value_expression_category": "computed",
            "target_expression_category": "computed"
        },
        {
            "pc": 641,
            "opcode": "CALL",
            "returndata_checked": null,
            "value_expression_category": "computed",
            "target_expression_category": "computed"
        }
    ],
    "eth_value_calls": 2,
    "guards_detected": []
}