Full Report
Equalizer Finance is a decentralized market focused on flash loans. The number of liquidity tokens created while minting was calculated based upon the amount of underlying tokens in the contract. The code for calculating this is shown below: uint256 denominator = stakedToken.balanceOf(address(this)) * factor / total_supply(); tokensToMint = amount * factor / denominator The token amount of LP tokens owned by the contract can be manipulated using the flashloan functionality. By calling flashloan, the balance of the contracts LP tokens is drastically decreased. Why is this bad? The denominator shown above takes into consideration the amount of LP tokens it owns! The smaller the denominator (hence amount of tokens in the contract) the more tokens that would be minted. The flow of the attack is as follows: Take out a flash loan from the vault for almost all of the LP tokens. In the real attack, they took half of the funds (50K USDC). Add the flash loaned funds as liquidity to the protocol. This brings back up the funds to 100K USDC and we get about 50K in LP tokens. Remove the liquidity. The flawed calculation shown above for minting returns a ridiculous amount of USDC back: 100K USDC. Pay back the flash loans. A massive profit has been gained. This service had been audited by Certik once and this vulnerability was missed. To me, this is a fairly straight forward attack so it's scary to me this was missed. Overall, good write up and explanation of the bug though!
Analysis Summary
# Incident Report: Equalizer Finance Flash Loan Manipulation
## Executive Summary
Equalizer Finance, a decentralized flash loan marketplace, was exploited due to a flawed liquidity token minting calculation. An attacker leveraged the protocol's own flash loan functionality to manipulate the contract's token balance, artificially inflating the number of LP tokens minted. This resulted in the unauthorized withdrawal of significant USDC reserves, highlighting a critical failure in logical validation despite an earlier audit.
## Incident Details
- **Discovery Date:** Not explicitly disclosed
- **Incident Date:** Not explicitly disclosed
- **Affected Organization:** Equalizer Finance
- **Sector:** Decentralized Finance (DeFi)
- **Geography:** Global/Decentralized
## Timeline of Events
### Initial Access
- **Date/Time:** Undisclosed
- **Vector:** Exploitation of Smart Contract Logic via Flash Loan.
- **Details:** The attacker initiated a flash loan from the Equalizer vault to seize a large portion of the protocol's underlying assets (50,000 USDC).
### Lateral Movement
- **Execution:** The attacker re-entered the protocol by adding the flash-loaned funds back as liquidity.
- **Details:** Because the minting formula used the current contract balance as a denominator (`stakedToken.balanceOf(address(this))`), and the contract's balance was depleted by the active flash loan, the calculation resulted in an abnormally high number of LP tokens being minted to the attacker.
### Data Exfiltration/Impact
- **Theft:** The attacker redeemed the inflated LP tokens for the underlying USDC.
- **Details:** By removing liquidity, the attacker received approximately 100,000 USDC—effectively doubling the initial funds involved in the transaction.
### Detection & Response
- **Detection:** Identified via post-incident chain analysis and security write-ups.
- **Response Actions:** The protocol’s vulnerability was analyzed to identify the specific mathematical flaw in the `mint` function.
## Attack Methodology
- **Initial Access:** Smart Contract Vulnerability (Logic Error).
- **Persistence:** N/A (Atomic transaction exploit).
- **Privilege Escalation:** Use of flash loans to manipulate the global state/balance of the contract.
- **Defense Evasion:** Transactions executed within the normal parameters of the smart contract's public functions.
- **Credential Access:** N/A.
- **Discovery:** Identifying that the `denominator` in the minting formula was susceptible to balance manipulation during a flash loan lifecycle.
- **Lateral Movement:** N/A.
- **Collection:** N/A.
- **Exfiltration:** Transfer of USDC to the attacker's wallet after paying back the flash loan.
- **Impact:** Financial loss via "Infinite Mint" style logic manipulation.
## Impact Assessment
- **Financial:** Loss of approximately 50,000 USDC in profit (100k withdrawn vs 50k original vault state).
- **Data Breach:** None.
- **Operational:** Temporary loss of trust in the liquidity pool mechanism.
- **Reputational:** High; the vulnerability had been missed during a professional audit by Certik.
## Indicators of Compromise
- **Behavioral indicators:** Large flash loan followed immediately by a liquidity provision and a liquidity withdrawal within a single block.
- **Contract Logic:** `tokensToMint = amount * factor / (stakedToken.balanceOf(address(this)) * factor / total_supply())`
## Response Actions
- **Containment:** Analysis of the flawed calculation.
- **Eradication:** Recommendation to update the minting formula to use a "cached" or "internal" balance that cannot be manipulated by active flash loans.
- **Recovery:** Protocol post-mortem and disclosure.
## Lessons Learned
- **Key takeaways:** Relying on `balanceOf(address(this))` for critical financial calculations is dangerous in protocols that offer flash loans, as the balance can be temporarily altered within a transaction.
- **Audit Limitations:** Even "audited" code (Certik) can contain straightforward logic flaws; multiple peer reviews and specialized DeFi stress-testing are necessary.
## Recommendations
- **Oracle/Internal State:** Use internal accounting variables to track balances instead of relying on the direct `balanceOf` query of the token contract.
- **Flash Loan Guard:** Implement checks to ensure that minting/burning of LP tokens cannot occur while a flash loan is "in flight" if those actions depend on vault balances.
- **Reentrancy/Logic Guards:** Standardize the use of "Safe" math and state-consistent variables for any calculation involving price or share value.