DeFiHardhatFoundry
250,000 USDC
View results
Submission Details
Severity: low
Invalid

`LibFertilizer.addUnderlying()` incorrectly handles decimals of barnRaiseToken

Summary

Protocol wrongly assumes that barnRaiseToken has 18 decimals. However there is functionality to migrate current barnRaiseToken to any other:

/**
* @notice Begins the process of Migration the Barn Raise to a new Well.
* @param well The address of the Well to migrate to.
* @dev
* Withdraws all underlying Unripe LP tokens to the owner contract.
* Converting, chopping and purchasing Fertilizer will be disabled until the migration is complete.
* The migration process is completed by calling {UnripeFacet.addMigratedUnderlying}.
@> * After migration, Unripe liquidity will be added into `well`. and Fertilizer purchases can only happen
* with the non-Bean token in `well`.
*
*/
function beginBarnRaiseMigration(address well) external {
LibDiamond.enforceIsOwnerOrContract();
LibFertilizer.beginBarnRaiseMigration(well);
}

So at some point barnRaiseToken can be updated from WETH to let's say USDC. As a result Fertilizer cannot be minted.

Vulnerability Details

As you can see, tokenAmountIn is submitted with 1e18 precision so that oracle pricing works correctly inside _getMintFertilizerOut() (that's because LibUsdOracle.getUsdPrice() has 1e18 precision too).

/**
* @notice Purchase Fertilizer from the Barn Raise with the Barn Raise token.
@> * @param tokenAmountIn Amount of tokens to buy Fertilizer with 18 decimal precision.
* @param minFertilizerOut The minimum amount of Fertilizer to purchase. Protects against a significant Barn Raise Token/USD price decrease.
* @param minLPTokensOut The minimum amount of LP tokens to receive after adding liquidity with Barn Raise tokens.
* @dev The # of Fertilizer minted is equal to the value of the Ether paid in USD.
*/
function mintFertilizer(
uint256 tokenAmountIn,
uint256 minFertilizerOut,
uint256 minLPTokensOut
) external payable fundsSafu noOutFlow returns (uint256 fertilizerAmountOut) {
fertilizerAmountOut = _getMintFertilizerOut(
tokenAmountIn,
LibBarnRaise.getBarnRaiseToken()
);
...
@> uint128 id = LibFertilizer.addFertilizer(
uint128(s.sys.season.current),
tokenAmountIn,
fertilizerAmountOut,
minLPTokensOut
);
...
}

Let's follow the call chain. As you can see it finally tries to transfer that 1e18 tokenAmount from user, which works incorrectly on non-18 decimal tokens:

function addFertilizer(
uint128 season,
uint256 tokenAmountIn,
uint256 fertilizerAmount,
uint256 minLP
) internal returns (uint128 id) {
...
@> addUnderlying(tokenAmountIn, fertilizerAmount.mul(DECIMALS), minLP);
...
}
function addUnderlying(
uint256 tokenAmountIn,
uint256 usdAmount,
uint256 minAmountOut
) internal {
...
IERC20(barnRaiseToken).transferFrom(
LibTractor._user(),
address(this),
@> uint256(tokenAmountIn)
);
IERC20(barnRaiseToken).approve(barnRaiseWell, uint256(tokenAmountIn));
C.bean().approve(barnRaiseWell, newDepositedLPBeans);
...
}

Impact

Fertilizer cannot be minted in case barnRaiseToken will be migrated to non-18 decimals token like USDC.

Tools Used

Manual Review

Recommendations

Convert 1e18 amount into token amount:

function addUnderlying(
uint256 tokenAmountIn,
uint256 usdAmount,
uint256 minAmountOut
) internal {
...
+ tokenAmountIn = tokenAmountIn / (10 ** 18 - ERC20(barnRaiseToken).decimals);
IERC20(barnRaiseToken).transferFrom(
LibTractor._user(),
address(this),
uint256(tokenAmountIn)
);
...
}
Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

Informational/Gas

Invalid as per docs https://docs.codehawks.com/hawks-auditors/how-to-determine-a-finding-validity

Appeal created

T1MOH Submitter
about 1 year ago
inallhonesty Lead Judge
about 1 year ago
inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

Informational/Gas

Invalid as per docs https://docs.codehawks.com/hawks-auditors/how-to-determine-a-finding-validity

Support

FAQs

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