019c0ea9-070a-72de-9802-b9a1e36ddc57
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 |
|---|---|---|---|---|
| 41501 | artifact.fetch | complete | 1 / 3 | 2 months ago |
| 41502 | proxy.resolve | complete | 1 / 3 | 2 months ago |
| 41503 | tool.cast_disasm | complete | 1 / 3 | 2 months ago |
| 41504 | analysis.bundle | complete | 1 / 3 | 2 months ago |
| 41505 | capability.graph | complete | 1 / 3 | 2 months ago |
| 41506 | detector.run | complete | 1 / 3 | 2 months ago |
| 41507 | validation.fork | complete | 1 / 3 | 2 months ago |
| 42187 | report.consolidate | complete | 1 / 6 | 2 months ago |
{
"method": "eip1967",
"status": "onchain_only",
"implementation": "0x7e0ae8e65fc3c322c9f2bedf630ce8ef799e292e",
"onchain_method": "eip1967"
}
No slither job recorded yet.
{"no_findings":false,"summary":"Bytecode shows a UUPS-style upgradeable implementation with an externally callable initializer and owner-only arbitrary call helpers. Main risks are uninitialized-proxy takeover and the admin’s broad powers if compromised.","findings":[{"severity":"medium","category":"upgradeability","title":"Initializer can be called by anyone if the proxy is left uninitialized","exploit_scenario":"If the proxy is deployed without executing the initializer, any caller can invoke selector 0xcd6dc687, which writes critical admin/state slots (e.g., slot 0x66). The attacker becomes the privileged admin and can then upgrade the proxy to malicious logic or use admin-only call functions to drain assets.","recommendation":"Ensure the proxy is initialized atomically at deployment (pass initializer calldata to the proxy constructor). Also disable initializers on the implementation instance (e.g., _disableInitializers) to prevent direct initialization and document the required initialization flow.","evidence":"Initializer path writes to slot 0x66 (SSTORE at pc:1915) and other critical slots (pc:1920) with only the Initializable guard (slot 0 check, SSTORE at pc:2822). No caller check is observed before these writes.","locations":["selector:0xcd6dc687","pc:1915","pc:1920","pc:2822"]},{"severity":"low","category":"access_control","title":"Owner-only arbitrary external call with ETH transfer capability","exploit_scenario":"Selectors 0x0f4414c8 and 0x4847a79c perform low-level CALLs to computed targets (pc:563, pc:1199). If the admin key (slot 0x66) is compromised, an attacker can transfer ETH from the contract or invoke arbitrary external contracts, potentially draining funds or triggering reentrancy in downstream targets.","recommendation":"Treat the admin as a highly privileged role (multisig/timelock), and consider restricting these functions (allowlist) or removing them if not required. Ensure operational procedures mitigate key compromise.","evidence":"Low-level CALLs at pc:563 and pc:1199 with computed target/value. Authorization check appears to compare CALLER to slot 0x66 at pc:1998.","locations":["selector:0x0f4414c8","pc:563","selector:0x4847a79c","pc:1199","pc:1998"]}]}
OpenAI Codex v0.77.0 (research preview)
--------
workdir: /tmp/codex-cv27gx3n
model: gpt-5.2-codex
provider: openai
approval: never
sandbox: read-only
reasoning effort: high
reasoning summaries: auto
session id: 019c0eb0-9b1e-7513-9873-038604cd2c8a
--------
user
Context: The user requested the proxy at 0x095c35b4217770893fbb7cf533869afce1b27a78.
Audit the implementation at 0x7e0ae8e65fc3c322c9f2bedf630ce8ef799e292e.
Findings should refer to the implementation unless explicitly about proxy mechanics.
You are a security auditor. You ONLY have runtime bytecode + analysis artifacts.
You MUST read `BYTECODE_BUNDLE.json` before concluding; it contains the bytecode summary,
evidence bundle, callsites, storage slots, and detector findings.
Special cases when reasoning from bytecode (be explicit about uncertainty):
- Selector inference is best-effort; missing selectors are common.
- Fallback/receive paths may be the only entrypoints.
- CALL vs DELEGATECALL semantics differ; DELEGATECALL executes in caller storage.
- Proxy patterns (EIP-1967, minimal proxies, beacon) change which storage is authoritative.
- Storage slots are raw; mappings/arrays appear via keccak patterns, names are unknown.
- Guard detection is heuristic; absence of guards does NOT mean unguarded.
- Returndata checking is unknown unless explicitly shown in evidence.
- Precompiles (0x1..0x9) and common ERC20 transfer selectors may appear; do not over-claim.
Output MUST be valid JSON matching the provided schema.
- If you find nothing meaningful: set no_findings=true and findings=[].
- Otherwise: set no_findings=false and include findings with severity/category/title.
- Locations can be pc references like "pc:0x123" or selectors like "selector:0xa9059cbb".
Focus on: reentrancy, access control, upgradeability/proxy issues, signature validation,
accounting/invariant breaks, dangerous delegatecall, and untrusted external calls.
Be conservative: if evidence is weak, mark severity low/medium and explain why.
mcp startup: no servers
exec
/bin/bash -lc ls in /tmp/codex-cv27gx3n succeeded in 6ms:
BYTECODE_BUNDLE.json
codex-output-schema.json
exec
/bin/bash -lc 'cat BYTECODE_BUNDLE.json' in /tmp/codex-cv27gx3n succeeded in 7ms:
{
"analysis_artifact": {
"address": "0x7e0ae8e65fc3c322c9f2bedf630ce8ef799e292e",
"artifact_hash": "0x8819dced5c43b7292431c83555e507d5f017a9fdeb572e6df22ba182d6a261a4",
"artifact_json": {
"auth": {
"guards": []
},
"basic_blocks": [
{
"end_pc": 12,
"hash": "0x7226f32bd1464d2f0494bff81111618f88488e0fa37dc599c9907e2b1d214668",
"opcodes": [
"PUSH1",
"PUSH1",
"MSTORE",
"PUSH1",
"CALLDATASIZE",
"LT",
"PUSH2",
exec
/bin/bash -lc 'rg -n "storage|slot|selector|callsite|delegatecall|selfdestruct|impl|implementation|eip" BYTECODE_BUNDLE.json' in /tmp/codex-cv27gx3n succeeded in 9ms:
3636: "callsites": [
4704: "dispatcher_type": "selector_jump_table",
4708: "selector": "0x52d1902d"
4712: "selector": "0x6323d7af"
4716: "selector": "0xcd6dc687"
4720: "selector": "0x4847a79c"
4724: "selector": "0x4f1ef286"
4728: "selector": "0x0f4414c8"
4732: "selector": "0x150b7a02"
4736: "selector": "0x3659cfe6"
4740: "selector": "0x375974eb"
4749: "selector": "0x52d1902d",
4752: "delegatecall": 1,
4753: "selfdestruct": 1,
4756: "storage": {
4758: "slots": [
4762: "slot": "0x0000000000000000000000000000000000000000000000000000000000000065"
4767: "slot": "0x0000000000000000000000000000000000000000000000000000000000000066"
4772: "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"
4777: "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"
exec
/bin/bash -lc "sed -n '3600,3720p' BYTECODE_BUNDLE.json" in /tmp/codex-cv27gx3n succeeded in 6ms:
"SELFDESTRUCT"
],
"start_pc": 4363
},
{
"end_pc": 4450,
"hash": "0x424b28caf4fc803df0980311dad2d1107b569537cadd72c9062c0ebd6e79da6f",
"opcodes": [
"OP_D1",
"OP_D5",
"OP_9B",
"OP_0F",
"PUSH5",
"STOP"
],
"start_pc": 4440
},
{
"end_pc": 4453,
"hash": "0xc6696f917b4d3718b9a0ecb35311b56723647991e403041867d2a4a2932748ba",
exec
/bin/bash -lc "sed -n '4680,4785p' BYTECODE_BUNDLE.json" in /tmp/codex-cv27gx3n succeeded in 7ms:
"type": "control_flow_fallthrough"
},
{
"from": "bb:4290",
"to": "bb:4308",
"type": "control_flow"
},
{
"from": "bb:4290",
"to": "bb:4304",
"type": "control_flow_fallthrough"
},
{
"from": "bb:4315",
"to": "bb:3650",
"type": "control_flow"
},
{
"from": "bb:4343",
"to": "bb:3694",
exec
/bin/bash -lc "sed -n '4785,4905p' BYTECODE_BUNDLE.json" in /tmp/codex-cv27gx3n succeeded in 6ms:
"op": "SLOAD",
"pc": 1868,
"slot": "0x0000000000000000000000000000000000000000000000000000000000000066"
},
{
"op": "SLOAD",
"pc": 1930,
"slot": "0x0000000000000000000000000000000000000000000000000000000000000000"
},
{
"op": "SLOAD",
"pc": 2001,
"slot": "0x0000000000000000000000000000000000000000000000000000000000000066"
},
{
"op": "SLOAD",
"pc": 2132,
"slot": "0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143"
},
{
exec
/bin/bash -lc 'rg -n "3313" BYTECODE_BUNDLE.json' in /tmp/codex-cv27gx3n succeeded in 9ms:
3660: "pc": 3313,
5658: "full": "0x60806040526004361061009a5760003560e01c80634847a79c1161006957806352d1902d1161004e57806352d1902d146101a25780636323d7af146101b7578063cd6dc687146101df57600080fd5b80634847a79c1461016f5780634f1ef2861461018f57600080fd5b80630f4414c8146100a6578063150b7a02146100dd5780633659cfe61461012e578063375974eb1461015057600080fd5b366100a157005b600080fd5b3480156100b257600080fd5b506100c66100c1366004610def565b6101ff565b6040516100d4929190610e9a565b60405180910390f35b3480156100e957600080fd5b506100fd6100f8366004610ebd565b610274565b6040517fffffffff0000000000000000000000000000000000000000000000000000000090911681526020016100d4565b34801561013a57600080fd5b5061014e610149366004610f2c565b6102e1565b005b34801561015c57600080fd5b506065545b6040519081526020016100d4565b34801561017b57600080fd5b506100c661018a366004610f47565b610483565b61014e61019d366004610fa0565b6104d0565b3480156101ae57600080fd5b5061016161065e565b3480156101c357600080fd5b506066546040516001600160a01b0390911681526020016100d4565b3480156101eb57600080fd5b5061014e6101fa366004610f47565b610723565b6000606061020b6107ce565b846001600160a01b03168484604051610225929190611062565b6000604051808303816000865af19150503d8060008114610262576040519150601f19603f3d011682016040523d82523d6000602084013e610267565b606091505b5091509150935093915050565b6040805160048152602481019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f150b7a02000000000000000000000000000000000000000000000000000000001790526000906102d790611072565b9695505050505050565b6001600160a01b037f0000000000000000000000007e0ae8e65fc3c322c9f2bedf630ce8ef799e292e1630036103845760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c000000000000000000000000000000000000000060648201526084015b60405180910390fd5b7f0000000000000000000000007e0ae8e65fc3c322c9f2bedf630ce8ef799e292e6001600160a01b03166103df7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b03161461045b5760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f78790000000000000000000000000000000000000000606482015260840161037b565b6104648161082a565b6040805160008082526020820190925261048091839190610832565b50565b6000606061048f6107ce565b6040516001600160a01b0385169084156108fc029085906000818181858888f1935050505060405180602001604052806000815250915091505b9250929050565b6001600160a01b037f0000000000000000000000007e0ae8e65fc3c322c9f2bedf630ce8ef799e292e16300361056e5760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c0000000000000000000000000000000000000000606482015260840161037b565b7f0000000000000000000000007e0ae8e65fc3c322c9f2bedf630ce8ef799e292e6001600160a01b03166105c97f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b0316146106455760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f78790000000000000000000000000000000000000000606482015260840161037b565b61064e8261082a565b61065a82826001610832565b5050565b6000306001600160a01b037f0000000000000000000000007e0ae8e65fc3c322c9f2bedf630ce8ef799e292e16146106fe5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c0000000000000000606482015260840161037b565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b60016000610730826109d7565b90508015610748576000805461ff0019166101001790555b606680547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038616179055606583905580156107c8576000805461ff001916905560405160ff831681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b6066546001600160a01b031633146108285760405162461bcd60e51b815260206004820152601260248201527f556e2d617574686f72697a65642063616c6c0000000000000000000000000000604482015260640161037b565b565b6104806107ce565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff161561086a5761086583610b10565b505050565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156108c4575060408051601f3d908101601f191682019092526108c1918101906110c2565b60015b6109365760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201527f6f6e206973206e6f742055555053000000000000000000000000000000000000606482015260840161037b565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81146109cb5760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f7860448201527f6961626c65555549440000000000000000000000000000000000000000000000606482015260840161037b565b50610865838383610be6565b60008054610100900460ff1615610a74578160ff1660011480156109fa5750303b155b610a6c5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161037b565b506000919050565b60005460ff808416911610610af15760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161037b565b506000805460ff191660ff92909216919091179055600190565b919050565b6001600160a01b0381163b610b8d5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e747261637400000000000000000000000000000000000000606482015260840161037b565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b610bef83610c0b565b600082511180610bfc5750805b15610865576107c88383610c4b565b610c1481610b10565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606001600160a01b0383163b610cca5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e74726163740000000000000000000000000000000000000000000000000000606482015260840161037b565b600080846001600160a01b031684604051610ce591906110db565b600060405180830381855af49150503d8060008114610d20576040519150601f19603f3d011682016040523d82523d6000602084013e610d25565b606091505b5091509150610d4d828260405180606001604052806027815260200161110b60279139610d56565b95945050505050565b60608315610d65575081610d8f565b825115610d755782518084602001fd5b8160405162461bcd60e51b815260040161037b91906110f7565b9392505050565b80356001600160a01b0381168114610b0b57600080fd5b60008083601f840112610dbf57600080fd5b50813567ffffffffffffffff811115610dd757600080fd5b6020830191508360208285010111156104c957600080fd5b600080600060408486031215610e0457600080fd5b610e0d84610d96565b9250602084013567ffffffffffffffff811115610e2957600080fd5b610e3586828701610dad565b9497909650939450505050565b60005b83811015610e5d578181015183820152602001610e45565b838111156107c85750506000910152565b60008151808452610e86816020860160208601610e42565b601f01601f19169290920160200192915050565b8215158152604060208201526000610eb56040830184610e6e565b949350505050565b600080600080600060808688031215610ed557600080fd5b610ede86610d96565b9450610eec60208701610d96565b935060408601359250606086013567ffffffffffffffff811115610f0f57600080fd5b610f1b88828901610dad565b969995985093965092949392505050565b600060208284031215610f3e57600080fd5b610d8f82610d96565b60008060408385031215610f5a57600080fd5b610f6383610d96565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60008060408385031215610fb357600080fd5b610fbc83610d96565b9150602083013567ffffffffffffffff80821115610fd957600080fd5b818501915085601f830112610fed57600080fd5b813581811115610fff57610fff610f71565b604051601f8201601f19908116603f0116810190838211818310171561102757611027610f71565b8160405282815288602084870101111561104057600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b8183823760009101908152919050565b6000815160208301517fffffffff00000000000000000000000000000000000000000000000000000000808216935060048310156110ba5780818460040360031b1b83161693505b505050919050565b6000602082840312156110d457600080fd5b5051919050565b600082516110ed818460208701610e42565b9190910192915050565b602081526000610d8f6020830184610e6e56fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212202cbb61a35c0b1b1abc5c2330a9d39e022523cd1e643481d730339effd1d59b0f64736f6c634300080d0033",
6772: "to": "call:3313",
6776: "from": "call:3313",
8264: "id": "call:3313",
8266: "pc": 3313,
8350: "pc": 3313,
exec
/bin/bash -lc 'rg -n "6107ce" BYTECODE_BUNDLE.json' in /tmp/codex-cv27gx3n succeeded in 6ms:
5658: "full": "0x60806040526004361061009a5760003560e01c80634847a79c1161006957806352d1902d1161004e57806352d1902d146101a25780636323d7af146101b7578063cd6dc687146101df57600080fd5b80634847a79c1461016f5780634f1ef2861461018f57600080fd5b80630f4414c8146100a6578063150b7a02146100dd5780633659cfe61461012e578063375974eb1461015057600080fd5b366100a157005b600080fd5b3480156100b257600080fd5b506100c66100c1366004610def565b6101ff565b6040516100d4929190610e9a565b60405180910390f35b3480156100e957600080fd5b506100fd6100f8366004610ebd565b610274565b6040517fffffffff0000000000000000000000000000000000000000000000000000000090911681526020016100d4565b34801561013a57600080fd5b5061014e610149366004610f2c565b6102e1565b005b34801561015c57600080fd5b506065545b6040519081526020016100d4565b34801561017b57600080fd5b506100c661018a366004610f47565b610483565b61014e61019d366004610fa0565b6104d0565b3480156101ae57600080fd5b5061016161065e565b3480156101c357600080fd5b506066546040516001600160a01b0390911681526020016100d4565b3480156101eb57600080fd5b5061014e6101fa366004610f47565b610723565b6000606061020b6107ce565b846001600160a01b03168484604051610225929190611062565b6000604051808303816000865af19150503d8060008114610262576040519150601f19603f3d011682016040523d82523d6000602084013e610267565b606091505b5091509150935093915050565b6040805160048152602481019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f150b7a02000000000000000000000000000000000000000000000000000000001790526000906102d790611072565b9695505050505050565b6001600160a01b037f0000000000000000000000007e0ae8e65fc3c322c9f2bedf630ce8ef799e292e1630036103845760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c000000000000000000000000000000000000000060648201526084015b60405180910390fd5b7f0000000000000000000000007e0ae8e65fc3c322c9f2bedf630ce8ef799e292e6001600160a01b03166103df7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b03161461045b5760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f78790000000000000000000000000000000000000000606482015260840161037b565b6104648161082a565b6040805160008082526020820190925261048091839190610832565b50565b6000606061048f6107ce565b6040516001600160a01b0385169084156108fc029085906000818181858888f1935050505060405180602001604052806000815250915091505b9250929050565b6001600160a01b037f0000000000000000000000007e0ae8e65fc3c322c9f2bedf630ce8ef799e292e16300361056e5760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c0000000000000000000000000000000000000000606482015260840161037b565b7f0000000000000000000000007e0ae8e65fc3c322c9f2bedf630ce8ef799e292e6001600160a01b03166105c97f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b0316146106455760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f78790000000000000000000000000000000000000000606482015260840161037b565b61064e8261082a565b61065a82826001610832565b5050565b6000306001600160a01b037f0000000000000000000000007e0ae8e65fc3c322c9f2bedf630ce8ef799e292e16146106fe5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c0000000000000000606482015260840161037b565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b60016000610730826109d7565b90508015610748576000805461ff0019166101001790555b606680547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038616179055606583905580156107c8576000805461ff001916905560405160ff831681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b6066546001600160a01b031633146108285760405162461bcd60e51b815260206004820152601260248201527f556e2d617574686f72697a65642063616c6c0000000000000000000000000000604482015260640161037b565b565b6104806107ce565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff161561086a5761086583610b10565b505050565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156108c4575060408051601f3d908101601f191682019092526108c1918101906110c2565b60015b6109365760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201527f6f6e206973206e6f742055555053000000000000000000000000000000000000606482015260840161037b565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81146109cb5760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f7860448201527f6961626c65555549440000000000000000000000000000000000000000000000606482015260840161037b565b50610865838383610be6565b60008054610100900460ff1615610a74578160ff1660011480156109fa5750303b155b610a6c5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161037b565b506000919050565b60005460ff808416911610610af15760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161037b565b506000805460ff191660ff92909216919091179055600190565b919050565b6001600160a01b0381163b610b8d5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e747261637400000000000000000000000000000000000000606482015260840161037b565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b610bef83610c0b565b600082511180610bfc5750805b15610865576107c88383610c4b565b610c1481610b10565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606001600160a01b0383163b610cca5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e74726163740000000000000000000000000000000000000000000000000000606482015260840161037b565b600080846001600160a01b031684604051610ce591906110db565b600060405180830381855af49150503d8060008114610d20576040519150601f19603f3d011682016040523d82523d6000602084013e610d25565b606091505b5091509150610d4d828260405180606001604052806027815260200161110b60279139610d56565b95945050505050565b60608315610d65575081610d8f565b825115610d755782518084602001fd5b8160405162461bcd60e51b815260040161037b91906110f7565b9392505050565b80356001600160a01b0381168114610b0b57600080fd5b60008083601f840112610dbf57600080fd5b50813567ffffffffffffffff811115610dd757600080fd5b6020830191508360208285010111156104c957600080fd5b600080600060408486031215610e0457600080fd5b610e0d84610d96565b9250602084013567ffffffffffffffff811115610e2957600080fd5b610e3586828701610dad565b9497909650939450505050565b60005b83811015610e5d578181015183820152602001610e45565b838111156107c85750506000910152565b60008151808452610e86816020860160208601610e42565b601f01601f19169290920160200192915050565b8215158152604060208201526000610eb56040830184610e6e565b949350505050565b600080600080600060808688031215610ed557600080fd5b610ede86610d96565b9450610eec60208701610d96565b935060408601359250606086013567ffffffffffffffff811115610f0f57600080fd5b610f1b88828901610dad565b969995985093965092949392505050565b600060208284031215610f3e57600080fd5b610d8f82610d96565b60008060408385031215610f5a57600080fd5b610f6383610d96565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60008060408385031215610fb357600080fd5b610fbc83610d96565b9150602083013567ffffffffffffffff80821115610fd957600080fd5b818501915085601f830112610fed57600080fd5b813581811115610fff57610fff610f71565b604051601f8201601f19908116603f0116810190838211818310171561102757611027610f71565b8160405282815288602084870101111561104057600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b8183823760009101908152919050565b6000815160208301517fffffffff00000000000000000000000000000000000000000000000000000000808216935060048310156110ba5780818460040360031b1b83161693505b505050919050565b6000602082840312156110d457600080fd5b5051919050565b600082516110ed818460208701610e42565b9190910192915050565b602081526000610d8f6020830184610e6e56fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212202cbb61a35c0b1b1abc5c2330a9d39e022523cd1e643481d730339effd1d59b0f64736f6c634300080d0033",
exec
/bin/bash -lc "python - <<'PY'
import json, binascii
from pathlib import Path
data=json.loads(Path('BYTECODE_BUNDLE.json').read_text())
full=data['analysis_artifact']['artifact_json']['full']
if full.startswith('0x'): full=full[2:]
code=bytes.fromhex(full)
# opcode names map
opnames = {}
# basic opcodes
for i in range(0x00,0x100):
opnames[i]=None
# define
base={
0x00:'STOP',0x01:'ADD',0x02:'MUL',0x03:'SUB',0x04:'DIV',0x05:'SDIV',0x06:'MOD',0x07:'SMOD',0x08:'ADDMOD',0x09:'MULMOD',0x0a:'EXP',0x0b:'SIGNEXTEND',
0x10:'LT',0x11:'GT',0x12:'SLT',0x13:'SGT',0x14:'EQ',0x15:'ISZERO',0x16:'AND',0x17:'OR',0x18:'XOR',0x19:'NOT',0x1a:'BYTE',0x1b:'SHL',0x1c:'SHR',0x1d:'SAR',
0x20:'SHA3',
0x30:'ADDRESS',0x31:'BALANCE',0x32:'ORIGIN',0x33:'CALLER',0x34:'CALLVALUE',0x35:'CALLDATALOAD',0x36:'CALLDATASIZE',0x37:'CALLDATACOPY',0x38:'CODESIZE',0x39:'CODECOPY',0x3a:'GASPRICE',0x3b:'EXTCODESIZE',0x3c:'EXTCODECOPY',0x3d:'RETURNDATASIZE',0x3e:'RETURNDATACOPY',0x3f:'EXTCODEHASH',
0x40:'BLOCKHASH',0x41:'COINBASE',0x42:'TIMESTAMP',0x43:'NUMBER',0x44:'DIFFICULTY',0x45:'GASLIMIT',0x46:'CHAINID',0x47:'SELFBALANCE',0x48:'BASEFEE',
0x50:'POP',0x51:'MLOAD',0x52:'MSTORE',0x53:'MSTORE8',0x54:'SLOAD',0x55:'SSTORE',0x56:'JUMP',0x57:'JUMPI',0x58:'PC',0x59:'MSIZE',0x5a:'GAS',0x5b:'JUMPDEST',
0x60:'PUSH1',0x61:'PUSH2',0x62:'PUSH3',0x63:'PUSH4',0x64:'PUSH5',0x65:'PUSH6',0x66:'PUSH7',0x67:'PUSH8',0x68:'PUSH9',0x69:'PUSH10',0x6a:'PUSH11',0x6b:'PUSH12',0x6c:'PUSH13',0x6d:'PUSH14',0x6e:'PUSH15',0x6f:'PUSH16',
0x70:'PUSH17',0x71:'PUSH18',0x72:'PUSH19',0x73:'PUSH20',0x74:'PUSH21',0x75:'PUSH22',0x76:'PUSH23',0x77:'PUSH24',0x78:'PUSH25',0x79:'PUSH26',0x7a:'PUSH27',0x7b:'PUSH28',0x7c:'PUSH29',0x7d:'PUSH30',0x7e:'PUSH31',0x7f:'PUSH32',
0x80:'DUP1',0x81:'DUP2',0x82:'DUP3',0x83:'DUP4',0x84:'DUP5',0x85:'DUP6',0x86:'DUP7',0x87:'DUP8',0x88:'DUP9',0x89:'DUP10',0x8a:'DUP11',0x8b:'DUP12',0x8c:'DUP13',0x8d:'DUP14',0x8e:'DUP15',0x8f:'DUP16',
0x90:'SWAP1',0x91:'SWAP2',0x92:'SWAP3',0x93:'SWAP4',0x94:'SWAP5',0x95:'SWAP6',0x96:'SWAP7',0x97:'SWAP8',0x98:'SWAP9',0x99:'SWAP10',0x9a:'SWAP11',0x9b:'SWAP12',0x9c:'SWAP13',0x9d:'SWAP14',0x9e:'SWAP15',0x9f:'SWAP16',
0xa0:'LOG0',0xa1:'LOG1',0xa2:'LOG2',0xa3:'LOG3',0xa4:'LOG4',
0xf0:'CREATE',0xf1:'CALL',0xf2:'CALLCODE',0xf3:'RETURN',0xf4:'DELEGATECALL',0xf5:'CREATE2',0xfa:'STATICCALL',0xfd:'REVERT',0xfe:'INVALID',0xff:'SELFDESTRUCT',
}
for k,v in base.items(): opnames[k]=v
# disassemble around a pc window
def disasm_window(target_pc, window=40):
# walk through code to map pc->(op,imm)
pc=0
mapping=[]
while pc < len(code):
op=code[pc]
name=opnames.get(op,'UNKNOWN')
if name and name.startswith('PUSH'):
n=op-0x5f
imm=code[pc+1:pc+1+n]
mapping.append((pc,name,imm))
pc+=1+n
else:
mapping.append((pc,name,b''))
pc+=1
# find index
idx=next((i for i,(p,_,_) in enumerate(mapping) if p==target_pc),None)
if idx is None:
# find nearest
idx=next((i for i,(p,_,_) in enumerate(mapping) if p>target_pc),len(mapping)-1)
start=max(0, idx-window)
end=min(len(mapping), idx+window)
for p,name,imm in mapping[start:end]:
marker='>>' if p==target_pc else ' '
if imm:
imm_hex=imm.hex()
print(f\"{marker} {p:04d}: {name} 0x{imm_hex}\")
else:
print(f\"{marker} {p:04d}: {name}\")
for pc in [563,1199,3313,4363]:
print('--- pc',pc)
disasm_window(pc, window=20)
PY" in /tmp/codex-cv27gx3n exited 1 in 35ms:
Traceback (most recent call last):
File "<stdin>", line 5, in <module>
KeyError: 'full'
exec
/bin/bash -lc "python - <<'PY'
import json
from pathlib import Path
j=json.loads(Path('BYTECODE_BUNDLE.json').read_text())
print(j.keys())
print(j['analysis_artifact'].keys())
print(j['analysis_artifact']['artifact_json'].keys())
PY" in /tmp/codex-cv27gx3n succeeded in 30ms:
dict_keys(['analysis_artifact', 'analysis_run', 'artifact', 'capability_graph', 'detector_findings', 'heuristics_summary'])
dict_keys(['address', 'artifact_hash', 'artifact_json', 'block_number', 'chain_id', 'codehash', 'created_at', 'id', 'updated_at', 'version'])
dict_keys(['auth', 'basic_blocks', 'callsites', 'cfg_edges', 'cfg_hash', 'dispatcher_type', 'function_entries', 'functions', 'selectors', 'sinks', 'storage', 'version'])
exec
/bin/bash -lc "python - <<'PY'
import json
from pathlib import Path
j=json.loads(Path('BYTECODE_BUNDLE.json').read_text())
print(j['artifact'].keys())
print(j['artifact']['artifact_json'].keys())
PY" in /tmp/codex-cv27gx3n exited 1 in 44ms:
dict_keys(['codehash', 'compiler_json', 'implementation_address', 'is_proxy', 'runtime_bytecode', 'verified_source'])
Traceback (most recent call last):
File "<stdin>", line 5, in <module>
KeyError: 'artifact_json'
exec
/bin/bash -lc "python - <<'PY'
import json
from pathlib import Path
j=json.loads(Path('BYTECODE_BUNDLE.json').read_text())
print(j['capability_graph'].keys())
PY" in /tmp/codex-cv27gx3n succeeded in 41ms:
dict_keys(['address', 'block_number', 'chain_id', 'codehash', 'created_at', 'graph_hash', 'graph_json', 'id', 'updated_at', 'version'])
exec
/bin/bash -lc "python - <<'PY'
import json
from pathlib import Path
j=json.loads(Path('BYTECODE_BUNDLE.json').read_text())
print(j['capability_graph']['graph_json'].keys())
PY" in /tmp/codex-cv27gx3n succeeded in 36ms:
dict_keys(['edges', 'nodes', 'version'])
exec
/bin/bash -lc "python - <<'PY'
import json
from pathlib import Path
j=json.loads(Path('BYTECODE_BUNDLE.json').read_text())
print(j['artifact'].keys())
print(type(j['artifact']['runtime_bytecode']))
print(j['artifact']['runtime_bytecode'][:20])
PY" in /tmp/codex-cv27gx3n exited 1 in 36ms:
dict_keys(['codehash', 'compiler_json', 'implementation_address', 'is_proxy', 'runtime_bytecode', 'verified_source'])
<class 'dict'>
Traceback (most recent call last):
File "<stdin>", line 6, in <module>
KeyError: slice(None, 20, None)
exec
/bin/bash -lc "python - <<'PY'
import json
from pathlib import Path
j=json.loads(Path('BYTECODE_BUNDLE.json').read_text())
print(j['artifact']['runtime_bytecode'].keys())
PY" in /tmp/codex-cv27gx3n succeeded in 30ms:
dict_keys(['full', 'head', 'length', 'tail', 'truncated'])
exec
/bin/bash -lc "python - <<'PY'
import json
from pathlib import Path
j=json.loads(Path('BYTECODE_BUNDLE.json').read_text())
full=j['artifact']['runtime_bytecode']['full']
if full.startswith('0x'): full=full[2:]
code=bytes.fromhex(full)
opnames = {}
base={
0x00:'STOP',0x01:'ADD',0x02:'MUL',0x03:'SUB',0x04:'DIV',0x05:'SDIV',0x06:'MOD',0x07:'SMOD',0x08:'ADDMOD',0x09:'MULMOD',0x0a:'EXP',0x0b:'SIGNEXTEND',
0x10:'LT',0x11:'GT',0x12:'SLT',0x13:'SGT',0x14:'EQ',0x15:'ISZERO',0x16:'AND',0x17:'OR',0x18:'XOR',0x19:'NOT',0x1a:'BYTE',0x1b:'SHL',0x1c:'SHR',0x1d:'SAR',
0x20:'SHA3',
0x30:'ADDRESS',0x31:'BALANCE',0x32:'ORIGIN',0x33:'CALLER',0x34:'CALLVALUE',0x35:'CALLDATALOAD',0x36:'CALLDATASIZE',0x37:'CALLDATACOPY',0x38:'CODESIZE',0x39:'CODECOPY',0x3a:'GASPRICE',0x3b:'EXTCODESIZE',0x3c:'EXTCODECOPY',0x3d:'RETURNDATASIZE',0x3e:'RETURNDATACOPY',0x3f:'EXTCODEHASH',
0x40:'BLOCKHASH',0x41:'COINBASE',0x42:'TIMESTAMP',0x43:'NUMBER',0x44:'DIFFICULTY',0x45:'GASLIMIT',0x46:'CHAINID',0x47:'SELFBALANCE',0x48:'BASEFEE',
0x50:'POP',0x51:'MLOAD',0x52:'MSTORE',0x53:'MSTORE8',0x54:'SLOAD',0x55:'SSTORE',0x56:'JUMP',0x57:'JUMPI',0x58:'PC',0x59:'MSIZE',0x5a:'GAS',0x5b:'JUMPDEST',
0x60:'PUSH1',0x61:'PUSH2',0x62:'PUSH3',0x63:'PUSH4',0x64:'PUSH5',0x65:'PUSH6',0x66:'PUSH7',0x67:'PUSH8',0x68:'PUSH9',0x69:'PUSH10',0x6a:'PUSH11',0x6b:'PUSH12',0x6c:'PUSH13',0x6d:'PUSH14',0x6e:'PUSH15',0x6f:'PUSH16',
0x70:'PUSH17',0x71:'PUSH18',0x72:'PUSH19',0x73:'PUSH20',0x74:'PUSH21',0x75:'PUSH22',0x76:'PUSH23',0x77:'PUSH24',0x78:'PUSH25',0x79:'PUSH26',0x7a:'PUSH27',0x7b:'PUSH28',0x7c:'PUSH29',0x7d:'PUSH30',0x7e:'PUSH31',0x7f:'PUSH32',
0x80:'DUP1',0x81:'DUP2',0x82:'DUP3',0x83:'DUP4',0x84:'DUP5',0x85:'DUP6',0x86:'DUP7',0x87:'DUP8',0x88:'DUP9',0x89:'DUP10',0x8a:'DUP11',0x8b:'DUP12',0x8c:'DUP13',0x8d:'DUP14',0x8e:'DUP15',0x8f:'DUP16',
0x90:'SWAP1',0x91:'SWAP2',0x92:'SWAP3',0x93:'SWAP4',0x94:'SWAP5',0x95:'SWAP6',0x96:'SWAP7',0x97:'SWAP8',0x98:'SWAP9',0x99:'SWAP10',0x9a:'SWAP11',0x9b:'SWAP12',0x9c:'SWAP13',0x9d:'SWAP14',0x9e:'SWAP15',0x9f:'SWAP16',
0xa0:'LOG0',0xa1:'LOG1',0xa2:'LOG2',0xa3:'LOG3',0xa4:'LOG4',
0xf0:'CREATE',0xf1:'CALL',0xf2:'CALLCODE',0xf3:'RETURN',0xf4:'DELEGATECALL',0xf5:'CREATE2',0xfa:'STATICCALL',0xfd:'REVERT',0xfe:'INVALID',0xff:'SELFDESTRUCT',
}
for k,v in base.items(): opnames[k]=v
def disasm_window(target_pc, window=20):
pc=0
mapping=[]
while pc < len(code):
op=code[pc]
name=opnames.get(op,'UNKNOWN')
if name and name.startswith('PUSH'):
n=op-0x5f
imm=code[pc+1:pc+1+n]
mapping.append((pc,name,imm))
pc+=1+n
else:
mapping.append((pc,name,b''))
pc+=1
idx=next((i for i,(p,_,_) in enumerate(mapping) if p==target_pc),None)
if idx is None:
# find nearest
idx=next((i for i,(p,_,_) in enumerate(mapping) if p>target_pc),len(mapping)-1)
start=max(0, idx-window)
end=min(len(mapping), idx+window)
for p,name,imm in mapping[start:end]:
marker='>>' if p==target_pc else ' '
if imm:
print(f\"{marker} {p:04d}: {name} 0x{imm.hex()}\")
else:
print(f\"{marker} {p:04d}: {name}\")
for pc in [563,1199,2199,3313,4363]:
print('--- pc',pc)
disasm_window(pc, window=25)
PY" in /tmp/codex-cv27gx3n succeeded in 53ms:
--- pc 563
0529: PUSH1 0xa0
0531: SHL
0532: SUB
0533: AND
0534: DUP5
0535: DUP5
0536: PUSH1 0x40
0538: MLOAD
0539: PUSH2 0x0225
0542: SWAP3
0543: SWAP2
0544: SWAP1
0545: PUSH2 0x1062
0548: JUMP
0549: JUMPDEST
0550: PUSH1 0x00
0552: PUSH1 0x40
0554: MLOAD
0555: DUP1
exec
/bin/bash -lc "python - <<'PY'
import json
from pathlib import Path
j=json.loads(Path('BYTECODE_BUNDLE.json').read_text())
full=j['artifact']['runtime_bytecode']['full']
if full.startswith('0x'): full=full[2:]
code=bytes.fromhex(full)
opnames={}
base={
0x00:'STOP',0x01:'ADD',0x02:'MUL',0x03:'SUB',0x04:'DIV',0x05:'SDIV',0x06:'MOD',0x07:'SMOD',0x08:'ADDMOD',0x09:'MULMOD',0x0a:'EXP',0x0b:'SIGNEXTEND',
0x10:'LT',0x11:'GT',0x12:'SLT',0x13:'SGT',0x14:'EQ',0x15:'ISZERO',0x16:'AND',0x17:'OR',0x18:'XOR',0x19:'NOT',0x1a:'BYTE',0x1b:'SHL',0x1c:'SHR',0x1d:'SAR',
0x20:'SHA3',
0x30:'ADDRESS',0x31:'BALANCE',0x32:'ORIGIN',0x33:'CALLER',0x34:'CALLVALUE',0x35:'CALLDATALOAD',0x36:'CALLDATASIZE',0x37:'CALLDATACOPY',0x38:'CODESIZE',0x39:'CODECOPY',0x3a:'GASPRICE',0x3b:'EXTCODESIZE',0x3c:'EXTCODECOPY',0x3d:'RETURNDATASIZE',0x3e:'RETURNDATACOPY',0x3f:'EXTCODEHASH',
0x40:'BLOCKHASH',0x41:'COINBASE',0x42:'TIMESTAMP',0x43:'NUMBER',0x44:'DIFFICULTY',0x45:'GASLIMIT',0x46:'CHAINID',0x47:'SELFBALANCE',0x48:'BASEFEE',
0x50:'POP',0x51:'MLOAD',0x52:'MSTORE',0x53:'MSTORE8',0x54:'SLOAD',0x55:'SSTORE',0x56:'JUMP',0x57:'JUMPI',0x58:'PC',0x59:'MSIZE',0x5a:'GAS',0x5b:'JUMPDEST',
0x60:'PUSH1',0x61:'PUSH2',0x62:'PUSH3',0x63:'PUSH4',0x64:'PUSH5',0x65:'PUSH6',0x66:'PUSH7',0x67:'PUSH8',0x68:'PUSH9',0x69:'PUSH10',0x6a:'PUSH11',0x6b:'PUSH12',0x6c:'PUSH13',0x6d:'PUSH14',0x6e:'PUSH15',0x6f:'PUSH16',
0x70:'PUSH17',0x71:'PUSH18',0x72:'PUSH19',0x73:'PUSH20',0x74:'PUSH21',0x75:'PUSH22',0x76:'PUSH23',0x77:'PUSH24',0x78:'PUSH25',0x79:'PUSH26',0x7a:'PUSH27',0x7b:'PUSH28',0x7c:'PUSH29',0x7d:'PUSH30',0x7e:'PUSH31',0x7f:'PUSH32',
0x80:'DUP1',0x81:'DUP2',0x82:'DUP3',0x83:'DUP4',0x84:'DUP5',0x85:'DUP6',0x86:'DUP7',0x87:'DUP8',0x88:'DUP9',0x89:'DUP10',0x8a:'DUP11',0x8b:'DUP12',0x8c:'DUP13',0x8d:'DUP14',0x8e:'DUP15',0x8f:'DUP16',
0x90:'SWAP1',0x91:'SWAP2',0x92:'SWAP3',0x93:'SWAP4',0x94:'SWAP5',0x95:'SWAP6',0x96:'SWAP7',0x97:'SWAP8',0x98:'SWAP9',0x99:'SWAP10',0x9a:'SWAP11',0x9b:'SWAP12',0x9c:'SWAP13',0x9d:'SWAP14',0x9e:'SWAP15',0x9f:'SWAP16',
0xa0:'LOG0',0xa1:'LOG1',0xa2:'LOG2',0xa3:'LOG3',0xa4:'LOG4',
0xf0:'CREATE',0xf1:'CALL',0xf2:'CALLCODE',0xf3:'RETURN',0xf4:'DELEGATECALL',0xf5:'CREATE2',0xfa:'STATICCALL',0xfd:'REVERT',0xfe:'INVALID',0xff:'SELFDESTRUCT',
}
for k,v in base.items(): opnames[k]=v
# build mapping once
mapping=[]
pc=0
while pc < len(code):
op=code[pc]
name=opnames.get(op,'UNKNOWN')
if name and name.startswith('PUSH'):
n=op-0x5f
imm=code[pc+1:pc+1+n]
mapping.append((pc,name,imm))
pc+=1+n
else:
mapping.append((pc,name,b''))
pc+=1
# helper to print around pc
def show(pc, window=30):
# find index
idx=next((i for i,(p,_,_) in enumerate(mapping) if p==pc),None)
if idx is None:
idx=next((i for i,(p,_,_) in enumerate(mapping) if p>pc),len(mapping)-1)
start=max(0, idx-window)
end=min(len(mapping), idx+window)
for p,name,imm in mapping[start:end]:
marker='>>' if p==pc else ' '
if imm:
print(f\"{marker} {p:04d}: {name} 0x{imm.hex()}\")
else:
print(f\"{marker} {p:04d}: {name}\")
# find JUMPDESTs around 0x720 (decimal 1824) and 0x7ce (1998)
for pc in [0x723,0x7ce,0x65e,0x2e1,0x483,0x4d0]:
print('--- around',pc)
show(pc, window=20)
PY" in /tmp/codex-cv27gx3n succeeded in 59ms:
--- around 1827
1706: MSTORE
1707: PUSH32 0x555550535570677261646561626c653a206d757374206e6f742062652063616c
1740: PUSH1 0x44
1742: DUP3
1743: ADD
1744: MSTORE
1745: PUSH32 0x6c6564207468726f7567682064656c656761746563616c6c0000000000000000
1778: PUSH1 0x64
1780: DUP3
1781: ADD
1782: MSTORE
1783: PUSH1 0x84
1785: ADD
1786: PUSH2 0x037b
1789: JUMP
1790: JUMPDEST
1791: POP
1792: PUSH32 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc
1825: SWAP1
exec
/bin/bash -lc "python - <<'PY'
import json
from pathlib import Path
j=json.loads(Path('BYTECODE_BUNDLE.json').read_text())
full=j['artifact']['runtime_bytecode']['full']
if full.startswith('0x'): full=full[2:]
code=bytes.fromhex(full)
# disassemble into list with pc
opnames={}
base={
0x00:'STOP',0x01:'ADD',0x02:'MUL',0x03:'SUB',0x04:'DIV',0x05:'SDIV',0x06:'MOD',0x07:'SMOD',0x08:'ADDMOD',0x09:'MULMOD',0x0a:'EXP',0x0b:'SIGNEXTEND',
0x10:'LT',0x11:'GT',0x12:'SLT',0x13:'SGT',0x14:'EQ',0x15:'ISZERO',0x16:'AND',0x17:'OR',0x18:'XOR',0x19:'NOT',0x1a:'BYTE',0x1b:'SHL',0x1c:'SHR',0x1d:'SAR',
0x20:'SHA3',
0x30:'ADDRESS',0x31:'BALANCE',0x32:'ORIGIN',0x33:'CALLER',0x34:'CALLVALUE',0x35:'CALLDATALOAD',0x36:'CALLDATASIZE',0x37:'CALLDATACOPY',0x38:'CODESIZE',0x39:'CODECOPY',0x3a:'GASPRICE',0x3b:'EXTCODESIZE',0x3c:'EXTCODECOPY',0x3d:'RETURNDATASIZE',0x3e:'RETURNDATACOPY',0x3f:'EXTCODEHASH',
0x40:'BLOCKHASH',0x41:'COINBASE',0x42:'TIMESTAMP',0x43:'NUMBER',0x44:'DIFFICULTY',0x45:'GASLIMIT',0x46:'CHAINID',0x47:'SELFBALANCE',0x48:'BASEFEE',
0x50:'POP',0x51:'MLOAD',0x52:'MSTORE',0x53:'MSTORE8',0x54:'SLOAD',0x55:'SSTORE',0x56:'JUMP',0x57:'JUMPI',0x58:'PC',0x59:'MSIZE',0x5a:'GAS',0x5b:'JUMPDEST',
0x60:'PUSH1',0x61:'PUSH2',0x62:'PUSH3',0x63:'PUSH4',0x64:'PUSH5',0x65:'PUSH6',0x66:'PUSH7',0x67:'PUSH8',0x68:'PUSH9',0x69:'PUSH10',0x6a:'PUSH11',0x6b:'PUSH12',0x6c:'PUSH13',0x6d:'PUSH14',0x6e:'PUSH15',0x6f:'PUSH16',
0x70:'PUSH17',0x71:'PUSH18',0x72:'PUSH19',0x73:'PUSH20',0x74:'PUSH21',0x75:'PUSH22',0x76:'PUSH23',0x77:'PUSH24',0x78:'PUSH25',0x79:'PUSH26',0x7a:'PUSH27',0x7b:'PUSH28',0x7c:'PUSH29',0x7d:'PUSH30',0x7e:'PUSH31',0x7f:'PUSH32',
0x80:'DUP1',0x81:'DUP2',0x82:'DUP3',0x83:'DUP4',0x84:'DUP5',0x85:'DUP6',0x86:'DUP7',0x87:'DUP8',0x88:'DUP9',0x89:'DUP10',0x8a:'DUP11',0x8b:'DUP12',0x8c:'DUP13',0x8d:'DUP14',0x8e:'DUP15',0x8f:'DUP16',
0x90:'SWAP1',0x91:'SWAP2',0x92:'SWAP3',0x93:'SWAP4',0x94:'SWAP5',0x95:'SWAP6',0x96:'SWAP7',0x97:'SWAP8',0x98:'SWAP9',0x99:'SWAP10',0x9a:'SWAP11',0x9b:'SWAP12',0x9c:'SWAP13',0x9d:'SWAP14',0x9e:'SWAP15',0x9f:'SWAP16',
0xa0:'LOG0',0xa1:'LOG1',0xa2:'LOG2',0xa3:'LOG3',0xa4:'LOG4',
0xf0:'CREATE',0xf1:'CALL',0xf2:'CALLCODE',0xf3:'RETURN',0xf4:'DELEGATECALL',0xf5:'CREATE2',0xfa:'STATICCALL',0xfd:'REVERT',0xfe:'INVALID',0xff:'SELFDESTRUCT',
}
for k,v in base.items(): opnames[k]=v
mapping=[]
pc=0
while pc < len(code):
op=code[pc]
name=opnames.get(op,'UNKNOWN')
if name and name.startswith('PUSH'):
n=op-0x5f
imm=code[pc+1:pc+1+n]
mapping.append((pc,name,imm))
pc+=1+n
else:
mapping.append((pc,name,b''))
pc+=1
# find SSTORE pcs
sstore_pcs=[p for p,name,_ in mapping if name=='SSTORE']
print('SSTORE count',len(sstore_pcs))
print('pcs',sstore_pcs)
# show windows around each sstore
for pc in sstore_pcs:
print('\\n--- around SSTORE at',pc)
# show 15 ops before and after
idx=next(i for i,(p,_,_) in enumerate(mapping) if p==pc)
start=max(0, idx-20)
end=min(len(mapping), idx+20)
for p,name,imm in mapping[start:end]:
marker='>>' if p==pc else ' '
if imm:
print(f\"{marker} {p:04d}: {name} 0x{imm.hex()}\")
else:
print(f\"{marker} {p:04d}: {name}\")
PY" in /tmp/codex-cv27gx3n succeeded in 53ms:
SSTORE count 6
pcs [1863, 1915, 1920, 1937, 2822, 3044]
--- around SSTORE at 1863
1832: PUSH2 0x0730
1835: DUP3
1836: PUSH2 0x09d7
1839: JUMP
1840: JUMPDEST
1841: SWAP1
1842: POP
1843: DUP1
1844: ISZERO
1845: PUSH2 0x0748
1848: JUMPI
1849: PUSH1 0x00
1851: DUP1
1852: SLOAD
1853: PUSH2 0xff00
1856: NOT
exec
/bin/bash -lc "python - <<'PY'
import json
from pathlib import Path
j=json.loads(Path('BYTECODE_BUNDLE.json').read_text())
full=j['artifact']['runtime_bytecode']['full']
if full.startswith('0x'): full=full[2:]
code=bytes.fromhex(full)
# simple scan for PUSH2 0x07ce patterns
pcs=[]
pc=0
while pc < len(code):
op=code[pc]
if op==0x61: # PUSH2
imm=code[pc+1:pc+3]
if imm==bytes.fromhex('07ce'):
pcs.append(pc)
pc+=3
elif 0x60 <= op <= 0x7f:
pc+=1+(op-0x5f)
else:
pc+=1
print('PUSH2 0x07ce at pcs:', pcs)
PY" in /tmp/codex-cv27gx3n succeeded in 38ms:
PUSH2 0x07ce at pcs: [519, 1163, 2094]
exec
/bin/bash -lc "python - <<'PY'
import json
from pathlib import Path
j=json.loads(Path('BYTECODE_BUNDLE.json').read_text())
full=j['artifact']['runtime_bytecode']['full']
if full.startswith('0x'): full=full[2:]
code=bytes.fromhex(full)
opnames={}
base={
0x00:'STOP',0x01:'ADD',0x02:'MUL',0x03:'SUB',0x04:'DIV',0x05:'SDIV',0x06:'MOD',0x07:'SMOD',0x08:'ADDMOD',0x09:'MULMOD',0x0a:'EXP',0x0b:'SIGNEXTEND',
0x10:'LT',0x11:'GT',0x12:'SLT',0x13:'SGT',0x14:'EQ',0x15:'ISZERO',0x16:'AND',0x17:'OR',0x18:'XOR',0x19:'NOT',0x1a:'BYTE',0x1b:'SHL',0x1c:'SHR',0x1d:'SAR',
0x20:'SHA3',
0x30:'ADDRESS',0x31:'BALANCE',0x32:'ORIGIN',0x33:'CALLER',0x34:'CALLVALUE',0x35:'CALLDATALOAD',0x36:'CALLDATASIZE',0x37:'CALLDATACOPY',0x38:'CODESIZE',0x39:'CODECOPY',0x3a:'GASPRICE',0x3b:'EXTCODESIZE',0x3c:'EXTCODECOPY',0x3d:'RETURNDATASIZE',0x3e:'RETURNDATACOPY',0x3f:'EXTCODEHASH',
0x40:'BLOCKHASH',0x41:'COINBASE',0x42:'TIMESTAMP',0x43:'NUMBER',0x44:'DIFFICULTY',0x45:'GASLIMIT',0x46:'CHAINID',0x47:'SELFBALANCE',0x48:'BASEFEE',
0x50:'POP',0x51:'MLOAD',0x52:'MSTORE',0x53:'MSTORE8',0x54:'SLOAD',0x55:'SSTORE',0x56:'JUMP',0x57:'JUMPI',0x58:'PC',0x59:'MSIZE',0x5a:'GAS',0x5b:'JUMPDEST',
0x60:'PUSH1',0x61:'PUSH2',0x62:'PUSH3',0x63:'PUSH4',0x64:'PUSH5',0x65:'PUSH6',0x66:'PUSH7',0x67:'PUSH8',0x68:'PUSH9',0x69:'PUSH10',0x6a:'PUSH11',0x6b:'PUSH12',0x6c:'PUSH13',0x6d:'PUSH14',0x6e:'PUSH15',0x6f:'PUSH16',
0x70:'PUSH17',0x71:'PUSH18',0x72:'PUSH19',0x73:'PUSH20',0x74:'PUSH21',0x75:'PUSH22',0x76:'PUSH23',0x77:'PUSH24',0x78:'PUSH25',0x79:'PUSH26',0x7a:'PUSH27',0x7b:'PUSH28',0x7c:'PUSH29',0x7d:'PUSH30',0x7e:'PUSH31',0x7f:'PUSH32',
0x80:'DUP1',0x81:'DUP2',0x82:'DUP3',0x83:'DUP4',0x84:'DUP5',0x85:'DUP6',0x86:'DUP7',0x87:'DUP8',0x88:'DUP9',0x89:'DUP10',0x8a:'DUP11',0x8b:'DUP12',0x8c:'DUP13',0x8d:'DUP14',0x8e:'DUP15',0x8f:'DUP16',
0x90:'SWAP1',0x91:'SWAP2',0x92:'SWAP3',0x93:'SWAP4',0x94:'SWAP5',0x95:'SWAP6',0x96:'SWAP7',0x97:'SWAP8',0x98:'SWAP9',0x99:'SWAP10',0x9a:'SWAP11',0x9b:'SWAP12',0x9c:'SWAP13',0x9d:'SWAP14',0x9e:'SWAP15',0x9f:'SWAP16',
0xa0:'LOG0',0xa1:'LOG1',0xa2:'LOG2',0xa3:'LOG3',0xa4:'LOG4',
0xf0:'CREATE',0xf1:'CALL',0xf2:'CALLCODE',0xf3:'RETURN',0xf4:'DELEGATECALL',0xf5:'CREATE2',0xfa:'STATICCALL',0xfd:'REVERT',0xfe:'INVALID',0xff:'SELFDESTRUCT',
}
for k,v in base.items(): opnames[k]=v
# build mapping
mapping=[]
pc=0
while pc < len(code):
op=code[pc]
name=opnames.get(op,'UNKNOWN')
if name and name.startswith('PUSH'):
n=op-0x5f
imm=code[pc+1:pc+1+n]
mapping.append((pc,name,imm))
pc+=1+n
else:
mapping.append((pc,name,b''))
pc+=1
# show around pc 2094
pc=2094
idx=next(i for i,(p,_,_) in enumerate(mapping) if p==pc)
start=max(0, idx-20)
end=min(len(mapping), idx+30)
for p,name,imm in mapping[start:end]:
marker='>>' if p==pc else ' '
if imm:
print(f\"{marker} {p:04d}: {name} 0x{imm.hex()}\")
else:
print(f\"{marker} {p:04d}: {name}\")
PY" in /tmp/codex-cv27gx3n succeeded in 38ms:
2034: ADD
2035: MSTORE
2036: PUSH1 0x12
2038: PUSH1 0x24
2040: DUP3
2041: ADD
2042: MSTORE
2043: PUSH32 0x556e2d617574686f72697a65642063616c6c0000000000000000000000000000
2076: PUSH1 0x44
2078: DUP3
2079: ADD
2080: MSTORE
2081: PUSH1 0x64
2083: ADD
2084: PUSH2 0x037b
2087: JUMP
2088: JUMPDEST
2089: JUMP
2090: JUMPDEST
2091: PUSH2 0x0480
exec
/bin/bash -lc "sed -n '5488,5535p' BYTECODE_BUNDLE.json" in /tmp/codex-cv27gx3n succeeded in 6ms:
"pc": 2806,
"slot": "0x0000000000000000000000000000000000000000000000000000000000000000"
},
{
"op": "SLOAD",
"pc": 2992,
"slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"
}
],
"writes": 6
}
}
],
"selectors": [
"0x52d1902d",
"0x6323d7af",
"0xcd6dc687",
"0x4847a79c",
"0x4f1ef286",
"0x0f4414c8",
exec
/bin/bash -lc "python - <<'PY'
import json
from pathlib import Path
j=json.loads(Path('BYTECODE_BUNDLE.json').read_text())
full=j['artifact']['runtime_bytecode']['full']
if full.startswith('0x'): full=full[2:]
code=bytes.fromhex(full)
# disassemble with pc
ops=[]
pc=0
while pc < len(code):
op=code[pc]
if 0x60 <= op <= 0x7f:
n=op-0x5f
imm=code[pc+1:pc+1+n]
ops.append((pc,op,imm))
pc+=1+n
else:
ops.append((pc,op,b''))
pc+=1
# find patterns PUSH4 sel; EQ; PUSH2 dest; JUMPI
selector_map={}
for i in range(len(ops)-3):
pc,op,imm=ops[i]
if op==0x63: # PUSH4
sel=imm.hex()
# look ahead for EQ then PUSH2 then JUMPI
if i+3 < len(ops):
op1=ops[i+1][1]
op2=ops[i+2][1]
op3=ops[i+3][1]
if op1==0x14 and op2==0x61 and op3==0x57:
dest=int.from_bytes(ops[i+2][2], 'big')
selector_map['0x'+sel]=dest
print('selector map')
for k,v in selector_map.items():
print(k, hex(v))
PY" in /tmp/codex-cv27gx3n succeeded in 49ms:
selector map
0x52d1902d 0x1a2
0x6323d7af 0x1b7
0xcd6dc687 0x1df
0x4847a79c 0x16f
0x4f1ef286 0x18f
0x0f4414c8 0xa6
0x150b7a02 0xdd
0x3659cfe6 0x12e
0x375974eb 0x150
exec
/bin/bash -lc "python - <<'PY'
import json
from pathlib import Path
j=json.loads(Path('BYTECODE_BUNDLE.json').read_text())
full=j['artifact']['runtime_bytecode']['full']
if full.startswith('0x'): full=full[2:]
code=bytes.fromhex(full)
opnames={}
base={
0x00:'STOP',0x01:'ADD',0x02:'MUL',0x03:'SUB',0x04:'DIV',0x05:'SDIV',0x06:'MOD',0x07:'SMOD',0x08:'ADDMOD',0x09:'MULMOD',0x0a:'EXP',0x0b:'SIGNEXTEND',
0x10:'LT',0x11:'GT',0x12:'SLT',0x13:'SGT',0x14:'EQ',0x15:'ISZERO',0x16:'AND',0x17:'OR',0x18:'XOR',0x19:'NOT',0x1a:'BYTE',0x1b:'SHL',0x1c:'SHR',0x1d:'SAR',
0x20:'SHA3',
0x30:'ADDRESS',0x31:'BALANCE',0x32:'ORIGIN',0x33:'CALLER',0x34:'CALLVALUE',0x35:'CALLDATALOAD',0x36:'CALLDATASIZE',0x37:'CALLDATACOPY',0x38:'CODESIZE',0x39:'CODECOPY',0x3a:'GASPRICE',0x3b:'EXTCODESIZE',0x3c:'EXTCODECOPY',0x3d:'RETURNDATASIZE',0x3e:'RETURNDATACOPY',0x3f:'EXTCODEHASH',
0x40:'BLOCKHASH',0x41:'COINBASE',0x42:'TIMESTAMP',0x43:'NUMBER',0x44:'DIFFICULTY',0x45:'GASLIMIT',0x46:'CHAINID',0x47:'SELFBALANCE',0x48:'BASEFEE',
0x50:'POP',0x51:'MLOAD',0x52:'MSTORE',0x53:'MSTORE8',0x54:'SLOAD',0x55:'SSTORE',0x56:'JUMP',0x57:'JUMPI',0x58:'PC',0x59:'MSIZE',0x5a:'GAS',0x5b:'JUMPDEST',
0x60:'PUSH1',0x61:'PUSH2',0x62:'PUSH3',0x63:'PUSH4',0x64:'PUSH5',0x65:'PUSH6',0x66:'PUSH7',0x67:'PUSH8',0x68:'PUSH9',0x69:'PUSH10',0x6a:'PUSH11',0x6b:'PUSH12',0x6c:'PUSH13',0x6d:'PUSH14',0x6e:'PUSH15',0x6f:'PUSH16',
0x70:'PUSH17',0x71:'PUSH18',0x72:'PUSH19',0x73:'PUSH20',0x74:'PUSH21',0x75:'PUSH22',0x76:'PUSH23',0x77:'PUSH24',0x78:'PUSH25',0x79:'PUSH26',0x7a:'PUSH27',0x7b:'PUSH28',0x7c:'PUSH29',0x7d:'PUSH30',0x7e:'PUSH31',0x7f:'PUSH32',
0x80:'DUP1',0x81:'DUP2',0x82:'DUP3',0x83:'DUP4',0x84:'DUP5',0x85:'DUP6',0x86:'DUP7',0x87:'DUP8',0x88:'DUP9',0x89:'DUP10',0x8a:'DUP11',0x8b:'DUP12',0x8c:'DUP13',0x8d:'DUP14',0x8e:'DUP15',0x8f:'DUP16',
0x90:'SWAP1',0x91:'SWAP2',0x92:'SWAP3',0x93:'SWAP4',0x94:'SWAP5',0x95:'SWAP6',0x96:'SWAP7',0x97:'SWAP8',0x98:'SWAP9',0x99:'SWAP10',0x9a:'SWAP11',0x9b:'SWAP12',0x9c:'SWAP13',0x9d:'SWAP14',0x9e:'SWAP15',0x9f:'SWAP16',
0xa0:'LOG0',0xa1:'LOG1',0xa2:'LOG2',0xa3:'LOG3',0xa4:'LOG4',
0xf0:'CREATE',0xf1:'CALL',0xf2:'CALLCODE',0xf3:'RETURN',0xf4:'DELEGATECALL',0xf5:'CREATE2',0xfa:'STATICCALL',0xfd:'REVERT',0xfe:'INVALID',0xff:'SELFDESTRUCT',
}
for k,v in base.items(): opnames[k]=v
# disassemble into list
ops=[]
pc=0
while pc < len(code):
op=code[pc]
name=opnames.get(op,'UNKNOWN')
if name and name.startswith('PUSH'):
n=op-0x5f
imm=code[pc+1:pc+1+n]
ops.append((pc,name,imm))
pc+=1+n
else:
ops.append((pc,name,b''))
pc+=1
selector_entries={
'0x52d1902d':0x1a2,
'0x6323d7af':0x1b7,
'0xcd6dc687':0x1df,
'0x4847a79c':0x16f,
'0x4f1ef286':0x18f,
'0x0f4414c8':0xa6,
'0x150b7a02':0xdd,
'0x3659cfe6':0x12e,
'0x375974eb':0x150,
}
# function to show first 20 ops after entry
for sel,entry in selector_entries.items():
print('\\nSelector',sel,'entry',hex(entry))
# find entry in ops
idx=next(i for i,(p,_,_) in enumerate(ops) if p==entry)
for p,name,imm in ops[idx:idx+20]:
if imm:
print(f\" {p:04d}: {name} 0x{imm.hex()}\")
else:
print(f\" {p:04d}: {name}\")
PY" in /tmp/codex-cv27gx3n succeeded in 37ms:
Selector 0x52d1902d entry 0x1a2
0418: JUMPDEST
0419: CALLVALUE
0420: DUP1
0421: ISZERO
0422: PUSH2 0x01ae
0425: JUMPI
0426: PUSH1 0x00
0428: DUP1
0429: REVERT
0430: JUMPDEST
0431: POP
0432: PUSH2 0x0161
0435: PUSH2 0x065e
0438: JUMP
0439: JUMPDEST
0440: CALLVALUE
0441: DUP1
0442: ISZERO
codex
{"no_findings":false,"summary":"Bytecode shows a UUPS-style upgradeable implementation with an externally callable initializer and owner-only arbitrary call helpers. Main risks are uninitialized-proxy takeover and the admin’s broad powers if compromised.","findings":[{"severity":"medium","category":"upgradeability","title":"Initializer can be called by anyone if the proxy is left uninitialized","exploit_scenario":"If the proxy is deployed without executing the initializer, any caller can invoke selector 0xcd6dc687, which writes critical admin/state slots (e.g., slot 0x66). The attacker becomes the privileged admin and can then upgrade the proxy to malicious logic or use admin-only call functions to drain assets.","recommendation":"Ensure the proxy is initialized atomically at deployment (pass initializer calldata to the proxy constructor). Also disable initializers on the implementation instance (e.g., _disableInitializers) to prevent direct initialization and document the required initialization flow.","evidence":"Initializer path writes to slot 0x66 (SSTORE at pc:1915) and other critical slots (pc:1920) with only the Initializable guard (slot 0 check, SSTORE at pc:2822). No caller check is observed before these writes.","locations":["selector:0xcd6dc687","pc:1915","pc:1920","pc:2822"]},{"severity":"low","category":"access_control","title":"Owner-only arbitrary external call with ETH transfer capability","exploit_scenario":"Selectors 0x0f4414c8 and 0x4847a79c perform low-level CALLs to computed targets (pc:563, pc:1199). If the admin key (slot 0x66) is compromised, an attacker can transfer ETH from the contract or invoke arbitrary external contracts, potentially draining funds or triggering reentrancy in downstream targets.","recommendation":"Treat the admin as a highly privileged role (multisig/timelock), and consider restricting these functions (allowlist) or removing them if not required. Ensure operational procedures mitigate key compromise.","evidence":"Low-level CALLs at pc:563 and pc:1199 with computed target/value. Authorization check appears to compare CALLER to slot 0x66 at pc:1998.","locations":["selector:0x0f4414c8","pc:563","selector:0x4847a79c","pc:1199","pc:1998"]}]}
tokens used
93,404
{
"codex": {
"ran_at": "2026-01-30T11:44:08.579724+00:00",
"returncode": 0
},
"project": {
"mode": "bytecode",
"bytecode_length": 8912,
"bytecode_truncated": false,
"capability_graph_present": true,
"analysis_artifact_present": true
},
"summary": "Bytecode shows a UUPS-style upgradeable implementation with an externally callable initializer and owner-only arbitrary call helpers. Main risks are uninitialized-proxy takeover and the admin\u2019s broad powers if compromised.",
"raw_final": {
"summary": "Bytecode shows a UUPS-style upgradeable implementation with an externally callable initializer and owner-only arbitrary call helpers. Main risks are uninitialized-proxy takeover and the admin\u2019s broad powers if compromised.",
"findings": [
{
"title": "Initializer can be called by anyone if the proxy is left uninitialized",
"category": "upgradeability",
"evidence": "Initializer path writes to slot 0x66 (SSTORE at pc:1915) and other critical slots (pc:1920) with only the Initializable guard (slot 0 check, SSTORE at pc:2822). No caller check is observed before these writes.",
"severity": "medium",
"locations": [
"selector:0xcd6dc687",
"pc:1915",
"pc:1920",
"pc:2822"
],
"recommendation": "Ensure the proxy is initialized atomically at deployment (pass initializer calldata to the proxy constructor). Also disable initializers on the implementation instance (e.g., _disableInitializers) to prevent direct initialization and document the required initialization flow.",
"exploit_scenario": "If the proxy is deployed without executing the initializer, any caller can invoke selector 0xcd6dc687, which writes critical admin/state slots (e.g., slot 0x66). The attacker becomes the privileged admin and can then upgrade the proxy to malicious logic or use admin-only call functions to drain assets."
},
{
"title": "Owner-only arbitrary external call with ETH transfer capability",
"category": "access_control",
"evidence": "Low-level CALLs at pc:563 and pc:1199 with computed target/value. Authorization check appears to compare CALLER to slot 0x66 at pc:1998.",
"severity": "low",
"locations": [
"selector:0x0f4414c8",
"pc:563",
"selector:0x4847a79c",
"pc:1199",
"pc:1998"
],
"recommendation": "Treat the admin as a highly privileged role (multisig/timelock), and consider restricting these functions (allowlist) or removing them if not required. Ensure operational procedures mitigate key compromise.",
"exploit_scenario": "Selectors 0x0f4414c8 and 0x4847a79c perform low-level CALLs to computed targets (pc:563, pc:1199). If the admin key (slot 0x66) is compromised, an attacker can transfer ETH from the contract or invoke arbitrary external contracts, potentially draining funds or triggering reentrancy in downstream targets."
}
],
"no_findings": false
},
"no_findings": false,
"proxy_context": {
"proxy_run_id": "019c0ea9-070a-72de-9802-b9a1e36ddc57",
"proxy_address": "0x095c35b4217770893fbb7cf533869afce1b27a78",
"implementation_run_id": "019c0ea9-2c1f-712c-a452-775a4bc4cf33",
"implementation_address": "0x7e0ae8e65fc3c322c9f2bedf630ce8ef799e292e"
},
"schema_version": 1
}
00000000: PUSH1 0x80 00000002: PUSH1 0x40 00000004: MSTORE 00000005: CALLDATASIZE 00000006: PUSH2 0x000b 00000009: JUMPI 0000000a: STOP 0000000b: JUMPDEST 0000000c: PUSH2 0x0013 0000000f: PUSH2 0x0015 00000012: JUMP 00000013: JUMPDEST 00000014: STOP 00000015: JUMPDEST 00000016: PUSH2 0x0025 00000019: PUSH2 0x0020 0000001c: PUSH2 0x0072 0000001f: JUMP 00000020: JUMPDEST 00000021: PUSH2 0x00b7 00000024: JUMP 00000025: JUMPDEST 00000026: JUMP 00000027: JUMPDEST 00000028: PUSH1 0x60 0000002a: PUSH2 0x004c 0000002d: DUP4 0000002e: DUP4 0000002f: PUSH1 0x40 00000031: MLOAD 00000032: DUP1 00000033: PUSH1 0x60 00000035: ADD 00000036: PUSH1 0x40 00000038: MSTORE 00000039: DUP1 0000003a: PUSH1 0x27 0000003c: DUP2 0000003d: MSTORE 0000003e: PUSH1 0x20 00000040: ADD 00000041: PUSH2 0x02a7 00000044: PUSH1 0x27 00000046: SWAP2 00000047: CODECOPY 00000048: PUSH2 0x00db 0000004b: JUMP 0000004c: JUMPDEST 0000004d: SWAP4 0000004e: SWAP3 0000004f: POP 00000050: POP 00000051: POP 00000052: JUMP 00000053: JUMPDEST 00000054: PUSH20 0xffffffffffffffffffffffffffffffffffffffff 00000069: AND 0000006a: EXTCODESIZE 0000006b: ISZERO 0000006c: ISZERO 0000006d: SWAP1 0000006e: JUMP 0000006f: JUMPDEST 00000070: SWAP1 00000071: JUMP 00000072: JUMPDEST 00000073: PUSH1 0x00 00000075: PUSH2 0x00b2 00000078: PUSH32 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc 00000099: SLOAD 0000009a: PUSH20 0xffffffffffffffffffffffffffffffffffffffff 000000af: AND 000000b0: SWAP1 000000b1: JUMP 000000b2: JUMPDEST 000000b3: SWAP1 000000b4: POP 000000b5: SWAP1 000000b6: JUMP 000000b7: JUMPDEST 000000b8: CALLDATASIZE 000000b9: PUSH1 0x00 000000bb: DUP1 000000bc: CALLDATACOPY 000000bd: PUSH1 0x00 000000bf: DUP1 000000c0: CALLDATASIZE 000000c1: PUSH1 0x00 000000c3: DUP5 000000c4: GAS 000000c5: DELEGATECALL 000000c6: RETURNDATASIZE 000000c7: PUSH1 0x00 000000c9: DUP1 000000ca: RETURNDATACOPY 000000cb: DUP1 000000cc: DUP1 000000cd: ISZERO 000000ce: PUSH2 0x00d6 000000d1: JUMPI 000000d2: RETURNDATASIZE 000000d3: PUSH1 0x00 000000d5: RETURN 000000d6: JUMPDEST 000000d7: RETURNDATASIZE 000000d8: PUSH1 0x00 000000da: REVERT 000000db: JUMPDEST 000000dc: PUSH1 0x60 000000de: PUSH20 0xffffffffffffffffffffffffffffffffffffffff 000000f3: DUP5 000000f4: AND 000000f5: EXTCODESIZE 000000f6: PUSH2 0x016c 000000f9: JUMPI 000000fa: PUSH1 0x40 000000fc: MLOAD 000000fd: PUSH3 0x461bcd 00000101: PUSH1 0xe5 00000103: SHL 00000104: DUP2 00000105: MSTORE 00000106: PUSH1 0x20 00000108: PUSH1 0x04 0000010a: DUP3 0000010b: ADD 0000010c: MSTORE 0000010d: PUSH1 0x26 0000010f: PUSH1 0x24 00000111: DUP3 00000112: ADD 00000113: MSTORE 00000114: PUSH32 0x416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f 00000135: PUSH1 0x44 00000137: DUP3 00000138: ADD 00000139: MSTORE 0000013a: PUSH32 0x6e74726163740000000000000000000000000000000000000000000000000000 0000015b: PUSH1 0x64 0000015d: DUP3 0000015e: ADD 0000015f: MSTORE 00000160: PUSH1 0x84 00000162: ADD 00000163: JUMPDEST 00000164: PUSH1 0x40 00000166: MLOAD 00000167: DUP1 00000168: SWAP2 00000169: SUB 0000016a: SWAP1 0000016b: REVERT 0000016c: JUMPDEST 0000016d: PUSH1 0x00 0000016f: DUP1 00000170: DUP6 00000171: PUSH20 0xffffffffffffffffffffffffffffffffffffffff 00000186: AND 00000187: DUP6 00000188: PUSH1 0x40 0000018a: MLOAD 0000018b: PUSH2 0x0194 0000018e: SWAP2 0000018f: SWAP1 00000190: PUSH2 0x0257 00000193: JUMP 00000194: JUMPDEST 00000195: PUSH1 0x00 00000197: PUSH1 0x40 00000199: MLOAD 0000019a: DUP1 0000019b: DUP4 0000019c: SUB 0000019d: DUP2 0000019e: DUP6 0000019f: GAS 000001a0: DELEGATECALL 000001a1: SWAP2 000001a2: POP 000001a3: POP 000001a4: RETURNDATASIZE 000001a5: DUP1 000001a6: PUSH1 0x00 000001a8: DUP2 000001a9: EQ 000001aa: PUSH2 0x01cf 000001ad: JUMPI 000001ae: PUSH1 0x40 000001b0: MLOAD 000001b1: SWAP2 000001b2: POP 000001b3: PUSH1 0x1f 000001b5: NOT 000001b6: PUSH1 0x3f 000001b8: RETURNDATASIZE 000001b9: ADD 000001ba: AND 000001bb: DUP3 000001bc: ADD 000001bd: PUSH1 0x40 000001bf: MSTORE 000001c0: RETURNDATASIZE 000001c1: DUP3 000001c2: MSTORE 000001c3: RETURNDATASIZE 000001c4: PUSH1 0x00 000001c6: PUSH1 0x20 000001c8: DUP5 000001c9: ADD 000001ca: RETURNDATACOPY 000001cb: PUSH2 0x01d4 000001ce: JUMP 000001cf: JUMPDEST 000001d0: PUSH1 0x60 000001d2: SWAP2 000001d3: POP 000001d4: JUMPDEST 000001d5: POP 000001d6: SWAP2 000001d7: POP 000001d8: SWAP2 000001d9: POP 000001da: PUSH2 0x01e4 000001dd: DUP3 000001de: DUP3 000001df: DUP7 000001e0: PUSH2 0x01ee 000001e3: JUMP 000001e4: JUMPDEST 000001e5: SWAP7 000001e6: SWAP6 000001e7: POP 000001e8: POP 000001e9: POP 000001ea: POP 000001eb: POP 000001ec: POP 000001ed: JUMP 000001ee: JUMPDEST 000001ef: PUSH1 0x60 000001f1: DUP4 000001f2: ISZERO 000001f3: PUSH2 0x01fd 000001f6: JUMPI 000001f7: POP 000001f8: DUP2 000001f9: PUSH2 0x004c 000001fc: JUMP 000001fd: JUMPDEST 000001fe: DUP3 000001ff: MLOAD 00000200: ISZERO 00000201: PUSH2 0x020d 00000204: JUMPI 00000205: DUP3 00000206: MLOAD 00000207: DUP1 00000208: DUP5 00000209: PUSH1 0x20 0000020b: ADD 0000020c: REVERT 0000020d: JUMPDEST 0000020e: DUP2 0000020f: PUSH1 0x40 00000211: MLOAD 00000212: PUSH3 0x461bcd 00000216: PUSH1 0xe5 00000218: SHL 00000219: DUP2 0000021a: MSTORE 0000021b: PUSH1 0x04 0000021d: ADD 0000021e: PUSH2 0x0163 00000221: SWAP2 00000222: SWAP1 00000223: PUSH2 0x0273 00000226: JUMP 00000227: JUMPDEST 00000228: PUSH1 0x00 0000022a: JUMPDEST 0000022b: DUP4 0000022c: DUP2 0000022d: LT 0000022e: ISZERO 0000022f: PUSH2 0x0242 00000232: JUMPI 00000233: DUP2 00000234: DUP2 00000235: ADD 00000236: MLOAD 00000237: DUP4 00000238: DUP3 00000239: ADD 0000023a: MSTORE 0000023b: PUSH1 0x20 0000023d: ADD 0000023e: PUSH2 0x022a 00000241: JUMP 00000242: JUMPDEST 00000243: DUP4 00000244: DUP2 00000245: GT 00000246: ISZERO 00000247: PUSH2 0x0251 0000024a: JUMPI 0000024b: PUSH1 0x00 0000024d: DUP5 0000024e: DUP5 0000024f: ADD 00000250: MSTORE 00000251: JUMPDEST 00000252: POP 00000253: POP 00000254: POP 00000255: POP 00000256: JUMP 00000257: JUMPDEST 00000258: PUSH1 0x00 0000025a: DUP3 0000025b: MLOAD 0000025c: PUSH2 0x0269 0000025f: DUP2 00000260: DUP5 00000261: PUSH1 0x20 00000263: DUP8 00000264: ADD 00000265: PUSH2 0x0227 00000268: JUMP 00000269: JUMPDEST 0000026a: SWAP2 0000026b: SWAP1 0000026c: SWAP2 0000026d: ADD 0000026e: SWAP3 0000026f: SWAP2 00000270: POP 00000271: POP 00000272: JUMP 00000273: JUMPDEST 00000274: PUSH1 0x20 00000276: DUP2 00000277: MSTORE 00000278: PUSH1 0x00 0000027a: DUP3 0000027b: MLOAD 0000027c: DUP1 0000027d: PUSH1 0x20 0000027f: DUP5 00000280: ADD 00000281: MSTORE 00000282: PUSH2 0x0292 00000285: DUP2 00000286: PUSH1 0x40 00000288: DUP6 00000289: ADD 0000028a: PUSH1 0x20 0000028c: DUP8 0000028d: ADD 0000028e: PUSH2 0x0227 00000291: JUMP 00000292: JUMPDEST 00000293: PUSH1 0x1f 00000295: ADD 00000296: PUSH1 0x1f 00000298: NOT 00000299: AND 0000029a: SWAP2 0000029b: SWAP1 0000029c: SWAP2 0000029d: ADD 0000029e: PUSH1 0x40 000002a0: ADD 000002a1: SWAP3 000002a2: SWAP2 000002a3: POP 000002a4: POP 000002a5: JUMP 000002a6: INVALID 000002a7: COINBASE 000002a8: PUSH5 0x6472657373 000002ae: GASPRICE 000002af: KECCAK256 000002b0: PUSH13 0x6f772d6c6576656c2064656c65 000002be: PUSH8 0x6174652063616c6c 000002c7: KECCAK256 000002c8: PUSH7 0x61696c6564a264 000002d0: PUSH10 0x70667358221220d92f9f 000002db: BALANCE 000002dc: SELFDESTRUCT 000002dd: UNKNOWN(0x0C) 000002de: UNKNOWN(0xB1) 000002df: UNKNOWN(0x27) 000002e0: SDIV 000002e1: UNKNOWN(0xE5) 000002e2: PUSH30 0xfe61c378cc8a0106180b4ad78c139de1f7f0cfba6864736f6c634300080d 00000301: STOP 00000302: CALLER
| Severity | Category | Tool | Title | Confidence | Validated | Confirmed | Details |
|---|---|---|---|---|---|---|---|
| critical | upgradeability | detector | Untrusted DELEGATECALL target reachable | 70 | no | no |
viewvalidation_json{
"sink": "DELEGATECALL",
"errors": 10,
"status": "unknown",
"attempts": 11,
"confirmed": false,
"trace_mode": "callTracer",
"call_targets": null,
"matched_probe": null,
"target_varies": null,
"classification": "no_sink"
}
witness_json{
"notes": "heuristic witness; entrypoints are best-effort selectors with zeroed calldata",
"constraints": [],
"entrypoints": [
{
"calldata": "0x",
"selector": "fallback",
"calldata_variants": [
"0x"
]
}
]
}
evidence_json{
"examples": [
{
"pc": 197,
"opcode": "DELEGATECALL",
"returndata_checked": null,
"value_expression_category": "n/a",
"target_expression_category": "computed"
},
{
"pc": 416,
"opcode": "DELEGATECALL",
"returndata_checked": null,
"value_expression_category": "n/a",
"target_expression_category": "computed"
}
],
"guards_detected": [],
"delegatecall_count": 2,
"untrusted_delegatecall_count": 2
}
|
| high | other | cast | SELFDESTRUCT present | 85 | no | — |
viewevidence_json{
"notes": "selfdestruct can remove contract code and send funds; review reachability",
"selfdestruct_count": 1
}
|
| high | other | detector | SELFDESTRUCT reachable | 65 | no | no |
viewtrace_id: 0x45ae806697c2291abec83754a69575cdff3d37711e8068fcb11f419107ba825b
validation_json{
"sink": "SELFDESTRUCT",
"errors": 0,
"status": "unknown",
"attempts": 1,
"trace_id": "0x45ae806697c2291abec83754a69575cdff3d37711e8068fcb11f419107ba825b",
"confirmed": false,
"trace_mode": "structLogs",
"call_targets": null,
"matched_probe": null,
"target_varies": null,
"classification": "no_sink"
}
witness_json{
"notes": "heuristic witness; entrypoints are best-effort selectors with zeroed calldata",
"constraints": [],
"entrypoints": [
{
"calldata": "0x",
"selector": "fallback",
"calldata_variants": [
"0x"
]
}
]
}
evidence_json{
"guards_detected": [],
"selfdestruct_count": 1
}
|
| medium | upgradeability | cast | DELEGATECALL present | 80 | no | — |
viewevidence_json{
"notes": "delegatecall enables execution in caller context; common in proxies/upgradeable patterns",
"delegatecall_count": 2
}
|
| medium | upgradeability | codex | Initializer can be called by anyone if the proxy is left uninitialized | 75 | no | — |
viewevidence_json{
"evidence": "Initializer path writes to slot 0x66 (SSTORE at pc:1915) and other critical slots (pc:1920) with only the Initializable guard (slot 0 check, SSTORE at pc:2822). No caller check is observed before these writes.",
"locations": [
"selector:0xcd6dc687",
"pc:1915",
"pc:1920",
"pc:2822"
],
"recommendation": "Ensure the proxy is initialized atomically at deployment (pass initializer calldata to the proxy constructor). Also disable initializers on the implementation instance (e.g., _disableInitializers) to prevent direct initialization and document the required initialization flow.",
"exploit_scenario": "If the proxy is deployed without executing the initializer, any caller can invoke selector 0xcd6dc687, which writes critical admin/state slots (e.g., slot 0x66). The attacker becomes the privileged admin and can then upgrade the proxy to malicious logic or use admin-only call functions to drain assets."
}
|
| low | access_control | codex | Owner-only arbitrary external call with ETH transfer capability | 65 | no | — |
viewevidence_json{
"evidence": "Low-level CALLs at pc:563 and pc:1199 with computed target/value. Authorization check appears to compare CALLER to slot 0x66 at pc:1998.",
"locations": [
"selector:0x0f4414c8",
"pc:563",
"selector:0x4847a79c",
"pc:1199",
"pc:1998"
],
"recommendation": "Treat the admin as a highly privileged role (multisig/timelock), and consider restricting these functions (allowlist) or removing them if not required. Ensure operational procedures mitigate key compromise.",
"exploit_scenario": "Selectors 0x0f4414c8 and 0x4847a79c perform low-level CALLs to computed targets (pc:563, pc:1199). If the admin key (slot 0x66) is compromised, an attacker can transfer ETH from the contract or invoke arbitrary external contracts, potentially draining funds or triggering reentrancy in downstream targets."
}
|