Commit 7e10a04f authored by Mark Tyneway's avatar Mark Tyneway Committed by GitHub

contracts-bedrock: delete dead `universal` scripts (#9083)

The coinbase fork of these scripts are now used in `superchain-ops`.
These scripts do not need to exist in the monorepo, they should live
in the `superchain-ops` repo. They are unused in the monorepo and there
is no reason to keep these scripts around as they only add to compile
time. They have not been maintained which is evident in the fact that
they still do not follow the style guide for import style. These scripts
were useful for a few upgrades but now that the coinbase fork of these
scripts are more maintained, there is no reason to keep these around.
parent 78d2cdd0
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import { console } from "forge-std/console.sol";
import { Script } from "forge-std/Script.sol";
import { ISemver } from "../../src/universal/ISemver.sol";
/// @title EnhancedScript
/// @notice Enhances forge-std' Script.sol with some additional application-specific functionality.
/// Logs simulation links using Tenderly.
abstract contract EnhancedScript is Script {
/// @notice Helper function used to compute the hash of ISemver's version string to be used in a
/// comparison.
function _versionHash(address _addr) internal view returns (bytes32) {
return keccak256(bytes(ISemver(_addr).version()));
}
/// @notice Log a tenderly simulation link. The TENDERLY_USERNAME and TENDERLY_PROJECT
/// environment variables will be used if they are present. The vm is staticcall'ed
/// because of a compiler issue with the higher level ABI.
function logSimulationLink(address _to, bytes memory _data, address _from) public view {
(, bytes memory projData) = VM_ADDRESS.staticcall(
abi.encodeWithSignature("envOr(string,string)", "TENDERLY_PROJECT", "TENDERLY_PROJECT")
);
string memory proj = abi.decode(projData, (string));
(, bytes memory userData) = VM_ADDRESS.staticcall(
abi.encodeWithSignature("envOr(string,string)", "TENDERLY_USERNAME", "TENDERLY_USERNAME")
);
string memory username = abi.decode(userData, (string));
string memory str = string.concat(
"https://dashboard.tenderly.co/",
username,
"/",
proj,
"/simulator/new?network=",
vm.toString(block.chainid),
"&contractAddress=",
vm.toString(_to),
"&rawFunctionInput=",
vm.toString(_data),
"&from=",
vm.toString(_from)
);
console.log(str);
}
}
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
/// @title GlobalConstants
/// @notice A set of constants.
contract GlobalConstants {
/// @notice Mainnet chain id.
uint256 constant MAINNET = 1;
/// @notice Goerli chain id.
uint256 constant GOERLI = 5;
/// @notice Optimism Goerli chain id.
uint256 constant OP_GOERLI = 420;
}
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import { console } from "forge-std/console.sol";
import { IMulticall3 } from "forge-std/interfaces/IMulticall3.sol";
import { LibSort } from "solady/utils/LibSort.sol";
import { IGnosisSafe, Enum } from "../interfaces/IGnosisSafe.sol";
import { EnhancedScript } from "../universal/EnhancedScript.sol";
import { GlobalConstants } from "../universal/GlobalConstants.sol";
import { ProxyAdmin } from "../../src/universal/ProxyAdmin.sol";
/// @title SafeBuilder
/// @notice Builds SafeTransactions
/// Assumes that a gnosis safe is used as the privileged account and the same
/// gnosis safe is the owner the proxy admin.
/// This could be optimized by checking for the number of approvals up front
/// and not submitting the final approval as `execTransaction` can be called when
/// there are `threshold - 1` approvals.
/// Uses the "approved hashes" method of interacting with the gnosis safe. Allows
/// for the most simple user experience when using automation and no indexer.
/// Run the command without the `--broadcast` flag and it will print a tenderly URL.
abstract contract SafeBuilder is EnhancedScript, GlobalConstants {
////////////////////////////////////////////////////////////////
// State //
////////////////////////////////////////////////////////////////
/// @notice Interface for multicall3.
IMulticall3 internal constant multicall = IMulticall3(MULTICALL3_ADDRESS);
/// @notice An array of approvals, used to generate the execution transaction.
address[] internal approvals;
////////////////////////////////////////////////////////////////
// Virtual Functions //
////////////////////////////////////////////////////////////////
/// @notice Follow up assertions to ensure that the script ran to completion.
function _postCheck() internal view virtual;
/// @notice Creates the calldata
function buildCalldata(address _proxyAdmin) internal view virtual returns (bytes memory);
/// @notice Internal helper function to compute the safe transaction hash.
function computeSafeTransactionHash(address _safe, address _proxyAdmin) public virtual returns (bytes32) {
return _getTransactionHash(_safe, _proxyAdmin);
}
////////////////////////////////////////////////////////////////
// Core Logic //
////////////////////////////////////////////////////////////////
function run() public returns (bool) {
address safe;
address proxyAdmin;
if (block.chainid == OP_GOERLI) {
safe = 0xE534ccA2753aCFbcDBCeB2291F596fc60495257e;
proxyAdmin = 0x4200000000000000000000000000000000000018;
} else if (block.chainid == GOERLI) {
safe = 0xBc1233d0C3e6B5d53Ab455cF65A6623F6dCd7e4f;
proxyAdmin = 0x01d3670863c3F4b24D7b107900f0b75d4BbC6e0d;
}
console.log("ChainID: %s", block.chainid);
return run(safe, proxyAdmin);
}
/// @notice The entrypoint to this script.
function run(address _safe, address _proxyAdmin) public returns (bool) {
require(_safe != address(0), "Safe address undefined");
require(_proxyAdmin != address(0), "ProxyAdminAddress undefined");
console.log("Using Safe: %s", _safe);
console.log("Using ProxyAdmin: %s", _proxyAdmin);
vm.startBroadcast();
bool success = _run(_safe, _proxyAdmin);
if (success) _postCheck();
return success;
}
/// @notice Computes the safe transaction hash for the provided safe and proxy admin.
function _getTransactionHash(address _safe, address _proxyAdmin) internal view returns (bytes32) {
// Ensure that the required contracts exist
require(address(multicall).code.length > 0, "multicall3 not deployed");
require(_safe.code.length > 0, "no code at safe address");
require(_proxyAdmin.code.length > 0, "no code at proxy admin address");
IGnosisSafe safe = IGnosisSafe(payable(_safe));
uint256 nonce = safe.nonce();
bytes memory data = buildCalldata(_proxyAdmin);
// Compute the safe transaction hash
bytes32 hash = safe.getTransactionHash({
to: address(multicall),
value: 0,
data: data,
operation: Enum.Operation.DelegateCall,
safeTxGas: 0,
baseGas: 0,
gasPrice: 0,
gasToken: address(0),
refundReceiver: address(0),
_nonce: nonce
});
return hash;
}
/// @notice The implementation of the upgrade. Split into its own function
/// to allow for testability. This is subject to a race condition if
/// the nonce changes by a different transaction finalizing while not
/// all of the signers have used this script.
function _run(address _safe, address _proxyAdmin) public returns (bool) {
IGnosisSafe safe = IGnosisSafe(payable(_safe));
bytes memory data = buildCalldata(_proxyAdmin);
// Compute the safe transaction hash
bytes32 hash = _getTransactionHash(_safe, _proxyAdmin);
// Send a transaction to approve the hash
safe.approveHash(hash);
logSimulationLink({ _to: address(safe), _from: msg.sender, _data: abi.encodeCall(safe.approveHash, (hash)) });
uint256 threshold = safe.getThreshold();
address[] memory owners = safe.getOwners();
for (uint256 i; i < owners.length; i++) {
address owner = owners[i];
uint256 approved = safe.approvedHashes(owner, hash);
if (approved == 1) {
approvals.push(owner);
}
}
if (approvals.length >= threshold) {
bytes memory signatures = buildSignatures();
bool success = safe.execTransaction({
to: address(multicall),
value: 0,
data: data,
operation: Enum.Operation.DelegateCall,
safeTxGas: 0,
baseGas: 0,
gasPrice: 0,
gasToken: address(0),
refundReceiver: payable(address(0)),
signatures: signatures
});
logSimulationLink({
_to: address(safe),
_from: msg.sender,
_data: abi.encodeCall(
safe.execTransaction,
(
address(multicall),
0,
data,
Enum.Operation.DelegateCall,
0,
0,
0,
address(0),
payable(address(0)),
signatures
)
)
});
require(success, "call not successful");
return true;
} else {
console.log("not enough approvals");
}
// Reset the approvals because they are only used transiently.
assembly {
sstore(approvals.slot, 0)
}
return false;
}
/// @notice Builds the signatures by tightly packing them together.
/// Ensures that they are sorted.
function buildSignatures() internal view returns (bytes memory) {
address[] memory addrs = new address[](approvals.length);
for (uint256 i; i < approvals.length; i++) {
addrs[i] = approvals[i];
}
LibSort.sort(addrs);
bytes memory signatures;
uint8 v = 1;
bytes32 s = bytes32(0);
for (uint256 i; i < addrs.length; i++) {
bytes32 r = bytes32(uint256(uint160(addrs[i])));
signatures = bytes.concat(signatures, abi.encodePacked(r, s, v));
}
return signatures;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment