The same deposited tokens can be used as margins for multiple positions
Summary
When a user deposits or withdraws tokens of any valid token type T through AccountFacet.deposit/createWithdrawRequest, these tokens can be used to increase/decrease the initialMarginInUsdFromBalance field for any number of positions whose marginToken is T. However, the same deposited/withdrawn tokens should only be counted into/out of the margin of at most one cross-margin position.
Vulnerability Detail
The AccountFacet.deposit/executeWithdraw function calls AssetsProcess.deposit/withdraw, which eventually calls PositionMarginProcess.updateAllPositionFromBalanceMargin. In this function, the fourth parameter of updatePositionFromBalanceMargin is the variable amount, which means that the same deposited/withdrawn tokens are counted into/out of the margin of multiple positions whose marginToken is the same as the token argument (by increasing/decreasing their initialMarginInUsdFromBalance fields).
As a matter of factor, the value of the fourth argument of the call to updatePositionFromBalanceMargin should be reduceAmount.
As evidence, if we first deposit tokens and then increase a position, we find that when some tokens are used as the margin of one position ("used as margin" means counted into the initialMarginInUsdFromBalance here), the usedAmount value increases by initialMarginInUsd (initialMarginInUsd >= initialMarginInUsdFromBalance), thus preventing the same tokens from being used as margin for other positions. This should be the expected behavior.
The same deposited/withdrawn tokens can be counted into the updating of the initialMarginInUsdFromBalance field for multiple positions.
The contract will thus overestimate/underestimate the risk of affected crossMargin positions. Users can profit accordingly.
link
High
The same deposited tokens can be used as margins for multiple positions
Summary
When a user deposits or withdraws tokens of any valid token type
T
throughAccountFacet.deposit/createWithdrawRequest
, these tokens can be used to increase/decrease theinitialMarginInUsdFromBalance
field for any number of positions whosemarginToken
isT
. However, the same deposited/withdrawn tokens should only be counted into/out of the margin of at most one cross-margin position.Vulnerability Detail
The
AccountFacet.deposit/executeWithdraw
function callsAssetsProcess.deposit/withdraw
, which eventually callsPositionMarginProcess.updateAllPositionFromBalanceMargin
. In this function, the fourth parameter ofupdatePositionFromBalanceMargin
is the variableamount
, which means that the same deposited/withdrawn tokens are counted into/out of the margin of multiple positions whose marginToken is the same as thetoken
argument (by increasing/decreasing theirinitialMarginInUsdFromBalance
fields). As a matter of factor, the value of the fourth argument of the call toupdatePositionFromBalanceMargin
should bereduceAmount
.As evidence, if we first deposit tokens and then increase a position, we find that when some tokens are used as the margin of one position ("used as margin" means counted into the
initialMarginInUsdFromBalance
here), theusedAmount
value increases byinitialMarginInUsd
(initialMarginInUsd >= initialMarginInUsdFromBalance
), thus preventing the same tokens from being used as margin for other positions. This should be the expected behavior.Impact
The same deposited/withdrawn tokens can be counted into the updating of the
initialMarginInUsdFromBalance
field for multiple positions. The contract will thus overestimate/underestimate the risk of affected crossMargin positions. Users can profit accordingly.Code Snippet
Tool used
Manual Review
Recommendation
Fixed the fourth parameter of the
updatePositionFromBalanceMargin
function call in theupdateAllPositionFromBalanceMargin
function toreduceAmount
.Duplicate of #35