-
Notifications
You must be signed in to change notification settings - Fork 58
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Prevent Collateral updates with pending orders #1711
Prevent Collateral updates with pending orders #1711
Conversation
Codecov Report
@@ Coverage Diff @@
## main #1711 +/- ##
=======================================
Coverage 72.77% 72.77%
=======================================
Files 57 57
Lines 720 720
Branches 236 236
=======================================
Hits 524 524
Misses 167 167
Partials 29 29
📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
@@ -54,6 +54,11 @@ contract PerpsAccountModule is IAccountModule { | |||
account.id = accountId; | |||
} | |||
|
|||
// Check if there are pending orders | |||
if (account.hasPendingOrders) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we add a check here that amountDelta < 0
? I don't think a user should ever be prevented from depositing collateral, but it makes sense to prevent withdrawals.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we need to check both sides in order to prevent some side effects we noticed on perpsv2 (i.e. ability to manipulate appropriate time to execute an order)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How could a person manipulate the timing by adding more collateral? I see how they could withdraw to cause the execution to revert, then deposit again when they want to execute.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea troy's point does make sense to me
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How could a person manipulate the timing by adding more collateral? I see how they could withdraw to cause the execution to revert, then deposit again when they want to execute.
@Tburm it just gives the user more tools to play with with bad intents, like imagine with me during crashing market prices, the user submits intention at the brink of what is possible with his margin, that by the time the order is elegible for execution, he doesn't have enough margin to get executed, he gets a free option to add collateral to be allowed to execute the pending order during that execution time window
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is a safer design therefore, to just allow modification of collateral if no pending order is there
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so, basically (we had this discussion on perpsV2, and there are some complex vectors or side effects) we want to prevent any change of collateral while orders are pending.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kaleb-keny That makes sense, thanks for the detail. I assumed they could somehow guarantee better execution, but in your example it would still require some favorable price action.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Tburm yeah the attacker would need to check for a favorable with respect to the more lively prices offchain (which are expected to impact his position post-execution)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense, thanks for the details. We should just make sure frontends are well aware of this, since users should know if/when they are prevented from depositing to fix underwater positions.
markets/perps-market/test/integration/Orders/OffchainAsyncOrder.pending.test.ts
Outdated
Show resolved
Hide resolved
What's the difference between this and checking if the account have an order by |
it needs to be done in a loop for each marketId |
systems().PerpsMarket | ||
); | ||
}); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No sure how valuable, but we could add an assertion for an order on the same market too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in fact that was already tested here: https://github.com/Synthetixio/synthetix-v3/blob/main/markets/perps-market/test/integration/Orders/OffchainAsyncOrder.commit.test.ts#L209
You can move orders from market to an account level and track a mapping of If you track Orders aren't tightly coupled to markets and they don't have an impact until settlement occurs. For settlement, as long as the keeper can find the associated marketId this order belongs to then it will operate just fine too. |
* Use load instead of mapping for AsyncOrder * small fix * cleanup
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor changes; logic is clear and looks good 👍🏽
/** | ||
* @notice Gets thrown when pending orders exist and attempts to modify collateral. | ||
*/ | ||
error PendingOrdersExist(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe rename to PendingOrderExists
since we can't have multiple orders anyway
AsyncOrder.Data storage order = AsyncOrder.load(commitment.accountId); | ||
|
||
if (order.sizeDelta != 0) { | ||
if (order.sizeDelta != 0 && order.marketId == commitment.marketId) { | ||
revert OrderAlreadyCommitted(commitment.marketId, commitment.accountId); | ||
} | ||
|
||
if (order.sizeDelta != 0) { | ||
revert IAccountModule.PendingOrdersExist(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe do AsyncOrder.createValid(..)
and move all these checks into that function. would clean up this method quite a bit.
// Check if there are pending orders | ||
if (AsyncOrder.load(accountId).sizeDelta != 0) { | ||
revert PendingOrdersExist(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could move this into the account storage and do account.checkPendingOrders()
or smth. as much as possible trying to move validations into storage libraries. non blocking; only if you think its cleaner
@@ -547,6 +547,7 @@ library PerpsAccount { | |||
struct Data { | |||
mapping(uint128 => uint256) collateralAmounts; | |||
uint128 id; | |||
bool hasPendingOrders; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dont think this is used; re-run yarn build
👍🏽
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🚢
Check if there's a pending order for the account for updateCollateral and commitOrder.
After some discussions the definition is that only a single pending order can exists per account, hence this PR also moves the asyncOrders mapping on
PerpsMarket
to a loadableAsyncOrder
instance mostly used inPerpsAccount
.