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

Analysis Run

019be3d6-828a-71dc-80f1-1fb633b503be

failed
Chain ID
1
Address
Block Number
Created
Thu, Jan 22, 2026 3:54 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
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
40673 artifact.fetch complete 1 / 3 2 months ago
40674 proxy.resolve complete 1 / 3 2 months ago
40675 tool.cast_disasm complete 1 / 3 2 months ago
40676 analysis.bundle complete 1 / 3 2 months ago
40677 capability.graph complete 1 / 3 2 months ago
40678 detector.run complete 1 / 3 2 months ago
40679 validation.fork complete 1 / 3 2 months ago
41278 report.consolidate complete 1 / 6 2 months ago
41279 tool.slither failed 2 / 2 2 months ago

Artifact

Runtime bytecode: available
Creation TX:
Deployer:
Proxy: yes confirmed
Verified Source: yes
Proxy evidence
{
    "method": "etherscan+onchain",
    "status": "confirmed",
    "etherscan_hint": {
        "source": "etherscan",
        "etherscan": {
            "proxy_flag": true,
            "implementation": "0xc973d09e51a20c9ab0214c439e4b34dbac52ad67"
        }
    },
    "implementation": "0xc973d09e51a20c9ab0214c439e4b34dbac52ad67",
    "onchain_method": "eip1967"
}

Slither

tool.slither
Status
failed slither failed (exit 1): 'forge clean' running (wd: /tmp/slither-cdlejaw7) 'forge config --json' running 'forge build --build-info --skip ./test/** ./script/** --force' running (wd: /tmp/slither-cdlejaw7) Traceback (most recent call last): File "/var/www/tripwire/.venv/bin/slither", line 10, in <module> sys.exit(main()) ~~~~^^ File "/var/www/tripwire/.venv/lib/python3.13/site-packages/slither/__main__.py", line 776, in main main_impl(all_detector_classes=detectors, all_printer_classes=printers) ~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/var/www/tripwire/.venv/lib/python3.13/site-packages/slither/__main__.py", line 882, in main_impl ) = process_all(filename, args, detector_classes, printer_classes) ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/var/www/tripwire/.venv/lib/python3.13/site-packages/slither/__main__.py", line 96, in process_all compilations = compile_all(target, **vars(args)) File "/var/www/tripwire/.venv/lib/python3.13/site-packages/crytic_compile/crytic_compile.py", line 722, in compile_all compilations.append(CryticCompile(target, **kwargs)) ~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^ File "/var/www/tripwire/.venv/lib/python3.13/site-packages/crytic_compile/crytic_compile.py", line 211, in __init__ self._compile(**kwargs) ~~~~~~~~~~~~~^^^^^^^^^^ File "/var/www/tripwire/.venv/lib/python3.13/site-packages/crytic_compile/crytic_compile.py", line 633, in _compile self._platform.compile(self, **kwargs) ~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^ File "/var/www/tripwire/.venv/lib/python3.13/site-packages/crytic_compile/platform/foundry.py", line 102, in compile hardhat_like_parsing( ~~~~~~~~~~~~~~~~~~~~^ crytic_compile, str(self._target), build_directory, str(self._project_root) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ) ^ File "/var/www/tripwire/.venv/lib/python3.13/site-packages/crytic_compile/platform/hardhat.py", line 52, in hardhat_like_parsing raise InvalidCompilation(txt) crytic_compile.platform.exceptions.InvalidCompilation: Compilation failed. Can you run build command? /tmp/slither-cdlejaw7/out/build-info is not a directory.
Attempts
2 / 2
Findings
0
Solc
View stderr
Traceback (most recent call last):
  File "/var/www/tripwire/worker/worker.py", line 198, in main
    payload = dispatch_job(job_type, job_id, job_meta, run_data, config, laravel_client)
  File "/var/www/tripwire/worker/worker.py", line 114, in dispatch_job
    return slither_run.run(job_id, job_meta, run_data, config, log, laravel_client)
           ~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/var/www/tripwire/worker/jobs/slither_run.py", line 1084, in run
    stdout_text, stderr_text, result_json = _run_slither(
                                            ~~~~~~~~~~~~^
        workspace,
        ^^^^^^^^^^
    ...<4 lines>...
        target_path=target_path,
        ^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/var/www/tripwire/worker/jobs/slither_run.py", line 958, in _run_slither
    raise RuntimeError(f"slither failed (exit {result.returncode}): {stderr_text or stdout_text}")
RuntimeError: slither failed (exit 1): 'forge clean' running (wd: /tmp/slither-cdlejaw7)
'forge config --json' running
'forge build --build-info --skip ./test/** ./script/** --force' running (wd: /tmp/slither-cdlejaw7)
Traceback (most recent call last):
  File "/var/www/tripwire/.venv/bin/slither", line 10, in <module>
    sys.exit(main())
             ~~~~^^
  File "/var/www/tripwire/.venv/lib/python3.13/site-packages/slither/__main__.py", line 776, in main
    main_impl(all_detector_classes=detectors, all_printer_classes=printers)
    ~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/var/www/tripwire/.venv/lib/python3.13/site-packages/slither/__main__.py", line 882, in main_impl
    ) = process_all(filename, args, detector_classes, printer_classes)
        ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/var/www/tripwire/.venv/lib/python3.13/site-packages/slither/__main__.py", line 96, in process_all
    compilations = compile_all(target, **vars(args))
  File "/var/www/tripwire/.venv/lib/python3.13/site-packages/crytic_compile/crytic_compile.py", line 722, in compile_all
    compilations.append(CryticCompile(target, **kwargs))
                        ~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^
  File "/var/www/tripwire/.venv/lib/python3.13/site-packages/crytic_compile/crytic_compile.py", line 211, in __init__
    self._compile(**kwargs)
    ~~~~~~~~~~~~~^^^^^^^^^^
  File "/var/www/tripwire/.venv/lib/python3.13/site-packages/crytic_compile/crytic_compile.py", line 633, in _compile
    self._platform.compile(self, **kwargs)
    ~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^
  File "/var/www/tripwire/.venv/lib/python3.13/site-packages/crytic_compile/platform/foundry.py", line 102, in compile
    hardhat_like_parsing(
    ~~~~~~~~~~~~~~~~~~~~^
        crytic_compile, str(self._target), build_directory, str(self._project_root)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/var/www/tripwire/.venv/lib/python3.13/site-packages/crytic_compile/platform/hardhat.py", line 52, in hardhat_like_parsing
    raise InvalidCompilation(txt)
crytic_compile.platform.exceptions.InvalidCompilation: Compilation failed. Can you run build command?
/tmp/slither-cdlejaw7/out/build-info is not a directory.

Codex

report.consolidate
Job Status
complete
Attempts
1 / 6
Findings
1
No findings?
no
Summary
The implementation relies on a single relayer to authorize all finalizations without any on-chain proof or fee validation, allowing arbitrary withdrawals if that relayer is compromised or malicious.
View stdout
{"no_findings":false,"summary":"The implementation relies on a single relayer to authorize all finalizations without any on-chain proof or fee validation, allowing arbitrary withdrawals if that relayer is compromised or malicious.","findings":[{"severity":"high","category":"access_control","title":"Relayer can finalize arbitrary transfers without proof or fee verification","exploit_scenario":"If the relayer key is compromised or malicious, it can call finalizeTransfer with any recipient and amount (and set any _finalizationFee ≤ _amount). Because there is no on-chain verification of a corresponding TransferInitiated event or cryptographic proof from the counterparty chain, the relayer can drain escrowed ETH by fabricating finalizations and incrementing the index sequentially.","recommendation":"Introduce on-chain verification of transfer proofs (e.g., light-client or validator/committee signatures) and validate _finalizationFee against an authenticated value from the counterparty chain. At minimum, require a threshold of trusted signers or a multisig for finalizeTransfer.","evidence":"finalizeTransfer is gated only by onlyRelayer and checks only the sequential index and _amount ≥ _finalizationFee; it does not verify any proof of a real transfer or a fixed fee.","locations":["contracts/standard-bridge/Gateway.sol:45"]}]}
View stderr
OpenAI Codex v0.77.0 (research preview)
--------
workdir: /tmp/codex-z_14u5ro
model: gpt-5.2-codex
provider: openai
approval: never
sandbox: read-only
reasoning effort: high
reasoning summaries: auto
session id: 019be412-e092-7ea2-ba88-eaa5d505ebc3
--------
user
Context: The user requested the proxy at 0xdbf24caff1470a6d08bf2ff2c6875bafc60cf881.
Audit the implementation at 0xc973d09e51a20c9ab0214c439e4b34dbac52ad67.
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
**Preparing to audit bundle contents**
exec
/bin/bash -lc ls in /tmp/codex-z_14u5ro succeeded in 13ms:
AUDIT_BUNDLE.txt
codex-output-schema.json
contracts
lib
exec
/bin/bash -lc "sed -n '1,200p' AUDIT_BUNDLE.txt" in /tmp/codex-z_14u5ro succeeded in 6ms:
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/interfaces/IGateway.sol
================================================================================
// SPDX-License-Identifier: BSL 1.1
pragma solidity 0.8.26;

/**
 * @title IGateway
 * @dev Interface for the Gateway contract in the standard bridge.
 */
interface IGateway {
    /**
     * @dev Emitted when a cross-chain transfer is initiated.
     * @param sender Address initiating the transfer.
     * @param recipient Address receiving the tokens.
     * @param amount Ether being transferred in wei.
     * @param transferIdx Current index of this gateway.
exec
/bin/bash -lc "sed -n '200,400p' AUDIT_BUNDLE.txt" in /tmp/codex-z_14u5ro succeeded in 8ms:
    /// @dev See https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable#storage-gaps
    uint256[48] private __gap;
}

================================================================================
FILE: contracts/standard-bridge/L1Gateway.sol
================================================================================
// SPDX-License-Identifier: BSL 1.1
pragma solidity 0.8.26;

import {Gateway} from "./Gateway.sol";
import {L1GatewayStorage} from "./L1GatewayStorage.sol";
import {Errors} from "../utils/Errors.sol";

/// @title L1Gateway
/// @notice Gateway contract deployed on L1 enabling the mev-commit standard bridge.
/// @dev This contract will escrow locked ETH, while a corresponding amount is minted from the SettlementGateway on the mev-commit chain.
contract L1Gateway is L1GatewayStorage, Gateway {

    /// @dev Emitted when a transfer needs withdrawal.


thinking
**Auditing fee and finalize logic**

Noticed initialize sets relayer and counterpartyFinalizationFee without zero checks, risking zero values if misconfigured. Also, finalizeTransfer allows relayer to set finalizationFee without verifying it matches stored counterpartyFinalizationFee, potentially enabling overpayment to relayer. This suggests a medium risk if relayer or owner is compromised, since fees aren't strictly validated against expected values.
thinking
**Identifying relayer trust and fund handling risks**

Confirmed relayer can finalize arbitrary transfers without proof, enabling full fund control and fee manipulation, reflecting a fundamental trust assumption rather than a direct vulnerability. Found a potential undercollateralization bug if recipient send fails but relayer fee is still paid, which can lock recipient withdrawals due to insufficient contract balance—this is a significant edge case worth flagging.
exec
/bin/bash -lc 'nl -ba contracts/standard-bridge/Gateway.sol' in /tmp/codex-z_14u5ro succeeded in 6ms:
     1	// SPDX-License-Identifier: BSL 1.1
     2	pragma solidity 0.8.26;
     3	
     4	import {Ownable2StepUpgradeable} from "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol";
     5	import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
     6	import {PausableUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol";
     7	import {ReentrancyGuardUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol";
     8	import {IGateway} from "../interfaces/IGateway.sol";
     9	import {GatewayStorage} from "./GatewayStorage.sol";
    10	
    11	abstract contract Gateway is IGateway, GatewayStorage,
    12	    Ownable2StepUpgradeable, UUPSUpgradeable, PausableUpgradeable, ReentrancyGuardUpgradeable {   
    13	
    14	    modifier onlyRelayer() {
    15	        require(msg.sender == relayer, SenderNotRelayer(msg.sender, relayer));
    16	        _;
    17	    }
    18	
    19	    /// @dev Initiates a transfer from the source chain gateway to its counterparty gateway on another chain.
    20	    /// @notice The _recipient is transferred eth on the destination chain via solidity's send function (with built-in gas limit).

thinking
**Requesting more L1Gateway lines**
exec
/bin/bash -lc 'nl -ba contracts/standard-bridge/L1Gateway.sol' in /tmp/codex-z_14u5ro succeeded in 6ms:
     1	// SPDX-License-Identifier: BSL 1.1
     2	pragma solidity 0.8.26;
     3	
     4	import {Gateway} from "./Gateway.sol";
     5	import {L1GatewayStorage} from "./L1GatewayStorage.sol";
     6	import {Errors} from "../utils/Errors.sol";
     7	
     8	/// @title L1Gateway
     9	/// @notice Gateway contract deployed on L1 enabling the mev-commit standard bridge.
    10	/// @dev This contract will escrow locked ETH, while a corresponding amount is minted from the SettlementGateway on the mev-commit chain.
    11	contract L1Gateway is L1GatewayStorage, Gateway {
    12	
    13	    /// @dev Emitted when a transfer needs withdrawal.
    14	    event TransferNeedsWithdrawal(address indexed recipient, uint256 amount);
    15	
    16	    /// @dev Emitted when a transfer is successful.
    17	    event TransferSuccess(address indexed recipient, uint256 amount);
    18	
    19	    error IncorrectEtherValueSent(uint256 msgValue, uint256 amountExpected);
    20	    error InsufficientContractBalance(uint256 thisContractBalance, uint256 amountRequested);


thinking
**Summarizing key potential vulnerabilities**

Identified that the centralized relayer can finalize arbitrary amounts, recipients, and fees without transfer proof validation, posing a high-severity risk due to single key compromise draining escrow. Also noted the relayer controls the finalization fee unchecked on-chain, consolidating these issues into one finding about relayer centralization. Confirmed that the gas limitation on send in fund withdrawal is intentional and not a vulnerability.
thinking
**Detailing central relayer vulnerability and severity decision**

Clarified that the core finding centers on the single relayer’s ability to finalize arbitrary transfers and set fees without on-chain proof, posing a high-severity access control risk. Decided to consolidate fee verification absence within this primary finding and include a clear exploit scenario, evidence references, and recommended mitigations in the JSON output.
codex
{"no_findings":false,"summary":"The implementation relies on a single relayer to authorize all finalizations without any on-chain proof or fee validation, allowing arbitrary withdrawals if that relayer is compromised or malicious.","findings":[{"severity":"high","category":"access_control","title":"Relayer can finalize arbitrary transfers without proof or fee verification","exploit_scenario":"If the relayer key is compromised or malicious, it can call finalizeTransfer with any recipient and amount (and set any _finalizationFee ≤ _amount). Because there is no on-chain verification of a corresponding TransferInitiated event or cryptographic proof from the counterparty chain, the relayer can drain escrowed ETH by fabricating finalizations and incrementing the index sequentially.","recommendation":"Introduce on-chain verification of transfer proofs (e.g., light-client or validator/committee signatures) and validate _finalizationFee against an authenticated value from the counterparty chain. At minimum, require a threshold of trusted signers or a multisig for finalizeTransfer.","evidence":"finalizeTransfer is gated only by onlyRelayer and checks only the sequential index and _amount ≥ _finalizationFee; it does not verify any proof of a real transfer or a fixed fee.","locations":["contracts/standard-bridge/Gateway.sol:45"]}]}
tokens used
16,301
Metadata
{
    "codex": {
        "ran_at": "2026-01-22T05:01:47.025965+00:00",
        "returncode": 0
    },
    "project": {
        "mode": "source",
        "file_count": 18,
        "import_count": 18,
        "first_party_contracts_count": 6
    },
    "summary": "The implementation relies on a single relayer to authorize all finalizations without any on-chain proof or fee validation, allowing arbitrary withdrawals if that relayer is compromised or malicious.",
    "raw_final": {
        "summary": "The implementation relies on a single relayer to authorize all finalizations without any on-chain proof or fee validation, allowing arbitrary withdrawals if that relayer is compromised or malicious.",
        "findings": [
            {
                "title": "Relayer can finalize arbitrary transfers without proof or fee verification",
                "category": "access_control",
                "evidence": "finalizeTransfer is gated only by onlyRelayer and checks only the sequential index and _amount \u2265 _finalizationFee; it does not verify any proof of a real transfer or a fixed fee.",
                "severity": "high",
                "locations": [
                    "contracts/standard-bridge/Gateway.sol:45"
                ],
                "recommendation": "Introduce on-chain verification of transfer proofs (e.g., light-client or validator/committee signatures) and validate _finalizationFee against an authenticated value from the counterparty chain. At minimum, require a threshold of trusted signers or a multisig for finalizeTransfer.",
                "exploit_scenario": "If the relayer key is compromised or malicious, it can call finalizeTransfer with any recipient and amount (and set any _finalizationFee \u2264 _amount). Because there is no on-chain verification of a corresponding TransferInitiated event or cryptographic proof from the counterparty chain, the relayer can drain escrowed ETH by fabricating finalizations and incrementing the index sequentially."
            }
        ],
        "no_findings": false
    },
    "no_findings": false,
    "proxy_context": {
        "proxy_run_id": "019be3d6-828a-71dc-80f1-1fb633b503be",
        "proxy_address": "0xdbf24caff1470a6d08bf2ff2c6875bafc60cf881",
        "implementation_run_id": "019be3d7-52ed-7231-975b-72409c137e98",
        "implementation_address": "0xc973d09e51a20c9ab0214c439e4b34dbac52ad67"
    },
    "schema_version": 1
}

Opcode Heuristics

tool.cast_disasm
Delegatecall
1
Selfdestruct
0
CREATE2
0
CALL-family (heavy)
0
EXT*/BALANCE
0
Total opcodes
46
Flags
delegatecall_present proxy_like_runtime
View cast disassembly output
00000000: PUSH1 0x80
00000002: PUSH1 0x40
00000004: MSTORE
00000005: PUSH32 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc
00000026: SLOAD
00000027: PUSH0
00000028: SWAP1
00000029: DUP2
0000002a: SWAP1
0000002b: PUSH1 0x01
0000002d: PUSH1 0x01
0000002f: PUSH1 0xa0
00000031: SHL
00000032: SUB
00000033: AND
00000034: CALLDATASIZE
00000035: DUP3
00000036: DUP1
00000037: CALLDATACOPY
00000038: DUP2
00000039: CALLDATASIZE
0000003a: SWAP2
0000003b: GAS
0000003c: DELEGATECALL
0000003d: RETURNDATASIZE
0000003e: PUSH0
0000003f: DUP1
00000040: RETURNDATACOPY
00000041: ISZERO
00000042: PUSH1 0x48
00000044: JUMPI
00000045: RETURNDATASIZE
00000046: PUSH0
00000047: RETURN
00000048: JUMPDEST
00000049: RETURNDATASIZE
0000004a: PUSH0
0000004b: REVERT
0000004c: INVALID
0000004d: LOG2
0000004e: PUSH5 0x6970667358
00000054: UNKNOWN(0x22)
00000055: SLT
00000056: KECCAK256
00000057: PUSH14 0x975dd30e6106636dbc53f0a50428
00000066: PUSH28

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: 0x0d1129ce59e63bbb075a404c8c2bdab12a7272168e20e2dbbb86fdf28f6d5d37
call_targets: 0xc973d09e51a20c9ab0214c439e4b34dbac52ad67
target_varies: no
classification: constant_target
validation_json
{
    "sink": "DELEGATECALL",
    "errors": 0,
    "status": "sink_reached",
    "attempts": 1,
    "trace_id": "0x0d1129ce59e63bbb075a404c8c2bdab12a7272168e20e2dbbb86fdf28f6d5d37",
    "confirmed": false,
    "trace_mode": "callTracer",
    "call_targets": [
        "0xc973d09e51a20c9ab0214c439e4b34dbac52ad67"
    ],
    "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": 60,
            "opcode": "DELEGATECALL",
            "returndata_checked": null,
            "value_expression_category": "n/a",
            "target_expression_category": "computed"
        }
    ],
    "guards_detected": [],
    "delegatecall_count": 1,
    "untrusted_delegatecall_count": 1
}
high access_control codex Relayer can finalize arbitrary transfers without proof or fee verification 85 no
view
evidence_json
{
    "evidence": "finalizeTransfer is gated only by onlyRelayer and checks only the sequential index and _amount \u2265 _finalizationFee; it does not verify any proof of a real transfer or a fixed fee.",
    "locations": [
        "contracts/standard-bridge/Gateway.sol:45"
    ],
    "recommendation": "Introduce on-chain verification of transfer proofs (e.g., light-client or validator/committee signatures) and validate _finalizationFee against an authenticated value from the counterparty chain. At minimum, require a threshold of trusted signers or a multisig for finalizeTransfer.",
    "exploit_scenario": "If the relayer key is compromised or malicious, it can call finalizeTransfer with any recipient and amount (and set any _finalizationFee \u2264 _amount). Because there is no on-chain verification of a corresponding TransferInitiated event or cryptographic proof from the counterparty chain, the relayer can drain escrowed ETH by fabricating finalizations and incrementing the index sequentially."
}
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
}
info upgradeability cast Likely proxy-like runtime 60 no
view
evidence_json
{
    "notes": "short runtime with SLOAD and DELEGATECALL resembles minimal proxy/upgradeable pattern",
    "sload_count": 1,
    "total_opcodes": 46,
    "delegatecall_count": 1
}