Skip to content

feat(wrapper-registry): adding wrapper-registry#50

Open
DRC9702 wants to merge 5 commits into
mainfrom
PROM-74-wrapper-registry-contract
Open

feat(wrapper-registry): adding wrapper-registry#50
DRC9702 wants to merge 5 commits into
mainfrom
PROM-74-wrapper-registry-contract

Conversation

@DRC9702

@DRC9702 DRC9702 commented Feb 4, 2022

Copy link
Copy Markdown
Contributor

Changes:

  • Adding IWrapperRegistry and WrapperRegistry

Testing:

Screen Shot 2022-02-08 at 2 28 40 PM

  • Wrote unit tests with 100% coverage

Reviewers:

@marktoda
@aalavandhan
@Melvillian
@Fiddlekins
@SocksNFlops
@MichalStachnik

* @title Wrapper Registry Interface
* @notice Interface for storing Wrapper addresses for tokens. Tokens are stored in bijection.
*/
interface IWrapperRegistry {

@aalavandhan aalavandhan Feb 4, 2022

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nice and clean interface definition 👍

Comment thread contracts/WrapperRegistry.sol Outdated
override
returns (address)
{
for (uint256 i = 0; i < numWrappers(); i++) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You could just invoke IWrapper(wrapper).underlying()? (which is one external storage read, rather than n internal reads)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I guess this function also had the purpose of validating that the underlying<->wrapper entry was present in the registry. Since IWrapper already has that functionality, it might actually be redundant to include this function at all. Thoughts?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'd elect to remove. You could determine if the wrapper was already in the registry with a staticcall to addWrapper

Comment thread contracts/WrapperRegistry.sol Outdated
Comment thread test/unit/WrapperRegistry.ts
Comment thread contracts/WrapperRegistry.sol Outdated
Comment thread contracts/WrapperRegistry.sol Outdated
/**
* @dev Mapping of underlying tokens to wrapper tokens
*/
mapping(address => address) private _wrapperMapping;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You can make the _underlyingToWrapperMapping an EnumerableMap instead of the regular mapping and get rid of the _underlyingTokens address set.

https://docs.openzeppelin.com/contracts/3.x/api/utils#EnumerableMap

That should still accomplish what you want ie):

  • O(1) add, remove and existence checks for underlying tokens
  • O(n) enumeration

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@aalavandhan, I believe EnumerableMap currently only has support for UintToAddressMap. That's the reason why I use both EnumerableSet and mapping to achieve the same goal.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Makes sense 👍

@marktoda marktoda left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks great, nice job

Comment thread contracts/WrapperRegistry.sol Outdated
override
returns (address)
{
for (uint256 i = 0; i < numWrappers(); i++) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'd elect to remove. You could determine if the wrapper was already in the registry with a staticcall to addWrapper

Comment thread test/unit/WrapperRegistry.ts Outdated
Comment thread test/unit/WrapperRegistry.ts
returns (address)
{
address underlyingToken = IButtonWrapper(wrapperToken).underlying();
if (

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is this check really required? The owner can ensure that they only add immutable wrappers so this will always be true.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@aalavandhan This is a non-permissioned view function that operates as the opposite of getWrapperFromUnderlying. The issue of not doing the check is that you can just take any wrapper and call IButtonWrapper(wrapperToken).underlying() without confirming if the wrapper is even in the registry or not. So if AMPL has one official wrapper and one unofficial bootleg wrapper, they'll both return AMPL even though only the first one is actually in the registry.

This isn't really a problem, but I think the point is that this function also operates as a check of "is this wrapper in the registry?". Otherwise people would just call .underlying() directly on the wrapper.

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