019bab3b-aaee-7307-8a62-f0c903f3c8f8
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 |
|---|---|---|---|---|
| 38429 | artifact.fetch | complete | 1 / 3 | 3 months ago |
| 38430 | proxy.resolve | complete | 1 / 3 | 3 months ago |
| 38431 | tool.cast_disasm | complete | 1 / 3 | 3 months ago |
| 38432 | analysis.bundle | complete | 1 / 3 | 3 months ago |
| 38433 | capability.graph | complete | 1 / 3 | 3 months ago |
| 38434 | detector.run | complete | 1 / 3 | 3 months ago |
| 38435 | validation.fork | complete | 1 / 3 | 3 months ago |
| 38996 | report.consolidate | complete | 1 / 6 | 3 months ago |
| 38997 | tool.slither | failed | 2 / 2 | 3 months ago |
{
"method": "etherscan+onchain",
"status": "confirmed",
"etherscan_hint": {
"source": "etherscan",
"etherscan": {
"proxy_flag": true,
"implementation": "0x68fe80c6e97e0c8613e2fed344358c6635ba5366"
}
},
"implementation": "0x68fe80c6e97e0c8613e2fed344358c6635ba5366",
"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-_c1aj8zf)
'forge config --json' running
'forge build --build-info --skip ./test/** ./script/** --force' running (wd: /tmp/slither-_c1aj8zf)
'forge' returned non-zero exit code 1
Error: Encountered invalid solc version in src/UUPSProxy.sol: No solc version exists that matches the version requirement: =0.8.13
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-_c1aj8zf/out/build-info is not a directory.
{"no_findings":false,"summary":"Found 2 issues in the LiquidityPool implementation: missing BNFT-holder authorization and a division-by-zero DoS in fund source allocation.","findings":[{"severity":"high","category":"access_control","title":"Unregistered address can execute BNFT deposit flow","exploit_scenario":"Any address with no BNFT registration has `bnftHoldersIndexes[msg.sender].index == 0` by default. If the current scheduling window includes index 0, that address can call `batchDepositAsBnftHolder` and pass the assignment/timestamp checks, forcing the pool to supply 30 ETH per validator while only posting 2 ETH, and can lock out the legitimate holder at index 0 by updating its timestamp.","recommendation":"Require `bnftHoldersIndexes[msg.sender].registered` and/or check that `bnftHolders[index].holder == msg.sender` before allowing BNFT deposits.","evidence":"`batchDepositAsBnftHolder` uses `bnftHoldersIndexes[msg.sender].index` and performs assignment/timestamp checks but never validates `registered` or holder identity.","locations":["src/LiquidityPool.sol:257","src/LiquidityPool.sol:260","src/LiquidityPool.sol:264","src/LiquidityPool.sol:265"]},{"severity":"low","category":"math","title":"Division-by-zero DoS in fund source allocation","exploit_scenario":"If `fundStatistics[ETHER_FAN].numberOfValidators` or `fundStatistics[ETHER_FAN].targetWeight` is zero (initially or after decreases), `allocateSourceOfFunds()` reverts. This blocks `batchDepositAsBnftHolder`, halting BNFT deposits until an admin fixes the values.","recommendation":"Guard against zero denominators (e.g., if either is zero, default to the other source or require initialization before use).","evidence":"`allocateSourceOfFunds()` divides by `fundStatistics[SourceOfFunds.ETHER_FAN].numberOfValidators` and `.targetWeight` with no zero checks.","locations":["src/LiquidityPool.sol:639","src/LiquidityPool.sol:640"]}]}
OpenAI Codex v0.77.0 (research preview)
--------
workdir: /tmp/codex-hcn7ma47
model: gpt-5.2-codex
provider: openai
approval: never
sandbox: read-only
reasoning effort: high
reasoning summaries: auto
session id: 019bab7d-dd16-73b3-8fd6-6bec968cb6c2
--------
user
Context: The user requested the proxy at 0x00c452affee3a17d9cecc1bcd2b8d5c7635c4cb9.
Audit the implementation at 0x68fe80c6e97e0c8613e2fed344358c6635ba5366.
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 'cat /tmp/codex-hcn7ma47/AUDIT_BUNDLE.txt' in /tmp/codex-hcn7ma47 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: src/AuctionManager.sol
================================================================================
// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;
import "./interfaces/IAuctionManager.sol";
import "./interfaces/INodeOperatorManager.sol";
import "./interfaces/IProtocolRevenueManager.sol";
import "@openzeppelin-upgradeable/contracts/security/ReentrancyGuardUpgradeable.sol";
import "@openzeppelin-upgradeable/contracts/security/PausableUpgradeable.sol";
import "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol";
import "@openzeppelin-upgradeable/contracts/proxy/utils/Initializable.sol";
import "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol";
contract AuctionManager is
Initializable,
thinking
**Investigating full contract files**
exec
/bin/bash -lc 'rg -n "''^FILE:" /tmp/codex-hcn7ma47/AUDIT_BUNDLE.txt' in /tmp/codex-hcn7ma47 succeeded in 7ms:
5:FILE: src/AuctionManager.sol
377:FILE: src/LiquidityPool.sol
1111:FILE: src/interfaces/IAuctionManager.sol
1161:FILE: src/interfaces/IEtherFiAdmin.sol
1173:FILE: src/interfaces/IEtherFiNode.sol
1269:FILE: src/interfaces/IEtherFiNodesManager.sol
1351:FILE: src/interfaces/ILiquidityPool.sol
1434:FILE: src/interfaces/IMembershipManager.sol
1528:FILE: src/interfaces/INodeOperatorManager.sol
1579:FILE: src/interfaces/IProtocolRevenueManager.sol
1597:FILE: src/interfaces/IRegulationsManager.sol
1618:FILE: src/interfaces/IStakingManager.sol
1664:FILE: src/interfaces/ITNFT.sol
1682:FILE: src/interfaces/IWithdrawRequestNFT.sol
1708:FILE: src/interfaces/IeETH.sol
thinking
**Examining implementation contract code**
exec
/bin/bash -lc "sed -n '1,260p' /tmp/codex-hcn7ma47/src/LiquidityPool.sol" in /tmp/codex-hcn7ma47 succeeded in 6ms:
// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;
import "@openzeppelin-upgradeable/contracts/token/ERC20/IERC20Upgradeable.sol";
import "@openzeppelin-upgradeable/contracts/token/ERC721/IERC721ReceiverUpgradeable.sol";
import "@openzeppelin-upgradeable/contracts/proxy/utils/Initializable.sol";
import "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol";
import "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol";
import "./interfaces/IRegulationsManager.sol";
import "./interfaces/IStakingManager.sol";
import "./interfaces/IEtherFiNodesManager.sol";
import "./interfaces/IeETH.sol";
import "./interfaces/IStakingManager.sol";
import "./interfaces/IMembershipManager.sol";
import "./interfaces/ITNFT.sol";
import "./interfaces/IWithdrawRequestNFT.sol";
import "./interfaces/ILiquidityPool.sol";
import "./interfaces/IEtherFiAdmin.sol";
thinking
**Requesting more file content**
exec
/bin/bash -lc "sed -n '260,620p' /tmp/codex-hcn7ma47/src/LiquidityPool.sol" in /tmp/codex-hcn7ma47 succeeded in 14ms:
uint32 index = bnftHoldersIndexes[msg.sender].index;
//Need to make sure the BNFT player is assigned for the current period
//See function for details
require(isAssigned(firstIndex, lastIndex, index), "Not assigned");
require(bnftHolders[index].timestamp < uint32(getCurrentSchedulingStartTimestamp()), "Already deposited");
require(msg.value == _numberOfValidators * 2 ether, "Deposit 2 ETH per validator");
require(totalValueInLp + msg.value >= 32 ether * _numberOfValidators, "Not enough balance");
//BNFT players are eligible to spin up anything up to the max amount of validators allowed (maxValidatorsPerOwner),
if(_numberOfValidators > maxValidatorsPerOwner) revert AboveMaxAllocation();
//Funds in the LP can come from our membership strategy or the eEth staking strategy. We select which source of funds will
//be used for spinning up these deposited ids. See the function for more detail on how we do this.
SourceOfFunds _source = allocateSourceOfFunds();
fundStatistics[_source].numberOfValidators += uint32(_numberOfValidators);
uint256 amountFromLp = 30 ether * _numberOfValidators;
if (amountFromLp > type(uint128).max) revert InvalidAmount();
exec
/bin/bash -lc "sed -n '620,980p' /tmp/codex-hcn7ma47/src/LiquidityPool.sol" in /tmp/codex-hcn7ma47 succeeded in 7ms:
if (totalPooledEther == 0) {
return _depositAmount;
}
return (_depositAmount * eETH.totalShares()) / totalPooledEther;
}
function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}
//--------------------------------------------------------------------------------------
//------------------------------------ GETTERS ---------------------------------------
//--------------------------------------------------------------------------------------
/// @notice Selects a source of funds to be used for the deposits
/// @dev The LP has two ways of accumulating funds, through eEth staking and through the ether fan page (membership manager).
/// We want to manipulate which funds we use per deposit. Example, if someone is making 2 deposits, we want to select where the 60 ETH
/// should come from. The funds will all be held in the LP but we are storing how many validators are spun up per source on the contract.
/// We simply check which of the sources is below their target allocation and allocate the deposits to it.
/// @return The chosen source of funds (EETH or ETHER_FAN)
function allocateSourceOfFunds() public view returns (SourceOfFunds) {
uint256 validatorRatio = (fundStatistics[SourceOfFunds.EETH].numberOfValidators * 10_000) / fundStatistics[SourceOfFunds.ETHER_FAN].numberOfValidators;
thinking
**Analyzing contracts for vulnerabilities**
I'm examining AuctionManager and LiquidityPool for potential issues like reentrancy, access control, division by zero, and asset accounting quirks. I'll pay close attention to external calls, permission checks, numeric edge cases, and trust assumptions to highlight possible risks or misconfigurations.
thinking
**Distinguishing implementation focus and key risks**
I'm confirming that the address corresponds to LiquidityPool as the implementation to audit, setting aside AuctionManager unless otherwise specified. My focus is on identifying critical issues like missing access control in batchDepositAsBnftHolder allowing unauthorized deposits, DoS risks from division by zero, potential oracle manipulation via timestamp-based scheduling, and pool accounting nuances around ETH deposits and withdrawals.
thinking
**Analyzing fund refund and access control nuances**
I'm untangling how user refunds for failed validators affect pool accounting and spotting potential misalignments in totalValueInLp and totalValueOutOfLp updates. I’m also reviewing access controls in deposit cancellation and batch deposit functions, noting missing checks that could let unauthorized actors interact improperly, plus subtle DoS and state sync concerns tied to ETH handling and whitelist logic.
thinking
**Summarizing primary BNFT deposit vulnerability**
I'm narrowing down to the main issue in LiquidityPool: a missing registration check that lets unregistered addresses call batchDepositAsBnftHolder and misuse BNFT slots, risking LP funds. I plan to reference specific source lines to clarify this critical access control flaw.
exec
/bin/bash -lc "nl -ba /tmp/codex-hcn7ma47/src/LiquidityPool.sol | sed -n '250,340p'" in /tmp/codex-hcn7ma47 succeeded in 8ms:
250
251 /// @notice Allows a BNFT player to deposit their 2 ETH and pair with 30 ETH from the LP
252 /// @dev This function has multiple dependencies that need to be followed before this function will succeed.
253 /// @param _candidateBidIds validator IDs that have been matched with the BNFT holder on the FE
254 /// @param _numberOfValidators how many validators the user wants to spin up. This can be less than the candidateBidIds length.
255 /// we may have more Ids sent in than needed to spin up incase some ids fail.
256 /// @return Array of bids that were successfully processed.
257 function batchDepositAsBnftHolder(uint256[] calldata _candidateBidIds, uint256 _numberOfValidators) external payable whenNotPaused returns (uint256[] memory){
258 //Checking which indexes form the schedule for the current scheduling period.
259 (uint256 firstIndex, uint128 lastIndex) = dutyForWeek();
260 uint32 index = bnftHoldersIndexes[msg.sender].index;
261
262 //Need to make sure the BNFT player is assigned for the current period
263 //See function for details
264 require(isAssigned(firstIndex, lastIndex, index), "Not assigned");
265 require(bnftHolders[index].timestamp < uint32(getCurrentSchedulingStartTimestamp()), "Already deposited");
266 require(msg.value == _numberOfValidators * 2 ether, "Deposit 2 ETH per validator");
267 require(totalValueInLp + msg.value >= 32 ether * _numberOfValidators, "Not enough balance");
268
269 //BNFT players are eligible to spin up anything up to the max amount of validators allowed (maxValidatorsPerOwner),
thinking
**Identifying potential issues in code**
exec
/bin/bash -lc "nl -ba /tmp/codex-hcn7ma47/src/LiquidityPool.sol | sed -n '640,720p'" in /tmp/codex-hcn7ma47 succeeded in 15ms:
640 uint256 weightRatio = (fundStatistics[SourceOfFunds.EETH].targetWeight * 10_000) / fundStatistics[SourceOfFunds.ETHER_FAN].targetWeight;
641
642 return validatorRatio > weightRatio ? SourceOfFunds.ETHER_FAN : SourceOfFunds.EETH;
643 }
644
645 /// @notice Fetching the starting timestamp of the current scheduling period
646 /// @return The timestamp of the begging of the current scheduling period
647 function getCurrentSchedulingStartTimestamp() public view returns (uint256) {
648 return block.timestamp - (block.timestamp % schedulingPeriodInSeconds);
649 }
650
651 /// @notice Checks whether the BNFT player with _index is assigned
652 /// @dev Because we allow a sliding window type selection, we use strict conditions to check whether the provided index is
653 /// inside the first and last index.
654 /// @param _firstIndex The index of the first selected BNFT holder
655 /// @param _lastIndex The index of the last selected BNFT holder
656 /// @param _index The index of the BNFT we are checking
657 /// @return Bool value if the BNFT player is assigned or not
658 function isAssigned(uint256 _firstIndex, uint128 _lastIndex, uint256 _index) public view returns (bool) {
659 if(_lastIndex < _firstIndex) {
thinking
**Summarizing audit findings and assumptions**
I'm gathering and organizing audit findings on LiquidityPool, focusing on potential high-severity access control flaws around unregistered BNFT holders, and low-severity division-by-zero DoS risks in fund allocation. I'm also clarifying assumptions on contract addresses and preparing a concise JSON report with categorized findings and evidence.
codex
{"no_findings":false,"summary":"Found 2 issues in the LiquidityPool implementation: missing BNFT-holder authorization and a division-by-zero DoS in fund source allocation.","findings":[{"severity":"high","category":"access_control","title":"Unregistered address can execute BNFT deposit flow","exploit_scenario":"Any address with no BNFT registration has `bnftHoldersIndexes[msg.sender].index == 0` by default. If the current scheduling window includes index 0, that address can call `batchDepositAsBnftHolder` and pass the assignment/timestamp checks, forcing the pool to supply 30 ETH per validator while only posting 2 ETH, and can lock out the legitimate holder at index 0 by updating its timestamp.","recommendation":"Require `bnftHoldersIndexes[msg.sender].registered` and/or check that `bnftHolders[index].holder == msg.sender` before allowing BNFT deposits.","evidence":"`batchDepositAsBnftHolder` uses `bnftHoldersIndexes[msg.sender].index` and performs assignment/timestamp checks but never validates `registered` or holder identity.","locations":["src/LiquidityPool.sol:257","src/LiquidityPool.sol:260","src/LiquidityPool.sol:264","src/LiquidityPool.sol:265"]},{"severity":"low","category":"math","title":"Division-by-zero DoS in fund source allocation","exploit_scenario":"If `fundStatistics[ETHER_FAN].numberOfValidators` or `fundStatistics[ETHER_FAN].targetWeight` is zero (initially or after decreases), `allocateSourceOfFunds()` reverts. This blocks `batchDepositAsBnftHolder`, halting BNFT deposits until an admin fixes the values.","recommendation":"Guard against zero denominators (e.g., if either is zero, default to the other source or require initialization before use).","evidence":"`allocateSourceOfFunds()` divides by `fundStatistics[SourceOfFunds.ETHER_FAN].numberOfValidators` and `.targetWeight` with no zero checks.","locations":["src/LiquidityPool.sol:639","src/LiquidityPool.sol:640"]}]}
tokens used
75,198
{
"codex": {
"ran_at": "2026-01-11T05:22:50.709297+00:00",
"returncode": 0
},
"project": {
"mode": "source",
"file_count": 46,
"import_count": 52,
"first_party_contracts_count": 15
},
"summary": "Found 2 issues in the LiquidityPool implementation: missing BNFT-holder authorization and a division-by-zero DoS in fund source allocation.",
"raw_final": {
"summary": "Found 2 issues in the LiquidityPool implementation: missing BNFT-holder authorization and a division-by-zero DoS in fund source allocation.",
"findings": [
{
"title": "Unregistered address can execute BNFT deposit flow",
"category": "access_control",
"evidence": "`batchDepositAsBnftHolder` uses `bnftHoldersIndexes[msg.sender].index` and performs assignment/timestamp checks but never validates `registered` or holder identity.",
"severity": "high",
"locations": [
"src/LiquidityPool.sol:257",
"src/LiquidityPool.sol:260",
"src/LiquidityPool.sol:264",
"src/LiquidityPool.sol:265"
],
"recommendation": "Require `bnftHoldersIndexes[msg.sender].registered` and/or check that `bnftHolders[index].holder == msg.sender` before allowing BNFT deposits.",
"exploit_scenario": "Any address with no BNFT registration has `bnftHoldersIndexes[msg.sender].index == 0` by default. If the current scheduling window includes index 0, that address can call `batchDepositAsBnftHolder` and pass the assignment/timestamp checks, forcing the pool to supply 30 ETH per validator while only posting 2 ETH, and can lock out the legitimate holder at index 0 by updating its timestamp."
},
{
"title": "Division-by-zero DoS in fund source allocation",
"category": "math",
"evidence": "`allocateSourceOfFunds()` divides by `fundStatistics[SourceOfFunds.ETHER_FAN].numberOfValidators` and `.targetWeight` with no zero checks.",
"severity": "low",
"locations": [
"src/LiquidityPool.sol:639",
"src/LiquidityPool.sol:640"
],
"recommendation": "Guard against zero denominators (e.g., if either is zero, default to the other source or require initialization before use).",
"exploit_scenario": "If `fundStatistics[ETHER_FAN].numberOfValidators` or `fundStatistics[ETHER_FAN].targetWeight` is zero (initially or after decreases), `allocateSourceOfFunds()` reverts. This blocks `batchDepositAsBnftHolder`, halting BNFT deposits until an admin fixes the values."
}
],
"no_findings": false
},
"no_findings": false,
"proxy_context": {
"proxy_run_id": "019bab3b-aaee-7307-8a62-f0c903f3c8f8",
"proxy_address": "0x00c452affee3a17d9cecc1bcd2b8d5c7635c4cb9",
"implementation_run_id": "019bab3c-a6af-702e-81df-bc4bc14e96dc",
"implementation_address": "0x68fe80c6e97e0c8613e2fed344358c6635ba5366"
},
"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 0x0074 00000021: JUMP 00000022: JUMPDEST 00000023: PUSH2 0x00b9 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 0x02f1 00000046: PUSH1 0x27 00000048: SWAP2 00000049: CODECOPY 0000004a: PUSH2 0x00dd 0000004d: JUMP 0000004e: JUMPDEST 0000004f: SWAP4 00000050: SWAP3 00000051: POP 00000052: POP 00000053: POP 00000054: JUMP 00000055: JUMPDEST 00000056: PUSH20 0xffffffffffffffffffffffffffffffffffffffff 0000006b: AND 0000006c: EXTCODESIZE 0000006d: ISZERO 0000006e: ISZERO 0000006f: SWAP1 00000070: JUMP 00000071: JUMPDEST 00000072: SWAP1 00000073: JUMP 00000074: JUMPDEST 00000075: PUSH1 0x00 00000077: PUSH2 0x00b4 0000007a: PUSH32 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc 0000009b: SLOAD 0000009c: PUSH20 0xffffffffffffffffffffffffffffffffffffffff 000000b1: AND 000000b2: SWAP1 000000b3: JUMP 000000b4: JUMPDEST 000000b5: SWAP1 000000b6: POP 000000b7: SWAP1 000000b8: JUMP 000000b9: JUMPDEST 000000ba: CALLDATASIZE 000000bb: PUSH1 0x00 000000bd: DUP1 000000be: CALLDATACOPY 000000bf: PUSH1 0x00 000000c1: DUP1 000000c2: CALLDATASIZE 000000c3: PUSH1 0x00 000000c5: DUP5 000000c6: GAS 000000c7: DELEGATECALL 000000c8: RETURNDATASIZE 000000c9: PUSH1 0x00 000000cb: DUP1 000000cc: RETURNDATACOPY 000000cd: DUP1 000000ce: DUP1 000000cf: ISZERO 000000d0: PUSH2 0x00d8 000000d3: JUMPI 000000d4: RETURNDATASIZE 000000d5: PUSH1 0x00 000000d7: RETURN 000000d8: JUMPDEST 000000d9: RETURNDATASIZE 000000da: PUSH1 0x00 000000dc: REVERT 000000dd: JUMPDEST 000000de: PUSH1 0x60 000000e0: PUSH1 0x00 000000e2: DUP1 000000e3: DUP6 000000e4: PUSH20 0xffffffffffffffffffffffffffffffffffffffff 000000f9: AND 000000fa: DUP6 000000fb: PUSH1 0x40 000000fd: MLOAD 000000fe: PUSH2 0x0107 00000101: SWAP2 00000102: SWAP1 00000103: PUSH2 0x0283 00000106: JUMP 00000107: JUMPDEST 00000108: PUSH1 0x00 0000010a: PUSH1 0x40 0000010c: MLOAD 0000010d: DUP1 0000010e: DUP4 0000010f: SUB 00000110: DUP2 00000111: DUP6 00000112: GAS 00000113: DELEGATECALL 00000114: SWAP2 00000115: POP 00000116: POP 00000117: RETURNDATASIZE 00000118: DUP1 00000119: PUSH1 0x00 0000011b: DUP2 0000011c: EQ 0000011d: PUSH2 0x0142 00000120: JUMPI 00000121: PUSH1 0x40 00000123: MLOAD 00000124: SWAP2 00000125: POP 00000126: PUSH1 0x1f 00000128: NOT 00000129: PUSH1 0x3f 0000012b: RETURNDATASIZE 0000012c: ADD 0000012d: AND 0000012e: DUP3 0000012f: ADD 00000130: PUSH1 0x40 00000132: MSTORE 00000133: RETURNDATASIZE 00000134: DUP3 00000135: MSTORE 00000136: RETURNDATASIZE 00000137: PUSH1 0x00 00000139: PUSH1 0x20 0000013b: DUP5 0000013c: ADD 0000013d: RETURNDATACOPY 0000013e: PUSH2 0x0147 00000141: JUMP 00000142: JUMPDEST 00000143: PUSH1 0x60 00000145: SWAP2 00000146: POP 00000147: JUMPDEST 00000148: POP 00000149: SWAP2 0000014a: POP 0000014b: SWAP2 0000014c: POP 0000014d: PUSH2 0x0158 00000150: DUP7 00000151: DUP4 00000152: DUP4 00000153: DUP8 00000154: PUSH2 0x0162 00000157: JUMP 00000158: JUMPDEST 00000159: SWAP7 0000015a: SWAP6 0000015b: POP 0000015c: POP 0000015d: POP 0000015e: POP 0000015f: POP 00000160: POP 00000161: JUMP 00000162: JUMPDEST 00000163: PUSH1 0x60 00000165: DUP4 00000166: ISZERO 00000167: PUSH2 0x01fd 0000016a: JUMPI 0000016b: DUP3 0000016c: MLOAD 0000016d: PUSH1 0x00 0000016f: SUB 00000170: PUSH2 0x01f6 00000173: JUMPI 00000174: PUSH20 0xffffffffffffffffffffffffffffffffffffffff 00000189: DUP6 0000018a: AND 0000018b: EXTCODESIZE 0000018c: PUSH2 0x01f6 0000018f: JUMPI 00000190: PUSH1 0x40 00000192: MLOAD 00000193: PUSH32 0x08c379a000000000000000000000000000000000000000000000000000000000 000001b4: DUP2 000001b5: MSTORE 000001b6: PUSH1 0x20 000001b8: PUSH1 0x04 000001ba: DUP3 000001bb: ADD 000001bc: MSTORE 000001bd: PUSH1 0x1d 000001bf: PUSH1 0x24 000001c1: DUP3 000001c2: ADD 000001c3: MSTORE 000001c4: PUSH32 0x416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000 000001e5: PUSH1 0x44 000001e7: DUP3 000001e8: ADD 000001e9: MSTORE 000001ea: PUSH1 0x64 000001ec: ADD 000001ed: JUMPDEST 000001ee: PUSH1 0x40 000001f0: MLOAD 000001f1: DUP1 000001f2: SWAP2 000001f3: SUB 000001f4: SWAP1 000001f5: REVERT 000001f6: JUMPDEST 000001f7: POP 000001f8: DUP2 000001f9: PUSH2 0x0207 000001fc: JUMP 000001fd: JUMPDEST 000001fe: PUSH2 0x0207 00000201: DUP4 00000202: DUP4 00000203: PUSH2 0x020f 00000206: JUMP 00000207: JUMPDEST 00000208: SWAP5 00000209: SWAP4 0000020a: POP 0000020b: POP 0000020c: POP 0000020d: POP 0000020e: JUMP 0000020f: JUMPDEST 00000210: DUP2 00000211: MLOAD 00000212: ISZERO 00000213: PUSH2 0x021f 00000216: JUMPI 00000217: DUP2 00000218: MLOAD 00000219: DUP1 0000021a: DUP4 0000021b: PUSH1 0x20 0000021d: ADD 0000021e: REVERT 0000021f: JUMPDEST 00000220: DUP1 00000221: PUSH1 0x40 00000223: MLOAD 00000224: PUSH32 0x08c379a000000000000000000000000000000000000000000000000000000000 00000245: DUP2 00000246: MSTORE 00000247: PUSH1 0x04 00000249: ADD 0000024a: PUSH2 0x01ed 0000024d: SWAP2 0000024e: SWAP1 0000024f: PUSH2 0x029f 00000252: JUMP 00000253: JUMPDEST 00000254: PUSH1 0x00 00000256: JUMPDEST 00000257: DUP4 00000258: DUP2 00000259: LT 0000025a: ISZERO 0000025b: PUSH2 0x026e 0000025e: JUMPI 0000025f: DUP2 00000260: DUP2 00000261: ADD 00000262: MLOAD 00000263: DUP4 00000264: DUP3 00000265: ADD 00000266: MSTORE 00000267: PUSH1 0x20 00000269: ADD 0000026a: PUSH2 0x0256 0000026d: JUMP 0000026e: JUMPDEST 0000026f: DUP4 00000270: DUP2 00000271: GT 00000272: ISZERO 00000273: PUSH2 0x027d 00000276: JUMPI 00000277: PUSH1 0x00 00000279: DUP5 0000027a: DUP5 0000027b: ADD 0000027c: MSTORE 0000027d: JUMPDEST 0000027e: POP 0000027f: POP 00000280: POP 00000281: POP 00000282: JUMP 00000283: JUMPDEST 00000284: PUSH1 0x00 00000286: DUP3 00000287: MLOAD 00000288: PUSH2 0x0295 0000028b: DUP2 0000028c: DUP5 0000028d: PUSH1 0x20 0000028f: DUP8 00000290: ADD 00000291: PUSH2 0x0253 00000294: JUMP 00000295: JUMPDEST 00000296: SWAP2 00000297: SWAP1 00000298: SWAP2 00000299: ADD 0000029a: SWAP3 0000029b: SWAP2 0000029c: POP 0000029d: POP 0000029e: JUMP 0000029f: JUMPDEST 000002a0: PUSH1 0x20 000002a2: DUP2 000002a3: MSTORE 000002a4: PUSH1 0x00 000002a6: DUP3 000002a7: MLOAD 000002a8: DUP1 000002a9: PUSH1 0x20 000002ab: DUP5 000002ac: ADD 000002ad: MSTORE 000002ae: PUSH2 0x02be 000002b1: DUP2 000002b2: PUSH1 0x40 000002b4: DUP6 000002b5: ADD 000002b6: PUSH1 0x20 000002b8: DUP8 000002b9: ADD 000002ba: PUSH2 0x0253 000002bd: JUMP 000002be: JUMPDEST 000002bf: PUSH1 0x1f 000002c1: ADD 000002c2: PUSH32 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0 000002e3: AND 000002e4: SWAP2 000002e5: SWAP1 000002e6: SWAP2 000002e7: ADD 000002e8: PUSH1 0x40 000002ea: ADD 000002eb: SWAP3 000002ec: SWAP2 000002ed: POP 000002ee: POP 000002ef: JUMP 000002f0: INVALID 000002f1: COINBASE 000002f2: PUSH5 0x6472657373 000002f8: GASPRICE 000002f9: KECCAK256 000002fa: PUSH13 0x6f772d6c6576656c2064656c65 00000308: PUSH8 0x6174652063616c6c 00000311: KECCAK256 00000312: PUSH7 0x61696c6564a264 0000031a: PUSH10 0x706673582212209a37d8 00000325: DIV 00000326: UNKNOWN(0xD4) 00000327: UNKNOWN(0x0F) 00000328: SWAP14 00000329: SGT 0000032a: DUP13 0000032b: UNKNOWN(0x0F) 0000032c: SUB 0000032d: UNKNOWN(0xCA) 0000032e: PUSH29 0xd03e999e9f9e1d34d86db16c353d9b56c900ab64736f6c634300080d00 0000034c: CALLER
| Severity | Category | Tool | Title | Confidence | Validated | Confirmed | Details |
|---|---|---|---|---|---|---|---|
| critical | upgradeability | detector | Untrusted DELEGATECALL target reachable | 70 | no | no |
viewtrace_id: 0x6eab753f50fd2457a5e7aa2bb7a16fdcf4224a9455246a9c77078a64f73e9b70
call_targets:
0x68fe80c6e97e0c8613e2fed344358c6635ba5366
target_varies:
no
classification:
constant_target
validation_json{
"sink": "DELEGATECALL",
"errors": 0,
"status": "sink_reached",
"attempts": 1,
"trace_id": "0x6eab753f50fd2457a5e7aa2bb7a16fdcf4224a9455246a9c77078a64f73e9b70",
"confirmed": false,
"trace_mode": "callTracer",
"call_targets": [
"0x68fe80c6e97e0c8613e2fed344358c6635ba5366"
],
"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": 199,
"opcode": "DELEGATECALL",
"returndata_checked": null,
"value_expression_category": "n/a",
"target_expression_category": "computed"
},
{
"pc": 275,
"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 | Unregistered address can execute BNFT deposit flow | 85 | no | — |
viewevidence_json{
"evidence": "`batchDepositAsBnftHolder` uses `bnftHoldersIndexes[msg.sender].index` and performs assignment/timestamp checks but never validates `registered` or holder identity.",
"locations": [
"src/LiquidityPool.sol:257",
"src/LiquidityPool.sol:260",
"src/LiquidityPool.sol:264",
"src/LiquidityPool.sol:265"
],
"recommendation": "Require `bnftHoldersIndexes[msg.sender].registered` and/or check that `bnftHolders[index].holder == msg.sender` before allowing BNFT deposits.",
"exploit_scenario": "Any address with no BNFT registration has `bnftHoldersIndexes[msg.sender].index == 0` by default. If the current scheduling window includes index 0, that address can call `batchDepositAsBnftHolder` and pass the assignment/timestamp checks, forcing the pool to supply 30 ETH per validator while only posting 2 ETH, and can lock out the legitimate holder at index 0 by updating its timestamp."
}
|
| 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 | math | codex | Division-by-zero DoS in fund source allocation | 65 | no | — |
viewevidence_json{
"evidence": "`allocateSourceOfFunds()` divides by `fundStatistics[SourceOfFunds.ETHER_FAN].numberOfValidators` and `.targetWeight` with no zero checks.",
"locations": [
"src/LiquidityPool.sol:639",
"src/LiquidityPool.sol:640"
],
"recommendation": "Guard against zero denominators (e.g., if either is zero, default to the other source or require initialization before use).",
"exploit_scenario": "If `fundStatistics[ETHER_FAN].numberOfValidators` or `fundStatistics[ETHER_FAN].targetWeight` is zero (initially or after decreases), `allocateSourceOfFunds()` reverts. This blocks `batchDepositAsBnftHolder`, halting BNFT deposits until an admin fixes the values."
}
|