019c0ea9-07ed-70da-abbb-d6eab83f6cb6
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 |
|---|---|---|---|---|
| 41711 | artifact.fetch | complete | 1 / 3 | 2 months ago |
| 41712 | proxy.resolve | complete | 1 / 3 | 2 months ago |
| 41713 | tool.cast_disasm | complete | 1 / 3 | 2 months ago |
| 41714 | analysis.bundle | complete | 1 / 3 | 2 months ago |
| 41715 | capability.graph | complete | 1 / 3 | 2 months ago |
| 41716 | detector.run | complete | 1 / 3 | 2 months ago |
| 41717 | validation.fork | complete | 1 / 3 | 2 months ago |
| 42295 | report.consolidate | complete | 1 / 6 | 2 months ago |
| 42296 | tool.slither | complete | 1 / 2 | 2 months ago |
{
"method": "etherscan+onchain",
"status": "confirmed",
"etherscan_hint": {
"source": "etherscan",
"etherscan": {
"proxy_flag": true,
"implementation": "0x438285fbccba55ce8cdef276030e6b35a0b65b6b"
}
},
"implementation": "0x438285fbccba55ce8cdef276030e6b35a0b65b6b",
"onchain_method": "eip1967"
}
'forge clean' running (wd: /tmp/slither-obs3i23f)
'forge config --json' running
'forge build --build-info --skip ./test/** ./script/** --force' running (wd: /tmp/slither-obs3i23f)
TransparentUpgradeableProxy.admin() (contracts/Contract.sol#791-796) calls TransparentUpgradeableProxy.ifAdmin() (contracts/Contract.sol#782-783) which halt the execution return(uint256,uint256)(0,returndatasize()()) (contracts/Contract.sol#37-38)
TransparentUpgradeableProxy.implementation() (contracts/Contract.sol#811-812) calls TransparentUpgradeableProxy.ifAdmin() (contracts/Contract.sol#782-783) which halt the execution return(uint256,uint256)(0,returndatasize()()) (contracts/Contract.sol#37-38)
TransparentUpgradeableProxy.changeAdmin(address) (contracts/Contract.sol#816-822) calls TransparentUpgradeableProxy.ifAdmin() (contracts/Contract.sol#782-783) which halt the execution return(uint256,uint256)(0,returndatasize()()) (contracts/Contract.sol#37-38)
TransparentUpgradeableProxy.upgradeTo(address) (contracts/Contract.sol#824-825) calls TransparentUpgradeableProxy.ifAdmin() (contracts/Contract.sol#782-783) which halt the execution return(uint256,uint256)(0,returndatasize()()) (contracts/Contract.sol#37-38)
TransparentUpgradeableProxy.upgradeToAndCall(address,bytes) (contracts/Contract.sol#837-840) calls TransparentUpgradeableProxy.ifAdmin() (contracts/Contract.sol#782-783) which halt the execution return(uint256,uint256)(0,returndatasize()()) (contracts/Contract.sol#37-38)
TransparentUpgradeableProxy.ifAdmin() (contracts/Contract.sol#782-783) calls Proxy._fallback() (contracts/Contract.sol#51-54) which halt the execution return(uint256,uint256)(0,returndatasize()()) (contracts/Contract.sol#37-38)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-return-in-assembly
ERC1967Upgrade._upgradeToAndCall(address,bytes,bool) (contracts/Contract.sol#133-140) ignores return value by Address.functionDelegateCall(newImplementation,data) (contracts/Contract.sol#139-140)
ERC1967Upgrade._upgradeToAndCallSecure(address,bytes,bool) (contracts/Contract.sol#147-175) ignores return value by Address.functionDelegateCall(newImplementation,data) (contracts/Contract.sol#152-155)
ERC1967Upgrade._upgradeToAndCallSecure(address,bytes,bool) (contracts/Contract.sol#147-175) ignores return value by Address.functionDelegateCall(newImplementation,abi.encodeWithSignature(upgradeTo(address),oldImplementation)) (contracts/Contract.sol#162-166)
ERC1967Upgrade._upgradeBeaconToAndCall(address,bytes,bool) (contracts/Contract.sol#182-188) ignores return value by Address.functionDelegateCall(IBeacon(newBeacon).implementation(),data) (contracts/Contract.sol#187-188)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#unused-return
AdminUpgradeabilityProxy.constructor(address,address,bytes).admin (contracts/Contract.sol#857-858) shadows:
- TransparentUpgradeableProxy.admin() (contracts/Contract.sol#791-796) (function)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#local-variable-shadowing
Modifier TransparentUpgradeableProxy.ifAdmin() (contracts/Contract.sol#782-783) does not always execute _; or revert
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-modifier
Reentrancy in ERC1967Upgrade._upgradeToAndCallSecure(address,bytes,bool) (contracts/Contract.sol#147-175):
External calls:
- Address.functionDelegateCall(newImplementation,data) (contracts/Contract.sol#152-155)
- Address.functionDelegateCall(newImplementation,abi.encodeWithSignature(upgradeTo(address),oldImplementation)) (contracts/Contract.sol#162-166)
Event emitted after the call(s):
- Upgraded(newImplementation) (contracts/Contract.sol#174)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-3
Proxy._delegate(address) (contracts/Contract.sol#18-38) uses assembly
- INLINE ASM (contracts/Contract.sol#21-38)
Address.isContract(address) (contracts/Contract.sol#290-300) uses assembly
- INLINE ASM (contracts/Contract.sol#299-300)
Address._verifyCallResult(bool,bytes,string) (contracts/Contract.sol#435-449) uses assembly
- INLINE ASM (contracts/Contract.sol#444-447)
StorageSlot.getAddressSlot(bytes32) (contracts/Contract.sol#483-488) uses assembly
- INLINE ASM (contracts/Contract.sol#488)
StorageSlot.getBooleanSlot(bytes32) (contracts/Contract.sol#495-504) uses assembly
- INLINE ASM (contracts/Contract.sol#500-504)
StorageSlot.getBytes32Slot(bytes32) (contracts/Contract.sol#508-512) uses assembly
- INLINE ASM (contracts/Contract.sol#510-512)
StorageSlot.getUint256Slot(bytes32) (contracts/Contract.sol#517-521) uses assembly
- INLINE ASM (contracts/Contract.sol#519-521)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#assembly-usage
Context._msgData() (contracts/Contract.sol#546-548) is never used and should be removed
ERC1967Upgrade._getBeacon() (contracts/Contract.sol#236-240) is never used and should be removed
ERC1967Upgrade._setBeacon(address) (contracts/Contract.sol#244-256) is never used and should be removed
ERC1967Upgrade._upgradeBeaconToAndCall(address,bytes,bool) (contracts/Contract.sol#182-188) is never used and should be removed
ERC1967Upgrade._upgradeTo(address) (contracts/Contract.sol#120-128) is never used and should be removed
TransparentUpgradeableProxy._admin() (contracts/Contract.sol#844-846) is never used and should be removed
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#dead-code
Version constraint ^0.8.0 contains known severe issues (https://solidity.readthedocs.io/en/latest/bugs.html)
- FullInlinerNonExpressionSplitArgumentEvaluationOrder
- MissingSideEffectsOnSelectorAccess
- AbiReencodingHeadOverflowWithStaticArrayCleanup
- DirtyBytesArrayToStorage
- DataLocationChangeInInternalOverride
- NestedCalldataArrayAbiReencodingSizeValidation
- SignedImmutables
- ABIDecodeTwoDimensionalArrayMemory
- KeccakCaching.
It is used by:
- ^0.8.0 (contracts/Contract.sol#1-2)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-versions-of-solidity
Low level call in Address.sendValue(address,uint256) (contracts/Contract.sol#321-326):
- (success,None) = recipient.call{value: amount}() (contracts/Contract.sol#324)
Low level call in Address.functionCallWithValue(address,bytes,uint256,string) (contracts/Contract.sol#377-387):
- (success,returndata) = target.call{value: value}(data) (contracts/Contract.sol#385-387)
Low level call in Address.functionStaticCall(address,bytes,string) (contracts/Contract.sol#400-412):
- (success,returndata) = target.staticcall(data) (contracts/Contract.sol#407-408)
Low level call in Address.functionDelegateCall(address,bytes,string) (contracts/Contract.sol#424-434):
- (success,returndata) = target.delegatecall(data) (contracts/Contract.sol#431)
Low level call in ProxyAdmin.getProxyImplementation(TransparentUpgradeableProxy) (contracts/Contract.sol#622-633):
- (success,returndata) = address(proxy).staticcall(0x5c60da1b) (contracts/Contract.sol#630-631)
Low level call in ProxyAdmin.getProxyAdmin(TransparentUpgradeableProxy) (contracts/Contract.sol#640-646):
- (success,returndata) = address(proxy).staticcall(0xf851a440) (contracts/Contract.sol#644-645)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#low-level-calls
Redundant expression "this (contracts/Contract.sol#546-547)" inContext (contracts/Contract.sol#539-549)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#redundant-statements
. analyzed (14 contracts with 100 detectors), 34 result(s) found
{
"solc": {
"status": "ok",
"use_rc": 0,
"version": "0.8.0",
"strategy": "solc-select",
"solc_path": "/var/www/tripwire/.venv/bin/solc",
"install_rc": 0,
"use_stderr": null,
"use_stdout": "Switched global version to 0.8.0",
"install_stderr": null,
"install_stdout": "Version '0.8.0' is already installed, skipping..."
},
"solc_args": "--base-path /tmp/slither-obs3i23f --allow-paths /tmp/slither-obs3i23f,/tmp/slither-obs3i23f/lib,/tmp/slither-obs3i23f/src",
"remappings": [],
"source_files": [
"contracts/Contract.sol"
],
"contract_count": 0,
"contract_names": [],
"detector_count": 34,
"workspace_hash": "004a4d714c2510d061abc52f244da717eb36ff316e31e0eba522179640ee3bae",
"duration_seconds": 1.3392176628112793,
"solc_version_requested": "0.8.2"
}
{"no_findings":false,"summary":"Signature validation lacks contract/domain separation, so the same validator signatures can be replayed across multiple GenericBridge deployments on the same chain.","findings":[{"severity":"medium","category":"auth","title":"Signatures are not bound to the bridge contract, enabling cross-contract replay","exploit_scenario":"If validators sign a claim for one GenericBridge deployment, an attacker can reuse the same signatures on a second GenericBridge instance on the same chain (or a redeployed instance with the same validator set) because the signed message omits `address(this)`. This can mint/withdraw assets from the unintended bridge instance.","recommendation":"Include `address(this)` (and optionally chainId) in the signed payload, or switch to EIP-712 with a domain separator bound to the contract address. Ensure both `claimToken` and `DTOBridgeToken.claimBridgeToken` compute claim IDs with the same domain binding.","evidence":"`claimToken` builds `_claimId` from origin token, recipient, amount, chainIds, txHash, name/symbol/decimals only, and `verifySignatures` checks this hash without any contract/domain binding.","locations":["contracts/generic/GenericBridge.sol"]}]}
OpenAI Codex v0.77.0 (research preview)
--------
workdir: /tmp/codex-d0ccrm3s
model: gpt-5.2-codex
provider: openai
approval: never
sandbox: read-only
reasoning effort: high
reasoning summaries: auto
session id: 019c0efd-352c-7cb1-b0a0-1fa5d2d58a38
--------
user
Context: The user requested the proxy at 0x02b758ce469af940c57a42ad1de5d404122bc283.
Audit the implementation at 0x438285fbccba55ce8cdef276030e6b35a0b65b6b.
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-d0ccrm3s succeeded in 8ms:
AUDIT_BUNDLE.txt
codex-output-schema.json
contracts
@openzeppelin
exec
/bin/bash -lc 'cat AUDIT_BUNDLE.txt' in /tmp/codex-d0ccrm3s succeeded in 6ms:
This file concatenates the full contents of first-party Solidity sources for auditing.
Do not treat dependency code under lib/ or @openzeppelin/ as first-party.
================================================================================
FILE: contracts/generic/DTOBridgeToken.sol
================================================================================
pragma solidity ^0.8.0;
import "@openzeppelin/contracts-upgradeable/utils/math/SafeMathUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; // for WETH
import "../interfaces/IDTOTokenBridge.sol";
// import "./Governable.sol";
import "../lib/ChainIdHolding.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20BurnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
contract DTOBridgeToken is
ERC20BurnableUpgradeable,
IDTOTokenBridge,
OwnableUpgradeable,
codex
{"no_findings":false,"summary":"Signature validation lacks contract/domain separation, so the same validator signatures can be replayed across multiple GenericBridge deployments on the same chain.","findings":[{"severity":"medium","category":"auth","title":"Signatures are not bound to the bridge contract, enabling cross-contract replay","exploit_scenario":"If validators sign a claim for one GenericBridge deployment, an attacker can reuse the same signatures on a second GenericBridge instance on the same chain (or a redeployed instance with the same validator set) because the signed message omits `address(this)`. This can mint/withdraw assets from the unintended bridge instance.","recommendation":"Include `address(this)` (and optionally chainId) in the signed payload, or switch to EIP-712 with a domain separator bound to the contract address. Ensure both `claimToken` and `DTOBridgeToken.claimBridgeToken` compute claim IDs with the same domain binding.","evidence":"`claimToken` builds `_claimId` from origin token, recipient, amount, chainIds, txHash, name/symbol/decimals only, and `verifySignatures` checks this hash without any contract/domain binding.","locations":["contracts/generic/GenericBridge.sol"]}]}
tokens used
22,633
{
"codex": {
"ran_at": "2026-01-30T13:04:14.333611+00:00",
"returncode": 0
},
"project": {
"mode": "source",
"file_count": 25,
"import_count": 35,
"first_party_contracts_count": 7
},
"summary": "Signature validation lacks contract/domain separation, so the same validator signatures can be replayed across multiple GenericBridge deployments on the same chain.",
"raw_final": {
"summary": "Signature validation lacks contract/domain separation, so the same validator signatures can be replayed across multiple GenericBridge deployments on the same chain.",
"findings": [
{
"title": "Signatures are not bound to the bridge contract, enabling cross-contract replay",
"category": "auth",
"evidence": "`claimToken` builds `_claimId` from origin token, recipient, amount, chainIds, txHash, name/symbol/decimals only, and `verifySignatures` checks this hash without any contract/domain binding.",
"severity": "medium",
"locations": [
"contracts/generic/GenericBridge.sol"
],
"recommendation": "Include `address(this)` (and optionally chainId) in the signed payload, or switch to EIP-712 with a domain separator bound to the contract address. Ensure both `claimToken` and `DTOBridgeToken.claimBridgeToken` compute claim IDs with the same domain binding.",
"exploit_scenario": "If validators sign a claim for one GenericBridge deployment, an attacker can reuse the same signatures on a second GenericBridge instance on the same chain (or a redeployed instance with the same validator set) because the signed message omits `address(this)`. This can mint/withdraw assets from the unintended bridge instance."
}
],
"no_findings": false
},
"no_findings": false,
"proxy_context": {
"proxy_run_id": "019c0ea9-07ed-70da-abbb-d6eab83f6cb6",
"proxy_address": "0x02b758ce469af940c57a42ad1de5d404122bc283",
"implementation_run_id": "019c0eaa-1573-73c9-bdcd-698f810a9fbd",
"implementation_address": "0x438285fbccba55ce8cdef276030e6b35a0b65b6b"
},
"schema_version": 1
}
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 0x005e 00000021: JUMP 00000022: JUMPDEST 00000023: PUSH2 0x0096 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 0x024c 00000046: PUSH1 0x27 00000048: SWAP2 00000049: CODECOPY 0000004a: PUSH2 0x00ba 0000004d: JUMP 0000004e: JUMPDEST 0000004f: SWAP4 00000050: SWAP3 00000051: POP 00000052: POP 00000053: POP 00000054: JUMP 00000055: JUMPDEST 00000056: EXTCODESIZE 00000057: ISZERO 00000058: ISZERO 00000059: SWAP1 0000005a: JUMP 0000005b: JUMPDEST 0000005c: SWAP1 0000005d: JUMP 0000005e: JUMPDEST 0000005f: PUSH1 0x00 00000061: PUSH2 0x0091 00000064: PUSH32 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc 00000085: SLOAD 00000086: PUSH1 0x01 00000088: PUSH1 0x01 0000008a: PUSH1 0xa0 0000008c: SHL 0000008d: SUB 0000008e: AND 0000008f: SWAP1 00000090: JUMP 00000091: JUMPDEST 00000092: SWAP1 00000093: POP 00000094: SWAP1 00000095: JUMP 00000096: JUMPDEST 00000097: CALLDATASIZE 00000098: PUSH1 0x00 0000009a: DUP1 0000009b: CALLDATACOPY 0000009c: PUSH1 0x00 0000009e: DUP1 0000009f: CALLDATASIZE 000000a0: PUSH1 0x00 000000a2: DUP5 000000a3: GAS 000000a4: DELEGATECALL 000000a5: RETURNDATASIZE 000000a6: PUSH1 0x00 000000a8: DUP1 000000a9: RETURNDATACOPY 000000aa: DUP1 000000ab: DUP1 000000ac: ISZERO 000000ad: PUSH2 0x00b5 000000b0: JUMPI 000000b1: RETURNDATASIZE 000000b2: PUSH1 0x00 000000b4: RETURN 000000b5: JUMPDEST 000000b6: RETURNDATASIZE 000000b7: PUSH1 0x00 000000b9: REVERT 000000ba: JUMPDEST 000000bb: PUSH1 0x60 000000bd: DUP4 000000be: EXTCODESIZE 000000bf: PUSH2 0x011e 000000c2: JUMPI 000000c3: PUSH1 0x40 000000c5: MLOAD 000000c6: PUSH3 0x461bcd 000000ca: PUSH1 0xe5 000000cc: SHL 000000cd: DUP2 000000ce: MSTORE 000000cf: PUSH1 0x20 000000d1: PUSH1 0x04 000000d3: DUP3 000000d4: ADD 000000d5: MSTORE 000000d6: PUSH1 0x26 000000d8: PUSH1 0x24 000000da: DUP3 000000db: ADD 000000dc: MSTORE 000000dd: PUSH32 0x416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f 000000fe: PUSH1 0x44 00000100: DUP3 00000101: ADD 00000102: MSTORE 00000103: PUSH6 0x1b9d1c9858dd 0000010a: PUSH1 0xd2 0000010c: SHL 0000010d: PUSH1 0x64 0000010f: DUP3 00000110: ADD 00000111: MSTORE 00000112: PUSH1 0x84 00000114: ADD 00000115: JUMPDEST 00000116: PUSH1 0x40 00000118: MLOAD 00000119: DUP1 0000011a: SWAP2 0000011b: SUB 0000011c: SWAP1 0000011d: REVERT 0000011e: JUMPDEST 0000011f: PUSH1 0x00 00000121: DUP1 00000122: DUP6 00000123: PUSH1 0x01 00000125: PUSH1 0x01 00000127: PUSH1 0xa0 00000129: SHL 0000012a: SUB 0000012b: AND 0000012c: DUP6 0000012d: PUSH1 0x40 0000012f: MLOAD 00000130: PUSH2 0x0139 00000133: SWAP2 00000134: SWAP1 00000135: PUSH2 0x01cc 00000138: JUMP 00000139: JUMPDEST 0000013a: PUSH1 0x00 0000013c: PUSH1 0x40 0000013e: MLOAD 0000013f: DUP1 00000140: DUP4 00000141: SUB 00000142: DUP2 00000143: DUP6 00000144: GAS 00000145: DELEGATECALL 00000146: SWAP2 00000147: POP 00000148: POP 00000149: RETURNDATASIZE 0000014a: DUP1 0000014b: PUSH1 0x00 0000014d: DUP2 0000014e: EQ 0000014f: PUSH2 0x0174 00000152: JUMPI 00000153: PUSH1 0x40 00000155: MLOAD 00000156: SWAP2 00000157: POP 00000158: PUSH1 0x1f 0000015a: NOT 0000015b: PUSH1 0x3f 0000015d: RETURNDATASIZE 0000015e: ADD 0000015f: AND 00000160: DUP3 00000161: ADD 00000162: PUSH1 0x40 00000164: MSTORE 00000165: RETURNDATASIZE 00000166: DUP3 00000167: MSTORE 00000168: RETURNDATASIZE 00000169: PUSH1 0x00 0000016b: PUSH1 0x20 0000016d: DUP5 0000016e: ADD 0000016f: RETURNDATACOPY 00000170: PUSH2 0x0179 00000173: JUMP 00000174: JUMPDEST 00000175: PUSH1 0x60 00000177: SWAP2 00000178: POP 00000179: JUMPDEST 0000017a: POP 0000017b: SWAP2 0000017c: POP 0000017d: SWAP2 0000017e: POP 0000017f: PUSH2 0x0189 00000182: DUP3 00000183: DUP3 00000184: DUP7 00000185: PUSH2 0x0193 00000188: JUMP 00000189: JUMPDEST 0000018a: SWAP7 0000018b: SWAP6 0000018c: POP 0000018d: POP 0000018e: POP 0000018f: POP 00000190: POP 00000191: POP 00000192: JUMP 00000193: JUMPDEST 00000194: PUSH1 0x60 00000196: DUP4 00000197: ISZERO 00000198: PUSH2 0x01a2 0000019b: JUMPI 0000019c: POP 0000019d: DUP2 0000019e: PUSH2 0x004e 000001a1: JUMP 000001a2: JUMPDEST 000001a3: DUP3 000001a4: MLOAD 000001a5: ISZERO 000001a6: PUSH2 0x01b2 000001a9: JUMPI 000001aa: DUP3 000001ab: MLOAD 000001ac: DUP1 000001ad: DUP5 000001ae: PUSH1 0x20 000001b0: ADD 000001b1: REVERT 000001b2: JUMPDEST 000001b3: DUP2 000001b4: PUSH1 0x40 000001b6: MLOAD 000001b7: PUSH3 0x461bcd 000001bb: PUSH1 0xe5 000001bd: SHL 000001be: DUP2 000001bf: MSTORE 000001c0: PUSH1 0x04 000001c2: ADD 000001c3: PUSH2 0x0115 000001c6: SWAP2 000001c7: SWAP1 000001c8: PUSH2 0x01e8 000001cb: JUMP 000001cc: JUMPDEST 000001cd: PUSH1 0x00 000001cf: DUP3 000001d0: MLOAD 000001d1: PUSH2 0x01de 000001d4: DUP2 000001d5: DUP5 000001d6: PUSH1 0x20 000001d8: DUP8 000001d9: ADD 000001da: PUSH2 0x021b 000001dd: JUMP 000001de: JUMPDEST 000001df: SWAP2 000001e0: SWAP1 000001e1: SWAP2 000001e2: ADD 000001e3: SWAP3 000001e4: SWAP2 000001e5: POP 000001e6: POP 000001e7: JUMP 000001e8: JUMPDEST 000001e9: PUSH1 0x00 000001eb: PUSH1 0x20 000001ed: DUP3 000001ee: MSTORE 000001ef: DUP3 000001f0: MLOAD 000001f1: DUP1 000001f2: PUSH1 0x20 000001f4: DUP5 000001f5: ADD 000001f6: MSTORE 000001f7: PUSH2 0x0207 000001fa: DUP2 000001fb: PUSH1 0x40 000001fd: DUP6 000001fe: ADD 000001ff: PUSH1 0x20 00000201: DUP8 00000202: ADD 00000203: PUSH2 0x021b 00000206: JUMP 00000207: JUMPDEST 00000208: PUSH1 0x1f 0000020a: ADD 0000020b: PUSH1 0x1f 0000020d: NOT 0000020e: AND 0000020f: SWAP2 00000210: SWAP1 00000211: SWAP2 00000212: ADD 00000213: PUSH1 0x40 00000215: ADD 00000216: SWAP3 00000217: SWAP2 00000218: POP 00000219: POP 0000021a: JUMP 0000021b: JUMPDEST 0000021c: PUSH1 0x00 0000021e: JUMPDEST 0000021f: DUP4 00000220: DUP2 00000221: LT 00000222: ISZERO 00000223: PUSH2 0x0236 00000226: JUMPI 00000227: DUP2 00000228: DUP2 00000229: ADD 0000022a: MLOAD 0000022b: DUP4 0000022c: DUP3 0000022d: ADD 0000022e: MSTORE 0000022f: PUSH1 0x20 00000231: ADD 00000232: PUSH2 0x021e 00000235: JUMP 00000236: JUMPDEST 00000237: DUP4 00000238: DUP2 00000239: GT 0000023a: ISZERO 0000023b: PUSH2 0x0245 0000023e: JUMPI 0000023f: PUSH1 0x00 00000241: DUP5 00000242: DUP5 00000243: ADD 00000244: MSTORE 00000245: JUMPDEST 00000246: POP 00000247: POP 00000248: POP 00000249: POP 0000024a: JUMP 0000024b: INVALID 0000024c: COINBASE 0000024d: PUSH5 0x6472657373 00000253: GASPRICE 00000254: KECCAK256 00000255: PUSH13 0x6f772d6c6576656c2064656c65 00000263: PUSH8 0x6174652063616c6c 0000026c: KECCAK256 0000026d: PUSH7 0x61696c6564a264 00000275: PUSH10 0x706673582212209b8470 00000280: CREATE 00000281: PUSH15 0x8a3960c912103fc2be177edaad6958 00000291: UNKNOWN(0x4E) 00000292: UNKNOWN(0xE3) 00000293: UNKNOWN(0xC7) 00000294: UNKNOWN(0xD2) 00000295: DUP1 00000296: SWAP15 00000297: UNKNOWN(0xE7) 00000298: CALLDATACOPY 00000299: UNKNOWN(0xE7) 0000029a: SWAP5 0000029b: ADDMOD 0000029c: UNKNOWN(0xE7) 0000029d: PUSH5 0x736f6c6343 000002a3: STOP 000002a4: ADDMOD 000002a5: MUL 000002a6: STOP 000002a7: CALLER
| Severity | Category | Tool | Title | Confidence | Validated | Confirmed | Details |
|---|---|---|---|---|---|---|---|
| critical | upgradeability | detector | Untrusted DELEGATECALL target reachable | 70 | no | no |
viewtrace_id: 0xe289a5a8544c7d688fce39bf115b46f295aa208cbb97e4c77d55192835ae40f3
call_targets:
0x438285fbccba55ce8cdef276030e6b35a0b65b6b
target_varies:
no
classification:
constant_target
validation_json{
"sink": "DELEGATECALL",
"errors": 0,
"status": "sink_reached",
"attempts": 1,
"trace_id": "0xe289a5a8544c7d688fce39bf115b46f295aa208cbb97e4c77d55192835ae40f3",
"confirmed": false,
"trace_mode": "callTracer",
"call_targets": [
"0x438285fbccba55ce8cdef276030e6b35a0b65b6b"
],
"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": 164,
"opcode": "DELEGATECALL",
"returndata_checked": null,
"value_expression_category": "n/a",
"target_expression_category": "computed"
},
{
"pc": 325,
"opcode": "DELEGATECALL",
"returndata_checked": null,
"value_expression_category": "n/a",
"target_expression_category": "computed"
}
],
"guards_detected": [],
"delegatecall_count": 2,
"untrusted_delegatecall_count": 2
}
|
| medium | auth | codex | Signatures are not bound to the bridge contract, enabling cross-contract replay | 75 | no | — |
viewevidence_json{
"evidence": "`claimToken` builds `_claimId` from origin token, recipient, amount, chainIds, txHash, name/symbol/decimals only, and `verifySignatures` checks this hash without any contract/domain binding.",
"locations": [
"contracts/generic/GenericBridge.sol"
],
"recommendation": "Include `address(this)` (and optionally chainId) in the signed payload, or switch to EIP-712 with a domain separator bound to the contract address. Ensure both `claimToken` and `DTOBridgeToken.claimBridgeToken` compute claim IDs with the same domain binding.",
"exploit_scenario": "If validators sign a claim for one GenericBridge deployment, an attacker can reuse the same signatures on a second GenericBridge instance on the same chain (or a redeployed instance with the same validator set) because the signed message omits `address(this)`. This can mint/withdraw assets from the unintended bridge instance."
}
|
| medium | upgradeability | cast | DELEGATECALL present | 80 | no | — |
viewevidence_json{
"notes": "delegatecall enables execution in caller context; common in proxies/upgradeable patterns",
"delegatecall_count": 2
}
|
| medium | other | detector | CREATE/CREATE2 reachable | 45 | no | no |
viewtrace_id: 0x22d8eb680a9beef109971d1166a20e6fb9a74d43497148f156c495b2aa9474fe
validation_json{
"sink": "CREATE",
"errors": 0,
"status": "unknown",
"attempts": 1,
"trace_id": "0x22d8eb680a9beef109971d1166a20e6fb9a74d43497148f156c495b2aa9474fe",
"confirmed": false,
"trace_mode": "structLogs",
"call_targets": null,
"matched_probe": null,
"target_varies": null,
"classification": "no_sink"
}
witness_json{
"notes": "heuristic witness; entrypoints are best-effort selectors with zeroed calldata",
"constraints": [],
"entrypoints": [
{
"calldata": "0x",
"selector": "fallback",
"calldata_variants": [
"0x"
]
}
]
}
evidence_json{
"create_count": 1,
"create2_count": 0
}
|
| low | other | cast | Contract creation opcode present | 60 | no | — |
viewevidence_json{
"notes": "runtime can deploy contracts dynamically via CREATE/CREATE2",
"create_count": 1,
"create2_count": 0
}
|