Small Shamrock Rook
High
CF is checked before minting nuAssets (instead of after), allowing CF to be massively decreased past the warning. This allows assets to be minted even past the critical CF of 110%, breaking the invariant stated in the README.
NumaPrinter.mintNuAsset()
has the notInWarningCF
modifier
modifier notInWarningCF() {
uint currentCF = vaultManager.getGlobalCF();
require(currentCF > vaultManager.getWarningCF(), "minting forbidden");
_;
}
Invariant stated in the README is bypassed:
New synthetics cannot be minted when CFTHEORETICAL < 110%, where CFTHEORETICAL = rETH_accountingBalance / synthetic_rETHdebt.
The modifier checks the CF before the minting of the nuAssets.
This means that a user can mint a large number of nuAssets to effectively minting past the warning CF.
No response
No response
No response
No response
The PoC shows that the CF goes from 1e5
to 1.0527e4
during the mint, while the warning CF is 9.9999e4
, so the warning CF has been bypassed, and assets have effectively been minted past the warning CF which should not be allowed.
Add the test to Printer.t.sol
function test_mintPastCF() public {
uint numaAmount = 1000001e18;
vm.startPrank(deployer);
numa.transfer(userA, numaAmount);
vm.stopPrank();
vm.startPrank(userA);
// compare getNbOfNuAssetFromNuma
(uint256 nuUSDAmount, uint fee) = moneyPrinter.getNbOfNuAssetFromNuma(
address(nuUSD),
numaAmount
);
numa.approve(address(moneyPrinter), numaAmount);
// warning cf test block mint
uint globalCFBefore = vaultManager.getGlobalCF();
// put back warning cf
vm.startPrank(deployer);
vaultManager.setScalingParameters(
vaultManager.cf_critical(),
globalCFBefore - 1,
vaultManager.cf_severe(),
vaultManager.debaseValue(),
vaultManager.rebaseValue(),
1 hours,
2 hours,
vaultManager.minimumScale(),
vaultManager.criticalDebaseMult()
);
console.log("globalCFBefore: %e", globalCFBefore);
console.log("warningCF: %e", vaultManager.getWarningCF());
vm.startPrank(userA);
// slippage ok
moneyPrinter.mintAssetFromNumaInput(
address(nuUSD),
numaAmount,
nuUSDAmount,
userA
);
uint globalCFAfter = vaultManager.getGlobalCF();
uint warningCF = vaultManager.getWarningCF();
console.log("globalCFAfter: %e", globalCFAfter);
console.log("warningCF: %e", warningCF);
assertGt(globalCFBefore, warningCF);
assertLt(globalCFAfter, warningCF);
}
Update the modifier in the following way:
modifier notInWarningCF() {
+ _;
uint currentCF = vaultManager.getGlobalCF();
require(currentCF > vaultManager.getWarningCF(), "minting forbidden");
- _;
}
This ensures that the CF is checked after minting the nuAssets, so it can't be bypassed.