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
Rank: 103/131
Findings: 1
Award: $6.67
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: YusSecurity
Also found by: 0xAsen, 0xCiphky, 0xDING99YA, 0xKbl, 0xSwahili, 0xbepresent, 3docSec, AS, Aymen0909, DeFiHackLabs, GREY-HAWK-REACH, KeyKiril, MiloTruck, QiuhaoLi, Silvermist, SovaSlava, TrungOre, VAD37, Vagner, Yanchuan, ZdravkoHr, ast3ros, cartlex_, d3e4, deth, ggg_ttt_hhh, gizzy, kodyvim, nirlin, nobody2018, rvierdiiev, serial-coder, sl1, tallo, xeros
6.6715 USDC - $6.67
https://github.com/code-423n4/2023-10-wildcat/blob/c5df665f0bc2ca5df6f06938d66494b11e7bdada/src/market/WildcatMarketWithdrawals.sol#L166-L170 https://github.com/code-423n4/2023-10-wildcat/blob/c5df665f0bc2ca5df6f06938d66494b11e7bdada/src/market/WildcatMarketBase.sol#L172-L176
When lender is removed from sanction list and try to release escrow, escrow's balance(asset, market token) will be released to borrower rather than lender, so this compromise market and user's balance.
In executeWithdrawal
of WildcatMarketWithdrawals.sol
address escrow = IWildcatSanctionsSentinel(sentinel).createEscrow( accountAddress, borrower, address(asset) );
In _blockAcount
of WildMarketBase.sol
https://github.com/code-423n4/2023-10-wildcat/blob/c5df665f0bc2ca5df6f06938d66494b11e7bdada/src/market/WildcatMarketBase.sol#L172-L176
address escrow = IWildcatSanctionsSentinel(sentinel).createEscrow( accountAddress, borrower, address(this) );
Above code blocks will record borrower as account on escrow.
When the lender is released from sanction list and try to release escrow, balance will be transferred to borrower. https://github.com/code-423n4/2023-10-wildcat/blob/c5df665f0bc2ca5df6f06938d66494b11e7bdada/src/WildcatSanctionsEscrow.sol#L33-L41
function releaseEscrow() public override { if (!canReleaseEscrow()) revert CanNotReleaseEscrow(); uint256 amount = balance(); IERC20(asset).transfer(account, amount); emit EscrowReleased(account, asset, amount); }
The test blow illustrates the scenario above
import "./BaseMarketTest.sol"; import {MockChainalysis} from "./helpers/MockChainalysis.sol"; import {WildcatSanctionsEscrow, IWildcatSanctionsEscrow} from "src/WildcatSanctionsEscrow.sol"; contract EscrowSanctionTest is BaseMarketTest { using MathUtils for uint256; using FeeMath for uint256; function test_executeWithdrawal_Sanctioned() external { _deposit(alice, 1e18); _requestWithdrawal(alice, 1e18); fastForward(parameters.withdrawalBatchDuration); sanctionsSentinel.sanction(alice); IWildcatSanctionsEscrow escrow = IWildcatSanctionsEscrow( sanctionsSentinel.getEscrowAddress(alice, borrower, address(asset)) ); vm.expectEmit(address(asset)); emit Transfer(address(market), address(escrow), 1e18); vm.expectEmit(address(market)); emit SanctionedAccountWithdrawalSentToEscrow( alice, address(escrow), uint32(block.timestamp), 1e18 ); market.executeWithdrawal(alice, uint32(block.timestamp)); uint256 prevAliceAmount = asset.balanceOf(alice); uint256 prevBorrowerAmount = asset.balanceOf(borrower); uint256 escrowAmount = asset.balanceOf(address(escrow)); sanctionsSentinel.unsanction(alice); assertEq(escrow.canReleaseEscrow(), true, "sanction isn't removed"); escrow.releaseEscrow(); assertEq( asset.balanceOf(alice), prevAliceAmount + escrowAmount, "assets wasn't be released to alice" ); assertNotEq( asset.balanceOf(borrower), prevBorrowerAmount + escrowAmount, "assets was released to borrower" ); } }
Added below code block into MockSanctionsSentinel.sol for testing
function unsanction(address account) external { MockChainalysis(chainalysisSanctionsList).unsanction(account); }
Above code can be fixed simply like below
In executeWithdrawal
in WildcatMarketWithdrawals.sol
address escrow = IWildcatSanctionsSentinel(sentinel).createEscrow( borrower, accountAddress, address(asset) );
address escrow = IWildcatSanctionsSentinel(sentinel).createEscrow( borrower, accountAddress, address(this) );
Visual Studio / Manual Review
Token-Transfer
#0 - c4-pre-sort
2023-10-27T02:44:19Z
minhquanym marked the issue as duplicate of #515
#1 - c4-judge
2023-11-07T12:06:45Z
MarioPoneder marked the issue as satisfactory