Platform: Code4rena
Start Date: 11/11/2022
Pot Size: $90,500 USDC
Total HM: 52
Participants: 92
Period: 7 days
Judge: LSDan
Total Solo HM: 20
Id: 182
League: ETH
Rank: 18/92
Findings: 4
Award: $1,279.93
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: c7e7eff
Also found by: 0x4non, 9svR6w, HE1M, Jeiwan, Trust, aphak5010, arcoun, cccz, clems4ever, corerouter, koxuan, rotcivegaf, unforgiven
10.2142 USDC - $10.21
The variable claimed
that keeps tracking of the total amount claimed per user per token its being being resetting with a wrong value.
This impacts on the line due
calculation on SyndicateRewardsProcessor.sol#L61
uint256 due = ((accumulatedETHPerLPShare * balance) / PRECISION) - claimed[_user][_token];
Yo could create a contract that mint LP, then in one transaction loop a transfer function with no value and use the received ether to redeposit and repeat.
manual revision
On SyndicateRewardsProcessor.sol#L63 instead of
claimed[_user][_token] = due;
You could do
claimed[_user][_token] += due;
#0 - c4-judge
2022-11-21T22:07:47Z
dmvt marked the issue as duplicate of #59
#1 - c4-judge
2022-11-29T16:46:59Z
dmvt marked the issue as partial-25
#2 - C4-Staff
2022-12-21T05:47:22Z
JeeberC4 marked the issue as duplicate of #147
🌟 Selected for report: unforgiven
Also found by: 0x4non
1012.6328 USDC - $1,012.63
https://github.com/code-423n4/2022-11-stakehouse/blob/main/contracts/liquid-staking/GiantMevAndFeesPool.sol#L146 https://github.com/code-423n4/2022-11-stakehouse/blob/main/contracts/liquid-staking/GiantMevAndFeesPool.sol#L152 https://github.com/code-423n4/2022-11-stakehouse/blob/main/contracts/liquid-staking/GiantMevAndFeesPool.sol#L161 https://github.com/code-423n4/2022-11-stakehouse/blob/main/contracts/liquid-staking/StakingFundsVault.sol#L315 https://github.com/code-423n4/2022-11-stakehouse/blob/main/contracts/liquid-staking/StakingFundsVault.sol#L333 https://github.com/code-423n4/2022-11-stakehouse/blob/main/contracts/liquid-staking/StakingFundsVault.sol#L337 https://github.com/code-423n4/2022-11-stakehouse/blob/39a3a84615725b7b2ce296861352117793e4c853/contracts/liquid-staking/SyndicateRewardsProcessor.sol#L67
A malicious user can craft a contract to reject ether loking the transfers.
Before and after gMevETH
and StakingFundsVault
is transfer is using the beforeTokenTransfer
to pay user any unclaimed ETH rewards.
This is dangerous because any user can be a contract that blocks ETH reception making this funtion fail all the times. Plus its a reentrancy risk.
Manual revision
Instead of transfering ETH you could wrap ETH in WETH and do a regular ERC20 transfer.
#0 - c4-judge
2022-11-21T21:25:48Z
dmvt marked the issue as duplicate of #260
#1 - c4-judge
2022-12-01T23:58:05Z
dmvt marked the issue as satisfactory
🌟 Selected for report: rotcivegaf
Also found by: 0x4non, clems4ever, datapunk
205.0581 USDC - $205.06
https://github.com/code-423n4/2022-11-stakehouse/blob/39a3a84615725b7b2ce296861352117793e4c853/contracts/liquid-staking/SyndicateRewardsProcessor.sol#L67 https://github.com/code-423n4/2022-11-stakehouse/blob/4b6828e9c807f2f7c569e6d721ca1289f7cf7112/contracts/liquid-staking/GiantMevAndFeesPool.sol#L146 https://github.com/code-423n4/2022-11-stakehouse/blob/4b6828e9c807f2f7c569e6d721ca1289f7cf7112/contracts/liquid-staking/StakingFundsVault.sol#L315
Multiple reentrancy issues mainly trigger by a low call ETH transfer.
Everytime you use the _distributeETHRewardsToUserForToken
method on SyndicateRewardsProcessor.sol#L67 there are many reentrancy opportunities for an attacker.
For example, a contract can call the function transfer of GiantLP
several times to transfer an amount from and to self. Because the update of the claimed would not be done until it is executed the function _afterTokenTransfer
, the due amount calculated in _distributeETHRewardsToUserForToken
of SyndicateRewardsProcessor contract and the lastInteractedTimestamp
of GiantLP
contract will be incorrect.
Manual revision
You could keep adding nonReentrant
modifiers, but i think the safest call here is to wrap ETH into WETH an transfer it as a normal ERC20 to avoid unwanted callbacks.
#0 - c4-judge
2022-11-21T22:02:25Z
dmvt marked the issue as duplicate of #35
#1 - c4-judge
2022-11-29T15:23:02Z
dmvt marked the issue as satisfactory
#2 - c4-judge
2022-11-29T15:54:10Z
dmvt marked the issue as partial-50
#3 - C4-Staff
2022-12-21T00:17:14Z
JeeberC4 marked the issue as duplicate of #35
#4 - liveactionllama
2022-12-22T09:24:59Z
Duplicate of #328
🌟 Selected for report: 0xSmartContract
Also found by: 0x4non, 0xNazgul, 0xRoxas, 0xdeadbeef0x, 0xmuxyz, 9svR6w, Awesome, Aymen0909, B2, Bnke0x0, CloudX, Deivitto, Diana, Franfran, IllIllI, Josiah, RaymondFam, ReyAdmirado, Rolezn, Sathish9098, Secureverse, SmartSek, Trust, Udsen, a12jmx, aphak5010, brgltd, bulej93, c3phas, ch0bu, chaduke, chrisdior4, clems4ever, cryptostellar5, datapunk, delfin454000, fs0c, gogo, gz627, hl_, immeas, joestakey, lukris02, martin, nogo, oyc_109, pashov, pavankv, peanuts, pedr02b2, rbserver, rotcivegaf, sahar, sakman, shark, tnevler, trustindistrust, zaskoh, zgo
52.0338 USDC - $52.03
On Syndicate.sol#L195 you have an unresolved todo that could lead to ETH stuck on the contract.
The codebase uses floating pragma. All contracts should be compiled with same pragma version. Locking the pragma ensures that contracts do not accidentally get deployed using either an outdated buggy compiler version or a compiler version different from what the code has been tested with. Recommendation: use a fixed solc version on contracts, and open progma on interfaces.
Files:
ERC20PermitUpgradeable
On LPToken.sol#L6 you are using draft version of Openzeppelin ERC20PermitUpgradeable
.
This contract is still a draft and is not considered ready for mainnet use. OpenZeppelin contracts may be considered draft contracts if they have not received adequate security auditing or are liable to change with future development.
__gap[50]
storage variable on Syndicate
and LpToken
Upgradeable contract is missing a __gap[50] storage variable to allow for new storage variables in later versions
Recommendation: add __gap
variable:
+ uint256[50] __gap;
On this contracts;
On LiquidStakingManager.sol#L870 instead of the magic number (2 ** 256) - 1
use typeof(uint256).max
for approving max;
Instead of
sETH.approve(syndicate, (2 ** 256) - 1);
USe
sETH.approve(syndicate, typeof(uint256).max);
Error InvalidBLSPubKey
is not being in use;
SyndicateErrors.sol#L8
Syndicate.sol#L15
Error KnotSlashed
is not being in use;
SyndicateErrors.sol#L10
Syndicate.sol#L17
Error NotCollateralizedOwnerAtIndex
is not being in use;
SyndicateErrors.sol#L20
Syndicate.sol#L27
There are some events declared that are never emmited, you should remove them or emit them;
ETHDeposited
on StakingFundsVault.sol#L25ERC20Recovered
on StakingFundsVault.sol#L31WETHUnwrapped
on StakingFundsVault.sol#L34forge fmt
or other toolPlease review the solidity coding convention; https://docs.soliditylang.org/en/v0.8.17/style-guide.html
The usually convention is license first, then pragma.
You could go with this on;
#0 - c4-judge
2022-12-02T21:38:48Z
dmvt marked the issue as grade-b