Summary
Wrong calculation of round and roundTime in the BuyerAgent::_computePhase
function.
Vulnerability Details
The BuyerAgent::_computePhase
function is the function to compute the current round, phase and time until next phase w.r.t given market parameters.
Below is the function :
File: contracts/swan/BuyerAgent.sol#L308-L327
function _computePhase(SwanMarketParameters memory params, uint256 elapsedTime)
internal
pure
returns (uint256, Phase, uint256)
{
uint256 cycleTime = _computeCycleTime(params);
@--> uint256 round = elapsedTime / cycleTime;
@--> uint256 roundTime = elapsedTime % cycleTime;
if (roundTime <= params.sellInterval) {
return (round, Phase.Sell, params.sellInterval - roundTime);
} else if (roundTime <= params.sellInterval + params.buyInterval) {
return (round, Phase.Buy, params.sellInterval + params.buyInterval - roundTime);
} else {
return (round, Phase.Withdraw, cycleTime - roundTime);
}
}
Impact
As we can see on the highlighted lines, round
and roundTime
has been switched. This may lead to a wrong current round value and time until next phase value returned and a broader impact on the functions that directly or indirectly rely to BuyerAgent::_computePhase()
.
Tools Used
Manual Review.
Recommendations
File: contracts/swan/BuyerAgent.sol#L308-L327
function _computePhase(SwanMarketParameters memory params, uint256 elapsedTime)
internal
pure
returns (uint256, Phase, uint256)
{
uint256 cycleTime = _computeCycleTime(params);
-- uint256 round = elapsedTime / cycleTime;
-- uint256 roundTime = elapsedTime % cycleTime;
++ uint256 round = elapsedTime % cycleTime;
++ uint256 roundTime = elapsedTime / cycleTime;
// example:
// |-------------> | (roundTime)
// |--Sell--|--Buy--|-Withdraw-| (cycleTime)
if (roundTime <= params.sellInterval) {
return (round, Phase.Sell, params.sellInterval - roundTime);
} else if (roundTime <= params.sellInterval + params.buyInterval) {
return (round, Phase.Buy, params.sellInterval + params.buyInterval - roundTime);
} else {
return (round, Phase.Withdraw, cycleTime - roundTime);
}
}