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

Internal balance still can increase even after protocol disable transferring tokens from External -> Internal balance, after L2 migration.

Summary

The protocol after after the L2 migration it doesn't support External -> Internal ERC20 Tokens transfer,
after migration Tokens must not transferred from External -> Internal, this option must be disabled,

protocol added this line of code to prevent External -> INTERNAL:

function transferToken(IERC20 token, address recipient, uint256 amount, LibTransfer.From fromMode, LibTransfer.To toMode) external payable {
checkBeanAsset(address(token));
@>> // L1 external -> internal transfers are not supported after the L2 migration.
@>> if (fromMode != LibTransfer.From.INTERNAL) { // <- If from External execute
@>> require(
@>> toMode == LibTransfer.To.EXTERNAL, // <- It requires transfer to External only
@>> "TokenFacet: EXTERNAL->INTERNAL transfers are disabled."
@>> );
}
LibTransfer.transferToken(token, msg.sender, recipient, amount, fromMode, toMode);
}

But when it comes to WETH EXTERNAL -> INTERNAL transfer can be made in L1TokenFacet.sol::wrapEth
if LibTransfer.To is INTERNAL the WETH will be transferred from EXTERNAL to INTERNAL,
in this line: if (mode == To.INTERNAL) LibBalance.increaseInternalBalance(recipient, token, amount);

Link: https://github.com/Cyfrin/2024-05-beanstalk-the-finale/blob/main/protocol/contracts/beanstalk/migration/L1TokenFacet.sol#L194-L197
function wrapEth(uint256 amount, LibTransfer.To mode) external payable {
LibWeth.wrap(amount, mode);
LibEth.refundEth();
}
Link: https://github.com/Cyfrin/2024-05-beanstalk-the-finale/blob/main/protocol/contracts/beanstalk/migration/L1Libraries/LibWeth.sol#L18-L21
function wrap(uint256 amount, LibTransfer.To mode) internal {
deposit(amount);
LibTransfer.sendToken(IERC20(WETH), amount, msg.sender, mode);
}
Link: https://github.com/Cyfrin/2024-05-beanstalk-the-finale/blob/main/protocol/contracts/beanstalk/migration/L1Libraries/LibTransfer.sol#L71-L75
function sendToken(IERC20 token, uint256 amount, address recipient, To mode) internal {
if (amount == 0) return;
if (mode == To.INTERNAL) LibBalance.increaseInternalBalance(recipient, token, amount);
else token.safeTransfer(recipient, amount);
}

Vulnerability Details

Impact

calculations that depend on INTERNAL balance can be tricked because it assumes after L2 migration Internal balance cannot be increased.

Tools Used

Recommendations

https://github.com/Cyfrin/2024-05-beanstalk-the-finale/blob/main/protocol/contracts/beanstalk/migration/L1TokenFacet.sol#L194-L197

funct
ion wrapEth(uint256 amount, LibTransfer.To mode) external payable {
require(
mode == LibTransfer.To.EXTERNAL,
"TokenFacet: EXTERNAL->INTERNAL transfers are disabled."
);
LibWeth.wrap(amount, mode);
LibEth.refundEth();
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 11 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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