Beginner FriendlyFoundryNFT
100 EXP
View results
Submission Details
Severity: high
Valid

Wrong check for divorce status in `Airdrop.claim()`

Vulnerability Details

Wrong check for divorce status in Airdrop.claim() lead to possibility to collect LoveToken even if the user is divorced.

POC

When we call soulmateContract.isDivorced() from Airdrop.claim() the msg.sender will be Airdrop contract address, who can never be in a Soulmate.divorced mapping.

Add this test to AirdropTest.t.sol and run via forge test --mt test_Divorce to see it success.

function test_Divorce() public {
_mintOneTokenForBothSoulmates();
vm.prank(soulmate1);
soulmateContract.getDivorced();
assertTrue(soulmateContract.isDivorced() == true);
vm.warp(block.timestamp + 200 days + 1 seconds);
vm.prank(soulmate1);
airdropContract.claim();
assertTrue(loveToken.balanceOf(soulmate1) == 200 ether);
vm.prank(soulmate2);
airdropContract.claim();
assertTrue(loveToken.balanceOf(soulmate2) == 200 ether);
}

Output:

Running 1 test for test/unit/AirdropTest.t.sol:AirdropTest
[PASS] test_Divorce() (gas: 403677)
Test result: ok. 1 passed; 0 failed; 0 skipped; finished in 1.84ms

Tools Used

Manual review, foundry.

Recommendations

Make the following changes in Solmate.isDivorced()
https://github.com/Cyfrin/2024-02-soulmate/blob/b3f9227942ffd5c443ce6bccaa980fea0304c38f/src/Soulmate.sol#L131C1-L133C6

- function isDivorced() public view returns (bool) {
+ function isDivorced(address soulmate) public view returns (bool) {
- return divorced[msg.sender];
+ return divorced[soulmate];
}

Make the following changes in ISoulmate
https://github.com/Cyfrin/2024-02-soulmate/blob/b3f9227942ffd5c443ce6bccaa980fea0304c38f/src/interface/ISoulmate.sol#L28

interface ISoulmate {
...
- function isDivorced() external view returns (bool);
+ function isDivorced(address soulmate) external view returns (bool);
...
}

Make the following changes in Airdrop.claim()
https://github.com/Cyfrin/2024-02-soulmate/blob/b3f9227942ffd5c443ce6bccaa980fea0304c38f/src/Airdrop.sol#L53

function claim() public {
// No LoveToken for people who don't love their soulmates anymore.
- if (soulmateContract.isDivorced()) revert Airdrop__CoupleIsDivorced();
+ if (soulmateContract.isDivorced(msg.sender)) revert Airdrop__CoupleIsDivorced();
// Calculating since how long soulmates are reunited
uint256 numberOfDaysInCouple = (block.timestamp -
soulmateContract.idToCreationTimestamp(
soulmateContract.ownerToId(msg.sender)
)) / daysInSecond;
uint256 amountAlreadyClaimed = _claimedBy[msg.sender];
if (
amountAlreadyClaimed >=
numberOfDaysInCouple * 10 ** loveToken.decimals()
) revert Airdrop__PreviousTokenAlreadyClaimed();
uint256 tokenAmountToDistribute = (numberOfDaysInCouple *
10 ** loveToken.decimals()) - amountAlreadyClaimed;
// Dust collector
if (
tokenAmountToDistribute >=
loveToken.balanceOf(address(airdropVault))
) {
tokenAmountToDistribute = loveToken.balanceOf(
address(airdropVault)
);
}
_claimedBy[msg.sender] += tokenAmountToDistribute;
emit TokenClaimed(msg.sender, tokenAmountToDistribute);
loveToken.transferFrom(
address(airdropVault),
msg.sender,
tokenAmountToDistribute
);
}
Updates

Lead Judging Commences

0xnevi Lead Judge over 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

finding-isDivorced-wrong-check

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.