DeFiHardhat
21,000 USDC
View results
Submission Details
Severity: medium
Invalid

Ensuring Correct Token Accounting with Balance Checks in the chop Function

Summary

The chop function is designed to convert an unripe token into its ripe counterpart by burning the unripe tokens and transferring the equivalent ripe tokens to the user. The function performs critical operations such as burning tokens and transferring assets, making it essential to ensure the correctness of these operations.

Vulnerability Details

The original implementation of the chop function does not include explicit balance checks before and after the critical operations of burning and transferring tokens. This can lead to potential discrepancies in token accounting, which may result in incorrect token burns or transfers.

By not verifying the balances before and after these operations, the function may not guarantee that the expected amounts are correctly processed, potentially leading to loss of funds or incorrect token state.

Impact

Incorrect Token Burning: If the burn operation does not reduce the user’s balance by the intended amount, it could result in an incorrect supply of unripe tokens.
Incorrect Token Transfer: If the transfer operation does not credit the correct amount of ripe tokens to the user, it could result in a loss of funds for the user.
State Inconsistency: Without verifying balances, the function might leave the contract in an inconsistent state, affecting the overall integrity of the token ecosystem.

Tools Used

Recommendations

Implement Balance Checks: Add explicit balance checks before and after the burn and transfer operations to ensure that the correct amounts are processed.
Ensure Successful Burn: Verify that the user’s balance of unripe tokens is reduced by the correct amount after the burn operation.
Ensure Successful Transfer: Verify that the user’s balance of ripe tokens is increased by the correct amount after the transfer operation.

function chop(
address unripeToken,
uint256 amount,
LibTransfer.From fromMode,
LibTransfer.To toMode
) external payable nonReentrant returns (uint256) {
// Check initial balance of unripeToken
uint256 initialUnripeBalance = IBean(unripeToken).balanceOf(msg.sender);
// Burn the token from the msg.sender address
uint256 supply = IBean(unripeToken).totalSupply();
uint256 burnedAmount = LibTransfer.burnToken(IBean(unripeToken), amount, msg.sender, fromMode);
// Ensure the burn was successful
uint256 finalUnripeBalance = IBean(unripeToken).balanceOf(msg.sender);
require(finalUnripeBalance == initialUnripeBalance - burnedAmount, "Chop: Burn amount mismatch");
// Get ripe address and ripe amount
(address underlyingToken, uint256 underlyingAmount) = LibChop.chop(
unripeToken,
burnedAmount,
supply
);
// Ensure we have a valid amount to transfer
require(underlyingAmount > 0, "Chop: no underlying");
// Check initial balance of underlyingToken
uint256 initialUnderlyingBalance = IERC20(underlyingToken).balanceOf(msg.sender);
// Send the corresponding amount of ripe token to the user address
IERC20(underlyingToken).sendToken(underlyingAmount, msg.sender, toMode);
// Ensure the transfer was successful
uint256 finalUnderlyingBalance = IERC20(underlyingToken).balanceOf(msg.sender);
require(finalUnderlyingBalance == initialUnderlyingBalance + underlyingAmount, "Chop: Transfer amount mismatch");
// Emit the event
emit Chop(msg.sender, unripeToken, burnedAmount, underlyingAmount);
return underlyingAmount;
Updates

Lead Judging Commences

giovannidisiena Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Too generic

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.