-
Notifications
You must be signed in to change notification settings - Fork 26
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
supply queue cannot have duplicates #367
Conversation
This was formerly suggested in #284 You can see there the reasoning and some numbers on gas cost The implementation in this PR is probably better because the input can be chosen to be cheaper |
I looked at the gas with 30 markets in this PR, it's +190k if given without sorting, and +30k if given already sorted. Thanks for the pointer I missed #284 and https://github.com/cantinasec/review-morpho-blue-1/issues/109. To me the main reason is to make sure the values returned by |
These numbers are low enough to me for an admin function so I believe it is worth being merged |
// Gnome sort. O(n) if already sorted. | ||
uint256 j; | ||
while (j < length) { | ||
if (j == 0 || Id.unwrap(sorted[j]) >= Id.unwrap(sorted[j - 1])) { |
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.
I feel like sorted[j]
& sorted[j-1]
could be stored as variables not only to be cheaper (max hundred gas) but also to be clearer
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.
Like curr = sorted[j]
, prev = sorted[j-1]
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.
I think you mean this but let me know if I misunderstood
uint256 j;
Id cur;
Id prev;
while (j < length) {
if (j==0) {
j++;
} else {
cur = sorted[j];
prev = sorted[j-1];
if (Id.unwrap(cur) >= Id.unwrap(prev)) {
j++;
} else {
(sorted[j], sorted[j - 1]) = (prev, cur);
j--;
}
}
}
prev = Id.wrap(0);
for (uint256 i; i < length; ++i) {
if (Id.unwrap(prev) == Id.unwrap(sorted[i])) revert ErrorsLib.DuplicateMarket(sorted[i]);
prev = sorted[i];
}
it's -23k gas (out of ~350k)
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.
Indeed! Not sure it's better in the end
The last for loop is maybe too much too, simply naming variables in the while loop could be enough
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.
to clarify, you're saying it may be worth moving duplicate detection inside the while loop. I think it's correct because:
- Some pair of equal elements in the array must end up with both elements adjacent to each other. Take the leftmost such pair.
- If the pair was already adjacent before sorting and never moved, since the sort looks at all initially adjacent pairs once, they will be detected
- If the last move that made the pair adjacent moved the right element of the pair into position, the next comparison is between the elements of the pair (
j--
), so they will be detected - If the last move that made the pair adjacent moved the left element of the pair into position, the next comparison will go left (
j--
) but the loop will not end untilj == length
and so the elements will compared and detected.
edit: inlining the equality check into the while loop is not worth the gas because it adds one every equality comparison at every step of the sort -- many of which return false but consume gas
is there a consensus on if we need this pr or not? I feel that we can just delegate to the risk manager to not have duplicates, and have maxDeposit and maxMint rely on this trust. wdyt? |
did we think about having a mapping |
Just had a call with @MathisGD and @Jean-Grimal. We think this PR adds too much complexity while it should be the responsibility of the allocator not to let duplicate markets in the |
edit: goal is to make sure the values returned by
maxDeposit
andmaxMint
are correctSupply queue is sorted and checked for duplicates on
setSupplyQueue
.