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

Remove unbounded loop in size() implementation #21

Merged
merged 2 commits into from
Apr 8, 2020
Merged

Conversation

fleupold
Copy link
Contributor

@fleupold fleupold commented Apr 7, 2020

More context: gnosis/dex-contracts#641

size() is currently iterating over all items making it potentially very gas costly. Since this behaviour is internal to the library it is easy for dependent contracts to oversee the consequences.

This PR therefore changes the implementation so that every insert will increment the size variable.

Due to the fact that the size variable is aligned (last takes 160 bits leaving 96 in the word), the amount of gas used on insertion barely changes (by measuring test suite with eth-gas-reporter):

min max avg
No storage 25713 66479 56044
U96 25469 66552 53192
U256 25469 86700 64361

I also removed the atIndex method as it is subject to the same flaw and therefore of questionable use anyway.

@fleupold fleupold requested a review from a team April 7, 2020 14:45
}

function next(address value) public view returns (address) {
return data.next(value);
}

function atIndex(uint256 index) public view returns (address) {
Copy link
Contributor

@bh2smith bh2smith Apr 7, 2020

Choose a reason for hiding this comment

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

I don’t see how removing this is relevant here. This is a standard implement of getting and element by index from such a data structure and I am under the impression that this is used somewhere.

However, I understand the implementation is subject to the same issue and suppose it would be overall better for someone to fetch the entire set and get their elements as needed off chain.

We will soon find out if/where it was being used.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We are not currently using it and my worry was that the fact this is using an unbounded loop is hidden behind a layer of abstraction making it easy for people to accidentally use it in code that would break if the set got too big. I can put it back if you feel it's valueable to keep.

Copy link
Contributor

Choose a reason for hiding this comment

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

Nah. There is no need to keep it if it isn't used.

Copy link
Contributor

Choose a reason for hiding this comment

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

Thinking about this a but more, wouldn't we avoid a lot of mess if size was just stored in the contract?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Technically we store the size in the contract (since the contract stores the self storage struct). The point for this library is to abstract set operations such as insertion and iteration (and arguably keeping track of size).

@fleupold fleupold changed the base branch from yarn to master April 8, 2020 20:44
@fleupold fleupold merged commit b511d0a into master Apr 8, 2020
@fleupold fleupold deleted the size_fix branch April 8, 2020 20:56
fleupold added a commit to gnosis/dex-contracts that referenced this pull request Aug 27, 2020
In order to deploy the exchange on xDai, we need to use the newest version of the solidity-data-structures package. There was a breaking change in the way that size gets computed (gnosis/solidity-data-structures#21) which requires small adjustments in the smart contract code.

### Test Plan

CI
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.

3 participants