Afterwards, if toggleTraderActive is called on the traderId, the traderId will be pushed to activeTraders again.
function toggleTraderActive(uint256 traderId)
external
onlyRoleMalt(ADMIN_ROLE, "Must have admin privs")
{
SwingTraderData storage trader = swingTraders[traderId];
require(trader.id == traderId, "Unknown trader");
bool active = !trader.active;
trader.active = active;
if (active) {
// setting it to active so add to activeTraders
trader.index = activeTraders.length;
activeTraders.push(traderId);
} else {
This means that in getTokenBalances()/calculateSwingTraderMaltRatio(), since there are two identical traderIds in activeTraders, the data in this trader will be calculated twice.
Wrong getTokenBalances() will result in wrong data when syncGlobalCollateral().
What's more serious is that even if toggleTraderActive is called again, only one traderId will pop up from activeTraders, and the other traderId cannot be popped up.
This causes the trade to participate in the calculation of getTokenBalances()/calculateSwingTraderMaltRatio() even if the trade is deactive.
Considering that the active parameter is likely to be false when addSwingTrader is called and cannot be recovered, this vulnerability should be high risk
Lines of code
https://github.com/code-423n4/2023-02-malt/blob/700f9b468f9cf8c9c5cffaa1eba1b8dea40503f9/contracts/StabilityPod/SwingTraderManager.sol#L397-L447
Vulnerability details
Impact
In SwingTraderManager.addSwingTrader, if active = false, the traderId is also pushed to activeTraders.
Afterwards, if toggleTraderActive is called on the traderId, the traderId will be pushed to activeTraders again.
This means that in getTokenBalances()/calculateSwingTraderMaltRatio(), since there are two identical traderIds in activeTraders, the data in this trader will be calculated twice. Wrong getTokenBalances() will result in wrong data when syncGlobalCollateral().
Wrong calculateSwingTraderMaltRatio() will cause MaltDataLab.getRealBurnBudget()/getSwingTraderEntryPrice() to be wrong.
What's more serious is that even if toggleTraderActive is called again, only one traderId will pop up from activeTraders, and the other traderId cannot be popped up.
This causes the trade to participate in the calculation of getTokenBalances()/calculateSwingTraderMaltRatio() even if the trade is deactive. Considering that the active parameter is likely to be false when addSwingTrader is called and cannot be recovered, this vulnerability should be high risk
Proof of Concept
https://github.com/code-423n4/2023-02-malt/blob/700f9b468f9cf8c9c5cffaa1eba1b8dea40503f9/contracts/StabilityPod/SwingTraderManager.sol#L397-L447
Tools Used
None
Recommended Mitigation Steps
Change to