-
Notifications
You must be signed in to change notification settings - Fork 37
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: rewrite transferOwnership script to use Foundry (#158)
## Description The transferOwnership script has been ported to Foundry, with feature parity, including tests. There was the need for a few workarounds in the tests, mostly because `prank` and `broadcast` aren't compatible with each other and because our proxy is based on Solidity 0.7 and its code isn't directly available in this repo. ## Test Plan New tests. I also deployed a new set of contracts on Sepolia and used the script to change the owner and manager. You can see the two resulting transactions for the [manager](https://sepolia.etherscan.io/tx/0xe4d4499c66f696c671374ffc3f7255dc05fc09b9643af85e4c0e4243919f044a#eventlog) and the [owner](https://sepolia.etherscan.io/tx/0x42a592e04a3a76463b51bff67f38a7195875400e41b7b59737ac8dd41dcb45a7#eventlog). ## Related Issues Closes #102 Closes #103
- Loading branch information
Showing
16 changed files
with
387 additions
and
264 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
// SPDX-License-Identifier: LGPL-3.0-or-later | ||
pragma solidity ^0.8.26; | ||
|
||
import {console} from "forge-std/Script.sol"; | ||
|
||
import {GPv2AllowListAuthentication} from "../src/contracts/GPv2AllowListAuthentication.sol"; | ||
|
||
import {ERC173, ERC165} from "./interfaces/ERC173.sol"; | ||
import {NetworksJson} from "./lib/NetworksJson.sol"; | ||
|
||
contract TransferOwnership is NetworksJson { | ||
// Required input | ||
string private constant INPUT_ENV_NEW_OWNER = "NEW_OWNER"; | ||
string private constant INPUT_ENV_RESET_MANAGER = "RESET_MANAGER"; | ||
// Optional input | ||
string private constant INPUT_ENV_AUTHENTICATOR_PROXY = "AUTHENTICATOR_PROXY"; | ||
|
||
NetworksJson internal networksJson; | ||
|
||
struct ScriptParams { | ||
address newOwner; | ||
bool resetManager; | ||
ERC173 authenticatorProxy; | ||
} | ||
|
||
constructor() { | ||
networksJson = new NetworksJson(); | ||
} | ||
|
||
function run() public virtual { | ||
ScriptParams memory params = paramsFromEnv(); | ||
runWith(params); | ||
} | ||
|
||
function runWith(ScriptParams memory params) public { | ||
console.log(string.concat("Using account ", vm.toString(msg.sender))); | ||
|
||
checkIsProxy(address(params.authenticatorProxy)); | ||
|
||
address owner = params.authenticatorProxy.owner(); | ||
if (owner != msg.sender) { | ||
revert(string.concat("Account does NOT match current owner ", vm.toString(owner))); | ||
} | ||
|
||
GPv2AllowListAuthentication authenticator = GPv2AllowListAuthentication(address(params.authenticatorProxy)); | ||
|
||
// Make sure to reset the manager BEFORE transferring ownership, or else | ||
// we will not be able to do it once we lose permissions. | ||
if (params.resetManager) { | ||
console.log( | ||
string.concat( | ||
"Setting new solver manager from ", | ||
vm.toString(authenticator.manager()), | ||
" to ", | ||
vm.toString(params.newOwner) | ||
) | ||
); | ||
vm.broadcast(msg.sender); | ||
authenticator.setManager(params.newOwner); | ||
console.log("Set new solver manager account."); | ||
} | ||
|
||
console.log( | ||
string.concat( | ||
"Setting new authenticator proxy owner from ", vm.toString(owner), " to ", vm.toString(params.newOwner) | ||
) | ||
); | ||
vm.broadcast(msg.sender); | ||
params.authenticatorProxy.transferOwnership(params.newOwner); | ||
console.log("Set new owner of the authenticator proxy."); | ||
} | ||
|
||
function paramsFromEnv() internal view returns (ScriptParams memory) { | ||
address newOwner = vm.envAddress(INPUT_ENV_NEW_OWNER); | ||
bool resetManager = vm.envBool(INPUT_ENV_RESET_MANAGER); | ||
|
||
address authenticatorProxy; | ||
try vm.envAddress(INPUT_ENV_AUTHENTICATOR_PROXY) returns (address env) { | ||
authenticatorProxy = env; | ||
} catch { | ||
try networksJson.addressOf("GPv2AllowListAuthentication_Proxy") returns (address addr) { | ||
authenticatorProxy = addr; | ||
} catch { | ||
revert( | ||
string.concat( | ||
"Could not find default authenticator address in file ", | ||
networksJson.PATH(), | ||
" for network with chain id ", | ||
vm.toString(block.chainid), | ||
". Export variable ", | ||
INPUT_ENV_AUTHENTICATOR_PROXY, | ||
" to manually specify a non-standard address for the authenticator." | ||
) | ||
); | ||
} | ||
} | ||
|
||
return ScriptParams({ | ||
newOwner: newOwner, | ||
resetManager: resetManager, | ||
authenticatorProxy: ERC173(authenticatorProxy) | ||
}); | ||
} | ||
|
||
function checkIsProxy(address candidate) internal view { | ||
if (address(candidate).code.length == 0) { | ||
revert(string.concat("No code at target authenticator proxy ", vm.toString(address(candidate)), ".")); | ||
} | ||
|
||
bool isERC173; | ||
try ERC165(candidate).supportsInterface(type(ERC173).interfaceId) returns (bool isERC173_) { | ||
isERC173 = isERC173_; | ||
} catch { | ||
isERC173 = false; | ||
} | ||
if (!isERC173) { | ||
revert( | ||
string.concat( | ||
"Not a valid proxy contract: target address ", | ||
vm.toString(address(candidate)), | ||
" does not support the ERC173 interface." | ||
) | ||
); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
// SPDX-License-Identifier: LGPL-3.0 | ||
pragma solidity >=0.7.6 <0.9.0; | ||
|
||
// Copied from: | ||
// <https://eips.ethereum.org/EIPS/eip-173#specification> | ||
|
||
/// @title ERC-173 Contract Ownership Standard | ||
/// Note: the ERC-165 identifier for this interface is 0x7f5828d0 | ||
interface ERC173 { | ||
/// @dev This emits when ownership of a contract changes. | ||
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); | ||
|
||
/// @notice Get the address of the owner | ||
/// @return The address of the owner. | ||
function owner() external view returns (address); | ||
|
||
/// @notice Set the address of the new owner of the contract | ||
/// @dev Set _newOwner to address(0) to renounce any ownership. | ||
/// @param _newOwner The address of the new owner of the contract | ||
function transferOwnership(address _newOwner) external; | ||
} | ||
|
||
interface ERC165 { | ||
/// @notice Query if a contract implements an interface | ||
/// @param interfaceID The interface identifier, as specified in ERC-165 | ||
/// @dev Interface identification is specified in ERC-165. | ||
/// @return `true` if the contract implements `interfaceID` and | ||
/// `interfaceID` is not 0xffffffff, `false` otherwise | ||
function supportsInterface(bytes4 interfaceID) external view returns (bool); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// SPDX-License-Identifier: LGPL-3.0-or-later | ||
pragma solidity ^0.8.26; | ||
|
||
import {Script} from "forge-std/Script.sol"; | ||
|
||
contract NetworksJson is Script { | ||
string public constant PATH = "./networks.json"; | ||
|
||
function addressOf(string memory contractName) public view returns (address) { | ||
return addressByChainId(contractName, block.chainid); | ||
} | ||
|
||
function addressByChainId(string memory contractName, uint256 chainId) public view returns (address) { | ||
string memory networksJson = vm.readFile(PATH); | ||
return | ||
vm.parseJsonAddress(networksJson, string.concat(".", contractName, ".", vm.toString(chainId), ".address")); | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.