Astaria contest - 0xsomeone's results

On a mission is to build a highly liquid NFT lending market.

General Information

Platform: Code4rena

Start Date: 05/01/2023

Pot Size: $90,500 USDC

Total HM: 55

Participants: 103

Period: 14 days

Judge: Picodes

Total Solo HM: 18

Id: 202

League: ETH

Astaria

Findings Distribution

Researcher Performance

Rank: 42/103

Findings: 2

Award: $262.76

🌟 Selected for report: 1

🚀 Solo Findings: 0

Findings Information

Labels

bug
3 (High Risk)
satisfactory
duplicate-521

Awards

33.2422 USDC - $33.24

External Links

Lines of code

https://github.com/code-423n4/2023-01-astaria/blob/main/src/ClearingHouse.sol#L172 https://github.com/code-423n4/2023-01-astaria/blob/main/src/ClearingHouse.sol#L123 https://github.com/code-423n4/2023-01-astaria/blob/main/src/ClearingHouse.sol#L143-L166 https://github.com/code-423n4/2023-01-astaria/blob/main/src/LienToken.sol#L498 https://github.com/code-423n4/2023-01-astaria/blob/main/src/LienToken.sol#L523 https://github.com/code-423n4/2023-01-astaria/blob/main/src/LienToken.sol#L642-L643

Vulnerability details

Impact

The payment token supplied encoded to the safeTransferFrom function call is not sanitized, permitting arbitrary payment tokens of any value to be provided instead of the actual intended one that was defined in the LienToken implementation's lien.token value. As a result, it is possible to pay debts using a worthless or malicious token, significantly compromising the integrity of the system.

Proof of Concept

A direct invocation of safeTransferFrom with an identifier argument of an arbitrary token will successfully "pay" the debt of a Lien token incorrectly. The currentOfferPrice computations used within ClearingHouse will also become meaningless as they will be done on the basis of a different token than the one provided for the payment of debts.

Tools Used

Manual review of the codebase.

We advise the payment token to be queried via the LienToken itself rather than accepted as an argument, disallowing worthless / malicious tokens from being able to repay debts.

#0 - c4-judge

2023-01-24T07:44:28Z

Picodes marked the issue as duplicate of #564

#1 - c4-judge

2023-02-15T07:29:41Z

Picodes marked the issue as satisfactory

#2 - c4-judge

2023-02-23T21:03:28Z

Picodes changed the severity to QA (Quality Assurance)

#3 - c4-judge

2023-02-24T10:37:08Z

This previously downgraded issue has been upgraded by Picodes

#4 - c4-judge

2023-02-24T10:39:29Z

Picodes marked the issue as not a duplicate

#5 - c4-judge

2023-02-24T10:40:26Z

Picodes marked the issue as duplicate of #521

Findings Information

🌟 Selected for report: 0xsomeone

Also found by: ayeslick, tsvetanovv

Labels

bug
2 (Med Risk)
primary issue
satisfactory
selected for report
M-07

Awards

229.5167 USDC - $229.52

External Links

Lines of code

https://github.com/code-423n4/2023-01-astaria/blob/main/src/ClearingHouse.sol#L148-L151 https://github.com/code-423n4/2023-01-astaria/blob/main/src/ClearingHouse.sol#L160-L165 https://github.com/code-423n4/2023-01-astaria/blob/main/src/LienToken.sol#L637-L641 https://github.com/code-423n4/2023-01-astaria/blob/main/src/CollateralToken.sol#L566-L577

Vulnerability details

Impact

The ClearingHouse implementation performs a @solmate-based safeApprove instruction ([1]) with the remaining balanceOf(address(this)) but contains code handling any remainder of funds that may remain in the contract [2]. Investigation of the payDebtViaClearingHouse function will indicate that the function may not consume the maximum approval that was set to the TRANSFER_PROXY [3].

As a result, any consequent invocation of _execute via safeTransferFrom from OpenSea with a paymentToken (i.e. identifier) such as USDT would fail. Given that the ClearingHouse of a particular collateralId is created only once, this vulnerability will impact consequent listings and cause them to fatally fail for a token that has been used in the past and is part of the non-compliant EIP-20 tokens, with USDT being the prime and most popular example.

The code in USDT that causes this complication is as follows:

require(!((_value != 0) && (allowed[msg.sender][_spender] != 0)));

Proof of Concept

The vulnerability is clearly defined above, however, for testing purposes, the ClearingHouse::safeTransferFrom function of a particular clearing house instance can be invoked twice with the same arguments. The second invocation will fail provided that the first invocation provided a token balance that exceeds the number of funds necessary for the debt payment which should be denoted in USDT.

On an important note, if the code used safeApprove from @openzeppelin this issue would affect any token, however, it is limited to non-standard tokens due to the usage of the @solmate implementation of safeApprove.

Tools Used

Manual review of the codebase. Historically, findings pertaining to incorrect approval mechanisms that do not support USDT have been marked as "medium" in severity in the past in the following cases:

We advise approvals to be properly handled by evaluating whether a non-zero approval already exists and in such an instance nullifying it before re-setting it to a non-zero value. Example below:

// Optimizing lookup
address transferProxy = address(ASTARIA_ROUTER.TRANSFER_PROXY());

// If existing approval is non-zero -> set it to zero
if (ERC20(paymentToken).allowance(address(this), transferProxy) != 0) {
    ERC20(paymentToken).safeApprove(transferProxy, 0);
}

// Set non-zero approval
ERC20(paymentToken).safeApprove(transferProxy, payment - liquidatorPayment);

#0 - c4-judge

2023-01-22T15:27:16Z

Picodes marked the issue as duplicate of #437

#1 - c4-judge

2023-02-24T10:15:05Z

Picodes marked the issue as selected for report

#2 - c4-judge

2023-02-24T10:19:50Z

Picodes 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