dex-contracts icon indicating copy to clipboard operation
dex-contracts copied to clipboard

User pagination is extremely gas inefficient

Open fleupold opened this issue 5 years ago • 3 comments

I noticed that getting the next user via our pagination is extremely gas inefficient (currently >1M gas)

Screen Shot 2020-04-07 at 11 59 12

I believe the reason for this is that we call the method size() on our IterableAppendOnlySet every time just to make sure it is not empty.

https://github.com/gnosis/dex-contracts/blob/b075120c985d4ad725ab8aaf6a325500907868ca/contracts/BatchExchange.sol#L445-L448

The way size() is implemented is by iterating over all items in the list vis SLOAD, which becomes increasingly inefficient as our set grows (it's unbounded so at some point even a single call will exceed gas limit).

We only rely on this method for our view functions (as far as I can tell, none of them are called via the solutionSubmission or orderPlacement).

We could omit the check or replace it with a check like allUsers.last() != address(0). However, this cannot be done in the BatchExchangeViewer contract as allUsers is declared private: https://github.com/gnosis/dex-contracts/blob/b075120c985d4ad725ab8aaf6a325500907868ca/contracts/BatchExchange.sol#L69.

fleupold avatar Apr 07 '20 10:04 fleupold

#647 mitigates this somewhat in the viewer by only fetching the list of users required for this page once. This allows to fetch the open orders with a page size of 1000 for now.

To really fix this we need to upgrade the IterableAppendOnlySet (pending https://github.com/gnosis/solidity-data-structures/pull/22)

fleupold avatar Apr 09 '20 12:04 fleupold

If we end up making the SPAM-rinkeby-test, I think it's best to do it in a newly deployed contract, so we don't ruin the current contract to get what's the limit. Does it make sense?

anxolin avatar Apr 09 '20 13:04 anxolin

Yes that makes perfect sense.

fleupold avatar Apr 09 '20 13:04 fleupold