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

Analysis Run

019bb490-f341-7224-a82a-cad72e12cb5f

complete
Chain ID
1
Address
Block Number
Created
Mon, Jan 12, 2026 11:35 PM
Review Summary

What survived the funnel

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

Confirmed
0
Validated
0
Source
Verified
Review Backing
Present
Best current signal
Untrusted DELEGATECALL target reachable
crit 0 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
40053 artifact.fetch complete 1 / 3 3 months ago
40054 proxy.resolve complete 1 / 3 3 months ago
40055 tool.cast_disasm complete 1 / 3 3 months ago
40056 analysis.bundle complete 1 / 3 3 months ago
40057 capability.graph complete 1 / 3 3 months ago
40058 detector.run complete 1 / 3 3 months ago
40059 validation.fork complete 1 / 3 3 months ago
40213 report.consolidate complete 1 / 6 3 months ago
40214 tool.slither complete 1 / 2 3 months ago

Artifact

Runtime bytecode: available
Creation TX:
Deployer:
Proxy: yes onchain_only
Verified Source: yes
Proxy evidence
{
    "method": "minimal_proxy",
    "status": "onchain_only",
    "implementation": "0x9c3e06659f1c34f930ce97fcbce6e04ae88e535b",
    "onchain_method": "minimal_proxy"
}

Slither

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

BaseEscrow._ethTransfer(address,uint256) (contracts/BaseEscrow.sol#95-98) sends eth to arbitrary user
	Dangerous calls:
	- (success,None) = to.call{value: amount}() (contracts/BaseEscrow.sol#96)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#functions-that-send-ether-to-arbitrary-destinations

BaseEscrow.onlyAccessTokenHolder() (contracts/BaseEscrow.sol#63-66) uses a dangerous strict equality:
	- _ACCESS_TOKEN.balanceOf(msg.sender) == 0 (contracts/BaseEscrow.sol#64)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-strict-equalities

Reentrancy in EscrowDst._withdraw(bytes32,IBaseEscrow.Immutables) (contracts/EscrowDst.sol#77-85):
	External calls:
	- _uniTransfer(immutables.token.get(),immutables.maker.get(),immutables.amount) (contracts/EscrowDst.sol#82)
		- (success,None) = to.call{value: amount}() (contracts/BaseEscrow.sol#96)
	- _ethTransfer(msg.sender,immutables.safetyDeposit) (contracts/EscrowDst.sol#83)
		- (success,None) = to.call{value: amount}() (contracts/BaseEscrow.sol#96)
	Event emitted after the call(s):
	- EscrowWithdrawal(secret) (contracts/EscrowDst.sol#84)
Reentrancy in EscrowDst.cancel(IBaseEscrow.Immutables) (contracts/EscrowDst.sol#62-71):
	External calls:
	- _uniTransfer(immutables.token.get(),immutables.taker.get(),immutables.amount) (contracts/EscrowDst.sol#68)
		- (success,None) = to.call{value: amount}() (contracts/BaseEscrow.sol#96)
	- _ethTransfer(msg.sender,immutables.safetyDeposit) (contracts/EscrowDst.sol#69)
		- (success,None) = to.call{value: amount}() (contracts/BaseEscrow.sol#96)
	Event emitted after the call(s):
	- EscrowCancelled() (contracts/EscrowDst.sol#70)
Reentrancy in BaseEscrow.rescueFunds(address,uint256,IBaseEscrow.Immutables) (contracts/BaseEscrow.sol#71-79):
	External calls:
	- _uniTransfer(token,msg.sender,amount) (contracts/BaseEscrow.sol#77)
		- (success,None) = to.call{value: amount}() (contracts/BaseEscrow.sol#96)
	Event emitted after the call(s):
	- FundsRescued(token,amount) (contracts/BaseEscrow.sol#78)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-3

BaseEscrow._keccakBytes32(bytes32) (contracts/BaseEscrow.sol#110-115) uses assembly
	- INLINE ASM (contracts/BaseEscrow.sol#111-114)
ImmutablesLib.hash(IBaseEscrow.Immutables) (contracts/libraries/ImmutablesLib.sol#19-25) uses assembly
	- INLINE ASM (contracts/libraries/ImmutablesLib.sol#20-24)
ImmutablesLib.hashMem(IBaseEscrow.Immutables) (contracts/libraries/ImmutablesLib.sol#32-36) uses assembly
	- INLINE ASM (contracts/libraries/ImmutablesLib.sol#33-35)
ProxyHashLib.computeProxyBytecodeHash(address) (contracts/libraries/ProxyHashLib.sol#15-25) uses assembly
	- INLINE ASM (contracts/libraries/ProxyHashLib.sol#16-24)
Create2.deploy(uint256,bytes32,bytes) (lib/openzeppelin-contracts/contracts/utils/Create2.sol#38-55) uses assembly
	- INLINE ASM (lib/openzeppelin-contracts/contracts/utils/Create2.sol#45-47)
Create2.computeAddress(bytes32,bytes32,address) (lib/openzeppelin-contracts/contracts/utils/Create2.sol#69-90) uses assembly
	- INLINE ASM (lib/openzeppelin-contracts/contracts/utils/Create2.sol#70-89)
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)
RevertReasonForwarder.reRevert() (lib/solidity-utils/contracts/libraries/RevertReasonForwarder.sol#14-21) uses assembly
	- INLINE ASM (lib/solidity-utils/contracts/libraries/RevertReasonForwarder.sol#16-20)
RevertReasonForwarder.reReason() (lib/solidity-utils/contracts/libraries/RevertReasonForwarder.sol#28-36) uses assembly
	- INLINE ASM (lib/solidity-utils/contracts/libraries/RevertReasonForwarder.sol#29-35)
SafeERC20.safeBalanceOf(IERC20,address) (lib/solidity-utils/contracts/libraries/SafeERC20.sol#44-61) uses assembly
	- INLINE ASM (lib/solidity-utils/contracts/libraries/SafeERC20.sol#49-60)
SafeERC20.safeTransferFrom(IERC20,address,address,uint256) (lib/solidity-utils/contracts/libraries/SafeERC20.sol#99-126) uses assembly
	- INLINE ASM (lib/solidity-utils/contracts/libraries/SafeERC20.sol#107-124)
SafeERC20.safeTransferFromPermit2(IERC20,address,address,uint256) (lib/solidity-utils/contracts/libraries/SafeERC20.sol#138-161) uses assembly
	- INLINE ASM (lib/solidity-utils/contracts/libraries/SafeERC20.sol#147-159)
SafeERC20.tryPermit(IERC20,address,address,bytes) (lib/solidity-utils/contracts/libraries/SafeERC20.sol#300-402) uses assembly
	- INLINE ASM (lib/solidity-utils/contracts/libraries/SafeERC20.sol#306-401)
SafeERC20._makeCall(IERC20,bytes4,address,uint256) (lib/solidity-utils/contracts/libraries/SafeERC20.sol#414-437) uses assembly
	- INLINE ASM (lib/solidity-utils/contracts/libraries/SafeERC20.sol#420-436)
SafeERC20.safeDeposit(IWETH,uint256) (lib/solidity-utils/contracts/libraries/SafeERC20.sol#444-456) uses assembly
	- INLINE ASM (lib/solidity-utils/contracts/libraries/SafeERC20.sol#447-454)
SafeERC20.safeWithdraw(IWETH,uint256) (lib/solidity-utils/contracts/libraries/SafeERC20.sol#464-475) uses assembly
	- INLINE ASM (lib/solidity-utils/contracts/libraries/SafeERC20.sol#466-474)
SafeERC20.safeWithdrawTo(IWETH,uint256,address) (lib/solidity-utils/contracts/libraries/SafeERC20.sol#484-495) uses assembly
	- INLINE ASM (lib/solidity-utils/contracts/libraries/SafeERC20.sol#487-493)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#assembly-usage

4 different versions of Solidity are used:
	- Version constraint 0.8.23 is used by:
		-0.8.23 (contracts/BaseEscrow.sol#3)
		-0.8.23 (contracts/Escrow.sol#3)
		-0.8.23 (contracts/EscrowDst.sol#3)
	- Version constraint ^0.8.0 is used by:
		-^0.8.0 (contracts/interfaces/IBaseEscrow.sol#3)
		-^0.8.0 (contracts/interfaces/IEscrow.sol#3)
		-^0.8.0 (contracts/interfaces/IEscrowDst.sol#3)
		-^0.8.0 (lib/solidity-utils/contracts/interfaces/IDaiLikePermit.sol#3)
		-^0.8.0 (lib/solidity-utils/contracts/interfaces/IERC7597Permit.sol#3)
		-^0.8.0 (lib/solidity-utils/contracts/interfaces/IPermit2.sol#3)
		-^0.8.0 (lib/solidity-utils/contracts/interfaces/IWETH.sol#3)
		-^0.8.0 (lib/solidity-utils/contracts/libraries/AddressLib.sol#3)
		-^0.8.0 (lib/solidity-utils/contracts/libraries/RevertReasonForwarder.sol#3)
		-^0.8.0 (lib/solidity-utils/contracts/libraries/SafeERC20.sol#3)
	- Version constraint ^0.8.20 is used by:
		-^0.8.20 (contracts/libraries/ImmutablesLib.sol#3)
		-^0.8.20 (contracts/libraries/ProxyHashLib.sol#3)
		-^0.8.20 (contracts/libraries/TimelocksLib.sol#3)
		-^0.8.20 (lib/openzeppelin-contracts/contracts/utils/Create2.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)
		->=0.4.16 (lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol#4)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#different-pragma-directives-are-used

Version constraint ^0.8.0 contains known severe issues (https://solidity.readthedocs.io/en/latest/bugs.html)
	- FullInlinerNonExpressionSplitArgumentEvaluationOrder
	- MissingSideEffectsOnSelectorAccess
	- AbiReencodingHeadOverflowWithStaticArrayCleanup
	- DirtyBytesArrayToStorage
	- DataLocationChangeInInternalOverride
	- NestedCalldataArrayAbiReencodingSizeValidation
	- SignedImmutables
	- ABIDecodeTwoDimensionalArrayMemory
	- KeccakCaching.
It is used by:
	- ^0.8.0 (contracts/interfaces/IBaseEscrow.sol#3)
	- ^0.8.0 (contracts/interfaces/IEscrow.sol#3)
	- ^0.8.0 (contracts/interfaces/IEscrowDst.sol#3)
	- ^0.8.0 (lib/solidity-utils/contracts/interfaces/IDaiLikePermit.sol#3)
	- ^0.8.0 (lib/solidity-utils/contracts/interfaces/IERC7597Permit.sol#3)
	- ^0.8.0 (lib/solidity-utils/contracts/interfaces/IPermit2.sol#3)
	- ^0.8.0 (lib/solidity-utils/contracts/interfaces/IWETH.sol#3)
	- ^0.8.0 (lib/solidity-utils/contracts/libraries/AddressLib.sol#3)
	- ^0.8.0 (lib/solidity-utils/contracts/libraries/RevertReasonForwarder.sol#3)
	- ^0.8.0 (lib/solidity-utils/contracts/libraries/SafeERC20.sol#3)
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 (contracts/libraries/ImmutablesLib.sol#3)
	- ^0.8.20 (contracts/libraries/ProxyHashLib.sol#3)
	- ^0.8.20 (contracts/libraries/TimelocksLib.sol#3)
	- ^0.8.20 (lib/openzeppelin-contracts/contracts/utils/Create2.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)
	- >=0.4.16 (lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol#4)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-versions-of-solidity

Low level call in BaseEscrow._ethTransfer(address,uint256) (contracts/BaseEscrow.sol#95-98):
	- (success,None) = to.call{value: amount}() (contracts/BaseEscrow.sol#96)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#low-level-calls

Variable BaseEscrow._ACCESS_TOKEN (contracts/BaseEscrow.sol#26) is not in mixedCase
Variable BaseEscrow.RESCUE_DELAY (contracts/BaseEscrow.sol#29) is not in mixedCase
Variable BaseEscrow.FACTORY (contracts/BaseEscrow.sol#31) is not in mixedCase
Variable Escrow.PROXY_BYTECODE_HASH (contracts/Escrow.sol#22) is not in mixedCase
Function IBaseEscrow.RESCUE_DELAY() (contracts/interfaces/IBaseEscrow.sol#52) is not in mixedCase
Function IBaseEscrow.FACTORY() (contracts/interfaces/IBaseEscrow.sol#54) is not in mixedCase
Function IEscrow.PROXY_BYTECODE_HASH() (contracts/interfaces/IEscrow.sol#14) is not in mixedCase
Function IERC20Permit.DOMAIN_SEPARATOR() (lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol#89) is not in mixedCase
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#conformance-to-solidity-naming-conventions

ProxyHashLib.computeProxyBytecodeHash(address) (contracts/libraries/ProxyHashLib.sol#15-25) uses literals with too many digits:
	- mstore(uint256,uint256)(0x00,implementation >> 0x88 | 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000) (contracts/libraries/ProxyHashLib.sol#22)
TimelocksLib.slitherConstructorConstantVariables() (contracts/libraries/TimelocksLib.sol#34-81) uses literals with too many digits:
	- _DEPLOYED_AT_MASK = 0xffffffff00000000000000000000000000000000000000000000000000000000 (contracts/libraries/TimelocksLib.sol#45)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#too-many-digits
. analyzed (21 contracts with 100 detectors), 46 result(s) found
Metadata
{
    "solc": {
        "status": "ok",
        "use_rc": 0,
        "version": "0.8.23",
        "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.23",
        "install_stderr": null,
        "install_stdout": "Version '0.8.23' is already installed, skipping..."
    },
    "solc_args": "--base-path /tmp/slither-q9vb76_3 --include-path /tmp/slither-q9vb76_3/lib --include-path /tmp/slither-q9vb76_3/lib/openzeppelin-contracts --include-path /tmp/slither-q9vb76_3/lib/solidity-utils --allow-paths /tmp/slither-q9vb76_3,/tmp/slither-q9vb76_3/lib,/tmp/slither-q9vb76_3/lib/openzeppelin-contracts,/tmp/slither-q9vb76_3/lib/solidity-utils,/tmp/slither-q9vb76_3/src",
    "remappings": [
        "@1inch/limit-order-protocol-contract/=lib/limit-order-protocol/",
        "@1inch/limit-order-settlement/=lib/limit-order-settlement/",
        "@1inch/solidity-utils/=lib/solidity-utils/",
        "solidity-utils/=lib/solidity-utils/",
        "limit-order-protocol/=lib/limit-order-protocol/",
        "limit-order-settlement/=lib/limit-order-settlement/",
        "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
        "ds-test/=lib/forge-std/lib/ds-test/src/",
        "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
        "forge-std/=lib/forge-std/src/",
        "murky/=lib/murky/",
        "openzeppelin-contracts/=lib/openzeppelin-contracts/"
    ],
    "source_files": [
        "contracts/EscrowDst.sol",
        "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol",
        "lib/solidity-utils/contracts/libraries/SafeERC20.sol",
        "lib/solidity-utils/contracts/libraries/AddressLib.sol",
        "contracts/libraries/TimelocksLib.sol",
        "contracts/interfaces/IEscrowDst.sol",
        "contracts/BaseEscrow.sol",
        "contracts/Escrow.sol",
        "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol",
        "lib/solidity-utils/contracts/interfaces/IDaiLikePermit.sol",
        "lib/solidity-utils/contracts/interfaces/IPermit2.sol",
        "lib/solidity-utils/contracts/interfaces/IERC7597Permit.sol",
        "lib/solidity-utils/contracts/interfaces/IWETH.sol",
        "lib/solidity-utils/contracts/libraries/RevertReasonForwarder.sol",
        "contracts/interfaces/IEscrow.sol",
        "contracts/libraries/ImmutablesLib.sol",
        "contracts/interfaces/IBaseEscrow.sol",
        "lib/openzeppelin-contracts/contracts/utils/Create2.sol",
        "contracts/libraries/ProxyHashLib.sol",
        "lib/openzeppelin-contracts/contracts/utils/Errors.sol"
    ],
    "contract_count": 0,
    "contract_names": [],
    "detector_count": 46,
    "workspace_hash": "44ede1c555649ec288338df4ae39eac737de512f62ed643327b56c09fdb33171",
    "duration_seconds": 0.8133449554443359,
    "solc_version_requested": "0.8.23"
}

Codex

report.consolidate
Job Status
complete
Attempts
1 / 6
Findings
0
No findings?
yes
Summary
No meaningful exploitable issues found in the implementation; core escrow logic is stateless and validates immutables against the CREATE2-derived address.
View stdout
{"no_findings":true,"summary":"No meaningful exploitable issues found in the implementation; core escrow logic is stateless and validates immutables against the CREATE2-derived address.","findings":[]}
View stderr
OpenAI Codex v0.77.0 (research preview)
--------
workdir: /tmp/codex-85dg_r1a
model: gpt-5.2-codex
provider: openai
approval: never
sandbox: read-only
reasoning effort: high
reasoning summaries: auto
session id: 019bb49b-03b9-7da2-bd4c-307c9e59b601
--------
user
Context: The user requested the proxy at 0x39c84b27db3219b876e6f09ddb4140bc67eecb69.
Audit the implementation at 0x9c3e06659f1c34f930ce97fcbce6e04ae88e535b.
Findings should refer to the implementation unless explicitly about proxy mechanics.

You are a security auditor. Audit this Solidity codebase for exploitable vulnerabilities.
Focus on: reentrancy, access control, upgradeability/proxy issues, signature validation, oracle manipulation,
accounting/invariant breaks, external call patterns, unchecked return values, and dangerous delegatecall.

Scope rules:
- You MUST fully read `AUDIT_BUNDLE.txt` before concluding. It contains the complete contents of all first-party Solidity sources in this workspace.
- Treat `lib/` and `@openzeppelin/` as third-party dependencies; skip them unless there is a concrete misuse angle in first-party code.
- If there are only dependency files and no first-party sources, set no_findings=true and explain in summary.

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 and file/line locations when possible.

Output constraints (IMPORTANT):
- severity MUST be exactly one of: info, low, medium, high, critical (lowercase).
- category MUST be exactly one of: access_control, reentrancy, math, oracle, upgradeability, auth, other.
Keep summary short and concrete.
mcp startup: no servers

thinking
**Choosing method to read AUDIT_BUNDLE**
exec
/bin/bash -lc ls in /tmp/codex-85dg_r1a succeeded in 5ms:
AUDIT_BUNDLE.txt
codex-output-schema.json
contracts
lib
exec
/bin/bash -lc 'cat AUDIT_BUNDLE.txt' in /tmp/codex-85dg_r1a succeeded in 7ms:
This file concatenates the full contents of first-party Solidity sources for auditing.
Do not treat dependency code under lib/ or @openzeppelin/ as first-party.

================================================================================
FILE: contracts/BaseEscrow.sol
================================================================================
// SPDX-License-Identifier: MIT

pragma solidity 0.8.23;

import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
import { AddressLib, Address } from "solidity-utils/contracts/libraries/AddressLib.sol";
import { SafeERC20 } from "solidity-utils/contracts/libraries/SafeERC20.sol";

import { ImmutablesLib } from "./libraries/ImmutablesLib.sol";
import { Timelocks, TimelocksLib } from "./libraries/TimelocksLib.sol";

import { IBaseEscrow } from "./interfaces/IBaseEscrow.sol";

/**


thinking
**Analyzing potential escrow contract vulnerabilities**

I'm auditing an escrow contract focusing on reentrancy risks, access controls, and token handling. I’m carefully inspecting how withdrawals, rescues, and cancellations work without state changes, the role of immutables in validating the contract’s address, and how repeated or reentrant calls might drain funds when unexpected tokens are sent or specific token behaviors like fee-on-transfer occur. There are nuanced considerations around factory deployment, minimal proxies, and timing of emergency rescues that influence contract safety.
thinking
**Evaluating immutables and proxy patterns**

I'm carefully verifying how immutable values, calldata handling, and proxy deployment interact, especially focusing on Create2 address validation and assumptions about encoded timelocks. I’m also checking the contract’s reliance on external token calls and potential edge cases in access token behavior, but overall, I find no critical issues in the stateless, immutable design and typical proxy usage.
codex
{"no_findings":true,"summary":"No meaningful exploitable issues found in the implementation; core escrow logic is stateless and validates immutables against the CREATE2-derived address.","findings":[]}
tokens used
16,955
Metadata
{
    "codex": {
        "ran_at": "2026-01-12T23:49:32.035921+00:00",
        "returncode": 0
    },
    "project": {
        "mode": "source",
        "file_count": 20,
        "import_count": 24,
        "first_party_contracts_count": 9
    },
    "summary": "No meaningful exploitable issues found in the implementation; core escrow logic is stateless and validates immutables against the CREATE2-derived address.",
    "raw_final": {
        "summary": "No meaningful exploitable issues found in the implementation; core escrow logic is stateless and validates immutables against the CREATE2-derived address.",
        "findings": [],
        "no_findings": true
    },
    "no_findings": true,
    "proxy_context": {
        "proxy_run_id": "019bb490-f341-7224-a82a-cad72e12cb5f",
        "proxy_address": "0x39c84b27db3219b876e6f09ddb4140bc67eecb69",
        "implementation_run_id": "019bb491-4432-70a1-a118-169deb6eada5",
        "implementation_address": "0x9c3e06659f1c34f930ce97fcbce6e04ae88e535b"
    },
    "schema_version": 1
}

Opcode Heuristics

tool.cast_disasm
Delegatecall
1
Selfdestruct
0
CREATE2
0
CALL-family (heavy)
0
EXT*/BALANCE
0
Total opcodes
24
Flags
delegatecall_present
View cast disassembly output
00000000: CALLDATASIZE
00000001: RETURNDATASIZE
00000002: RETURNDATASIZE
00000003: CALLDATACOPY
00000004: RETURNDATASIZE
00000005: RETURNDATASIZE
00000006: RETURNDATASIZE
00000007: CALLDATASIZE
00000008: RETURNDATASIZE
00000009: PUSH20 0x9c3e06659f1c34f930ce97fcbce6e04ae88e535b
0000001e: GAS
0000001f: DELEGATECALL
00000020: RETURNDATASIZE
00000021: DUP3
00000022: DUP1
00000023: RETURNDATACOPY
00000024: SWAP1
00000025: RETURNDATASIZE
00000026: SWAP2
00000027: PUSH1 0x2b
00000029: JUMPI
0000002a: REVERT
0000002b: JUMPDEST
0000002c: RETURN

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 no no
view
trace_id: 0x2609cbcd3b95c0461bbabb388e66bfca23b378c25b10be6a5dfdb1ffc186b337
call_targets: 0x9c3e06659f1c34f930ce97fcbce6e04ae88e535b
target_varies: no
classification: constant_target
validation_json
{
    "sink": "DELEGATECALL",
    "errors": 0,
    "status": "sink_reached",
    "attempts": 1,
    "trace_id": "0x2609cbcd3b95c0461bbabb388e66bfca23b378c25b10be6a5dfdb1ffc186b337",
    "confirmed": false,
    "trace_mode": "callTracer",
    "call_targets": [
        "0x9c3e06659f1c34f930ce97fcbce6e04ae88e535b"
    ],
    "matched_probe": null,
    "target_varies": false,
    "classification": "constant_target"
}
witness_json
{
    "notes": "heuristic witness; entrypoints are best-effort selectors with zeroed calldata",
    "constraints": [],
    "entrypoints": [
        {
            "calldata": "0x",
            "selector": "fallback",
            "calldata_variants": [
                "0x"
            ]
        }
    ]
}
evidence_json
{
    "examples": [
        {
            "pc": 31,
            "opcode": "DELEGATECALL",
            "returndata_checked": null,
            "value_expression_category": "n/a",
            "target_expression_category": "computed"
        }
    ],
    "guards_detected": [],
    "delegatecall_count": 1,
    "untrusted_delegatecall_count": 1
}
high other slither BaseEscrow._ethTransfer(address,uint256) (contracts/BaseEscrow.sol#95-98) sends eth to arbitrary user 85 no
view
evidence_json
{
    "impact": "High",
    "detector": "arbitrary-send-eth",
    "elements": [
        {
            "name": "_ethTransfer",
            "type": "function",
            "source_mapping": {
                "lines": [
                    95,
                    96,
                    97,
                    98
                ],
                "start": 3025,
                "length": 180,
                "ending_column": 6,
                "is_dependency": false,
                "filename_short": "contracts/BaseEscrow.sol",
                "starting_column": 5,
                "filename_absolute": "/tmp/slither-q9vb76_3/contracts/BaseEscrow.sol",
                "filename_relative": "contracts/BaseEscrow.sol"
            },
            "type_specific_fields": {
                "parent": {
                    "name": "BaseEscrow",
                    "type": "contract",
                    "source_mapping": {
                        "lines": [
                            19,
                            20,
                            21,
                            22,
                            23,
                            24,
                            25,
                            26,
                            27,
                            28,
                            29,
                            30,
                            31,
                            32,
                            33,
                            34,
                            35,
                            36,
                            37,
                            38,
                            39,
                            40,
                            41,
                            42,
                            43,
                            44,
                            45,
                            46,
                            47,
                            48,
                            49,
                            50,
                            51,
                            52,
                            53,
                            54,
                            55,
                            56,
                            57,
                            58,
                            59,
                            60,
                            61,
                            62,
                            63,
                            64,
                            65,
                            66,
                            67,
                            68,
                            69,
                            70,
                            71,
                            72,
                            73,
                            74,
                            75,
                            76,
                            77,
                            78,
                            79,
                            80,
                            81,
                            82,
                            83,
                            84,
                            85,
                            86,
                            87,
                            88,
                            89,
                            90,
                            91,
                            92,
                            93,
                            94,
                            95,
                            96,
                            97,
                            98,
                            99,
                            100,
                            101,
                            102,
                            103,
                            104,
                            105,
                            106,
                            107,
                            108,
                            109,
                            110,
                            111,
                            112,
                            113,
                            114,
                            115,
                            116
                        ],
                        "start": 761,
                        "length": 3016,
                        "ending_column": 2,
                        "is_dependency": false,
                        "filename_short": "contracts/BaseEscrow.sol",
                        "starting_column": 1,
                        "filename_absolute": "/tmp/slither-q9vb76_3/contracts/BaseEscrow.sol",
                        "filename_relative": "contracts/BaseEscrow.sol"
                    }
                },
                "signature": "_ethTransfer(address,uint256)"
            }
        },
        {
            "name": "(success,None) = to.call{value: amount}()",
            "type": "node",
            "source_mapping": {
                "lines": [
                    96
                ],
                "start": 3094,
                "length": 46,
                "ending_column": 55,
                "is_dependency": false,
                "filename_short": "contracts/BaseEscrow.sol",
                "starting_column": 9,
                "filename_absolute": "/tmp/slither-q9vb76_3/contracts/BaseEscrow.sol",
                "filename_relative": "contracts/BaseEscrow.sol"
            },
            "type_specific_fields": {
                "parent": {
                    "name": "_ethTransfer",
                    "type": "function",
                    "source_mapping": {
                        "lines": [
                            95,
                            96,
                            97,
                            98
                        ],
                        "start": 3025,
                        "length": 180,
                        "ending_column": 6,
                        "is_dependency": false,
                        "filename_short": "contracts/BaseEscrow.sol",
                        "starting_column": 5,
                        "filename_absolute": "/tmp/slither-q9vb76_3/contracts/BaseEscrow.sol",
                        "filename_relative": "contracts/BaseEscrow.sol"
                    },
                    "type_specific_fields": {
                        "parent": {
                            "name": "BaseEscrow",
                            "type": "contract",
                            "source_mapping": {
                                "lines": [
                                    19,
                                    20,
                                    21,
                                    22,
                                    23,
                                    24,
                                    25,
                                    26,
                                    27,
                                    28,
                                    29,
                                    30,
                                    31,
                                    32,
                                    33,
                                    34,
                                    35,
                                    36,
                                    37,
                                    38,
                                    39,
                                    40,
                                    41,
                                    42,
                                    43,
                                    44,
                                    45,
                                    46,
                                    47,
                                    48,
                                    49,
                                    50,
                                    51,
                                    52,
                                    53,
                                    54,
                                    55,
                                    56,
                                    57,
                                    58,
                                    59,
                                    60,
                                    61,
                                    62,
                                    63,
                                    64,
                                    65,
                                    66,
                                    67,
                                    68,
                                    69,
                                    70,
                                    71,
                                    72,
                                    73,
                                    74,
                                    75,
                                    76,
                                    77,
                                    78,
                                    79,
                                    80,
                                    81,
                                    82,
                                    83,
                                    84,
                                    85,
                                    86,
                                    87,
                                    88,
                                    89,
                                    90,
                                    91,
                                    92,
                                    93,
                                    94,
                                    95,
                                    96,
                                    97,
                                    98,
                                    99,
                                    100,
                                    101,
                                    102,
                                    103,
                                    104,
                                    105,
                                    106,
                                    107,
                                    108,
                                    109,
                                    110,
                                    111,
                                    112,
                                    113,
                                    114,
                                    115,
                                    116
                                ],
                                "start": 761,
                                "length": 3016,
                                "ending_column": 2,
                                "is_dependency": false,
                                "filename_short": "contracts/BaseEscrow.sol",
                                "starting_column": 1,
                                "filename_absolute": "/tmp/slither-q9vb76_3/contracts/BaseEscrow.sol",
                                "filename_relative": "contracts/BaseEscrow.sol"
                            }
                        },
                        "signature": "_ethTransfer(address,uint256)"
                    }
                }
            }
        }
    ],
    "locations": [
        {
            "file": "contracts/BaseEscrow.sol",
            "name": "_ethTransfer",
            "type": "function",
            "lines": [
                95,
                96,
                97,
                98
            ]
        },
        {
            "file": "contracts/BaseEscrow.sol",
            "name": "(success,None) = to.call{value: amount}()",
            "type": "node",
            "lines": [
                96
            ]
        }
    ],
    "description": "BaseEscrow._ethTransfer(address,uint256) (contracts/BaseEscrow.sol#95-98) sends eth to arbitrary user\n\tDangerous calls:\n\t- (success,None) = to.call{value: amount}() (contracts/BaseEscrow.sol#96)"
}
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
}