Platform: Code4rena
Start Date: 09/12/2021
Pot Size: $25,000 USDC
Total HM: 12
Participants: 25
Period: 4 days
Judge: LSDan
Total Solo HM: 4
Id: 64
League: ETH
Rank: 14/25
Findings: 2
Award: $528.85
🌟 Selected for report: 1
🚀 Solo Findings: 0
🌟 Selected for report: pmerkleplant
Also found by: GiveMeTestEther, WatchPug, defsec, pauliax
510.9568 USDC - $510.96
pmerkleplant
There exist ERC20 tokens that charge a fee for every transfer.
This kind of token does not work correctly with the TwabRewards
contract as the
rewards calculation for an user is based on promotion.tokensPerEpoch
(see line 320).
However, the actual amount of tokens the contract holds could be less than
promotion.tokensPerEpoch * promotion.numberOfEpochs
leading to not claimable
rewards for users claiming later than others.
To disable fee-on transfer tokens for the contract, add the following code in
createPromotion
around line 11:
uint256 oldBalance = _token.balanceOf(address(this)); _token.safeTransferFrom(msg.sender, address(this), _tokensPerEpoch * _numberOfEpochs); uint256 newBalance = _token.balanceOf(address(this)); require(oldBalance + _tokenPerEpoch * _numberOfEpochs == newBalance);
#0 - dmvt
2022-01-17T11:46:08Z
This issue results in a direct loss of funds and can happen easily.
3 — High (H): vulns have a risk of 3 and are considered “High” severity when assets can be stolen/lost/compromised directly (or indirectly if there is a valid attack path that does not have hand-wavy hypotheticals).
🌟 Selected for report: robee
Also found by: 0x0x0x, defsec, leastwood, pmerkleplant
13.1075 USDC - $13.11
pmerkleplant
Caching the array length outside a loop in a variable saves reading it on each iteration as long as the array's length is not changed during the loop.
Therefore, the following loops could be refactored:
TwabRewards.sol:172: for (uint256 index = 0; index < _epochIds.length; index++) TwabRewards.sol:217: for (uint256 index = 0; index < _epochIds.length; index++)
Use the following pattern for refactoring:
uint length = arr.length; for (uint i = 0; i < length; i++) { // ... }
grep
#0 - PierrickGT
2021-12-10T17:29:28Z
🌟 Selected for report: gpersoon
Also found by: 0xabcc, WatchPug, cmichel, danb, gzeon, pauliax, pmerkleplant, sirhashalot
pmerkleplant
The function _requirePromotionActive
requires the variable _promotionEndTimestamp
to be greater than 0 and to be greater than block.timestamp
(see line 255).
As block.timestamp
is always greater than 0, the first check is unnecessary
and could be removed to save gas.
#0 - PierrickGT
2021-12-10T17:28:40Z