019c0ea9-0976-7128-8854-e104b5d873b5
Open this run to answer one question: is this real attacker-relevant behavior with real impact, or just normal contract plumbing?
| ID | Type | Status | Attempts | Heartbeat |
|---|---|---|---|---|
| 42082 | artifact.fetch | complete | 1 / 3 | 2 months ago |
| 42083 | proxy.resolve | complete | 1 / 3 | 2 months ago |
| 42084 | tool.cast_disasm | complete | 1 / 3 | 2 months ago |
| 42085 | analysis.bundle | complete | 1 / 3 | 2 months ago |
| 42086 | capability.graph | complete | 1 / 3 | 2 months ago |
| 42087 | detector.run | complete | 1 / 3 | 2 months ago |
| 42088 | validation.fork | complete | 1 / 3 | 2 months ago |
| 42448 | report.consolidate | complete | 1 / 6 | 2 months ago |
| 42449 | tool.slither | failed | 2 / 2 | 2 months ago |
{
"method": "etherscan+onchain",
"status": "confirmed",
"etherscan_hint": {
"source": "etherscan",
"etherscan": {
"proxy_flag": true,
"implementation": "0x4a1dc57d949db46a456d0104f437ed87ee24422f"
}
},
"implementation": "0x4a1dc57d949db46a456d0104f437ed87ee24422f",
"onchain_method": "eip1967"
}
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-0bvblhdr)
'forge config --json' running
'forge build --build-info --skip ./test/** ./script/** --force' running (wd: /tmp/slither-0bvblhdr)
'forge' returned non-zero exit code 1
[2m2026-01-30T16:57:28.666045Z[0m [31mERROR[0m [2mfoundry_compilers_artifacts_solc::sources[0m[2m:[0m [3merror[0m[2m=[0m"/tmp/slither-0bvblhdr/lib/openzeppelin-contracts/contracts/token/ERC20/SafeERC20.sol": No such file or directory (os error 2)
stdout: [2m2026-01-30T16:57:28.666193Z[0m [31mERROR[0m [2mfoundry_compilers_artifacts_solc::sources[0m[2m:[0m [3merror[0m[2m=[0m"/tmp/slither-0bvblhdr/lib/openzeppelin-contracts/contracts/proxy/ProxyAdmin.sol": No such file or directory (os error 2)
stdout: [2m2026-01-30T16:57:28.666250Z[0m [31mERROR[0m [2mfoundry_compilers_artifacts_solc::sources[0m[2m:[0m [3merror[0m[2m=[0m"/tmp/slither-0bvblhdr/lib/openzeppelin-contracts/contracts/token/ERC20/SafeERC20.sol": No such file or directory (os error 2)
stdout: [2m2026-01-30T16:57:28.666289Z[0m [31mERROR[0m [2mfoundry_compilers_artifacts_solc::sources[0m[2m:[0m [3merror[0m[2m=[0m"/tmp/slither-0bvblhdr/lib/openzeppelin-contracts/contracts/math/SafeMath.sol": No such file or directory (os error 2)
stdout: [2m2026-01-30T16:57:28.666340Z[0m [31mERROR[0m [2mfoundry_compilers_artifacts_solc::sources[0m[2m:[0m [3merror[0m[2m=[0m"/tmp/slither-0bvblhdr/lib/openzeppelin-contracts/contracts/token/ERC20/SafeERC20.sol": No such file or directory (os error 2)
stdout: [2m2026-01-30T16:57:28.666372Z[0m [31mERROR[0m [2mfoundry_compilers_artifacts_solc::sources[0m[2m:[0m [3merror[0m[2m=[0m"/tmp/slither-0bvblhdr/lib/openzeppelin-contracts/contracts/math/SafeMath.sol": No such file or directory (os error 2)
stdout: [2m2026-01-30T16:57:28.666396Z[0m [31mERROR[0m [2mfoundry_compilers_artifacts_solc::sources[0m[2m:[0m [3merror[0m[2m=[0m"/tmp/slither-0bvblhdr/lib/openzeppelin-contracts/contracts/math/SafeMath.sol": No such file or directory (os error 2)
stdout: [2m2026-01-30T16:57:28.666425Z[0m [31mERROR[0m [2mfoundry_compilers_artifacts_solc::sources[0m[2m:[0m [3merror[0m[2m=[0m"/tmp/slither-0bvblhdr/lib/openzeppelin-contracts/contracts/math/SafeMath.sol": No such file or directory (os error 2)
stdout: [2m2026-01-30T16:57:28.666463Z[0m [31mERROR[0m [2mfoundry_compilers_artifacts_solc::sources[0m[2m:[0m [3merror[0m[2m=[0m"/tmp/slither-0bvblhdr/lib/openzeppelin-contracts/contracts/presets/ERC20PresetMinterPauser.sol": No such file or directory (os error 2)
stdout: [2m2026-01-30T16:57:28.666478Z[0m [31mERROR[0m [2mfoundry_compilers_artifacts_solc::sources[0m[2m:[0m [3merror[0m[2m=[0m"/tmp/slither-0bvblhdr/lib/openzeppelin-contracts/contracts/presets/ERC20PresetMinterPauser.sol": No such file or directory (os error 2)
stdout: Unable to resolve imports:
stdout: "@openzeppelin/contracts/math/SafeMath.sol" in "/tmp/slither-0bvblhdr/contracts/swapper/uniswap/MockRouter.sol"
stdout: "@openzeppelin/contracts/token/ERC20/SafeERC20.sol" in "/tmp/slither-0bvblhdr/contracts/SwapSettlement.sol"
stdout: "@openzeppelin/contracts/presets/ERC20PresetMinterPauser.sol" in "/tmp/slither-0bvblhdr/contracts/testing/TokenB.sol"
stdout: "@openzeppelin/contracts/token/ERC20/SafeERC20.sol" in "/tmp/slither-0bvblhdr/contracts/swapper/uniswap/MockPair.sol"
stdout: "@openzeppelin/contracts/presets/ERC20PresetMinterPauser.sol" in "/tmp/slither-0bvblhdr/contracts/testing/TokenA.sol"
stdout: "@openzeppelin/contracts/proxy/ProxyAdmin.sol" in "/tmp/slither-0bvblhdr/contracts/deployment/DeploymentAdmin.sol"
stdout: "@openzeppelin/contracts/math/SafeMath.sol" in "/tmp/slither-0bvblhdr/contracts/libs/LibGas.sol"
stdout: "@openzeppelin/contracts/math/SafeMath.sol" in "/tmp/slither-0bvblhdr/contracts/swapper/uniswap/MockPair.sol"
stdout: "@openzeppelin/contracts/math/SafeMath.sol" in "/tmp/slither-0bvblhdr/contracts/swapper/uniswap/Uniswapper.sol"
stdout: "@openzeppelin/contracts/token/ERC20/SafeERC20.sol" in "/tmp/slither-0bvblhdr/contracts/libs/LibGas.sol"
stdout: with remappings:
stdout: openzeppelin-contracts/=/tmp/slither-0bvblhdr/lib/openzeppelin-contracts/
stdout: @openzeppelin/contracts/=/tmp/slither-0bvblhdr/lib/openzeppelin-contracts/contracts/
stdout: Compiling 23 files with Solc 0.6.8
stdout: Solc 0.6.8 finished in 12.48ms
Error: Compiler run failed:
stderr: Error: Source "lib/openzeppelin-contracts/contracts/token/ERC20/SafeERC20.sol" not found: File not found.
stderr: contracts/SwapSettlement.sol:7:1: ParserError: Source "lib/openzeppelin-contracts/contracts/token/ERC20/SafeERC20.sol" not found: File not found.
stderr: import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
stderr: ^---------------------------------------------------------^
stderr: Error: Source "lib/openzeppelin-contracts/contracts/proxy/ProxyAdmin.sol" not found: File not found.
stderr: contracts/deployment/DeploymentAdmin.sol:4:1: ParserError: Source "lib/openzeppelin-contracts/contracts/proxy/ProxyAdmin.sol" not found: File not found.
stderr: import "@openzeppelin/contracts/proxy/ProxyAdmin.sol";
stderr: ^----------------------------------------------------^
stderr: Error: Source "lib/openzeppelin-contracts/contracts/token/ERC20/SafeERC20.sol" not found: File not found.
stderr: contracts/libs/LibGas.sol:5:1: ParserError: Source "lib/openzeppelin-contracts/contracts/token/ERC20/SafeERC20.sol" not found: File not found.
stderr: import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
stderr: ^---------------------------------------------------------^
stderr: Error: Source "lib/openzeppelin-contracts/contracts/math/SafeMath.sol" not found: File not found.
stderr: contracts/libs/LibGas.sol:6:1: ParserError: Source "lib/openzeppelin-contracts/contracts/math/SafeMath.sol" not found: File not found.
stderr: import "@openzeppelin/contracts/math/SafeMath.sol";
stderr: ^-------------------------------------------------^
stderr: Error: Source "lib/openzeppelin-contracts/contracts/token/ERC20/SafeERC20.sol" not found: File not found.
stderr: contracts/swapper/uniswap/MockPair.sol:5:1: ParserError: Source "lib/openzeppelin-contracts/contracts/token/ERC20/SafeERC20.sol" not found: File not found.
stderr: import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
stderr: ^---------------------------------------------------------^
stderr: Error: Source "lib/openzeppelin-contracts/contracts/math/SafeMath.sol" not found: File not found.
stderr: contracts/swapper/uniswap/MockPair.sol:6:1: ParserError: Source "lib/openzeppelin-contracts/contracts/math/SafeMath.sol" not found: File not found.
stderr: import "@openzeppelin/contracts/math/SafeMath.sol";
stderr: ^-------------------------------------------------^
stderr: Error: Source "lib/openzeppelin-contracts/contracts/math/SafeMath.sol" not found: File not found.
stderr: contracts/swapper/uniswap/MockRouter.sol:4:1: ParserError: Source "lib/openzeppelin-contracts/contracts/math/SafeMath.sol" not found: File not found.
stderr: import "@openzeppelin/contracts/math/SafeMath.sol";
stderr: ^-------------------------------------------------^
stderr: Error: Source "lib/openzeppelin-contracts/contracts/math/SafeMath.sol" not found: File not found.
stderr: contracts/swapper/uniswap/Uniswapper.sol:6:1: ParserError: Source "lib/openzeppelin-contracts/contracts/math/SafeMath.sol" not found: File not found.
stderr: import "@openzeppelin/contracts/math/SafeMath.sol";
stderr: ^-------------------------------------------------^
stderr: Error: Source "lib/openzeppelin-contracts/contracts/presets/ERC20PresetMinterPauser.sol" not found: File not found.
stderr: contracts/testing/TokenA.sol:4:1: ParserError: Source "lib/openzeppelin-contracts/contracts/presets/ERC20PresetMinterPauser.sol" not found: File not found.
stderr: import "@openzeppelin/contracts/presets/ERC20PresetMinterPauser.sol";
stderr: ^-------------------------------------------------------------------^
stderr: Error: Source "lib/openzeppelin-contracts/contracts/presets/ERC20PresetMinterPauser.sol" not found: File not found.
stderr: contracts/testing/TokenB.sol:4:1: ParserError: Source "lib/openzeppelin-contracts/contracts/presets/ERC20PresetMinterPauser.sol" not found: File not found.
stderr: import "@openzeppelin/contracts/presets/ERC20PresetMinterPauser.sol";
stderr: ^-------------------------------------------------------------------^
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-0bvblhdr/out/build-info is not a directory.
{"no_findings":false,"summary":"Found two issues: relays can execute unapproved orders/penalties because orders are unauthenticated, and ERC20 return values are unchecked in Uniswapper leading to silent transfer failures/refund loss with non‑standard tokens.","findings":[{"severity":"high","category":"auth","title":"Orders are unauthenticated, allowing relays to execute arbitrary trades or penalties against any trader","exploit_scenario":"A compromised or malicious RELAY_ROLE calls fill() with order.trader set to a victim who has deposited gas. Because the order is not signed or nonce‑checked, the relay can (a) trigger _penalize by passing an unapproved script or invalid order, draining the victim’s gas balance, or (b) execute an arbitrary swap using the victim’s token allowance to trade at unfavorable rates without the victim’s consent.","recommendation":"Introduce EIP‑712 signed orders with per‑trader nonces/cancellation, and require signature verification in fill(). Enforce gasAllowance/minFee constraints and validate that the order was authored by the trader before performing swaps or penalties.","evidence":"fill() only requires onlyRelay and does not verify any signature/nonce, while Types.Order carries no signature fields.","locations":["contracts/SwapSettlement.sol:95","contracts/SwapSettlement.sol:103","contracts/Types.sol:33"]},{"severity":"low","category":"other","title":"Unchecked ERC20 return values can silently fail transfers and strand/refund tokens in Uniswapper","exploit_scenario":"For ERC20s that return false on transfer (without reverting), _exactOut will proceed even if the refund transfer fails. The swap is considered successful by SwapSettlement, but the unused input tokens remain in Uniswapper, causing traders to lose funds or leaving recoverable balances in the script contract.","recommendation":"Use SafeERC20 (safeTransfer/safeTransferFrom) and check return values for all token transfers, including refunds. Consider reverting on failed refunds to avoid silent loss or implement a recovery mechanism.","evidence":"Token transfers in _exactIn/_exactOut and the refund path ignore the boolean return value.","locations":["contracts/swapper/uniswap/Uniswapper.sol:92","contracts/swapper/uniswap/Uniswapper.sol:152","contracts/swapper/uniswap/Uniswapper.sol:183"]}]}
OpenAI Codex v0.77.0 (research preview)
--------
workdir: /tmp/codex-2ebmgfmx
model: gpt-5.2-codex
provider: openai
approval: never
sandbox: read-only
reasoning effort: high
reasoning summaries: auto
session id: 019c0f7b-1939-78b3-af20-4a395c84f5ac
--------
user
Context: The user requested the proxy at 0xfca6a62a11cd75ef6506c4973a67c5b2a3d8915f.
Audit the implementation at 0x4a1dc57d949db46a456d0104f437ed87ee24422f.
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
exec
/bin/bash -lc ls in /tmp/codex-2ebmgfmx succeeded in 8ms:
AUDIT_BUNDLE.txt
codex-output-schema.json
contracts
@nomiclabs
@openzeppelin
exec
/bin/bash -lc 'cat AUDIT_BUNDLE.txt' in /tmp/codex-2ebmgfmx 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: @nomiclabs/buidler/console.sol
================================================================================
// SPDX-License-Identifier: MIT
pragma solidity >= 0.4.22 <0.8.0;
library console {
address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);
function _sendLogPayload(bytes memory payload) private view {
uint256 payloadLength = payload.length;
address consoleAddress = CONSOLE_ADDRESS;
assembly {
let payloadStart := add(payload, 32)
let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)
}
}
exec
/bin/bash -lc 'rg --files contracts' in /tmp/codex-2ebmgfmx succeeded in 14ms:
contracts/SwapSettlement.sol
contracts/GasTank.sol
contracts/testing/TokenA.sol
contracts/testing/TokenB.sol
contracts/libs/LibConfig.sol
contracts/libs/LibStorage.sol
contracts/libs/LibGas.sol
contracts/libs/LibAccess.sol
contracts/Types.sol
contracts/interfaces/ISwapAction.sol
contracts/swapper/uniswapRouting/RoutedSwap.sol
contracts/BaseAccess.sol
contracts/BaseConfig.sol
contracts/interfaces/uniswap/IV2Router.sol
contracts/interfaces/uniswap/IPairFactory.sol
contracts/interfaces/uniswap/IPair.sol
contracts/swapper/uniswap/Uniswapper.sol
contracts/deployment/DeploymentAdmin.sol
exec
/bin/bash -lc "sed -n '1,200p' contracts/SwapSettlement.sol" in /tmp/codex-2ebmgfmx succeeded in 7ms:
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.6.8;
pragma experimental ABIEncoderV2;
import "./GasTank.sol";
import "./Types.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "./interfaces/ISwapAction.sol";
contract SwapSettlement is GasTank {
using SafeMath for uint256;
using SafeMath for uint112;
using SafeMath for uint128;
using SafeMath for uint;
using SafeERC20 for IERC20;
//============= EVENT DEFS =================/
event TraderPenalized(address indexed trader, uint256 penalty, uint256 gasPaid, string reason);
event SwapFailed(address indexed trader, uint gasPaid, string reason);
exec
/bin/bash -lc "sed -n '200,400p' contracts/SwapSettlement.sol" in /tmp/codex-2ebmgfmx succeeded in 6ms:
require(tracking.actualOut.sub(tracking.outBal) >= order.output.amount, "Swap action did not transfer output tokens to trader");
require(tracking.afterIn < tracking.inBal, "Input tokens not used!");
require(tracking.inBal.sub(tracking.afterIn) <= order.input.amount, "Used too many input tokens");
//otherwise, pay fee and gas
uint256 totalGasUsed = startGas.sub(gasleft()).add(GAS_OVERHEAD);
uint256 gasFee = totalGasUsed.mul(tx.gasprice);
//console.log("Gas fee", gasFee);
deduct(order.trader, uint112(gasFee.add(order.fee)));
_msgSender().transfer(gasFee);
payable(LibStorage.getConfigStorage().devTeam).transfer(order.fee);
emit SwapSuccess(order.trader,
_msgSender(),
tracking.inBal.sub(tracking.afterIn),
tracking.actualOut.sub(tracking.outBal),
order.fee,
gasFee);
}
}
exec
/bin/bash -lc "sed -n '1,240p' contracts/GasTank.sol" in /tmp/codex-2ebmgfmx succeeded in 6ms:
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.6.8;
pragma experimental ABIEncoderV2;
import "./BaseConfig.sol";
import "./libs/LibGas.sol";
abstract contract GasTank is BaseConfig {
using LibGas for Types.GasBalances;
//========== VIEWS =============/
function availableGasForWithdraw(address owner) external view returns (uint256) {
return LibStorage.getGasStorage().availableForWithdraw(owner);
}
function totalGasDeposited(address owner) external view returns (uint256) {
return LibStorage.getGasStorage().total(owner);
}
function totalGasLocked(address owner) external view returns (uint256) {
exec
/bin/bash -lc "sed -n '1,240p' contracts/BaseAccess.sol" in /tmp/codex-2ebmgfmx succeeded in 6ms:
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.6.8;
import "./libs/LibAccess.sol";
import "./libs/LibStorage.sol";
import "./Types.sol";
import "@nomiclabs/buidler/console.sol";
abstract contract BaseAccess {
using LibAccess for Types.AccessControl;
//bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");
bytes32 public constant ADMIN_ROLE = 0xa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775;
//bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
bytes32 public constant PAUSER_ROLE = 0x65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a;
//bytes32 public constant RELAY_ROLE = keccak256("RELAY_ROLE");
bytes32 public constant RELAY_ROLE = 0x077a1d526a4ce8a773632ab13b4fbbf1fcc954c3dab26cd27ea0e2a6750da5d7;
//bytes32 public constant ACTION_ROLE = keccak256("ACTION_ROLE");
exec
/bin/bash -lc "sed -n '1,260p' contracts/BaseConfig.sol" in /tmp/codex-2ebmgfmx succeeded in 9ms:
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.6.8;
pragma experimental ABIEncoderV2;
import "./Types.sol";
import "./libs/LibStorage.sol";
import "./libs/LibConfig.sol";
import "./BaseAccess.sol";
abstract contract BaseConfig is BaseAccess {
using LibConfig for Types.Config;
function initConfig(Types.Config memory config) internal {
LibStorage.getConfigStorage().store(config);
BaseAccess.initAccess();
}
function getConfig() external view returns (Types.Config memory) {
return LibStorage.getConfigStorage().copy();
}
exec
/bin/bash -lc "sed -n '1,260p' contracts/libs/LibAccess.sol" in /tmp/codex-2ebmgfmx succeeded in 7ms:
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.6.8;
import "../Types.sol";
library LibAccess {
function hasRole(Types.AccessControl storage ac, bytes32 role, address actor) external view returns (bool) {
return ac.roles[role][actor];
}
function _addRole(Types.AccessControl storage ac, bytes32 role, address actor) internal {
ac.roles[role][actor] = true;
}
function _revokeRole(Types.AccessControl storage ac, bytes32 role, address actor) internal {
delete ac.roles[role][actor];
}
}
exec
/bin/bash -lc "sed -n '1,240p' contracts/Types.sol" in /tmp/codex-2ebmgfmx succeeded in 6ms:
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.6.8;
pragma experimental ABIEncoderV2;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
library Types {
struct TokenAmount {
IERC20 token;
uint112 amount;
}
struct GasAllowance {
uint112 maxGas;
uint8 percentGasPaid;
}
enum OrderType {
EXACT_IN,
exec
/bin/bash -lc "sed -n '1,240p' contracts/deployment/DeploymentAdmin.sol" in /tmp/codex-2ebmgfmx succeeded in 6ms:
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.6.8;
import "@openzeppelin/contracts/proxy/ProxyAdmin.sol";
contract DeploymentAdmin is ProxyAdmin {
}
exec
/bin/bash -lc "sed -n '1,240p' contracts/libs/LibConfig.sol" in /tmp/codex-2ebmgfmx succeeded in 11ms:
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.6.8;
pragma experimental ABIEncoderV2;
import "../Types.sol";
library LibConfig {
function store(Types.Config storage cs, Types.Config memory config) public {
cs.devTeam = config.devTeam;
cs.minFee = config.minFee;
cs.penaltyFee = config.penaltyFee;
cs.lockoutBlocks = config.lockoutBlocks;
require(cs.devTeam != address(0), "Invalid dev team address");
}
function copy(Types.Config storage config) public view returns(Types.Config memory) {
Types.Config memory cs;
cs.devTeam = config.devTeam;
cs.minFee = config.minFee;
exec
/bin/bash -lc "sed -n '1,200p' contracts/interfaces/ISwapAction.sol" in /tmp/codex-2ebmgfmx succeeded in 13ms:
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.6.8;
pragma experimental ABIEncoderV2;
import "../Types.sol";
interface ISwapAction {
// @dev perform a swap according to the order details. Returns a bool indicating
// success and a string fail reason.
function swap(Types.Order calldata order, bytes calldata data) external returns (bool, string memory failReason);
}
exec
/bin/bash -lc 'rg "minFee|penaltyFee|gasAllowance" -n contracts' in /tmp/codex-2ebmgfmx succeeded in 13ms:
contracts/SwapSettlement.sol:69: uint256 total = gas.add(order.fee).add(LibStorage.getConfigStorage().penaltyFee);
contracts/SwapSettlement.sol:233: uint128 fee = LibStorage.getConfigStorage().penaltyFee;
contracts/Types.sol:41: GasAllowance gasAllowance;
contracts/Types.sol:67: uint128 minFee;
contracts/Types.sol:71: uint128 penaltyFee;
contracts/libs/LibConfig.sol:11: cs.minFee = config.minFee;
contracts/libs/LibConfig.sol:12: cs.penaltyFee = config.penaltyFee;
contracts/libs/LibConfig.sol:20: cs.minFee = config.minFee;
contracts/libs/LibConfig.sol:21: cs.penaltyFee = config.penaltyFee;
exec
/bin/bash -lc "rg \"hasEnough\\(\" -n contracts" in /tmp/codex-2ebmgfmx succeeded in 23ms:
contracts/libs/LibGas.sol:64: function hasEnough(Types.GasBalances storage gs, address account, uint256 estimateUse, uint112 price) internal view returns (bool) {
exec
/bin/bash -lc "nl -ba contracts/SwapSettlement.sol | sed -n '80,170p'" in /tmp/codex-2ebmgfmx succeeded in 7ms:
80 return b;
81 }
82
83 // @dev whether the trader has approved this contract to spend enought for order
84 function _canSpend(Types.Order memory order) internal view returns (bool) {
85 bool b = order.input.token.allowance(order.trader, address(this)) >= order.input.amount;
86 //console.log("Can spend tokens", b);
87 return b;
88 }
89
90
91
92 //=============== MUTATIONS ==================/
93
94 // @dev fill an order using the given script and calldata.
95 function fill(
96 Types.Order memory order,
97 ISwapAction script,
98 bytes memory data) public onlyRelay nonReentrant {
99
exec
/bin/bash -lc "nl -ba contracts/Types.sol | sed -n '20,120p'" in /tmp/codex-2ebmgfmx succeeded in 8ms:
20 EXACT_IN,
21 EXACT_OUT
22 }
23
24 //status of order. Only tracked on action from user/miners
25 enum OrderStatus {
26 UNDEFINED,
27 PENDING,
28 FILLED,
29 CANCELLED,
30 PENALIZED
31 }
32
33 struct Order {
34 //trader that owns the order
35 address trader;
36
37 //fee offered (120+128 = 248)
38 uint128 fee;
39
exec
/bin/bash -lc "nl -ba contracts/swapper/uniswap/Uniswapper.sol | sed -n '80,200p'" in /tmp/codex-2ebmgfmx succeeded in 10ms:
80 if(order.input.token.balanceOf(address(this)) < order.input.amount) {
81 return (false, "Input funds not transferred to swap");
82 }
83
84 //console.log("Amount out", amount);
85 //console.log("Expected output", order.output.amount);
86 (uint amount, IPair pair) = _getOutputQuote(order);
87 if(amount < order.output.amount) {
88 return (false,'Excessive output required');
89 }
90 bool success = false;
91 string memory failReason = "";
92 try order.input.token.transfer{
93 gas: gasleft()
94 }(address(pair), order.input.amount){
95 success = true;
96 } catch Error(string memory err) {
97 success = false;
98 failReason = err;
99 } catch {
codex
{"no_findings":false,"summary":"Found two issues: relays can execute unapproved orders/penalties because orders are unauthenticated, and ERC20 return values are unchecked in Uniswapper leading to silent transfer failures/refund loss with non‑standard tokens.","findings":[{"severity":"high","category":"auth","title":"Orders are unauthenticated, allowing relays to execute arbitrary trades or penalties against any trader","exploit_scenario":"A compromised or malicious RELAY_ROLE calls fill() with order.trader set to a victim who has deposited gas. Because the order is not signed or nonce‑checked, the relay can (a) trigger _penalize by passing an unapproved script or invalid order, draining the victim’s gas balance, or (b) execute an arbitrary swap using the victim’s token allowance to trade at unfavorable rates without the victim’s consent.","recommendation":"Introduce EIP‑712 signed orders with per‑trader nonces/cancellation, and require signature verification in fill(). Enforce gasAllowance/minFee constraints and validate that the order was authored by the trader before performing swaps or penalties.","evidence":"fill() only requires onlyRelay and does not verify any signature/nonce, while Types.Order carries no signature fields.","locations":["contracts/SwapSettlement.sol:95","contracts/SwapSettlement.sol:103","contracts/Types.sol:33"]},{"severity":"low","category":"other","title":"Unchecked ERC20 return values can silently fail transfers and strand/refund tokens in Uniswapper","exploit_scenario":"For ERC20s that return false on transfer (without reverting), _exactOut will proceed even if the refund transfer fails. The swap is considered successful by SwapSettlement, but the unused input tokens remain in Uniswapper, causing traders to lose funds or leaving recoverable balances in the script contract.","recommendation":"Use SafeERC20 (safeTransfer/safeTransferFrom) and check return values for all token transfers, including refunds. Consider reverting on failed refunds to avoid silent loss or implement a recovery mechanism.","evidence":"Token transfers in _exactIn/_exactOut and the refund path ignore the boolean return value.","locations":["contracts/swapper/uniswap/Uniswapper.sol:92","contracts/swapper/uniswap/Uniswapper.sol:152","contracts/swapper/uniswap/Uniswapper.sol:183"]}]}
tokens used
47,359
{
"codex": {
"ran_at": "2026-01-30T15:23:25.473509+00:00",
"returncode": 0
},
"project": {
"mode": "source",
"file_count": 36,
"import_count": 40,
"first_party_contracts_count": 19
},
"summary": "Found two issues: relays can execute unapproved orders/penalties because orders are unauthenticated, and ERC20 return values are unchecked in Uniswapper leading to silent transfer failures/refund loss with non\u2011standard tokens.",
"raw_final": {
"summary": "Found two issues: relays can execute unapproved orders/penalties because orders are unauthenticated, and ERC20 return values are unchecked in Uniswapper leading to silent transfer failures/refund loss with non\u2011standard tokens.",
"findings": [
{
"title": "Orders are unauthenticated, allowing relays to execute arbitrary trades or penalties against any trader",
"category": "auth",
"evidence": "fill() only requires onlyRelay and does not verify any signature/nonce, while Types.Order carries no signature fields.",
"severity": "high",
"locations": [
"contracts/SwapSettlement.sol:95",
"contracts/SwapSettlement.sol:103",
"contracts/Types.sol:33"
],
"recommendation": "Introduce EIP\u2011712 signed orders with per\u2011trader nonces/cancellation, and require signature verification in fill(). Enforce gasAllowance/minFee constraints and validate that the order was authored by the trader before performing swaps or penalties.",
"exploit_scenario": "A compromised or malicious RELAY_ROLE calls fill() with order.trader set to a victim who has deposited gas. Because the order is not signed or nonce\u2011checked, the relay can (a) trigger _penalize by passing an unapproved script or invalid order, draining the victim\u2019s gas balance, or (b) execute an arbitrary swap using the victim\u2019s token allowance to trade at unfavorable rates without the victim\u2019s consent."
},
{
"title": "Unchecked ERC20 return values can silently fail transfers and strand/refund tokens in Uniswapper",
"category": "other",
"evidence": "Token transfers in _exactIn/_exactOut and the refund path ignore the boolean return value.",
"severity": "low",
"locations": [
"contracts/swapper/uniswap/Uniswapper.sol:92",
"contracts/swapper/uniswap/Uniswapper.sol:152",
"contracts/swapper/uniswap/Uniswapper.sol:183"
],
"recommendation": "Use SafeERC20 (safeTransfer/safeTransferFrom) and check return values for all token transfers, including refunds. Consider reverting on failed refunds to avoid silent loss or implement a recovery mechanism.",
"exploit_scenario": "For ERC20s that return false on transfer (without reverting), _exactOut will proceed even if the refund transfer fails. The swap is considered successful by SwapSettlement, but the unused input tokens remain in Uniswapper, causing traders to lose funds or leaving recoverable balances in the script contract."
}
],
"no_findings": false
},
"no_findings": false,
"proxy_context": {
"proxy_run_id": "019c0ea9-0976-7128-8854-e104b5d873b5",
"proxy_address": "0xfca6a62a11cd75ef6506c4973a67c5b2a3d8915f",
"implementation_run_id": "019c0eab-c14a-7068-a5b7-e9885803d0b8",
"implementation_address": "0x4a1dc57d949db46a456d0104f437ed87ee24422f"
},
"schema_version": 1
}
00000000: PUSH1 0x80 00000002: PUSH1 0x40 00000004: MSTORE 00000005: PUSH1 0x04 00000007: CALLDATASIZE 00000008: LT 00000009: PUSH2 0x004e 0000000c: JUMPI 0000000d: PUSH1 0x00 0000000f: CALLDATALOAD 00000010: PUSH1 0xe0 00000012: SHR 00000013: DUP1 00000014: PUSH4 0x3659cfe6 00000019: EQ 0000001a: PUSH2 0x0065 0000001d: JUMPI 0000001e: DUP1 0000001f: PUSH4 0x4f1ef286 00000024: EQ 00000025: PUSH2 0x0098 00000028: JUMPI 00000029: DUP1 0000002a: PUSH4 0x5c60da1b 0000002f: EQ 00000030: PUSH2 0x0118 00000033: JUMPI 00000034: DUP1 00000035: PUSH4 0x8f283970 0000003a: EQ 0000003b: PUSH2 0x0149 0000003e: JUMPI 0000003f: DUP1 00000040: PUSH4 0xf851a440 00000045: EQ 00000046: PUSH2 0x017c 00000049: JUMPI 0000004a: PUSH2 0x005d 0000004d: JUMP 0000004e: JUMPDEST 0000004f: CALLDATASIZE 00000050: PUSH2 0x005d 00000053: JUMPI 00000054: PUSH2 0x005b 00000057: PUSH2 0x0191 0000005a: JUMP 0000005b: JUMPDEST 0000005c: STOP 0000005d: JUMPDEST 0000005e: PUSH2 0x005b 00000061: PUSH2 0x0191 00000064: JUMP 00000065: JUMPDEST 00000066: CALLVALUE 00000067: DUP1 00000068: ISZERO 00000069: PUSH2 0x0071 0000006c: JUMPI 0000006d: PUSH1 0x00 0000006f: DUP1 00000070: REVERT 00000071: JUMPDEST 00000072: POP 00000073: PUSH2 0x005b 00000076: PUSH1 0x04 00000078: DUP1 00000079: CALLDATASIZE 0000007a: SUB 0000007b: PUSH1 0x20 0000007d: DUP2 0000007e: LT 0000007f: ISZERO 00000080: PUSH2 0x0088 00000083: JUMPI 00000084: PUSH1 0x00 00000086: DUP1 00000087: REVERT 00000088: JUMPDEST 00000089: POP 0000008a: CALLDATALOAD 0000008b: PUSH1 0x01 0000008d: PUSH1 0x01 0000008f: PUSH1 0xa0 00000091: SHL 00000092: SUB 00000093: AND 00000094: PUSH2 0x01ab 00000097: JUMP 00000098: JUMPDEST 00000099: PUSH2 0x005b 0000009c: PUSH1 0x04 0000009e: DUP1 0000009f: CALLDATASIZE 000000a0: SUB 000000a1: PUSH1 0x40 000000a3: DUP2 000000a4: LT 000000a5: ISZERO 000000a6: PUSH2 0x00ae 000000a9: JUMPI 000000aa: PUSH1 0x00 000000ac: DUP1 000000ad: REVERT 000000ae: JUMPDEST 000000af: PUSH1 0x01 000000b1: PUSH1 0x01 000000b3: PUSH1 0xa0 000000b5: SHL 000000b6: SUB 000000b7: DUP3 000000b8: CALLDATALOAD 000000b9: AND 000000ba: SWAP2 000000bb: SWAP1 000000bc: DUP2 000000bd: ADD 000000be: SWAP1 000000bf: PUSH1 0x40 000000c1: DUP2 000000c2: ADD 000000c3: PUSH1 0x20 000000c5: DUP3 000000c6: ADD 000000c7: CALLDATALOAD 000000c8: PUSH5 0x0100000000 000000ce: DUP2 000000cf: GT 000000d0: ISZERO 000000d1: PUSH2 0x00d9 000000d4: JUMPI 000000d5: PUSH1 0x00 000000d7: DUP1 000000d8: REVERT 000000d9: JUMPDEST 000000da: DUP3 000000db: ADD 000000dc: DUP4 000000dd: PUSH1 0x20 000000df: DUP3 000000e0: ADD 000000e1: GT 000000e2: ISZERO 000000e3: PUSH2 0x00eb 000000e6: JUMPI 000000e7: PUSH1 0x00 000000e9: DUP1 000000ea: REVERT 000000eb: JUMPDEST 000000ec: DUP1 000000ed: CALLDATALOAD 000000ee: SWAP1 000000ef: PUSH1 0x20 000000f1: ADD 000000f2: SWAP2 000000f3: DUP5 000000f4: PUSH1 0x01 000000f6: DUP4 000000f7: MUL 000000f8: DUP5 000000f9: ADD 000000fa: GT 000000fb: PUSH5 0x0100000000 00000101: DUP4 00000102: GT 00000103: OR 00000104: ISZERO 00000105: PUSH2 0x010d 00000108: JUMPI 00000109: PUSH1 0x00 0000010b: DUP1 0000010c: REVERT 0000010d: JUMPDEST 0000010e: POP 0000010f: SWAP1 00000110: SWAP3 00000111: POP 00000112: SWAP1 00000113: POP 00000114: PUSH2 0x01e5 00000117: JUMP 00000118: JUMPDEST 00000119: CALLVALUE 0000011a: DUP1 0000011b: ISZERO 0000011c: PUSH2 0x0124 0000011f: JUMPI 00000120: PUSH1 0x00 00000122: DUP1 00000123: REVERT 00000124: JUMPDEST 00000125: POP 00000126: PUSH2 0x012d 00000129: PUSH2 0x0292 0000012c: JUMP 0000012d: JUMPDEST 0000012e: PUSH1 0x40 00000130: DUP1 00000131: MLOAD 00000132: PUSH1 0x01 00000134: PUSH1 0x01 00000136: PUSH1 0xa0 00000138: SHL 00000139: SUB 0000013a: SWAP1 0000013b: SWAP3 0000013c: AND 0000013d: DUP3 0000013e: MSTORE 0000013f: MLOAD 00000140: SWAP1 00000141: DUP2 00000142: SWAP1 00000143: SUB 00000144: PUSH1 0x20 00000146: ADD 00000147: SWAP1 00000148: RETURN 00000149: JUMPDEST 0000014a: CALLVALUE 0000014b: DUP1 0000014c: ISZERO 0000014d: PUSH2 0x0155 00000150: JUMPI 00000151: PUSH1 0x00 00000153: DUP1 00000154: REVERT 00000155: JUMPDEST 00000156: POP 00000157: PUSH2 0x005b 0000015a: PUSH1 0x04 0000015c: DUP1 0000015d: CALLDATASIZE 0000015e: SUB 0000015f: PUSH1 0x20 00000161: DUP2 00000162: LT 00000163: ISZERO 00000164: PUSH2 0x016c 00000167: JUMPI 00000168: PUSH1 0x00 0000016a: DUP1 0000016b: REVERT 0000016c: JUMPDEST 0000016d: POP 0000016e: CALLDATALOAD 0000016f: PUSH1 0x01 00000171: PUSH1 0x01 00000173: PUSH1 0xa0 00000175: SHL 00000176: SUB 00000177: AND 00000178: PUSH2 0x02cf 0000017b: JUMP 0000017c: JUMPDEST 0000017d: CALLVALUE 0000017e: DUP1 0000017f: ISZERO 00000180: PUSH2 0x0188 00000183: JUMPI 00000184: PUSH1 0x00 00000186: DUP1 00000187: REVERT 00000188: JUMPDEST 00000189: POP 0000018a: PUSH2 0x012d 0000018d: PUSH2 0x0389 00000190: JUMP 00000191: JUMPDEST 00000192: PUSH2 0x0199 00000195: PUSH2 0x03ba 00000198: JUMP 00000199: JUMPDEST 0000019a: PUSH2 0x01a9 0000019d: PUSH2 0x01a4 000001a0: PUSH2 0x041a 000001a3: JUMP 000001a4: JUMPDEST 000001a5: PUSH2 0x043f 000001a8: JUMP 000001a9: JUMPDEST 000001aa: JUMP 000001ab: JUMPDEST 000001ac: PUSH2 0x01b3 000001af: PUSH2 0x0463 000001b2: JUMP 000001b3: JUMPDEST 000001b4: PUSH1 0x01 000001b6: PUSH1 0x01 000001b8: PUSH1 0xa0 000001ba: SHL 000001bb: SUB 000001bc: AND 000001bd: CALLER 000001be: PUSH1 0x01 000001c0: PUSH1 0x01 000001c2: PUSH1 0xa0 000001c4: SHL 000001c5: SUB 000001c6: AND 000001c7: EQ 000001c8: ISZERO 000001c9: PUSH2 0x01da 000001cc: JUMPI 000001cd: PUSH2 0x01d5 000001d0: DUP2 000001d1: PUSH2 0x0488 000001d4: JUMP 000001d5: JUMPDEST 000001d6: PUSH2 0x01e2 000001d9: JUMP 000001da: JUMPDEST 000001db: PUSH2 0x01e2 000001de: PUSH2 0x0191 000001e1: JUMP 000001e2: JUMPDEST 000001e3: POP 000001e4: JUMP 000001e5: JUMPDEST 000001e6: PUSH2 0x01ed 000001e9: PUSH2 0x0463 000001ec: JUMP 000001ed: JUMPDEST 000001ee: PUSH1 0x01 000001f0: PUSH1 0x01 000001f2: PUSH1 0xa0 000001f4: SHL 000001f5: SUB 000001f6: AND 000001f7: CALLER 000001f8: PUSH1 0x01 000001fa: PUSH1 0x01 000001fc: PUSH1 0xa0 000001fe: SHL 000001ff: SUB 00000200: AND 00000201: EQ 00000202: ISZERO 00000203: PUSH2 0x0285 00000206: JUMPI 00000207: PUSH2 0x020f 0000020a: DUP4 0000020b: PUSH2 0x0488 0000020e: JUMP 0000020f: JUMPDEST 00000210: PUSH1 0x00 00000212: DUP4 00000213: PUSH1 0x01 00000215: PUSH1 0x01 00000217: PUSH1 0xa0 00000219: SHL 0000021a: SUB 0000021b: AND 0000021c: DUP4 0000021d: DUP4 0000021e: PUSH1 0x40 00000220: MLOAD 00000221: DUP1 00000222: DUP4 00000223: DUP4 00000224: DUP1 00000225: DUP3 00000226: DUP5 00000227: CALLDATACOPY 00000228: PUSH1 0x40 0000022a: MLOAD 0000022b: SWAP3 0000022c: ADD 0000022d: SWAP5 0000022e: POP 0000022f: PUSH1 0x00 00000231: SWAP4 00000232: POP 00000233: SWAP1 00000234: SWAP2 00000235: POP 00000236: POP 00000237: DUP1 00000238: DUP4 00000239: SUB 0000023a: DUP2 0000023b: DUP6 0000023c: GAS 0000023d: DELEGATECALL 0000023e: SWAP2 0000023f: POP 00000240: POP 00000241: RETURNDATASIZE 00000242: DUP1 00000243: PUSH1 0x00 00000245: DUP2 00000246: EQ 00000247: PUSH2 0x026c 0000024a: JUMPI 0000024b: PUSH1 0x40 0000024d: MLOAD 0000024e: SWAP2 0000024f: POP 00000250: PUSH1 0x1f 00000252: NOT 00000253: PUSH1 0x3f 00000255: RETURNDATASIZE 00000256: ADD 00000257: AND 00000258: DUP3 00000259: ADD 0000025a: PUSH1 0x40 0000025c: MSTORE 0000025d: RETURNDATASIZE 0000025e: DUP3 0000025f: MSTORE 00000260: RETURNDATASIZE 00000261: PUSH1 0x00 00000263: PUSH1 0x20 00000265: DUP5 00000266: ADD 00000267: RETURNDATACOPY 00000268: PUSH2 0x0271 0000026b: JUMP 0000026c: JUMPDEST 0000026d: PUSH1 0x60 0000026f: SWAP2 00000270: POP 00000271: JUMPDEST 00000272: POP 00000273: POP 00000274: SWAP1 00000275: POP 00000276: DUP1 00000277: PUSH2 0x027f 0000027a: JUMPI 0000027b: PUSH1 0x00 0000027d: DUP1 0000027e: REVERT 0000027f: JUMPDEST 00000280: POP 00000281: PUSH2 0x028d 00000284: JUMP 00000285: JUMPDEST 00000286: PUSH2 0x028d 00000289: PUSH2 0x0191 0000028c: JUMP 0000028d: JUMPDEST 0000028e: POP 0000028f: POP 00000290: POP 00000291: JUMP 00000292: JUMPDEST 00000293: PUSH1 0x00 00000295: PUSH2 0x029c 00000298: PUSH2 0x0463 0000029b: JUMP 0000029c: JUMPDEST 0000029d: PUSH1 0x01 0000029f: PUSH1 0x01 000002a1: PUSH1 0xa0 000002a3: SHL 000002a4: SUB 000002a5: AND 000002a6: CALLER 000002a7: PUSH1 0x01 000002a9: PUSH1 0x01 000002ab: PUSH1 0xa0 000002ad: SHL 000002ae: SUB 000002af: AND 000002b0: EQ 000002b1: ISZERO 000002b2: PUSH2 0x02c4 000002b5: JUMPI 000002b6: PUSH2 0x02bd 000002b9: PUSH2 0x041a 000002bc: JUMP 000002bd: JUMPDEST 000002be: SWAP1 000002bf: POP 000002c0: PUSH2 0x02cc 000002c3: JUMP 000002c4: JUMPDEST 000002c5: PUSH2 0x02cc 000002c8: PUSH2 0x0191 000002cb: JUMP 000002cc: JUMPDEST 000002cd: SWAP1 000002ce: JUMP 000002cf: JUMPDEST 000002d0: PUSH2 0x02d7 000002d3: PUSH2 0x0463 000002d6: JUMP 000002d7: JUMPDEST 000002d8: PUSH1 0x01 000002da: PUSH1 0x01 000002dc: PUSH1 0xa0 000002de: SHL 000002df: SUB 000002e0: AND 000002e1: CALLER 000002e2: PUSH1 0x01 000002e4: PUSH1 0x01 000002e6: PUSH1 0xa0 000002e8: SHL 000002e9: SUB 000002ea: AND 000002eb: EQ 000002ec: ISZERO 000002ed: PUSH2 0x01da 000002f0: JUMPI 000002f1: PUSH1 0x01 000002f3: PUSH1 0x01 000002f5: PUSH1 0xa0 000002f7: SHL 000002f8: SUB 000002f9: DUP2 000002fa: AND 000002fb: PUSH2 0x0335 000002fe: JUMPI 000002ff: PUSH1 0x40 00000301: MLOAD 00000302: PUSH3 0x461bcd 00000306: PUSH1 0xe5 00000308: SHL 00000309: DUP2 0000030a: MSTORE 0000030b: PUSH1 0x04 0000030d: ADD 0000030e: DUP1 0000030f: DUP1 00000310: PUSH1 0x20 00000312: ADD 00000313: DUP3 00000314: DUP2 00000315: SUB 00000316: DUP3 00000317: MSTORE 00000318: PUSH1 0x3a 0000031a: DUP2 0000031b: MSTORE 0000031c: PUSH1 0x20 0000031e: ADD 0000031f: DUP1 00000320: PUSH2 0x0555 00000323: PUSH1 0x3a 00000325: SWAP2 00000326: CODECOPY 00000327: PUSH1 0x40 00000329: ADD 0000032a: SWAP2 0000032b: POP 0000032c: POP 0000032d: PUSH1 0x40 0000032f: MLOAD 00000330: DUP1 00000331: SWAP2 00000332: SUB 00000333: SWAP1 00000334: REVERT 00000335: JUMPDEST 00000336: PUSH32 0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f 00000357: PUSH2 0x035e 0000035a: PUSH2 0x0463 0000035d: JUMP 0000035e: JUMPDEST 0000035f: PUSH1 0x40 00000361: DUP1 00000362: MLOAD 00000363: PUSH1 0x01 00000365: PUSH1 0x01 00000367: PUSH1 0xa0 00000369: SHL 0000036a: SUB 0000036b: SWAP3 0000036c: DUP4 0000036d: AND 0000036e: DUP2 0000036f: MSTORE 00000370: SWAP2 00000371: DUP5 00000372: AND 00000373: PUSH1 0x20 00000375: DUP4 00000376: ADD 00000377: MSTORE 00000378: DUP1 00000379: MLOAD 0000037a: SWAP2 0000037b: DUP3 0000037c: SWAP1 0000037d: SUB 0000037e: ADD 0000037f: SWAP1 00000380: LOG1 00000381: PUSH2 0x01d5 00000384: DUP2 00000385: PUSH2 0x04c8 00000388: JUMP 00000389: JUMPDEST 0000038a: PUSH1 0x00 0000038c: PUSH2 0x0393 0000038f: PUSH2 0x0463 00000392: JUMP 00000393: JUMPDEST 00000394: PUSH1 0x01 00000396: PUSH1 0x01 00000398: PUSH1 0xa0 0000039a: SHL 0000039b: SUB 0000039c: AND 0000039d: CALLER 0000039e: PUSH1 0x01 000003a0: PUSH1 0x01 000003a2: PUSH1 0xa0 000003a4: SHL 000003a5: SUB 000003a6: AND 000003a7: EQ 000003a8: ISZERO 000003a9: PUSH2 0x02c4 000003ac: JUMPI 000003ad: PUSH2 0x02bd 000003b0: PUSH2 0x0463 000003b3: JUMP 000003b4: JUMPDEST 000003b5: EXTCODESIZE 000003b6: ISZERO 000003b7: ISZERO 000003b8: SWAP1 000003b9: JUMP 000003ba: JUMPDEST 000003bb: PUSH2 0x03c2 000003be: PUSH2 0x0463 000003c1: JUMP 000003c2: JUMPDEST 000003c3: PUSH1 0x01 000003c5: PUSH1 0x01 000003c7: PUSH1 0xa0 000003c9: SHL 000003ca: SUB 000003cb: AND 000003cc: CALLER 000003cd: PUSH1 0x01 000003cf: PUSH1 0x01 000003d1: PUSH1 0xa0 000003d3: SHL 000003d4: SUB 000003d5: AND 000003d6: EQ 000003d7: ISZERO 000003d8: PUSH2 0x0412 000003db: JUMPI 000003dc: PUSH1 0x40 000003de: MLOAD 000003df: PUSH3 0x461bcd 000003e3: PUSH1 0xe5 000003e5: SHL 000003e6: DUP2 000003e7: MSTORE 000003e8: PUSH1 0x04 000003ea: ADD 000003eb: DUP1 000003ec: DUP1 000003ed: PUSH1 0x20 000003ef: ADD 000003f0: DUP3 000003f1: DUP2 000003f2: SUB 000003f3: DUP3 000003f4: MSTORE 000003f5: PUSH1 0x42 000003f7: DUP2 000003f8: MSTORE 000003f9: PUSH1 0x20 000003fb: ADD 000003fc: DUP1 000003fd: PUSH2 0x05c5 00000400: PUSH1 0x42 00000402: SWAP2 00000403: CODECOPY 00000404: PUSH1 0x60 00000406: ADD 00000407: SWAP2 00000408: POP 00000409: POP 0000040a: PUSH1 0x40 0000040c: MLOAD 0000040d: DUP1 0000040e: SWAP2 0000040f: SUB 00000410: SWAP1 00000411: REVERT 00000412: JUMPDEST 00000413: PUSH2 0x01a9 00000416: PUSH2 0x01a9 00000419: JUMP 0000041a: JUMPDEST 0000041b: PUSH32 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc 0000043c: SLOAD 0000043d: SWAP1 0000043e: JUMP 0000043f: JUMPDEST 00000440: CALLDATASIZE 00000441: PUSH1 0x00 00000443: DUP1 00000444: CALLDATACOPY 00000445: PUSH1 0x00 00000447: DUP1 00000448: CALLDATASIZE 00000449: PUSH1 0x00 0000044b: DUP5 0000044c: GAS 0000044d: DELEGATECALL 0000044e: RETURNDATASIZE 0000044f: PUSH1 0x00 00000451: DUP1 00000452: RETURNDATACOPY 00000453: DUP1 00000454: DUP1 00000455: ISZERO 00000456: PUSH2 0x045e 00000459: JUMPI 0000045a: RETURNDATASIZE 0000045b: PUSH1 0x00 0000045d: RETURN 0000045e: JUMPDEST 0000045f: RETURNDATASIZE 00000460: PUSH1 0x00 00000462: REVERT 00000463: JUMPDEST 00000464: PUSH32 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103 00000485: SLOAD 00000486: SWAP1 00000487: JUMP 00000488: JUMPDEST 00000489: PUSH2 0x0491 0000048c: DUP2 0000048d: PUSH2 0x04ec 00000490: JUMP 00000491: JUMPDEST 00000492: PUSH1 0x40 00000494: MLOAD 00000495: PUSH1 0x01 00000497: PUSH1 0x01 00000499: PUSH1 0xa0 0000049b: SHL 0000049c: SUB 0000049d: DUP3 0000049e: AND 0000049f: SWAP1 000004a0: PUSH32 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b 000004c1: SWAP1 000004c2: PUSH1 0x00 000004c4: SWAP1 000004c5: LOG2 000004c6: POP 000004c7: JUMP 000004c8: JUMPDEST 000004c9: PUSH32 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103 000004ea: SSTORE 000004eb: JUMP 000004ec: JUMPDEST 000004ed: PUSH2 0x04f5 000004f0: DUP2 000004f1: PUSH2 0x03b4 000004f4: JUMP 000004f5: JUMPDEST 000004f6: PUSH2 0x0530 000004f9: JUMPI 000004fa: PUSH1 0x40 000004fc: MLOAD 000004fd: PUSH3 0x461bcd 00000501: PUSH1 0xe5 00000503: SHL 00000504: DUP2 00000505: MSTORE 00000506: PUSH1 0x04 00000508: ADD 00000509: DUP1 0000050a: DUP1 0000050b: PUSH1 0x20 0000050d: ADD 0000050e: DUP3 0000050f: DUP2 00000510: SUB 00000511: DUP3 00000512: MSTORE 00000513: PUSH1 0x36 00000515: DUP2 00000516: MSTORE 00000517: PUSH1 0x20 00000519: ADD 0000051a: DUP1 0000051b: PUSH2 0x058f 0000051e: PUSH1 0x36 00000520: SWAP2 00000521: CODECOPY 00000522: PUSH1 0x40 00000524: ADD 00000525: SWAP2 00000526: POP 00000527: POP 00000528: PUSH1 0x40 0000052a: MLOAD 0000052b: DUP1 0000052c: SWAP2 0000052d: SUB 0000052e: SWAP1 0000052f: REVERT 00000530: JUMPDEST 00000531: PUSH32 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc 00000552: SSTORE 00000553: JUMP 00000554: INVALID 00000555: SLOAD 00000556: PUSH19 0x616e73706172656e745570677261646561626c 0000056a: PUSH6 0x50726f78793a 00000571: KECCAK256 00000572: PUSH15 0x65772061646d696e20697320746865 00000582: KECCAK256 00000583: PUSH27 0x65726f20616464726573735570677261646561626c6550726f7879 0000059f: GASPRICE 000005a0: KECCAK256 000005a1: PUSH15 0x657720696d706c656d656e74617469 000005b1: PUSH16 0x6e206973206e6f74206120636f6e7472 000005c2: PUSH2 0x6374 000005c5: SLOAD 000005c6: PUSH19 0x616e73706172656e745570677261646561626c 000005da: PUSH6 0x50726f78793a 000005e1: KECCAK256 000005e2: PUSH2 0x646d 000005e5: PUSH10 0x6e2063616e6e6f742066 000005f0: PUSH2 0x6c6c 000005f3: PUSH3 0x61636b 000005f7: KECCAK256 000005f8: PUSH21 0x6f2070726f787920746172676574a2646970667358 0000060e: UNKNOWN(0x22) 0000060f: SLT 00000610: KECCAK256 00000611: PUSH11 0x10ba3ffd6033d03562e9c0 0000061d: SWAP8 0000061e: PUSH32
| Severity | Category | Tool | Title | Confidence | Validated | Confirmed | Details |
|---|---|---|---|---|---|---|---|
| critical | upgradeability | detector | Untrusted DELEGATECALL target reachable | 70 | no | no |
viewtrace_id: 0x18a58223095c61e4ed5cbf5bd462018f3b5edb411dd5d6a3401861f4f4d249c8
call_targets:
0x4a1dc57d949db46a456d0104f437ed87ee24422f
target_varies:
no
classification:
constant_target
validation_json{
"sink": "DELEGATECALL",
"errors": 0,
"status": "sink_reached",
"attempts": 2,
"trace_id": "0x18a58223095c61e4ed5cbf5bd462018f3b5edb411dd5d6a3401861f4f4d249c8",
"confirmed": false,
"trace_mode": "callTracer",
"call_targets": [
"0x4a1dc57d949db46a456d0104f437ed87ee24422f"
],
"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": "0x3659cfe6",
"selector": "0x3659cfe6",
"calldata_variants": [
"0x3659cfe6",
"0x3659cfe60000000000000000000000000000000000000000000000000000000000000000"
]
},
{
"calldata": "0x4f1ef286",
"selector": "0x4f1ef286",
"calldata_variants": [
"0x4f1ef286",
"0x4f1ef2860000000000000000000000000000000000000000000000000000000000000000"
]
},
{
"calldata": "0x5c60da1b",
"selector": "0x5c60da1b",
"calldata_variants": [
"0x5c60da1b",
"0x5c60da1b0000000000000000000000000000000000000000000000000000000000000000"
]
},
{
"calldata": "0x8f283970",
"selector": "0x8f283970",
"calldata_variants": [
"0x8f283970",
"0x8f2839700000000000000000000000000000000000000000000000000000000000000000"
]
},
{
"calldata": "0xf851a440",
"selector": "0xf851a440",
"calldata_variants": [
"0xf851a440",
"0xf851a4400000000000000000000000000000000000000000000000000000000000000000"
]
}
]
}
evidence_json{
"examples": [
{
"pc": 573,
"opcode": "DELEGATECALL",
"returndata_checked": null,
"value_expression_category": "n/a",
"target_expression_category": "computed"
},
{
"pc": 1101,
"opcode": "DELEGATECALL",
"returndata_checked": null,
"value_expression_category": "n/a",
"target_expression_category": "computed"
}
],
"guards_detected": [],
"delegatecall_count": 2,
"untrusted_delegatecall_count": 2
}
|
| high | auth | codex | Orders are unauthenticated, allowing relays to execute arbitrary trades or penalties against any trader | 85 | no | — |
viewevidence_json{
"evidence": "fill() only requires onlyRelay and does not verify any signature/nonce, while Types.Order carries no signature fields.",
"locations": [
"contracts/SwapSettlement.sol:95",
"contracts/SwapSettlement.sol:103",
"contracts/Types.sol:33"
],
"recommendation": "Introduce EIP\u2011712 signed orders with per\u2011trader nonces/cancellation, and require signature verification in fill(). Enforce gasAllowance/minFee constraints and validate that the order was authored by the trader before performing swaps or penalties.",
"exploit_scenario": "A compromised or malicious RELAY_ROLE calls fill() with order.trader set to a victim who has deposited gas. Because the order is not signed or nonce\u2011checked, the relay can (a) trigger _penalize by passing an unapproved script or invalid order, draining the victim\u2019s gas balance, or (b) execute an arbitrary swap using the victim\u2019s token allowance to trade at unfavorable rates without the victim\u2019s consent."
}
|
| medium | upgradeability | cast | DELEGATECALL present | 80 | no | — |
viewevidence_json{
"notes": "delegatecall enables execution in caller context; common in proxies/upgradeable patterns",
"delegatecall_count": 2
}
|
| low | other | codex | Unchecked ERC20 return values can silently fail transfers and strand/refund tokens in Uniswapper | 65 | no | — |
viewevidence_json{
"evidence": "Token transfers in _exactIn/_exactOut and the refund path ignore the boolean return value.",
"locations": [
"contracts/swapper/uniswap/Uniswapper.sol:92",
"contracts/swapper/uniswap/Uniswapper.sol:152",
"contracts/swapper/uniswap/Uniswapper.sol:183"
],
"recommendation": "Use SafeERC20 (safeTransfer/safeTransferFrom) and check return values for all token transfers, including refunds. Consider reverting on failed refunds to avoid silent loss or implement a recovery mechanism.",
"exploit_scenario": "For ERC20s that return false on transfer (without reverting), _exactOut will proceed even if the refund transfer fails. The swap is considered successful by SwapSettlement, but the unused input tokens remain in Uniswapper, causing traders to lose funds or leaving recoverable balances in the script contract."
}
|