There are two possible scenarios. In both of the scenarios the ultimate moto of the Attacker
will be to drain the funds from the Airdrop Vault
. Attacker
will exploit the vulnerability that is in Soulmate::idToCreationTimestamp
function. Furthermore, there is no restriction/validation that msg.sender
actually owns any SoulmateToken
.
Soulmate
token is mintedIn this scenario the attacker can immediately drain all the 500m tokens from the Airdrop Vault
.
Attacker
will first find out the total balance
of Love Tokens
held within the Airdrop Vault
. Then he will try to replicate the logic of calculating Airdrop::claim::numberOfDaysInCouple
variable and he will divide the block.timstamp
with the daysInSecond
it will result into the number of tokens that can be claimed in one call. Then the attacker will divide the balance / 1e18
with the number of tokens he can claim in one call this is how attacker will compute the total calls (total number of addresses) that he needs.
Now Attacker
will call Airdrop::claim
function (the above) number of calculated times with different addresses and the attack succceeds. Proof of Concept
is also provided in the following section of this report.
In below snippet source line of vulnerability is pointed, in which Airdrop::claim::numberOfDaysInCouple
will always be a big number because 0
will be subtracted from block.timestamp
because in our scenario Soulmate::idToCreationTimestamp
function will always return 0
.
Airdrop.sol:
https://github.com/Cyfrin/2024-02-soulmate/blob/b3f9227942ffd5c443ce6bccaa980fea0304c38f/src/Airdrop.sol#L51C5-L89C6
Soulmate
tokens are mintedIn this scenario the attacker will drain the remaining tokens from the Airdrop Vault
. Attacker
will first find out the total balance
of Love Tokens
remaining in the Airdrop Vault
. In this scenario, the higher the number of days passed (since first token was minted) the higher the number of tokens Attacker
can claim in a call.
In this scenario Soulmate::idToCreationTimestamp
function will always return the creation time of first SoulmateToken
id.
The Attacker
will again compute the total calls (total number of addresses) that he needs in order to drain all the remaining LoveTokens
in Airdrop Vault
.
Now Attacker
will call Airdrop::claim
function (the above) number of calculated times with different addresses and the attack succceeds. For clarity, in the PoC
each and every line is commented.
Please note that source of the code is same as provided in Scenario 1
.
In this scenario the attacker can immediately drain all the 500m tokens from the Airdrop Vault
.
In this scenario the attacker can drain all remaining tokens from the Airdrop Vault
.
Manual Review
We should implement multiple mitigations as below:
because there are number of external calls, we should use reentrancy guard
Soulmate::nextID
shoule be incremented before updating the state
Airdrop.sol:
Soulmate::nextID
increment and validation in Airdrop.sol
Soulmate.sol:
Airdrop.sol:
High severity, This issue is separated from the flawed `isDivorced()` check presented in issue #168 as even if that is fixed, if ownership is not checked, isDivorced would still default to false and allow bypass to claim airdrops by posing as tokenId 0 in turn resulting in this [important check for token claim is bypassed.](https://github.com/Cyfrin/2024-02-soulmate/blob/b3f9227942ffd5c443ce6bccaa980fea0304c38f/src/Airdrop.sol#L61-L66). #220 is the most comprehensive issue as it correctly recognizes both issues existing within the same function.
High severity, This issue is separated from the flawed `isDivorced()` check presented in issue #168 as even if that is fixed, if ownership is not checked, isDivorced would still default to false and allow bypass to claim airdrops by posing as tokenId 0 in turn resulting in this [important check for token claim is bypassed.](https://github.com/Cyfrin/2024-02-soulmate/blob/b3f9227942ffd5c443ce6bccaa980fea0304c38f/src/Airdrop.sol#L61-L66). #220 is the most comprehensive issue as it correctly recognizes both issues existing within the same function.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.