Skip to content

Conversation

@nicholaspai
Copy link
Member

@nicholaspai nicholaspai commented Jan 4, 2023

This PR makes SpokePools compatible with OpenZeppelin's upgradeable proxy pattern. Some important changes to support upgradeability:

  • SpokePool's constructor adds the _disableInitializers call to prevent it from being left uninitialized.
  • All non-constant state variables that have initial values are instead set in the initialize function.
  • Contracts that the SpokePool extends such as Lockable and Testable that have constructors replaces those with upgradeable versions that replace constructors with initializers.
  • All unit tests involving the spoke pool are changed to interface with an upgradeable version of the spoke pool

This PR makes SpokePools compatible with OpenZeppelin's upgradeable proxy pattern
@linear
Copy link

linear bot commented Jan 4, 2023

ACX-520 Add features to SpokePool to make future upgrades easier

Make SpokePool compatible with OZ upgradeable proxies

nicholaspai and others added 9 commits January 4, 2023 17:54
UUPS proxies allow the implementation contract to define the conditions under which an upgrade can be called, compared to a Transparent proxy in which only the owner of the proxy can upgrade.

This allows the SpokePool upgrades to be triggered by the cross domain admin via the HubPool
 into nick/acx-520-add-features-to-spokepool-to-make-future
 into nick/acx-520-add-features-to-spokepool-to-make-future
@nicholaspai nicholaspai marked this pull request as ready for review January 24, 2023 18:26
@nicholaspai nicholaspai changed the title [WIP] feat: Make SpokePool's upgradeable !feat: Make SpokePool's upgradeable Jan 24, 2023
@nicholaspai nicholaspai requested review from mrice32 and pxrl January 29, 2023 18:43
Copy link
Contributor

@mrice32 mrice32 left a comment

Choose a reason for hiding this comment

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

LGTM!

@@ -0,0 +1,80 @@
// SPDX-License-Identifier: AGPL-3.0-only
Copy link
Contributor

Choose a reason for hiding this comment

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

As discussed IRL, maybe we should just use the OZ lockable contract? Do you see any problem with that?

Copy link
Member Author

Choose a reason for hiding this comment

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

Nope, I looked into Lockable. The main feature we add is the _startReentrantGuardDisabled internal function but that's not used by Across contracts so I think we're safe to use OZ lockable

Copy link
Contributor

Choose a reason for hiding this comment

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

Awesome!


/**
* @title MockSpokePool
* @notice Logic is 100% copied from "@uma/core/contracts/common/implementation/MultiCaller.sol" but one
Copy link
Contributor

Choose a reason for hiding this comment

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

We should remember to exclude this contract from the audit scope considering the contract's logic has already been audited.

Comment on lines -5 to +6
"Arbitrum_Adapter": { "address": "0x937958992799bF4A9a656E6596FD10d7Da5c2216", "blockNumber": 14704380 },
"Arbitrum_Adapter": { "address": "0x29528780E29abb8Af95a5e5a125b94766987543F", "blockNumber": 16243583 },
"Arbitrum_RescueAdapter": { "address": "0xC6fA0a4EBd802c01157d6E7fB1bbd2ae196ae375", "blockNumber": 16233939 },
Copy link
Contributor

Choose a reason for hiding this comment

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

Seems unrelated - maybe split it out?

Copy link
Member Author

Choose a reason for hiding this comment

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

This was accidentally removed so i'm just adding it back here

Copy link
Contributor

Choose a reason for hiding this comment

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

It's preferable from a commit hygiene standpoint to split it out and submit it separately - at least so it's not ++confusing when someone looks back at the commit history and sees it modified as part of something totally unrelated. Just my 2c.

@pxrl pxrl changed the title !feat: Make SpokePool's upgradeable !feat: Make SpokePools upgradeable Jan 31, 2023
// Any deposit quote times greater than or less than this value to the current contract time is blocked. Forces
// caller to use an approximately "current" realized fee. Defaults to 10 minutes.
uint32 public depositQuoteTimeBuffer = 600;
uint32 public depositQuoteTimeBuffer;
Copy link
Contributor

@pxrl pxrl Jan 31, 2023

Choose a reason for hiding this comment

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

It won't be possible to add any more state variables to the base SpokePool after deployment. Have we ruled out adding some placeholders, just in case we find a use for something else in future?

Copy link
Member Author

Choose a reason for hiding this comment

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

Great point 6a9f509

What do you and @mrice32 think about adding 50 storage slots for future upgrades?

Copy link
Contributor

Choose a reason for hiding this comment

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

Great call! Any reason not to make it way way bigger than we'd ever need? Like 1000? Just to be super safe

Copy link
Member Author

Choose a reason for hiding this comment

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

Here's a thought experiment. Imagine we wanted to support bridging with arbitrary data so that someone could bridge-and-swap. Say we had to upgrade the deposit() function (or add a new depositWithData function). Would this be possible with upgradeable proxies? How much of the extra storage slots would we need?

Copy link
Contributor

Choose a reason for hiding this comment

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

It depends on the implementation. If the data is just hashed into the deposit data and added to an event, no storage changes would be necessary.

If we needed to store extra info about each deposit, deposits would need extra storage, but they aren't stored continuously, so that can be done without pre-reserving slots.

In this implementation, what extra contiguous storage would you imagine needing?

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm not sure, this was just a functionality that I discussed with Ryan about adding and wanted to make sure we're prepared for it. Basically bridge-and-swap would be a good UX addition

Copy link
Member Author

Choose a reason for hiding this comment

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

What if we needed to add a new Base contract function, does that take up slots?

Copy link
Contributor

Choose a reason for hiding this comment

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

Nope, functions don't take up slots or anything. They are just more bytecode in the implementation contract.

nicholaspai and others added 5 commits January 31, 2023 10:59
 into nick/acx-520-add-features-to-spokepool-to-make-future
Signed-off-by: nicholaspai <npai.nyc@gmail.com>
Co-authored-by: Paul <108695806+pxrl@users.noreply.github.com>
Signed-off-by: nicholaspai <npai.nyc@gmail.com>
Copy link
Contributor

@mrice32 mrice32 left a comment

Choose a reason for hiding this comment

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

LGTM!

@nicholaspai nicholaspai requested a review from mrice32 January 31, 2023 20:32
Copy link
Contributor

@mrice32 mrice32 left a comment

Choose a reason for hiding this comment

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

Copy link
Contributor

@pxrl pxrl left a comment

Choose a reason for hiding this comment

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

Nice!

@pxrl
Copy link
Contributor

pxrl commented Feb 1, 2023

@nicholaspai One final thought: the OVM_SpokePool is also a base contract. Not sure whether we want to reserve some slots there as well?

Signed-off-by: nicholaspai <npai.nyc@gmail.com>
Signed-off-by: nicholaspai <npai.nyc@gmail.com>
@nicholaspai
Copy link
Member Author

nicholaspai commented Feb 2, 2023

@nicholaspai One final thought: the OVM_SpokePool is also a base contract. Not sure whether we want to reserve some slots there as well?

Great call, i've added 100 slots for OVM_SpokePool and updated SpokePool's __gap to 1000

cc @mrice32

@nicholaspai nicholaspai requested review from mrice32 and pxrl February 2, 2023 21:56
Copy link
Contributor

@mrice32 mrice32 left a comment

Choose a reason for hiding this comment

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

@nicholaspai One final thought: the OVM_SpokePool is also a base contract. Not sure whether we want to reserve some slots there as well?

Great call, i've added 100 slots for OVM_SpokePool and updated SpokePool's __gap to 1000

cc @mrice32

@nicholaspai why not just use a 1000 gap everywhere to give us tons of room and standardize? We have 2^256 slots to work with here, so there's no running out :).

@nicholaspai nicholaspai requested a review from mrice32 February 3, 2023 01:53
Copy link
Contributor

@mrice32 mrice32 left a comment

Choose a reason for hiding this comment

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

LGTM!

@nicholaspai nicholaspai requested a review from mrice32 February 3, 2023 19:43
@nicholaspai
Copy link
Member Author

@dohaki @mrice32 @pxrl I had to update this to take into account the new EIP712 contract that the SpokePool extends. This required changing that contract to be upgradeable with an initializer function instead of a constructor see this commit 22f5fbe#diff-8c305f0568345cd237252c531582ce424adc9c7c9151cfefe304fd389b874c59 !

@nicholaspai nicholaspai requested a review from dohaki February 3, 2023 19:48
Copy link
Contributor

@mrice32 mrice32 left a comment

Choose a reason for hiding this comment

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

LGTM!

* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[1000] private __gap;
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is the gap at the bottom of the file below the functions? Shouldn't it be at the end of the list of variables, like in the other contracts?

Copy link
Member Author

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

Makes sense. Either way is totally fine! However, I think this PR has it done both ways. Ovm_SpokePool and SpokePool seem to have it at the top. As long as it's consistent, LGTM!

* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[1000] private __gap;
Copy link
Contributor

Choose a reason for hiding this comment

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

Same as above.

* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[1000] private __gap;
Copy link
Contributor

Choose a reason for hiding this comment

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

Same as above.

@nicholaspai nicholaspai requested a review from mrice32 February 4, 2023 18:10
Copy link
Contributor

@dohaki dohaki left a comment

Choose a reason for hiding this comment

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

Awesome LGTM 👍 I mainly looked at the changes related to EIP712

Copy link
Contributor

@mrice32 mrice32 left a comment

Choose a reason for hiding this comment

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

Signed-off-by: nicholaspai <npai.nyc@gmail.com>
* https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.8.0/contracts/utils/cryptography/EIP712.sol
* https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/master/contracts/utils/cryptography/EIP712Upgradeable.sol
*
* NOTE: Modified version that allows to build a domain separator that relies on a different chain id than the chain this
Copy link
Contributor

@pxrl pxrl Feb 8, 2023

Choose a reason for hiding this comment

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

Suggested change
* https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/master/contracts/utils/cryptography/EIP712Upgradeable.sol
* https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/cb0c1443f9b0aded3b08dfb3088f5ed5c9c72bea/contracts/utils/cryptography/EIP712Upgradeable.sol

Referring to master could be misleading in future, so it probably makes sense to refer to a specific version. I expect that we're just migrating from openzeppelin-contracts v4.8.0 to openzeppelin-contracts-upgradeable v4.8.0 - is that correct? (nb. the linked version is a permalink to https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/release-v4.8/contracts/utils/cryptography/EIP712Upgradeable.sol)

(FWIW I hate that it stretches off to infinity because the URL is so long...)

Copy link
Contributor

@pxrl pxrl left a comment

Choose a reason for hiding this comment

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

Would be nice to be more specific in the comment referring to the OZ EIP712Upgradable contract, but otherwise 👍

@mrice32 mrice32 merged commit c50eeb5 into master Feb 10, 2023
@mrice32 mrice32 deleted the nick/acx-520-add-features-to-spokepool-to-make-future branch February 10, 2023 20:42
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.

5 participants