Platform: Code4rena
Start Date: 29/03/2022
Pot Size: $50,000 USDC
Total HM: 16
Participants: 42
Period: 5 days
Judge: 0xean
Total Solo HM: 9
Id: 105
League: ETH
Rank: 16/42
Findings: 3
Award: $734.97
🌟 Selected for report: 0
🚀 Solo Findings: 0
560.4852 USDC - $560.49
Due to how the cooldown period is calculated after a transfer, a user can strategically transfer between accounts to increase their cooldown timestamp while keeping it within the UNSTAKE_PERIOD
, so they can unstake anytime, defeating the cooldown mechanism.
return ((amount * _senderCooldown) + (receiverBalance * receiverCooldown)) / (amount + receiverBalance);
#0 - Kogaroshi
2022-04-02T21:11:33Z
Duplicate of https://github.com/code-423n4/2022-03-paladin-findings/issues/7 As stated in Issue https://github.com/code-423n4/2022-03-paladin-findings/issues/7, Unstake period is reduced to 2 days
#1 - 0xean
2022-04-11T15:41:35Z
closing as dupe of #7
🌟 Selected for report: IllIllI
Also found by: 0v3rf10w, 0xDjango, 0xkatana, 0xmint, Czar102, Dravee, Funen, Ruhum, TerrierLover, defsec, gzeon, hake, hyh, jah, kenta, minhquanym, okkothejawa, pmerkleplant, rayn, reassor, robee, sorrynotsorry, sseefried, teryanarmen
113.8588 USDC - $113.86
Consider to pin Solidity version to latest 0.8.12
HolyPaladinToken._updateDropPerSecond() (contracts/HolyPaladinToken.sol#714-742) performs a multiplication on the result of a division: -dropDecreasePerMonth = (startDropPerSecond - endDropPerSecond) / (dropDecreaseDuration / MONTH) (contracts/HolyPaladinToken.sol#729) -nbMonthEllapsed = (block.timestamp - lastDropUpdate) / MONTH (contracts/HolyPaladinToken.sol#730) -dropPerSecondDecrease = dropDecreasePerMonth * nbMonthEllapsed (contracts/HolyPaladinToken.sol#732) HolyPaladinToken._getNewIndex(uint256) (contracts/HolyPaladinToken.sol#744-761) performs a multiplication on the result of a division: -baseDropPerSecond = (_currentDropPerSecond * UNIT) / maxLockBonusRatio (contracts/HolyPaladinToken.sol#752) -accruedBaseAmount = ellapsedTime * baseDropPerSecond (contracts/HolyPaladinToken.sol#755) HolyPaladinToken._getUserAccruedRewards(address,uint256) (contracts/HolyPaladinToken.sol#786-851) performs a multiplication on the result of a division: -lockingRewards = (userLockedBalance * ((indexDiff * vars.periodBonusRatio) / UNIT)) / UNIT (contracts/HolyPaladinToken.sol#842) HolyPaladinToken._lock(address,uint256,uint256,HolyPaladinToken.LockAction) (contracts/HolyPaladinToken.sol#1137-1233) performs a multiplication on the result of a division: -durationRatio = ((duration - MIN_LOCK_DURATION) * UNIT) / (MAX_LOCK_DURATION - MIN_LOCK_DURATION) (contracts/HolyPaladinToken.sol#1156) -userLockBonusRatio = minLockBonusRatio + (((maxLockBonusRatio - minLockBonusRatio) * durationRatio) / UNIT) (contracts/HolyPaladinToken.sol#1157) HolyPaladinToken._lock(address,uint256,uint256,HolyPaladinToken.LockAction) (contracts/HolyPaladinToken.sol#1137-1233) performs a multiplication on the result of a division: -durationRatio_scope_0 = ((duration - MIN_LOCK_DURATION) * UNIT) / (MAX_LOCK_DURATION - MIN_LOCK_DURATION) (contracts/HolyPaladinToken.sol#1212) -userLockBonusRatio_scope_1 = minLockBonusRatio + (((maxLockBonusRatio - minLockBonusRatio) * durationRatio_scope_0) / UNIT) (contracts/HolyPaladinToken.sol#1213) HolyPaladinToken._kick(address,address) (contracts/HolyPaladinToken.sol#1270-1315) performs a multiplication on the result of a division: -nbWeeksOverLockTime = (block.timestamp - userCurrentLockEnd) / WEEK (contracts/HolyPaladinToken.sol#1305) -penaltyPercent = nbWeeksOverLockTime * kickRatioPerWeek (contracts/HolyPaladinToken.sol#1306) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#divide-before-multiply
Same result but inconsistant with comment https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L861
setKickRatio https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L1416 setEndDropPerSecond https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L1433
_rewardsVault
#0 - Kogaroshi
2022-04-02T19:57:56Z
QA & gas optimizations changes are done in the PR: https://github.com/PaladinFinance/Paladin-Tokenomics/pull/6 (some changes/tips were implemented, others are noted but won't be applied)
🌟 Selected for report: TerrierLover
Also found by: 0v3rf10w, 0xDjango, 0xNazgul, 0xkatana, 0xmint, Cityscape, Czar102, Dravee, Funen, IllIllI, Tomio, antonttc, defsec, gzeon, hake, kenta, minhquanym, pmerkleplant, rayn, rfa, robee, saian, securerodd, teryanarmen
60.6214 USDC - $60.62
> 0
is less efficient than != 0
for uint in require conditionRef: https://twitter.com/GalloDaSballo/status/1485430908165443590
contracts/HolyPaladinToken.sol:229: require(balanceOf(msg.sender) > 0, "hPAL: No balance"); contracts/HolyPaladinToken.sol:385: require(amount > 0, "hPAL: incorrect amount"); contracts/HolyPaladinToken.sol:1062: require(amount > 0, "hPAL: Null amount"); contracts/HolyPaladinToken.sol:1078: require(amount > 0, "hPAL: Null amount"); contracts/HolyPaladinToken.sol:1237: require(userLocks[user].length > 0, "hPAL: No Lock"); contracts/HolyPaladinToken.sol:1246: require(currentUserLock.amount > 0, "hPAL: No Lock"); contracts/HolyPaladinToken.sol:1272: require(userLocks[user].length > 0, "hPAL: No Lock"); contracts/HolyPaladinToken.sol:1281: require(currentUserLock.amount > 0, "hPAL: No Lock"); contracts/HolyPaladinToken.sol:1342: require(amount > 0, "hPAL: Null amount");
transferToken
Since it is onlyOwner, we don't really need to prevent reentrancy https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/PaladinRewardReserve.sol#L52
Use uint(1) instead of bool(true) to save gas by avoiding masking ops https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/PaladinRewardReserve.sol#L52
This can be unchecked as Total locked must be greater than or equal to currentUserLock https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L1286
currentTotalLocked -= currentUserLock.amount;
This can be uncheced as WEEK != 0 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L1305
uint256 nbWeeksOverLockTime = (block.timestamp - userCurrentLockEnd) / WEEK;
#0 - Kogaroshi
2022-04-02T19:49:26Z
QA & gas optimizations changes are done in the PR: https://github.com/PaladinFinance/Paladin-Tokenomics/pull/6 (some changes/tips were implemented, others are noted but won't be applied)