-
Notifications
You must be signed in to change notification settings - Fork 14
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
Refactor to remove Head and Tail address #129
Conversation
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 that insertSorted
can be completely refactored with this new design. See morpho-org/morpho-optimizers#1255
While I love the idea, it would also require a big refactor of the verification done with Certora. Is it worth to invest some time into it ? @morpho-org/onchain-team |
If it would take you 1 day or something I'm against and we can forget about it |
Yes probably one or two days to do it: I know well how it works now but it still requires to refactor almost all the invariants |
while (numberOfIterations < maxIterations && next != address(0) && list.accounts[next].value >= value) { | ||
next = list.accounts[next].next; | ||
unchecked { | ||
++numberOfIterations; | ||
} | ||
} |
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.
this should work too, idk what's best
while (numberOfIterations < maxIterations && next != address(0) && list.accounts[next].value >= value) { | |
next = list.accounts[next].next; | |
unchecked { | |
++numberOfIterations; | |
} | |
} | |
unchecked { | |
while (numberOfIterations++ < maxIterations && next != address(0) && list.accounts[next].value >= value) { | |
next = list.accounts[next].next; | |
} | |
} |
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 this implementation, on the last iteration, numberOfIterations
will also be incremented. At the end of the loop, numberOfIterations
will be one greater than in the current implementation. To replicate the same behavior as the current implementation, the comparison numberOfIterations == maxIterations
would need to be changed to numberOfIterations == maxIterations + 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.
To minimize storage reads (which is the heaviest operation), I would have written it like this:
uint256 numberOfIterations;
address prevId = address(0);
address nextId = list.accounts[address(0)].next; // If not added at the end of the list `id` will be inserted before `next`.
Account storage nextAccount = list.accounts[nextId];
unchecked {
while (true) {
if (++numberOfIterations == maxIterations) {
nextAccount = list.accounts[address(0)];
prevId = nextAccount.prev;
break;
} else if (nextId == address(0) || nextAccount.value < value) {
break;
} else {
prevId = nextId;
nextId = nextAccount.next;
nextAccount = list.accounts[nextId];
}
}
}
list.accounts[id] = Account(prevId, nextId, value);
list.accounts[prevId].next = id;
nextAccount.prev = id;
if (numberOfIterations == maxIterations) { | ||
next = address(0); | ||
} |
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.
this works too, but maybe less readable
if (numberOfIterations == maxIterations) { | |
next = address(0); | |
} | |
assembly { | |
next := mul(next, iszero(eq(numberOfIterations, maxIterations))) | |
} |
while (numberOfIterations < maxIterations && next != address(0) && list.accounts[next].value >= value) { | ||
next = list.accounts[next].next; | ||
unchecked { | ||
++numberOfIterations; | ||
} | ||
} |
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 minimize storage reads (which is the heaviest operation), I would have written it like this:
uint256 numberOfIterations;
address prevId = address(0);
address nextId = list.accounts[address(0)].next; // If not added at the end of the list `id` will be inserted before `next`.
Account storage nextAccount = list.accounts[nextId];
unchecked {
while (true) {
if (++numberOfIterations == maxIterations) {
nextAccount = list.accounts[address(0)];
prevId = nextAccount.prev;
break;
} else if (nextId == address(0) || nextAccount.value < value) {
break;
} else {
prevId = nextId;
nextId = nextAccount.next;
nextAccount = list.accounts[nextId];
}
}
}
list.accounts[id] = Account(prevId, nextId, value);
list.accounts[prevId].next = id;
nextAccount.prev = id;
@@ -79,12 +77,11 @@ library DoubleLinkedList { | |||
/// @param id The address of the account. | |||
function remove(List storage list, address id) internal { |
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.
this function can be optimized:
function remove(List storage list, address id) internal {
Account storage account = list.accounts[id];
if (id == address(0)) revert AddressIsZero();
if (account.value == 0) revert AccountDoesNotExist();
address prevId = account.prev;
address nextId = account.next;
list.accounts[prevId].next = nextId;
list.accounts[nextId].prev = prevId;
account.prev = address(0);
account.next = address(0);
account.value = 0;
}
The line if (id == address(0)) revert AddressIsZero();
can be removed, but the error thrown would no longer be accurate in the case of a null address.
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 will implement but not sure we will merge the PR as mentioned above
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.
can you remove changes to the test @Tristan22400 please?
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 we do not want to merge because of this discussion
Agree with you @QGarchery. Sorry about that @Tristan22400 I'm closing this PR |
Fixes : #85