Skip to content
This repository has been archived by the owner on Apr 27, 2022. It is now read-only.

Upgradable Authenticator #351

Merged
merged 20 commits into from
Feb 3, 2021
Merged

Upgradable Authenticator #351

merged 20 commits into from
Feb 3, 2021

Conversation

bh2smith
Copy link
Contributor

@bh2smith bh2smith commented Jan 18, 2021

Closes #167

This PR introduces minor changes to the AllowListAuthenticator making it upgradable and includes tests verifying upgradability. In particular:

  • removing customInitiallyOwnable as it is no longer used: Not yet sure how this will affect the deployments directory which still includes it.
  • Updating authenticator deployment script to deploy as proxy.
  • rename authenticator owner to manager because of name collision with proxy owner
  • introduce proxy.ts with helper methods to fetch implementation and owner address.
  • Include two unit tests: one verifying that upgrade is possible and the other to ensure preservation of storage.

Note that the unit tests involving Authenticator's non-upgrade related functionality do not use the proxy deployment as specified in the migration scripts, so that manager must be set immediately after deployment.

We had originally planned/hoped to use the hardhat-upgrades plugin and opened the following two PRs to openzeppelin-upgrades, but this plugin turned out to be unnecessary.

Test Plan

Old + new unit and e2e tests.

@bh2smith bh2smith changed the title attempt at upgradable Authenticator with hardhat-upgrades Upgradable Authenticator Jan 18, 2021
@bh2smith bh2smith force-pushed the 167/upgradable_authenticator branch from b15486b to 4fe914f Compare February 1, 2021 21:16
@bh2smith bh2smith marked this pull request as ready for review February 2, 2021 10:01
@bh2smith bh2smith requested a review from a team February 2, 2021 10:01
Copy link
Contributor

@nlordell nlordell left a comment

Choose a reason for hiding this comment

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

Looks very good! Requested changes:

  • Remove @openzeppelin/contracts-upgradeable since we shouldn't be mixing and matching upgradeable contract libraries
  • Add unit tests to make sure setManager cannot be called to "take control" of the contract after deployment.

package.json Outdated Show resolved Hide resolved
src/contracts/GPv2AllowListAuthentication.sol Outdated Show resolved Hide resolved
src/ts/deploy.ts Show resolved Hide resolved
src/ts/proxy.ts Outdated Show resolved Hide resolved
test/GPv2AllowListAuthenticator.test.ts Outdated Show resolved Hide resolved
src/contracts/GPv2AllowListAuthentication.sol Outdated Show resolved Hide resolved
src/contracts/GPv2AllowListAuthentication.sol Outdated Show resolved Hide resolved
test/e2e/upgradeAuthenticator.test.ts Show resolved Hide resolved
Copy link
Contributor

@fedgiac fedgiac left a comment

Choose a reason for hiding this comment

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

Nice work.
How does changing the owner and the manager work? To my understanding:

  1. the owner can probably be changed with a custom proxy function,
  2. the manager cannot be changed once is set, and is the initial owner.

I think 2 can be fixed by hardcoding the manager to be the owner with some assembly reading the right storage slot, then the behavior would be as expected (owner = manager after changing the owner).
In any case, I would test both cases to clarify what is expected of the proxy.

test/e2e/upgradeAuthenticator.test.ts Outdated Show resolved Hide resolved
test/GPv2AllowListAuthenticator.test.ts Show resolved Hide resolved
test/e2e/deployment.test.ts Show resolved Hide resolved
test/e2e/upgradeAuthenticator.test.ts Show resolved Hide resolved
@bh2smith bh2smith requested a review from nlordell February 2, 2021 12:19
Copy link
Contributor

@nlordell nlordell left a comment

Choose a reason for hiding this comment

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

Looks great!

src/ts/proxy.ts Show resolved Hide resolved
test/GPv2AllowListAuthenticator.test.ts Show resolved Hide resolved
Copy link
Contributor

@nlordell nlordell left a comment

Choose a reason for hiding this comment

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

Just one change I noticed last minute

yarn.lock Outdated
@@ -629,72 +629,72 @@
path-browserify "^1.0.0"
url "^0.11.0"

"@sentry/[email protected]":
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we revert the yarn.lock changes? I don't think they should be included in this PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This wasn't intentional.. I will revert them but I am just using whatever yarn install gives me.

Copy link
Contributor

@nlordell nlordell Feb 2, 2021

Choose a reason for hiding this comment

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

This is probably because the package.json changed and then the change was reverted. If you revert the lock file, then yarn install this should be the same.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I am not able to make this happen without forcing the lock file from main. Could it be my node version that is doing this?

Copy link
Contributor

Choose a reason for hiding this comment

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

Super weird....

Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, maybe its something specific to your setup. If I run yarn install on your branch, it respects the lock file and does not overwrite it:

$ git clone -b 167/upgradable_authenticator [email protected]:gnosis/gp-v2-contracts.git TEMP
...
$ cd TEMP; yarn
...
$ git status
On branch 167/upgradable_authenticator
Your branch is up to date with 'origin/167/upgradable_authenticator'.

nothing to commit, working tree clean

@frangio
Copy link

frangio commented Feb 2, 2021

As I was discussing with @bh2smith over Slack, I think it's necessary to have an automated mechanism to check that the storage layout of future upgrades remains compatible, to avoid accidentally corrupting the storage of live contracts. This check is built into the OpenZeppelin Upgrades plugin but I understand you weren't able to use it because you needed deterministic deployments.

Even if you don't use it for production deployment, my recommendation would be to have a set of tests that use our plugin to deploy and upgrade from one version to the next. Having this as part of your test suite should provide some assurance that future upgrades are correct.

One issue we have currently is that you need to skip one of the checks that we do (disallowing delegatecall), but this is something we can quickly add if you need it.

Copy link
Contributor

@fedgiac fedgiac left a comment

Choose a reason for hiding this comment

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

A point worth discussing before merging: do we really want that the manager is set once for all and can never change until we change the authenticator contract code with a function that does so? The owner of the proxy may change, but not the manager.

Otherwise, the PR and the feature look very nice to me!

To frangio: I agree that with the current changes we can't update the contract without testing that each "base" entry in storage is preserved. We should discuss this in the team, but I believe that upgrades will be sufficiently few and the used storage sufficiently limited that we can resort to manual testing for each update. Depending on the complexity, we may as well do as you say and use openzeppelin-upgrades to test the upgrade process.

src/ts/proxy.ts Outdated Show resolved Hide resolved
src/ts/proxy.ts Show resolved Hide resolved
@bh2smith
Copy link
Contributor Author

bh2smith commented Feb 2, 2021

@fedgiac note that we can always introduce a function in the version 2 contract that allows us to update the manager. Is this good enough for our purposes or should we make another onlyManager method right now that allows the manager to reassign someone else?

@fedgiac
Copy link
Contributor

fedgiac commented Feb 3, 2021

I'd make it so that the proxy owner can change the manager at will. Upgrading the proxy is a relatively expensive operations (as pointed out by frangio), and changing the manager is something that we might need to do from the start, for example because we want to assign this power to some other staking contract, or a DAO. Note that we use the same owner address on mainnet and Rinkeby for now: the first transaction I expect after releasing is changing the owner of the mainnet contract to some other address. Then also the manager should be changing.

}

function updateManager(address newManager) external onlyProxyAdmin {
manager = newManager;
Copy link
Contributor

Choose a reason for hiding this comment

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

If the manager gets set to address(0), then anyone can call initializeManager and take ownership of the contract now.

Maybe instead of adding the ability of changing the manager in this PR, we do it as a separate PR. What do you think @fedgiac ?

Copy link
Contributor

Choose a reason for hiding this comment

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

My understanding is that the current changes on the owner are work in progress.
I don't mind if it's done here or done in another PR, but I think that making provision for changing the manager is necessary before releasing.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think that making provision for changing the manager is necessary before releasing.

Selbstverständlich

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Reverted the onlyProxyAdmin

Copy link
Contributor

@nlordell nlordell left a comment

Choose a reason for hiding this comment

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

I think there are some security wholes with the additional changes. I propose merging the PR as it was before and adding the ability to change the manager and proxy owner as a separate PR.

Comment on lines 24 to 27
// Slot taken from https://eips.ethereum.org/EIPS/eip-1967#specification
// obtained as bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)
bytes32 slot =
0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
Copy link
Contributor

Choose a reason for hiding this comment

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

This should probably be a constant.

@fedgiac
Copy link
Contributor

fedgiac commented Feb 3, 2021

For the records, I'm ok with merging the PR as it was before the recent changes and discuss the work on the settable manager in another PR.

@bh2smith bh2smith added the merge when green Merge when green! label Feb 3, 2021
@mergify mergify bot merged commit 9b5796c into main Feb 3, 2021
@mergify mergify bot deleted the 167/upgradable_authenticator branch February 3, 2021 14:30
@fleupold
Copy link
Contributor

fleupold commented Feb 3, 2021

If we allow to change the manager later, isn't that equivalent to inheriting open zeppelin's Ownable?

@nlordell
Copy link
Contributor

nlordell commented Feb 3, 2021

isn't that equivalent to inheriting open zeppelin's Ownable?

Yes, I think we just need to inherit both Initializable and Ownable and then we get everything out of the box.

@fedgiac fedgiac mentioned this pull request Feb 4, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
merge when green Merge when green!
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Make Authentication Contract Upgradable
5 participants