20,000 USDC
View results
Submission Details
Severity: low
Valid

LOSS OF PRECISION DUE TO ROUNDING

[L-1] Loss of precision due to rounding

https://github.com/Cyfrin/2023-07-beedle/blob/main/src/Lender.sol#L246
uint256 loanRatio = (debt * 10 ** 18) / collateral;
https://github.com/Cyfrin/2023-07-beedle/blob/main/src/Lender.sol#L265
uint256 fees = (debt * borrowerFee) / 10000;
https://github.com/Cyfrin/2023-07-beedle/blob/main/src/Lender.sol#L384
uint256 loanRatio = (totalDebt * 10 ** 18) / loan.collateral;
https://github.com/Cyfrin/2023-07-beedle/blob/main/src/Lender.sol#L475
uint256 currentAuctionRate = (MAX_INTEREST_RATE * timeElapsed) /
loan.auctionLength;
https://github.com/Cyfrin/2023-07-beedle/blob/main/src/Lender.sol#L561
uint256 govFee = (borrowerFee * loan.collateral) / 10000;
https://github.com/Cyfrin/2023-07-beedle/blob/main/src/Lender.sol#L618
uint256 loanRatio = (debt * 10 ** 18) / collateral;
https://github.com/Cyfrin/2023-07-beedle/blob/main/src/Lender.sol#L650
uint256 fee = (borrowerFee * (debt - debtToPay)) / 10000;
https://github.com/Cyfrin/2023-07-beedle/blob/main/src/Lender.sol#L724
interest = (l.interestRate * l.debt * timeElapsed) / 10000 / 365 days;
https://github.com/Cyfrin/2023-07-beedle/blob/main/src/Lender.sol#L725
fees = (lenderFee * interest) / 10000;

[L-2] Consider using OpenZeppelin’s SafeCast library to prevent unexpected overflows when casting from uint256.
Using the SafeCast library can help prevent unexpected errors in your Solidity code and make your contracts more secure

https://github.com/Cyfrin/2023-07-beedle/blob/main/src/Lender.sol#L650
uint256 fee = (borrowerFee * (debt - debtToPay)) / 10000;
https://github.com/Cyfrin/2023-07-beedle/blob/main/src/Lender.sol#L723C8-L726C26
uint256 timeElapsed = block.timestamp - l.startTimestamp;
interest = (l.interestRate * l.debt * timeElapsed) / 10000 / 365 days;
fees = (lenderFee * interest) / 10000;
interest -= fees;

[L-3] Lack of Sanity/Threshold/Limit Checks
Devoid of sanity/threshold/limit checks, critical parameters can be configured to invalid values, causing a variety of issues and breaking expected interactions within/between contracts. Consider adding proper uint256 validation as well as zero address checks for critical changes. A worst case scenario would render the contract needing to be re-deployed in the event of human/accidental errors that involve value assignments to immutable variables. If the validation procedure is unclear or too complex to implement on-chain, document the potential issues that could produce invalid values.

https://github.com/Cyfrin/2023-07-beedle/blob/main/src/Lender.sol#L84
function setLenderFee(uint256 _fee) external onlyOwner {
if (_fee > 5000) revert FeeTooHigh();
lenderFee = _fee;
}
https://github.com/Cyfrin/2023-07-beedle/blob/main/src/Lender.sol#L92
function setBorrowerFee(uint256 _fee) external onlyOwner {
if (_fee > 500) revert FeeTooHigh();
borrowerFee = _fee;
}
https://github.com/Cyfrin/2023-07-beedle/blob/main/src/Lender.sol#L100
function setFeeReceiver(address _feeReceiver) external onlyOwner {
feeReceiver = _feeReceiver;
}
https://github.com/Cyfrin/2023-07-beedle/blob/main/src/Fees.sol#L19
constructor(address _weth, address _staking) {
WETH = _weth;
staking = _staking;
}
https://github.com/Cyfrin/2023-07-beedle/blob/main/src/Beedle.sol#L15
function _afterTokenTransfer(address from, address to, uint256 amount)
internal
override(ERC20, ERC20Votes)
{
super._afterTokenTransfer(from, to, amount);
}
https://github.com/Cyfrin/2023-07-beedle/blob/main/src/Beedle.sol#L22C11-L22C12
function _mint(address to, uint256 amount)
internal
override(ERC20, ERC20Votes)
{
super._mint(to, amount);
}
https://github.com/Cyfrin/2023-07-beedle/blob/main/src/Beedle.sol#L29
function _burn(address account, uint256 amount)
internal
override(ERC20, ERC20Votes)
{
super._burn(account, amount);
https://github.com/Cyfrin/2023-07-beedle/blob/main/src/Beedle.sol#L36
function mint(address to, uint256 amount) external onlyOwner {
_mint(to, amount);
}

[L-4] Function Calls in Loop Could Lead to Denial of Service
Function calls made in unbounded loop are error-prone with potential resource exhaustion as it can trap the contract due to the gas limitations or failed transactions

https://github.com/Cyfrin/2023-07-beedle/blob/main/src/Lender.sol#L233
for (uint256 i = 0; i < borrows.length; i++) {
bytes32 poolId = borrows[i].poolId;
uint256 debt = borrows[i].debt;
uint256 collateral = borrows[i].collateral;
https://github.com/Cyfrin/2023-07-beedle/blob/main/src/Lender.sol#L293
for (uint256 i = 0; i < loanIds.length; i++) {
uint256 loanId = loanIds[i];
https://github.com/Cyfrin/2023-07-beedle/blob/main/src/Lender.sol#L359
for (uint256 i = 0; i < loanIds.length; i++) {
uint256 loanId = loanIds[i];
bytes32 poolId = poolIds[i];
https://github.com/Cyfrin/2023-07-beedle/blob/main/src/Lender.sol#L438C9-L439C41
for (uint256 i = 0; i < loanIds.length; i++) {
uint256 loanId = loanIds[i];
https://github.com/Cyfrin/2023-07-beedle/blob/main/src/Lender.sol#L549C8-L550C41
for (uint256 i = 0; i < loanIds.length; i++) {
uint256 loanId = loanIds[i];
https://github.com/Cyfrin/2023-07-beedle/blob/main/src/Lender.sol#L592
for (uint256 i = 0; i < refinances.length; i++) {

[NC-1] Use scientific notation (e.g. 1e18) rather than exponentiation (e.g. 10**18)
While the compiler knows to optimize away the exponentiation, it’s still better coding practice to use idioms that do not require compiler optimization, if they exist.

https://github.com/Cyfrin/2023-07-beedle/blob/main/src/Lender.sol#L246
uint256 loanRatio = (debt * 10 ** 18) / collateral;
https://github.com/Cyfrin/2023-07-beedle/blob/main/src/Lender.sol#L384
uint256 loanRatio = (totalDebt * 10 ** 18) / loan.collateral;
https://github.com/Cyfrin/2023-07-beedle/blob/main/src/Lender.sol#L618
uint256 loanRatio = (debt * 10 ** 18) / collateral;

[NC-2] Take advantage of Custom Error’s return value property
An important feature of Custom Error is that values such as address, tokenID, msg.value can be written inside the () sign, this kind of approach provides a serious advantage in debugging and examining the revert details of dapps such as tenderly
https://github.com/Cyfrin/2023-07-beedle/blob/main/src/Lender.sol#L183
if (pools[poolId].lender != msg.sender) revert Unauthorized();
https://github.com/Cyfrin/2023-07-beedle/blob/main/src/Lender.sol#L184
if (amount == 0) revert PoolConfig();
https://github.com/Cyfrin/2023-07-beedle/blob/main/src/Lender.sol#L247
if (loanRatio > pool.maxLoanRatio) revert RatioTooHigh();

https://github.com/Cyfrin/2023-07-beedle/blob/main/src/Lender.sol#L375
if (pool.auctionLength < loan.auctionLength) revert AuctionTooShort();

[NC-4] Use constants instead of using numbers directly without explanations.
https://github.com/Cyfrin/2023-07-beedle/blob/main/src/Lender.sol#L265
uint256 fees = (debt * borrowerFee) / 10000;
https://github.com/Cyfrin/2023-07-beedle/blob/main/src/Lender.sol#L561
uint256 govFee = (borrowerFee * loan.collateral) / 10000;
https://github.com/Cyfrin/2023-07-beedle/blob/main/src/Lender.sol#L650
uint256 fee = (borrowerFee * (debt - debtToPay)) / 10000;
https://github.com/Cyfrin/2023-07-beedle/blob/main/src/Lender.sol#L724
interest = (l.interestRate * l.debt * timeElapsed) / 10000 / 365 days;
fees = (lenderFee * interest) / 10000;

Support

FAQs

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