Commit 082d075d authored by Mark Tyneway's avatar Mark Tyneway Committed by GitHub

contracts-bedrock: delete unused `sync()` method (#9100)

* contracts-bedrock: delete unused `sync()` method

We no longer maintain the hardhat deploy artifacts found
in the `deployments` directory of `contracts-bedrock`. Keeping
them up to date requires a bunch of brittle solidity code that
isn't nice to maintain. This PR simply removes the `sync()` method
as it is no longer used in the devnet. We migrated towards using
the `superchain-registry` style JSON files to generate the genesis
files. A follow up PR will remove the `deployments` artifacts
and the source of truth for the contract addresses will be
`superchain-registry`.

By removing this code, we can incrementally refactor the deploy
scripts to be much more simple to read and maintain. It removes
code that is already dead and unused in hot paths which will speed
up the compilation time for the smart contracts.

* devnet: remove call to `sync()`

The `sync()` command is now deprecated

* devnet: replace legacy flag usage

Use `addresses.json` over hh deploy artifacts
parent 65e01316
...@@ -149,12 +149,6 @@ def deploy_contracts(paths): ...@@ -149,12 +149,6 @@ def deploy_contracts(paths):
shutil.copy(paths.l1_deployments_path, paths.addresses_json_path) shutil.copy(paths.l1_deployments_path, paths.addresses_json_path)
log.info('Syncing contracts.')
run_command([
'forge', 'script', fqn, '--sig', 'sync()',
'--rpc-url', 'http://127.0.0.1:8545'
], env={}, cwd=paths.contracts_bedrock_dir)
def init_devnet_l1_deploy_config(paths, update_timestamp=False): def init_devnet_l1_deploy_config(paths, update_timestamp=False):
deploy_config = read_json(paths.devnet_config_template_path) deploy_config = read_json(paths.devnet_config_template_path)
if update_timestamp: if update_timestamp:
...@@ -223,7 +217,7 @@ def devnet_deploy(paths): ...@@ -223,7 +217,7 @@ def devnet_deploy(paths):
'go', 'run', 'cmd/main.go', 'genesis', 'l2', 'go', 'run', 'cmd/main.go', 'genesis', 'l2',
'--l1-rpc', 'http://localhost:8545', '--l1-rpc', 'http://localhost:8545',
'--deploy-config', paths.devnet_config_path, '--deploy-config', paths.devnet_config_path,
'--deployment-dir', paths.deployment_dir, '--l1-deployments', paths.addresses_json_path,
'--outfile.l2', paths.genesis_l2_path, '--outfile.l2', paths.genesis_l2_path,
'--outfile.rollup', paths.rollup_config_path '--outfile.rollup', paths.rollup_config_path
], cwd=paths.op_node_dir) ], cwd=paths.op_node_dir)
......
...@@ -10,23 +10,6 @@ import { IAddressManager } from "scripts/interfaces/IAddressManager.sol"; ...@@ -10,23 +10,6 @@ import { IAddressManager } from "scripts/interfaces/IAddressManager.sol";
import { LibString } from "solady/utils/LibString.sol"; import { LibString } from "solady/utils/LibString.sol";
import { Artifacts, Deployment } from "scripts/Artifacts.s.sol"; import { Artifacts, Deployment } from "scripts/Artifacts.s.sol";
/// @notice A `hardhat-deploy` style artifact
struct Artifact {
string abi;
address addr;
string[] args;
bytes bytecode;
bytes deployedBytecode;
string devdoc;
string metadata;
uint256 numDeployments;
string receipt;
bytes32 solcInputHash;
string storageLayout;
bytes32 transactionHash;
string userdoc;
}
/// @notice Contains information about a storage slot. Mirrors the layout of the storage /// @notice Contains information about a storage slot. Mirrors the layout of the storage
/// slot object in Forge artifacts so that we can deserialize JSON into this struct. /// slot object in Forge artifacts so that we can deserialize JSON into this struct.
struct StorageSlot { struct StorageSlot {
...@@ -42,8 +25,7 @@ struct StorageSlot { ...@@ -42,8 +25,7 @@ struct StorageSlot {
/// @author tynes /// @author tynes
/// @notice A contract that can make deploying and interacting with deployments easy. /// @notice A contract that can make deploying and interacting with deployments easy.
/// When a contract is deployed, call the `save` function to write its name and /// When a contract is deployed, call the `save` function to write its name and
/// contract address to disk. Then the `sync` function can be called to generate /// contract address to disk. Inspired by `forge-deploy`.
/// hardhat deploy style artifacts. Forked from `forge-deploy`.
abstract contract Deployer is Script, Artifacts { abstract contract Deployer is Script, Artifacts {
/// @notice Path to the deploy artifact generated by foundry /// @notice Path to the deploy artifact generated by foundry
string internal deployPath; string internal deployPath;
...@@ -72,142 +54,60 @@ abstract contract Deployer is Script, Artifacts { ...@@ -72,142 +54,60 @@ abstract contract Deployer is Script, Artifacts {
); );
} }
/// @notice Call this function to sync the deployment artifacts such that
/// hardhat deploy style artifacts are created.
function sync() public {
Deployment[] memory deployments = _getTempDeployments();
console.log("Syncing %s deployments", deployments.length);
console.log("Using deployment artifact %s", deployPath);
for (uint256 i; i < deployments.length; i++) {
address addr = deployments[i].addr;
string memory deploymentName = deployments[i].name;
string memory deployTx = _getDeployTransactionByContractAddress(addr);
if (bytes(deployTx).length == 0) {
console.log("Deploy Tx not found for %s skipping deployment artifact generation", deploymentName);
continue;
}
string memory contractName = _getContractNameFromDeployTransaction(deployTx);
console.log("Syncing deployment %s: contract %s", deploymentName, contractName);
string[] memory args = getDeployTransactionConstructorArguments(deployTx);
bytes memory code = _getCode(contractName);
bytes memory deployedCode = _getDeployedCode(contractName);
string memory receipt = _getDeployReceiptByContractAddress(addr);
string memory artifactPath = string.concat(deploymentsDir, "/", deploymentName, ".json");
uint256 numDeployments = 0;
try vm.readFile(artifactPath) returns (string memory res) {
numDeployments = stdJson.readUint(string(res), "$.numDeployments");
vm.removeFile(artifactPath);
} catch { }
numDeployments++;
Artifact memory artifact = Artifact({
abi: getAbi(contractName),
addr: addr,
args: args,
bytecode: code,
deployedBytecode: deployedCode,
devdoc: getDevDoc(contractName),
metadata: getMetadata(contractName),
numDeployments: numDeployments,
receipt: receipt,
solcInputHash: bytes32(0),
storageLayout: getStorageLayout(contractName),
transactionHash: stdJson.readBytes32(deployTx, "$.hash"),
userdoc: getUserDoc(contractName)
});
string memory json = _serializeArtifact(artifact);
vm.writeJson({ json: json, path: artifactPath });
}
console.log("Synced temp deploy files, deleting %s", tempDeploymentsPath);
vm.removeFile(tempDeploymentsPath);
}
/// @notice Returns the name of the deployment script. Children contracts /// @notice Returns the name of the deployment script. Children contracts
/// must implement this to ensure that the deploy artifacts can be found. /// must implement this to ensure that the deploy artifacts can be found.
/// This should be the same as the name of the script and is used as the file /// This should be the same as the name of the script and is used as the file
/// name inside of the `broadcast` directory when looking up deployment artifacts. /// name inside of the `broadcast` directory when looking up deployment artifacts.
function name() public pure virtual returns (string memory); function name() public pure virtual returns (string memory);
/// @notice Returns the json of the deployment transaction given a contract address. /// @notice Removes the semantic versioning from a contract name. The semver will exist if the contract is compiled
function _getDeployTransactionByContractAddress(address _addr) internal returns (string memory) { /// more than once with different versions of the compiler.
function _stripSemver(string memory _name) internal returns (string memory) {
string[] memory cmd = new string[](3); string[] memory cmd = new string[](3);
cmd[0] = Executables.bash; cmd[0] = Executables.bash;
cmd[1] = "-c"; cmd[1] = "-c";
cmd[2] = string.concat( cmd[2] = string.concat(
Executables.jq, Executables.echo, " ", _name, " | ", Executables.sed, " -E 's/[.][0-9]+\\.[0-9]+\\.[0-9]+//g'"
" -r '.transactions[] | select(.contractAddress == ",
'"',
vm.toString(_addr),
'"',
') | select(.transactionType == "CREATE"',
' or .transactionType == "CREATE2"',
")' < ",
deployPath
); );
bytes memory res = vm.ffi(cmd); bytes memory res = vm.ffi(cmd);
return string(res); return string(res);
} }
/// @notice Returns the contract name from a deploy transaction. /// @notice Builds the fully qualified name of a contract. Assumes that the
function _getContractNameFromDeployTransaction(string memory _deployTx) internal pure returns (string memory) { /// file name is the same as the contract name but strips semver for the file name.
return stdJson.readString(_deployTx, ".contractName"); function _getFullyQualifiedName(string memory _name) internal returns (string memory) {
} string memory sanitized = _stripSemver(_name);
return string.concat(sanitized, ".sol:", _name);
/// @notice Wrapper for vm.getCode that handles semver in the name.
function _getCode(string memory _name) internal returns (bytes memory) {
string memory fqn = _getFullyQualifiedName(_name);
bytes memory code = vm.getCode(fqn);
return code;
}
/// @notice Wrapper for vm.getDeployedCode that handles semver in the name.
function _getDeployedCode(string memory _name) internal returns (bytes memory) {
string memory fqn = _getFullyQualifiedName(_name);
bytes memory code = vm.getDeployedCode(fqn);
return code;
} }
/// @notice Removes the semantic versioning from a contract name. The semver will exist if the contract is compiled /// @notice Returns the storage layout for a deployed contract.
/// more than once with different versions of the compiler. function getStorageLayout(string memory _name) public returns (string memory layout_) {
function _stripSemver(string memory _name) internal returns (string memory) {
string[] memory cmd = new string[](3); string[] memory cmd = new string[](3);
cmd[0] = Executables.bash; cmd[0] = Executables.bash;
cmd[1] = "-c"; cmd[1] = "-c";
cmd[2] = string.concat( cmd[2] = string.concat(Executables.jq, " -r '.storageLayout' < ", _getForgeArtifactPath(_name));
Executables.echo, " ", _name, " | ", Executables.sed, " -E 's/[.][0-9]+\\.[0-9]+\\.[0-9]+//g'"
);
bytes memory res = vm.ffi(cmd); bytes memory res = vm.ffi(cmd);
return string(res); layout_ = string(res);
} }
/// @notice Returns the constructor arguent of a deployment transaction given a transaction json. /// @notice Returns the abi from a the forge artifact
function getDeployTransactionConstructorArguments(string memory _transaction) internal returns (string[] memory) { function getAbi(string memory _name) public returns (string memory abi_) {
string[] memory cmd = new string[](3); string[] memory cmd = new string[](3);
cmd[0] = Executables.bash; cmd[0] = Executables.bash;
cmd[1] = "-c"; cmd[1] = "-c";
cmd[2] = string.concat(Executables.jq, " -r '.arguments' <<< '", _transaction, "'"); cmd[2] = string.concat(Executables.jq, " -r '.abi' < ", _getForgeArtifactPath(_name));
bytes memory res = vm.ffi(cmd); bytes memory res = vm.ffi(cmd);
abi_ = string(res);
string[] memory args = new string[](0);
if (keccak256(bytes("null")) != keccak256(res)) {
args = stdJson.readStringArray(string(res), "");
}
return args;
} }
/// @notice Builds the fully qualified name of a contract. Assumes that the /// @notice Returns the methodIdentifiers from the forge artifact
/// file name is the same as the contract name but strips semver for the file name. function getMethodIdentifiers(string memory _name) public returns (string[] memory ids_) {
function _getFullyQualifiedName(string memory _name) internal returns (string memory) { string[] memory cmd = new string[](3);
string memory sanitized = _stripSemver(_name); cmd[0] = Executables.bash;
return string.concat(sanitized, ".sol:", _name); cmd[1] = "-c";
cmd[2] = string.concat(Executables.jq, " '.methodIdentifiers | keys' < ", _getForgeArtifactPath(_name));
bytes memory res = vm.ffi(cmd);
ids_ = stdJson.readStringArray(string(res), "");
} }
function _getForgeArtifactDirectory(string memory _name) internal returns (string memory dir_) { function _getForgeArtifactDirectory(string memory _name) internal returns (string memory dir_) {
...@@ -249,85 +149,6 @@ abstract contract Deployer is Script, Artifacts { ...@@ -249,85 +149,6 @@ abstract contract Deployer is Script, Artifacts {
return vm.readFile(forgeArtifactPath); return vm.readFile(forgeArtifactPath);
} }
/// @notice Returns the receipt of a deployment transaction.
function _getDeployReceiptByContractAddress(address _addr) internal returns (string memory receipt_) {
string[] memory cmd = new string[](3);
cmd[0] = Executables.bash;
cmd[1] = "-c";
cmd[2] = string.concat(
Executables.jq,
" -r '.receipts[] | select(.contractAddress == ",
'"',
vm.toString(_addr),
'"',
")' < ",
deployPath
);
bytes memory res = vm.ffi(cmd);
string memory receipt = string(res);
receipt_ = receipt;
}
/// @notice Returns the devdoc for a deployed contract.
function getDevDoc(string memory _name) internal returns (string memory doc_) {
string[] memory cmd = new string[](3);
cmd[0] = Executables.bash;
cmd[1] = "-c";
cmd[2] = string.concat(Executables.jq, " -r '.devdoc' < ", _getForgeArtifactPath(_name));
bytes memory res = vm.ffi(cmd);
doc_ = string(res);
}
/// @notice Returns the storage layout for a deployed contract.
function getStorageLayout(string memory _name) internal returns (string memory layout_) {
string[] memory cmd = new string[](3);
cmd[0] = Executables.bash;
cmd[1] = "-c";
cmd[2] = string.concat(Executables.jq, " -r '.storageLayout' < ", _getForgeArtifactPath(_name));
bytes memory res = vm.ffi(cmd);
layout_ = string(res);
}
/// @notice Returns the abi for a deployed contract.
function getAbi(string memory _name) public returns (string memory abi_) {
string[] memory cmd = new string[](3);
cmd[0] = Executables.bash;
cmd[1] = "-c";
cmd[2] = string.concat(Executables.jq, " -r '.abi' < ", _getForgeArtifactPath(_name));
bytes memory res = vm.ffi(cmd);
abi_ = string(res);
}
/// @notice
function getMethodIdentifiers(string memory _name) public returns (string[] memory ids_) {
string[] memory cmd = new string[](3);
cmd[0] = Executables.bash;
cmd[1] = "-c";
cmd[2] = string.concat(Executables.jq, " '.methodIdentifiers | keys' < ", _getForgeArtifactPath(_name));
bytes memory res = vm.ffi(cmd);
ids_ = stdJson.readStringArray(string(res), "");
}
/// @notice Returns the userdoc for a deployed contract.
function getUserDoc(string memory _name) internal returns (string memory doc_) {
string[] memory cmd = new string[](3);
cmd[0] = Executables.bash;
cmd[1] = "-c";
cmd[2] = string.concat(Executables.jq, " -r '.userdoc' < ", _getForgeArtifactPath(_name));
bytes memory res = vm.ffi(cmd);
doc_ = string(res);
}
/// @notice
function getMetadata(string memory _name) internal returns (string memory metadata_) {
string[] memory cmd = new string[](3);
cmd[0] = Executables.bash;
cmd[1] = "-c";
cmd[2] = string.concat(Executables.jq, " '.metadata | tostring' < ", _getForgeArtifactPath(_name));
bytes memory res = vm.ffi(cmd);
metadata_ = string(res);
}
/// @dev Pulls the `_initialized` storage slot information from the Forge artifacts for a given contract. /// @dev Pulls the `_initialized` storage slot information from the Forge artifacts for a given contract.
function getInitializedSlot(string memory _contractName) internal returns (StorageSlot memory slot_) { function getInitializedSlot(string memory _contractName) internal returns (StorageSlot memory slot_) {
string memory storageLayout = getStorageLayout(_contractName); string memory storageLayout = getStorageLayout(_contractName);
...@@ -368,25 +189,4 @@ abstract contract Deployer is Script, Artifacts { ...@@ -368,25 +189,4 @@ abstract contract Deployer is Script, Artifacts {
bytes32 slotVal = vm.load(contractAddress, bytes32(vm.parseUint(slot.slot))); bytes32 slotVal = vm.load(contractAddress, bytes32(vm.parseUint(slot.slot)));
initialized_ = uint8((uint256(slotVal) >> (slot.offset * 8)) & 0xFF); initialized_ = uint8((uint256(slotVal) >> (slot.offset * 8)) & 0xFF);
} }
/// @notice Turns an Artifact into a json serialized string
/// @param _artifact The artifact to serialize
/// @return The json serialized string
function _serializeArtifact(Artifact memory _artifact) internal returns (string memory) {
string memory json = "";
json = stdJson.serialize("", "address", _artifact.addr);
json = stdJson.serialize("", "abi", _artifact.abi);
json = stdJson.serialize("", "args", _artifact.args);
json = stdJson.serialize("", "bytecode", _artifact.bytecode);
json = stdJson.serialize("", "deployedBytecode", _artifact.deployedBytecode);
json = stdJson.serialize("", "devdoc", _artifact.devdoc);
json = stdJson.serialize("", "metadata", _artifact.metadata);
json = stdJson.serialize("", "numDeployments", _artifact.numDeployments);
json = stdJson.serialize("", "receipt", _artifact.receipt);
json = stdJson.serialize("", "solcInputHash", _artifact.solcInputHash);
json = stdJson.serialize("", "storageLayout", _artifact.storageLayout);
json = stdJson.serialize("", "transactionHash", _artifact.transactionHash);
json = stdJson.serialize("", "userdoc", _artifact.userdoc);
return json;
}
} }
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