Skip to content

Commit c15d99a

Browse files
authored
feat: ownership transfer script can set arbitrary manager (#234)
## Description When the contract is deployed to a new network, we often need to update the manager and the owner to two separate addresses (for example, some administrative and the DAO respectively). These changes make this easier. ## Test Plan Updated tests. Try the updated ## Note I added the `--slow` flag so that the two transactions aren't submitted at the same time. This is to prevent the unlikely scenario where a malicious block builder wouldn't be able to just execute the second transaction by overriding the first from another attempt (which could happen if the first attempt was done with incorrect parameters).
1 parent f3a13f8 commit c15d99a

File tree

3 files changed

+29
-44
lines changed

3 files changed

+29
-44
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,8 @@ The following parameters can be set:
142142

143143
```sh
144144
export ETH_RPC_URL='https://rpc.url.example.com'
145-
export NEW_OWNER=0x1111111111111111111111111111111111111111
146-
export RESET_MANAGER=true # true if the new owner should also become the manager, false otherwise
145+
export NEW_OWNER=0x1111111111111111111111111111111111111111
146+
export NEW_MANAGER=0x2222222222222222222222222222222222222222
147147
```
148148

149149
To test run the script from a specific owner (sender):
@@ -155,7 +155,7 @@ forge script script/TransferOwnership.s.sol:TransferOwnership --rpc-url "$ETH_RP
155155
To actually execute the transaction:
156156

157157
```sh
158-
forge script script/TransferOwnership.s.sol:TransferOwnership --rpc-url "$ETH_RPC_URL" --private-key 0x0000000000000000000000000000000000000000000000000000000000000001 --broadcast
158+
forge script script/TransferOwnership.s.sol:TransferOwnership --rpc-url "$ETH_RPC_URL" --private-key 0x0000000000000000000000000000000000000000000000000000000000000001 --broadcast --slow
159159
```
160160

161161
## Releases

script/TransferOwnership.s.sol

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@ import {NetworksJson} from "./lib/NetworksJson.sol";
1111
contract TransferOwnership is NetworksJson {
1212
// Required input
1313
string private constant INPUT_ENV_NEW_OWNER = "NEW_OWNER";
14-
string private constant INPUT_ENV_RESET_MANAGER = "RESET_MANAGER";
14+
string private constant INPUT_ENV_NEW_MANAGER = "NEW_MANAGER";
1515
// Optional input
1616
string private constant INPUT_ENV_AUTHENTICATOR_PROXY = "AUTHENTICATOR_PROXY";
1717

1818
NetworksJson internal networksJson;
1919

2020
struct ScriptParams {
2121
address newOwner;
22-
bool resetManager;
22+
address newManager;
2323
ERC173 authenticatorProxy;
2424
}
2525

@@ -46,19 +46,17 @@ contract TransferOwnership is NetworksJson {
4646

4747
// Make sure to reset the manager BEFORE transferring ownership, or else
4848
// we will not be able to do it once we lose permissions.
49-
if (params.resetManager) {
50-
console.log(
51-
string.concat(
52-
"Setting new solver manager from ",
53-
vm.toString(authenticator.manager()),
54-
" to ",
55-
vm.toString(params.newOwner)
56-
)
57-
);
58-
vm.broadcast(msg.sender);
59-
authenticator.setManager(params.newOwner);
60-
console.log("Set new solver manager account.");
61-
}
49+
console.log(
50+
string.concat(
51+
"Setting new solver manager from ",
52+
vm.toString(authenticator.manager()),
53+
" to ",
54+
vm.toString(params.newManager)
55+
)
56+
);
57+
vm.broadcast(msg.sender);
58+
authenticator.setManager(params.newManager);
59+
console.log("Set new solver manager account.");
6260

6361
console.log(
6462
string.concat(
@@ -68,11 +66,14 @@ contract TransferOwnership is NetworksJson {
6866
vm.broadcast(msg.sender);
6967
params.authenticatorProxy.transferOwnership(params.newOwner);
7068
console.log("Set new owner of the authenticator proxy.");
69+
70+
console.log(string.concat("Final owner: ", vm.toString(params.authenticatorProxy.owner())));
71+
console.log(string.concat("Final manager: ", vm.toString(authenticator.manager())));
7172
}
7273

7374
function paramsFromEnv() internal view returns (ScriptParams memory) {
7475
address newOwner = vm.envAddress(INPUT_ENV_NEW_OWNER);
75-
bool resetManager = vm.envBool(INPUT_ENV_RESET_MANAGER);
76+
address newManager = vm.envAddress(INPUT_ENV_NEW_MANAGER);
7677

7778
address authenticatorProxy;
7879
try vm.envAddress(INPUT_ENV_AUTHENTICATOR_PROXY) returns (address env) {
@@ -95,11 +96,8 @@ contract TransferOwnership is NetworksJson {
9596
}
9697
}
9798

98-
return ScriptParams({
99-
newOwner: newOwner,
100-
resetManager: resetManager,
101-
authenticatorProxy: ERC173(authenticatorProxy)
102-
});
99+
return
100+
ScriptParams({newOwner: newOwner, newManager: newManager, authenticatorProxy: ERC173(authenticatorProxy)});
103101
}
104102

105103
function checkIsProxy(address candidate) internal view {

test/script/TransferOwnership.t.sol

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -30,40 +30,27 @@ contract TestTransferOwnership is Test {
3030
proxyAsAuthenticator = GPv2AllowListAuthentication(deployed);
3131
}
3232

33-
function test_transfers_proxy_ownership_and_resets_manager() public {
33+
function test_transfers_proxy_ownership_and_updates_manager() public {
3434
address newOwner = makeAddr("TestTransferOwnership: new proxy owner");
35+
address newManager = makeAddr("TestTransferOwnership: new authenticator manager");
3536
assertEq(proxy.owner(), owner);
3637
assertEq(proxyAsAuthenticator.manager(), owner);
3738

3839
TransferOwnership.ScriptParams memory params =
39-
TransferOwnership.ScriptParams({newOwner: newOwner, authenticatorProxy: proxy, resetManager: true});
40+
TransferOwnership.ScriptParams({newOwner: newOwner, authenticatorProxy: proxy, newManager: newManager});
4041

4142
script.runWith(params);
4243

4344
assertEq(proxy.owner(), newOwner, "did not change the owner");
44-
assertEq(proxyAsAuthenticator.manager(), newOwner, "did not change the manager");
45-
}
46-
47-
function test_only_transfers_proxy_ownership() public {
48-
address newOwner = makeAddr("TestTransferOwnership: new proxy owner");
49-
assertEq(proxy.owner(), owner);
50-
assertEq(proxyAsAuthenticator.manager(), owner);
51-
52-
TransferOwnership.ScriptParams memory params =
53-
TransferOwnership.ScriptParams({newOwner: newOwner, authenticatorProxy: proxy, resetManager: false});
54-
55-
script.runWith(params);
56-
57-
assertEq(proxy.owner(), newOwner, "did not change the owner");
58-
assertEq(proxyAsAuthenticator.manager(), owner, "changed the manager");
45+
assertEq(proxyAsAuthenticator.manager(), newManager, "did not change the manager");
5946
}
6047

6148
function test_reverts_if_no_proxy_at_target() public {
6249
address notAProxy = makeAddr("not a proxy");
6350
TransferOwnership.ScriptParams memory params = TransferOwnership.ScriptParams({
6451
newOwner: makeAddr("some owner"),
6552
authenticatorProxy: ERC173(notAProxy),
66-
resetManager: false
53+
newManager: makeAddr("some manager")
6754
});
6855

6956
vm.expectRevert(bytes(string.concat("No code at target authenticator proxy ", vm.toString(notAProxy), ".")));
@@ -75,7 +62,7 @@ contract TestTransferOwnership is Test {
7562
TransferOwnership.ScriptParams memory params = TransferOwnership.ScriptParams({
7663
newOwner: makeAddr("some owner"),
7764
authenticatorProxy: ERC173(noERC173Proxy),
78-
resetManager: false
65+
newManager: makeAddr("some manager")
7966
});
8067
vm.etch(noERC173Proxy, hex"1337");
8168
vm.mockCall(
@@ -99,7 +86,7 @@ contract TestTransferOwnership is Test {
9986
TransferOwnership.ScriptParams memory params = TransferOwnership.ScriptParams({
10087
newOwner: makeAddr("some owner"),
10188
authenticatorProxy: ERC173(revertingProxy),
102-
resetManager: false
89+
newManager: makeAddr("some manager")
10390
});
10491
vm.etch(revertingProxy, hex"1337");
10592
vm.mockCallRevert(

0 commit comments

Comments
 (0)