Caviar Private Pools - ulqiorra's results

A fully on-chain NFT AMM that allows you to trade every NFT in a collection.

General Information

Platform: Code4rena

Start Date: 07/04/2023

Pot Size: $47,000 USDC

Total HM: 20

Participants: 120

Period: 6 days

Judge: GalloDaSballo

Total Solo HM: 4

Id: 230

League: ETH

Caviar

Findings Distribution

Researcher Performance

Rank: 15/120

Findings: 3

Award: $564.03

QA:
grade-b

🌟 Selected for report: 0

🚀 Solo Findings: 0

Awards

26.761 USDC - $26.76

Labels

bug
3 (High Risk)
satisfactory
duplicate-184

External Links

Lines of code

https://github.com/code-423n4/2023-04-caviar/blob/cd8a92667bcb6657f70657183769c244d04c015c/src/PrivatePool.sol#L459

Vulnerability details

Impact

In PrivatePool, there are functions that assume the trader has approved the contract to spend their funds. For example, these functions are buy(), change(), and deposit():

However, these functions do not reset the allowance based on the results of the trades. The allowance can be greater than the commission requires, up to infinity. For example, some DeFi projects on Ethereum Mainnet set a request on the frontend to sign a transaction for infinite allowance so that the user does not pay unnecessary fees next time they interact with the project.

The pool owner can use the execute() function to call ERC20(baseToken).transferFrom(victimAddress, maliciousOwner, anyAmountOfTokens) on behalf of the pool, which has the approval from the victim to transfer their funds:

It should be noted that there is no implemented router for PrivatePool with ERC-20 base token. Therefore, interaction with such private pools is currently possible only directly, which makes the importance of the discovery HIGH.

It is recommended to remove the execute() function and reconsider the way airdrops are received, or to clear the trader's allowance at the end of the transactions.

#0 - c4-pre-sort

2023-04-20T16:40:02Z

0xSorryNotSorry marked the issue as duplicate of #184

#1 - c4-judge

2023-05-01T19:21:29Z

GalloDaSballo marked the issue as satisfactory

Findings Information

🌟 Selected for report: Brenzee

Also found by: ladboy233, ulqiorra

Labels

bug
2 (Med Risk)
downgraded by judge
satisfactory
duplicate-230

Awards

506.2665 USDC - $506.27

External Links

Lines of code

https://github.com/code-423n4/2023-04-caviar/blob/cd8a92667bcb6657f70657183769c244d04c015c/src/PrivatePool.sol#L459

Vulnerability details

Impact

Ownership of the pool is determined through ownership of the Factory ERC721 NFT:

modifier onlyOwner() virtual { if (msg.sender != Factory(factory).ownerOf(uint160(address(this)))) { revert Unauthorized(); } _; }

https://github.com/code-423n4/2023-04-caviar/blob/cd8a92667bcb6657f70657183769c244d04c015c/src/PrivatePool.sol#L127-L133

The current owner can trade their ownership NFT in exchange for funds comparable to those locked in the pool. Or it could be the owner of an empty pool who transferred their NFT to someone else, and that person decided to provide liquidity to it.

However, before doing so, a malicious owner can use the PrivatePool.execute() function to grant themselves unlimited approval to withdraw baseToken from the pool, as well as make themselves the NFT operator for this pool, giving them the ability to always withdraw any NFT from the pool:

privatePool.execute( pool.baseToken(), abi.encodeWithSignature( "approve(address,uint256)", hackerAddress, type(uint).max ) ); privatePool.execute( pool.nft(), abi.encodeWithSignature( "setApprovalForAll(address,bool)", hackerAddress, true ) )

Thus, the previous owner will be able to withdraw all the funds and NFTs from the pool, even if they are no longer the actual owner of the pool.

In its current form, the execute() function is too dangerous and should be removed.

#0 - c4-pre-sort

2023-04-20T17:55:05Z

0xSorryNotSorry marked the issue as duplicate of #295

#1 - c4-judge

2023-04-28T11:02:47Z

GalloDaSballo marked the issue as duplicate of #230

#2 - c4-judge

2023-04-30T16:37:22Z

GalloDaSballo changed the severity to 2 (Med Risk)

#3 - c4-judge

2023-05-01T07:28:56Z

GalloDaSballo marked the issue as satisfactory

Awards

30.9954 USDC - $31.00

Labels

bug
grade-b
QA (Quality Assurance)
Q-01

External Links

Factory contract is Owned. However, it is recommended to use a two-step ownership mechanism, which reduces the probability of making a mistake when transferring ownership: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/3b117992e17ae67fcd19ea2bd988f64520813cd1/contracts/access/Ownable2Step.sol

#0 - c4-judge

2023-05-01T08:50:27Z

GalloDaSballo marked the issue as grade-c

#1 - c4-judge

2023-05-04T17:50:13Z

GalloDaSballo marked the issue as grade-b

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