Open hats-bug-reporter[bot] opened 2 months ago
It is indeed possible to call revokeHumanity
to prevent its transfer. Note that if the humanity was valid, the actor preventing the transfer will lose its deposit.
As you pointed it out in the report, in order to prevent a malicious actor from continuously preventing the transfer of a humanity (even if it is at the cost of continuously losing deposits), we have a failed revocation cooldown making sure that the owner of the humanity can transfer it after a unique invalid revocation request.
Therefore the issue you are reporting has already been mitigated.
Hey @clesaege, I understand the attacker loses their deposit in a failed revocation attempt, but that’s precisely why this is a griefing attack. The attacker doesn’t care about losing the deposit. They just want to disrupt the user. The failedRevocationCooldown
doesn’t prevent the griefing attack because the user can still be blocked when trying to transfer their humanity. Furthermore, a griefing attack is a scenario that can occur at least once. If this were continuously replicable, it would be closer to a DoS attack that could break the protocol entirely.
Transferring humanity is in many scenarios urgent, like when a user needs to participate in DeFi. If they fall victim to a griefing attack, they’re blocked from participating until the revocation is resolved, potentially leading to indirect financial loss.
As a result, this issue still stands and represents a valid griefing attack scenario.
Transferring humanity is in many scenarios urgent, like when a user needs to participate in DeFi.
Users can never have an expectation of a fast transfer from one platform to another as humanities can be targeted by revocation requests. They can still bridge using updateHumanity
.
Users can be the target of revocation requests at any time, preventing immediate transfer, but after a request there is a cooldown to allow them to transfer. This is the expected behaviour (similar to how you can delay a registration by challenging a request, this is OK as it costs the delayer money and the duration you are able to delay has an upper bound).
Github username: -- Twitter username: -- Submission hash (on-chain): 0x5b04fef3722428ddf8d912712de4e38e8e07b13a1d8186d47efc6bc5d92fb5e8 Severity: medium
Description: Description\ When a user wants to transfer his humanity to another chain, he has to call the
transferHumanity()
function ofCrossChainProofOfHumanity.sol
.transferHumanity()
callsccDischargeHumanity(msg.sender)
in order to discharge the humanity directly from the user. However, a malicious actor can front-run thetransferHumanity()
transaction, and callrevokeHumanity()
with the user's_humanityId
in order to prevent him from transferring, by causing his transaction to revert due tonbPendingRequests != 0
. The user won't be able to calltransferHumanity()
until thependingRevocation
gets resolved. After it gets resolved, the user has a time window equal tofailedRevocationCooldown
to transfer his humanity, if he fails to do so, his nexttransferHumanity()
will also be front-runnable.Attack Scenario\ Alice is a legitimate user with a humanity that wants to transfer to another chain. Bob is a malicious actor that wants to stop Alice from doing so.
Alice calls
transferHumanity()
Bob calls
revokeHumanity()
with Alice's_humanityId
and front-runs Alice.Alice's call gets reverted.
Alice has to wait until the
pendingRevocation
gets resolved.After it gets resolved, Alice has a window of
failedRevocationCooldown
to transfer her humanity.If he fails to do so, Bob can start over and deny her transferring her humanity to another chain.
Attachments
CrossChainProofOfHumanity.sol@L250-289
ProofOfHumanityExtended.sol@L544-566
ProofOfHumanityExtended.sol@L801-840
The change requires multiple changes to the code, an idea would be to change where the
nbPendingRequests
are incremented, for example, they could be incremented inchallengeRequest
instead.