Frax Ether Liquid Staking contest - OptimismSec's results

A liquid ETH staking derivative designed to uniquely leverage the Frax Finance ecosystem.

General Information

Platform: Code4rena

Start Date: 22/09/2022

Pot Size: $30,000 USDC

Total HM: 12

Participants: 133

Period: 3 days

Judge: 0xean

Total Solo HM: 2

Id: 165

League: ETH

Frax Finance

Findings Distribution

Researcher Performance

Rank: 54/133

Findings: 2

Award: $47.99

🌟 Selected for report: 0

🚀 Solo Findings: 0

Awards

19.982 USDC - $19.98

Labels

bug
duplicate
2 (Med Risk)
out of scope

External Links

Lines of code

https://github.com/code-423n4/2022-09-frax/blob/55ea6b1ef3857a277e2f47d42029bc0f3d6f9173/src/frxETHMinter.sol#L190-L204 https://github.com/code-423n4/2022-09-frax/blob/55ea6b1ef3857a277e2f47d42029bc0f3d6f9173/src/frxETHMinter.sol#L159-L174

Vulnerability details

Impact

True trustlessness is hard, but there's not much point in having open source smart contracts unless the goal is achieved completely. The moment a vector exists where a rug pull could occur a user should be rightly suspicious.

Although TimelockController is used on the timelock_address the same does not hold for the owner. The owner in the contract can withdraw ERC20 tokens or ether to themselves without going through the timelock, anytime they want (now or in the future).

Proof of Concept

  • See lines 159-174 and lines 190 - 204.

  • The onlyByOwnGov modifier makes sure that only the timelock can call the contract, or the deployer or owner of the contract.

  • The emergency functions,recoverEther and recoverERC20, are extremely powewr functions and should only be called by the timelock contract which is has governance mechnisms to prevent unilateral use. This does not hold for the owner who could always use these functions to completely drain the contract of funds.

  • The contract also lets the owner call setWithHoldRatio anytime they want, without a timelock. In combination with moveWithheldETH this presents another rug pull vector.

Tools Used

Manual Inspection

Split the authority modifiers into two. Only the timelock_address should exclusively be able to recoverEth, recoverERC20, setWithHoldRatio and moveWithheldETH from the contract.

The two modifiers could be implemented as follows:

  modifier onlyTimeLock() {
        require(msg.sender == timelock_address , "Caller Not timelock");
        _;
    }

  modifier onlyOwner() {
        require(msg.sender == owner , "Caller Not owner");
        _;
    }

#0 - FortisFortuna

2022-09-25T21:12:08Z

We are well aware of the permission structure. The owner will most likely be a large multisig. We mentioned the Frax Multisig in the scope too.

#1 - joestakey

2022-09-26T18:15:14Z

Duplicate of #107

L-01: Round-off errors in frxETHMinter._submit can lead to loss of funds

Although the amount we are speaking about are tiny, perhaps consider rounding up when the withholdRatio is set to a non-zero value. Otherwise the possiblity exists that when extremely small msg.values are sent nothing is withheld.

The only check done for msg.value is to see if it is greater than zero on line 88. No other checks are done

require(msg.value != 0, "Cannot submit 0");

However, msg.value on line 96, is being divided by a constant RATIO_PRECISION which can lead to a result of zero for withheld_amt

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