The upgradeable Swan.sol contract, which utilizes the UUPS (Universal Upgradeable Proxy Standard) pattern, introduces a risk of funds becoming locked in BuyerAgent contracts if the token used for transactions in Swan.sol is changed during an upgrade. This vulnerability arises because the withdraw function in BuyerAgent is restricted to a specific token address (the one used by Swan.sol at the time), preventing buyers from accessing their funds if a different token is later set in Swan.sol.
The withdraw function in BuyerAgent allows authorized buyers to withdraw funds only under specific conditions tied to the token initially specified by Swan.sol. This dependency is illustrated as follows:
Since BuyerAgent relies on swan.token() to identify and withdraw the asset, an upgrade in Swan.sol that changes the token address without an update mechanism in BuyerAgent will effectively lock all funds if a withdrawal is attempted after the token change. This issue is further exacerbated if the withdraw phase has not yet been reached for the buyer, as only partial withdrawals are permitted outside of this phase.
Multiple BuyerAgent contracts contain funds allocated in the original token specified by Swan.sol.
Swan.sol undergoes an upgrade, changing the token address via swan.token().
Buyers attempting to withdraw funds after this upgrade are restricted to withdrawing only the new token, leaving the original token funds locked in the BuyerAgent contract.
Buyers who have not reached the full withdrawal phase in BuyerAgent will be unable to access their locked funds if the token changes upon an upgrade. This can lead to significant loss of funds and disrupt the withdrawal process, as there is no mechanism in place to handle a token change.
Manual review
To prevent fund lockups due to token changes in Swan.sol, implement the following fix:
Add a Fallback Withdrawal Function: Introduce an additional withdrawal function in BuyerAgent that allows authorized withdrawals of the initially held token, regardless of the current token address in swan.token(). This fallback function should check if the token address used for the initial deposits differs from the current swan.token() address, and allow withdrawal of the originally deposited token in this case.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.