// must ensure enough amount is left to pay for interest first, then send gains and fund left to borrower
///@dev refundWithCheck ensures actual cannot be more than expected, since amount owed to LP is in actual,
/// it ensures (1) on the collateralFrom part of refund, tokenOwed is covered, and (2) on the amountReceived
/// part, received is no less than liquidity addback + token owed.
while this refund logic works ok when borrower intends to close his position
Some tokens (e.g. USDC, USDT) have a contract level admin controlled address blocklist. If an address is blocked, then transfers to and from that address are forbidden.
Malicious or compromised token owners can trap funds in a contract by adding the contract address to the blocklist. This could potentially be the result of regulatory action against the contract itself, against a single user of the contract (e.g. a Uniswap LP), or could also be a part of an extortion attempt against users of the blocked contract.
assume the borrower who open the position is not blocklisted, so he can borrow the liquidity out
then he transfer the liquidity (borrowed fund) to another account and make trade
Lines of code
https://github.com/code-423n4/2023-12-particle/blob/a3af40839b24aa13f5764d4f84933dbfa8bc8134/contracts/protocol/ParticlePositionManager.sol#L305 https://github.com/code-423n4/2023-12-particle/blob/a3af40839b24aa13f5764d4f84933dbfa8bc8134/contracts/protocol/ParticlePositionManager.sol#L456 https://github.com/code-423n4/2023-12-particle/blob/a3af40839b24aa13f5764d4f84933dbfa8bc8134/contracts/protocol/ParticlePositionManager.sol#L374
Vulnerability details
Impact
position cannot be liquidated if the borrower is blocklisted
Proof of Concept
When the position is closed, the function _closePosition is called
in this case, the msg.sender is the borrower who open the position
the close position logic involves refund logic
while this refund logic works ok when borrower intends to close his position
the same _closePosition runs, the codes tries to close the position for borrower
now we have a problem
assume the borrower who open the position is not blocklisted, so he can borrow the liquidity out
then he transfer the liquidity (borrowed fund) to another account and make trade
then the original borrower account is blocklisted
the liquiation will revert in refund flow when the code attempts to send the token to the blocklisted borrower
Failed to liquidate the position make original lender lose fund
Tools Used
Manual Review
Recommended Mitigation Steps
let the original borrower claim the fund if their position are liquidated and avoid send token out during the liquidation flow
Assessed type
Token-Transfer