HIGH severity: Delegators incorrectly receive less rewards for longer proposals with multiple delegations. **Description:** Delegators incorrectly receive less rewards for longer proposals with multiple delegations as [retrieving the expected rewards](https://github.com/dexe-network/DeXe-Protocol/tree/f2fe12eeac0c4c63ac39670912640dc91d94bda5/contracts/libs/gov/gov-pool/GovPoolMicropool.sol#L145-L157)...

Vulnerable code:
async function changeInternalSettings2(validatorsVote, duration) {
      let GOV_POOL_SETTINGS = JSON.parse(JSON.stringify(POOL_PARAMETERS.settingsParams.proposalSettings[1]));
      GOV_POOL_SETTINGS.validatorsVote = validatorsVote;
      GOV_POOL_SETTINGS.duration = duration;

      await executeValidatorProposal(
        [
          [settings.address, 0, getBytesAddSettings([GOV_POOL_SETTINGS])],
          [settings.address, 0, getBytesChangeExecutors([govPool.address, settings.address], [4, 4])],
        ],
        []
      );
    }

it("audit micropool rewards short-change delegator for long proposals with multiple delegations", async () => {
        // so proposals will be active in voting state for longer
        const WEEK = (30 * 24 * 60 * 60) / 4;
        const TWO_WEEKS = WEEK * 2;
        const MONTH = TWO_WEEKS * 2;
        const TWO_MONTHS = MONTH * 2;

        // so proposal doesn't need to go to validators
        await changeInternalSettings2(false, TWO_MONTHS);

        // required for executing the first 2 proposals
        await govPool.deposit(govPool.address, wei("200"), []);

        // create 4 proposals; only the first 2 will be executed
        // create proposal 1
        await govPool.createProposal(
          "example.com",
          [[govPool.address, 0, getBytesGovVote(4, wei("100"), [], true)]],
          [[govPool.address, 0, getBytesGovVote(4, wei("100"), [], false)]]
        );
        // create proposal 2
        await govPool.createProposal(
          "example.com",
          [[govPool.address, 0, getBytesGovVote(5, wei("100"), [], true)]],
          [[govPool.address, 0, getBytesGovVote(5, wei("100"), [], false)]]
        );
        // create proposal 3
        await govPool.createProposal(
          "example.com",
          [[govPool.address, 0, getBytesGovVote(5, wei("100"), [], true)]],
          [[govPool.address, 0, getBytesGovVote(5, wei("100"), [], false)]]
        );
        // create proposal 4
        await govPool.createProposal(
          "example.com",
          [[govPool.address, 0, getBytesGovVote(5, wei("100"), [], true)]],
          [[govPool.address, 0, getBytesGovVote(5, wei("100"), [], false)]]
        );

        let proposal1Id = 2;
        let proposal2Id = 3;
        let DELEGATEE = await accounts(10);
        let DELEGATOR1 = await accounts(9);

        let delegator1Tokens = wei("200000000000000000000");
        let delegator1Half = wei("100000000000000000000");

        let delegateeReward = wei("40000000000000000000");
        let delegator1Reward = wei("160000000000000000000");

        // mint tokens & deposit them to have voting power
        await token.mint(DELEGATOR1, delegator1Tokens);
        await token.approve(userKeeper.address, delegator1Tokens, { from: DELEGATOR1 });
        await govPool.deposit(DELEGATOR1, delegator1Tokens, [], { from: DELEGATOR1 });

        // delegator1 delegates its total voting power to AUDITOR
        await govPool.delegate(DELEGATEE, delegator1Tokens, [], { from: DELEGATOR1 });

        // DELEGATEE votes on the first proposal
        await govPool.vote(proposal1Id, true, "0", [], { from: DELEGATEE });

        // advance time
        await setTime((await getCurrentBlockTime()) + 1);

        // proposal now in SucceededFor state
        assert.equal(await govPool.getProposalState(proposal1Id), ProposalState.SucceededFor);

        // execute proposal 1
        await govPool.execute(proposal1Id);

        // verify pending rewards via GovPool::getPendingRewards()
        let pendingRewards = await govPool.getPendingRewards(DELEGATEE, [proposal1Id]);

        assert.deepEqual(pendingRewards.onchainTokens, [rewardToken.address]);
        assert.equal(pendingRewards.votingRewards[0].personal, "0");
        assert.equal(pendingRewards.votingRewards[0].micropool, delegateeReward);
        assert.equal(pendingRewards.votingRewards[0].treasury, "0");

        pendingRewards = await govPool.getPendingRewards(DELEGATOR1, [proposal1Id]);

        assert.deepEqual(pendingRewards.onchainTokens, [rewardToken.address]);
        assert.equal(pendingRewards.votingRewards[0].personal, "0");
        assert.equal(pendingRewards.votingRewards[0].micropool, "0");
        assert.equal(pendingRewards.votingRewards[0].treasury, "0");

        // verify pending delegator rewards via GovPool::getDelegatorRewards()
        pendingRewards = await govPool.getDelegatorRewards([proposal1Id], DELEGATOR1, DELEGATEE);
        assert.deepEqual(pendingRewards.rewardTokens, [rewardToken.address]);
        assert.deepEqual(pendingRewards.isVoteFor, [true]);
        assert.deepEqual(pendingRewards.isClaimed, [false]);
        // delegator1 receives full reward for all tokens they delegated
        assert.deepEqual(pendingRewards.expectedRewards, [delegator1Reward]);

        // reward balances 0 before claiming rewards
        assert.equal((await rewardToken.balanceOf(DELEGATEE)).toFixed(), "0");
        assert.equal((await rewardToken.balanceOf(DELEGATOR1)).toFixed(), "0");

        // claim rewards
        await govPool.claimRewards([proposal1Id], { from: DELEGATEE });
        await govPool.claimMicropoolRewards([proposal1Id], DELEGATEE, { from: DELEGATOR1 });

        // verify reward balances after claiming rewards
        assert.equal((await rewardToken.balanceOf(DELEGATEE)).toFixed(), delegateeReward);
        assert.equal((await rewardToken.balanceOf(DELEGATOR1)).toFixed(), delegator1Reward);

        assert.equal(await govPool.getProposalState(proposal2Id), ProposalState.Voting);

        // delegator1 undelegates half of its total voting power from DELEGATEE,
        // such that DELEGATEE only has half the voting power for second proposal
        await govPool.undelegate(DELEGATEE, delegator1Half, [], { from: DELEGATOR1 });

        // DELEGATEE votes on the second proposal for the first time using the first
        // half of DELEGATOR1's voting power. This isn't enough to decide the proposal
        await govPool.vote(proposal2Id, true, "0", [], { from: DELEGATEE });

        // time advances 1 month, proposal is a longer proposal so still in voting state
        await setTime((await getCurrentBlockTime()) + MONTH);

        // delegator1 delegates remaining half of its voting power to DELEGATEE
        // this cancels the previous vote and re-votes with the full voting power
        // which will be enough to decide the proposal
        await govPool.delegate(DELEGATEE, delegator1Half, [], { from: DELEGATOR1 });

        // advance time
        await setTime((await getCurrentBlockTime()) + 1);

        // proposal now in SucceededFor state
        assert.equal(await govPool.getProposalState(proposal2Id), ProposalState.SucceededFor);

        // execute proposal 2
        await govPool.execute(proposal2Id);

        // verify pending rewards via GovPool::getPendingRewards()
        pendingRewards = await govPool.getPendingRewards(DELEGATEE, [proposal2Id]);

        assert.deepEqual(pendingRewards.onchainTokens, [rewardToken.address]);
        assert.equal(pendingRewards.votingRewards[0].personal, "0");
        // delegatee getting paid the full rewards for the total voting power
        // delegator1 delegated
        assert.equal(pendingRewards.votingRewards[0].micropool, delegateeReward);
        assert.equal(pendingRewards.votingRewards[0].treasury, "0");

        pendingRewards = await govPool.getPendingRewards(DELEGATOR1, [proposal2Id]);

        assert.deepEqual(pendingRewards.onchainTokens, [rewardToken.address]);
        assert.equal(pendingRewards.votingRewards[0].personal, "0");
        assert.equal(pendingRewards.votingRewards[0].micropool, "0");
        assert.equal(pendingRewards.votingRewards[0].treasury, "0");

        // verify pending delegator rewards via GovPool::getDelegatorRewards()
        pendingRewards = await govPool.getDelegatorRewards([proposal2Id], DELEGATOR1, DELEGATEE);
        assert.deepEqual(pendingRewards.rewardTokens, [rewardToken.address]);
        assert.deepEqual(pendingRewards.isVoteFor, [true]);
        assert.deepEqual(pendingRewards.isClaimed, [false]);

        // fails as delegator1 only paid half the rewards - not being paid for the
        // full amount it delegated!
        assert.deepEqual(pendingRewards.expectedRewards, [delegator1Reward]);
      });