019b3836-22a9-708c-9e79-2665fbe783ab
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 |
|---|---|---|---|---|
| 333 | artifact.fetch | complete | 1 / 3 | 3 months ago |
| 334 | tool.cast_disasm | complete | 1 / 3 | 3 months ago |
| 43495 | analysis.bundle | complete | 1 / 3 | 1 week ago |
| 43496 | capability.graph | complete | 1 / 3 | 1 week ago |
| 43497 | detector.run | complete | 1 / 3 | 1 week ago |
| 43498 | validation.fork | complete | 1 / 3 | 1 week ago |
| 82459 | report.consolidate | complete | 1 / 6 | 1 week ago |
No slither job recorded yet.
{"no_findings":false,"summary":"Fallback-only bytecode with three ETH-bearing CALL sites, no detected auth guards, and state cleanup that occurs after external payouts. The strongest issue is reentrancy risk on the payout path; a secondary issue is unchecked CALL success on all outbound transfers.","findings":[{"severity":"high","category":"reentrancy","title":"External payout calls occur before round state is cleared","exploit_scenario":"A prior participant can register a contract as one of the payout recipients via the fallback update path. When the expiry/payout branch executes, the contract performs value-bearing CALLs to stored recipient addresses at pc 0x6d and pc 0xac before clearing slot 2 and before wiping the recipient fields in slots 0/1. A malicious recipient can reenter the fallback during the first payout while the old state is still live, potentially triggering the payout logic repeatedly and draining more of the contract balance than intended. This is based on bytecode-only reasoning, so the exact branch condition is inferred rather than source-confirmed.","recommendation":"Apply checks-effects-interactions: fully clear or checkpoint the active round before any external CALL, or add an explicit reentrancy guard around the fallback payout path. If payouts must remain external, store owed balances and let recipients withdraw in a separate pull-payment flow.","evidence":"The artifact reports no detected guards (`auth.guards=[]`) and three CALL sites. The first two CALLs are at pc 109/0x6d and 172/0xac, both with `returndata_checked: null` and computed targets/values. State-reset writes happen only afterward at pc 185/0xb9 (slot 2), pc 215-216/0xd7-0xd8 and pc 224/0xe0 (slot 0/1 cleanup), and pc 236/0xec (slot 3 reset). Recipient addresses appear user-influenced because the fallback update routine writes slots 1 and 0 at pc 334/0x14e and pc 339/0x153. Detector finding `Untrusted CALL target/value reachable` is validated/confirmed.","locations":["pc:0x6d","pc:0xac","pc:0xb9","pc:0xd7","pc:0xe0","pc:0xec","pc:0x14e","pc:0x153"]},{"severity":"medium","category":"other","title":"Outbound ETH transfers ignore CALL success and continue","exploit_scenario":"If a payout recipient or refund recipient is a contract that reverts or otherwise makes the CALL fail, this bytecode does not check the returned success flag before continuing. On the payout path, the contract appears to proceed into state cleanup and round reset even when one or both payouts fail, which can skip owed payments and strand funds in the contract. On the refund-like path at pc 0x112, a failed ETH send to `CALLER` is also ignored.","recommendation":"Check the boolean result of each CALL and revert on failure, or convert the design to pull-based withdrawals so failed recipients cannot silently break accounting. If non-reverting behavior is required, record failed payouts as claimable balances instead of discarding the failure.","evidence":"All three callsites in the bundle have `returndata_checked: null`: pc 109/0x6d, 172/0xac, and 274/0x112. In the bytecode, each CALL is followed by POPs rather than a conditional revert path, so success is discarded. After the payout CALLs, execution continues into storage writes that clear/reset state (pc 0xb9, 0xd7, 0xe0, 0xec), which creates accounting risk if the transfer did not actually occur. Detector finding `ETH value transfer possible` is validated/confirmed.","locations":["pc:0x6d","pc:0xac","pc:0x112","pc:0xb9","pc:0xd7","pc:0xe0","pc:0xec"]}]}
OpenAI Codex v0.118.0 (research preview)
--------
workdir: /tmp/codex-33obuzoq
model: gpt-5.4
provider: openai
approval: never
sandbox: read-only
reasoning effort: high
reasoning summaries: none
session id: 019d5a82-7c39-78d1-929f-b2b094cb360f
--------
user
You are a security auditor. You ONLY have runtime bytecode + analysis artifacts.
You MUST read `BYTECODE_BUNDLE.json` before concluding; it contains the bytecode summary,
evidence bundle, callsites, storage slots, and detector findings.
Special cases when reasoning from bytecode (be explicit about uncertainty):
- Selector inference is best-effort; missing selectors are common.
- Fallback/receive paths may be the only entrypoints.
- CALL vs DELEGATECALL semantics differ; DELEGATECALL executes in caller storage.
- Proxy patterns (EIP-1967, minimal proxies, beacon) change which storage is authoritative.
- Storage slots are raw; mappings/arrays appear via keccak patterns, names are unknown.
- Guard detection is heuristic; absence of guards does NOT mean unguarded.
- Returndata checking is unknown unless explicitly shown in evidence.
- Precompiles (0x1..0x9) and common ERC20 transfer selectors may appear; do not over-claim.
Output MUST be valid JSON matching the provided schema.
- If you find nothing meaningful: set no_findings=true and findings=[].
- Otherwise: set no_findings=false and include findings with severity/category/title.
- Locations can be pc references like "pc:0x123" or selectors like "selector:0xa9059cbb".
Focus on: reentrancy, access control, upgradeability/proxy issues, signature validation,
accounting/invariant breaks, dangerous delegatecall, and untrusted external calls.
Be conservative: if evidence is weak, mark severity low/medium and explain why.
warning: Codex could not find system bubblewrap on PATH. Please install bubblewrap with your package manager. Codex will use the vendored bubblewrap in the meantime.
exec
/bin/bash -lc pwd in /tmp/codex-33obuzoq
succeeded in 0ms:
/tmp/codex-33obuzoq
exec
/bin/bash -lc 'rg --files' in /tmp/codex-33obuzoq
succeeded in 0ms:
codex-output-schema.json
BYTECODE_BUNDLE.json
exec
/bin/bash -lc "sed -n '1,260p' BYTECODE_BUNDLE.json" in /tmp/codex-33obuzoq
succeeded in 0ms:
{
"analysis_artifact": {
"address": "0xfc67bd301a4c698b461e5e9f26eab60d230b77a4",
"artifact_hash": "0x348ffa907b2a18715048f8e58e317370432ac5ba602ba11ec2617eb1f507f9a5",
"artifact_json": {
"auth": {
"guards": []
},
"basic_blocks": [
{
"end_pc": 10,
"hash": "0xac0bdec5d70ac003da16146b40dd072a1529c7207bdb7c1e984cda39da7e0897",
"opcodes": [
"PUSH1",
"PUSH1",
"MSTORE",
"CALLDATASIZE",
"ISZERO",
"PUSH2",
"JUMPI"
],
"start_pc": 0
},
{
"end_pc": 31,
"hash": "0x9eb4aa0f520a79a3f5e316d1e94ceb7c2c096c022b44d74b6e1fdcd385b4166d",
"opcodes": [
"JUMPDEST",
"PUSH2",
"PUSH1",
"PUSH1",
"PUSH1",
"PUSH1",
"POP",
"SLOAD",
"GT",
"OP_80",
"ISZERO",
"PUSH2",
"JUMPI"
],
"start_pc": 11
},
{
"end_pc": 45,
"hash": "0x4b7468393bef1fc83071421d9f2df99457d9e3e5559bc21ff386d2023e45d0d4",
"opcodes": [
"POP",
"PUSH3",
"PUSH1",
"PUSH1",
"POP",
"SLOAD",
"TIMESTAMP",
"SUB",
"GT"
],
"start_pc": 32
},
{
"end_pc": 51,
"hash": "0xdfe96000889c110656da416ef3ae7d6f29671d0b93bc0f7f8baa61c5239e6b6d",
"opcodes": [
"JUMPDEST",
"ISZERO",
"PUSH2",
"JUMPI"
],
"start_pc": 46
},
{
"end_pc": 78,
"hash": "0xab22199b4d1941b724675f0ddad6aba2c2a017c5226af710ac2504285c6a934d",
"opcodes": [
"OP_80",
"SLOAD",
"CALLVALUE",
"PUSH1",
"PUSH1",
"PUSH1",
"EXP",
"SUB",
"ADDRESS",
"OP_81",
"AND",
"BALANCE",
"OP_91",
"OP_90",
"OP_91",
"SUB",
"OP_92",
"OP_91",
"AND",
"EQ",
"PUSH2",
"JUMPI"
],
"start_pc": 52
},
{
"end_pc": 114,
"hash": "0x5e4abfbbf72adceeda93577a57e79dc20e8c248cbd5b9fa138b054859687a421",
"opcodes": [
"PUSH1",
"OP_80",
"SLOAD",
"PUSH1",
"PUSH1",
"PUSH1",
"EXP",
"SUB",
"AND",
"OP_90",
"PUSH1",
"PUSH1",
"OP_84",
"MUL",
"DIV",
"PUSH1",
"OP_82",
"OP_81",
"OP_81",
"OP_81",
"OP_85",
"OP_88",
"OP_83",
"CALL",
"POP",
"POP",
"POP",
"POP",
"POP"
],
"start_pc": 79
},
{
"end_pc": 134,
"hash": "0x498a9a43a5498ab53607e59da45dbd714d8e898df7a294735c2b11593c39058f",
"opcodes": [
"JUMPDEST",
"PUSH1",
"SLOAD",
"PUSH1",
"PUSH1",
"PUSH1",
"EXP",
"SUB",
"AND",
"PUSH1",
"EQ",
"PUSH2",
"JUMPI"
],
"start_pc": 115
},
{
"end_pc": 177,
"hash": "0xda7b2e64112f3e307dfb8bbe6aa2f879c32a9ff0854aaed2e08307d041ccc677",
"opcodes": [
"PUSH1",
"SLOAD",
"PUSH1",
"MLOAD",
"PUSH1",
"PUSH1",
"PUSH1",
"EXP",
"SUB",
"OP_91",
"OP_90",
"OP_91",
"AND",
"OP_90",
"PUSH1",
"OP_90",
"PUSH1",
"PUSH1",
"OP_85",
"MUL",
"DIV",
"OP_90",
"OP_82",
"OP_81",
"OP_81",
"OP_81",
"OP_85",
"OP_88",
"OP_83",
"CALL",
"POP",
"POP",
"POP",
"POP",
"POP"
],
"start_pc": 135
},
{
"end_pc": 236,
"hash": "0x2b424cad0b3eeeed88643f2db571b92b910affac2114c8b69f4e4772e3a096a0",
"opcodes": [
"JUMPDEST",
"PUSH1",
"PUSH1",
"OP_81",
"OP_90",
"SSTORE",
"OP_80",
"SLOAD",
"PUSH20",
"NOT",
"OP_90",
"OP_81",
"AND",
"OP_90",
"OP_91",
"SSTORE",
"PUSH1",
"OP_80",
"SLOAD",
"OP_90",
"OP_91",
"AND",
"OP_90",
"SSTORE",
"PUSH8",
"PUSH1",
"SSTORE"
],
"start_pc": 178
},
{
"end_pc": 247,
"hash": "0x8af0acf29c292bf5a9ce46485cdd9a39f73d1bf0867eed51d979e0184dcfc8d0",
"opcodes": [
"JUMPDEST",
"PUSH1",
"SLOAD",
"CALLVALUE",
"LT",
"ISZERO",
"PUSH2",
"JUMPI"
],
"start_pc": 237
},
{
"end_pc": 284,
"hash": "0x809361b977fdc151985ad0b6dcc6edbe3840b841c3e026dc4d5bc711be9f08ca",
"opcodes": [
"PUSH1",
"MLOAD",
"CALLER",
"PUSH1",
"PUSH1",
"PUSH1",
"EXP",
"SUB",
"AND",
"OP_90",
exec
/bin/bash -lc "sed -n '261,520p' BYTECODE_BUNDLE.json" in /tmp/codex-33obuzoq
succeeded in 0ms:
"PUSH1",
"OP_90",
"CALLVALUE",
"OP_90",
"OP_82",
"OP_81",
"OP_81",
"OP_81",
"OP_85",
"OP_88",
"OP_83",
"CALL",
"OP_93",
"POP",
"POP",
"POP",
"POP",
"POP",
"PUSH2",
"JUMP"
],
"start_pc": 248
},
{
"end_pc": 286,
"hash": "0x9d1eb45248d1d499f3afcc0a801c2af0284d44907feaf3d11ea39dddd1e35a0e",
"opcodes": [
"JUMPDEST",
"STOP"
],
"start_pc": 285
},
{
"end_pc": 347,
"hash": "0xb0de7f3059f532f56a07da969a8904bda23682e0c10bc179ab577ab563eab121",
"opcodes": [
"JUMPDEST",
"PUSH1",
"OP_80",
"SLOAD",
"PUSH1",
"OP_80",
"SLOAD",
"PUSH20",
"NOT",
"OP_90",
"OP_81",
"AND",
"PUSH1",
"PUSH1",
"PUSH1",
"EXP",
"SUB",
"OP_84",
"AND",
"OR",
"OP_90",
"OP_91",
"SSTORE",
"AND",
"CALLER",
"OR",
"OP_90",
"SSTORE",
"CALLVALUE",
"PUSH1",
"SSTORE",
"TIMESTAMP",
"PUSH1",
"SSTORE"
],
"start_pc": 287
},
{
"end_pc": 350,
"hash": "0x3f2a62513986267f2204c579491db542e415c8fd39d211acc6a57cf2b8263f67",
"opcodes": [
"JUMPDEST",
"POP",
"JUMP"
],
"start_pc": 348
}
],
"callsites": [
{
"opcode": "CALL",
"pc": 109,
"returndata_checked": null,
"target_expression_category": "computed",
"value_expression_category": "computed"
},
{
"opcode": "CALL",
"pc": 172,
"returndata_checked": null,
"target_expression_category": "computed",
"value_expression_category": "computed"
},
{
"opcode": "CALL",
"pc": 274,
"returndata_checked": null,
"target_expression_category": "computed",
"value_expression_category": "computed"
}
],
"cfg_edges": [
{
"from": "bb:0",
"to": "bb:11",
"type": "control_flow"
},
{
"from": "bb:0",
"to": "bb:11",
"type": "control_flow_fallthrough"
},
{
"from": "bb:11",
"to": "bb:46",
"type": "control_flow"
},
{
"from": "bb:11",
"to": "bb:32",
"type": "control_flow_fallthrough"
},
{
"from": "bb:32",
"to": "bb:46",
"type": "control_flow_fallthrough"
},
{
"from": "bb:46",
"to": "bb:237",
"type": "control_flow"
},
{
"from": "bb:46",
"to": "bb:52",
"type": "control_flow_fallthrough"
},
{
"from": "bb:52",
"to": "bb:115",
"type": "control_flow"
},
{
"from": "bb:52",
"to": "bb:79",
"type": "control_flow_fallthrough"
},
{
"from": "bb:79",
"to": "bb:115",
"type": "control_flow_fallthrough"
},
{
"from": "bb:115",
"to": "bb:178",
"type": "control_flow"
},
{
"from": "bb:115",
"to": "bb:135",
"type": "control_flow_fallthrough"
},
{
"from": "bb:135",
"to": "bb:178",
"type": "control_flow_fallthrough"
},
{
"from": "bb:178",
"to": "bb:237",
"type": "control_flow_fallthrough"
},
{
"from": "bb:237",
"to": "bb:287",
"type": "control_flow"
},
{
"from": "bb:237",
"to": "bb:248",
"type": "control_flow_fallthrough"
},
{
"from": "bb:248",
"to": "bb:348",
"type": "control_flow"
},
{
"from": "bb:287",
"to": "bb:348",
"type": "control_flow_fallthrough"
}
],
"cfg_hash": "0x177b9ba39708b8831091738402bff1fa2eb63df16dd6c182093a332099aa04c4",
"dispatcher_type": "fallback_only",
"function_entries": [
{
"entry_pc": 0,
"selector": "fallback"
}
],
"functions": [
{
"auth": {
"guards": []
},
"entry_pc": 0,
"selector": "fallback",
"sinks": {
"call": 3,
"delegatecall": 0,
"selfdestruct": 0,
"staticcall": 0
},
"storage": {
"reads": 11,
"slots": [
{
"op": "SLOAD",
"pc": 24,
"slot": "0x0000000000000000000000000000000000000000000000000000000000000002"
},
{
"op": "SLOAD",
"pc": 42,
"slot": "0x0000000000000000000000000000000000000000000000000000000000000002"
},
{
"op": "SLOAD",
"pc": 82,
"slot": "0x0000000000000000000000000000000000000000000000000000000000000000"
},
{
"op": "SLOAD",
"pc": 118,
"slot": "0x0000000000000000000000000000000000000000000000000000000000000001"
},
{
"op": "SLOAD",
"pc": 137,
"slot": "0x0000000000000000000000000000000000000000000000000000000000000001"
},
{
"op": "SSTORE",
"pc": 185,
"slot": "0x0000000000000000000000000000000000000000000000000000000000000000"
},
{
"op": "SLOAD",
"pc": 219,
"slot": "0x0000000000000000000000000000000000000000000000000000000000000001"
},
{
"op": "SSTORE",
exec
/bin/bash -lc "sed -n '521,860p' BYTECODE_BUNDLE.json" in /tmp/codex-33obuzoq
succeeded in 0ms:
"pc": 236,
"slot": "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000"
},
{
"op": "SLOAD",
"pc": 240,
"slot": "0x0000000000000000000000000000000000000000000000000000000000000003"
},
{
"op": "SLOAD",
"pc": 291,
"slot": "0x0000000000000000000000000000000000000000000000000000000000000000"
},
{
"op": "SLOAD",
"pc": 295,
"slot": "0x0000000000000000000000000000000000000000000000000000000000000001"
}
],
"writes": 8
}
}
],
"selectors": [],
"sinks": {
"call": 3,
"create": 0,
"create2": 0,
"delegatecall": 0,
"selfdestruct": 0,
"staticcall": 0,
"upgrade_slot_write_suspected": false
},
"storage": {
"keccak_count": 0,
"reads": 11,
"slots": [
{
"op": "SLOAD",
"pc": 24,
"slot": "0x0000000000000000000000000000000000000000000000000000000000000002"
},
{
"op": "SLOAD",
"pc": 42,
"slot": "0x0000000000000000000000000000000000000000000000000000000000000002"
},
{
"op": "SLOAD",
"pc": 82,
"slot": "0x0000000000000000000000000000000000000000000000000000000000000000"
},
{
"op": "SLOAD",
"pc": 118,
"slot": "0x0000000000000000000000000000000000000000000000000000000000000001"
},
{
"op": "SLOAD",
"pc": 137,
"slot": "0x0000000000000000000000000000000000000000000000000000000000000001"
},
{
"op": "SSTORE",
"pc": 185,
"slot": "0x0000000000000000000000000000000000000000000000000000000000000000"
},
{
"op": "SLOAD",
"pc": 219,
"slot": "0x0000000000000000000000000000000000000000000000000000000000000001"
},
{
"op": "SSTORE",
"pc": 236,
"slot": "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000"
},
{
"op": "SLOAD",
"pc": 240,
"slot": "0x0000000000000000000000000000000000000000000000000000000000000003"
},
{
"op": "SLOAD",
"pc": 291,
"slot": "0x0000000000000000000000000000000000000000000000000000000000000000"
},
{
"op": "SLOAD",
"pc": 295,
"slot": "0x0000000000000000000000000000000000000000000000000000000000000001"
}
],
"writes": 8
},
"version": "analysis_artifact_v1"
},
"block_number": null,
"chain_id": 1,
"codehash": "0x699872161ac66ed2937791f59bb932297779c0b234052c08949f3bd2548c58e3",
"created_at": "2026-04-04T19:45:22.000000Z",
"id": 1535,
"updated_at": "2026-04-04T19:45:22.000000Z",
"version": "analysis_artifact_v1"
},
"analysis_run": {
"address": "0xfc67bd301a4c698b461e5e9f26eab60d230b77a4",
"block_number": null,
"chain_id": 1,
"child_links": [],
"created_at": "2025-12-19T20:03:50.000000Z",
"id": "019b3836-22a9-708c-9e79-2665fbe783ab",
"parent_links": [],
"status": "running",
"updated_at": "2026-04-04T19:45:22.000000Z"
},
"artifact": {
"codehash": "0x699872161ac66ed2937791f59bb932297779c0b234052c08949f3bd2548c58e3",
"compiler_json": {
"etherscan": {
"skipped": true
}
},
"implementation_address": null,
"is_proxy": false,
"runtime_bytecode": {
"full": "0x6060604052361561000b575b61011d6000600060026000505411801561002e5750620151806002600050544203115b156100ed57805434600160a060020a033081163191909103929116146100735760008054600160a060020a031690600a6006840204606082818181858883f150505050505b600154600160a060020a03166000146100b257600154604051600160a060020a039190911690600090600a60028502049082818181858883f150505050505b60006002819055805473ffffffffffffffffffffffffffffffffffffffff19908116909155600180549091169055670de0b6b3a76400006003555b60035434101561011f5760405133600160a060020a031690600090349082818181858883f193505050505061015c565b005b600080546001805473ffffffffffffffffffffffffffffffffffffffff19908116600160a060020a03841617909155163317905534600355426002555b5056",
"head": null,
"length": 704,
"tail": null,
"truncated": false
},
"verified_source": false
},
"capability_graph": {
"address": "0xfc67bd301a4c698b461e5e9f26eab60d230b77a4",
"block_number": null,
"chain_id": 1,
"codehash": "0x699872161ac66ed2937791f59bb932297779c0b234052c08949f3bd2548c58e3",
"created_at": "2026-04-04T19:45:22.000000Z",
"graph_hash": "0xacf5f16d36fe8363c25baaf31e30a4c0943a06e7e77227c13892aa2eb7c852d6",
"graph_json": {
"edges": [
{
"from": "bb:0",
"to": "bb:11",
"type": "control_flow"
},
{
"from": "bb:0",
"to": "bb:11",
"type": "control_flow_fallthrough"
},
{
"from": "bb:11",
"to": "bb:46",
"type": "control_flow"
},
{
"from": "bb:11",
"to": "bb:32",
"type": "control_flow_fallthrough"
},
{
"from": "bb:32",
"to": "bb:46",
"type": "control_flow_fallthrough"
},
{
"from": "bb:46",
"to": "bb:237",
"type": "control_flow"
},
{
"from": "bb:46",
"to": "bb:52",
"type": "control_flow_fallthrough"
},
{
"from": "bb:52",
"to": "bb:115",
"type": "control_flow"
},
{
"from": "bb:52",
"to": "bb:79",
"type": "control_flow_fallthrough"
},
{
"from": "bb:79",
"to": "bb:115",
"type": "control_flow_fallthrough"
},
{
"from": "bb:115",
"to": "bb:178",
"type": "control_flow"
},
{
"from": "bb:115",
"to": "bb:135",
"type": "control_flow_fallthrough"
},
{
"from": "bb:135",
"to": "bb:178",
"type": "control_flow_fallthrough"
},
{
"from": "bb:178",
"to": "bb:237",
"type": "control_flow_fallthrough"
},
{
"from": "bb:237",
"to": "bb:287",
"type": "control_flow"
},
{
"from": "bb:237",
"to": "bb:248",
"type": "control_flow_fallthrough"
},
{
"from": "bb:248",
"to": "bb:348",
"type": "control_flow"
},
{
"from": "bb:287",
"to": "bb:348",
"type": "control_flow_fallthrough"
},
{
"from": "fn:fallback",
"to": "bb:0",
"type": "entry"
},
{
"from": "bb:79",
"to": "call:109",
"type": "contains"
},
{
"from": "call:109",
"to": "sink:call",
"type": "capability"
},
{
"from": "bb:135",
"to": "call:172",
"type": "contains"
},
{
"from": "call:172",
"to": "sink:call",
"type": "capability"
},
{
"from": "bb:248",
"to": "call:274",
"type": "contains"
},
{
"from": "call:274",
"to": "sink:call",
"type": "capability"
}
],
"nodes": [
{
"end_pc": 10,
"hash": "0xac0bdec5d70ac003da16146b40dd072a1529c7207bdb7c1e984cda39da7e0897",
"id": "bb:0",
"start_pc": 0,
"type": "basic_block"
},
{
"end_pc": 31,
"hash": "0x9eb4aa0f520a79a3f5e316d1e94ceb7c2c096c022b44d74b6e1fdcd385b4166d",
"id": "bb:11",
"start_pc": 11,
"type": "basic_block"
},
{
"end_pc": 45,
"hash": "0x4b7468393bef1fc83071421d9f2df99457d9e3e5559bc21ff386d2023e45d0d4",
"id": "bb:32",
"start_pc": 32,
"type": "basic_block"
},
{
"end_pc": 51,
"hash": "0xdfe96000889c110656da416ef3ae7d6f29671d0b93bc0f7f8baa61c5239e6b6d",
"id": "bb:46",
"start_pc": 46,
"type": "basic_block"
},
{
"end_pc": 78,
"hash": "0xab22199b4d1941b724675f0ddad6aba2c2a017c5226af710ac2504285c6a934d",
"id": "bb:52",
"start_pc": 52,
"type": "basic_block"
},
{
"end_pc": 114,
"hash": "0x5e4abfbbf72adceeda93577a57e79dc20e8c248cbd5b9fa138b054859687a421",
"id": "bb:79",
"start_pc": 79,
"type": "basic_block"
},
{
"end_pc": 134,
"hash": "0x498a9a43a5498ab53607e59da45dbd714d8e898df7a294735c2b11593c39058f",
"id": "bb:115",
"start_pc": 115,
"type": "basic_block"
},
{
"end_pc": 177,
"hash": "0xda7b2e64112f3e307dfb8bbe6aa2f879c32a9ff0854aaed2e08307d041ccc677",
"id": "bb:135",
"start_pc": 135,
"type": "basic_block"
},
{
"end_pc": 236,
"hash": "0x2b424cad0b3eeeed88643f2db571b92b910affac2114c8b69f4e4772e3a096a0",
"id": "bb:178",
"start_pc": 178,
"type": "basic_block"
},
{
"end_pc": 247,
"hash": "0x8af0acf29c292bf5a9ce46485cdd9a39f73d1bf0867eed51d979e0184dcfc8d0",
"id": "bb:237",
"start_pc": 237,
"type": "basic_block"
},
exec
/bin/bash -lc "sed -n '861,1200p' BYTECODE_BUNDLE.json" in /tmp/codex-33obuzoq
succeeded in 0ms:
{
"end_pc": 284,
"hash": "0x809361b977fdc151985ad0b6dcc6edbe3840b841c3e026dc4d5bc711be9f08ca",
"id": "bb:248",
"start_pc": 248,
"type": "basic_block"
},
{
"end_pc": 286,
"hash": "0x9d1eb45248d1d499f3afcc0a801c2af0284d44907feaf3d11ea39dddd1e35a0e",
"id": "bb:285",
"start_pc": 285,
"type": "basic_block"
},
{
"end_pc": 347,
"hash": "0xb0de7f3059f532f56a07da969a8904bda23682e0c10bc179ab577ab563eab121",
"id": "bb:287",
"start_pc": 287,
"type": "basic_block"
},
{
"end_pc": 350,
"hash": "0x3f2a62513986267f2204c579491db542e415c8fd39d211acc6a57cf2b8263f67",
"id": "bb:348",
"start_pc": 348,
"type": "basic_block"
},
{
"id": "call:109",
"opcode": "CALL",
"pc": 109,
"type": "callsite"
},
{
"id": "call:172",
"opcode": "CALL",
"pc": 172,
"type": "callsite"
},
{
"id": "call:274",
"opcode": "CALL",
"pc": 274,
"type": "callsite"
},
{
"id": "sink:call",
"type": "sink"
},
{
"entry_pc": 0,
"id": "fn:fallback",
"selector": "fallback",
"type": "function"
}
],
"version": "capability_graph_v1"
},
"id": 1535,
"updated_at": "2026-04-04T19:45:22.000000Z",
"version": "capability_graph_v1"
},
"detector_findings": [
{
"confidence": 60,
"evidence_json": {
"call_count": 3,
"examples": [
{
"opcode": "CALL",
"pc": 109,
"returndata_checked": null,
"target_expression_category": "computed",
"value_expression_category": "computed"
},
{
"opcode": "CALL",
"pc": 172,
"returndata_checked": null,
"target_expression_category": "computed",
"value_expression_category": "computed"
},
{
"opcode": "CALL",
"pc": 274,
"returndata_checked": null,
"target_expression_category": "computed",
"value_expression_category": "computed"
}
],
"guards_detected": [],
"untrusted_call_count": 3
},
"normalized_json": {
"sink": "CALL"
},
"severity": "high",
"title": "Untrusted CALL target/value reachable",
"validated": true,
"validation_json": {
"attempts": 1,
"call_targets": [
"0x0000000000000000000000000000000000000001",
"0xfc67bd301a4c698b461e5e9f26eab60d230b77a4"
],
"classification": "target_varies",
"confirmed": true,
"errors": 0,
"matched_probe": null,
"sink": "CALL",
"status": "confirmed",
"target_varies": true,
"trace_id": "0xcec881074db4fc85d9d1a11d2957b033a783502954d378179861cb6ee186543a",
"trace_mode": "callTracer"
}
},
{
"confidence": 55,
"evidence_json": {
"eth_value_calls": 3,
"examples": [
{
"opcode": "CALL",
"pc": 109,
"returndata_checked": null,
"target_expression_category": "computed",
"value_expression_category": "computed"
},
{
"opcode": "CALL",
"pc": 172,
"returndata_checked": null,
"target_expression_category": "computed",
"value_expression_category": "computed"
},
{
"opcode": "CALL",
"pc": 274,
"returndata_checked": null,
"target_expression_category": "computed",
"value_expression_category": "computed"
}
],
"guards_detected": []
},
"normalized_json": {
"sink": "CALL",
"value": "nonzero"
},
"severity": "high",
"title": "ETH value transfer possible",
"validated": true,
"validation_json": {
"attempts": 1,
"call_targets": [
"0x0000000000000000000000000000000000000001",
"0xfc67bd301a4c698b461e5e9f26eab60d230b77a4"
],
"classification": "target_varies",
"confirmed": true,
"errors": 0,
"matched_probe": null,
"sink": "CALL",
"status": "confirmed",
"target_varies": true,
"trace_id": "0xcec881074db4fc85d9d1a11d2957b033a783502954d378179861cb6ee186543a",
"trace_mode": "callTracer"
}
}
],
"heuristics_summary": {
"create2_count": 0,
"delegatecall_count": 0,
"flags": [],
"selfdestruct_count": 0
}
}
exec
/bin/bash -lc 'cat codex-output-schema.json' in /tmp/codex-33obuzoq
succeeded in 0ms:
{"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"}}}}}}}
exec
/bin/bash -lc "node -e \"const b='6060604052361561000b575b61011d6000600060026000505411801561002e5750620151806002600050544203115b156100ed57805434600160a060020a033081163191909103929116146100735760008054600160a060020a031690600a6006840204606082818181858883f150505050505b600154600160a060020a03166000146100b257600154604051600160a060020a039190911690600090600a60028502049082818181858883f150505050505b60006002819055805473ffffffffffffffffffffffffffffffffffffffff19908116909155600180549091169055670de0b6b3a76400006003555b60035434101561011f5760405133600160a060020a031690600090349082818181858883f193505050505061015c565b005b600080546001805473ffffffffffffffffffffffffffffffffffffffff19908116600160a060020a03841617909155163317905534600355426002555b5056\"; console.log(b.length/2);\"" in /tmp/codex-33obuzoq
exited 2 in 0ms:
/bin/bash: -c: line 1: syntax error near unexpected token `b.length/2'
/bin/bash: -c: line 1: `node -e "const b='6060604052361561000b575b61011d6000600060026000505411801561002e5750620151806002600050544203115b156100ed57805434600160a060020a033081163191909103929116146100735760008054600160a060020a031690600a6006840204606082818181858883f150505050505b600154600160a060020a03166000146100b257600154604051600160a060020a039190911690600090600a60028502049082818181858883f150505050505b60006002819055805473ffffffffffffffffffffffffffffffffffffffff19908116909155600180549091169055670de0b6b3a76400006003555b60035434101561011f5760405133600160a060020a031690600090349082818181858883f193505050505061015c565b005b600080546001805473ffffffffffffffffffffffffffffffffffffffff19908116600160a060020a03841617909155163317905534600355426002555b5056"; console.log(b.length/2);"'
exec
/bin/bash -lc "python3 - <<'PY'
code='6060604052361561000b575b61011d6000600060026000505411801561002e5750620151806002600050544203115b156100ed57805434600160a060020a033081163191909103929116146100735760008054600160a060020a031690600a6006840204606082818181858883f150505050505b600154600160a060020a03166000146100b257600154604051600160a060020a039190911690600090600a60028502049082818181858883f150505050505b60006002819055805473ffffffffffffffffffffffffffffffffffffffff19908116909155600180549091169055670de0b6b3a76400006003555b60035434101561011f5760405133600160a060020a031690600090349082818181858883f193505050505061015c565b005b600080546001805473ffffffffffffffffffffffffffffffffffffffff19908116600160a060020a03841617909155163317905534600355426002555b5056'
ops={i:name for i,name in enumerate(['STOP','ADD','MUL','SUB','DIV','SDIV','MOD','SMOD','ADDMOD','MULMOD','EXP','SIGNEXTEND'])}
ops.update({0x10:'LT',0x11:'GT',0x12:'SLT',0x13:'SGT',0x14:'EQ',0x15:'ISZERO',0x16:'AND',0x17:'OR',0x18:'XOR',0x19:'NOT',0x1a:'BYTE',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',0x40:'BLOCKHASH',0x41:'COINBASE',0x42:'TIMESTAMP',0x43:'NUMBER',0x44:'DIFFICULTY',0x45:'GASLIMIT',0x50:'POP',0x51:'MLOAD',0x52:'MSTORE',0x53:'MSTORE8',0x54:'SLOAD',0x55:'SSTORE',0x56:'JUMP',0x57:'JUMPI',0x58:'PC',0x59:'MSIZE',0x5a:'GAS',0x5b:'JUMPDEST',0xf0:'CREATE',0xf1:'CALL',0xf2:'CALLCODE',0xf3:'RETURN',0xf4:'DELEGATECALL',0xf5:'CREATE2',0xfa:'STATICCALL',0xfd:'REVERT',0xfe:'INVALID',0xff:'SELFDESTRUCT'})
for i in range(1,33): ops[0x5f+i]=f'PUSH{i}'
for i in range(1,17): ops[0x7f+i]=f'DUP{i}'
for i in range(1,17): ops[0x8f+i]=f'SWAP{i}'
for i in range(0,5): ops[0xa0+i]=f'LOG{i}'
b=bytes.fromhex(code)
pc=0
while pc < len(b):
op=b[pc]
name=ops.get(op,hex(op))
if name.startswith('PUSH'):
n=int(name[4:])
data=b[pc+1:pc+1+n]
print(f'{pc:04x}: {name} 0x{data.hex()}')
pc+=1+n
else:
print(f'{pc:04x}: {name}')
pc+=1
PY" in /tmp/codex-33obuzoq
succeeded in 0ms:
0000: PUSH1 0x60
0002: PUSH1 0x40
0004: MSTORE
0005: CALLDATASIZE
0006: ISZERO
0007: PUSH2 0x000b
000a: JUMPI
000b: JUMPDEST
000c: PUSH2 0x011d
000f: PUSH1 0x00
0011: PUSH1 0x00
0013: PUSH1 0x02
0015: PUSH1 0x00
0017: POP
0018: SLOAD
0019: GT
001a: DUP1
001b: ISZERO
001c: PUSH2 0x002e
001f: JUMPI
0020: POP
0021: PUSH3 0x015180
0025: PUSH1 0x02
0027: PUSH1 0x00
0029: POP
002a: SLOAD
002b: TIMESTAMP
002c: SUB
002d: GT
002e: JUMPDEST
002f: ISZERO
0030: PUSH2 0x00ed
0033: JUMPI
0034: DUP1
0035: SLOAD
0036: CALLVALUE
0037: PUSH1 0x01
0039: PUSH1 0xa0
003b: PUSH1 0x02
003d: EXP
003e: SUB
003f: ADDRESS
0040: DUP2
0041: AND
0042: BALANCE
0043: SWAP2
0044: SWAP1
0045: SWAP2
0046: SUB
0047: SWAP3
0048: SWAP2
0049: AND
004a: EQ
004b: PUSH2 0x0073
004e: JUMPI
004f: PUSH1 0x00
0051: DUP1
0052: SLOAD
0053: PUSH1 0x01
0055: PUSH1 0xa0
0057: PUSH1 0x02
0059: EXP
005a: SUB
005b: AND
005c: SWAP1
005d: PUSH1 0x0a
005f: PUSH1 0x06
0061: DUP5
0062: MUL
0063: DIV
0064: PUSH1 0x60
0066: DUP3
0067: DUP2
0068: DUP2
0069: DUP2
006a: DUP6
006b: DUP9
006c: DUP4
006d: CALL
006e: POP
006f: POP
0070: POP
0071: POP
0072: POP
0073: JUMPDEST
0074: PUSH1 0x01
0076: SLOAD
0077: PUSH1 0x01
0079: PUSH1 0xa0
007b: PUSH1 0x02
007d: EXP
007e: SUB
007f: AND
0080: PUSH1 0x00
0082: EQ
0083: PUSH2 0x00b2
0086: JUMPI
0087: PUSH1 0x01
0089: SLOAD
008a: PUSH1 0x40
008c: MLOAD
008d: PUSH1 0x01
008f: PUSH1 0xa0
0091: PUSH1 0x02
0093: EXP
0094: SUB
0095: SWAP2
0096: SWAP1
0097: SWAP2
0098: AND
0099: SWAP1
009a: PUSH1 0x00
009c: SWAP1
009d: PUSH1 0x0a
009f: PUSH1 0x02
00a1: DUP6
00a2: MUL
00a3: DIV
00a4: SWAP1
00a5: DUP3
00a6: DUP2
00a7: DUP2
00a8: DUP2
00a9: DUP6
00aa: DUP9
00ab: DUP4
00ac: CALL
00ad: POP
00ae: POP
00af: POP
00b0: POP
00b1: POP
00b2: JUMPDEST
00b3: PUSH1 0x00
00b5: PUSH1 0x02
00b7: DUP2
00b8: SWAP1
00b9: SSTORE
00ba: DUP1
00bb: SLOAD
00bc: PUSH20 0xffffffffffffffffffffffffffffffffffffffff
00d1: NOT
00d2: SWAP1
00d3: DUP2
00d4: AND
00d5: SWAP1
00d6: SWAP2
00d7: SSTORE
00d8: PUSH1 0x01
00da: DUP1
00db: SLOAD
00dc: SWAP1
00dd: SWAP2
00de: AND
00df: SWAP1
00e0: SSTORE
00e1: PUSH8 0x0de0b6b3a7640000
00ea: PUSH1 0x03
00ec: SSTORE
00ed: JUMPDEST
00ee: PUSH1 0x03
00f0: SLOAD
00f1: CALLVALUE
00f2: LT
00f3: ISZERO
00f4: PUSH2 0x011f
00f7: JUMPI
00f8: PUSH1 0x40
00fa: MLOAD
00fb: CALLER
00fc: PUSH1 0x01
00fe: PUSH1 0xa0
0100: PUSH1 0x02
0102: EXP
0103: SUB
0104: AND
0105: SWAP1
0106: PUSH1 0x00
0108: SWAP1
0109: CALLVALUE
010a: SWAP1
010b: DUP3
010c: DUP2
010d: DUP2
010e: DUP2
010f: DUP6
0110: DUP9
0111: DUP4
0112: CALL
0113: SWAP4
0114: POP
0115: POP
0116: POP
0117: POP
0118: POP
0119: PUSH2 0x015c
011c: JUMP
011d: JUMPDEST
011e: STOP
011f: JUMPDEST
0120: PUSH1 0x00
0122: DUP1
0123: SLOAD
0124: PUSH1 0x01
0126: DUP1
0127: SLOAD
0128: PUSH20 0xffffffffffffffffffffffffffffffffffffffff
013d: NOT
013e: SWAP1
013f: DUP2
0140: AND
0141: PUSH1 0x01
0143: PUSH1 0xa0
0145: PUSH1 0x02
0147: EXP
0148: SUB
0149: DUP5
014a: AND
014b: OR
014c: SWAP1
014d: SWAP2
014e: SSTORE
014f: AND
0150: CALLER
0151: OR
0152: SWAP1
0153: SSTORE
0154: CALLVALUE
0155: PUSH1 0x03
0157: SSTORE
0158: TIMESTAMP
0159: PUSH1 0x02
015b: SSTORE
015c: JUMPDEST
015d: POP
015e: JUMP
exec
/bin/bash -lc "python3 - <<'PY'
mods=['eth','ethereum','eth_utils','eth_abi','web3']
for m in mods:
try:
__import__(m)
print(m,'ok')
except Exception as e:
print(m,'no')
PY" in /tmp/codex-33obuzoq
succeeded in 639ms:
eth no
ethereum no
eth_utils ok
eth_abi ok
web3 ok
exec
/bin/bash -lc "python3 - <<'PY'
mods=['eth_tester','evmdasm','pyevmasm','ethereum_input_decoder']
for m in mods:
try:
__import__(m)
print(m,'ok')
except Exception:
print(m,'no')
PY" in /tmp/codex-33obuzoq
succeeded in 0ms:
eth_tester no
evmdasm no
pyevmasm no
ethereum_input_decoder no
exec
/bin/bash -lc "python3 - <<'PY'
code='6060604052361561000b575b61011d6000600060026000505411801561002e5750620151806002600050544203115b156100ed57805434600160a060020a033081163191909103929116146100735760008054600160a060020a031690600a6006840204606082818181858883f150505050505b600154600160a060020a03166000146100b257600154604051600160a060020a039190911690600090600a60028502049082818181858883f150505050505b60006002819055805473ffffffffffffffffffffffffffffffffffffffff19908116909155600180549091169055670de0b6b3a76400006003555b60035434101561011f5760405133600160a060020a031690600090349082818181858883f193505050505061015c565b005b600080546001805473ffffffffffffffffffffffffffffffffffffffff19908116600160a060020a03841617909155163317905534600355426002555b5056'
ops={}
base=['STOP','ADD','MUL','SUB','DIV','SDIV','MOD','SMOD','ADDMOD','MULMOD','EXP','SIGNEXTEND']
for i,n in enumerate(base): ops[i]=n
ops.update({0x10:'LT',0x11:'GT',0x12:'SLT',0x13:'SGT',0x14:'EQ',0x15:'ISZERO',0x16:'AND',0x17:'OR',0x18:'XOR',0x19:'NOT',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',0x40:'BLOCKHASH',0x41:'COINBASE',0x42:'TIMESTAMP',0x43:'NUMBER',0x44:'DIFFICULTY',0x45:'GASLIMIT',0x50:'POP',0x51:'MLOAD',0x52:'MSTORE',0x53:'MSTORE8',0x54:'SLOAD',0x55:'SSTORE',0x56:'JUMP',0x57:'JUMPI',0x58:'PC',0x59:'MSIZE',0x5a:'GAS',0x5b:'JUMPDEST',0xf0:'CREATE',0xf1:'CALL',0xf2:'CALLCODE',0xf3:'RETURN',0xf4:'DELEGATECALL',0xf5:'CREATE2',0xfa:'STATICCALL',0xfd:'REVERT',0xfe:'INVALID',0xff:'SELFDESTRUCT'})
for i in range(1,33): ops[0x5f+i]=f'PUSH{i}'
for i in range(1,17): ops[0x7f+i]=f'DUP{i}'
for i in range(1,17): ops[0x8f+i]=f'SWAP{i}'
for i in range(0,5): ops[0xa0+i]=f'LOG{i}'
b=bytes.fromhex(code)
inst=[]
pc=0
while pc<len(b):
op=b[pc]; name=ops.get(op,hex(op)); arg=None
if name.startswith('PUSH'):
n=int(name[4:]); arg='0x'+b[pc+1:pc+1+n].hex(); inst.append((pc,name,arg)); pc+=1+n
else:
inst.append((pc,name,None)); pc+=1
pc_to_i={pc:i for i,(pc,_,_) in enumerate(inst)}
def run(start_pc, stop_pcs=None, stack=None):
if stack is None: stack=[]
i=pc_to_i[start_pc]
while i < len(inst):
pc,name,arg=inst[i]
print(f'{pc:04x} {name} {arg or \"\"} stack={stack}')
if stop_pcs and pc in stop_pcs: break
if name.startswith('PUSH'):
stack.append(arg)
elif name.startswith('DUP'):
n=int(name[3:]); stack.append(stack[-n])
elif name.startswith('SWAP'):
n=int(name[4:]); stack[-1],stack[-1-n]=stack[-1-n],stack[-1]
elif name=='POP':
stack.pop()
elif name=='SLOAD':
k=stack.pop(); stack.append(f'SLOAD[{k}]')
elif name=='SSTORE':
k=stack.pop(); v=stack.pop(); print(' SSTORE',k,'=',v)
elif name in ('ADD','SUB','MUL','DIV','EXP','AND','OR','XOR','EQ','LT','GT'):
a=stack.pop(); b=stack.pop(); stack.append(f'({b} {name} {a})')
elif name in ('ISZERO','NOT','BALANCE'):
a=stack.pop(); stack.append(f'{name}({a})')
elif name in ('ADDRESS','CALLER','CALLVALUE','TIMESTAMP','CALLDATASIZE','GAS'):
stack.append(name)
elif name=='MLOAD':
off=stack.pop(); stack.append(f'MLOAD[{off}]')
elif name=='MSTORE':
off=stack.pop(); val=stack.pop(); print(' MSTORE',off,'=',val)
elif name=='JUMPI':
dest=stack.pop(); cond=stack.pop(); print(' JUMPI to',dest,'if',cond)
break
elif name=='JUMP':
dest=stack.pop(); print(' JUMP to',dest); break
elif name=='CALL':
gas=stack.pop(); to=stack.pop(); value=stack.pop(); ino=stack.pop(); ins=stack.pop(); outo=stack.pop(); outs=stack.pop(); stack.append(f'CALL({to},value={value},gas={gas},in={ino}/{ins},out={outo}/{outs})')
elif name=='JUMPDEST' or name=='STOP':
pass
else:
print('unhandled',name); break
i+=1
print('final stack',stack)
print('--- start to first branch ---')
run(0)
print('--- at 0x34 ---')
run(0x34, stack=['RET'])
print('--- at 0x74 ---')
run(0x74, stack=['RET'])
print('--- at 0xee then jump path? ---')
run(0xee, stack=['RET'])
print('--- at 0x11f ---')
run(0x11f, stack=['RET','NEWADDR'])
PY" in /tmp/codex-33obuzoq
succeeded in 0ms:
--- start to first branch ---
0000 PUSH1 0x60 stack=[]
0002 PUSH1 0x40 stack=['0x60']
0004 MSTORE stack=['0x60', '0x40']
MSTORE 0x40 = 0x60
0005 CALLDATASIZE stack=[]
0006 ISZERO stack=['CALLDATASIZE']
0007 PUSH2 0x000b stack=['ISZERO(CALLDATASIZE)']
000a JUMPI stack=['ISZERO(CALLDATASIZE)', '0x000b']
JUMPI to 0x000b if ISZERO(CALLDATASIZE)
final stack []
--- at 0x34 ---
0034 DUP1 stack=['RET']
0035 SLOAD stack=['RET', 'RET']
0036 CALLVALUE stack=['RET', 'SLOAD[RET]']
0037 PUSH1 0x01 stack=['RET', 'SLOAD[RET]', 'CALLVALUE']
0039 PUSH1 0xa0 stack=['RET', 'SLOAD[RET]', 'CALLVALUE', '0x01']
003b PUSH1 0x02 stack=['RET', 'SLOAD[RET]', 'CALLVALUE', '0x01', '0xa0']
003d EXP stack=['RET', 'SLOAD[RET]', 'CALLVALUE', '0x01', '0xa0', '0x02']
003e SUB stack=['RET', 'SLOAD[RET]', 'CALLVALUE', '0x01', '(0xa0 EXP 0x02)']
003f ADDRESS stack=['RET', 'SLOAD[RET]', 'CALLVALUE', '(0x01 SUB (0xa0 EXP 0x02))']
0040 DUP2 stack=['RET', 'SLOAD[RET]', 'CALLVALUE', '(0x01 SUB (0xa0 EXP 0x02))', 'ADDRESS']
0041 AND stack=['RET', 'SLOAD[RET]', 'CALLVALUE', '(0x01 SUB (0xa0 EXP 0x02))', 'ADDRESS', '(0x01 SUB (0xa0 EXP 0x02))']
0042 BALANCE stack=['RET', 'SLOAD[RET]', 'CALLVALUE', '(0x01 SUB (0xa0 EXP 0x02))', '(ADDRESS AND (0x01 SUB (0xa0 EXP 0x02)))']
0043 SWAP2 stack=['RET', 'SLOAD[RET]', 'CALLVALUE', '(0x01 SUB (0xa0 EXP 0x02))', 'BALANCE((ADDRESS AND (0x01 SUB (0xa0 EXP 0x02))))']
0044 SWAP1 stack=['RET', 'SLOAD[RET]', 'BALANCE((ADDRESS AND (0x01 SUB (0xa0 EXP 0x02))))', '(0x01 SUB (0xa0 EXP 0x02))', 'CALLVALUE']
0045 SWAP2 stack=['RET', 'SLOAD[RET]', 'BALANCE((ADDRESS AND (0x01 SUB (0xa0 EXP 0x02))))', 'CALLVALUE', '(0x01 SUB (0xa0 EXP 0x02))']
0046 SUB stack=['RET', 'SLOAD[RET]', '(0x01 SUB (0xa0 EXP 0x02))', 'CALLVALUE', 'BALANCE((ADDRESS AND (0x01 SUB (0xa0 EXP 0x02))))']
0047 SWAP3 stack=['RET', 'SLOAD[RET]', '(0x01 SUB (0xa0 EXP 0x02))', '(CALLVALUE SUB BALANCE((ADDRESS AND (0x01 SUB (0xa0 EXP 0x02)))))']
0048 SWAP2 stack=['(CALLVALUE SUB BALANCE((ADDRESS AND (0x01 SUB (0xa0 EXP 0x02)))))', 'SLOAD[RET]', '(0x01 SUB (0xa0 EXP 0x02))', 'RET']
0049 AND stack=['(CALLVALUE SUB BALANCE((ADDRESS AND (0x01 SUB (0xa0 EXP 0x02)))))', 'RET', '(0x01 SUB (0xa0 EXP 0x02))', 'SLOAD[RET]']
004a EQ stack=['(CALLVALUE SUB BALANCE((ADDRESS AND (0x01 SUB (0xa0 EXP 0x02)))))', 'RET', '((0x01 SUB (0xa0 EXP 0x02)) AND SLOAD[RET])']
004b PUSH2 0x0073 stack=['(CALLVALUE SUB BALANCE((ADDRESS AND (0x01 SUB (0xa0 EXP 0x02)))))', '(RET EQ ((0x01 SUB (0xa0 EXP 0x02)) AND SLOAD[RET]))']
004e JUMPI stack=['(CALLVALUE SUB BALANCE((ADDRESS AND (0x01 SUB (0xa0 EXP 0x02)))))', '(RET EQ ((0x01 SUB (0xa0 EXP 0x02)) AND SLOAD[RET]))', '0x0073']
JUMPI to 0x0073 if (RET EQ ((0x01 SUB (0xa0 EXP 0x02)) AND SLOAD[RET]))
final stack ['(CALLVALUE SUB BALANCE((ADDRESS AND (0x01 SUB (0xa0 EXP 0x02)))))']
--- at 0x74 ---
0074 PUSH1 0x01 stack=['RET']
0076 SLOAD stack=['RET', '0x01']
0077 PUSH1 0x01 stack=['RET', 'SLOAD[0x01]']
0079 PUSH1 0xa0 stack=['RET', 'SLOAD[0x01]', '0x01']
007b PUSH1 0x02 stack=['RET', 'SLOAD[0x01]', '0x01', '0xa0']
007d EXP stack=['RET', 'SLOAD[0x01]', '0x01', '0xa0', '0x02']
007e SUB stack=['RET', 'SLOAD[0x01]', '0x01', '(0xa0 EXP 0x02)']
007f AND stack=['RET', 'SLOAD[0x01]', '(0x01 SUB (0xa0 EXP 0x02))']
0080 PUSH1 0x00 stack=['RET', '(SLOAD[0x01] AND (0x01 SUB (0xa0 EXP 0x02)))']
0082 EQ stack=['RET', '(SLOAD[0x01] AND (0x01 SUB (0xa0 EXP 0x02)))', '0x00']
0083 PUSH2 0x00b2 stack=['RET', '((SLOAD[0x01] AND (0x01 SUB (0xa0 EXP 0x02))) EQ 0x00)']
0086 JUMPI stack=['RET', '((SLOAD[0x01] AND (0x01 SUB (0xa0 EXP 0x02))) EQ 0x00)', '0x00b2']
JUMPI to 0x00b2 if ((SLOAD[0x01] AND (0x01 SUB (0xa0 EXP 0x02))) EQ 0x00)
final stack ['RET']
--- at 0xee then jump path? ---
00ee PUSH1 0x03 stack=['RET']
00f0 SLOAD stack=['RET', '0x03']
00f1 CALLVALUE stack=['RET', 'SLOAD[0x03]']
00f2 LT stack=['RET', 'SLOAD[0x03]', 'CALLVALUE']
00f3 ISZERO stack=['RET', '(SLOAD[0x03] LT CALLVALUE)']
00f4 PUSH2 0x011f stack=['RET', 'ISZERO((SLOAD[0x03] LT CALLVALUE))']
00f7 JUMPI stack=['RET', 'ISZERO((SLOAD[0x03] LT CALLVALUE))', '0x011f']
JUMPI to 0x011f if ISZERO((SLOAD[0x03] LT CALLVALUE))
final stack ['RET']
--- at 0x11f ---
011f JUMPDEST stack=['RET', 'NEWADDR']
0120 PUSH1 0x00 stack=['RET', 'NEWADDR']
0122 DUP1 stack=['RET', 'NEWADDR', '0x00']
0123 SLOAD stack=['RET', 'NEWADDR', '0x00', '0x00']
0124 PUSH1 0x01 stack=['RET', 'NEWADDR', '0x00', 'SLOAD[0x00]']
0126 DUP1 stack=['RET', 'NEWADDR', '0x00', 'SLOAD[0x00]', '0x01']
0127 SLOAD stack=['RET', 'NEWADDR', '0x00', 'SLOAD[0x00]', '0x01', '0x01']
0128 PUSH20 0xffffffffffffffffffffffffffffffffffffffff stack=['RET', 'NEWADDR', '0x00', 'SLOAD[0x00]', '0x01', 'SLOAD[0x01]']
013d NOT stack=['RET', 'NEWADDR', '0x00', 'SLOAD[0x00]', '0x01', 'SLOAD[0x01]', '0xffffffffffffffffffffffffffffffffffffffff']
013e SWAP1 stack=['RET', 'NEWADDR', '0x00', 'SLOAD[0x00]', '0x01', 'SLOAD[0x01]', 'NOT(0xffffffffffffffffffffffffffffffffffffffff)']
013f DUP2 stack=['RET', 'NEWADDR', '0x00', 'SLOAD[0x00]', '0x01', 'NOT(0xffffffffffffffffffffffffffffffffffffffff)', 'SLOAD[0x01]']
0140 AND stack=['RET', 'NEWADDR', '0x00', 'SLOAD[0x00]', '0x01', 'NOT(0xffffffffffffffffffffffffffffffffffffffff)', 'SLOAD[0x01]', 'NOT(0xffffffffffffffffffffffffffffffffffffffff)']
0141 PUSH1 0x01 stack=['RET', 'NEWADDR', '0x00', 'SLOAD[0x00]', '0x01', 'NOT(0xffffffffffffffffffffffffffffffffffffffff)', '(SLOAD[0x01] AND NOT(0xffffffffffffffffffffffffffffffffffffffff))']
0143 PUSH1 0xa0 stack=['RET', 'NEWADDR', '0x00', 'SLOAD[0x00]', '0x01', 'NOT(0xffffffffffffffffffffffffffffffffffffffff)', '(SLOAD[0x01] AND NOT(0xffffffffffffffffffffffffffffffffffffffff))', '0x01']
0145 PUSH1 0x02 stack=['RET', 'NEWADDR', '0x00', 'SLOAD[0x00]', '0x01', 'NOT(0xffffffffffffffffffffffffffffffffffffffff)', '(SLOAD[0x01] AND NOT(0xffffffffffffffffffffffffffffffffffffffff))', '0x01', '0xa0']
0147 EXP stack=['RET', 'NEWADDR', '0x00', 'SLOAD[0x00]', '0x01', 'NOT(0xffffffffffffffffffffffffffffffffffffffff)', '(SLOAD[0x01] AND NOT(0xffffffffffffffffffffffffffffffffffffffff))', '0x01', '0xa0', '0x02']
0148 SUB stack=['RET', 'NEWADDR', '0x00', 'SLOAD[0x00]', '0x01', 'NOT(0xffffffffffffffffffffffffffffffffffffffff)', '(SLOAD[0x01] AND NOT(0xffffffffffffffffffffffffffffffffffffffff))', '0x01', '(0xa0 EXP 0x02)']
0149 DUP5 stack=['RET', 'NEWADDR', '0x00', 'SLOAD[0x00]', '0x01', 'NOT(0xffffffffffffffffffffffffffffffffffffffff)', '(SLOAD[0x01] AND NOT(0xffffffffffffffffffffffffffffffffffffffff))', '(0x01 SUB (0xa0 EXP 0x02))']
014a AND stack=['RET', 'NEWADDR', '0x00', 'SLOAD[0x00]', '0x01', 'NOT(0xffffffffffffffffffffffffffffffffffffffff)', '(SLOAD[0x01] AND NOT(0xffffffffffffffffffffffffffffffffffffffff))', '(0x01 SUB (0xa0 EXP 0x02))', 'SLOAD[0x00]']
014b OR stack=['RET', 'NEWADDR', '0x00', 'SLOAD[0x00]', '0x01', 'NOT(0xffffffffffffffffffffffffffffffffffffffff)', '(SLOAD[0x01] AND NOT(0xffffffffffffffffffffffffffffffffffffffff))', '((0x01 SUB (0xa0 EXP 0x02)) AND SLOAD[0x00])']
014c SWAP1 stack=['RET', 'NEWADDR', '0x00', 'SLOAD[0x00]', '0x01', 'NOT(0xffffffffffffffffffffffffffffffffffffffff)', '((SLOAD[0x01] AND NOT(0xffffffffffffffffffffffffffffffffffffffff)) OR ((0x01 SUB (0xa0 EXP 0x02)) AND SLOAD[0x00]))']
014d SWAP2 stack=['RET', 'NEWADDR', '0x00', 'SLOAD[0x00]', '0x01', '((SLOAD[0x01] AND NOT(0xffffffffffffffffffffffffffffffffffffffff)) OR ((0x01 SUB (0xa0 EXP 0x02)) AND SLOAD[0x00]))', 'NOT(0xffffffffffffffffffffffffffffffffffffffff)']
014e SSTORE stack=['RET', 'NEWADDR', '0x00', 'SLOAD[0x00]', 'NOT(0xffffffffffffffffffffffffffffffffffffffff)', '((SLOAD[0x01] AND NOT(0xffffffffffffffffffffffffffffffffffffffff)) OR ((0x01 SUB (0xa0 EXP 0x02)) AND SLOAD[0x00]))', '0x01']
SSTORE 0x01 = ((SLOAD[0x01] AND NOT(0xffffffffffffffffffffffffffffffffffffffff)) OR ((0x01 SUB (0xa0 EXP 0x02)) AND SLOAD[0x00]))
014f AND stack=['RET', 'NEWADDR', '0x00', 'SLOAD[0x00]', 'NOT(0xffffffffffffffffffffffffffffffffffffffff)']
0150 CALLER stack=['RET', 'NEWADDR', '0x00', '(SLOAD[0x00] AND NOT(0xffffffffffffffffffffffffffffffffffffffff))']
0151 OR stack=['RET', 'NEWADDR', '0x00', '(SLOAD[0x00] AND NOT(0xffffffffffffffffffffffffffffffffffffffff))', 'CALLER']
0152 SWAP1 stack=['RET', 'NEWADDR', '0x00', '((SLOAD[0x00] AND NOT(0xffffffffffffffffffffffffffffffffffffffff)) OR CALLER)']
0153 SSTORE stack=['RET', 'NEWADDR', '((SLOAD[0x00] AND NOT(0xffffffffffffffffffffffffffffffffffffffff)) OR CALLER)', '0x00']
SSTORE 0x00 = ((SLOAD[0x00] AND NOT(0xffffffffffffffffffffffffffffffffffffffff)) OR CALLER)
0154 CALLVALUE stack=['RET', 'NEWADDR']
0155 PUSH1 0x03 stack=['RET', 'NEWADDR', 'CALLVALUE']
0157 SSTORE stack=['RET', 'NEWADDR', 'CALLVALUE', '0x03']
SSTORE 0x03 = CALLVALUE
0158 TIMESTAMP stack=['RET', 'NEWADDR']
0159 PUSH1 0x02 stack=['RET', 'NEWADDR', 'TIMESTAMP']
015b SSTORE stack=['RET', 'NEWADDR', 'TIMESTAMP', '0x02']
SSTORE 0x02 = TIMESTAMP
015c JUMPDEST stack=['RET', 'NEWADDR']
015d POP stack=['RET', 'NEWADDR']
015e JUMP stack=['RET']
JUMP to RET
final stack []
exec
/bin/bash -lc "python3 - <<'PY'
# symbolic path to inspect stack entering 0xed and 0x34/0x74
code='6060604052361561000b575b61011d6000600060026000505411801561002e5750620151806002600050544203115b156100ed57805434600160a060020a033081163191909103929116146100735760008054600160a060020a031690600a6006840204606082818181858883f150505050505b600154600160a060020a03166000146100b257600154604051600160a060020a039190911690600090600a60028502049082818181858883f150505050505b60006002819055805473ffffffffffffffffffffffffffffffffffffffff19908116909155600180549091169055670de0b6b3a76400006003555b60035434101561011f5760405133600160a060020a031690600090349082818181858883f193505050505061015c565b005b600080546001805473ffffffffffffffffffffffffffffffffffffffff19908116600160a060020a03841617909155163317905534600355426002555b5056'
ops={}
base=['STOP','ADD','MUL','SUB','DIV','SDIV','MOD','SMOD','ADDMOD','MULMOD','EXP','SIGNEXTEND']
for i,n in enumerate(base): ops[i]=n
ops.update({0x10:'LT',0x11:'GT',0x12:'SLT',0x13:'SGT',0x14:'EQ',0x15:'ISZERO',0x16:'AND',0x17:'OR',0x18:'XOR',0x19:'NOT',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',0x40:'BLOCKHASH',0x41:'COINBASE',0x42:'TIMESTAMP',0x43:'NUMBER',0x44:'DIFFICULTY',0x45:'GASLIMIT',0x50:'POP',0x51:'MLOAD',0x52:'MSTORE',0x53:'MSTORE8',0x54:'SLOAD',0x55:'SSTORE',0x56:'JUMP',0x57:'JUMPI',0x58:'PC',0x59:'MSIZE',0x5a:'GAS',0x5b:'JUMPDEST',0xf0:'CREATE',0xf1:'CALL',0xf2:'CALLCODE',0xf3:'RETURN',0xf4:'DELEGATECALL',0xf5:'CREATE2',0xfa:'STATICCALL',0xfd:'REVERT',0xfe:'INVALID',0xff:'SELFDESTRUCT'})
for i in range(1,33): ops[0x5f+i]=f'PUSH{i}'
for i in range(1,17): ops[0x7f+i]=f'DUP{i}'
for i in range(1,17): ops[0x8f+i]=f'SWAP{i}'
for i in range(0,5): ops[0xa0+i]=f'LOG{i}'
b=bytes.fromhex(code)
inst=[]
pc=0
while pc<len(b):
op=b[pc]; name=ops.get(op,hex(op)); arg=None
if name.startswith('PUSH'):
n=int(name[4:]); arg='0x'+b[pc+1:pc+1+n].hex(); inst.append((pc,name,arg)); pc+=1+n
else:
inst.append((pc,name,None)); pc+=1
pc_to_i={pc:i for i,(pc,_,_) in enumerate(inst)}
def step(i,stack):
pc,name,arg=inst[i]
if name.startswith('PUSH'): stack.append(arg); return i+1
if name.startswith('DUP'): n=int(name[3:]); stack.append(stack[-n]); return i+1
if name.startswith('SWAP'): n=int(name[4:]); stack[-1],stack[-1-n]=stack[-1-n],stack[-1]; return i+1
if name=='POP': stack.pop(); return i+1
if name=='SLOAD': k=stack.pop(); stack.append(f'SLOAD[{k}]'); return i+1
if name=='SSTORE': k=stack.pop(); v=stack.pop(); print(f'{pc:04x} SSTORE {k}={v}'); return i+1
if name in ('ADD','SUB','MUL','DIV','EXP','AND','OR','XOR','EQ','LT','GT'): a=stack.pop(); b=stack.pop(); stack.append(f'({b} {name} {a})'); return i+1
if name in ('ISZERO','NOT','BALANCE'): a=stack.pop(); stack.append(f'{name}({a})'); return i+1
if name in ('ADDRESS','CALLER','CALLVALUE','TIMESTAMP','CALLDATASIZE','GAS'): stack.append(name); return i+1
if name=='MLOAD': off=stack.pop(); stack.append(f'MLOAD[{off}]'); return i+1
if name=='MSTORE': off=stack.pop(); val=stack.pop(); return i+1
if name=='JUMPI': dest=stack.pop(); cond=stack.pop(); print(f'{pc:04x} JUMPI {dest} if {cond} stack_after={stack}'); return ('JUMPI',dest,cond)
if name=='JUMP': dest=stack.pop(); print(f'{pc:04x} JUMP {dest} stack_after={stack}'); return ('JUMP',dest)
if name=='CALL': gas=stack.pop(); to=stack.pop(); value=stack.pop(); ino=stack.pop(); ins=stack.pop(); outo=stack.pop(); outs=stack.pop(); stack.append(f'CALL({to},value={value},gas={gas},in={ino}/{ins},out={outo}/{outs})'); print(f'{pc:04x} CALL to={to} value={value} stack_after={stack}'); return i+1
return i+1
# simulate from 0x0b to 0x33 then take jump to 0xed
stack=[]
i=pc_to_i[0x0b]
while True:
pc,name,arg=inst[i]
print(f'{pc:04x} {name} {arg or \"\"} stack={stack}')
r=step(i,stack)
if isinstance(r,tuple):
print('branch tuple',r)
break
i=r
print('stack before branching',stack)
# continue as if jumped to 0xed
print('enter 0xed stack',stack)
PY" in /tmp/codex-33obuzoq
succeeded in 0ms:
000b JUMPDEST stack=[]
000c PUSH2 0x011d stack=[]
000f PUSH1 0x00 stack=['0x011d']
0011 PUSH1 0x00 stack=['0x011d', '0x00']
0013 PUSH1 0x02 stack=['0x011d', '0x00', '0x00']
0015 PUSH1 0x00 stack=['0x011d', '0x00', '0x00', '0x02']
0017 POP stack=['0x011d', '0x00', '0x00', '0x02', '0x00']
0018 SLOAD stack=['0x011d', '0x00', '0x00', '0x02']
0019 GT stack=['0x011d', '0x00', '0x00', 'SLOAD[0x02]']
001a DUP1 stack=['0x011d', '0x00', '(0x00 GT SLOAD[0x02])']
001b ISZERO stack=['0x011d', '0x00', '(0x00 GT SLOAD[0x02])', '(0x00 GT SLOAD[0x02])']
001c PUSH2 0x002e stack=['0x011d', '0x00', '(0x00 GT SLOAD[0x02])', 'ISZERO((0x00 GT SLOAD[0x02]))']
001f JUMPI stack=['0x011d', '0x00', '(0x00 GT SLOAD[0x02])', 'ISZERO((0x00 GT SLOAD[0x02]))', '0x002e']
001f JUMPI 0x002e if ISZERO((0x00 GT SLOAD[0x02])) stack_after=['0x011d', '0x00', '(0x00 GT SLOAD[0x02])']
branch tuple ('JUMPI', '0x002e', 'ISZERO((0x00 GT SLOAD[0x02]))')
stack before branching ['0x011d', '0x00', '(0x00 GT SLOAD[0x02])']
enter 0xed stack ['0x011d', '0x00', '(0x00 GT SLOAD[0x02])']
exec
/bin/bash -lc "python3 - <<'PY'
# simulate path from 0x0b to 0x34 taking payout branch fallthroughs
code='6060604052361561000b575b61011d6000600060026000505411801561002e5750620151806002600050544203115b156100ed57805434600160a060020a033081163191909103929116146100735760008054600160a060020a031690600a6006840204606082818181858883f150505050505b600154600160a060020a03166000146100b257600154604051600160a060020a039190911690600090600a60028502049082818181858883f150505050505b60006002819055805473ffffffffffffffffffffffffffffffffffffffff19908116909155600180549091169055670de0b6b3a76400006003555b60035434101561011f5760405133600160a060020a031690600090349082818181858883f193505050505061015c565b005b600080546001805473ffffffffffffffffffffffffffffffffffffffff19908116600160a060020a03841617909155163317905534600355426002555b5056'
ops={}
base=['STOP','ADD','MUL','SUB','DIV','SDIV','MOD','SMOD','ADDMOD','MULMOD','EXP','SIGNEXTEND']
for i,n in enumerate(base): ops[i]=n
ops.update({0x10:'LT',0x11:'GT',0x12:'SLT',0x13:'SGT',0x14:'EQ',0x15:'ISZERO',0x16:'AND',0x17:'OR',0x18:'XOR',0x19:'NOT',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',0x40:'BLOCKHASH',0x41:'COINBASE',0x42:'TIMESTAMP',0x43:'NUMBER',0x44:'DIFFICULTY',0x45:'GASLIMIT',0x50:'POP',0x51:'MLOAD',0x52:'MSTORE',0x53:'MSTORE8',0x54:'SLOAD',0x55:'SSTORE',0x56:'JUMP',0x57:'JUMPI',0x58:'PC',0x59:'MSIZE',0x5a:'GAS',0x5b:'JUMPDEST',0xf0:'CREATE',0xf1:'CALL',0xf2:'CALLCODE',0xf3:'RETURN',0xf4:'DELEGATECALL',0xf5:'CREATE2',0xfa:'STATICCALL',0xfd:'REVERT',0xfe:'INVALID',0xff:'SELFDESTRUCT'})
for i in range(1,33): ops[0x5f+i]=f'PUSH{i}'
for i in range(1,17): ops[0x7f+i]=f'DUP{i}'
for i in range(1,17): ops[0x8f+i]=f'SWAP{i}'
b=bytes.fromhex(code)
inst=[]; pc=0
while pc<len(b):
op=b[pc]; name=ops.get(op,hex(op)); arg=None
if name.startswith('PUSH'):
n=int(name[4:]); arg='0x'+b[pc+1:pc+1+n].hex(); inst.append((pc,name,arg)); pc+=1+n
else:
inst.append((pc,name,None)); pc+=1
pc_to_i={pc:i for i,(pc,_,_) in enumerate(inst)}
stack=[]
i=pc_to_i[0x0b]
branch_choices={0x1f:'fallthrough',0x33:'fallthrough',0x4e:'jump'}
while True:
pc,name,arg=inst[i]
print(f'{pc:04x} {name} {arg or \"\"} stack={stack}')
if name.startswith('PUSH'): stack.append(arg); i+=1; continue
if name.startswith('DUP'): stack.append(stack[-int(name[3:])]); i+=1; continue
if name.startswith('SWAP'):
n=int(name[4:]); stack[-1],stack[-1-n]=stack[-1-n],stack[-1]; i+=1; continue
if name=='POP': stack.pop(); i+=1; continue
if name=='SLOAD': k=stack.pop(); stack.append(f'SLOAD[{k}]'); i+=1; continue
if name in ('ADD','SUB','MUL','DIV','EXP','AND','OR','XOR','EQ','LT','GT'):
a=stack.pop(); b=stack.pop(); stack.append(f'({b} {name} {a})'); i+=1; continue
if name in ('ISZERO','NOT','BALANCE'):
a=stack.pop(); stack.append(f'{name}({a})'); i+=1; continue
if name in ('ADDRESS','CALLER','CALLVALUE','TIMESTAMP','CALLDATASIZE','GAS'): stack.append(name); i+=1; continue
if name=='JUMPI':
dest=stack.pop(); cond=stack.pop(); print(' JUMPI',dest,'if',cond,'remaining',stack)
choice=branch_choices.get(pc,'fallthrough')
if choice=='jump': i=pc_to_i[int(dest,16)]
else: i+=1
continue
if name=='JUMPDEST': i+=1; continue
if pc==0x73:
print('entry stack at 0x73',stack); break
if name=='CALL': print('CALL stack',stack); break
PY" in /tmp/codex-33obuzoq
2026-04-04T22:03:40.379817Z ERROR codex_core::tools::router: error=write_stdin failed: stdin is closed for this session; rerun exec_command with tty=true to keep stdin open
codex
{"no_findings":false,"summary":"Fallback-only bytecode with three ETH-bearing CALL sites, no detected auth guards, and state cleanup that occurs after external payouts. The strongest issue is reentrancy risk on the payout path; a secondary issue is unchecked CALL success on all outbound transfers.","findings":[{"severity":"high","category":"reentrancy","title":"External payout calls occur before round state is cleared","exploit_scenario":"A prior participant can register a contract as one of the payout recipients via the fallback update path. When the expiry/payout branch executes, the contract performs value-bearing CALLs to stored recipient addresses at pc 0x6d and pc 0xac before clearing slot 2 and before wiping the recipient fields in slots 0/1. A malicious recipient can reenter the fallback during the first payout while the old state is still live, potentially triggering the payout logic repeatedly and draining more of the contract balance than intended. This is based on bytecode-only reasoning, so the exact branch condition is inferred rather than source-confirmed.","recommendation":"Apply checks-effects-interactions: fully clear or checkpoint the active round before any external CALL, or add an explicit reentrancy guard around the fallback payout path. If payouts must remain external, store owed balances and let recipients withdraw in a separate pull-payment flow.","evidence":"The artifact reports no detected guards (`auth.guards=[]`) and three CALL sites. The first two CALLs are at pc 109/0x6d and 172/0xac, both with `returndata_checked: null` and computed targets/values. State-reset writes happen only afterward at pc 185/0xb9 (slot 2), pc 215-216/0xd7-0xd8 and pc 224/0xe0 (slot 0/1 cleanup), and pc 236/0xec (slot 3 reset). Recipient addresses appear user-influenced because the fallback update routine writes slots 1 and 0 at pc 334/0x14e and pc 339/0x153. Detector finding `Untrusted CALL target/value reachable` is validated/confirmed.","locations":["pc:0x6d","pc:0xac","pc:0xb9","pc:0xd7","pc:0xe0","pc:0xec","pc:0x14e","pc:0x153"]},{"severity":"medium","category":"other","title":"Outbound ETH transfers ignore CALL success and continue","exploit_scenario":"If a payout recipient or refund recipient is a contract that reverts or otherwise makes the CALL fail, this bytecode does not check the returned success flag before continuing. On the payout path, the contract appears to proceed into state cleanup and round reset even when one or both payouts fail, which can skip owed payments and strand funds in the contract. On the refund-like path at pc 0x112, a failed ETH send to `CALLER` is also ignored.","recommendation":"Check the boolean result of each CALL and revert on failure, or convert the design to pull-based withdrawals so failed recipients cannot silently break accounting. If non-reverting behavior is required, record failed payouts as claimable balances instead of discarding the failure.","evidence":"All three callsites in the bundle have `returndata_checked: null`: pc 109/0x6d, 172/0xac, and 274/0x112. In the bytecode, each CALL is followed by POPs rather than a conditional revert path, so success is discarded. After the payout CALLs, execution continues into storage writes that clear/reset state (pc 0xb9, 0xd7, 0xe0, 0xec), which creates accounting risk if the transfer did not actually occur. Detector finding `ETH value transfer possible` is validated/confirmed.","locations":["pc:0x6d","pc:0xac","pc:0x112","pc:0xb9","pc:0xd7","pc:0xe0","pc:0xec"]}]}
tokens used
80,855
{
"codex": {
"ran_at": "2026-04-04T22:04:05.323372+00:00",
"returncode": 0
},
"project": {
"mode": "bytecode",
"bytecode_length": 704,
"bytecode_truncated": false,
"capability_graph_present": true,
"analysis_artifact_present": true
},
"summary": "Fallback-only bytecode with three ETH-bearing CALL sites, no detected auth guards, and state cleanup that occurs after external payouts. The strongest issue is reentrancy risk on the payout path; a secondary issue is unchecked CALL success on all outbound transfers.",
"raw_final": {
"summary": "Fallback-only bytecode with three ETH-bearing CALL sites, no detected auth guards, and state cleanup that occurs after external payouts. The strongest issue is reentrancy risk on the payout path; a secondary issue is unchecked CALL success on all outbound transfers.",
"findings": [
{
"title": "External payout calls occur before round state is cleared",
"category": "reentrancy",
"evidence": "The artifact reports no detected guards (`auth.guards=[]`) and three CALL sites. The first two CALLs are at pc 109/0x6d and 172/0xac, both with `returndata_checked: null` and computed targets/values. State-reset writes happen only afterward at pc 185/0xb9 (slot 2), pc 215-216/0xd7-0xd8 and pc 224/0xe0 (slot 0/1 cleanup), and pc 236/0xec (slot 3 reset). Recipient addresses appear user-influenced because the fallback update routine writes slots 1 and 0 at pc 334/0x14e and pc 339/0x153. Detector finding `Untrusted CALL target/value reachable` is validated/confirmed.",
"severity": "high",
"locations": [
"pc:0x6d",
"pc:0xac",
"pc:0xb9",
"pc:0xd7",
"pc:0xe0",
"pc:0xec",
"pc:0x14e",
"pc:0x153"
],
"recommendation": "Apply checks-effects-interactions: fully clear or checkpoint the active round before any external CALL, or add an explicit reentrancy guard around the fallback payout path. If payouts must remain external, store owed balances and let recipients withdraw in a separate pull-payment flow.",
"exploit_scenario": "A prior participant can register a contract as one of the payout recipients via the fallback update path. When the expiry/payout branch executes, the contract performs value-bearing CALLs to stored recipient addresses at pc 0x6d and pc 0xac before clearing slot 2 and before wiping the recipient fields in slots 0/1. A malicious recipient can reenter the fallback during the first payout while the old state is still live, potentially triggering the payout logic repeatedly and draining more of the contract balance than intended. This is based on bytecode-only reasoning, so the exact branch condition is inferred rather than source-confirmed."
},
{
"title": "Outbound ETH transfers ignore CALL success and continue",
"category": "other",
"evidence": "All three callsites in the bundle have `returndata_checked: null`: pc 109/0x6d, 172/0xac, and 274/0x112. In the bytecode, each CALL is followed by POPs rather than a conditional revert path, so success is discarded. After the payout CALLs, execution continues into storage writes that clear/reset state (pc 0xb9, 0xd7, 0xe0, 0xec), which creates accounting risk if the transfer did not actually occur. Detector finding `ETH value transfer possible` is validated/confirmed.",
"severity": "medium",
"locations": [
"pc:0x6d",
"pc:0xac",
"pc:0x112",
"pc:0xb9",
"pc:0xd7",
"pc:0xe0",
"pc:0xec"
],
"recommendation": "Check the boolean result of each CALL and revert on failure, or convert the design to pull-based withdrawals so failed recipients cannot silently break accounting. If non-reverting behavior is required, record failed payouts as claimable balances instead of discarding the failure.",
"exploit_scenario": "If a payout recipient or refund recipient is a contract that reverts or otherwise makes the CALL fail, this bytecode does not check the returned success flag before continuing. On the payout path, the contract appears to proceed into state cleanup and round reset even when one or both payouts fail, which can skip owed payments and strand funds in the contract. On the refund-like path at pc 0x112, a failed ETH send to `CALLER` is also ignored."
}
],
"no_findings": false
},
"no_findings": false,
"schema_version": 1
}
00000000: PUSH1 0x60 00000002: PUSH1 0x40 00000004: MSTORE 00000005: CALLDATASIZE 00000006: ISZERO 00000007: PUSH2 0x000b 0000000a: JUMPI 0000000b: JUMPDEST 0000000c: PUSH2 0x011d 0000000f: PUSH1 0x00 00000011: PUSH1 0x00 00000013: PUSH1 0x02 00000015: PUSH1 0x00 00000017: POP 00000018: SLOAD 00000019: GT 0000001a: DUP1 0000001b: ISZERO 0000001c: PUSH2 0x002e 0000001f: JUMPI 00000020: POP 00000021: PUSH3 0x015180 00000025: PUSH1 0x02 00000027: PUSH1 0x00 00000029: POP 0000002a: SLOAD 0000002b: TIMESTAMP 0000002c: SUB 0000002d: GT 0000002e: JUMPDEST 0000002f: ISZERO 00000030: PUSH2 0x00ed 00000033: JUMPI 00000034: DUP1 00000035: SLOAD 00000036: CALLVALUE 00000037: PUSH1 0x01 00000039: PUSH1 0xa0 0000003b: PUSH1 0x02 0000003d: EXP 0000003e: SUB 0000003f: ADDRESS 00000040: DUP2 00000041: AND 00000042: BALANCE 00000043: SWAP2 00000044: SWAP1 00000045: SWAP2 00000046: SUB 00000047: SWAP3 00000048: SWAP2 00000049: AND 0000004a: EQ 0000004b: PUSH2 0x0073 0000004e: JUMPI 0000004f: PUSH1 0x00 00000051: DUP1 00000052: SLOAD 00000053: PUSH1 0x01 00000055: PUSH1 0xa0 00000057: PUSH1 0x02 00000059: EXP 0000005a: SUB 0000005b: AND 0000005c: SWAP1 0000005d: PUSH1 0x0a 0000005f: PUSH1 0x06 00000061: DUP5 00000062: MUL 00000063: DIV 00000064: PUSH1 0x60 00000066: DUP3 00000067: DUP2 00000068: DUP2 00000069: DUP2 0000006a: DUP6 0000006b: DUP9 0000006c: DUP4 0000006d: CALL 0000006e: POP 0000006f: POP 00000070: POP 00000071: POP 00000072: POP 00000073: JUMPDEST 00000074: PUSH1 0x01 00000076: SLOAD 00000077: PUSH1 0x01 00000079: PUSH1 0xa0 0000007b: PUSH1 0x02 0000007d: EXP 0000007e: SUB 0000007f: AND 00000080: PUSH1 0x00 00000082: EQ 00000083: PUSH2 0x00b2 00000086: JUMPI 00000087: PUSH1 0x01 00000089: SLOAD 0000008a: PUSH1 0x40 0000008c: MLOAD 0000008d: PUSH1 0x01 0000008f: PUSH1 0xa0 00000091: PUSH1 0x02 00000093: EXP 00000094: SUB 00000095: SWAP2 00000096: SWAP1 00000097: SWAP2 00000098: AND 00000099: SWAP1 0000009a: PUSH1 0x00 0000009c: SWAP1 0000009d: PUSH1 0x0a 0000009f: PUSH1 0x02 000000a1: DUP6 000000a2: MUL 000000a3: DIV 000000a4: SWAP1 000000a5: DUP3 000000a6: DUP2 000000a7: DUP2 000000a8: DUP2 000000a9: DUP6 000000aa: DUP9 000000ab: DUP4 000000ac: CALL 000000ad: POP 000000ae: POP 000000af: POP 000000b0: POP 000000b1: POP 000000b2: JUMPDEST 000000b3: PUSH1 0x00 000000b5: PUSH1 0x02 000000b7: DUP2 000000b8: SWAP1 000000b9: SSTORE 000000ba: DUP1 000000bb: SLOAD 000000bc: PUSH20 0xffffffffffffffffffffffffffffffffffffffff 000000d1: NOT 000000d2: SWAP1 000000d3: DUP2 000000d4: AND 000000d5: SWAP1 000000d6: SWAP2 000000d7: SSTORE 000000d8: PUSH1 0x01 000000da: DUP1 000000db: SLOAD 000000dc: SWAP1 000000dd: SWAP2 000000de: AND 000000df: SWAP1 000000e0: SSTORE 000000e1: PUSH8 0x0de0b6b3a7640000 000000ea: PUSH1 0x03 000000ec: SSTORE 000000ed: JUMPDEST 000000ee: PUSH1 0x03 000000f0: SLOAD 000000f1: CALLVALUE 000000f2: LT 000000f3: ISZERO 000000f4: PUSH2 0x011f 000000f7: JUMPI 000000f8: PUSH1 0x40 000000fa: MLOAD 000000fb: CALLER 000000fc: PUSH1 0x01 000000fe: PUSH1 0xa0 00000100: PUSH1 0x02 00000102: EXP 00000103: SUB 00000104: AND 00000105: SWAP1 00000106: PUSH1 0x00 00000108: SWAP1 00000109: CALLVALUE 0000010a: SWAP1 0000010b: DUP3 0000010c: DUP2 0000010d: DUP2 0000010e: DUP2 0000010f: DUP6 00000110: DUP9 00000111: DUP4 00000112: CALL 00000113: SWAP4 00000114: POP 00000115: POP 00000116: POP 00000117: POP 00000118: POP 00000119: PUSH2 0x015c 0000011c: JUMP 0000011d: JUMPDEST 0000011e: STOP 0000011f: JUMPDEST 00000120: PUSH1 0x00 00000122: DUP1 00000123: SLOAD 00000124: PUSH1 0x01 00000126: DUP1 00000127: SLOAD 00000128: PUSH20 0xffffffffffffffffffffffffffffffffffffffff 0000013d: NOT 0000013e: SWAP1 0000013f: DUP2 00000140: AND 00000141: PUSH1 0x01 00000143: PUSH1 0xa0 00000145: PUSH1 0x02 00000147: EXP 00000148: SUB 00000149: DUP5 0000014a: AND 0000014b: OR 0000014c: SWAP1 0000014d: SWAP2 0000014e: SSTORE 0000014f: AND 00000150: CALLER 00000151: OR 00000152: SWAP1 00000153: SSTORE 00000154: CALLVALUE 00000155: PUSH1 0x03 00000157: SSTORE 00000158: TIMESTAMP 00000159: PUSH1 0x02 0000015b: SSTORE 0000015c: JUMPDEST 0000015d: POP 0000015e: JUMP
Warning: This is a nightly build of Foundry. It is recommended to use the latest stable version. To mute this warning set `FOUNDRY_DISABLE_NIGHTLY_WARNING` in your environment.
| Severity | Category | Tool | Title | Confidence | Validated | Confirmed | Details |
|---|---|---|---|---|---|---|---|
| high | other | detector | Untrusted CALL target/value reachable | 60 | yes | yes |
viewtrace_id: 0xcec881074db4fc85d9d1a11d2957b033a783502954d378179861cb6ee186543a
call_targets:
0x0000000000000000000000000000000000000001, 0xfc67bd301a4c698b461e5e9f26eab60d230b77a4
target_varies:
yes
classification:
target_varies
validation_json{
"sink": "CALL",
"errors": 0,
"status": "confirmed",
"attempts": 1,
"trace_id": "0xcec881074db4fc85d9d1a11d2957b033a783502954d378179861cb6ee186543a",
"confirmed": true,
"trace_mode": "callTracer",
"call_targets": [
"0x0000000000000000000000000000000000000001",
"0xfc67bd301a4c698b461e5e9f26eab60d230b77a4"
],
"matched_probe": null,
"target_varies": true,
"classification": "target_varies"
}
witness_json{
"notes": "heuristic witness; entrypoints are best-effort selectors with zeroed calldata",
"constraints": [],
"entrypoints": [
{
"calldata": "0x",
"selector": "fallback",
"calldata_variants": [
"0x"
]
}
]
}
evidence_json{
"examples": [
{
"pc": 109,
"opcode": "CALL",
"returndata_checked": null,
"value_expression_category": "computed",
"target_expression_category": "computed"
},
{
"pc": 172,
"opcode": "CALL",
"returndata_checked": null,
"value_expression_category": "computed",
"target_expression_category": "computed"
},
{
"pc": 274,
"opcode": "CALL",
"returndata_checked": null,
"value_expression_category": "computed",
"target_expression_category": "computed"
}
],
"call_count": 3,
"guards_detected": [],
"untrusted_call_count": 3
}
|
| high | other | detector | ETH value transfer possible | 55 | yes | yes |
viewtrace_id: 0xcec881074db4fc85d9d1a11d2957b033a783502954d378179861cb6ee186543a
call_targets:
0x0000000000000000000000000000000000000001, 0xfc67bd301a4c698b461e5e9f26eab60d230b77a4
target_varies:
yes
classification:
target_varies
validation_json{
"sink": "CALL",
"errors": 0,
"status": "confirmed",
"attempts": 1,
"trace_id": "0xcec881074db4fc85d9d1a11d2957b033a783502954d378179861cb6ee186543a",
"confirmed": true,
"trace_mode": "callTracer",
"call_targets": [
"0x0000000000000000000000000000000000000001",
"0xfc67bd301a4c698b461e5e9f26eab60d230b77a4"
],
"matched_probe": null,
"target_varies": true,
"classification": "target_varies"
}
witness_json{
"notes": "heuristic witness; entrypoints are best-effort selectors with zeroed calldata",
"constraints": [],
"entrypoints": [
{
"calldata": "0x",
"selector": "fallback",
"calldata_variants": [
"0x"
]
}
]
}
evidence_json{
"examples": [
{
"pc": 109,
"opcode": "CALL",
"returndata_checked": null,
"value_expression_category": "computed",
"target_expression_category": "computed"
},
{
"pc": 172,
"opcode": "CALL",
"returndata_checked": null,
"value_expression_category": "computed",
"target_expression_category": "computed"
},
{
"pc": 274,
"opcode": "CALL",
"returndata_checked": null,
"value_expression_category": "computed",
"target_expression_category": "computed"
}
],
"eth_value_calls": 3,
"guards_detected": []
}
|
| high | reentrancy | codex | External payout calls occur before round state is cleared | 85 | no | — |
viewevidence_json{
"evidence": "The artifact reports no detected guards (`auth.guards=[]`) and three CALL sites. The first two CALLs are at pc 109/0x6d and 172/0xac, both with `returndata_checked: null` and computed targets/values. State-reset writes happen only afterward at pc 185/0xb9 (slot 2), pc 215-216/0xd7-0xd8 and pc 224/0xe0 (slot 0/1 cleanup), and pc 236/0xec (slot 3 reset). Recipient addresses appear user-influenced because the fallback update routine writes slots 1 and 0 at pc 334/0x14e and pc 339/0x153. Detector finding `Untrusted CALL target/value reachable` is validated/confirmed.",
"locations": [
"pc:0x6d",
"pc:0xac",
"pc:0xb9",
"pc:0xd7",
"pc:0xe0",
"pc:0xec",
"pc:0x14e",
"pc:0x153"
],
"recommendation": "Apply checks-effects-interactions: fully clear or checkpoint the active round before any external CALL, or add an explicit reentrancy guard around the fallback payout path. If payouts must remain external, store owed balances and let recipients withdraw in a separate pull-payment flow.",
"exploit_scenario": "A prior participant can register a contract as one of the payout recipients via the fallback update path. When the expiry/payout branch executes, the contract performs value-bearing CALLs to stored recipient addresses at pc 0x6d and pc 0xac before clearing slot 2 and before wiping the recipient fields in slots 0/1. A malicious recipient can reenter the fallback during the first payout while the old state is still live, potentially triggering the payout logic repeatedly and draining more of the contract balance than intended. This is based on bytecode-only reasoning, so the exact branch condition is inferred rather than source-confirmed."
}
|
| medium | other | codex | Outbound ETH transfers ignore CALL success and continue | 75 | no | — |
viewevidence_json{
"evidence": "All three callsites in the bundle have `returndata_checked: null`: pc 109/0x6d, 172/0xac, and 274/0x112. In the bytecode, each CALL is followed by POPs rather than a conditional revert path, so success is discarded. After the payout CALLs, execution continues into storage writes that clear/reset state (pc 0xb9, 0xd7, 0xe0, 0xec), which creates accounting risk if the transfer did not actually occur. Detector finding `ETH value transfer possible` is validated/confirmed.",
"locations": [
"pc:0x6d",
"pc:0xac",
"pc:0x112",
"pc:0xb9",
"pc:0xd7",
"pc:0xe0",
"pc:0xec"
],
"recommendation": "Check the boolean result of each CALL and revert on failure, or convert the design to pull-based withdrawals so failed recipients cannot silently break accounting. If non-reverting behavior is required, record failed payouts as claimable balances instead of discarding the failure.",
"exploit_scenario": "If a payout recipient or refund recipient is a contract that reverts or otherwise makes the CALL fail, this bytecode does not check the returned success flag before continuing. On the payout path, the contract appears to proceed into state cleanup and round reset even when one or both payouts fail, which can skip owed payments and strand funds in the contract. On the refund-like path at pc 0x112, a failed ETH send to `CALLER` is also ignored."
}
|