You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Description: Description
According to the Docs https://dev.spectra.finance/technical-reference/contract-functions/principal-token#flashloan, flash loans should be profitable to the protocol, meaning that Zero fee is not allowed. However, there's currently no check that this requirement is met, allowing borrowers to get loans at Zero fee. Consider the flashLoan function:
function flashLoan(
IERC3156FlashBorrower_receiver,
address_token,
uint256_amount,
bytescalldata_data
) externaloverride whenNotPaused returns (bool) {
if (_amount >maxFlashLoan(_token)) revertFlashLoanExceedsMaxAmount();
uint256 fee =flashFee(_token, _amount);
_updateFees(fee);
// Initiate the flash loan by lending the requested IBT amountaddress _ibt = ibt;
IERC20(_ibt).safeTransfer(address(_receiver), _amount);
// Execute the flash loanif (_receiver.onFlashLoan(msg.sender, _token, _amount, fee, _data) != ON_FLASH_LOAN)
revertFlashLoanCallbackFailed();
// Repay the debt + feeIERC20(_ibt).safeTransferFrom(address(_receiver), address(this), _amount + fee);
returntrue;
}
the src/tokens/PrincipalToken.sol::flashfee function:
function flashFee(address_token, uint256_amount) publicviewoverridereturns (uint256) {
if (_token != ibt) revertAddressError();
return _amount._computeFlashloanFee(registry);
}
and the src/libraries/PrincipalTokenUtil.sol::_computeFlashloanFee function:
Nowhere do we have a check that the loan is profitable to the protocol. Attack Scenario
Describe how the vulnerability can be exploited.
Attachments
Proof of Concept (PoC) File
For a POC, add this contract at src/mocks/ERC3156FlashBorrowerMock.sol:
// SPDX-License-Identifier: MITpragma solidity^0.8.20;
import {IERC20} from"openzeppelin-contracts/token/ERC20/IERC20.sol";
import {IERC3156FlashBorrower} from"openzeppelin-contracts/interfaces/IERC3156.sol";
import {IERC3156FlashLender} from"openzeppelin-contracts/interfaces/IERC3156.sol";
import {Address} from"openzeppelin-contracts/utils/Address.sol";
/** * @dev WARNING: this IERC3156FlashBorrower mock implementation is for testing purposes ONLY. * Writing a secure flash lock borrower is not an easy task, and should be done with the utmost care. * This is not an example of how it should be done, and no pattern present in this mock should be considered secure. * Following best practices, always have your contract properly audited before using them to manipulate important funds on * live networks. */contractERC3156FlashBorrowerMockisIERC3156FlashBorrower {
bytes32internal constant _RETURN_VALUE =keccak256("ERC3156FlashBorrower.onFlashLoan");
boolimmutable _enableApprove;
boolimmutable _enableReturn;
event BalanceOf(addresstoken, addressaccount, uint256value);
event TotalSupply(addresstoken, uint256value);
constructor(boolenableReturn, boolenableApprove) {
_enableApprove = enableApprove;
_enableReturn = enableReturn;
}
function onFlashLoan(
addressinitiator,
addresstoken,
uint256amount,
uint256fee,
bytescalldatadata
) publicreturns (bytes32) {
//require(address(this) == initiator);emitBalanceOf(token, address(this), IERC20(token).balanceOf(address(this)));
emitTotalSupply(token, IERC20(token).totalSupply());
if (_enableApprove) {
IERC20(token).approve(msg.sender, amount + fee);
}
return _enableReturn ? _RETURN_VALUE : bytes32(0);
}
}
Also , add this test to test/PrincipalToken/PrincipalToken.t.sol:
function testFlashloan() public {
uint256 amountToDeposit =1e18;
underlying.approve(address(principalToken), amountToDeposit);
principalToken.deposit(amountToDeposit, MOCK_ADDR_1);
uint256 fee =IERC3156FlashLender(principalToken).flashFee(address(ibt),0.5e18);
principalToken.flashLoan(IERC3156FlashBorrower(eRC3156FlashBorrowerMock), address(ibt), 0.5e18, bytes(""));
assertEq(fee,0);
}
Revised Code File (Optional)
Introduce a check to ensure that loans are profitable to the protocol.
The text was updated successfully, but these errors were encountered:
"The DAO is responsible for setting the different fees in the protocol, and can decide to set them to 0"- you provided Docs indicating that Zero fees are not allowed. I think that this amounts to changing the contest rules midway.
Every sensible auditor in this contest would believe that the project is a business venture and would not want to miss making honest profits, unless it's clearly indicated by the project- which is not. Not charging fee without notice is lost profit for any business.
Github username: --
Twitter username: --
Submission hash (on-chain): 0xe98ba4f76944c4e43865e558e437fd5de4be99db36c7d64f16928d885ea78b63
Severity: high
Description:
Description
According to the Docs https://dev.spectra.finance/technical-reference/contract-functions/principal-token#flashloan, flash loans should be profitable to the protocol, meaning that Zero fee is not allowed. However, there's currently no check that this requirement is met, allowing borrowers to get loans at Zero fee. Consider the flashLoan function:
the src/tokens/PrincipalToken.sol::flashfee function:
and the src/libraries/PrincipalTokenUtil.sol::_computeFlashloanFee function:
Nowhere do we have a check that the loan is profitable to the protocol.
Attack Scenario
Describe how the vulnerability can be exploited.
Attachments
For a POC, add this contract at src/mocks/ERC3156FlashBorrowerMock.sol:
Also , add this test to test/PrincipalToken/PrincipalToken.t.sol:
The text was updated successfully, but these errors were encountered: