Frankencoin - J4de'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: 9/199

Findings: 5

Award: $1,036.45

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: giovannidisiena

Also found by: J4de, bin2chen, tallo

Labels

bug
3 (High Risk)
satisfactory
upgraded by judge
duplicate-886

Awards

946.1175 USDC - $946.12

External Links

Lines of code

https://github.com/code-423n4/2023-04-frankencoin/blob/main/contracts/Position.sol#L249-L255

Vulnerability details

Impact

If the collateral is a multi-address ERC20 token, the withdraw function can be used to bypass the checkCollateral check.

Proof of Concept

Tools Used

Manual audit

There is no business dealing with other ERC20 tokens in the Position.sol contract. It is recommended that there is no need to provide token withdraw at a specified address.

#0 - c4-pre-sort

2023-04-22T11:52:32Z

0xA5DF marked the issue as primary issue

#1 - c4-pre-sort

2023-04-22T15:35:58Z

0xA5DF marked the issue as duplicate of #886

#2 - c4-judge

2023-05-18T09:42:18Z

hansfriese changed the severity to 3 (High Risk)

#3 - c4-judge

2023-05-18T09:43:04Z

hansfriese marked the issue as satisfactory

Lines of code

https://github.com/code-423n4/2023-04-frankencoin/blob/main/contracts/Equity.sol#L309-L316

Vulnerability details

Impact

In the loop body, addressesToWipe[0] is processed every time, which causes the first address to be processed in each value of RestructureCapTable, which does not conform to the original intention of the RestructureCapTable function.

Proof of Concept

Tools Used

Manual audit

    function restructureCapTable(address[] calldata helpers, address[] calldata addressesToWipe) public {
        require(zchf.equity() < MINIMUM_EQUITY);
        checkQualified(msg.sender, helpers);
        for (uint256 i = 0; i<addressesToWipe.length; i++){
-           address current = addressesToWipe[0];
+           address current = addressesToWipe[i];
            _burn(current, balanceOf(current));
        }
    }

#0 - c4-pre-sort

2023-04-20T14:24:23Z

0xA5DF marked the issue as duplicate of #941

#1 - c4-judge

2023-05-18T14:28:47Z

hansfriese marked the issue as satisfactory

Findings Information

Labels

bug
2 (Med Risk)
satisfactory
duplicate-745

Awards

33.835 USDC - $33.83

External Links

Lines of code

https://github.com/code-423n4/2023-04-frankencoin/blob/main/contracts/MintingHub.sol#L208-L214

Vulnerability details

Impact

File: MintingHub.sol
208         if (challenge.position.tryAvertChallenge(challenge.size, _bidAmountZCHF)) {
209             // bid was high enough, let bidder buy collateral from challenger
210             zchf.transferFrom(msg.sender, challenge.challenger, _bidAmountZCHF);
211             challenge.position.collateral().transfer(msg.sender, challenge.size);
212             emit ChallengeAverted(address(challenge.position), _challengeNumber);
213             delete challenges[_challengeNumber];
214         } else {

During the challenge, if the bid is high enough to satisfy tryAvertChallenge, the challenge can be ended immediately, and the bidder and challenger exchange tokens.

File: Position.sol
304     function tryAvertChallenge(uint256 _collateralAmount, uint256 _bidAmountZCHF) external onlyHub returns (bool) {
305         if (block.timestamp >= expiration){
306             return false; // position expired, let every challenge succeed
307         } else if (_bidAmountZCHF * ONE_DEC18 >= price * _collateralAmount){
308             // challenge averted, bid is high enough
309             challengedAmount -= _collateralAmount;
310             // Don't allow minter to close the position immediately so challenge can be repeated before
311             // the owner has a chance to mint more on an undercollateralized position
312             restrictMinting(1 days);
313             return true;
314         } else {
315             return false;
316         }
317     }

After satisfying tryAvertChallenge, position will enter a 1-day cooldown period.

The attacker can act as a challenger and bidder to make the position enter a 1-day cooldown at 0 cost.

Proof of Concept

Tools Used

Manual audit

It is recommended to charge a certain fee for challengers who fail the challenge.

#0 - c4-pre-sort

2023-04-22T11:55:09Z

0xA5DF marked the issue as primary issue

#1 - c4-pre-sort

2023-04-24T16:27:00Z

0xA5DF marked the issue as duplicate of #745

#2 - c4-judge

2023-05-18T13:53:33Z

hansfriese marked the issue as satisfactory

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)
downgraded by judge
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#L1

Vulnerability details

Impact

The power of minter in Frankencoin is very large, and minter may be a third-party component. If minter gets out of control, it may cause Frankencoin to crash. But the current situation is that as long as minter is added, even if it loses control later, Frankencoin shareholders cannot delete or restrict it.

Proof of Concept

Tools Used

Manual audit

It is recommended that shareholders vote (requires a large number of votes) to delete minter.

#0 - c4-pre-sort

2023-04-28T08:11:55Z

0xA5DF marked the issue as duplicate of #230

#1 - c4-judge

2023-05-18T13:41:43Z

hansfriese changed the severity to 2 (Med Risk)

#2 - c4-judge

2023-05-18T13:44:55Z

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