The Wildcat Protocol - 0xDING99YA's results

Banking, but worse - a protocol for fixed-rate, undercollateralised credit facilities.

General Information

Platform: Code4rena

Start Date: 16/10/2023

Pot Size: $60,500 USDC

Total HM: 16

Participants: 131

Period: 10 days

Judge: 0xTheC0der

Total Solo HM: 3

Id: 296

League: ETH

Wildcat Protocol

Findings Distribution

Researcher Performance

Rank: 10/131

Findings: 2

Award: $654.32

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: MiloTruck

Also found by: 0xDING99YA, Robert

Labels

bug
3 (High Risk)
partial-25
sponsor confirmed
sufficient quality report
duplicate-491

Awards

647.6492 USDC - $647.65

External Links

Lines of code

https://github.com/code-423n4/2023-10-wildcat/blob/c5df665f0bc2ca5df6f06938d66494b11e7bdada/src/WildcatSanctionsSentinel.sol#L87-L120

Vulnerability details

Impact

createEscrow() will return the escrow contract address if it was already deployed, or deploy a new one if not. However, attacker can make the createEscrow() always return the escrow address without code deployed, sanctioned funds will be transferred to that address and since there is no code there, there is no way to recover these funds.

Proof of Concept

createEscrow() will first get the escrow contract address and use code hash to determine if it is a contract.

escrowContract = getEscrowAddress(borrower, account, asset); if (escrowContract.codehash != bytes32(0)) return escrowContract;

If escrowContract.codehash != bytes32(0), it will consider the escrowContract was already deployed and return that address. If escrowContract does not exist or it's empty, 0x0 code hash will be returned. See here: https://eips.ethereum.org/EIPS/eip-1052

However, the issue here is that an attacker can send 1 Wei to the not yet created escrowContract, that will make the escrowContract not defined as empty anymore since it has balance now, and the returned code hash will be c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470, which is not 0. The definition of empty address can be found here: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-161.md

As a result, since the escrowContratc has 1 Wei balance and will return a non-zero code hash, createEscrow() will directly return that address and never create the real escrow. Funds will still be transferred to that escrowContract when an account is sanctioned, but later when the account is not sanctioned and want to retrieve those funds it will not work since the escrow is basically an EOA.

Tools Used

Manual Review

Use external code size instead to determine if an address is contract or not

Assessed type

Other

#0 - c4-pre-sort

2023-10-27T02:59:13Z

minhquanym marked the issue as sufficient quality report

#1 - c4-pre-sort

2023-10-28T14:51:17Z

minhquanym marked the issue as primary issue

#2 - d1ll0n

2023-10-31T09:55:24Z

Well that's embarrassing.

Good catch, thank you :pray:

#3 - c4-sponsor

2023-10-31T09:55:29Z

d1ll0n (sponsor) confirmed

#4 - c4-judge

2023-11-07T10:14:22Z

MarioPoneder marked the issue as duplicate of #491

#5 - c4-judge

2023-11-07T10:16:50Z

MarioPoneder marked the issue as partial-25

#6 - MarioPoneder

2023-11-07T10:17:44Z

found 1/3 instances, see primary

#7 - c4-judge

2023-11-07T10:18:17Z

MarioPoneder marked the issue as satisfactory

#8 - c4-judge

2023-11-07T10:21:51Z

MarioPoneder marked the issue as partial-25

Awards

6.6715 USDC - $6.67

Labels

bug
3 (High Risk)
satisfactory
duplicate-68

External Links

Lines of code

https://github.com/code-423n4/2023-10-wildcat/blob/c5df665f0bc2ca5df6f06938d66494b11e7bdada/src/market/WildcatMarketBase.sol#L157-L187 https://github.com/code-423n4/2023-10-wildcat/blob/c5df665f0bc2ca5df6f06938d66494b11e7bdada/src/market/WildcatMarketWithdrawals.sol#L164-L170 https://github.com/code-423n4/2023-10-wildcat/blob/c5df665f0bc2ca5df6f06938d66494b11e7bdada/src/WildcatSanctionsSentinel.sol#L108 https://github.com/code-423n4/2023-10-wildcat/blob/c5df665f0bc2ca5df6f06938d66494b11e7bdada/src/WildcatSanctionsEscrow.sol#L16-L19

Vulnerability details

Impact

When creating an escrow for an account, the parameters used should be in "borrower, account, asset" order, however, in _blockAccount() and executeWithdrawals(), these two functions use "account, borrower, asset" order when constructing the escrow. The escrow contract created in this way will mark the sanctioned account as the borrower, and the sanctioned account can simply update the sanctionOverride mapping to get their funds back when it is still under sanctioned.

Proof of Concept

From WildcatSanctionsSentinel.sol and WildcatSanctionsEscrow.sol we can see that the correct parameters when constructing the escrow should be in order "borrower, account, asset".

tmpEscrowParams = TmpEscrowParams(borrower, account, asset); new WildcatSanctionsEscrow{ salt: keccak256(abi.encode(borrower, account, asset)) }(); constructor() { sentinel = msg.sender; (borrower, account, asset) = WildcatSanctionsSentinel(sentinel).tmpEscrowParams(); }

However, in _blockAccount() and executeWithdrawl() the order is not correct.

address escrow = IWildcatSanctionsSentinel(sentinel).createEscrow( accountAddress, borrower, address(asset) ); if (scaledBalance > 0) { account.scaledBalance = 0; address escrow = IWildcatSanctionsSentinel(sentinel).createEscrow( accountAddress, borrower, address(this) );

We can see it uses "account, borrower, asset" instead of "borrower, account, asset". So the escrow created will mark the real sanctioned account as the borrower, mark the real borrower as the sanctioned address and then transfer the funds. Therefore the real sanctioned address can simply call overrideSanction() and then transfer the funds back (Actually they don't even need to do that because isSanctioned() will return false for the real borrower).

Tools Used

Manual Review

Just make sure when constructing the escrow the parameters used are correct

Assessed type

Other

#0 - c4-pre-sort

2023-10-27T02:53:11Z

minhquanym marked the issue as duplicate of #515

#1 - c4-judge

2023-11-07T12:10:11Z

MarioPoneder 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