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

Analysis Run

363801c0-c873-4a99-a145-6211ab1fb838

failed
Chain ID
1
Address
Block Number
Created
Mon, Dec 29, 2025 6:38 AM
Review Summary

What survived the funnel

Open this run to answer one question: is this real attacker-relevant behavior with real impact, or just normal contract plumbing?

Confirmed
1
Validated
1
Source
Verified
Review Backing
Present
Best current signal
Untrusted DELEGATECALL target reachable
crit 1 high 0 proxy context implementation known
Review Checklist
1. Read the findings table first. Ignore raw jobs until the result looks real.
2. Confirm attacker control, not just the existence of a sink.
3. Confirm money or privilege impact.
4. Keep it if the behavior is real. Kill it if this is normal proxy, admin, or upgrade plumbing.

Processing Jobs

Status & attempts
ID Type Status Attempts Heartbeat
30451 report.consolidate complete 1 / 1 3 months ago
103565 artifact.fetch failed 1 / 3 1 week ago
103566 tool.cast_disasm complete 1 / 3 1 week ago
103567 analysis.bundle complete 1 / 3 1 week ago
103568 capability.graph complete 1 / 3 1 week ago
103569 detector.run complete 1 / 3 1 week ago
103570 validation.fork complete 1 / 3 1 week ago
113888 tool.slither complete 1 / 2 1 week ago

Artifact

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

Slither

tool.slither
Status
complete
Attempts
1 / 2
Findings
0
Solc
0.8.22 (solc-select)
View stderr
'forge clean' running (wd: /tmp/slither-pcl9z1vg)
'forge config --json' running
'forge build --build-info --skip ./test/** ./script/** --force' running (wd: /tmp/slither-pcl9z1vg)

ImmutableBeaconProxy.constructor(bytes) (contracts/base/proxy/ImmutableBeaconProxy.sol#17-23) ignores return value by _implementation().safeDelegateCall(initDataWithSelector) (contracts/base/proxy/ImmutableBeaconProxy.sol#21)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#unused-return

Proxy._delegate(address) (lib/openzeppelin-contracts/contracts/proxy/Proxy.sol#22-45) uses assembly
	- INLINE ASM (lib/openzeppelin-contracts/contracts/proxy/Proxy.sol#23-44)
LowLevelCall.callNoReturn(address,uint256,bytes) (lib/openzeppelin-contracts/contracts/utils/LowLevelCall.sol#19-23) uses assembly
	- INLINE ASM (lib/openzeppelin-contracts/contracts/utils/LowLevelCall.sol#20-22)
LowLevelCall.callReturn64Bytes(address,uint256,bytes) (lib/openzeppelin-contracts/contracts/utils/LowLevelCall.sol#38-48) uses assembly
	- INLINE ASM (lib/openzeppelin-contracts/contracts/utils/LowLevelCall.sol#43-47)
LowLevelCall.staticcallNoReturn(address,bytes) (lib/openzeppelin-contracts/contracts/utils/LowLevelCall.sol#51-55) uses assembly
	- INLINE ASM (lib/openzeppelin-contracts/contracts/utils/LowLevelCall.sol#52-54)
LowLevelCall.staticcallReturn64Bytes(address,bytes) (lib/openzeppelin-contracts/contracts/utils/LowLevelCall.sol#62-71) uses assembly
	- INLINE ASM (lib/openzeppelin-contracts/contracts/utils/LowLevelCall.sol#66-70)
LowLevelCall.delegatecallNoReturn(address,bytes) (lib/openzeppelin-contracts/contracts/utils/LowLevelCall.sol#74-78) uses assembly
	- INLINE ASM (lib/openzeppelin-contracts/contracts/utils/LowLevelCall.sol#75-77)
LowLevelCall.delegatecallReturn64Bytes(address,bytes) (lib/openzeppelin-contracts/contracts/utils/LowLevelCall.sol#85-94) uses assembly
	- INLINE ASM (lib/openzeppelin-contracts/contracts/utils/LowLevelCall.sol#89-93)
LowLevelCall.returnDataSize() (lib/openzeppelin-contracts/contracts/utils/LowLevelCall.sol#97-101) uses assembly
	- INLINE ASM (lib/openzeppelin-contracts/contracts/utils/LowLevelCall.sol#98-100)
LowLevelCall.returnData() (lib/openzeppelin-contracts/contracts/utils/LowLevelCall.sol#104-111) uses assembly
	- INLINE ASM (lib/openzeppelin-contracts/contracts/utils/LowLevelCall.sol#105-110)
LowLevelCall.bubbleRevert() (lib/openzeppelin-contracts/contracts/utils/LowLevelCall.sol#114-120) uses assembly
	- INLINE ASM (lib/openzeppelin-contracts/contracts/utils/LowLevelCall.sol#115-119)
LowLevelCall.bubbleRevert(bytes) (lib/openzeppelin-contracts/contracts/utils/LowLevelCall.sol#122-126) uses assembly
	- INLINE ASM (lib/openzeppelin-contracts/contracts/utils/LowLevelCall.sol#123-125)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#assembly-usage

3 different versions of Solidity are used:
	- Version constraint 0.8.22 is used by:
		-0.8.22 (contracts/base/proxy/ImmutableBeaconProxy.sol#2)
		-0.8.22 (contracts/interfaces/base/proxy/IBeacon.sol#2)
		-0.8.22 (contracts/interfaces/compiler/Command.sol#2)
		-0.8.22 (contracts/libraries/CommandLibrary.sol#2)
		-0.8.22 (contracts/libraries/SafeCall.sol#2)
	- Version constraint ^0.8.20 is used by:
		-^0.8.20 (lib/openzeppelin-contracts/contracts/proxy/Proxy.sol#4)
		-^0.8.20 (lib/openzeppelin-contracts/contracts/utils/Address.sol#4)
		-^0.8.20 (lib/openzeppelin-contracts/contracts/utils/Errors.sol#4)
		-^0.8.20 (lib/openzeppelin-contracts/contracts/utils/LowLevelCall.sol#4)
	- Version constraint >=0.4.16 is used by:
		->=0.4.16 (lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol#4)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#different-pragma-directives-are-used

Version constraint 0.8.22 contains known severe issues (https://solidity.readthedocs.io/en/latest/bugs.html)
	- VerbatimInvalidDeduplication.
It is used by:
	- 0.8.22 (contracts/base/proxy/ImmutableBeaconProxy.sol#2)
	- 0.8.22 (contracts/interfaces/base/proxy/IBeacon.sol#2)
	- 0.8.22 (contracts/interfaces/compiler/Command.sol#2)
	- 0.8.22 (contracts/libraries/CommandLibrary.sol#2)
	- 0.8.22 (contracts/libraries/SafeCall.sol#2)
Version constraint ^0.8.20 contains known severe issues (https://solidity.readthedocs.io/en/latest/bugs.html)
	- VerbatimInvalidDeduplication
	- FullInlinerNonExpressionSplitArgumentEvaluationOrder
	- MissingSideEffectsOnSelectorAccess.
It is used by:
	- ^0.8.20 (lib/openzeppelin-contracts/contracts/proxy/Proxy.sol#4)
	- ^0.8.20 (lib/openzeppelin-contracts/contracts/utils/Address.sol#4)
	- ^0.8.20 (lib/openzeppelin-contracts/contracts/utils/Errors.sol#4)
	- ^0.8.20 (lib/openzeppelin-contracts/contracts/utils/LowLevelCall.sol#4)
Version constraint >=0.4.16 contains known severe issues (https://solidity.readthedocs.io/en/latest/bugs.html)
	- DirtyBytesArrayToStorage
	- ABIDecodeTwoDimensionalArrayMemory
	- KeccakCaching
	- EmptyByteArrayCopy
	- DynamicArrayCleanup
	- ImplicitConstructorCallvalueCheck
	- TupleAssignmentMultiStackSlotComponents
	- MemoryArrayCreationOverflow
	- privateCanBeOverridden
	- SignedArrayStorageCopy
	- ABIEncoderV2StorageArrayWithMultiSlotElement
	- DynamicConstructorArgumentsClippedABIV2
	- UninitializedFunctionPointerInConstructor_0.4.x
	- IncorrectEventSignatureInLibraries_0.4.x
	- ExpExponentCleanup
	- NestedArrayFunctionCallDecoder
	- ZeroFunctionSelector.
It is used by:
	- >=0.4.16 (lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol#4)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-versions-of-solidity

Low level call in ImmutableBeaconProxy._implementation() (contracts/base/proxy/ImmutableBeaconProxy.sol#25-35):
	- (success,result) = beacon.staticcall(abi.encodeWithSelector(IBeacon.implementation.selector)) (contracts/base/proxy/ImmutableBeaconProxy.sol#26-28)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#low-level-calls

Parameter CommandPresets.approve(address,address,uint256)._token (contracts/libraries/CommandLibrary.sol#13) is not in mixedCase
Parameter CommandPresets.approve(address,address,uint256)._to (contracts/libraries/CommandLibrary.sol#14) is not in mixedCase
Parameter CommandPresets.approve(address,address,uint256)._amount (contracts/libraries/CommandLibrary.sol#15) is not in mixedCase
Parameter CommandPresets.transfer(address,address,uint256)._token (contracts/libraries/CommandLibrary.sol#23) is not in mixedCase
Parameter CommandPresets.transfer(address,address,uint256)._to (contracts/libraries/CommandLibrary.sol#24) is not in mixedCase
Parameter CommandPresets.transfer(address,address,uint256)._amount (contracts/libraries/CommandLibrary.sol#25) is not in mixedCase
Parameter CommandExecutor.execute(Command[])._cmds (contracts/libraries/CommandLibrary.sol#35) is not in mixedCase
Parameter CommandLibrary.last(Command[])._self (contracts/libraries/CommandLibrary.sol#43) is not in mixedCase
Parameter CommandLibrary.asArray(Command)._self (contracts/libraries/CommandLibrary.sol#47) is not in mixedCase
Parameter CommandLibrary.append(Command[],Command[])._self (contracts/libraries/CommandLibrary.sol#53) is not in mixedCase
Parameter CommandLibrary.append(Command[],Command[])._cmds (contracts/libraries/CommandLibrary.sol#54) is not in mixedCase
Parameter CommandLibrary.push(Command[],Command)._self (contracts/libraries/CommandLibrary.sol#67) is not in mixedCase
Parameter CommandLibrary.push(Command[],Command)._cmd (contracts/libraries/CommandLibrary.sol#68) is not in mixedCase
Parameter CommandLibrary.populateWithApprove(Command,address,uint256)._self (contracts/libraries/CommandLibrary.sol#78) is not in mixedCase
Parameter CommandLibrary.populateWithApprove(Command,address,uint256)._token (contracts/libraries/CommandLibrary.sol#79) is not in mixedCase
Parameter CommandLibrary.populateWithApprove(Command,address,uint256)._amount (contracts/libraries/CommandLibrary.sol#80) is not in mixedCase
Parameter SafeCall.safeCallAll(Command[])._cmds (contracts/libraries/SafeCall.sol#14) is not in mixedCase
Parameter SafeCall.safeCall(Command)._cmd (contracts/libraries/SafeCall.sol#20) is not in mixedCase
Parameter SafeCall.safeCall(address,bytes)._target (contracts/libraries/SafeCall.sol#24) is not in mixedCase
Parameter SafeCall.safeCall(address,bytes)._data (contracts/libraries/SafeCall.sol#24) is not in mixedCase
Parameter SafeCall.safeCall(address,uint256,bytes)._target (contracts/libraries/SafeCall.sol#29) is not in mixedCase
Parameter SafeCall.safeCall(address,uint256,bytes)._value (contracts/libraries/SafeCall.sol#30) is not in mixedCase
Parameter SafeCall.safeCall(address,uint256,bytes)._data (contracts/libraries/SafeCall.sol#31) is not in mixedCase
Parameter SafeCall.safeDelegateCall(address,bytes)._target (contracts/libraries/SafeCall.sol#37) is not in mixedCase
Parameter SafeCall.safeDelegateCall(address,bytes)._data (contracts/libraries/SafeCall.sol#38) is not in mixedCase
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#conformance-to-solidity-naming-conventions
. analyzed (11 contracts with 100 detectors), 42 result(s) found
Metadata
{
    "solc": {
        "status": "ok",
        "use_rc": 0,
        "version": "0.8.22",
        "strategy": "solc-select",
        "solc_path": "/var/www/tripwire/.venv/bin/solc",
        "install_rc": 0,
        "use_stderr": null,
        "use_stdout": "Switched global version to 0.8.22",
        "install_stderr": null,
        "install_stdout": "Version '0.8.22' is already installed, skipping..."
    },
    "solc_args": "--base-path /tmp/slither-pcl9z1vg --include-path /tmp/slither-pcl9z1vg/lib --include-path /tmp/slither-pcl9z1vg/lib/openzeppelin-contracts --allow-paths /tmp/slither-pcl9z1vg,/tmp/slither-pcl9z1vg/lib,/tmp/slither-pcl9z1vg/lib/openzeppelin-contracts,/tmp/slither-pcl9z1vg/src",
    "remappings": [
        "openzeppelin-contracts/=lib/openzeppelin-contracts/",
        "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/"
    ],
    "source_files": [
        "@openzeppelin/contracts/proxy/Proxy.sol",
        "@openzeppelin/contracts/token/ERC20/IERC20.sol",
        "@openzeppelin/contracts/utils/Address.sol",
        "contracts/base/proxy/ImmutableBeaconProxy.sol",
        "contracts/interfaces/base/proxy/IBeacon.sol",
        "contracts/interfaces/compiler/Command.sol",
        "contracts/libraries/CommandLibrary.sol",
        "contracts/libraries/SafeCall.sol"
    ],
    "contract_count": 0,
    "contract_names": [],
    "detector_count": 42,
    "workspace_hash": "c1a6ff6e8678e8ab03c26b77cf029d5644228c9d046c8ed8a6d8314fa7da0c0d",
    "duration_seconds": 0.4782140254974365,
    "solc_version_requested": "0.8.22"
}

Codex

report.consolidate
Job Status
complete
Attempts
1 / 1
Findings
1
No findings?
no
Summary
Identified 1 low-severity issue related to unchecked ERC20 return values in the command execution helpers.
View stderr
[codex:1489482] OpenAI Codex v0.77.0 (research preview)
[codex:1489482] --------
[codex:1489482] workdir: /tmp/codex-multi-m0_gar7d
[codex:1489482] model: gpt-5.2-codex
[codex:1489482] provider: openai
[codex:1489482] approval: never
[codex:1489482] sandbox: read-only
[codex:1489482] reasoning effort: xhigh
[codex:1489482] reasoning summaries: auto
[codex:1489482] session id: 019b68d1-b094-7390-a871-890fd9af6fac
[codex:1489482] --------
[codex:1489482] user
[codex:1489482] You are a security auditor. Audit this Solidity codebase for exploitable vulnerabilities.
[codex:1489482] Focus on: reentrancy, access control, upgradeability/proxy issues, signature validation, oracle manipulation,
[codex:1489482] accounting/invariant breaks, external call patterns, unchecked return values, and dangerous delegatecall.
[codex:1489482] 
[codex:1489482] Scope rules:
[codex:1489482] - You MUST fully read `AUDIT_BUNDLE.txt` before concluding. It contains the complete contents of all first-party `contracts/**/*.sol` files.
[codex:1489482] - Treat `lib/` and `@openzeppelin/` as third-party dependencies; skip them unless there is a concrete misuse angle in first-party code.
[codex:1489482] 
[codex:1489482] Output MUST be valid JSON matching the provided schema.
[codex:1489482] - If you find nothing meaningful: set no_findings=true and findings=[].
[codex:1489482] - Otherwise: set no_findings=false and include findings with severity/category/title and file/line locations when possible.
[codex:1489482] 
[codex:1489482] Output constraints (IMPORTANT):
[codex:1489482] - severity MUST be exactly one of: info, low, medium, high, critical (lowercase).
[codex:1489482] - category MUST be exactly one of: access_control, reentrancy, math, oracle, upgradeability, auth, other.
[codex:1489482] mcp startup: no servers
[codex:1489482] 
[codex:1489482] thinking
[codex:1489482] **Reading audit file**
[codex:1489482] exec
[codex:1489482] /bin/bash -lc ls in /tmp/codex-multi-m0_gar7d succeeded in 5ms:
[codex:1489482] AUDIT_BUNDLE.txt
[codex:1489482] codex-output-schema.json
[codex:1489482] contracts
[codex:1489482] exec
[codex:1489482] /bin/bash -lc 'cat AUDIT_BUNDLE.txt' in /tmp/codex-multi-m0_gar7d succeeded in 5ms:
[codex:1489482] This file concatenates the full contents of first-party Solidity sources for auditing.
[codex:1489482] 
[codex:1489482] ================================================================================
[codex:1489482] FILE: contracts/@openzeppelin/contracts/proxy/Proxy.sol
[codex:1489482] ================================================================================
[codex:1489482] // SPDX-License-Identifier: MIT
[codex:1489482] // OpenZeppelin Contracts (last updated v5.0.0) (proxy/Proxy.sol)
[codex:1489482] 
[codex:1489482] pragma solidity ^0.8.20;
[codex:1489482] 
[codex:1489482] /**
[codex:1489482]  * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
[codex:1489482]  * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
[codex:1489482]  * be specified by overriding the virtual {_implementation} function.
[codex:1489482]  *
[codex:1489482]  * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
[codex:1489482]  * different contract through the {_delegate} function.
[codex:1489482]  *
[codex:1489482]  * The success and return data of the delegated call will be returned back to the caller of the proxy.
[codex:1489482]  */
[codex:1489482] 
[codex:1489482] 
[codex:1489482] 
[codex:1489482] thinking
[codex:1489482] **Evaluating first-party Solidity contracts for vulnerabilities**
[codex:1489482] 
[codex:1489482] I'm carefully auditing the specified first-party Solidity contracts, focusing especially on ImmutableBeaconProxy and Command-related libraries, checking their initialization, call patterns, access control, and upgradeability model. While the proxy’s immutable beacon design and delegatecall usage have some nuanced risks—like potential misconfiguration or edge cases with beacon addresses—the code’s safeguards and context reduce exploitable issues. The CommandExecutor library permits arbitrary external calls without access control if deployed, which could be risky if it held assets, but its usage here seems limited. Overall, I find no clear exploitable vulnerabilities in this bundle and would mark the audit as no findings while noting some cautionary points about misuse or misconfiguration.
[codex:1489482] thinking
[codex:1489482] **Identifying external call and proxy upgrade patterns**
[codex:1489482] 
[codex:1489482] I'm analyzing subtle issues like unchecked ERC20 return values in SafeCall and CommandExecutor, which could allow false success assumptions during token transfers, potentially leading to accounting inconsistencies. I also reviewed ImmutableBeaconProxy’s proxy delegatecall logic, noting its constructor initialization and beacon assignment are standard but could cause problems if beacon or implementation addresses are misconfigured. While none of these clearly rise to critical vulnerabilities, they represent important external call and upgradeability nuances worth mentioning in the audit.
[codex:1489482] thinking
[codex:1489482] **Noting unchecked ERC20 return risks and code details**
[codex:1489482] 
[codex:1489482] I’m exploring the common ERC20 pitfall where SafeCall and CommandExecutor don’t verify boolean return values, which can cause silent failures on token transfers or approvals—usually low severity but important depending on usage. I’m also checking related library code and considering line references to back this finding with precise locations for the audit report.
[codex:1489482] exec
[codex:1489482] /bin/bash -lc 'nl -ba contracts/contracts/libraries/SafeCall.sol' in /tmp/codex-multi-m0_gar7d succeeded in 5ms:
[codex:1489482]      1	// SPDX-License-Identifier: BUSL-1.1
[codex:1489482]      2	pragma solidity 0.8.22;
[codex:1489482]      3	
[codex:1489482]      4	import {Address} from "@openzeppelin/contracts/utils/Address.sol";
[codex:1489482]      5	import {Command} from "contracts/interfaces/compiler/Command.sol";
[codex:1489482]      6	
[codex:1489482]      7	/**
[codex:1489482]      8	 * @notice Safe methods performing a low-level calls that revert
[codex:1489482]      9	 * if the call was not successful
[codex:1489482]     10	 */
[codex:1489482]     11	library SafeCall {
[codex:1489482]     12	    using Address for address;
[codex:1489482]     13	
[codex:1489482]     14	    function safeCallAll(Command[] memory _cmds) internal {
[codex:1489482]     15	        for (uint256 i; i < _cmds.length; i++) {
[codex:1489482]     16	            safeCall(_cmds[i]);
[codex:1489482]     17	        }
[codex:1489482]     18	    }
[codex:1489482]     19	
[codex:1489482]     20	    function safeCall(Command memory _cmd) internal returns (bytes memory result_) {
[codex:1489482] 
[codex:1489482] thinking
[codex:1489482] **Reviewing safeCall and CommandExecutor handling**
[codex:1489482] exec
[codex:1489482] /bin/bash -lc 'nl -ba contracts/contracts/libraries/CommandLibrary.sol' in /tmp/codex-multi-m0_gar7d succeeded in 5ms:
[codex:1489482]      1	// SPDX-License-Identifier: BUSL-1.1
[codex:1489482]      2	pragma solidity 0.8.22;
[codex:1489482]      3	
[codex:1489482]      4	import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
[codex:1489482]      5	import {Command} from "contracts/interfaces/compiler/Command.sol";
[codex:1489482]      6	import {SafeCall} from "contracts/libraries/SafeCall.sol";
[codex:1489482]      7	
[codex:1489482]      8	/**
[codex:1489482]      9	 * @notice Utility to convert often-used methods into a Command object
[codex:1489482]     10	 */
[codex:1489482]     11	library CommandPresets {
[codex:1489482]     12	    function approve(
[codex:1489482]     13	        address _token,
[codex:1489482]     14	        address _to,
[codex:1489482]     15	        uint256 _amount
[codex:1489482]     16	    ) internal pure returns (Command[] memory result_) {
[codex:1489482]     17	        result_ = new Command[](2);
[codex:1489482]     18	        result_[0] = Command(_token, 0, abi.encodeCall(IERC20.approve, (_to, 0)));
[codex:1489482]     19	        result_[1] = Command(_token, 0, abi.encodeCall(IERC20.approve, (_to, _amount)));
[codex:1489482]     20	    }
[codex:1489482] 
[codex:1489482] thinking
[codex:1489482] **Summarizing potential vulnerabilities and findings**
[codex:1489482] 
[codex:1489482] I'm examining potential issues like unchecked ERC20 return values in command execution helpers, immutability of the beacon proxy, and delegatecall use. The biggest concern is the CommandExecutor ignoring ERC20 call returns, which could cause silent failures if tokens return false on transfer/approval. I'll include this as a low-severity finding with evidence and locations, noting it's exploitable in stateful use cases despite absence of stateful contracts here.
[codex:1489482] codex
[codex:1489482] {"no_findings":false,"summary":"Identified 1 low-severity issue related to unchecked ERC20 return values in the command execution helpers.","findings":[{"severity":"low","category":"other","title":"ERC20 return values ignored in command execution helpers","exploit_scenario":"If CommandExecutor is used to execute ERC20 transfers/approvals, a token that returns false (or a transfer that fails but does not revert) will be treated as success. Higher-level logic that assumes the transfer occurred can proceed and update accounting or release assets, leading to inconsistencies or potential loss.","recommendation":"When executing ERC20 commands, verify return data: treat empty return data as success, but if non-empty, decode bool and require it to be true (SafeERC20 pattern). Alternatively, add ERC20-specific helpers that validate return values before continuing the command sequence.","evidence":"CommandExecutor.execute ignores return data from safeCallAll, and SafeCall.safeCall uses functionCallWithValue without decoding the returned bool, even though CommandPresets builds IERC20.transfer/approve calls that typically return a bool.","locations":["contracts/contracts/libraries/CommandLibrary.sol:12","contracts/contracts/libraries/CommandLibrary.sol:32","contracts/contracts/libraries/SafeCall.sol:28"]}]}
[codex:1489482] tokens used
[codex:1489482] 26,980
[codex:1489482] {"no_findings":false,"summary":"Identified 1 low-severity issue related to unchecked ERC20 return values in the command execution helpers.","findings":[{"severity":"low","category":"other","title":"ERC20 return values ignored in command execution helpers","exploit_scenario":"If CommandExecutor is used to execute ERC20 transfers/approvals, a token that returns false (or a transfer that fails but does not revert) will be treated as success. Higher-level logic that assumes the transfer occurred can proceed and update accounting or release assets, leading to inconsistencies or potential loss.","recommendation":"When executing ERC20 commands, verify return data: treat empty return data as success, but if non-empty, decode bool and require it to be true (SafeERC20 pattern). Alternatively, add ERC20-specific helpers that validate return values before continuing the command sequence.","evidence":"CommandExecutor.execute ignores return data from safeCallAll, and SafeCall.safeCall uses functionCallWithValue without decoding the returned bool, even though CommandPresets builds IERC20.transfer/approve calls that typically return a bool.","locations":["contracts/contracts/libraries/CommandLibrary.sol:12","contracts/contracts/libraries/CommandLibrary.sol:32","contracts/contracts/libraries/SafeCall.sol:28"]}]}
Metadata
{
    "codex": {
        "ran_at": "2025-12-29T06:38:57.114926+00:00",
        "returncode": 0
    },
    "summary": "Identified 1 low-severity issue related to unchecked ERC20 return values in the command execution helpers.",
    "raw_final": {
        "summary": "Identified 1 low-severity issue related to unchecked ERC20 return values in the command execution helpers.",
        "findings": [
            {
                "title": "ERC20 return values ignored in command execution helpers",
                "category": "other",
                "evidence": "CommandExecutor.execute ignores return data from safeCallAll, and SafeCall.safeCall uses functionCallWithValue without decoding the returned bool, even though CommandPresets builds IERC20.transfer/approve calls that typically return a bool.",
                "severity": "low",
                "locations": [
                    "contracts/contracts/libraries/CommandLibrary.sol:12",
                    "contracts/contracts/libraries/CommandLibrary.sol:32",
                    "contracts/contracts/libraries/SafeCall.sol:28"
                ],
                "recommendation": "When executing ERC20 commands, verify return data: treat empty return data as success, but if non-empty, decode bool and require it to be true (SafeERC20 pattern). Alternatively, add ERC20-specific helpers that validate return values before continuing the command sequence.",
                "exploit_scenario": "If CommandExecutor is used to execute ERC20 transfers/approvals, a token that returns false (or a transfer that fails but does not revert) will be treated as success. Higher-level logic that assumes the transfer occurred can proceed and update accounting or release assets, leading to inconsistencies or potential loss."
            }
        ],
        "no_findings": false
    },
    "no_findings": false,
    "schema_version": 1
}

Opcode Heuristics

tool.cast_disasm
Delegatecall
1
Selfdestruct
0
CREATE2
0
CALL-family (heavy)
1
EXT*/BALANCE
0
Total opcodes
379
Flags
delegatecall_present
View cast disassembly output
00000000: PUSH1 0x80
00000002: PUSH1 0x40
00000004: MSTORE
00000005: PUSH2 0x000c
00000008: PUSH2 0x000e
0000000b: JUMP
0000000c: JUMPDEST
0000000d: STOP
0000000e: JUMPDEST
0000000f: PUSH2 0x001e
00000012: PUSH2 0x0019
00000015: PUSH2 0x0020
00000018: JUMP
00000019: JUMPDEST
0000001a: PUSH2 0x01ec
0000001d: JUMP
0000001e: JUMPDEST
0000001f: JUMP
00000020: JUMPDEST
00000021: PUSH1 0x40
00000023: DUP1
00000024: MLOAD
00000025: PUSH1 0x04
00000027: DUP2
00000028: MSTORE
00000029: PUSH1 0x24
0000002b: DUP2
0000002c: ADD
0000002d: DUP3
0000002e: MSTORE
0000002f: PUSH1 0x20
00000031: DUP2
00000032: ADD
00000033: DUP1
00000034: MLOAD
00000035: PUSH28 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff
00000052: AND
00000053: PUSH32 0x5c60da1b00000000000000000000000000000000000000000000000000000000
00000074: OR
00000075: SWAP1
00000076: MSTORE
00000077: SWAP1
00000078: MLOAD
00000079: PUSH1 0x00
0000007b: SWAP2
0000007c: DUP3
0000007d: SWAP2
0000007e: DUP3
0000007f: SWAP2
00000080: PUSH20 0xffffffffffffffffffffffffffffffffffffffff
00000095: PUSH32 0x0000000000000000000000007ad1dd2516f1499852aaeb95a33d7ec1ba31b5c3
000000b6: AND
000000b7: SWAP2
000000b8: PUSH2 0x00c1
000000bb: SWAP2
000000bc: SWAP1
000000bd: PUSH2 0x0256
000000c0: JUMP
000000c1: JUMPDEST
000000c2: PUSH1 0x00
000000c4: PUSH1 0x40
000000c6: MLOAD
000000c7: DUP1
000000c8: DUP4
000000c9: SUB
000000ca: DUP2
000000cb: DUP6
000000cc: GAS
000000cd: STATICCALL
000000ce: SWAP2
000000cf: POP
000000d0: POP
000000d1: RETURNDATASIZE
000000d2: DUP1
000000d3: PUSH1 0x00
000000d5: DUP2
000000d6: EQ
000000d7: PUSH2 0x00fc
000000da: JUMPI
000000db: PUSH1 0x40
000000dd: MLOAD
000000de: SWAP2
000000df: POP
000000e0: PUSH1 0x1f
000000e2: NOT
000000e3: PUSH1 0x3f
000000e5: RETURNDATASIZE
000000e6: ADD
000000e7: AND
000000e8: DUP3
000000e9: ADD
000000ea: PUSH1 0x40
000000ec: MSTORE
000000ed: RETURNDATASIZE
000000ee: DUP3
000000ef: MSTORE
000000f0: RETURNDATASIZE
000000f1: PUSH1 0x00
000000f3: PUSH1 0x20
000000f5: DUP5
000000f6: ADD
000000f7: RETURNDATACOPY
000000f8: PUSH2 0x0101
000000fb: JUMP
000000fc: JUMPDEST
000000fd: PUSH1 0x60
000000ff: SWAP2
00000100: POP
00000101: JUMPDEST
00000102: POP
00000103: SWAP2
00000104: POP
00000105: SWAP2
00000106: POP
00000107: DUP2
00000108: PUSH2 0x013d
0000010b: JUMPI
0000010c: PUSH1 0x40
0000010e: MLOAD
0000010f: PUSH32 0x73a769bf00000000000000000000000000000000000000000000000000000000
00000130: DUP2
00000131: MSTORE
00000132: PUSH1 0x04
00000134: ADD
00000135: PUSH1 0x40
00000137: MLOAD
00000138: DUP1
00000139: SWAP2
0000013a: SUB
0000013b: SWAP1
0000013c: REVERT
0000013d: JUMPDEST
0000013e: DUP1
0000013f: MLOAD
00000140: PUSH1 0x20
00000142: EQ
00000143: PUSH2 0x0184
00000146: JUMPI
00000147: DUP1
00000148: MLOAD
00000149: PUSH1 0x40
0000014b: MLOAD
0000014c: PUSH32 0x7ce64c7800000000000000000000000000000000000000000000000000000000
0000016d: DUP2
0000016e: MSTORE
0000016f: PUSH1 0x04
00000171: ADD
00000172: PUSH2 0x017b
00000175: SWAP2
00000176: SWAP1
00000177: PUSH2 0x0266
0000017a: JUMP
0000017b: JUMPDEST
0000017c: PUSH1 0x40
0000017e: MLOAD
0000017f: DUP1
00000180: SWAP2
00000181: SUB
00000182: SWAP1
00000183: REVERT
00000184: JUMPDEST
00000185: DUP1
00000186: DUP1
00000187: PUSH1 0x20
00000189: ADD
0000018a: SWAP1
0000018b: MLOAD
0000018c: DUP2
0000018d: ADD
0000018e: SWAP1
0000018f: PUSH2 0x0198
00000192: SWAP2
00000193: SWAP1
00000194: PUSH2 0x02b2
00000197: JUMP
00000198: JUMPDEST
00000199: SWAP3
0000019a: POP
0000019b: PUSH20 0xffffffffffffffffffffffffffffffffffffffff
000001b0: DUP4
000001b1: AND
000001b2: PUSH2 0x01e7
000001b5: JUMPI
000001b6: PUSH1 0x40
000001b8: MLOAD
000001b9: PUSH32 0xfb678c3000000000000000000000000000000000000000000000000000000000
000001da: DUP2
000001db: MSTORE
000001dc: PUSH1 0x04
000001de: ADD
000001df: PUSH1 0x40
000001e1: MLOAD
000001e2: DUP1
000001e3: SWAP2
000001e4: SUB
000001e5: SWAP1
000001e6: REVERT
000001e7: JUMPDEST
000001e8: POP
000001e9: POP
000001ea: SWAP1
000001eb: JUMP
000001ec: JUMPDEST
000001ed: CALLDATASIZE
000001ee: PUSH1 0x00
000001f0: DUP1
000001f1: CALLDATACOPY
000001f2: PUSH1 0x00
000001f4: DUP1
000001f5: CALLDATASIZE
000001f6: PUSH1 0x00
000001f8: DUP5
000001f9: GAS
000001fa: DELEGATECALL
000001fb: RETURNDATASIZE
000001fc: PUSH1 0x00
000001fe: DUP1
000001ff: RETURNDATACOPY
00000200: DUP1
00000201: DUP1
00000202: ISZERO
00000203: PUSH2 0x020b
00000206: JUMPI
00000207: RETURNDATASIZE
00000208: PUSH1 0x00
0000020a: RETURN
0000020b: JUMPDEST
0000020c: RETURNDATASIZE
0000020d: PUSH1 0x00
0000020f: REVERT
00000210: JUMPDEST
00000211: PUSH1 0x00
00000213: JUMPDEST
00000214: DUP4
00000215: DUP2
00000216: LT
00000217: ISZERO
00000218: PUSH2 0x022b
0000021b: JUMPI
0000021c: DUP2
0000021d: DUP2
0000021e: ADD
0000021f: MLOAD
00000220: DUP4
00000221: DUP3
00000222: ADD
00000223: MSTORE
00000224: PUSH1 0x20
00000226: ADD
00000227: PUSH2 0x0213
0000022a: JUMP
0000022b: JUMPDEST
0000022c: POP
0000022d: POP
0000022e: PUSH1 0x00
00000230: SWAP2
00000231: ADD
00000232: MSTORE
00000233: JUMP
00000234: JUMPDEST
00000235: PUSH1 0x00
00000237: PUSH2 0x023e
0000023a: DUP3
0000023b: MLOAD
0000023c: SWAP1
0000023d: JUMP
0000023e: JUMPDEST
0000023f: PUSH2 0x024c
00000242: DUP2
00000243: DUP6
00000244: PUSH1 0x20
00000246: DUP7
00000247: ADD
00000248: PUSH2 0x0210
0000024b: JUMP
0000024c: JUMPDEST
0000024d: SWAP3
0000024e: SWAP1
0000024f: SWAP3
00000250: ADD
00000251: SWAP3
00000252: SWAP2
00000253: POP
00000254: POP
00000255: JUMP
00000256: JUMPDEST
00000257: PUSH2 0x0260
0000025a: DUP2
0000025b: DUP4
0000025c: PUSH2 0x0234
0000025f: JUMP
00000260: JUMPDEST
00000261: SWAP3
00000262: SWAP2
00000263: POP
00000264: POP
00000265: JUMP
00000266: JUMPDEST
00000267: DUP2
00000268: DUP2
00000269: MSTORE
0000026a: PUSH1 0x20
0000026c: DUP2
0000026d: ADD
0000026e: PUSH2 0x0260
00000271: JUMP
00000272: JUMPDEST
00000273: PUSH1 0x00
00000275: PUSH20 0xffffffffffffffffffffffffffffffffffffffff
0000028a: DUP3
0000028b: AND
0000028c: PUSH2 0x0260
0000028f: JUMP
00000290: JUMPDEST
00000291: PUSH2 0x0299
00000294: DUP2
00000295: PUSH2 0x0272
00000298: JUMP
00000299: JUMPDEST
0000029a: DUP2
0000029b: EQ
0000029c: PUSH2 0x02a4
0000029f: JUMPI
000002a0: PUSH1 0x00
000002a2: DUP1
000002a3: REVERT
000002a4: JUMPDEST
000002a5: POP
000002a6: JUMP
000002a7: JUMPDEST
000002a8: DUP1
000002a9: MLOAD
000002aa: PUSH2 0x0260
000002ad: DUP2
000002ae: PUSH2 0x0290
000002b1: JUMP
000002b2: JUMPDEST
000002b3: PUSH1 0x00
000002b5: PUSH1 0x20
000002b7: DUP3
000002b8: DUP5
000002b9: SUB
000002ba: SLT
000002bb: ISZERO
000002bc: PUSH2 0x02c7
000002bf: JUMPI
000002c0: PUSH2 0x02c7
000002c3: PUSH1 0x00
000002c5: DUP1
000002c6: REVERT
000002c7: JUMPDEST
000002c8: PUSH2 0x02d1
000002cb: DUP4
000002cc: DUP4
000002cd: PUSH2 0x02a7
000002d0: JUMP
000002d1: JUMPDEST
000002d2: SWAP4
000002d3: SWAP3
000002d4: POP
000002d5: POP
000002d6: POP
000002d7: JUMP
000002d8: INVALID
000002d9: LOG2
000002da: PUSH5 0x6970667358
000002e0: UNKNOWN(0x22)
000002e1: SLT
000002e2: KECCAK256
000002e3: UNKNOWN(0xE9)
000002e4: UNKNOWN(0xD2)
000002e5: CLZ
000002e6: PUSH20 0x399766fd4a2b1c6e9767ef0aba61b69658e29e68
000002fb: UNKNOWN(0x0E)
000002fc: PUSH13 0x3d0c0b50155f64736f6c634300
0000030a: ADDMOD
0000030b: AND
0000030c: STOP
0000030d: CALLER

Findings

validated = confirmed for call sinks; sink observed for others
Severity Category Tool Title Confidence Validated Confirmed Details
critical upgradeability detector Untrusted DELEGATECALL target reachable 70 yes yes
view
trace_id: 0xc8b88cc5e93639465d361e656bc88009558b2afd0a81001851bcef90fc46072d
call_targets: 0x2cbc40d524a87b709d5d5f4195b2086b302f2e96, 0xb1f0129a5d7c082d1244502bdac694a744193072
target_varies: yes
classification: target_varies
validation_json
{
    "sink": "DELEGATECALL",
    "errors": 0,
    "status": "confirmed",
    "attempts": 1,
    "trace_id": "0xc8b88cc5e93639465d361e656bc88009558b2afd0a81001851bcef90fc46072d",
    "confirmed": true,
    "trace_mode": "callTracer",
    "call_targets": [
        "0x2cbc40d524a87b709d5d5f4195b2086b302f2e96",
        "0xb1f0129a5d7c082d1244502bdac694a744193072"
    ],
    "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": 506,
            "opcode": "DELEGATECALL",
            "returndata_checked": null,
            "value_expression_category": "n/a",
            "target_expression_category": "computed"
        }
    ],
    "guards_detected": [],
    "delegatecall_count": 1,
    "untrusted_delegatecall_count": 1
}
medium upgradeability cast DELEGATECALL present 80 no
view
evidence_json
{
    "notes": "delegatecall enables execution in caller context; common in proxies/upgradeable patterns",
    "delegatecall_count": 1
}
low other codex ERC20 return values ignored in command execution helpers 65 no
view
evidence_json
{
    "evidence": "CommandExecutor.execute ignores return data from safeCallAll, and SafeCall.safeCall uses functionCallWithValue without decoding the returned bool, even though CommandPresets builds IERC20.transfer/approve calls that typically return a bool.",
    "locations": [
        "contracts/contracts/libraries/CommandLibrary.sol:12",
        "contracts/contracts/libraries/CommandLibrary.sol:32",
        "contracts/contracts/libraries/SafeCall.sol:28"
    ],
    "recommendation": "When executing ERC20 commands, verify return data: treat empty return data as success, but if non-empty, decode bool and require it to be true (SafeERC20 pattern). Alternatively, add ERC20-specific helpers that validate return values before continuing the command sequence.",
    "exploit_scenario": "If CommandExecutor is used to execute ERC20 transfers/approvals, a token that returns false (or a transfer that fails but does not revert) will be treated as success. Higher-level logic that assumes the transfer occurred can proceed and update accounting or release assets, leading to inconsistencies or potential loss."
}