OpenZeppelin / openzeppelin-contracts

OpenZeppelin Contracts is a library for secure smart contract development.
https://openzeppelin.com/contracts
MIT License
24.87k stars 11.78k forks source link

Consider code duplication as optimization for EnumerableSet/Map #2259

Closed frangio closed 1 year ago

frangio commented 4 years ago

Our implementation of EnumerableSet and EnumerableMap is using a kind of type erasure whereby the typed key/value is cast to and from bytes32, and the typed interface internally uses a set of functions that manipulate structures of bytes32. For example:

https://github.com/OpenZeppelin/openzeppelin-contracts/blob/394987f36527f16f85efdfbe9c944da629077917/contracts/utils/EnumerableSet.sol#L147-L149

A quick inspection showed that Solidity may not be inlining these internal calls, contributing to bytecode size and additional gas cost.

We should first confirm that this is the case.

I believe this is an optimization that should be done by the compiler, and we should report an issue. However, we may want to work around it in the meantime. A potential workaround would be to repeat the code for each new variant of the data structure (i.e. manual monomorphization). We should see whether this approach generates better code (smaller, less expensive).

frangio commented 2 years ago

We are now doing code generation but retain the "type erasure" approach due to backwards compatibility of the storage layout (arguably a limitation of our Upgrades Plugins).

https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3429#issuecomment-1194551666