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: 7/92
Findings: 10
Award: $3,013.55
🌟 Selected for report: 5
🚀 Solo Findings: 2
🌟 Selected for report: c7e7eff
Also found by: 0x4non, 9svR6w, HE1M, Jeiwan, Trust, aphak5010, arcoun, cccz, clems4ever, corerouter, koxuan, rotcivegaf, unforgiven
40.8568 USDC - $40.86
https://github.com/code-423n4/2022-11-stakehouse/blob/4b6828e9c807f2f7c569e6d721ca1289f7cf7112/contracts/liquid-staking/SyndicateRewardsProcessor.sol#L51 https://github.com/code-423n4/2022-11-stakehouse/blob/4b6828e9c807f2f7c569e6d721ca1289f7cf7112/contracts/liquid-staking/SyndicateRewardsProcessor.sol#L63
The StakingFundsVault
is used to stake 4 ETH. The stakers of the 4 ETH then get rewarded 50% of the fees of the validator according to the amount of ETH that they have staked. The rewards are actually distributed in the SyndiacteRewardsProcessor._distributeRewardsToUserForToken
function (https://github.com/code-423n4/2022-11-stakehouse/blob/4b6828e9c807f2f7c569e6d721ca1289f7cf7112/contracts/liquid-staking/SyndicateRewardsProcessor.sol#L51).
The problem is that in this function, the total claimed ETH of a staker is not calculated correctly.
It is currently calculated as:
claimed[_user][_token] = due;
But it should be calculated as:
claimed[_user][_token] += due;
Currently when the function is called, previous reward payouts are forgotten about.
This allows a staker to receive more rewards then he should be able to, causing a loss of funds for the other stakers.
The issue can be seen easily by the following scenario:
claimed["Bob"][token] = 1 ETH
)StakingFundsVault
receives rewards such that Bob should now be able to claim another 2 ETHStakingFundsVault.claimRewards
function is called by Bob which in turn calls SyndiacteRewardsProcessor._distributeRewardsToUserForToken
. Bob receives 2 ETH and the wrong value is set for his claimed rewards (claimed["Bob"][token] = 2 ETH
instead of claimed["Bob"][token] = 3 ETH
)VSCode
Change:
claimed[_user][_token] = due;
to:
claimed[_user][_token] += due;
#0 - c4-judge
2022-11-20T22:19:46Z
dmvt marked the issue as duplicate of #59
#1 - c4-judge
2022-11-29T16:49:14Z
dmvt marked the issue as satisfactory
#2 - C4-Staff
2022-12-21T05:47:07Z
JeeberC4 marked the issue as duplicate of #147
🌟 Selected for report: 9svR6w
Also found by: JTJabba, aphak5010, unforgiven
410.1163 USDC - $410.12
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/GiantMevAndFeesPool.sol#L170 https://github.com/code-423n4/2022-11-stakehouse/blob/4b6828e9c807f2f7c569e6d721ca1289f7cf7112/contracts/liquid-staking/StakingFundsVault.sol#L343
This issue exists in GiantMevAndFeesPool
as well as in StakingFundsVault
.
From here on I will explain the issue based on the GiantMevAndFeesPool
but the explanation can be transferred easily to the StakingFundsVault
.
The holders of a GiantMevAndFeesPool
s GiantLP
tokens receive a share of the staking rewards.
In order to handle the rewards correctly in case the tokens are transferred, the GiantMevAndFeesPool
implements the beforeTokenTransfer
(https://github.com/code-423n4/2022-11-stakehouse/blob/4b6828e9c807f2f7c569e6d721ca1289f7cf7112/contracts/liquid-staking/GiantMevAndFeesPool.sol#L146) and afterTokenTransfer
(https://github.com/code-423n4/2022-11-stakehouse/blob/4b6828e9c807f2f7c569e6d721ca1289f7cf7112/contracts/liquid-staking/GiantMevAndFeesPool.sol#L170) functions.
The beforeTokenTransfer
function sends all pending rewards to the sender and receiver of the token transfer.
The afterTokenTransfer
functions updates the amount of claimed rewards for the receiver of the token transfer. This is done to disallow the receiver to claim rewards for tokens that the sender has already claimed rewards for.
The problem is that the claimed rewards for the sender are not adapted in the afterTokenTransfer
.
The claimed rewards for the sender should be lowered to reflect the sender's now lower balance.
This causes the sender to miss out on future rewards (-> loss of funds).
Consider the following scenario:
beforeTokenTransfer
is called and rewards for Alice and Bob are claimed (5 ETH for Alice and 5 ETH for Bob)afterTokenTransfer
function is executed. Bob's claimed amount will be set to 6 ETH, reflecting his new balance of 6 GiantLP.VSCode
In the afterTokenTransfer
function call _setClaimedToMax(_from)
:
- function afterTokenTransfer(address, address _to, uint256) external { + function afterTokenTransfer(address _from, address _to, uint256) external { require(msg.sender == address(lpTokenETH), "Caller is not giant LP"); _setClaimedToMax(_to); + _setClaimedToMax(_from); }
#0 - c4-judge
2022-11-21T13:50:43Z
dmvt marked the issue as duplicate of #179
#1 - c4-judge
2022-11-21T22:18:40Z
dmvt marked the issue as duplicate of #178
#2 - c4-judge
2022-12-01T20:38:07Z
dmvt marked the issue as satisfactory
8.8271 USDC - $8.83
https://github.com/code-423n4/2022-11-stakehouse/blob/4b6828e9c807f2f7c569e6d721ca1289f7cf7112/contracts/liquid-staking/ETHPoolLPFactory.sol#L82 https://github.com/code-423n4/2022-11-stakehouse/blob/4b6828e9c807f2f7c569e6d721ca1289f7cf7112/contracts/liquid-staking/GiantPoolBase.sol#L96 https://github.com/code-423n4/2022-11-stakehouse/blob/4b6828e9c807f2f7c569e6d721ca1289f7cf7112/contracts/liquid-staking/SavETHVault.sol#L141 https://github.com/code-423n4/2022-11-stakehouse/blob/4b6828e9c807f2f7c569e6d721ca1289f7cf7112/contracts/liquid-staking/StakingFundsVault.sol#L184 https://github.com/code-423n4/2022-11-stakehouse/blob/4b6828e9c807f2f7c569e6d721ca1289f7cf7112/contracts/liquid-staking/StakingFundsVault.sol#L230 https://github.com/code-423n4/2022-11-stakehouse/blob/4b6828e9c807f2f7c569e6d721ca1289f7cf7112/contracts/liquid-staking/GiantLP.sol#L17 https://github.com/code-423n4/2022-11-stakehouse/blob/4b6828e9c807f2f7c569e6d721ca1289f7cf7112/contracts/liquid-staking/GiantLP.sol#L44 https://github.com/code-423n4/2022-11-stakehouse/blob/4b6828e9c807f2f7c569e6d721ca1289f7cf7112/contracts/liquid-staking/GiantLP.sol#L45 https://github.com/code-423n4/2022-11-stakehouse/blob/4b6828e9c807f2f7c569e6d721ca1289f7cf7112/contracts/liquid-staking/LPToken.sol#L20 https://github.com/code-423n4/2022-11-stakehouse/blob/4b6828e9c807f2f7c569e6d721ca1289f7cf7112/contracts/liquid-staking/LPToken.sol#L67 https://github.com/code-423n4/2022-11-stakehouse/blob/4b6828e9c807f2f7c569e6d721ca1289f7cf7112/contracts/liquid-staking/LPToken.sol#L68
The GiantLP
and LPToken
tokens record the last interaction time of a token transfer.
The lastInteractedTimestamp
of an address is updated whenever the address is the sender or receiver of a transfer.
This lastInteractedTimestamp
is then used in the application to allow certain operations only when a certain time since the last token interaction has passed (30 mins or 1 days).
Any user can therefore cause the lastInteractedTimestamp
to be updated by making a token transfer transaction with zero value to the victim address.
So an attacker can deny a victim to perform any of the actions that depend on the checks that are listed below.
For example the attacker can deny the victim to withdraw LP tokens from a Giant Pool or deny him to claim rewards from a StakingFundsVault.
ETHPoolLPFactory.rotateLPTokens
GiantPoolBase._assertUserHasEnoughGiantLPToClaimVaultLP
https://github.com/code-423n4/2022-11-stakehouse/blob/4b6828e9c807f2f7c569e6d721ca1289f7cf7112/contracts/liquid-staking/GiantPoolBase.sol#L96
1 days check
This function in turn is called in GiantSavETHVaultPool.withdrawDETH
and GiantPoolBase.withdrawLPTokens
.
SavETHVault.burnLPToken
StakingFundsVault.burnLPForETH
StakingFundsVault.claimRewards
GiantLP
LPToken
lastInteractedTimestamp
to be updated.VSCode
You might consider to only update the lastInteractedTimestamp
of a user if:
Or
In other words not any sender should be able to update the lastInteractedTimestamp
of a user.
#0 - c4-judge
2022-11-20T15:25:29Z
dmvt marked the issue as duplicate of #49
#1 - c4-judge
2022-11-29T22:48:27Z
dmvt marked the issue as satisfactory
#2 - c4-judge
2022-11-29T22:48:32Z
dmvt marked the issue as partial-50
#3 - c4-judge
2022-11-29T22:48:37Z
dmvt changed the severity to 2 (Med Risk)
115.1607 USDC - $115.16
The GiantPoolBase.withdrawETH
function requires that the amount to withdraw is at least as big as the MIN_STAKING_AMOUNT
(https://github.com/code-423n4/2022-11-stakehouse/blob/4b6828e9c807f2f7c569e6d721ca1289f7cf7112/contracts/liquid-staking/GiantPoolBase.sol#L53).
This check does not serve any purpose and can actually cause the user problems when withdrawing his ETH.
GiantPoolBase.depositETH
function.MIN_STAKING_AMOUNT + 0.99 * MIN_STAKING_AMOUNT
.MIN_STAKING_AMOUNT
ETH from the GiantPool.0.99 * MIN_STAKING_AMOUNT
ETH left in the GiantPool. This is a problem since he cannot withdraw this amount of ETH since it is smaller than MIN_STAKING_AMOUNT
.VSCode
The require(_amount >= MIN_STAKING_AMOUNT, "Invalid amount");
statement should just be removed. It does not serve any purpose anyway.
#0 - c4-judge
2022-11-20T17:03:49Z
dmvt marked the issue as primary issue
#1 - c4-sponsor
2022-11-28T17:59:39Z
vince0656 marked the issue as sponsor confirmed
#2 - c4-judge
2022-11-29T23:09:22Z
dmvt marked the issue as selected for report
#3 - c4-judge
2022-11-30T12:20:38Z
dmvt marked the issue as satisfactory
86.3705 USDC - $86.37
https://github.com/code-423n4/2022-11-stakehouse/blob/4b6828e9c807f2f7c569e6d721ca1289f7cf7112/contracts/liquid-staking/GiantPoolBase.sol#L69 https://github.com/code-423n4/2022-11-stakehouse/blob/4b6828e9c807f2f7c569e6d721ca1289f7cf7112/contracts/liquid-staking/GiantPoolBase.sol#L95
The GiantPoolBase.withdrawLPTokens
function (https://github.com/code-423n4/2022-11-stakehouse/blob/4b6828e9c807f2f7c569e6d721ca1289f7cf7112/contracts/liquid-staking/GiantPoolBase.sol#L69) allows to withdraw LP tokens from a GiantPool by burning an equal amount of GiantLP.
This allows a user to handle the LP tokens directly without the need for a GiantPool as intermediary.
It is not checked however whether the LP tokens to be withdrawn were transferred to the GiantPool in exchange for staking ETH.
I.e. whether the LP token are of any value.
There are two issues associated with this behavior.
A malicious user can create and mint his own LP Token and send it to the GiantPool. Users that want to withdraw LP tokens from the GiantPool can then be tricked into withdrawing worthless attacker LP tokens, thereby burning their GiantLP tokens that are mapped 1:1 to ETH. (-> loss of funds)
This can also mess up internal accounting logic. For every LP token that is owned by a GiantPool there should be a corresponding GiantLP token. Using the described behavior this ratio can be broken such that there are LP token owned by the GiantPool for which there is no GiantLP token. This means some LP token cannot be transferred from the GiantPool and there will always be some amount of LP token "stuck" in the GiantPool.
GiantPoolBase._assertUserHasEnoughGiantLPToClaimVaultLP
(https://github.com/code-423n4/2022-11-stakehouse/blob/4b6828e9c807f2f7c569e6d721ca1289f7cf7112/contracts/liquid-staking/GiantPoolBase.sol#L95).The same issue exists for the GiantSavETHVaultPool.withdrawDETH
function.
But in this case, the victim must also provide a wrong savETHVault address which makes this issue less likely to be exploited.
VSCode
The GiantPool should store information about which LP tokens it receives for staking ETH.
When calling the GiantPoolBase.withdrawLPTokens
function it can then be checked if the LP tokens to be withdrawn were indeed transferred to the GiantPool in exchange for staking ETH.
#0 - c4-judge
2022-11-20T17:34:15Z
dmvt marked the issue as primary issue
#1 - c4-sponsor
2022-11-28T17:59:20Z
vince0656 marked the issue as sponsor confirmed
#2 - c4-judge
2022-11-30T12:33:56Z
dmvt marked the issue as satisfactory
#3 - c4-judge
2022-11-30T12:34:01Z
dmvt marked the issue as selected for report
🌟 Selected for report: aphak5010
877.6151 USDC - $877.62
https://github.com/code-423n4/2022-11-stakehouse/blob/4b6828e9c807f2f7c569e6d721ca1289f7cf7112/contracts/smart-wallet/OwnableSmartWallet.sol#L94 https://github.com/code-423n4/2022-11-stakehouse/blob/4b6828e9c807f2f7c569e6d721ca1289f7cf7112/contracts/smart-wallet/OwnableSmartWallet.sol#L105-L106
The OwnableSmartWallet
contract employs a mechanism for the owner to approve addresses that can then claim ownership (https://github.com/code-423n4/2022-11-stakehouse/blob/4b6828e9c807f2f7c569e6d721ca1289f7cf7112/contracts/smart-wallet/OwnableSmartWallet.sol#L94) of the contract.
The source code has a comment included which states that "Approval is revoked, in order to avoid unintended transfer allowance if this wallet ever returns to the previous owner" (https://github.com/code-423n4/2022-11-stakehouse/blob/4b6828e9c807f2f7c569e6d721ca1289f7cf7112/contracts/smart-wallet/OwnableSmartWallet.sol#L105-L106).
This means that when ownership is transferred from User A to User B, the approvals that User A has given should be revoked.
The existing code does not however revoke all approvals that User A has given. It only revokes one approval.
This can lead to unwanted transfers of ownership.
VSCode
You should invalidate all approvals User A has given when another User becomes the owner of the OwnableSmartWallet.
Unfortunately you cannot use a statement like delete _isTransferApproved[owner()]
.
So you would need an array that keeps track of approvals as pointed out in this StackExchange question: https://ethereum.stackexchange.com/questions/15553/how-to-delete-a-mapping
#0 - c4-judge
2022-11-20T17:43:22Z
dmvt marked the issue as primary issue
#1 - c4-sponsor
2022-11-28T17:59:02Z
vince0656 marked the issue as sponsor confirmed
#2 - c4-judge
2022-11-30T12:37:21Z
dmvt marked the issue as selected for report
#3 - c4-judge
2022-11-30T12:37:27Z
dmvt marked the issue as satisfactory
🌟 Selected for report: aphak5010
877.6151 USDC - $877.62
https://github.com/code-423n4/2022-11-stakehouse/blob/4b6828e9c807f2f7c569e6d721ca1289f7cf7112/contracts/liquid-staking/GiantSavETHVaultPool.sol#L127 https://github.com/code-423n4/2022-11-stakehouse/blob/4b6828e9c807f2f7c569e6d721ca1289f7cf7112/contracts/liquid-staking/GiantMevAndFeesPool.sol#L116 https://github.com/code-423n4/2022-11-stakehouse/blob/4b6828e9c807f2f7c569e6d721ca1289f7cf7112/contracts/liquid-staking/GiantPoolBase.sol#L22
The GiantSavETHVaultPool
and GiantMevAndFeesPool
both have a batchRotateLPTokens
function that allows to move staked ETH to another key.
Both functions require that the GiantLP balance of the sender is >=0.5 ether
.
The reason for this is that there is a common interest
needed in order to rotate LP Tokens.
The way this is implemented right now does not serve this purpose and even makes the functions unable to be called in some cases.
The MIN_STAKING_AMOUNT
for the GiantPools is 0.001 ether
(https://github.com/code-423n4/2022-11-stakehouse/blob/4b6828e9c807f2f7c569e6d721ca1289f7cf7112/contracts/liquid-staking/GiantPoolBase.sol#L22).
So a user should expect that this amount is sufficient to properly use the contract.
However even if there are multiple users paying into the GiantPool, they might not reach the 0.5 ETH threshold to call the function.
So even if they would use some kind of multisig wallet to call the batchRotateLPTokens
function, it would not be possible.
Also the threshold does not scale.
Imagine that User A puts 100 ETH into the GiantPool. Another User B puts 0.5 ETH into the GiantPool.
Can we speak of "common interest" when User B wants to rotate the LP Tokens?
VSCode
My suggestion is to use a formula like:
require(lpTokenETH.balanceOf(msg.sender) >= (lpTokenETH.totalSupply() / CONSTANT_VALUE))
.
Where you can choose a CONSTANT_VALUE like 20 or 50.
This properly scales the required amount and helps mitigate both scenarios.
#0 - c4-judge
2022-11-20T23:38:52Z
dmvt marked the issue as primary issue
#1 - c4-sponsor
2022-11-28T17:34:18Z
vince0656 marked the issue as sponsor confirmed
#2 - c4-judge
2022-11-30T14:10:13Z
dmvt marked the issue as satisfactory
#3 - c4-judge
2022-11-30T14:10:58Z
dmvt marked the issue as selected for report
115.1607 USDC - $115.16
https://github.com/code-423n4/2022-11-stakehouse/blob/4b6828e9c807f2f7c569e6d721ca1289f7cf7112/contracts/liquid-staking/GiantMevAndFeesPool.sol#L82 https://github.com/code-423n4/2022-11-stakehouse/blob/4b6828e9c807f2f7c569e6d721ca1289f7cf7112/contracts/liquid-staking/GiantMevAndFeesPool.sol#L91
The GiantMevAndFeesPool.previewAccumulatedETH
function (https://github.com/code-423n4/2022-11-stakehouse/blob/4b6828e9c807f2f7c569e6d721ca1289f7cf7112/contracts/liquid-staking/GiantMevAndFeesPool.sol#L82) allows to view the ETH that is accumulated by an address.
However the formula is not correct.
In each iteration of the foor loop, accumulated
is assigned a new value (https://github.com/code-423n4/2022-11-stakehouse/blob/4b6828e9c807f2f7c569e6d721ca1289f7cf7112/contracts/liquid-staking/GiantMevAndFeesPool.sol#L91) when actually the value should be updated like this:
accumulated += StakingFundsVault(payable(_stakingFundsVaults[i])).batchPreviewAccumulatedETH( address(this), _lpTokens[i] );
Obviously the accumulated
value must be calculated for all stakingFundVaults not only for one stakingFundsVault.
While this calculation is not used internally by the contract, it will cause any third-party contract that relies on this calculation to behave incorrectly.
For example a third party smart contract might only allow users to withdraw once the value returned by previewAccumulatedETH
reaches a certain threshold. Because of the issue however the accumulated ETH value that is returned will always be too low.
VSCode
Fix:
@@ -88,7 +88,7 @@ contract GiantMevAndFeesPool is ITransferHookProcessor, GiantPoolBase, Syndicate uint256 accumulated; for (uint256 i; i < _stakingFundsVaults.length; ++i) { - accumulated = StakingFundsVault(payable(_stakingFundsVaults[i])).batchPreviewAccumulatedETH( + accumulated += StakingFundsVault(payable(_stakingFundsVaults[i])).batchPreviewAccumulatedETH( address(this), _lpTokens[i] );
#0 - c4-judge
2022-11-20T23:46:41Z
dmvt marked the issue as primary issue
#1 - c4-sponsor
2022-11-28T17:32:08Z
vince0656 marked the issue as sponsor confirmed
#2 - c4-judge
2022-11-30T14:17:53Z
dmvt marked the issue as satisfactory
#3 - c4-judge
2022-11-30T14:18:49Z
dmvt marked the issue as selected for report
6.2548 USDC - $6.25
The LiquidStakingManager.updateNodeRunnerWhitelistStatus
(https://github.com/code-423n4/2022-11-stakehouse/blob/4b6828e9c807f2f7c569e6d721ca1289f7cf7112/contracts/liquid-staking/LiquidStakingManager.sol#L278-L284) function will always revert since isNodeRunnerWhitelisted[_nodeRunner] != isNodeRunnerWhitelisted[_nodeRunner]
always evaluates to false
.
The worst case scenario that I can think of is:
Basically just call the LiquidStakingManager.updateNodeRunnerWhitelistStatus
function and see that it always reverts.
VSCode
Change
require(isNodeRunnerWhitelisted[_nodeRunner] != isNodeRunnerWhitelisted[_nodeRunner], "Unnecessary update to same status");
to
require(isNodeRunnerWhitelisted[_nodeRunner] != isWhitelisted, "Unnecessary update to same status");
#0 - c4-judge
2022-11-20T16:11:20Z
dmvt marked the issue as primary issue
#1 - c4-sponsor
2022-11-28T18:01:31Z
vince0656 marked the issue as sponsor confirmed
#2 - c4-judge
2022-11-30T11:39:51Z
dmvt marked the issue as selected for report
#3 - c4-judge
2022-11-30T11:39:55Z
dmvt marked the issue as not selected for report
#4 - c4-judge
2022-11-30T11:40:03Z
dmvt marked the issue as satisfactory
#5 - C4-Staff
2022-12-21T00:11:18Z
JeeberC4 marked the issue as duplicate of #378
🌟 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
475.5642 USDC - $475.56
Risk | Title | File | Instances |
---|---|---|---|
L-00 | Missing zero-address checks | - | 6 |
L-01 | SavETHVault.isBLSPublicKeyBanned does not behave as stated in comment | SavETHVault.sol | 1 |
L-02 | Implement 2-Step-Process for assigning roles | - | 1 |
N-00 | Unlocked pragma | - | 18 |
N-01 | Move SPDX-License-Identifier to top of the file | - | 12 |
N-02 | Event is missing indexed fields | - | 35 |
N-03 | Variable can be declared immutable | - | 17 |
N-04 | Specify visibility for all state variables | - | 3 |
N-05 | Make public functions that are not called internally external | - | 1 |
When an address is assigned to a variable, it should be checked whether the address is the zero-address.
In most cases it is not intended to assign the zero-address to the variable and it can cause the contract to be unusable.
There are 6 instances of this issue.
The comment documenting the behavior of SavETHVault.isBLSPublicKeyBanned
explains the behavior of the function as "Utility function that proxies through to the liquid staking manager to check whether the BLS key ever registered with the network but is now banned" (https://github.com/code-423n4/2022-11-stakehouse/blob/4b6828e9c807f2f7c569e6d721ca1289f7cf7112/contracts/liquid-staking/SavETHVault.sol#L222).
However when looking at the LiquidStakingManager.isBLSPublicKeyBanned
function (https://github.com/code-423n4/2022-11-stakehouse/blob/4b6828e9c807f2f7c569e6d721ca1289f7cf7112/contracts/liquid-staking/LiquidStakingManager.sol#L500) it becomes clear that the function returns true not only when the public key is banned but also when the public key is not part of the LSD Network. The comment therefore is misleading and can negatively impact any third-party components that rely on it.
In the LiquidStakingManager
contract a 2-Step-Process should be used to set a new DAO address.
Currently the updateDAOAddress
function is used for this (https://github.com/code-423n4/2022-11-stakehouse/blob/4b6828e9c807f2f7c569e6d721ca1289f7cf7112/contracts/liquid-staking/LiquidStakingManager.sol#L239).
There should be a second function called claimDAO
implemented that needs to be called by the new DAO to actually change the DAO address. This prevents setting a wrong DAO address by mistake.
Some of the files in scope use 0.8.13
as the Solidity compiler version.
Others use ^0.8.13
, meaning that the file will compile with versions >=0.8.13
and <0.9.0
.
It is considered best practice to use a locked Solidity version, thereby only allowing compilation with a specific version.
So the instances of ^0.8.13
should be changed to 0.8.13
.
There are 18 instances of this.
It is best practice to move the SPDX-License-Identifier to the top of the source file.
There are 12 instances where the SPDX-License-Identifier is after the Solidity version.
Each event should use three indexed fields if it has three or more fields.
There are 35 instances of events that do not have 3 indexed fields.
immutable
Variables that are only assigned in the constructor should be declared immutable
.
There are 17 instances of this.
All state variables should have their visibility specified which improves readability and avoids misunderstandings.
There are 3 instances of state variables that don't have a visibility specified (the default is internal
).
public
functions that are not called internally external
Functions that are not called internally should be declared external
.
There is 1 instance of this.
#0 - c4-judge
2022-12-01T23:25:53Z
dmvt marked the issue as grade-a