Skip to content
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

0 byte/payable selector bug #246

Conversation

startswithaj
Copy link
Contributor

@startswithaj startswithaj commented May 15, 2024

There is a bug where selector tracking is broken when adding and then removing the payable selector 0x00000000. For this issue to occur the 0x00000000 selector has to be added to a new row, and then removed.

Only effects facet-> selector tracking and does not/cannot effect selector -> facet.

Please see SolidStateDiamond.behavior.ts for POC. And DiamondWritableInternal.sol for a potential fix.

// The diamond example comes with 8 function selectors
// [cut, loupe, loupe, loupe, loupe, erc165, transferOwnership, owner]
// This bug manifests if you add the payableSelector(0x00000000) to the 1st slot in a fresh row and remove it
// We Add 8 more random selectors to the diamond, then add the payable selector to the 1st slot in a fresh row
// [cut, loupe, loupe, loupe, loupe, erc165, transferOwnership, owner]
// [rand1, rand2, rand3, rand4, rand5, rand6, rand7, rand8]
// [payableSelector]
// We then remove the payable selector from the diamond, this causes malfunction in the slot tracking, 
// And `rand8` is lost from the selector tracking

If an already deployed Diamond suffers from this issue, whereby a selector is missing from a facet mapping, you must Remove the selector and Add it again. Replace on the same facet will not fix the mapping.

If you want to check if a Diamond Suffers from this bug, you get a list of the selectors you expect to be on each facet and compare them to the output of diamond.facets(). You can use the event history of a diamond to calculate which selectors should be exposed on each facet.

This does not affect the onchain behaviour of a diamond.

closes #60

@ItsNickBarry
Copy link
Member

Linking #60 because I believe it's related.

Comment on lines 153 to 161
if (
selectorSlot != 0 ||
(selectorInSlotIndex != 0 && selector == 0)
) {
selectorInSlotIndex--;
} else {
selectorSlotCount--;
selectorSlot = l.selectorSlots[selectorSlotCount];
selectorInSlotIndex = 7;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Invert the logic and revert the order of the if/else blocks:

Suggested change
if (
selectorSlot != 0 ||
(selectorInSlotIndex != 0 && selector == 0)
) {
selectorInSlotIndex--;
} else {
selectorSlotCount--;
selectorSlot = l.selectorSlots[selectorSlotCount];
selectorInSlotIndex = 7;
if (
selectorSlot == 0 &&
(selectorInSlotIndex == 0 || selector != 0)
) {
selectorSlotCount--;
selectorSlot = l.selectorSlots[selectorSlotCount];
selectorInSlotIndex = 7;
} else {
selectorInSlotIndex--;

Makes the diff easier to reason about, and == is fundamentally easier to reason about than !=.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also I'm rather confident that the selector comparison is redundant. And I'm somewhat confident that selectorSlot comparison is also redundant. Isn't the selectorInSlotIndex comparison all we need? Tests pass if I remove the others.

Like this:

if (selectorInSlotIndex == 0) {
    selectorSlotCount--;
    selectorSlot = l.selectorSlots[selectorSlotCount];
    selectorInSlotIndex = 7;
} else {
    selectorInSlotIndex--;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think you are definitely right about this. Updating.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made the above changes after merging the diamond-cleanup branch and pushed them here.

@ItsNickBarry ItsNickBarry changed the base branch from master to diamond-cleanup May 22, 2024 15:52
@ItsNickBarry
Copy link
Member

@startswithaj I changed the base of this PR to diamond-cleanup, and merged those changes here.

@startswithaj
Copy link
Contributor Author

Should I merge this?

Copy link
Member

@ItsNickBarry ItsNickBarry left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@startswithaj Okay to merge as long as you're okay with the new changes I've pushed. Let's also wait 12 hours so that @NouDaimon can analyse the situation.

Copy link
Collaborator

@NouDaimon NouDaimon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix looks good to me.

@ItsNickBarry ItsNickBarry merged commit 9358895 into solidstate-network:diamond-cleanup May 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Unexpected error message when calling Diamond selectors that have been removed
3 participants