f3e7c777-190e-4408-a4ce-7e7b7bb1ab2c
Open this run to answer one question: is this real attacker-relevant behavior with real impact, or just normal contract plumbing?
| 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 |
No slither job recorded yet.
[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`"]}]}
{
"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
}
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
| 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 | — |
viewevidence_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 |
viewtrace_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 |
viewtrace_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": []
}
|