Platform: Code4rena
Start Date: 08/01/2024
Pot Size: $83,600 USDC
Total HM: 23
Participants: 116
Period: 10 days
Judge: 0xean
Total Solo HM: 1
Id: 317
League: ETH
Rank: 106/116
Findings: 1
Award: $2.72
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: stackachu
Also found by: 0xHelium, 0xabhay, 0xc695, 0xpiken, DeFiHackLabs, EV_om, HSP, J4X, Krace, KupiaSec, Qkite, ZanyBonzy, albertwh1te, cccz, evmboi32, hals, hash, holydevoti0n, krikolkk, ladboy233, lanrebayode77, marqymarq10, oakcobalt, peanuts, peter, rbserver, said, serial-coder, sin1st3r__
2.7205 USDC - $2.72
https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/modules/PaymentEscrow.sol#L190-L202 https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/policies/Stop.sol#L265-L306
When a borrower is blacklisted by USDC and the lender sets ERC20 as USDC, transferring USDC to the borrower becomes impossible, leading to a chain of reverts:
PaymentEscrow._settlePaymentInFull reverts PaymentEscrow._settlePayment reverts PaymentEscrow.settlePayment reverts Stop.stopRent reverts
As a result, the borrower's PAY rentals can't be stopped, allowing them to keep the NFT indefinitely.
The implementation of USDC's transfer and transferFrom functions differs from other ERC20 contracts. It first checks if the account is on the blacklist.
modifier notBlacklisted(address _account) { require( !blacklisted[_account], "Blacklistable: account is blacklisted" ); _; } /** * @notice Transfer tokens from the caller * @param to Payee's address * @param value Transfer amount * @return True if successful */ function transfer(address to, uint256 value) external override whenNotPaused notBlacklisted(msg.sender) notBlacklisted(to) returns (bool) { _transfer(msg.sender, to, value); return true; } /** * @notice Transfer tokens by spending allowance * @param from Payer's address * @param to Payee's address * @param value Transfer amount * @return True if successful */ function transferFrom( address from, address to, uint256 value ) external override whenNotPaused notBlacklisted(msg.sender) notBlacklisted(from) notBlacklisted(to) returns (bool) { require( value <= allowed[from][msg.sender], "ERC20: transfer amount exceeds allowance" ); _transfer(from, to, value); allowed[from][msg.sender] = allowed[from][msg.sender].sub(value); return true; }
Foundry
Allow users to claim their fees instead of sending them directly to the user's address.
ERC20
#0 - c4-pre-sort
2024-01-21T17:35:52Z
141345 marked the issue as duplicate of #64
#1 - c4-judge
2024-01-28T20:49:26Z
0xean changed the severity to 2 (Med Risk)
#2 - c4-judge
2024-01-28T21:00:34Z
0xean marked the issue as satisfactory