0xRAM LabsAutomated Security Assessment

documentation

https://github.com/smartcontractkit/documentation
May 26, 2026 at 12:00 AM06ca2c87-df3
0/ 100
CRITICAL RISK

Your protocol has 8 security issues — 1 Critical, 2 High, 1 Medium, 4 Low severity.

Security Overview //

Security Overview

🔴

Access Control

Vulnerable

1 finding(s) — includes critical severity

🟢

Reentrancy Protection

Secure

🟢

Oracle Security

Secure

🟢

Upgrade Safety

Secure

🟢

Input Validation

Secure

🟡

Event Logging

Needs Attention

3 finding(s) — medium/low severity

Severity Breakdown

Critical
1
High
2
Medium
1
Low
4
Info
0
121Lines of Code
1Contracts Analyzed
20Detectors Run
56msScan Duration

Vulnerability Breakdown

Below is a comprehensive breakdown of the vulnerabilities discovered in your smart contracts. As part of our marketing outreach, we expose the highest-severity vulnerability for free.

Free Security InsightCriticalSWC-105

Missing access control on `withdraw()`

BalancerOffChain.sol:40

Impact

An attacker could call `withdraw()` to perform privileged actions such as draining funds, minting tokens, or changing contract configuration.

Description

The sensitive function `withdraw` is public but has no access control modifier (e.g., onlyOwner, onlyRole) or inline msg.sender check. Anyone can call this function.

Vulnerable Code

38 37 | }
39 38 |
40 39 | /// @dev withdraw an `amount`from multiple elements of the `balances` array. The elements are provided in `indexes`
41 >>> 40 | function withdraw(
42 41 | uint256 amount,
43 42 | uint256[] memory indexes
44 43 | ) public {

Recommendation

Add an access control modifier like `onlyOwner` or use OpenZeppelin's `AccessControl` to restrict who can call `withdraw()`.

7 More Issues Detected

The following findings require expert review for full remediation guidance.

High

Denial of Service (DoS) via unbounded array loop

Line 44 contains a `for` loop that appears to iterate over the length of a dynamic array. If the array grows too large, the gas cost to execute the loop will exceed the block gas limit, causing the function to become permanently unusable.

41 | uint256 amount, 42 | uint256[] memory indexes 43 | ) public { >>> 44 | for (uint256 i = 0; i < indexes.length; i++) {

Avoid iterating over unbounded dynamic arrays. Instead, use a pull-payment pattern or implement pagination so the loop can be processed in smaller, bounded chunks.

Full details available in comprehensive audit
High

Denial of Service (DoS) via unbounded array loop

Line 113 contains a `for` loop that appears to iterate over the length of a dynamic array. If the array grows too large, the gas cost to execute the loop will exceed the block gas limit, causing the function to become permanently unusable.

110 | uint256 _balance; 111 | uint256 _liquidity = liquidity; 112 | >>> 113 | for (uint256 i = 0; i < indexes.length; i++) {

Avoid iterating over unbounded dynamic arrays. Instead, use a pull-payment pattern or implement pagination so the loop can be processed in smaller, bounded chunks.

Full details available in comprehensive audit
Medium

`addLiquidity()` lacks slippage and deadline protection

Function `addLiquidity` at line 33 appears to perform a swap/trade operation but has no slippage protection (minAmountOut) or deadline parameter. This makes it highly vulnerable to sandwich attacks and MEV extraction.

30 | } 31 | 32 | /// @dev called to increase the liquidity of the contract >>> 33 | function addLiquidity(

Add a `minAmountOut` or equivalent slippage parameter and a `deadline` parameter. Validate both with require statements.

Full details available in comprehensive audit
Low

Floating pragma: `pragma solidity ^0.8.20`

The Solidity version pragma `^0.8.20` is not locked to a specific compiler version. Different compiler versions may introduce different behavior, optimizations, or bugs.

1 | // SPDX-License-Identifier: MIT >>> 2 | pragma solidity ^0.8.20; 3 | 4 | import {

Lock the pragma to a specific version, e.g., `pragma solidity 0.8.20;`. Use the latest stable version for new contracts.

Full details available in comprehensive audit
Low

State-changing function `addLiquidity` does not emit an event

The function `addLiquidity` is public/external and mutates state variables, but it does not emit any events. Emitting events is a standard security practice in Solidity to facilitate off-chain tracking, indexing, and security monitoring.

30 | } 31 | 32 | /// @dev called to increase the liquidity of the contract >>> 33 | function addLiquidity(

Define an event and emit it at the end of the state-changing operations in this function, passing relevant arguments (like old and new values).

Full details available in comprehensive audit
Low

State-changing function `withdraw` does not emit an event

The function `withdraw` is public/external and mutates state variables, but it does not emit any events. Emitting events is a standard security practice in Solidity to facilitate off-chain tracking, indexing, and security monitoring.

37 | } 38 | 39 | /// @dev withdraw an `amount`from multiple elements of the `balances` array. The elements are provided in `indexes` >>> 40 | function withdraw(

Define an event and emit it at the end of the state-changing operations in this function, passing relevant arguments (like old and new values).

Full details available in comprehensive audit
Low

State-changing function `performUpkeep` does not emit an event

The function `performUpkeep` is public/external and mutates state variables, but it does not emit any events. Emitting events is a standard security practice in Solidity to facilitate off-chain tracking, indexing, and security monitoring.

102 | * @dev return `upkeepNeeded`if rebalancing must be done and `performData` which contains an array of increments. This 103 | will be used in `performUpkeep` 104 | */ >>> 105 | function performUpkeep(

Define an event and emit it at the end of the state-changing operations in this function, passing relevant arguments (like old and new values).

Full details available in comprehensive audit

Our automated scan found 8 issues. Our expert auditors go deeper — covering logic bugs, economic attack vectors, and cross-contract interactions that automated tools miss.

Initiate Secure Audit Request

Or email us at audit@0xram.com (Contact form is preferred for priority review)

Secure Your Protocol
Before Launch

This automated scan is just the surface. Our team of expert auditors conducts line-by-line manual reviews, formal verification, and economic simulations to ensure your protocol is battle-tested.

Initiate Priority Audit Intake

Or email us at audit@0xram.com (Contact form preferred for priority queueing)

145+
Protocols
$4.82B+
TVL Secured
0
Post-Audit Exploits

© 2026 0xRAM Labs. All rights reserved.

Disclaimer: This report was dynamically generated by our automated static analyzer. It does not replace a comprehensive, line-by-line manual code audit by senior cryptographers.