codehawks-2023-07-dsc-m05
[M-05] Anyone can burn DecentralizedStableCoin tokens with burnFrom function
Summary
burn 함수에는 권한 설정을 했지만 burnFrom 함수에는 설정하지 않았다. 따라서 권한을 우회하여 토큰을 소각할 수 있다.
Keyword
access control, burnable, openzeppelin, erc20
Vulnerability
DSC 토큰은 Openzeppelin 의 ERC20Burnable 컨트랙트를 상속한다. 이 컨트랙트에는 기본적인 burn 함수와 burnFrom 함수가 구현되어 있다.
abstract contract ERC20Burnable is Context, ERC20 {
/**
* @dev Destroys `amount` tokens from the caller.
*
* See {ERC20-_burn}.
*/
function burn(uint256 amount) public virtual {
_burn(_msgSender(), amount);
}
/**
* @dev Destroys `amount` tokens from `account`, deducting from the caller's
* allowance.
*
* See {ERC20-_burn} and {ERC20-allowance}.
*
* Requirements:
*
* - the caller must have allowance for ``accounts``'s tokens of at least
* `amount`.
*/
function burnFrom(address account, uint256 amount) public virtual {
_spendAllowance(account, _msgSender(), amount);
_burn(account, amount);
}
}DSC 토큰은 burn 함수를 오버라이드하여 onlyOwner modifier를 붙였다. 따라서 관리자인 DSCEngine 컨트랙트에 의해서만 토큰의 물량이 조절되도록 제한한다.
function burn(uint256 _amount) public override onlyOwner {
uint256 balance = balanceOf(msg.sender);
if (_amount <= 0) {
revert DecentralizedStableCoin__MustBeMoreThanZero();
}
if (balance < _amount) {
revert DecentralizedStableCoin__BurnAmountExceedsBalance();
}
super.burn(_amount);
}하지만 burnFrom 함수는 오버라이드 하지 않았다. 따라서 누구나 자신 또는 approve 받은 DSC 토큰을 소각할 수 있다.
Impact
onlyOwner를 우회하여 DSC 토큰을 소각할 수 있다.
Mitigation
burnFrom를 오버라이드하여 아무나 호출할 수 없도록 한다. 또는 함수를 사용할 수 없도록 한다.
@@ -40,6 +40,7 @@ contract DecentralizedStableCoin is ERC20Burnable, Ownable {
error DecentralizedStableCoin__MustBeMoreThanZero();
error DecentralizedStableCoin__BurnAmountExceedsBalance();
error DecentralizedStableCoin__NotZeroAddress();
+ error DecentralizedStableCoin__BlockFunction();
constructor() ERC20("DecentralizedStableCoin", "DSC") {}
@@ -54,6 +55,10 @@ contract DecentralizedStableCoin is ERC20Burnable, Ownable {
super.burn(_amount);
}
+ function burnFrom(address, uint256) public pure override {
+ revert DecentralizedStableCoin__BlockFunction();
+ }
+
function mint(address _to, uint256 _amount) external onlyOwner returns (bool) {
if (_to == address(0)) {
revert DecentralizedStableCoin__NotZeroAddress();tags: bughunting, codehawks, smart contract, solidity, access control vulnerability, openzeppelin, erc20, severity medium