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

Analysis Run

019bab3b-ac5a-722f-b716-e6968b11ca70

failed
Chain ID
1
Address
Block Number
Created
Sun, Jan 11, 2026 4:06 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
38744 artifact.fetch complete 1 / 3 3 months ago
38745 proxy.resolve complete 1 / 3 3 months ago
38746 tool.cast_disasm complete 1 / 3 3 months ago
38747 analysis.bundle complete 1 / 3 3 months ago
38748 capability.graph complete 1 / 3 3 months ago
38749 detector.run complete 1 / 3 3 months ago
38750 validation.fork complete 1 / 3 3 months ago
39166 report.consolidate complete 1 / 6 3 months ago
39167 tool.slither failed 2 / 2 3 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": "0x49643fc85fb1f25b6775ebbbdc69295d45105abc"
        }
    },
    "implementation": "0x49643fc85fb1f25b6775ebbbdc69295d45105abc",
    "onchain_method": "eip1967"
}

Slither

tool.slither
Status
failed slither failed (exit 1): 'forge clean' running (wd: /tmp/slither-z9z2vbz6) 'forge config --json' running 'forge build --build-info --skip ./test/** ./script/** --force' running (wd: /tmp/slither-z9z2vbz6) 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-z9z2vbz6/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-z9z2vbz6)
'forge config --json' running
'forge build --build-info --skip ./test/** ./script/** --force' running (wd: /tmp/slither-z9z2vbz6)
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-z9z2vbz6/out/build-info is not a directory.

Codex

report.consolidate
Job Status
complete
Attempts
1 / 6
Findings
3
No findings?
no
Summary
Identified three issues: retired committees retain authority to process requests; transfer limit logic can ignore USD minima; and oracle anomalies can bypass limits due to unchecked prices combined with fail-open handling.
View stdout
{"no_findings":false,"summary":"Identified three issues: retired committees retain authority to process requests; transfer limit logic can ignore USD minima; and oracle anomalies can bypass limits due to unchecked prices combined with fail-open handling.","findings":[{"severity":"high","category":"access_control","title":"Retired committee members remain authorized to process requests","exploit_scenario":"After a committee rotation, members of the old committee can still call `receiveRequest` with their historical `_committeeId` and reach the previous `signatureThreshold`. They can mint or release arbitrary amounts by submitting any parameters and signing among themselves, even if governance intended to revoke them.","recommendation":"Enforce that `receiveRequest` only accepts the current `committeeId`, or add an explicit `activeCommitteeId`/revocation mechanism so old committees are disabled once a new committee is set. If you need overlap for in-flight requests, add a bounded grace period.","evidence":"`setCommittee` only increments `committeeId` and adds new members; it never disables old committees. `receiveRequest` accepts any `_committeeId` provided by the caller and only checks membership for that id.","locations":["contracts/AbstractMost.sol:295","contracts/AbstractMost.sol:367"]},{"severity":"medium","category":"other","title":"USD transfer minimum is ignored when default minimum is smaller (often zero)","exploit_scenario":"If `defaultMinima[_token]` is left at the default `0` (or set lower than the USD-based minimum), `minimumTransferAmount` returns the smaller of the two values. This makes the USD oracle limit ineffective, allowing any amount to pass `isRequestAllowed`.","recommendation":"When a USD oracle is configured, use the USD-derived minimum as the floor (e.g., `Math.max(defaultMinima, usdBasedMinimum)`), or if `defaultMinima` is zero, treat it as unset and use the USD value directly.","evidence":"`minimumTransferAmount` computes `usdBasedMinimum` and then uses `Math.min(minimum, usdBasedMinimum)`, which selects the smaller threshold.","locations":["contracts/TransferLimit.sol:62"]},{"severity":"medium","category":"oracle","title":"Oracle anomalies can bypass transfer limits due to unchecked price and fail-open handling","exploit_scenario":"If the oracle returns zero, negative, or stale data, `minimumTransferAmount` can revert (division by zero) or underflow to an extremely large uint cast. `Most.checkTransferAllowed` catches all errors and proceeds as if no limit exists, so an attacker who can manipulate oracle responses can bypass transfer limits entirely.","recommendation":"Validate `usdPrice > 0`, ensure `answeredInRound >= roundId`, and check `updatedAt` freshness before using prices. Consider failing closed (revert) in `Most` when the transfer limit contract errors instead of ignoring failures.","evidence":"`minimumTransferAmount` casts `usdPrice` to `uint256` with no checks and divides by it; `Most.checkTransferAllowed` catches and ignores failures.","locations":["contracts/TransferLimit.sol:68","contracts/Most.sol:41"]}]}
View stderr
OpenAI Codex v0.77.0 (research preview)
--------
workdir: /tmp/codex-1ve8blzm
model: gpt-5.2-codex
provider: openai
approval: never
sandbox: read-only
reasoning effort: high
reasoning summaries: auto
session id: 019babde-a604-7513-b216-56422c002384
--------
user
Context: The user requested the proxy at 0xf2139f5c8afb8a4d64084efc5532830774742830.
Audit the implementation at 0x49643fc85fb1f25b6775ebbbdc69295d45105abc.
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
**Reading AUDIT_BUNDLE file**
exec
/bin/bash -lc ls in /tmp/codex-1ve8blzm succeeded in 8ms:
AUDIT_BUNDLE.txt
@chainlink
codex-output-schema.json
contracts
@openzeppelin
@openzeppelin-4.5.0
exec
/bin/bash -lc 'cat AUDIT_BUNDLE.txt' in /tmp/codex-1ve8blzm 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: @chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol
================================================================================
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

// solhint-disable-next-line interface-starts-with-i
interface AggregatorV3Interface {
  function decimals() external view returns (uint8);

  function description() external view returns (string memory);

  function version() external view returns (uint256);

  function getRoundData(
    uint80 _roundId
  ) external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);

thinking
**Searching for relevant contracts**
exec
/bin/bash -lc 'rg "''^FILE:" -n AUDIT_BUNDLE.txt' in /tmp/codex-1ve8blzm succeeded in 16ms:
5:FILE: @chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol
29:FILE: @openzeppelin-4.5.0/contracts/access/Ownable.sol
109:FILE: @openzeppelin-4.5.0/contracts/security/ReentrancyGuard.sol
176:FILE: @openzeppelin-4.5.0/contracts/token/ERC20/ERC20.sol
563:FILE: @openzeppelin-4.5.0/contracts/token/ERC20/IERC20.sol
649:FILE: @openzeppelin-4.5.0/contracts/token/ERC20/extensions/IERC20Metadata.sol
681:FILE: @openzeppelin-4.5.0/contracts/token/ERC20/utils/SafeERC20.sol
784:FILE: @openzeppelin-4.5.0/contracts/utils/Address.sol
1010:FILE: @openzeppelin-4.5.0/contracts/utils/Context.sol
1038:FILE: contracts/AbstractMost.sol
1507:FILE: contracts/ITransferLimit.sol
1523:FILE: contracts/IWETH9.sol
1538:FILE: contracts/IWrappedToken.sol
1556:FILE: contracts/MockOracle.sol
1586:FILE: contracts/Most.sol
1643:FILE: contracts/MostL2.sol
1983:FILE: contracts/StableSwap/IStableSwapLP.sol
2002:FILE: contracts/StableSwap/StableSwapLP.sol
2038:FILE: contracts/StableSwap/StableSwapTwoPool.sol
2998:FILE: contracts/Token.sol

thinking
**Reviewing main contract files**
exec
/bin/bash -lc 'rg --files contracts' in /tmp/codex-1ve8blzm succeeded in 37ms:
contracts/IWETH9.sol
contracts/WrappedToken.sol
contracts/MostL2.sol
contracts/Token.sol
contracts/MockOracle.sol
contracts/IWrappedToken.sol
contracts/TransferLimit.sol
contracts/AbstractMost.sol
contracts/ITransferLimit.sol
contracts/Most.sol
contracts/StableSwap/IStableSwapLP.sol
contracts/StableSwap/StableSwapTwoPool.sol
contracts/StableSwap/StableSwapLP.sol

thinking
**Inspecting AbstractMost class**
exec
/bin/bash -lc "sed -n '1,240p' contracts/AbstractMost.sol" in /tmp/codex-1ve8blzm succeeded in 5ms:
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import {Ownable2StepUpgradeable} from "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol";
import {PausableUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol";
import {IWETH9} from "./IWETH9.sol";
import {IWrappedToken} from "./IWrappedToken.sol";

/// @title Most
/// @author Cardinal Cryptography
abstract contract AbstractMost is
    Initializable,
    UUPSUpgradeable,
    Ownable2StepUpgradeable,
    PausableUpgradeable
exec
/bin/bash -lc "sed -n '240,520p' contracts/AbstractMost.sol" in /tmp/codex-1ve8blzm succeeded in 26ms:
            amount,
            destReceiverAddress,
            requestNonce
        );

        ++requestNonce;
    }

    function onReceiveRequestThresholdMet(
        bytes32 requestHash,
        bytes32 destTokenAddress,
        uint256 amount,
        bytes32 destReceiverAddress
    ) internal virtual {
        processedRequests[requestHash] = true;
        delete pendingRequests[requestHash];

        address _destTokenAddress = bytes32ToAddress(destTokenAddress);
        address _destReceiverAddress = bytes32ToAddress(destReceiverAddress);


thinking
**Identifying required components**
exec
/bin/bash -lc "sed -n '1,220p' contracts/Most.sol" in /tmp/codex-1ve8blzm succeeded in 7ms:
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

import {AbstractMost} from "./AbstractMost.sol";
import {ITransferLimit} from "./ITransferLimit.sol";

/// @title Most
/// @author Cardinal Cryptography
contract Most is AbstractMost {
    ITransferLimit public transferLimit;

    /// @custom:oz-upgrades-unsafe-allow constructor
    constructor() {
        _disableInitializers();
    }

    function setTransferLimitContract(
        ITransferLimit _transferLimit
    ) external onlyOwner {
exec
/bin/bash -lc "sed -n '1,220p' contracts/MostL2.sol" in /tmp/codex-1ve8blzm succeeded in 19ms:
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

import {AbstractMost} from "./AbstractMost.sol";
import {StableSwapTwoPool} from "./StableSwap/StableSwapTwoPool.sol";
import {IWrappedToken} from "./IWrappedToken.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

/// @title MostL2.sol
/// @author Cardinal Cryptography
contract MostL2 is AbstractMost {
    using SafeERC20 for IERC20;

    /// Ratio between bridged azero (12 decimals) and native token on L2 (18 decimals)
    uint256 public constant BAZERO_TO_NATIVE_RATIO = 1e6;

    address payable public stableSwapAddress;
    address public bAzeroAddress;
exec
/bin/bash -lc "sed -n '220,520p' contracts/MostL2.sol" in /tmp/codex-1ve8blzm succeeded in 13ms:
    }

    /// @notice Invoke this tx to transfer funds to the destination chain.
    /// Account needs to send native Azero which are swapped for bazero
    /// tokens. Since the Bazero have 12 decimals and Azero have 18,
    /// user need to send at leas 10e6 tokens with this call.
    ///
    /// @dev Tx emits a CrosschainTransferRequest event that the relayers listen to
    /// & forward to the destination chain.
    function sendRequestNative(
        bytes32 destReceiverAddress,
        uint256 amount_to_bridge
    ) external payable whenNotPaused {
        require(
            amount_to_bridge >= BAZERO_TO_NATIVE_RATIO,
            "Value must be at least 10e6"
        );
        if (destReceiverAddress == bytes32(0)) {
            revert ZeroAddress();
        }

thinking
**Identifying required interfaces**
exec
/bin/bash -lc "sed -n '1,160p' contracts/ITransferLimit.sol" in /tmp/codex-1ve8blzm succeeded in 28ms:
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";

interface ITransferLimit {
    function isRequestAllowed(
        address _token,
        uint256 _amount
    ) external view returns (bool);
}
exec
/bin/bash -lc "sed -n '1,160p' contracts/IWrappedToken.sol" in /tmp/codex-1ve8blzm succeeded in 5ms:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.2;

/// @title Interface for WrappedToken
interface IWrappedToken {
    /// @notice Mint a given amount of remote PSP22 token representation to a given address
    function mint(address, uint256) external;

    /// @notice Burn a given amount of remote PSP22 token representation
    function burn(uint256) external;

    /// @notice Approve spending a given amount of token to the spender
    function approve(address spender, uint256 value) external returns (bool);
}
exec
/bin/bash -lc "sed -n '1,200p' contracts/MockOracle.sol" in /tmp/codex-1ve8blzm succeeded in 6ms:
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

/// @title MockOracle
/// @author Cardinal Cryptography
/// @notice Mock Chainlink oracle for testing purposes
contract MockOracle {
    int public price;

    function setPrice(int _price) public {
        price = _price;
    }

    function latestRoundData()
        public
        view
        returns (uint80, int, uint, uint, uint80)
    {
        return (0, price, 0, 0, 0);

thinking
**Inspecting StableSwapTwoPool components**
exec
/bin/bash -lc "sed -n '1,260p' contracts/StableSwap/StableSwapTwoPool.sol" in /tmp/codex-1ve8blzm succeeded in 27ms:
// MIT License
//
// Copyright (c) 2024 PancakeSwap
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
exec
/bin/bash -lc "sed -n '260,620p' contracts/StableSwap/StableSwapTwoPool.sol" in /tmp/codex-1ve8blzm succeeded in 8ms:
                }
            } else {
                if (Dprev - D <= 1) {
                    break;
                }
            }
        }
        return D;
    }

    function get_D_mem(
        uint256[N_COINS] memory _balances,
        uint256 amp
    ) internal view returns (uint256) {
        return get_D(_xp_mem(_balances), amp);
    }

    function get_virtual_price() external view returns (uint256) {
        /**
        Returns portfolio virtual price (for calculating profit)
exec
/bin/bash -lc "sed -n '620,980p' contracts/StableSwap/StableSwapTwoPool.sol" in /tmp/codex-1ve8blzm succeeded in 27ms:
        uint256[N_COINS] memory fees;
        for (uint256 i = 0; i < N_COINS; i++) {
            uint256 ideal_balance = (D1 * old_balances[i]) / D0;
            uint256 difference;
            if (ideal_balance > new_balances[i]) {
                difference = ideal_balance - new_balances[i];
            } else {
                difference = new_balances[i] - ideal_balance;
            }
            fees[i] = (_fee * difference) / FEE_DENOMINATOR;
            balances[i] =
                new_balances[i] -
                ((fees[i] * _admin_fee) / FEE_DENOMINATOR);
            new_balances[i] -= fees[i];
        }
        uint256 D2 = get_D_mem(new_balances, amp);

        uint256 token_amount = ((D0 - D2) * token_supply) / D0;
        require(token_amount > 0, "token_amount must be greater than 0");
        token_amount += 1; // In case of rounding errors - make it unfavorable for the "attacker"

thinking
**Considering StableSwap LP concept**
exec
/bin/bash -lc "sed -n '1,220p' contracts/StableSwap/StableSwapLP.sol" in /tmp/codex-1ve8blzm succeeded in 5ms:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;

import "@openzeppelin-4.5.0/contracts/token/ERC20/ERC20.sol";

contract StableSwapLP is ERC20 {
    address public minter;

    constructor() ERC20("StableSwap LPs", "Stable-LP") {
        minter = msg.sender;
    }

    /**
     * @notice Checks if the msg.sender is the minter address.
     */
    modifier onlyMinter() {
        require(msg.sender == minter, "Not minter");
        _;
    }

exec
/bin/bash -lc "sed -n '1,200p' contracts/StableSwap/IStableSwapLP.sol" in /tmp/codex-1ve8blzm succeeded in 12ms:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;

interface IStableSwapLP {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    function mint(address _to, uint256 _amount) external;

    function burnFrom(address _to, uint256 _amount) external;

    function setMinter(address _newMinter) external;
}

thinking
**Identifying dependency IWETH9**
exec
/bin/bash -lc "sed -n '1,120p' contracts/IWETH9.sol" in /tmp/codex-1ve8blzm succeeded in 8ms:
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.2;

/// @title Interface for WETH9
interface IWETH9 {
    /// @notice Deposit ether to get wrapped ether
    function deposit() external payable;

    /// @notice Withdraw wrapped ether to get ether
    function withdraw(uint256) external;
}



thinking
**Analyzing smart contract trust and reentrancy risks**

I'm auditing a UUPS upgradeable bridge contract with guardian committees controlling minting. There’s no cryptographic signature validation—just guardian approvals via msg.sender—and older committees remain authorized after rotation, posing a potential access control vulnerability. Reentrancy issues may arise during token transfers especially with malicious ERC777 tokens and native fee handling, though some state updates precede external calls reducing risk. Oracle price feeds lack stale or negative checks, enabling bypass or DoS of transfer limits. Also, minimum transfer amount logic uses `Math.min` incorrectly, effectively disabling limits under some configs. Low-level stable swap call handling risks reverts if unexpected data returned, potentially halting bridging processing. Overall, governance trust assumptions and careful contract call patterns require scrutiny.
thinking
**Evaluating upgradeability, reentrancy, and token swap intricacies**

I'm scrutinizing how receiveRequest handles swap failures and state rollback, confirming internal call reverts revert all changes properly. I notice reentrancy risks in MostL2’s fee handling where raw calls to owner and msg.sender could reenter sendTokenRequest before nonce increments, but increment timing avoids duplicate nonces. Initialization misses __UUPSUpgradeable_init calls but likely not critical. The bridge doesn’t revoke old committees on rotation, so previous members can still act under old IDs, posing governance risks. Token swaps rely on external stablePool calls that must return data correctly or revert. Some token approval patterns don’t reset allowances, though it’s internal use. Handling of native token balances in swap pools may allow accidental ETH trapping. StableSwap contract functions carefully update balances with reentrancy guards. Overall, a mix of upgradeable contract considerations, cross-contract call safety, and state correctness in bridging flows.
thinking
**Analyzing token transfer handling and limit logic**

I'm checking how token transfers use safeTransferFrom after balance updates with reentrancy guards, and how native token transfers rely on adjustable gas limits. I notice the minimumTransferAmount calculation misuses Math.min, likely disabling the USD limit which could let transfers bypass limits. Oracle price validations are lax: zero or negative prices cause unexpected behaviors. Token burn logic assumes wrapped tokens behave as expected, and committee rotations don’t revoke old committees, so prior members retain permissions. There are subtle concerns about low-level calls and approvals without full return checks. Overall, it’s a mix of transfer mechanics, oracle dependency logic, and committee key management that I’m piecing together.
exec
/bin/bash -lc "nl -ba contracts/TransferLimit.sol | sed -n '35,140p'" in /tmp/codex-1ve8blzm succeeded in 8ms:
    35	
    36	    /// @notice Set the default minimum transfer amount for a token - this is used if no USD oracle is set
    37	    /// @param _token The token address
    38	    /// @param _limit The minimum transfer amount
    39	    function setDefaultLimit(address _token, uint256 _limit) public onlyOwner {
    40	        defaultMinima[_token] = _limit;
    41	    }
    42	
    43	    /// @notice Set the USD oracle params for a token
    44	    /// @param _token The token address
    45	    /// @param _tokenDecimals The number of decimals the token has
    46	    /// @param _oracle The Chainlink oracle address
    47	    /// @param _limit The minimum transfer amount in USD with no decimals
    48	    function setUSDOracle(
    49	        address _token,
    50	        uint256 _tokenDecimals,
    51	        AggregatorV3Interface _oracle,
    52	        uint256 _limit
    53	    ) public onlyOwner {
    54	        usdMinima[_token] = USDMinimum({

thinking
**Adding line numbers for debugging**
exec
/bin/bash -lc "nl -ba contracts/AbstractMost.sol | sed -n '40,220p'" in /tmp/codex-1ve8blzm succeeded in 28ms:
    40	
    41	    address public wrappedAzeroAddress;
    42	
    43	    struct Request {
    44	        uint256 signatureCount;
    45	        mapping(address => bool) signatures;
    46	    }
    47	
    48	    event CrosschainTransferRequest(
    49	        uint256 indexed committeeId,
    50	        bytes32 indexed destTokenAddress,
    51	        uint256 amount,
    52	        bytes32 indexed destReceiverAddress,
    53	        uint256 requestNonce
    54	    );
    55	
    56	    event RequestSigned(bytes32 requestHash, address signer);
    57	
    58	    event RequestProcessed(bytes32 requestHash);
    59	

thinking
**Noting missing lines for functions**
exec
/bin/bash -lc "nl -ba contracts/AbstractMost.sol | sed -n '220,420p'" in /tmp/codex-1ve8blzm succeeded in 28ms:
   220	    }
   221	
   222	    function sendRequestAzeroToNative(
   223	        uint256 amount,
   224	        bytes32 destReceiverAddress
   225	    ) external virtual whenNotPaused {
   226	        if (amount == 0) revert ZeroAmount();
   227	        if (destReceiverAddress == bytes32(0)) revert ZeroAddress();
   228	        if (wrappedAzeroAddress == address(0)) revert AzeroAddressNotSet();
   229	
   230	        checkTransferAllowed(wrappedAzeroAddress, amount);
   231	
   232	        IERC20 azeroToken = IERC20(wrappedAzeroAddress);
   233	        azeroToken.safeTransferFrom(msg.sender, address(this), amount);
   234	        IWrappedToken burnableToken = IWrappedToken(wrappedAzeroAddress);
   235	        burnableToken.burn(amount);
   236	
   237	        emit CrosschainTransferRequest(
   238	            committeeId,
   239	            0x0,

thinking
**Reviewing lines for try-catch blocks**
exec
/bin/bash -lc "nl -ba contracts/Most.sol | sed -n '1,140p'" in /tmp/codex-1ve8blzm succeeded in 25ms:
     1	// SPDX-License-Identifier: MIT
     2	
     3	pragma solidity ^0.8.20;
     4	
     5	import {AbstractMost} from "./AbstractMost.sol";
     6	import {ITransferLimit} from "./ITransferLimit.sol";
     7	
     8	/// @title Most
     9	/// @author Cardinal Cryptography
    10	contract Most is AbstractMost {
    11	    ITransferLimit public transferLimit;
    12	
    13	    /// @custom:oz-upgrades-unsafe-allow constructor
    14	    constructor() {
    15	        _disableInitializers();
    16	    }
    17	
    18	    function setTransferLimitContract(
    19	        ITransferLimit _transferLimit
    20	    ) external onlyOwner {

thinking
**Composing detailed security findings and JSON report**

I’m putting together a clear JSON report with three findings: a high-severity access control issue where old committees remain authorized, a medium-severity logic bug allowing USD transfer minima bypass via Math.min, and a medium-severity oracle validation flaw combined with Most’s fail-open behavior enabling transfer limit bypass; I’m including concise summaries, scenarios, recommendations, evidences, and exact code locations.
codex
{"no_findings":false,"summary":"Identified three issues: retired committees retain authority to process requests; transfer limit logic can ignore USD minima; and oracle anomalies can bypass limits due to unchecked prices combined with fail-open handling.","findings":[{"severity":"high","category":"access_control","title":"Retired committee members remain authorized to process requests","exploit_scenario":"After a committee rotation, members of the old committee can still call `receiveRequest` with their historical `_committeeId` and reach the previous `signatureThreshold`. They can mint or release arbitrary amounts by submitting any parameters and signing among themselves, even if governance intended to revoke them.","recommendation":"Enforce that `receiveRequest` only accepts the current `committeeId`, or add an explicit `activeCommitteeId`/revocation mechanism so old committees are disabled once a new committee is set. If you need overlap for in-flight requests, add a bounded grace period.","evidence":"`setCommittee` only increments `committeeId` and adds new members; it never disables old committees. `receiveRequest` accepts any `_committeeId` provided by the caller and only checks membership for that id.","locations":["contracts/AbstractMost.sol:295","contracts/AbstractMost.sol:367"]},{"severity":"medium","category":"other","title":"USD transfer minimum is ignored when default minimum is smaller (often zero)","exploit_scenario":"If `defaultMinima[_token]` is left at the default `0` (or set lower than the USD-based minimum), `minimumTransferAmount` returns the smaller of the two values. This makes the USD oracle limit ineffective, allowing any amount to pass `isRequestAllowed`.","recommendation":"When a USD oracle is configured, use the USD-derived minimum as the floor (e.g., `Math.max(defaultMinima, usdBasedMinimum)`), or if `defaultMinima` is zero, treat it as unset and use the USD value directly.","evidence":"`minimumTransferAmount` computes `usdBasedMinimum` and then uses `Math.min(minimum, usdBasedMinimum)`, which selects the smaller threshold.","locations":["contracts/TransferLimit.sol:62"]},{"severity":"medium","category":"oracle","title":"Oracle anomalies can bypass transfer limits due to unchecked price and fail-open handling","exploit_scenario":"If the oracle returns zero, negative, or stale data, `minimumTransferAmount` can revert (division by zero) or underflow to an extremely large uint cast. `Most.checkTransferAllowed` catches all errors and proceeds as if no limit exists, so an attacker who can manipulate oracle responses can bypass transfer limits entirely.","recommendation":"Validate `usdPrice > 0`, ensure `answeredInRound >= roundId`, and check `updatedAt` freshness before using prices. Consider failing closed (revert) in `Most` when the transfer limit contract errors instead of ignoring failures.","evidence":"`minimumTransferAmount` casts `usdPrice` to `uint256` with no checks and divides by it; `Most.checkTransferAllowed` catches and ignores failures.","locations":["contracts/TransferLimit.sol:68","contracts/Most.sol:41"]}]}
tokens used
54,595
Metadata
{
    "codex": {
        "ran_at": "2026-01-11T07:09:21.909120+00:00",
        "returncode": 0
    },
    "project": {
        "mode": "source",
        "file_count": 43,
        "import_count": 40,
        "first_party_contracts_count": 22
    },
    "summary": "Identified three issues: retired committees retain authority to process requests; transfer limit logic can ignore USD minima; and oracle anomalies can bypass limits due to unchecked prices combined with fail-open handling.",
    "raw_final": {
        "summary": "Identified three issues: retired committees retain authority to process requests; transfer limit logic can ignore USD minima; and oracle anomalies can bypass limits due to unchecked prices combined with fail-open handling.",
        "findings": [
            {
                "title": "Retired committee members remain authorized to process requests",
                "category": "access_control",
                "evidence": "`setCommittee` only increments `committeeId` and adds new members; it never disables old committees. `receiveRequest` accepts any `_committeeId` provided by the caller and only checks membership for that id.",
                "severity": "high",
                "locations": [
                    "contracts/AbstractMost.sol:295",
                    "contracts/AbstractMost.sol:367"
                ],
                "recommendation": "Enforce that `receiveRequest` only accepts the current `committeeId`, or add an explicit `activeCommitteeId`/revocation mechanism so old committees are disabled once a new committee is set. If you need overlap for in-flight requests, add a bounded grace period.",
                "exploit_scenario": "After a committee rotation, members of the old committee can still call `receiveRequest` with their historical `_committeeId` and reach the previous `signatureThreshold`. They can mint or release arbitrary amounts by submitting any parameters and signing among themselves, even if governance intended to revoke them."
            },
            {
                "title": "USD transfer minimum is ignored when default minimum is smaller (often zero)",
                "category": "other",
                "evidence": "`minimumTransferAmount` computes `usdBasedMinimum` and then uses `Math.min(minimum, usdBasedMinimum)`, which selects the smaller threshold.",
                "severity": "medium",
                "locations": [
                    "contracts/TransferLimit.sol:62"
                ],
                "recommendation": "When a USD oracle is configured, use the USD-derived minimum as the floor (e.g., `Math.max(defaultMinima, usdBasedMinimum)`), or if `defaultMinima` is zero, treat it as unset and use the USD value directly.",
                "exploit_scenario": "If `defaultMinima[_token]` is left at the default `0` (or set lower than the USD-based minimum), `minimumTransferAmount` returns the smaller of the two values. This makes the USD oracle limit ineffective, allowing any amount to pass `isRequestAllowed`."
            },
            {
                "title": "Oracle anomalies can bypass transfer limits due to unchecked price and fail-open handling",
                "category": "oracle",
                "evidence": "`minimumTransferAmount` casts `usdPrice` to `uint256` with no checks and divides by it; `Most.checkTransferAllowed` catches and ignores failures.",
                "severity": "medium",
                "locations": [
                    "contracts/TransferLimit.sol:68",
                    "contracts/Most.sol:41"
                ],
                "recommendation": "Validate `usdPrice > 0`, ensure `answeredInRound >= roundId`, and check `updatedAt` freshness before using prices. Consider failing closed (revert) in `Most` when the transfer limit contract errors instead of ignoring failures.",
                "exploit_scenario": "If the oracle returns zero, negative, or stale data, `minimumTransferAmount` can revert (division by zero) or underflow to an extremely large uint cast. `Most.checkTransferAllowed` catches all errors and proceeds as if no limit exists, so an attacker who can manipulate oracle responses can bypass transfer limits entirely."
            }
        ],
        "no_findings": false
    },
    "no_findings": false,
    "proxy_context": {
        "proxy_run_id": "019bab3b-ac5a-722f-b716-e6968b11ca70",
        "proxy_address": "0xf2139f5c8afb8a4d64084efc5532830774742830",
        "implementation_run_id": "019bab3d-f2be-72f8-a06f-15a39da6a9c7",
        "implementation_address": "0x49643fc85fb1f25b6775ebbbdc69295d45105abc"
    },
    "schema_version": 1
}

Opcode Heuristics

tool.cast_disasm
Delegatecall
2
Selfdestruct
0
CREATE2
0
CALL-family (heavy)
0
EXT*/BALANCE
2
Total opcodes
424
Flags
delegatecall_present
View cast disassembly output
00000000: PUSH1 0x80
00000002: PUSH1 0x40
00000004: MSTORE
00000005: CALLDATASIZE
00000006: PUSH2 0x0013
00000009: JUMPI
0000000a: PUSH2 0x0011
0000000d: PUSH2 0x0017
00000010: JUMP
00000011: JUMPDEST
00000012: STOP
00000013: JUMPDEST
00000014: PUSH2 0x0011
00000017: JUMPDEST
00000018: PUSH2 0x0027
0000001b: PUSH2 0x0022
0000001e: PUSH2 0x0067
00000021: JUMP
00000022: JUMPDEST
00000023: PUSH2 0x009f
00000026: JUMP
00000027: JUMPDEST
00000028: JUMP
00000029: JUMPDEST
0000002a: PUSH1 0x60
0000002c: PUSH2 0x004e
0000002f: DUP4
00000030: DUP4
00000031: PUSH1 0x40
00000033: MLOAD
00000034: DUP1
00000035: PUSH1 0x60
00000037: ADD
00000038: PUSH1 0x40
0000003a: MSTORE
0000003b: DUP1
0000003c: PUSH1 0x27
0000003e: DUP2
0000003f: MSTORE
00000040: PUSH1 0x20
00000042: ADD
00000043: PUSH2 0x0268
00000046: PUSH1 0x27
00000048: SWAP2
00000049: CODECOPY
0000004a: PUSH2 0x00c3
0000004d: JUMP
0000004e: JUMPDEST
0000004f: SWAP4
00000050: SWAP3
00000051: POP
00000052: POP
00000053: POP
00000054: JUMP
00000055: JUMPDEST
00000056: PUSH1 0x01
00000058: PUSH1 0x01
0000005a: PUSH1 0xa0
0000005c: SHL
0000005d: SUB
0000005e: AND
0000005f: EXTCODESIZE
00000060: ISZERO
00000061: ISZERO
00000062: SWAP1
00000063: JUMP
00000064: JUMPDEST
00000065: SWAP1
00000066: JUMP
00000067: JUMPDEST
00000068: PUSH1 0x00
0000006a: PUSH2 0x009a
0000006d: PUSH32 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc
0000008e: SLOAD
0000008f: PUSH1 0x01
00000091: PUSH1 0x01
00000093: PUSH1 0xa0
00000095: SHL
00000096: SUB
00000097: AND
00000098: SWAP1
00000099: JUMP
0000009a: JUMPDEST
0000009b: SWAP1
0000009c: POP
0000009d: SWAP1
0000009e: JUMP
0000009f: JUMPDEST
000000a0: CALLDATASIZE
000000a1: PUSH1 0x00
000000a3: DUP1
000000a4: CALLDATACOPY
000000a5: PUSH1 0x00
000000a7: DUP1
000000a8: CALLDATASIZE
000000a9: PUSH1 0x00
000000ab: DUP5
000000ac: GAS
000000ad: DELEGATECALL
000000ae: RETURNDATASIZE
000000af: PUSH1 0x00
000000b1: DUP1
000000b2: RETURNDATACOPY
000000b3: DUP1
000000b4: DUP1
000000b5: ISZERO
000000b6: PUSH2 0x00be
000000b9: JUMPI
000000ba: RETURNDATASIZE
000000bb: PUSH1 0x00
000000bd: RETURN
000000be: JUMPDEST
000000bf: RETURNDATASIZE
000000c0: PUSH1 0x00
000000c2: REVERT
000000c3: JUMPDEST
000000c4: PUSH1 0x60
000000c6: PUSH1 0x00
000000c8: DUP1
000000c9: DUP6
000000ca: PUSH1 0x01
000000cc: PUSH1 0x01
000000ce: PUSH1 0xa0
000000d0: SHL
000000d1: SUB
000000d2: AND
000000d3: DUP6
000000d4: PUSH1 0x40
000000d6: MLOAD
000000d7: PUSH2 0x00e0
000000da: SWAP2
000000db: SWAP1
000000dc: PUSH2 0x0218
000000df: JUMP
000000e0: JUMPDEST
000000e1: PUSH1 0x00
000000e3: PUSH1 0x40
000000e5: MLOAD
000000e6: DUP1
000000e7: DUP4
000000e8: SUB
000000e9: DUP2
000000ea: DUP6
000000eb: GAS
000000ec: DELEGATECALL
000000ed: SWAP2
000000ee: POP
000000ef: POP
000000f0: RETURNDATASIZE
000000f1: DUP1
000000f2: PUSH1 0x00
000000f4: DUP2
000000f5: EQ
000000f6: PUSH2 0x011b
000000f9: JUMPI
000000fa: PUSH1 0x40
000000fc: MLOAD
000000fd: SWAP2
000000fe: POP
000000ff: PUSH1 0x1f
00000101: NOT
00000102: PUSH1 0x3f
00000104: RETURNDATASIZE
00000105: ADD
00000106: AND
00000107: DUP3
00000108: ADD
00000109: PUSH1 0x40
0000010b: MSTORE
0000010c: RETURNDATASIZE
0000010d: DUP3
0000010e: MSTORE
0000010f: RETURNDATASIZE
00000110: PUSH1 0x00
00000112: PUSH1 0x20
00000114: DUP5
00000115: ADD
00000116: RETURNDATACOPY
00000117: PUSH2 0x0120
0000011a: JUMP
0000011b: JUMPDEST
0000011c: PUSH1 0x60
0000011e: SWAP2
0000011f: POP
00000120: JUMPDEST
00000121: POP
00000122: SWAP2
00000123: POP
00000124: SWAP2
00000125: POP
00000126: PUSH2 0x0131
00000129: DUP7
0000012a: DUP4
0000012b: DUP4
0000012c: DUP8
0000012d: PUSH2 0x013b
00000130: JUMP
00000131: JUMPDEST
00000132: SWAP7
00000133: SWAP6
00000134: POP
00000135: POP
00000136: POP
00000137: POP
00000138: POP
00000139: POP
0000013a: JUMP
0000013b: JUMPDEST
0000013c: PUSH1 0x60
0000013e: DUP4
0000013f: ISZERO
00000140: PUSH2 0x01ac
00000143: JUMPI
00000144: DUP3
00000145: MLOAD
00000146: PUSH2 0x01a5
00000149: JUMPI
0000014a: PUSH1 0x01
0000014c: PUSH1 0x01
0000014e: PUSH1 0xa0
00000150: SHL
00000151: SUB
00000152: DUP6
00000153: AND
00000154: EXTCODESIZE
00000155: PUSH2 0x01a5
00000158: JUMPI
00000159: PUSH1 0x40
0000015b: MLOAD
0000015c: PUSH3 0x461bcd
00000160: PUSH1 0xe5
00000162: SHL
00000163: DUP2
00000164: MSTORE
00000165: PUSH1 0x20
00000167: PUSH1 0x04
00000169: DUP3
0000016a: ADD
0000016b: MSTORE
0000016c: PUSH1 0x1d
0000016e: PUSH1 0x24
00000170: DUP3
00000171: ADD
00000172: MSTORE
00000173: PUSH32 0x416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000
00000194: PUSH1 0x44
00000196: DUP3
00000197: ADD
00000198: MSTORE
00000199: PUSH1 0x64
0000019b: ADD
0000019c: JUMPDEST
0000019d: PUSH1 0x40
0000019f: MLOAD
000001a0: DUP1
000001a1: SWAP2
000001a2: SUB
000001a3: SWAP1
000001a4: REVERT
000001a5: JUMPDEST
000001a6: POP
000001a7: DUP2
000001a8: PUSH2 0x01b6
000001ab: JUMP
000001ac: JUMPDEST
000001ad: PUSH2 0x01b6
000001b0: DUP4
000001b1: DUP4
000001b2: PUSH2 0x01be
000001b5: JUMP
000001b6: JUMPDEST
000001b7: SWAP5
000001b8: SWAP4
000001b9: POP
000001ba: POP
000001bb: POP
000001bc: POP
000001bd: JUMP
000001be: JUMPDEST
000001bf: DUP2
000001c0: MLOAD
000001c1: ISZERO
000001c2: PUSH2 0x01ce
000001c5: JUMPI
000001c6: DUP2
000001c7: MLOAD
000001c8: DUP1
000001c9: DUP4
000001ca: PUSH1 0x20
000001cc: ADD
000001cd: REVERT
000001ce: JUMPDEST
000001cf: DUP1
000001d0: PUSH1 0x40
000001d2: MLOAD
000001d3: PUSH3 0x461bcd
000001d7: PUSH1 0xe5
000001d9: SHL
000001da: DUP2
000001db: MSTORE
000001dc: PUSH1 0x04
000001de: ADD
000001df: PUSH2 0x019c
000001e2: SWAP2
000001e3: SWAP1
000001e4: PUSH2 0x0234
000001e7: JUMP
000001e8: JUMPDEST
000001e9: PUSH1 0x00
000001eb: JUMPDEST
000001ec: DUP4
000001ed: DUP2
000001ee: LT
000001ef: ISZERO
000001f0: PUSH2 0x0203
000001f3: JUMPI
000001f4: DUP2
000001f5: DUP2
000001f6: ADD
000001f7: MLOAD
000001f8: DUP4
000001f9: DUP3
000001fa: ADD
000001fb: MSTORE
000001fc: PUSH1 0x20
000001fe: ADD
000001ff: PUSH2 0x01eb
00000202: JUMP
00000203: JUMPDEST
00000204: DUP4
00000205: DUP2
00000206: GT
00000207: ISZERO
00000208: PUSH2 0x0212
0000020b: JUMPI
0000020c: PUSH1 0x00
0000020e: DUP5
0000020f: DUP5
00000210: ADD
00000211: MSTORE
00000212: JUMPDEST
00000213: POP
00000214: POP
00000215: POP
00000216: POP
00000217: JUMP
00000218: JUMPDEST
00000219: PUSH1 0x00
0000021b: DUP3
0000021c: MLOAD
0000021d: PUSH2 0x022a
00000220: DUP2
00000221: DUP5
00000222: PUSH1 0x20
00000224: DUP8
00000225: ADD
00000226: PUSH2 0x01e8
00000229: JUMP
0000022a: JUMPDEST
0000022b: SWAP2
0000022c: SWAP1
0000022d: SWAP2
0000022e: ADD
0000022f: SWAP3
00000230: SWAP2
00000231: POP
00000232: POP
00000233: JUMP
00000234: JUMPDEST
00000235: PUSH1 0x20
00000237: DUP2
00000238: MSTORE
00000239: PUSH1 0x00
0000023b: DUP3
0000023c: MLOAD
0000023d: DUP1
0000023e: PUSH1 0x20
00000240: DUP5
00000241: ADD
00000242: MSTORE
00000243: PUSH2 0x0253
00000246: DUP2
00000247: PUSH1 0x40
00000249: DUP6
0000024a: ADD
0000024b: PUSH1 0x20
0000024d: DUP8
0000024e: ADD
0000024f: PUSH2 0x01e8
00000252: JUMP
00000253: JUMPDEST
00000254: PUSH1 0x1f
00000256: ADD
00000257: PUSH1 0x1f
00000259: NOT
0000025a: AND
0000025b: SWAP2
0000025c: SWAP1
0000025d: SWAP2
0000025e: ADD
0000025f: PUSH1 0x40
00000261: ADD
00000262: SWAP3
00000263: SWAP2
00000264: POP
00000265: POP
00000266: JUMP
00000267: INVALID
00000268: COINBASE
00000269: PUSH5 0x6472657373
0000026f: GASPRICE
00000270: KECCAK256
00000271: PUSH13 0x6f772d6c6576656c2064656c65
0000027f: PUSH8 0x6174652063616c6c
00000288: KECCAK256
00000289: PUSH7 0x61696c6564a264
00000291: PUSH10 0x70667358221220ff8e6f
0000029c: UNKNOWN(0x2D)
0000029d: PUSH23 0x1d58b3bd984933269e01a7ff1f70a460b808056daa4cff
000002b5: CLZ
000002b6: UNKNOWN(0xE8)
000002b7: UNKNOWN(0xAB)
000002b8: PUSH10 0x64736f6c634300080900
000002c3: 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 no no
view
trace_id: 0x4c6d8834092af7bfd2342c0596a1769d1e9ef75df35fe324a06498c0617bbec3
call_targets: 0x49643fc85fb1f25b6775ebbbdc69295d45105abc
target_varies: no
classification: constant_target
validation_json
{
    "sink": "DELEGATECALL",
    "errors": 0,
    "status": "sink_reached",
    "attempts": 1,
    "trace_id": "0x4c6d8834092af7bfd2342c0596a1769d1e9ef75df35fe324a06498c0617bbec3",
    "confirmed": false,
    "trace_mode": "callTracer",
    "call_targets": [
        "0x49643fc85fb1f25b6775ebbbdc69295d45105abc"
    ],
    "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": 173,
            "opcode": "DELEGATECALL",
            "returndata_checked": null,
            "value_expression_category": "n/a",
            "target_expression_category": "computed"
        },
        {
            "pc": 236,
            "opcode": "DELEGATECALL",
            "returndata_checked": null,
            "value_expression_category": "n/a",
            "target_expression_category": "computed"
        }
    ],
    "guards_detected": [],
    "delegatecall_count": 2,
    "untrusted_delegatecall_count": 2
}
high access_control codex Retired committee members remain authorized to process requests 85 no
view
evidence_json
{
    "evidence": "`setCommittee` only increments `committeeId` and adds new members; it never disables old committees. `receiveRequest` accepts any `_committeeId` provided by the caller and only checks membership for that id.",
    "locations": [
        "contracts/AbstractMost.sol:295",
        "contracts/AbstractMost.sol:367"
    ],
    "recommendation": "Enforce that `receiveRequest` only accepts the current `committeeId`, or add an explicit `activeCommitteeId`/revocation mechanism so old committees are disabled once a new committee is set. If you need overlap for in-flight requests, add a bounded grace period.",
    "exploit_scenario": "After a committee rotation, members of the old committee can still call `receiveRequest` with their historical `_committeeId` and reach the previous `signatureThreshold`. They can mint or release arbitrary amounts by submitting any parameters and signing among themselves, even if governance intended to revoke them."
}
medium other codex USD transfer minimum is ignored when default minimum is smaller (often zero) 75 no
view
evidence_json
{
    "evidence": "`minimumTransferAmount` computes `usdBasedMinimum` and then uses `Math.min(minimum, usdBasedMinimum)`, which selects the smaller threshold.",
    "locations": [
        "contracts/TransferLimit.sol:62"
    ],
    "recommendation": "When a USD oracle is configured, use the USD-derived minimum as the floor (e.g., `Math.max(defaultMinima, usdBasedMinimum)`), or if `defaultMinima` is zero, treat it as unset and use the USD value directly.",
    "exploit_scenario": "If `defaultMinima[_token]` is left at the default `0` (or set lower than the USD-based minimum), `minimumTransferAmount` returns the smaller of the two values. This makes the USD oracle limit ineffective, allowing any amount to pass `isRequestAllowed`."
}
medium oracle codex Oracle anomalies can bypass transfer limits due to unchecked price and fail-open handling 75 no
view
evidence_json
{
    "evidence": "`minimumTransferAmount` casts `usdPrice` to `uint256` with no checks and divides by it; `Most.checkTransferAllowed` catches and ignores failures.",
    "locations": [
        "contracts/TransferLimit.sol:68",
        "contracts/Most.sol:41"
    ],
    "recommendation": "Validate `usdPrice > 0`, ensure `answeredInRound >= roundId`, and check `updatedAt` freshness before using prices. Consider failing closed (revert) in `Most` when the transfer limit contract errors instead of ignoring failures.",
    "exploit_scenario": "If the oracle returns zero, negative, or stale data, `minimumTransferAmount` can revert (division by zero) or underflow to an extremely large uint cast. `Most.checkTransferAllowed` catches all errors and proceeds as if no limit exists, so an attacker who can manipulate oracle responses can bypass transfer limits entirely."
}
medium upgradeability cast DELEGATECALL present 80 no
view
evidence_json
{
    "notes": "delegatecall enables execution in caller context; common in proxies/upgradeable patterns",
    "delegatecall_count": 2
}