Frankencoin - 7siech's results

A decentralized and fully collateralized stablecoin.

General Information

Platform: Code4rena

Start Date: 12/04/2023

Pot Size: $60,500 USDC

Total HM: 21

Participants: 199

Period: 7 days

Judge: hansfriese

Total Solo HM: 5

Id: 231

League: ETH

Frankencoin

Findings Distribution

Researcher Performance

Rank: 95/199

Findings: 1

Award: $33.83

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: Ruhum

Also found by: 7siech, DadeKuma, J4de, Lirios, deliriusz, foxb868, hihen, juancito, ladboy233, rbserver, santipu_, zaevlad

Labels

bug
2 (Med Risk)
satisfactory
duplicate-230

Awards

33.835 USDC - $33.83

External Links

Lines of code

https://github.com/code-423n4/2023-04-frankencoin/blob/main/contracts/Frankencoin.sol#L84 https://github.com/code-423n4/2023-04-frankencoin/blob/main/contracts/Frankencoin.sol#L152

Vulnerability details

Impact

It is reasonable to assume there will be occasions of misbehaving minters that will threaten the functioning of the Frankencoin ecosystem and there is no way to disable any such minter without redeploying the contract.

Ex. an attacker can deploy a malicious minter during bootstrap by backrunning the deployment of the Frankencoin contract

Ex. a previously approved stablecoin depegs and causes a material loss in the future

Proof of Concept

While the system is bootstrapping and there is no totalSupply minted, any call to suggestMinter immediately succeeds allowing for zero values for both the applicationPeriod and applicationFee parameters.

  function suggestMinter(address _minter, uint256 _applicationPeriod, uint256 _applicationFee, string calldata _message) override external {
      if (_applicationPeriod < MIN_APPLICATION_PERIOD && totalSupply() > 0) revert PeriodTooShort();
      if (_applicationFee < MIN_FEE  && totalSupply() > 0) revert FeeTooLow();
      if (minters[_minter] != 0) revert AlreadyRegistered();
      _transfer(msg.sender, address(reserve), _applicationFee);
      minters[_minter] = block.timestamp + _applicationPeriod;
      emit MinterApplied(_minter, _applicationPeriod, _applicationFee, _message);
   }

It is only possible to deny a minter during the application period (which can be zero during bootstrap), but once a minter has been added to the system, it can not be removed/disabled.

   function denyMinter(address _minter, address[] calldata _helpers, string calldata _message) override external {
      if (block.timestamp > minters[_minter]) revert TooLate();
      reserve.checkQualified(msg.sender, _helpers);
      delete minters[_minter];
      emit MinterDenied(_minter, _message);
   }

Tools Used

Manual review

I recommend adding functionality to either suggest removing a minter completely or pausing a minter.

This would also be beneficial in the case of bankruptcy in combination with Equity.restructureCapTable ex. if a previously approved stablecoin depegs and causes the loss.

Having the ability to disable the minter in such a case would help increase the chances of survival of the system and further advances the goal of decentralization and self-organization of the community.

#0 - c4-pre-sort

2023-04-22T13:45:12Z

0xA5DF marked the issue as duplicate of #230

#1 - c4-judge

2023-05-18T13:40:11Z

hansfriese marked the issue as satisfactory

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter