-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Attackers can conduct a permanent DoS
on others' snapshots.
#30
Comments
MiloTruck marked the issue as not a duplicate |
MiloTruck marked the issue as primary issue |
The crux of this issue is an attacker front-running a user's call to
However, I don't believe it is possible to start a snapshot and call Will check with the sponsor though. A simple fix would be to revert in |
MiloTruck marked the issue as unsatisfactory: |
Fixed this by updating
|
This issue, along with H-7 from the previous audit, presents identical possibilities and impacts. Therefore, I think this issue is indeed valid. |
If you're referring to this line in H-7:
It was written by me. It's not possible because an attacker does not know which block his and the victim's transactions will get included in, and therefore, he will not know which parent block root to generate proofs for. Even if the attacker was a validator, he would have to:
All under 12 seconds.
The number of potential sets of proofs is infinite, it's not possible for one of them to randomly be valid. Given the numerous unlikely conditions required for this to ever occur, I believe QA is appropriate. If you believe validators can pull this off, you need to be able to explain in detail what occurs on the beacon chain at the consensus level. Otherwise, this is just hypothetical speculation. |
MiloTruck removed the grade |
MiloTruck changed the severity to QA (Quality Assurance) |
MiloTruck marked the issue as grade-b |
Lines of code
https://github.com/code-423n4/2024-07-karak/blob/main/src/NativeVault.sol#L126-L162
https://github.com/code-423n4/2024-07-karak/blob/main/src/NativeVault.sol#L448-L474
https://github.com/code-423n4/2024-07-karak/blob/main/src/NativeVault.sol#L476-L495
https://github.com/code-423n4/2024-07-karak/blob/main/src/entities/NativeVaultLib.sol#L110-L144
Vulnerability details
Impact
Attackers can conduct a permanent
DoS
on others' snapshots.Proof of Concept
Let's consider the following scenario:
Alice last called the
startSnapshot()
function 8 days ago and is about to invoke it again.Bob, the attacker, executes the following two functions in succession by front-running Alice within the same block:
validateExpiredSnapshot()
function, usingnodeOwner
set to Alice.validateSnapshotProofs()
function, withnodeOwner
as Alice andbalanceProofs
containing all of Alice's validators.As a result:
The snapshot started by Bob is finalized. At this point:
validatorDetails.lastBalanceUpdateTimestamp
is set tonode.currentSnapshotTimestamp
, which isblock.timestamp
.This occurs for all of Alice's active validators during the NativeVaultLib.validateSnapshotProof() function call within the validateSnapshotProofs() function.
https://github.com/code-423n4/2024-07-karak/blob/main/src/entities/NativeVaultLib.sol#L118-L125
node.currentSnapshotTimestamp
is set to 0 at L487(https://github.com/code-423n4/2024-07-karak/blob/main/src/NativeVault.sol#L487).https://github.com/code-423n4/2024-07-karak/blob/main/src/NativeVault.sol#L487
delete node.currentSnapshotTimestamp;
This happens after all validators are proven, during the _updateSnapshot() function call within the validateSnapshotProofs() function.
Finally, Alice's transaction to call the
startSnapshot()
function succeeds, asnode.currentSnapshotTimestamp == 0
. So,node.currentSnapshotTimestamp
is set toblock.timestamp
at L470, which results invalidatorDetails.lastBalanceUpdateTimestamp == node.currentSnapshotTimestamp == block.timestamp
for all the active validators.https://github.com/code-423n4/2024-07-karak/blob/main/src/NativeVault.sol#L470
From this point forward, Alice's call to
validateSnapshotProofs()
will always revert at L149, as the values ofvalidatorDetails.lastBalanceUpdateTimestamp
andnode.currentSnapshotTimestamp
are now identical. As a result, the validators can never be proven andsnapshot.remainingProofs
is forever stuck at a non-zero value, leading to a permanentDoS
on Alice's snapshot.https://github.com/code-423n4/2024-07-karak/blob/main/src/NativeVault.sol#L149-L151
If this occurs, stakers won't be able to withdraw all ETH staked to the validators. This is because the value of
withdrawableCreditedNodeETH
will never increase since it only increases by snapshot. As a result, thewithdrawableCreditedNodeETH
can't include all withdrawn ethers from validators tonodeAddress
. So, thewithdrawableWei()
function doesn't return proper value.This attack is available even when the nodeOwner calls
startSnapshot()
with the parameterrevertIfNoBalanceChange
as true. The attacker can circumvent a revert by donating 1 wei to nodeAddress between steps 2 and 3. (Donations are feasible because the NativeNode inherits from the Ownable contract, which includes the payable functioncancelOwnershipHandover()
, allowing anyone to call it. Even in the absence of the payable function cancelOwnershipHandover(), there are alternative methods available.)Tools Used
Manual review
Recommended Mitigation Steps
There should be a mechanism in place to prevent double snapshots from occurring within the same block.
Assessed type
DoS
The text was updated successfully, but these errors were encountered: