The FluxToken contract allows users to mint some $FLUX at once using AlchemechNFT or AlEthNFT. The number of mint is calculated based on the tokenData of the NFT. However, FluxToken.calculateBPT does not divide by BPS resulting in the number of mint being 10000 times larger than expected.
Vulnerability Details
Please look at the following code. The getClaimableFlux function is used to calculate the number of mint. It calls the calculateBPT function.
///// https://github.com/alchemix-finance/alchemix-v2-dao/blob/f1007439ad3a32e412468c4c42f62f676822dc1f/src/FluxToken.sol#L215-L216
function getClaimableFlux(uint256 _amount, address _nft) public view returns (uint256 claimableFlux) {
uint256 bpt = calculateBPT(_amount);
Let's look at the calculateBPT function, which multiplies _amount by bptMultiplier.
///// https://github.com/alchemix-finance/alchemix-v2-dao/blob/f1007439ad3a32e412468c4c42f62f676822dc1f/src/FluxToken.sol#L232-L234
function calculateBPT(uint256 _amount) public view returns (uint256 bptOut) {
bptOut = _amount * bptMultiplier;
}
According to the comment of the bptMultiplier variable, it should represent 0.4%. So, multiplied by bptMultiplier should be divided by BPS (10000)
///// https://github.com/alchemix-finance/alchemix-v2-dao/blob/f1007439ad3a32e412468c4c42f62f676822dc1f/src/FluxToken.sol#L43-L44
/// @notice The ratio of FLUX patron NFT holders receive (.4%)
uint256 public bptMultiplier = 40;
Note: The two divisions by BPS in the getClaimableFlux function correspond to the following variables, which have nothing to do with bptMultiplier.
FOUNDRY_PROFILE=default forge test --fork-url https://eth-mainnet.alchemyapi.io/v2/VFefkgjj8h3SgRYcCvmtp9KoMJJij6gD --fork-block-number 17133822 -vvv --match-test testYttriumzzPocTemp
The log
$ FOUNDRY_PROFILE=default forge test --fork-url https://eth-mainnet.alchemyapi.io/v2/VFefkgjj8h3SgRYcCvmtp9KoMJJij6gD --fork-block-number 17133822 -vvv --match-test testYttriumzzPocTemp
[⠊] Compiling...
No files changed, compilation skipped
Ran 1 test for src/test/FluxToken.t.sol:FluxTokenTest
[PASS] testYttriumzzPocTemp() (gas: 118155)
Logs:
tokenData of patronNFT: 249991869582520600
Get $FLUX: 7499756087469342000
Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 14.90ms (889.67µs CPU time)
Ran 1 test suite in 792.98ms (14.90ms CPU time): 1 tests passed, 0 failed, 0 skipped (1 total tests)
The tokenData of the NFT is 0.24999186958252062, and the mint $FLUX is 7.499756087469342.