Vulnerability: Delegation Limitation in Voting Power Management
Severity: medium

Description:
MgCVG Voting power delegation system is constrained by 2 hard limits, first on the number of tokens delegated to one user (maxTokenIdsDelegated = 25) and second on the number of delegatees for one token ( maxMgDelegatees = 5). Once this limit is reached for a token, the token owner cannot modify the delegation percentage to an existing delegated user. This inflexibility can prevent efficient and dynamic management of delegated voting power.\\nObserve these lines :\\n```\\nfunction delegateMgCvg(uint256 _tokenId, address _to, uint96 _percentage) external onlyTokenOwner(_tokenId) {\\n    require(_percentage <= 100, "INVALID_PERCENTAGE");\\n\\n    uint256 _delegateesLength = delegatedMgCvg[_tokenId].length;\\n    require(_delegateesLength < maxMgDelegatees, "TOO_MUCH_DELEGATEES");\\n\\n    uint256 tokenIdsDelegated = mgCvgDelegatees[_to].length;\\n    require(tokenIdsDelegated < maxTokenIdsDelegated, "TOO_MUCH_MG_TOKEN_ID_DELEGATED");\\n```\\n\\nif either `maxMgDelegatees` or `maxTokenIdsDelegated` are reached, delegation is no longer possible. The problem is the fact that this function can be either used to delegate or to update percentage of delegation or also to remove a delegation but in cases where we already delegated to a maximum of users (maxMgDelegatees) OR the user to who we delegated has reached the maximum number of tokens that can be delegated to him/her (maxTokenIdsDelegated), an update or a removal of delegation is no longer possible.\\n6 scenarios are possible :\\n`maxTokenIdsDelegated` is set to 5, Alice is the third to delegate her voting power to Bob and choose to delegate 10% to him. Bob gets 2 other people delegating their tokens to him, Alice wants to increase the power delegated to Bob to 50% but she cannot due to Bob reaching `maxTokenIdsDelegated`\\n`maxTokenIdsDelegated` is set to 25, Alice is the 10th to delegate her voting power to Bob and choose to delegate 10%, DAO decrease `maxTokenIdsDelegated` to 3, Alice wants to increase the power delegated to Bob to 50%, but she cannot due to this\\n`maxTokenIdsDelegated` is set to 5, Alice is the third to delegate her voting power to Bob and choose to delegate 90%. Bob gets 2 other people delegating their tokens to him, Alice wants to only remove the power delegated to Bob using this function, but she cannot due to this\\n`maxMgDelegatees` is set to 3, Alice delegates her voting power to Bob,Charly and Donald by 20% each, Alice reaches `maxMgDelegatees` and she cannot update her voting power for any of Bob,Charly or Donald\\n`maxMgDelegatees` is set to 5, Alice delegates her voting power to Bob,Charly and Donald by 20% each,DAO decreasesmaxMgDelegatees to 3. Alice cannot update or remove her voting power delegated to any of Bob,Charly and Donald\\n`maxMgDelegatees` is set to 3, Alice delegates her voting power to Bob,Charly and Donald by 20% each, Alice wants to only remove her delegation to Bob but she reached `maxMgDelegatees` so she cannot only remove her delegation to Bob\\nA function is provided to remove all user to who we delegated but this function cannot be used as a solution to this problem due to 2 things :\\nIt's clearly not intended to do an update of voting power percentage by first removing all delegation we did because `delegateMgCvg()` is clearly defined to allow to delegate OR to remove one delegation OR to update percentage of delegation but in some cases it's impossible which is not acceptable\\nif Alice wants to update it's percentage delegated to Bob , she would have to remove all her delegatees and would take the risk that someone is faster than her and delegate to Bob before her, making Bob reaches `maxTokenIdsDelegated` and would render impossible for Alice to re-delegate to Bob\\nPOC\\nYou can add it to test/ut/delegation/balance-delegation.spec.ts :\\n```\\nit("maxTokenIdsDelegated is reached => Cannot update percentage of delegate", async function () {\\n        (await lockingPositionDelegate.maxTokenIdsDelegated()).should.be.equal(25);\\n        await lockingPositionDelegate.connect(treasuryDao).setMaxTokenIdsDelegated(3);\\n        (await lockingPositionDelegate.maxTokenIdsDelegated()).should.be.equal(3);\\n\\n        await lockingPositionDelegate.connect(user1).delegateMgCvg(1, user10, 20);\\n        await lockingPositionDelegate.connect(user2).delegateMgCvg(2, user10, 30);\\n        await lockingPositionDelegate.connect(user3).delegateMgCvg(3, user10, 30);\\n        \\n        const txFail = lockingPositionDelegate.connect(user1).delegateMgCvg(1, user10, 40);\\n        await expect(txFail).to.be.revertedWith("TOO_MUCH_MG_TOKEN_ID_DELEGATED");\\n    });\\n    it("maxTokenIdsDelegated IS DECREASED => PERCENTAGE UPDATE IS NO LONGER POSSIBLE", async function () {\\n        await lockingPositionDelegate.connect(treasuryDao).setMaxTokenIdsDelegated(25);\\n        (await lockingPositionDelegate.maxTokenIdsDelegated()).should.be.equal(25);\\n\\n        await lockingPositionDelegate.connect(user1).delegateMgCvg(1, user10, 20);\\n        await lockingPositionDelegate.connect(user2).delegateMgCvg(2, user10, 30);\\n        await lockingPositionDelegate.connect(user3).delegateMgCvg(3, user10, 30);\\n\\n        await lockingPositionDelegate.connect(treasuryDao).setMaxTokenIdsDelegated(3);\\n        (await lockingPositionDelegate.maxTokenIdsDelegated()).should.be.equal(3);        \\n\\n        const txFail = lockingPositionDelegate.connect(user1).delegateMgCvg(1, user10, 40);\\n        await expect(txFail).to.be.revertedWith("TOO_MUCH_MG_TOKEN_ID_DELEGATED");\\n        await lockingPositionDelegate.connect(treasuryDao).setMaxTokenIdsDelegated(25);\\n        (await lockingPositionDelegate.maxTokenIdsDelegated()).should.be.equal(25);\\n    });\\n    it("maxMgDelegatees : TRY TO UPDATE PERCENTAGE DELEGATED TO A USER IF WE ALREADY REACH maxMgDelegatees", async function () {\\n        await lockingPositionDelegate.connect(treasuryDao).setMaxMgDelegatees(3);\\n        (await lockingPositionDelegate.maxMgDelegatees()).should.be.equal(3);\\n\\n        await lockingPositionDelegate.connect(user1).delegateMgCvg(1, user10, 20);\\n        await lockingPositionDelegate.connect(user1).delegateMgCvg(1, user2, 30);\\n        await lockingPositionDelegate.connect(user1).delegateMgCvg(1, user3, 30);\\n\\n        const txFail = lockingPositionDelegate.connect(user1).delegateMgCvg(1, user10, 40);\\n        await expect(txFail).to.be.revertedWith("TOO_MUCH_DELEGATEES");\\n    });\\n    it("maxMgDelegatees : maxMgDelegatees IS DECREASED => PERCENTAGE UPDATE IS NO LONGER POSSIBLE", async function () {\\n        await lockingPositionDelegate.connect(treasuryDao).setMaxMgDelegatees(5);\\n        (await lockingPositionDelegate.maxMgDelegatees()).should.be.equal(5);\\n\\n        await lockingPositionDelegate.connect(user1).delegateMgCvg(1, user10, 20);\\n        await lockingPositionDelegate.connect(user1).delegateMgCvg(1, user2, 30);\\n        await lockingPositionDelegate.connect(user1).delegateMgCvg(1, user3, 10);\\n\\n        await lockingPositionDelegate.connect(treasuryDao).setMaxMgDelegatees(2);\\n        (await lockingPositionDelegate.maxMgDelegatees()).should.be.equal(2);\\n\\n        const txFail2 = lockingPositionDelegate.connect(user1).delegateMgCvg(1, user2, 50);\\n        await expect(txFail2).to.be.revertedWith("TOO_MUCH_DELEGATEES");\\n    });\\n```\\n

Impact:
In some cases it is impossible to update percentage delegated or to remove only one delegated percentage then forcing users to remove all their voting power delegatations, taking the risk that someone is faster then them to delegate to their old delegated users and reach threshold for delegation, making impossible for them to re-delegate

Recommended mitigation:
Issue Delegation Limitation in Voting Power Management\\nSeparate functions for new delegations and updates : Implement logic that differentiates between adding a new delegatee and updating an existing delegation to allow updates to existing delegations even if the maximum number of delegatees is reached