The maxAssetCount
used to limit the amount of assets that can be listed to a buyer in their sell phase can be bypassed, leading to unlimited amount of asset listing to the buyer.
When listing assets, the maxAssetCount
limits the amount of assets that can be listed to a buyer agent. This check is done in the Swan
contract list
function below. The check makes sure that the maxAssetCount
of the current market parameter is equal to the amount of assets listed to the buyer(to make sure that its already full).
The issue arises from the fact that there is a function that allows for the setting of new market parameters by the owner regardless of the phase in the SwanManager
contract.
When the owner changes the marketParameters maxAssetCount during a sell phase for a buyer agent, which is very likely because diffrent buyer agents have different phases. An issue can arise. Lets take an example
The maxAssetCount
is 7.
A buyer is in the sell phase and has its assetsPerBuyerRound
filled to the current market parameter maxAssetCount
which is 7.
The admin updates the maxAssetCount
to 5. When a user tries to list to the buyer again, the current market Parameter maxAssetCount is 5 but the users assetPerBuyerRound length is 7. Meaning 5 == 7
does not hold true anymore and a user can continue listing on and on because 7 can never decrease back down to 5.
This would allow for unlimited listing of assets to a buyer above the maxAssetCount expected by the protocol which may in turn affect the expected assests to go through for a purchase request for the buyer.
Making use of a > =
than the ==
check used in the function.
SwanManager::setMarketParameters pushes the new parameters `marketParameters.push(_marketParameters);` After that, when user calls list the protocol computes the round and the phase `(uint256 round, BuyerAgent.Phase phase,) = buyer.getRoundPhase();` Inside the getRoundPhase function you have this if statement on top: `if (marketParams.length == marketParameterIdx + 1) {`. The setMarketParameters call changed the `marketParams` length, thing which will case the first case to be false and run the else statement. At the end of that statement we see there is a new round. So the second element of this check `(getCurrentMarketParameters().maxAssetCount == assetsPerBuyerRound[_buyer][round].length` is zero, because the [round] is fresh.
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.