In the LikeRegistry::matchRewards function, the LikeRegistry::userBalances mapping values are being reset to 0, which could result in the uneven distribution of funds especially in case of multiple matches having a common underlying user, by transferring lesser ether amount than expected to one of the MultiSigWallet contracts and more ether amount than expected to the other.
Uneven distribution of funds to the deployed MultiSigWallet contracts corresponding to the matches.
Bob executes the LikeRegistry::likeUser function, passing the address of Alice and attaching 1 ether as msg.value.
Now, the value of userBalances[Alice] is 1 ether.
Jack also executes the LikeRegistry::likeUser function, passing the address of Alice and attaching 1 ether as msg.value.
Now, the value of userBalances[Alice] is 2 ether.
Alice executes the LikeRegistry::likeUser function, passing the address of Bob and attaching 1 ether as msg.value.
Now, the value of userBalances[Bob] is 1 ether.
Now, since the like of Bob-Alice is mutual, when Alice executes the LikeRegistry::likeUser function, the likes[liked][msg.sender] value will be true, triggering the call to the LikeRegistry::matchRewards function.
In the LikeRegistry::matchRewards function, the value of totalRewards would be 3 ether (i.e., the sum of userBalances[Bob] and userBalances[Alice]), and the values of userBalances[Bob] and userBalances[Alice] would be reset to 0.
The MultiSigWallet contract corresponding to Bob-Alice match (say MultiSigWallet_BobAlice) is deployed and funded with 3 ether minus 10% FEE (0.3 ether), that makes the balance of the MultiSigWallet_BobAlice as 2.7 ether.
Alice executes the LikeRegistry::likeUser function, passing the address of Jack and attaching 1 ether as msg.value.
Now, the value of userBalances[Jack] is 1 ether, but the value of userBalances[Alice] is 0.
Now, since the like of Jack-Alice is mutual, when Alice executes the LikeRegistry::likeUser function, the likes[liked][msg.sender] value will be true, triggering the call to the LikeRegistry::matchRewards function.
In the LikeRegistry::matchRewards function, the value of totalRewards would be 1 ether (i.e., the sum of userBalances[Jack] and userBalances[Alice]), and the value of userBalances[Jack] and userBalances[Alice] would be reset to 0.
The MultiSigWallet contract corresponding to Jack-Alice match (say MultiSigWallet_JackAlice) is deployed and funded with 1 ether minus 10% FEE (0.1 ether), that makes the balance of the MultiSigWallet_JackAlice as 0.9 ether.
Ideally, the balance of MultiSigWallet_BobAlice should be equal to MultiSigWallet_JackAlice, with both being 1.8 ether. However, as seen above, the balance of MultiSigWallet_BobAlice is 2.7 ether, while the balance of MultiSigWallet_JackAlice is only 0.9 ether.
All of this happened due to the uneven distribution of funds resulting from Alice being the common underlying user in both the matches.
Since there isn't a way to track MultiSigWallet contract address corresponding to the match, therefore I've added the return statements in the LikeRegistry::likeUser and LikeRegistry::matchRewards functions, basically a kind of mutation testing.
So, the revised LikeRegistry::likeUser and LikeRegistry::matchRewards functions would be:
Then, create a test file named as DatingDappTest.t.sol inside the test folder with the following content:
On executing forge test --mt testUnevenFundsInMultiSigsOnMultipleMatches -vvv command, the output logs would be:
In the LikeRegistry::matchRewards function, instead of resetting the LikeRegistry::userBalances mapping values to 0, you can add if-else conditions to decrement the values of userBalances by 1 ether if their value is more than 1 ether, otherwise reset them to 0. And, instead of assigning the matchUserOne and matchUserTwo with the values of userBalances[from] and userBalances[to] respectively, you can assign them as 1 ether.
Likelihood: High, always. Impact: High, loss of funds
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.