Protocol allow for users to be able to delegate a portion of their veToken balance. However, in a situation where users attemts to delegate any of the remaining portion of their veToken balance to another user, the below checks in BoostController::delegateBoost makes it impossible for that action to be taken.
contract POC is Test {
RAACGauge raacGauge;
MockToken rewardToken;
MockToken stakingToken;
BoostController boostController;
RAACToken raacToken;
veRAACToken veRAAC;
address owner = makeAddr("owner");
address user = makeAddr("user");
address user2 = makeAddr("user2");
address pool = makeAddr("pool");
function setUp() public {
vm.startPrank(owner);
raacToken = new RAACToken( owner, 0, 0);
veRAAC = new veRAACToken(address(raacToken));
stakingToken = new MockToken("STAKING TOKEN","STT", 18);
rewardToken = new MockToken("REWARD TOKEN","RWD", 18);
boostController = new BoostController((address(veRAAC)));
raacGauge = new RAACGauge( address(rewardToken), address(stakingToken), address(boostController));
raacToken.setMinter(owner);
boostController.modifySupportedPool(pool, true);
raacToken.mint(user, 10 ether);
stakingToken.mint(user, 10 ether);
raacToken.mint(user2, 10 ether);
stakingToken.mint(user2, 10 ether);
vm.stopPrank();
}
function test_POC() public {
vm.startPrank(user);
raacToken.approve(address(veRAAC), 2 ether);
veRAAC.lock(2 ether, 366 days);
vm.stopPrank();
vm.startPrank(user2);
raacToken.approve(address(veRAAC), 2 ether);
veRAAC.lock(2 ether, 366 days);
vm.stopPrank();
vm.warp(2 weeks);
vm.startPrank(user);
uint256 remainder = veRAAC.balanceOf(user) - 0.1 ether;
boostController.delegateBoost(owner, 0.1 ether, 8 days);
vm.expectRevert();
boostController.delegateBoost(owner, remainder, 8 days);
vm.stopPrank();
}
}
Since partial delegation is allowed, there should be a variable that tracks the total tokens delegated by a user, and that the total amount delegated at anytime should be less than the user balance
Example:
+ mapping(address => uint256) public totalDelegatedByUser;
function delegateBoost(
address to,
uint256 amount,
uint256 duration
) external override nonReentrant {
if (paused()) revert EmergencyPaused();
if (to == address(0)) revert InvalidPool();
if (amount == 0) revert InvalidBoostAmount();
if (duration < MIN_DELEGATION_DURATION || duration > MAX_DELEGATION_DURATION)
revert InvalidDelegationDuration();
uint256 userBalance = IERC20(address(veToken)).balanceOf(msg.sender);
if (userBalance < amount) revert InsufficientVeBalance();
UserBoost storage delegation = userBoosts[msg.sender][to];
- if (delegation.amount > 0) revert BoostAlreadyDelegated();
if (totalDelegatedByUser[msg.sender] + amount > userBalance) revert BoostAlreadyDelegated();
delegation.amount = amount;
delegation.expiry = block.timestamp + duration;
delegation.delegatedTo = to;
delegation.lastUpdateTime = block.timestamp;
+ totalDelegatedByUser[msg.sender] += amount;
emit BoostDelegated(msg.sender, to, amount, duration);
}