The BoostController contract contains a vulnerability in the working supply calculation, where the working supply is overwritten instead of being accumulated. This leads to incorrect boost calculations for users.
pragma solidity ^0.8.19;
import "forge-std/Test.sol";
import {BoostController} from "../contracts/core/governance/boost/BoostController.sol";
import {MockVeToken} from "../test/mocks/MockVeToken.sol";
* @title BoostController Vulnerability Test Suite
* @notice This test suite systematically demonstrates and verifies vulnerabilities in the BoostController contract.
* @dev Test methodology:
* 1. Each test focuses on a specific vulnerability
* 2. Tests are designed to FAIL when the vulnerability exists
* 3. Tests will PASS once the vulnerability is fixed
* 4. Detailed logging is included to help understand the vulnerability
*/
contract BoostControllerTest is Test {
BoostController public boostController;
MockVeToken public veToken;
address public admin = address(1);
address public manager = address(2);
address public emergencyAdmin = address(3);
address public user1 = address(4);
address public user2 = address(5);
address public delegator = address(6);
address public delegatee = address(7);
address public pool = address(8);
event LogTestStep(string description);
event LogValue(string name, uint256 value);
event LogAddress(string name, address value);
event LogBoostState(
string description,
uint256 boost,
uint256 workingSupply,
uint256 baseSupply
);
function setUp() public {
console.log("Setting up test environment...");
veToken = new MockVeToken();
emit LogTestStep("Deployed MockVeToken");
veToken.setBalance(user1, 1000e18);
veToken.setBalance(user2, 1500e18);
veToken.setBalance(delegator, 2000e18);
veToken.setBalance(delegatee, 500e18);
emit LogTestStep("Set up test balances");
vm.startPrank(admin);
boostController = new BoostController(address(veToken));
emit LogTestStep("Deployed BoostController");
emit LogAddress("veToken", address(veToken));
boostController.grantRole(boostController.MANAGER_ROLE(), manager);
emit LogTestStep("Granted MANAGER_ROLE to manager");
vm.stopPrank();
vm.prank(manager);
boostController.modifySupportedPool(pool, true);
emit LogTestStep("Configured test pool as supported");
emit LogAddress("pool", pool);
console.log("Setup complete");
}
* @notice Tests the working supply aggregation vulnerability
* @dev Vulnerability details:
* - Issue: Working supply is overwritten instead of accumulated
* - Impact: Incorrect total working supply leads to wrong boost calculations
* - Location: updateUserBoost() function
* - Line: poolBoost.workingSupply = newBoost;
*
* Test scenario:
* 1. User1 updates boost (1000e18 veToken = 40% capacity)
* 2. User2 updates boost (1500e18 veToken = 60% capacity)
* 3. Working supply should be sum of both boosts
* 4. Currently, it's only equal to User2's boost
*/
function testWorkingSupplyAggregationFails() public {
emit LogTestStep("Starting working supply aggregation test");
(, uint256 initialWorkingSupply, , ) = boostController.getPoolBoost(
pool
);
emit LogValue("Initial working supply", initialWorkingSupply);
console.log("Updating boost for user1...");
vm.prank(user1);
boostController.updateUserBoost(user1, pool);
(uint256 boost1, , , ) = boostController.getUserBoost(user1, pool);
emit LogValue("User1 boost", boost1);
(, uint256 intermediateWorkingSupply, , ) = boostController
.getPoolBoost(pool);
emit LogValue("Working supply after user1", intermediateWorkingSupply);
console.log("User1 boost calculated:", boost1);
console.log("Updating boost for user2...");
vm.prank(user2);
boostController.updateUserBoost(user2, pool);
(uint256 boost2, , , ) = boostController.getUserBoost(user2, pool);
emit LogValue("User2 boost", boost2);
(, uint256 finalWorkingSupply, , ) = boostController.getPoolBoost(pool);
emit LogValue("Final working supply", finalWorkingSupply);
console.log("User2 boost calculated:", boost2);
uint256 expectedWorkingSupply = boost1 + boost2;
emit LogValue("Expected working supply", expectedWorkingSupply);
emit LogValue("Actual working supply", finalWorkingSupply);
console.log("Verifying working supply calculation...");
console.log("Expected:", expectedWorkingSupply);
console.log("Actual:", finalWorkingSupply);
assertEq(
finalWorkingSupply,
expectedWorkingSupply,
"Working supply should be sum of all user boosts"
);
}
}