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

Analysis Run

f6ee2b29-8387-4dfc-b1ac-59adb68ab932

complete
Chain ID
1
Address
Block Number
Created
Sat, Jan 3, 2026 9:41 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
Not yet
Best current signal
Untrusted CALL target/value reachable
crit 0 high 0 direct contract
Review Checklist
1. Read the findings table first. Ignore raw jobs until the result looks real.
2. Confirm attacker control, not just the existence of a sink.
3. Confirm money or privilege impact.
4. Keep it if the behavior is real. Kill it if this is normal proxy, admin, or upgrade plumbing.

Processing Jobs

Status & attempts
ID Type Status Attempts Heartbeat
31464 report.consolidate complete 1 / 1 3 months ago
77410 artifact.fetch complete 1 / 3 1 week ago
77411 tool.cast_disasm complete 1 / 3 1 week ago
77412 analysis.bundle complete 1 / 3 1 week ago
77413 capability.graph complete 1 / 3 1 week ago
77414 detector.run complete 1 / 3 1 week ago
77415 validation.fork complete 1 / 3 1 week ago

Artifact

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

Slither

tool.slither

No slither job recorded yet.

Codex

report.consolidate
Job Status
complete
Attempts
1 / 1
Findings
0
No findings?
yes
Summary
No concrete, exploitable profit path identified from the provided runtime bytecode; the only external call appears owner-gated and transfers tokens to the stored owner address.
View stderr
[codex:84920] OpenAI Codex v0.77.0 (research preview)
[codex:84920] --------
[codex:84920] workdir: /tmp/codex-multi-wnrmrpjt
[codex:84920] model: gpt-5.2-codex
[codex:84920] provider: openai
[codex:84920] approval: never
[codex:84920] sandbox: read-only
[codex:84920] reasoning effort: xhigh
[codex:84920] reasoning summaries: auto
[codex:84920] session id: 019b85cb-778f-70a2-8112-8f19e2a14cc0
[codex:84920] --------
[codex:84920] user
[codex:84920] 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:84920] 
[codex:84920] Read `BYTECODE_BUNDLE.txt` completely before concluding.
[codex:84920] 
[codex:84920] ONLY REPORT if you find a CONCRETE, EXPLOITABLE path to profit. We do NOT care about:
[codex:84920] - Gas inefficiency, code quality, or best practices
[codex:84920] - Theoretical vulnerabilities without a clear extraction path
[codex:84920] - Generic footguns (unchecked return values, etc.) unless they enable theft
[codex:84920] - Issues requiring social engineering or off-chain coordination
[codex:84920] 
[codex:84920] PATTERNS WORTH INVESTIGATING in bytecode:
[codex:84920] - CALL/DELEGATECALL with controllable destination or calldata
[codex:84920] - Value transfers (CALL with non-zero value) without prior CALLER/ORIGIN checks
[codex:84920] - SSTORE to low slots (0-10) that might be owner/admin storage
[codex:84920] - ecrecover (signature validation) - look for missing nonce/replay protection
[codex:84920] - External calls before state updates (reentrancy)
[codex:84920] - SELFDESTRUCT with controllable beneficiary
[codex:84920] - Proxy patterns (DELEGATECALL to storage slot) with unprotected upgrade paths
[codex:84920] 
[codex:84920] For each finding, you MUST explain:
[codex:84920] 1. The specific bytecode pattern/offsets that indicate the vulnerability
[codex:84920] 2. The concrete sequence of transactions to extract value
[codex:84920] 3. Why you believe this is exploitable (not just suspicious)
[codex:84920] 
[codex:84920] If you cannot identify a concrete profit path from bytecode alone: set no_findings=true.
[codex:84920] Do NOT hallucinate. Bytecode-only analysis is limited - be honest about uncertainty.
[codex:84920] 
[codex:84920] Output MUST be valid JSON matching the provided schema.
[codex:84920] - severity: info, low, medium, high, critical (use high/critical ONLY for clear extraction paths)
[codex:84920] - category: access_control, reentrancy, math, oracle, upgradeability, auth, other
[codex:84920] mcp startup: no servers
[codex:84920] 
[codex:84920] thinking
[codex:84920] **Reading bytecode file**
[codex:84920] exec
[codex:84920] /bin/bash -lc ls in /tmp/codex-multi-wnrmrpjt succeeded in 6ms:
[codex:84920] BYTECODE_BUNDLE.txt
[codex:84920] codex-output-schema.json
[codex:84920] exec
[codex:84920] /bin/bash -lc 'wc -l BYTECODE_BUNDLE.txt' in /tmp/codex-multi-wnrmrpjt succeeded in 5ms:
[codex:84920] 5 BYTECODE_BUNDLE.txt
[codex:84920] exec
[codex:84920] /bin/bash -lc 'cat BYTECODE_BUNDLE.txt' in /tmp/codex-multi-wnrmrpjt succeeded in 5ms:
[codex:84920] Runtime bytecode bundle for best-effort auditing.
[codex:84920] Note: without verified source, conclusions are low-confidence unless a concrete pattern is visible.
[codex:84920] 
[codex:84920] FILE: runtime_bytecode.hex
[codex:84920] 0x606060405260e060020a60003504636b8357ac8114601a575b005b60c86004356024356000805481903373ffffffffffffffffffffffffffffffffffffffff9081169116141560c1575080547fa9059cbb00000000000000000000000000000000000000000000000000000000606090815273ffffffffffffffffffffffffffffffffffffffff9182166064526084849052849182169063a9059cbb9060a49060209060448188876161da5a03f11560025750506040515115905060c1578291505b5092915050565b60408051918252519081900360200190f3
[codex:84920] 
[codex:84920] thinking
[codex:84920] **Decoding and analyzing bytecode manually**
[codex:84920] exec
[codex:84920] /bin/bash -lc "python - <<'PY'
[codex:84920] bytecode='606060405260e060020a60003504636b8357ac8114601a575b005b60c86004356024356000805481903373ffffffffffffffffffffffffffffffffffffffff9081169116141560c1575080547fa9059cbb00000000000000000000000000000000000000000000000000000000606090815273ffffffffffffffffffffffffffffffffffffffff9182166064526084849052849182169063a9059cbb9060a49060209060448188876161da5a03f11560025750506040515115905060c1578291505b5092915050565b60408051918252519081900360200190f3'
[codex:84920] 
[codex:84920] ops={
[codex:84920] 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:84920] 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:84920] 0x20:'SHA3',0x30:'ADDRESS',0x31:'BALANCE',0x32:'ORIGIN',0x33:'CALLER',0x34:'CALLVALUE',0x35:'CALLDATALOAD',0x36:'CALLDATASIZE',0x37:'CALLDATACOPY',0x38:'CODESIZE',0x39:'CODECOPY',0x3a:'GASPRICE',0x3b:'EXTCODESIZE',0x3c:'EXTCODECOPY',0x3d:'RETURNDATASIZE',0x3e:'RETURNDATACOPY',0x3f:'EXTCODEHASH',
[codex:84920] 0x40:'BLOCKHASH',0x41:'COINBASE',0x42:'TIMESTAMP',0x43:'NUMBER',0x44:'DIFFICULTY',0x45:'GASLIMIT',0x46:'CHAINID',0x47:'SELFBALANCE',0x48:'BASEFEE',
[codex:84920] 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:84920] 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:84920] 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:84920] 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:84920] 0xa0:'LOG0',0xa1:'LOG1',0xa2:'LOG2',0xa3:'LOG3',0xa4:'LOG4',
[codex:84920] 0xf0:'CREATE',0xf1:'CALL',0xf2:'CALLCODE',0xf3:'RETURN',0xf4:'DELEGATECALL',0xf5:'CREATE2',0xfa:'STATICCALL',0xfd:'REVERT',0xfe:'INVALID',0xff:'SELFDESTRUCT'
[codex:84920] }
[codex:84920] 
[codex:84920] b=bytes.fromhex(bytecode)
[codex:84920] 
[codex:84920] pc=0
[codex:84920] while pc<len(b):
[codex:84920]     op=b[pc]
[codex:84920]     name=ops.get(op,f'OP{op:02x}')
[codex:84920]     if 0x60<=op<=0x7f:
[codex:84920]         n=op-0x5f
[codex:84920]         data=b[pc+1:pc+1+n]
[codex:84920]         print(f'{pc:04x}: {name} 0x{data.hex()}')
[codex:84920]         pc+=1+n
[codex:84920]     else:
[codex:84920]         print(f'{pc:04x}: {name}')
[codex:84920]         pc+=1
[codex:84920] PY" in /tmp/codex-multi-wnrmrpjt succeeded in 17ms:
[codex:84920] 0000: PUSH1 0x60
[codex:84920] 0002: PUSH1 0x40
[codex:84920] 0004: MSTORE
[codex:84920] 0005: PUSH1 0xe0
[codex:84920] 0007: PUSH1 0x02
[codex:84920] 0009: EXP
[codex:84920] 000a: PUSH1 0x00
[codex:84920] 000c: CALLDATALOAD
[codex:84920] 000d: DIV
[codex:84920] 000e: PUSH4 0x6b8357ac
[codex:84920] 0013: DUP2
[codex:84920] 0014: EQ
[codex:84920] 0015: PUSH1 0x1a
[codex:84920] 0017: JUMPI
[codex:84920] 0018: JUMPDEST
[codex:84920] 0019: STOP
[codex:84920] 001a: JUMPDEST
[codex:84920] 001b: PUSH1 0xc8
[codex:84920] 001d: PUSH1 0x04
[codex:84920] 001f: CALLDATALOAD
[codex:84920] 
[codex:84920] 
[codex:84920] thinking
[codex:84920] **Analyzing function selector and control flow**
[codex:84920] thinking
[codex:84920] **Planning symbolic stack simulation**
[codex:84920] 
[codex:84920] I’m thinking about writing a simple symbolic EVM interpreter to track the stack precisely through the not-owner branch and verify the actual JUMP target, helping me confirm if owner check can be bypassed. This approach should clear up any ambiguity around stack state and jump destinations.
[codex:84920] exec
[codex:84920] /bin/bash -lc "python - <<'PY'
[codex:84920] bytecode='606060405260e060020a60003504636b8357ac8114601a575b005b60c86004356024356000805481903373ffffffffffffffffffffffffffffffffffffffff9081169116141560c1575080547fa9059cbb00000000000000000000000000000000000000000000000000000000606090815273ffffffffffffffffffffffffffffffffffffffff9182166064526084849052849182169063a9059cbb9060a49060209060448188876161da5a03f11560025750506040515115905060c1578291505b5092915050565b60408051918252519081900360200190f3'
[codex:84920] 
[codex:84920] b=bytes.fromhex(bytecode)
[codex:84920] 
[codex:84920] # build opcode list
[codex:84920] ops={
[codex:84920] 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:84920] 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:84920] 0x20:'SHA3',0x30:'ADDRESS',0x31:'BALANCE',0x32:'ORIGIN',0x33:'CALLER',0x34:'CALLVALUE',0x35:'CALLDATALOAD',0x36:'CALLDATASIZE',0x37:'CALLDATACOPY',0x38:'CODESIZE',0x39:'CODECOPY',0x3a:'GASPRICE',0x3b:'EXTCODESIZE',0x3c:'EXTCODECOPY',0x3d:'RETURNDATASIZE',0x3e:'RETURNDATACOPY',0x3f:'EXTCODEHASH',
[codex:84920] 0x40:'BLOCKHASH',0x41:'COINBASE',0x42:'TIMESTAMP',0x43:'NUMBER',0x44:'DIFFICULTY',0x45:'GASLIMIT',0x46:'CHAINID',0x47:'SELFBALANCE',0x48:'BASEFEE',
[codex:84920] 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:84920] 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:84920] 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:84920] 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:84920] 0xf0:'CREATE',0xf1:'CALL',0xf2:'CALLCODE',0xf3:'RETURN',0xf4:'DELEGATECALL',0xf5:'CREATE2',0xfa:'STATICCALL',0xfd:'REVERT',0xfe:'INVALID',0xff:'SELFDESTRUCT'
[codex:84920] }
[codex:84920] 
[codex:84920] # disasm list with pc
[codex:84920] inst=[]
[codex:84920] pc=0
[codex:84920] while pc<len(b):
[codex:84920]     op=b[pc]
[codex:84920]     name=ops.get(op,f'OP{op:02x}')
[codex:84920]     if 0x60<=op<=0x7f:
[codex:84920]         n=op-0x5f
[codex:84920]         data=b[pc+1:pc+1+n]
[codex:84920]         inst.append((pc,name,int.from_bytes(data,'big'),n))
[codex:84920]         pc+=1+n
[codex:84920]     else:
[codex:84920]         inst.append((pc,name,None,0))
[codex:84920]         pc+=1
[codex:84920] 
[codex:84920] # map pc to index
[codex:84920] idx={pc:i for i,(pc,_,_,_) in enumerate(inst)}
[codex:84920] 
[codex:84920] # simulate until pc 0xc7 for not-owner branch
[codex:84920] stack=[]
[codex:84920] 
[codex:84920] # helper to push symbol
[codex:84920] 
[codex:84920] def push(x):
[codex:84920]     stack.append(x)
[codex:84920] 
[codex:84920] def pop():
[codex:84920]     return stack.pop()
[codex:84920] 
[codex:84920] # symbolic inputs
[codex:84920] symbol_map={'CALLER':'caller','SLOAD0':'slot0','ARG1':'arg1','ARG2':'arg2','SEL':'sel'}
[codex:84920] 
[codex:84920] pc=0
[codex:84920] 
[codex:84920] # We'll override JUMPI for equality check at 0x48 to jump (not owner)
[codex:84920] # and for others, just follow fallthrough unless specified.
[codex:84920] 
[codex:84920] step=0
[codex:84920] while True:
[codex:84920]     if pc not in idx:
[codex:84920]         print('pc not found',pc)
[codex:84920]         break
[codex:84920]     i=idx[pc]
[codex:84920]     (pc,op,val,n)=inst[i]
[codex:84920]     # print state
[codex:84920]     #print(f'{pc:04x} {op} {val if val is not None else \"\"} stack={stack}')
[codex:84920]     if pc==0x1a:
[codex:84920]         # start tracking from here
[codex:84920]         pass
[codex:84920]     if op.startswith('PUSH'):
[codex:84920]         push(val)
[codex:84920]         pc=inst[i+1][0]
[codex:84920]     elif op=='CALLDATALOAD':
[codex:84920]         off=pop()
[codex:84920]         if off==0x04:
[codex:84920]             push('arg1')
[codex:84920]         elif off==0x24:
[codex:84920]             push('arg2')
[codex:84920]         else:
[codex:84920]             push(f'calldata@{off}')
[codex:84920]         pc=inst[i+1][0]
[codex:84920]     elif op=='CALLER':
[codex:84920]         push('caller')
[codex:84920]         pc=inst[i+1][0]
[codex:84920]     elif op=='SLOAD':
[codex:84920]         slot=pop()
[codex:84920]         push('slot0' if slot==0 else f'slot{slot}')
[codex:84920]         pc=inst[i+1][0]
[codex:84920]     elif op=='DUP1':
[codex:84920]         push(stack[-1])
[codex:84920]         pc=inst[i+1][0]
[codex:84920]     elif op=='DUP2':
[codex:84920]         push(stack[-2])
[codex:84920]         pc=inst[i+1][0]
[codex:84920]     elif op=='DUP3':
[codex:84920]         push(stack[-3])
[codex:84920]         pc=inst[i+1][0]
[codex:84920]     elif op=='DUP4':
[codex:84920]         push(stack[-4])
[codex:84920]         pc=inst[i+1][0]
[codex:84920]     elif op=='DUP5':
[codex:84920]         push(stack[-5])
[codex:84920]         pc=inst[i+1][0]
[codex:84920]     elif op=='DUP8':
[codex:84920]         push(stack[-8])
[codex:84920]         pc=inst[i+1][0]
[codex:84920]     elif op=='DUP9':
[codex:84920]         push(stack[-9])
[codex:84920]         pc=inst[i+1][0]
[codex:84920]     elif op=='SWAP1':
[codex:84920]         stack[-1],stack[-2]=stack[-2],stack[-1]
[codex:84920]         pc=inst[i+1][0]
[codex:84920]     elif op=='SWAP2':
[codex:84920]         stack[-1],stack[-3]=stack[-3],stack[-1]
[codex:84920]         pc=inst[i+1][0]
[codex:84920]     elif op=='SWAP3':
[codex:84920]         stack[-1],stack[-4]=stack[-4],stack[-1]
[codex:84920]         pc=inst[i+1][0]
[codex:84920]     elif op=='AND':
[codex:84920]         a=pop(); b=pop();
[codex:84920]         # symbolize
[codex:84920]         push(f'({a}&{b})')
[codex:84920]         pc=inst[i+1][0]
[codex:84920]     elif op=='EQ':
[codex:84920]         a=pop(); b=pop();
[codex:84920]         push(f'({a}=={b})')
[codex:84920]         pc=inst[i+1][0]
[codex:84920]     elif op=='ISZERO':
[codex:84920]         a=pop();
[codex:84920]         push(f'"'!{a}'"')
[codex:84920]         pc=inst[i+1][0]
[codex:84920]     elif op=='POP':
[codex:84920]         pop();
[codex:84920]         pc=inst[i+1][0]
[codex:84920]     elif op=='JUMPI':
[codex:84920]         dest=pop(); cond=pop();
[codex:84920]         # choose branch for owner check only
[codex:84920]         if pc==0x48:
[codex:84920]             # take jump (not owner)
[codex:84920]             pc=dest
[codex:84920]         else:
[codex:84920]             # default: fallthrough (not taking)
[codex:84920]             pc=inst[i+1][0]
[codex:84920]     elif op=='JUMP':
[codex:84920]         dest=pop();
[codex:84920]         print('JUMP dest',dest,'stack',stack)
[codex:84920]         break
[codex:84920]     elif op=='STOP':
[codex:84920]         print('STOP')
[codex:84920]         break
[codex:84920]     else:
[codex:84920]         # for other ops we don't care in this path
[codex:84920]         pc=inst[i+1][0]
[codex:84920]     step+=1
[codex:84920]     if step>200:
[codex:84920]         print('too many steps')
[codex:84920]         break
[codex:84920] PY" in /tmp/codex-multi-wnrmrpjt succeeded in 18ms:
[codex:84920] STOP
[codex:84920] 
[codex:84920] thinking
[codex:84920] **Analyzing program counter behavior**
[codex:84920] exec
[codex:84920] /bin/bash -lc "python - <<'PY'
[codex:84920] bytecode='606060405260e060020a60003504636b8357ac8114601a575b005b60c86004356024356000805481903373ffffffffffffffffffffffffffffffffffffffff9081169116141560c1575080547fa9059cbb00000000000000000000000000000000000000000000000000000000606090815273ffffffffffffffffffffffffffffffffffffffff9182166064526084849052849182169063a9059cbb9060a49060209060448188876161da5a03f11560025750506040515115905060c1578291505b5092915050565b60408051918252519081900360200190f3'
[codex:84920] 
[codex:84920] b=bytes.fromhex(bytecode)
[codex:84920] 
[codex:84920] ops={
[codex:84920] 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:84920] 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:84920] 0x20:'SHA3',0x30:'ADDRESS',0x31:'BALANCE',0x32:'ORIGIN',0x33:'CALLER',0x34:'CALLVALUE',0x35:'CALLDATALOAD',0x36:'CALLDATASIZE',0x37:'CALLDATACOPY',0x38:'CODESIZE',0x39:'CODECOPY',0x3a:'GASPRICE',0x3b:'EXTCODESIZE',0x3c:'EXTCODECOPY',0x3d:'RETURNDATASIZE',0x3e:'RETURNDATACOPY',0x3f:'EXTCODEHASH',
[codex:84920] 0x40:'BLOCKHASH',0x41:'COINBASE',0x42:'TIMESTAMP',0x43:'NUMBER',0x44:'DIFFICULTY',0x45:'GASLIMIT',0x46:'CHAINID',0x47:'SELFBALANCE',0x48:'BASEFEE',
[codex:84920] 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:84920] 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:84920] 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:84920] 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:84920] 0xf0:'CREATE',0xf1:'CALL',0xf2:'CALLCODE',0xf3:'RETURN',0xf4:'DELEGATECALL',0xf5:'CREATE2',0xfa:'STATICCALL',0xfd:'REVERT',0xfe:'INVALID',0xff:'SELFDESTRUCT'
[codex:84920] }
[codex:84920] 
[codex:84920] # disasm list with pc
[codex:84920] inst=[]
[codex:84920] pc=0
[codex:84920] while pc<len(b):
[codex:84920]     op=b[pc]
[codex:84920]     name=ops.get(op,f'OP{op:02x}')
[codex:84920]     if 0x60<=op<=0x7f:
[codex:84920]         n=op-0x5f
[codex:84920]         data=b[pc+1:pc+1+n]
[codex:84920]         inst.append((pc,name,int.from_bytes(data,'big'),n))
[codex:84920]         pc+=1+n
[codex:84920]     else:
[codex:84920]         inst.append((pc,name,None,0))
[codex:84920]         pc+=1
[codex:84920] idx={pc:i for i,(pc,_,_,_) in enumerate(inst)}
[codex:84920] 
[codex:84920] stack=['sel']
[codex:84920] pc=0x1a
[codex:84920] step=0
[codex:84920] while True:
[codex:84920]     if pc not in idx:
[codex:84920]         print('pc not found',pc)
[codex:84920]         break
[codex:84920]     i=idx[pc]
[codex:84920]     (pc,op,val,n)=inst[i]
[codex:84920]     # print(f'{pc:04x} {op} {val if val is not None else \"\"} stack={stack}')
[codex:84920]     if op.startswith('PUSH'):
[codex:84920]         stack.append(val)
[codex:84920]         pc=inst[i+1][0]
[codex:84920]     elif op=='CALLDATALOAD':
[codex:84920]         off=stack.pop()
[codex:84920]         if off==0x04:
[codex:84920]             stack.append('arg1')
[codex:84920]         elif off==0x24:
[codex:84920]             stack.append('arg2')
[codex:84920]         else:
[codex:84920]             stack.append(f'calldata@{off}')
[codex:84920]         pc=inst[i+1][0]
[codex:84920]     elif op=='CALLER':
[codex:84920]         stack.append('caller')
[codex:84920]         pc=inst[i+1][0]
[codex:84920]     elif op=='SLOAD':
[codex:84920]         slot=stack.pop()
[codex:84920]         stack.append('slot0' if slot==0 else f'slot{slot}')
[codex:84920]         pc=inst[i+1][0]
[codex:84920]     elif op.startswith('DUP'):
[codex:84920]         n=int(op[3:])
[codex:84920]         stack.append(stack[-n])
[codex:84920]         pc=inst[i+1][0]
[codex:84920]     elif op.startswith('SWAP'):
[codex:84920]         n=int(op[4:])
[codex:84920]         stack[-1],stack[-1-n]=stack[-1-n],stack[-1]
[codex:84920]         pc=inst[i+1][0]
[codex:84920]     elif op=='AND':
[codex:84920]         a=stack.pop(); b=stack.pop();
[codex:84920]         stack.append(f'({a}&{b})')
[codex:84920]         pc=inst[i+1][0]
[codex:84920]     elif op=='EQ':
[codex:84920]         a=stack.pop(); b=stack.pop();
[codex:84920]         stack.append(f'({a}=={b})')
[codex:84920]         pc=inst[i+1][0]
[codex:84920]     elif op=='ISZERO':
[codex:84920]         a=stack.pop(); stack.append(f'"'!{a}'"'); pc=inst[i+1][0]
[codex:84920]     elif op=='POP':
[codex:84920]         stack.pop(); pc=inst[i+1][0]
[codex:84920]     elif op=='JUMPI':
[codex:84920]         dest=stack.pop(); cond=stack.pop();
[codex:84920]         if pc==0x48:
[codex:84920]             # take non-owner branch
[codex:84920]             pc=dest
[codex:84920]         else:
[codex:84920]             pc=inst[i+1][0]
[codex:84920]     elif op=='JUMP':
[codex:84920]         dest=stack.pop();
[codex:84920]         print('JUMP dest',dest)
[codex:84920]         print('stack after pop',stack)
[codex:84920]         break
[codex:84920]     else:
[codex:84920]         # ignore
[codex:84920]         pc=inst[i+1][0]
[codex:84920]     step+=1
[codex:84920]     if step>200:
[codex:84920]         print('too many steps')
[codex:84920]         break
[codex:84920] PY" in /tmp/codex-multi-wnrmrpjt succeeded in 19ms:
[codex:84920] JUMP dest 200
[codex:84920] stack after pop ['sel', 0]
[codex:84920] 
[codex:84920] thinking
[codex:84920] **Verifying control flow and vulnerabilities**
[codex:84920] exec
[codex:84920] /bin/bash -lc 'cat codex-output-schema.json' in /tmp/codex-multi-wnrmrpjt succeeded in 5ms:
[codex:84920] {"type": "object", "additionalProperties": false, "required": ["no_findings", "summary", "findings"], "properties": {"no_findings": {"type": "boolean"}, "summary": {"type": "string"}, "findings": {"type": "array", "items": {"type": "object", "additionalProperties": false, "required": ["severity", "category", "title", "evidence", "locations", "exploit_scenario", "recommendation"], "properties": {"severity": {"type": "string", "enum": ["info", "low", "medium", "high", "critical"]}, "category": {"type": "string", "enum": ["access_control", "reentrancy", "math", "oracle", "upgradeability", "auth", "other"]}, "title": {"type": "string"}, "exploit_scenario": {"type": "string"}, "recommendation": {"type": "string"}, "evidence": {"type": "string"}, "locations": {"type": "array", "items": {"type": "string"}}}}}}}
[codex:84920] 
[codex:84920] thinking
[codex:84920] **Preparing JSON output**
[codex:84920] codex
[codex:84920] {"no_findings":true,"summary":"No concrete, exploitable profit path identified from the provided runtime bytecode; the only external call appears owner-gated and transfers tokens to the stored owner address.","findings":[]}
[codex:84920] tokens used
[codex:84920] 33,953
[codex:84920] {"no_findings":true,"summary":"No concrete, exploitable profit path identified from the provided runtime bytecode; the only external call appears owner-gated and transfers tokens to the stored owner address.","findings":[]}
Metadata
{
    "codex": {
        "ran_at": "2026-01-03T21:41:43.968351+00:00",
        "returncode": 0
    },
    "summary": "No concrete, exploitable profit path identified from the provided runtime bytecode; the only external call appears owner-gated and transfers tokens to the stored owner address.",
    "raw_final": {
        "summary": "No concrete, exploitable profit path identified from the provided runtime bytecode; the only external call appears owner-gated and transfers tokens to the stored owner address.",
        "findings": [],
        "no_findings": true
    },
    "no_findings": true,
    "schema_version": 1
}

Opcode Heuristics

tool.cast_disasm
Delegatecall
0
Selfdestruct
0
CREATE2
0
CALL-family (heavy)
1
EXT*/BALANCE
0
Total opcodes
114
Flags
No heuristic flags raised.
View cast disassembly output
00000000: PUSH1 0x60
00000002: PUSH1 0x40
00000004: MSTORE
00000005: PUSH1 0xe0
00000007: PUSH1 0x02
00000009: EXP
0000000a: PUSH1 0x00
0000000c: CALLDATALOAD
0000000d: DIV
0000000e: PUSH4 0x6b8357ac
00000013: DUP2
00000014: EQ
00000015: PUSH1 0x1a
00000017: JUMPI
00000018: JUMPDEST
00000019: STOP
0000001a: JUMPDEST
0000001b: PUSH1 0xc8
0000001d: PUSH1 0x04
0000001f: CALLDATALOAD
00000020: PUSH1 0x24
00000022: CALLDATALOAD
00000023: PUSH1 0x00
00000025: DUP1
00000026: SLOAD
00000027: DUP2
00000028: SWAP1
00000029: CALLER
0000002a: PUSH20 0xffffffffffffffffffffffffffffffffffffffff
0000003f: SWAP1
00000040: DUP2
00000041: AND
00000042: SWAP2
00000043: AND
00000044: EQ
00000045: ISZERO
00000046: PUSH1 0xc1
00000048: JUMPI
00000049: POP
0000004a: DUP1
0000004b: SLOAD
0000004c: PUSH32 0xa9059cbb00000000000000000000000000000000000000000000000000000000
0000006d: PUSH1 0x60
0000006f: SWAP1
00000070: DUP2
00000071: MSTORE
00000072: PUSH20 0xffffffffffffffffffffffffffffffffffffffff
00000087: SWAP2
00000088: DUP3
00000089: AND
0000008a: PUSH1 0x64
0000008c: MSTORE
0000008d: PUSH1 0x84
0000008f: DUP5
00000090: SWAP1
00000091: MSTORE
00000092: DUP5
00000093: SWAP2
00000094: DUP3
00000095: AND
00000096: SWAP1
00000097: PUSH4 0xa9059cbb
0000009c: SWAP1
0000009d: PUSH1 0xa4
0000009f: SWAP1
000000a0: PUSH1 0x20
000000a2: SWAP1
000000a3: PUSH1 0x44
000000a5: DUP2
000000a6: DUP9
000000a7: DUP8
000000a8: PUSH2 0x61da
000000ab: GAS
000000ac: SUB
000000ad: CALL
000000ae: ISZERO
000000af: PUSH1 0x02
000000b1: JUMPI
000000b2: POP
000000b3: POP
000000b4: PUSH1 0x40
000000b6: MLOAD
000000b7: MLOAD
000000b8: ISZERO
000000b9: SWAP1
000000ba: POP
000000bb: PUSH1 0xc1
000000bd: JUMPI
000000be: DUP3
000000bf: SWAP2
000000c0: POP
000000c1: JUMPDEST
000000c2: POP
000000c3: SWAP3
000000c4: SWAP2
000000c5: POP
000000c6: POP
000000c7: JUMP
000000c8: JUMPDEST
000000c9: PUSH1 0x40
000000cb: DUP1
000000cc: MLOAD
000000cd: SWAP2
000000ce: DUP3
000000cf: MSTORE
000000d0: MLOAD
000000d1: SWAP1
000000d2: DUP2
000000d3: SWAP1
000000d4: SUB
000000d5: PUSH1 0x20
000000d7: ADD
000000d8: SWAP1
000000d9: RETURN

Findings

validated = confirmed for call sinks; sink observed for others
Severity Category Tool Title Confidence Validated Confirmed Details
high other detector Untrusted CALL target/value reachable 60 no no
view
trace_id: 0xe874d85040e66e84cc3ea15572799403c996259f1ff32bc578eea747df3336a8
call_targets: 0xa0589b980cb3c2e153b7ac7dc7c01c2223d7c5d7
target_varies: no
classification: constant_target
validation_json
{
    "sink": "CALL",
    "errors": 0,
    "status": "sink_reached",
    "attempts": 1,
    "trace_id": "0xe874d85040e66e84cc3ea15572799403c996259f1ff32bc578eea747df3336a8",
    "confirmed": false,
    "trace_mode": "callTracer",
    "call_targets": [
        "0xa0589b980cb3c2e153b7ac7dc7c01c2223d7c5d7"
    ],
    "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": "0x6b8357ac",
            "selector": "0x6b8357ac",
            "calldata_variants": [
                "0x6b8357ac",
                "0x6b8357ac0000000000000000000000000000000000000000000000000000000000000000"
            ]
        }
    ]
}
evidence_json
{
    "examples": [
        {
            "pc": 173,
            "opcode": "CALL",
            "returndata_checked": null,
            "value_expression_category": "computed",
            "target_expression_category": "computed"
        }
    ],
    "call_count": 1,
    "guards_detected": [],
    "untrusted_call_count": 1
}
high other detector ETH value transfer possible 55 no no
view
trace_id: 0xe874d85040e66e84cc3ea15572799403c996259f1ff32bc578eea747df3336a8
call_targets: 0xa0589b980cb3c2e153b7ac7dc7c01c2223d7c5d7
target_varies: no
classification: constant_target
validation_json
{
    "sink": "CALL",
    "errors": 0,
    "status": "sink_reached",
    "attempts": 1,
    "trace_id": "0xe874d85040e66e84cc3ea15572799403c996259f1ff32bc578eea747df3336a8",
    "confirmed": false,
    "trace_mode": "callTracer",
    "call_targets": [
        "0xa0589b980cb3c2e153b7ac7dc7c01c2223d7c5d7"
    ],
    "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": "0x6b8357ac",
            "selector": "0x6b8357ac",
            "calldata_variants": [
                "0x6b8357ac",
                "0x6b8357ac0000000000000000000000000000000000000000000000000000000000000000"
            ]
        }
    ]
}
evidence_json
{
    "examples": [
        {
            "pc": 173,
            "opcode": "CALL",
            "returndata_checked": null,
            "value_expression_category": "computed",
            "target_expression_category": "computed"
        }
    ],
    "eth_value_calls": 1,
    "guards_detected": []
}