The function burn
in DecentralizedStableCoin.sol has an onlyOwner
modifier, so only DSCEngine can use this function. But there is also the function burnFrom
in ERC20Burnable that allows burning tokens. Normally, users can only burn their DSCTokens by executing the burnDSC
function in the DSCEngine, and in this case, they can only burn as many tokens as were minted:
File: src/DSCEngine.sol
272: function _burnDsc(uint256 amountDscToBurn, address onBehalfOf, address dscFrom) private {
273: s_DSCMinted[onBehalfOf] -= amountDscToBurn;
274: bool success = i_dsc.transferFrom(dscFrom, address(this), amountDscToBurn);
275:
276: if (!success) {
277: revert DSCEngine__TransferFailed();
278: }
279: i_dsc.burn(amountDscToBurn);
280: }
With burnFrom
, users can now burn DSC Tokens that were sent to them and that they did not mint themselves.
Here's a test that can be attached to DSCEngineTest.t.sol, demonstrating that a user can burn more tokens than they have minted.
function testBurnFrom() public {
address user2 = makeAddr("user2");
ERC20Mock(weth).mint(user2, STARTING_USER_BALANCE);
vm.startPrank(user2);
ERC20Mock(weth).approve(address(dsce), amountCollateral);
dsce.depositCollateralAndMintDsc(weth, amountCollateral, amountToMint);
dsc.approve(user, amountToMint);
dsc.transfer(user, amountToMint);
assertEq(dsc.balanceOf(user2), 0);
assertEq(dsc.balanceOf(user), amountToMint);
vm.stopPrank();
vm.startPrank(user);
ERC20Mock(weth).approve(address(dsce), amountCollateral);
dsce.depositCollateralAndMintDsc(weth, amountCollateral, amountToMint);
dsc.approve(user, 2*amountToMint);
dsc.burnFrom(user, 2*amountToMint);
assertEq(amountToMint, dsce.getDscMinted(user));
assertEq(dsc.balanceOf(user), 0);
vm.stopPrank();
}
The function getDscMinted()
needs to be added to DSCEngine, as there is currently no way to access the private variable s_DSCMinted:
function getDscMinted(address user) public view returns(uint256) {
return s_DSCMinted[user];
}
Recommendation
Add the burnFrom
function with an onlyOwner
modifier in DecentralizedStableCoin.sol so that not everyone can burn more tokens than they have minted themselves:
function burnFrom(address account, uint256 amount) public onlyOwner override {
_spendAllowance(account, _msgSender(), amount);
_burn(account, amount);
}