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
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.
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 indexes44 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.
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.
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.
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.
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.
`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.
Add a `minAmountOut` or equivalent slippage parameter and a `deadline` parameter. Validate both with require statements.
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.
Lock the pragma to a specific version, e.g., `pragma solidity 0.8.20;`. Use the latest stable version for new contracts.
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.
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).
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.
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).
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.
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).
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.
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.
Or email us at audit@0xram.com (Contact form preferred for priority queueing)