Skip to content

Instantly share code, notes, and snippets.

View CharaD7's full-sized avatar
๐Ÿ 
Working from home

Joy Ayitey CharaD7

๐Ÿ 
Working from home
View GitHub Profile
@CharaD7
CharaD7 / AUDIT_REPORT.md
Created September 24, 2026 10:15
Aera Protocol Audit Report - Full findings and evidence

Aera Protocol Audit Report

Date: 2026-09-22 Program: Aera (Immunefi, Max Bounty: $500K) Scope: 29 in-scope targets across Ethereum, Arbitrum, Optimism, Base, Morph L2 Method: Static analysis, ChainScope graph analysis (1229 nodes, 2024 edges), source code review Affected Deployed Assets:

  • Finding 1 (BaseFeeCalculator/PriceAndFeeCalculator): Base 0x69dd4d44eed6bbc33b8a0bdfe17897ab9044372e, Arbitrum 0xd61ecfB5cEd67Ef4F01E0dfae591c838BfA33932, Optimism 0xfb6De307b11C50D8B8A0790cd5c82c620D574440, Ethereum 0x8F3FfA11CD5915f0E869192663b905504A2Ef4a5
  • Finding 3 (Provisioner): Base 0x18cf8d963e1a727f9bbf3aeffa0bd04fb4dbda07, Arbitrum 0xdd4a42603E6d8E515C3468789375A98c376821b3, Optimism 0xcc923371F0d3A9cA75d98E767Df9dE1cdf5799Ef, Ethereum 0x74C4A66CE4F4779B11E7c63D42e51EEef3A80D11, 0xd580c26F7bD8A8a66fd32a97Df2308C083b65d9c Deployed Assets:
@CharaD7
CharaD7 / Finding3_MissingNonReentrant.t.sol
Created September 24, 2026 10:15
Finding 3: Missing nonReentrant on Provisioner - Verified PoC (3 tests passing)
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.29;
import {Test} from "forge-std/Test.sol";
import {console} from "forge-std/console.sol";
import {IERC20} from "src/interfaces/IERC20.sol";
import {ReentrancyGuardTransient} from "@oz/utils/ReentrancyGuardTransient.sol";
import {SafeERC20} from "@oz/token/ERC20/utils/SafeERC20.sol";
/// @title Finding 3: Missing nonReentrant on Provisioner
@CharaD7
CharaD7 / ClaimFeesAccessControl.t.sol
Created September 24, 2026 10:15
Finding 1: Access Control Gap in BaseFeeCalculator - Verified PoC (5 tests passing)
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.29;
import {Test} from "forge-std/Test.sol";
import {BaseFeeCalculator} from "src/core/BaseFeeCalculator.sol";
import {Authority} from "@solmate/auth/Auth.sol";
import {IERC20} from "src/interfaces/IERC20.sol";
/// @title Access Control Gap PoC
/// @notice Demonstrates that BaseFeeCalculator.claimFees() and claimProtocolFees()
@CharaD7
CharaD7 / LIDO_LOW_BUG_REPORT.md
Created September 19, 2026 11:32
Lido CSM -- Low: FeeOracle.finalizeUpgradeV3 missing access control and no reinitializer. Impact category: Missing access controls / unprotected internal interfaces. Per Immunefi scope: Flat ,000. PoC: 3/3 tests pass.

Lido CSM -- Low: FeeOracle.finalizeUpgradeV3 Missing Access Control

Brief/Intro

FeeOracle.finalizeUpgradeV3(uint256 consensusVersion) in lidofinance/community-staking-module is an external function with no access control and no reinitializer modifier. Anyone can call it to change the oracle's consensus version. If exploited, an attacker could manipulate the oracle's consensus configuration, potentially disrupting oracle report processing.

Vulnerability Details

FeeOracle inherits PausableWithRoles and BaseOracle, which provide access control through whenNotPaused/whenPaused modifiers on most functions. However, finalizeUpgradeV3 has no modifier at all:

@CharaD7
CharaD7 / LIDO_BUG_REPORT.md
Created September 19, 2026 11:32
Lido CSM -- CRITICAL: No-Access-Control Oracle Frame Configuration Manipulation. executeOffsetPhase/executeRestorePhase have no access control. Impact categories: Permanent freezing of funds, Protocol insolvency, Any governance voting result manipulation, Missing access controls, Susceptibility to frontrunning, Theft of tokenized staking yield. โ€ฆ

Lido CSM -- No-Access-Control Oracle Frame Configuration Manipulation

Brief/Intro

TwoPhaseFrameConfigUpdate in lidofinance/community-staking-module has two external functions, executeOffsetPhase() and executeRestorePhase(), with zero access control. Anyone can call them to manipulate the Lido Oracle's frame configuration or permanently renounce MANAGE_FRAME_CONFIG_ROLE on HashConsensus. If exploited in production, an attacker could halt the oracle, disrupt governance voting, and permanently freeze the protocol's ability to adjust oracle parameters.

Vulnerability Details

TwoPhaseFrameConfigUpdate is a helper contract that adjusts the Lido Oracle's frame configuration (epochs per frame, fast lane length) via a two-phase process:

@CharaD7
CharaD7 / lido_low_poc.sol
Created September 19, 2026 11:10
Lido CSM -- Low Severity PoC: FeeOracle.finalizeUpgradeV3 missing access control. 3/3 tests confirm anyone can call finalizeUpgradeV3.
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.33;
// Lido CSM -- Low Severity: FeeOracle.finalizeUpgradeV3 Missing Access Control
// Target: src/FeeOracle.sol (finalizeUpgradeV3)
// Severity: Low | Program: Lido Immunefi | Primacy of Rules | No KYC
// ChainScope: 871 nodes, 2351 edges, 0 extractor failures, 100% confidence
// The vulnerable function in FeeOracle.sol:
//
@CharaD7
CharaD7 / RailDoSTest.t.sol
Created September 16, 2026 21:05
weETH OFT pairwise rate-limit rail-saturation DoS (live mainnet fork PoC, ether.fi/Immunefi)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { Test } from "forge-std/Test.sol";
import { WeEthAbi } from "../src/WeEthAbi.sol";
/// @notice Live mainnet-fork proof of the per-rail rate-limit DoS on the
/// deployed L1 weETH OFT adapter (EtherFiOFTAdapterUpgradeable).
/// Rail L1->BNB (eid 30102): limit 20 weETH / 14400s, observed live.
contract RailDoSTest is Test {
@CharaD7
CharaD7 / olympus_mc11.md
Created September 9, 2026 23:00
Olympus Monocooler (loan market) - setTreasuryBorrower is permissionless before initialization: any caller takes over the treasury-borrower money path (borrow/repay/writeOffDebt) and mints arbitrary debt -> insolvency. Real-contract Foundry PoC proves non-admin takeover + free mint. Latent: live 0xdb59 already initialized.

MonoCooler - setTreasuryBorrower permissionless before initialization (uninitialized-role take-over; latent critical)

Report

Verified against the deployed source and a fork-Foundry PoC. The MonoCooler constructor never sets treasuryBorrower, and the setter is guarded only by if (treasuryBorrower != address(0) && !_isAdmin(msg.sender)) revert. Because a fresh deploy has treasuryBorrower == address(0), the guard short-circuits, so the FIRST caller can point the Cooler at an arbitrary ICoolerTreasuryBorrower and gain control of borrow() / repay() / writeOffDebt().

Severity note: the CURRENTLY-DEPLOYED MonoCooler (0xdb59...e7cc) is already initialized, so this is NOT exploitable on the

@CharaD7
CharaD7 / termmax_bad_debt_null_result.sol
Created September 8, 2026 20:03
TermMax V2 โ€” INVESTIGATION (NULL RESULT): bad-debt not written down to totalAssets() does NOT reproduce as protocol insolvency; vault stays solvent. Includes trace + repro tests.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;
//
// TermMax / Term Structure Labs -- INVESTIGATION (NULL RESULT). Do NOT submit.
// ========================================================================
// Candidate : Protocol insolvency via bad debt never written down to totalAssets()
// Contract : contracts/v2/vault/TermMaxVaultV2.sol + contracts/v2/vault/OrderManagerV2.sol
// Result : The accounting asymmetry is REAL, but the end-to-end insolvency / depositor
// theft DOES NOT REPRODUCE. The vault remains solvent. => Medium, not CRIT/HIGH.
@CharaD7
CharaD7 / termmax_burnToAToken_StealsUnclaimedYield.t.sol
Created September 8, 2026 20:03
TermMax V2 (termstructurelabs) HIGH โ€” theft of unclaimed yield: StableERC4626ForAave.burnToAToken pays raw index-appreciated aTokens against a pinned 1:1 share price (forged PoC + index-aware MockAave)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;
//
// TermMax / Term Structure Labs -- High: theft of unclaimed yield
// ===============================================================
// Contract : contracts/v2/tokens/StableERC4626ForAave.sol (TermMax V2)
// Bug : burnToAToken() burns `amount` shares but pays `amount` AAVE aTokens (raw,
// index-unadjusted), while totalAssets() is pinned to totalSupply() (1:1) and the
// Aave interest is quarantined as owner-milked income.