code-423n4 / 2023-03-wenwin-findings

1 stars 1 forks source link

Player who didn't refer anyone receives referral reward #191

Closed code423n4 closed 1 year ago

code423n4 commented 1 year ago

Lines of code

https://github.com/code-423n4/2023-03-wenwin/blob/main/src/ReferralSystem.sol#L145-L149

Vulnerability details

Impact

A player who never referred anyone can receive a referral reward by calling ReferralSystem.claimReferralReward()

Proof of Concept

It appears that ReferralSystem.claimPerDraw() returns referral rewards for a player's own tickets even when that player hasn't referred anyone; this doesn't seem to be the purpose of referral rewards from reading their documentation.

POC: first remove "abstract" keyword from test/ReferralSystemBase.sol so these tests run (I noticed they were not running by default). Then add the following POC test:

function testClaimNoReferrer() public {
    uint128 currentDraw = lottery.currentDraw();

    vm.startPrank(user);                       // no referrer
    buySameTickets(currentDraw, uint120(0x0F), address(0), 1);
    vm.stopPrank();

    executeDraw();

    uint128[] memory drawIds = new uint128[](1);
    drawIds[0] = 0;

    uint prevUserBalance = lotteryToken.balanceOf(user);
    vm.prank(user);

    // this should be zero as the user didn't refer anyone
    uint claimedReward = referralSystem.claimReferralReward(drawIds);
    // this should fail but passes as a referral reward is received anyway,
    // though this is less than if the user self-referred (see my other report)
    assert(claimedReward > 0);
    console.log(claimedReward); // outputs 961538500000000000000000

    uint afterUserBalance = lotteryToken.balanceOf(user);

    // user balance has increased
    assert(afterUserBalance > prevUserBalance);

    uint diffUserBalance = afterUserBalance - prevUserBalance;

    // proves that the users balance has increased by the claimed referral reward
    assertEq(diffUserBalance, claimedReward);
}

Tools Used

manual inspection

Recommended Mitigation Steps

Change ReferralSystem.claimPerDraw() to not return referral rewards simply for buying tickets, when the player has not actually referred anyone.

code423n4 commented 1 year ago

Withdrawn by dacian