diff --git a/.env b/.env index 07dd85a9c..0f3b7cf39 100644 --- a/.env +++ b/.env @@ -122,22 +122,4 @@ ESPRESSO_BENCH_END_BLOCK=150 ESPRESSO_SEQUENCER_FETCH_RATE_LIMIT=25 # Query service stress test -ESPRESSO_NASTY_CLIENT_PORT=24011 - -# Openzeppelin Defender Deployment Profile -DEFENDER_KEY= -DEFENDER_SECRET= -FEE_CONTRACT_SALT=17 -LIGHT_CLIENT_SALT=12 -FEE_CONTRACT_UPGRADE_NAME="FeeContract.sol" -LIGHT_CLIENT_UPGRADE_NAME="LightClientV2.sol" -FOUNDRY_OUT=contracts/out - -# The Ethereum address of the safe multisig wallet used to deploy and operate the contracts. -SAFE_MULTISIG_ADDRESS= -# The Ethereum private key of the wallet used for the proposing multisig transactions. -SAFE_ORCHESTRATOR_PRIVATE_KEY= - -# Light Client -LIGHT_CLIENT_PROXY_CONTRACT_ADDRESS= -APPROVED_PROVER_ADDRESS= +ESPRESSO_NASTY_CLIENT_PORT=24011 \ No newline at end of file diff --git a/.env.contracts.example b/.env.contracts.example new file mode 100644 index 000000000..49cded36c --- /dev/null +++ b/.env.contracts.example @@ -0,0 +1,42 @@ +# Since foundry and openzeppelin defender expect secrets to be in the .env file, remember to source this file before your forge script command +## e.g. `source .env.contracts && force script $YOUR_SCRIPT_NAME` + +# Openzeppelin Defender Deployment Profile +export DEFENDER_KEY= +export DEFENDER_SECRET= +export FEE_CONTRACT_SALT= +export LIGHT_CLIENT_SALT= +export FEE_CONTRACT_UPGRADE_NAME= #e.g "FeeContract.sol" +export LIGHT_CLIENT_UPGRADE_NAME= +export FOUNDRY_OUT=contracts/out + +# The Ethereum address of the safe multisig wallet used to deploy and operate the contracts. +export SAFE_MULTISIG_ADDRESS= +# The Ethereum private key of the wallet used for the proposing multisig transactions. +export SAFE_ORCHESTRATOR_PRIVATE_KEY= + +# Light Client +export LIGHT_CLIENT_PROXY_CONTRACT_ADDRESS= +export APPROVED_PROVER_ADDRESS= + +# Plonk Verification Library Deployment with Defender +export PLONK_VERIFIER_SALT=# Openzeppelin Defender Deployment Profile +export DEFENDER_KEY= +export DEFENDER_SECRET= +export FEE_CONTRACT_SALT= +export LIGHT_CLIENT_SALT= +export FEE_CONTRACT_UPGRADE_NAME= #e.g "FeeContract.sol" +export LIGHT_CLIENT_UPGRADE_NAME= +export FOUNDRY_OUT=contracts/out + +# The Ethereum address of the safe multisig wallet used to deploy and operate the contracts. +export SAFE_MULTISIG_ADDRESS= +# The Ethereum private key of the wallet used for the proposing multisig transactions. +export SAFE_ORCHESTRATOR_PRIVATE_KEY= + +# Light Client +export LIGHT_CLIENT_PROXY_CONTRACT_ADDRESS= +export APPROVED_PROVER_ADDRESS= + +# Plonk Verification Library Deployment with Defender +export PLONK_VERIFIER_SALT= diff --git a/.gitignore b/.gitignore index 1d100bae8..c10964137 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,6 @@ wake-coverage.cov # generated by failing serialization tests data/*-actual.json data/*-actual.bin + +# Secret environment variables +.env.contracts \ No newline at end of file diff --git a/contracts/script/FeeContractWithDefender.s.sol b/contracts/script/FeeContractWithDefender.s.sol index 4ad708658..c20798b05 100644 --- a/contracts/script/FeeContractWithDefender.s.sol +++ b/contracts/script/FeeContractWithDefender.s.sol @@ -39,7 +39,7 @@ contract FeeContractDefenderDeployScript is Script { Upgrades.deployUUPSProxy(contractName, abi.encodeCall(FC.initialize, (multisig)), opts); //generate the deployment file path, output and write to the file - (string memory filePath, string memory fileData) = utils.generateDeploymentOutput( + (string memory filePath, string memory fileData) = utils.generateProxyDeploymentOutput( contractName, contractSalt, proxyAddress, multisig, approvalProcessId, viaType ); utils.writeJson(filePath, fileData); diff --git a/contracts/script/LightClientWithDefender.s.sol b/contracts/script/LightClientWithDefender.s.sol index d11d9f72c..79abcc2cf 100644 --- a/contracts/script/LightClientWithDefender.s.sol +++ b/contracts/script/LightClientWithDefender.s.sol @@ -55,7 +55,7 @@ contract LightClientDefenderDeployScript is Script { ); //generate the file path, file output and write to the file - (string memory filePath, string memory fileData) = utils.generateDeploymentOutput( + (string memory filePath, string memory fileData) = utils.generateProxyDeploymentOutput( contractName, contractSalt, proxy, diff --git a/contracts/script/PlonkVerifierWithDefender.s.sol b/contracts/script/PlonkVerifierWithDefender.s.sol new file mode 100644 index 000000000..5a07d0e80 --- /dev/null +++ b/contracts/script/PlonkVerifierWithDefender.s.sol @@ -0,0 +1,54 @@ +pragma solidity ^0.8.20; + +import { Script } from "forge-std/Script.sol"; + +import { Defender, ApprovalProcessResponse } from "openzeppelin-foundry-upgrades/Defender.sol"; +import { Upgrades, Options } from "openzeppelin-foundry-upgrades/Upgrades.sol"; +import { PlonkVerifier as PV } from "../src/libraries/PlonkVerifier.sol"; +import { UtilsScript } from "./Utils.s.sol"; + +contract PlonkVerifierDefenderDeployScript is Script { + string public contractName = "PlonkVerifier.sol"; + UtilsScript public utils = new UtilsScript(); + uint256 public contractSalt = uint256(vm.envInt("PLONK_VERIFIER_SALT")); + + function run() public returns (address contractAddress, address multisig) { + ApprovalProcessResponse memory upgradeApprovalProcess = Defender.getDeployApprovalProcess(); + multisig = upgradeApprovalProcess.via; + + if (upgradeApprovalProcess.via == address(0)) { + revert( + string.concat( + "Deploy approval process with id ", + upgradeApprovalProcess.approvalProcessId, + " has no assigned address" + ) + ); + } + + Options memory opts; + opts.defender.useDefenderDeploy = true; + opts.defender.skipLicenseType = true; + opts.defender.salt = bytes32(abi.encodePacked(contractSalt)); + + contractAddress = Defender.deployContract(contractName, opts.defender); + + //generate the file path, file output and write to the file + (string memory filePath, string memory fileData) = utils.generateDeploymentOutput( + contractName, + contractSalt, + contractAddress, + multisig, + upgradeApprovalProcess.approvalProcessId, + upgradeApprovalProcess.viaType + ); + utils.writeJson(filePath, fileData); + + //generate the salt history file path, output and write to the file + (string memory saltFilePath, string memory saltFileData) = + utils.generateSaltOutput(contractName, contractSalt); + utils.writeJson(saltFilePath, saltFileData); + + return (contractAddress, multisig); + } +} diff --git a/contracts/script/README.md b/contracts/script/README.md index 1d5707bdf..e74cddebc 100644 --- a/contracts/script/README.md +++ b/contracts/script/README.md @@ -20,7 +20,7 @@ file is used. 1. Choose a network 1. Select the approval process created in Step 2 1. Be sure to save `DEFENDER_SECRET` ("Team Secret key") and `DEFENDER_KEY` ("Team API Key"), that is shown at the - end of this step, into the `.env` file. The keys won't be available later at a later point. + end of this step, into the `.env.contracts` file. The keys won't be available later at a later point. 4. In the home folder of this repo, you're in a nix shell: Enter `nix-shell` in the terminal 5. If the contracts have never been compiled run, `forge build` @@ -33,7 +33,18 @@ Steps: 1. Run the Deployment command. ```bash - forge clean && FeeContractWithDefender.s.sol:FeeContractDefenderDeployScript --ffi --rpc-url https://ethereum-sepolia.publicnode.com --build-info true + source .env.contracts && \ + forge clean && \ + FeeContractWithDefender.s.sol:FeeContractDefenderDeployScript \ + --ffi \ + --rpc-url https://ethereum-sepolia.publicnode.com \ + --build-info true + source .env.contracts && \ + forge clean && \ + FeeContractWithDefender.s.sol:FeeContractDefenderDeployScript \ + --ffi \ + --rpc-url https://ethereum-sepolia.publicnode.com \ + --build-info true ``` 1. Go to the [deploy](https://defender.openzeppelin.com/v2/#/deploy) tab OpenZeppelin Defender's UI and click on the @@ -77,15 +88,37 @@ multisig: address 0xc56fA6505d10bF322e01327e22479DE78C3Bf1cE ### Deploying the Light Client Contract -Read Deploying the Fee Contract for a more detailed version of this. +Read Deploying the Fee Contract for a more detailed version of this. Since the LightClient contract uses the +PlonkVerifier library, the PlonkVerifier library has to be deployed and then referenced at deployment time. Thus ensure +you've deployed the PlonkVerifier ([see steps below](#deploy-the-plonk-verifier-library-with-defender)) and set the +`$PLONK_VERIFIER_ADDRESS` variable in the command below. Each time modifications are made to the Plonk Verifier, +contracts that depend on it such as the Light Client contract have to be upgraded and should use the new PlonkVerifier +contract address as part of the deployment. Read Deploying the Fee Contract for a more detailed version of this. Since +the LightClient contract uses the PlonkVerifier library, the PlonkVerifier library has to be deployed and then +referenced at deployment time. Thus ensure you've deployed the PlonkVerifier +([see steps below](#deploy-the-plonk-verifier-library-with-defender)) and set the `$PLONK_VERIFIER_ADDRESS` variable in +the command below. Each time modifications are made to the Plonk Verifier, contracts that depend on it such as the Light +Client contract have to be upgraded and should use the new PlonkVerifier contract address as part of the deployment. 1. Initiate the Deployment with OpenZeppelin Defender ```bash -forge clean && forge script contracts/script/LightClientWithDefender.s.sol:LightClientDefenderDeployScript --ffi --rpc-url https://ethereum-sepolia.publicnode.com --build-info true +source .env.contracts && \ +forge clean && \ +forge script contracts/script/LightClientWithDefender.s.sol:LightClientDefenderDeployScript \ +--ffi --rpc-url https://ethereum-sepolia.publicnode.com \ +--build-info true \ +--libraries contracts/src/libraries/PlonkVerifier.sol:PlonkVerifier:$PLONK_VERIFIER_ADDRESS ``` -Follow the same steps as for the deployment of the fee contract above. +source .env.contracts && \ +forge clean && \ +forge script contracts/script/LightClientWithDefender.s.sol:LightClientDefenderDeployScript \ +--ffi --rpc-url https://ethereum-sepolia.publicnode.com \ +--build-info true \ +--libraries contracts/src/libraries/PlonkVerifier.sol:PlonkVerifier:$PLONK_VERIFIER_ADDRESS + +```` 2. Verify the Contract @@ -95,7 +128,7 @@ forge verify-contract --chain-id 11155111 \ --compiler-version $SOLC_VERSION \ $LIGHT_CLIENT_CONTRACT_ADDRESS \ contracts/src/LightClient.sol:LightClient -``` +```` 3. Inform Etherscan that it's a Proxy When the proxy is deployed, go to Etherscan. Go to Contract > Code > More Options and select the 'is this a proxy?' option. You should then be able to interact with the implementation contract via a @@ -107,14 +140,21 @@ contracts/src/LightClient.sol:LightClient Steps: -1. Ensure that the salt has been updated in the `.env` file. The upgrade script retrieves the proxyAddress from the - previous deployment by reading a file in the following path: +1. Ensure that the salt has been updated in the `.env.contracts` file. The upgrade script retrieves the proxyAddress + from the previous deployment by reading a file in the following path: +1. Ensure that the salt has been updated in the `.env.contracts` file. The upgrade script retrieves the proxyAddress + from the previous deployment by reading a file in the following path: `script/output/defenderDeployments/$CONTRACT_NAME/$CHAIN_ID/$SALT.json`. It knows the salt from a previous deployment by reading the `saltHistory.json` file. Run the following command: ```bash +source .env.contracts && \ +source .env.contracts && \ forge clean && \ -forge script contracts/script/FeeContractWithDefender.s.sol:FeeContractDefenderUpgradeScript --ffi --rpc-url https://ethereum-sepolia.publicnode.com --build-info true +forge script contracts/script/FeeContractWithDefender.s.sol:FeeContractDefenderUpgradeScript \ +--ffi \ +--rpc-url https://ethereum-sepolia.publicnode.com \ +--build-info true ``` 2. This command requires you to go to OpenZeppelin Defender's UI to see the transaction. Click that transaction which @@ -127,16 +167,41 @@ The transactions being confirmed are: (i) the deployment of the new fee contract Ensure that you update the version in the `getVersion()` method of the latest implementation contract. +Since the LightClient contract uses the PlonkVerifier library, the PlonkVerifier library has to be deployed and then +referenced at deployment time. Thus ensure you've deployed the PlonkVerifier +([see steps below](#deploy-the-plonk-verifier-library-with-defender)) and set the `$PLONK_VERIFIER_ADDRESS` variable in +the command below. Each time modifications are made to the Plonk Verifier, contracts that depend on it such as the Light +Client contract have to be upgraded and should use the new PlonkVerifier contract address as part of the deployment. + +Since the LightClient contract uses the PlonkVerifier library, the PlonkVerifier library has to be deployed and then +referenced at deployment time. Thus ensure you've deployed the PlonkVerifier +([see steps below](#deploy-the-plonk-verifier-library-with-defender)) and set the `$PLONK_VERIFIER_ADDRESS` variable in +the command below. Each time modifications are made to the Plonk Verifier, contracts that depend on it such as the Light +Client contract have to be upgraded and should use the new PlonkVerifier contract address as part of the deployment. + Steps: -1. Ensure that the salt has been updated in the `.env` file. The upgrade script retrieves the proxyAddress from the - previous deployment by reading a file in the following path: +1. Ensure that the salt has been updated in the `.env.contracts` file. The upgrade script retrieves the proxyAddress + from the previous deployment by reading a file in the following path: +1. Ensure that the salt has been updated in the `.env.contracts` file. The upgrade script retrieves the proxyAddress + from the previous deployment by reading a file in the following path: `script/output/defenderDeployments/$CONTRACT_NAME/$CHAIN_ID/$SALT.json`. It knows the salt from a previous deployment by reading the `saltHistory.json` file. Run the following command: ```bash +source .env.contracts && \ +source .env.contracts && \ forge clean && \ -forge script contracts/script/LightClientWithDefender.s.sol:LightClientDefenderUpgradeScript --ffi --rpc-url https://ethereum-sepolia.publicnode.com --build-info true +forge script contracts/script/LightClientWithDefender.s.sol:LightClientDefenderUpgradeScript \ +--ffi \ +--rpc-url https://ethereum-sepolia.publicnode.com \ +--build-info true \ +--libraries contracts/src/libraries/PlonkVerifier.sol:PlonkVerifier:$PLONK_VERIFIER_ADDRESS +forge script contracts/script/LightClientWithDefender.s.sol:LightClientDefenderUpgradeScript \ +--ffi \ +--rpc-url https://ethereum-sepolia.publicnode.com \ +--build-info true \ +--libraries contracts/src/libraries/PlonkVerifier.sol:PlonkVerifier:$PLONK_VERIFIER_ADDRESS ``` 2. This command requires you to go to OpenZeppelin Defender's UI to see the transaction. Click that transaction which @@ -208,3 +273,86 @@ forge script contracts/script/UpgradeSameLightClient.s.sol:UpgradeLightClientScr Note: the `$mnemonicOffset` should be zero by default if address referenced by the `$MNEMONIC` in the `.env` is the first address in that wallet. Otherwise, please specify the correct `$mnemonicOffset` + +# Deploy the Plonk Verifier Library with Defender + +The Plonk Verifier contract is not upgradeable and deploying we deploy with defender as part of our workflow so that we +can also deploy it with a multisig wallet. Each time modifications are made to the Plonk Verifier, contracts that depend +on it such as the Light Client contract have to be upgraded and should use the new PlonkVerifier contract address as +part of the deployment. + +Ensure that you update the salt, `PLONK_VERIFIER_SALT`, in the `.env.contracts` file before each deployment. + +```bash +source .env.contracts && \ +forge clean && \ +forge script contracts/script/PlonkVerifierWithDefender.s.sol:PlonkVerifierDefenderDeployScript \ +--ffi \ +--rpc-url https://ethereum-sepolia.publicnode.com \ +--build-info true +``` + +# Deploying Upgradable Contracts without OpenZeppelin Defender or a Safe Multisig Wallet + +## LightClient Contract Deployment + +```bash +forge script contracts/script/LightClient.s.sol:DeployLightClientContractScript $numBlocksPerEpoch $numInitValidators \ +--sig 'run(uint32, uint32)' \ +--ffi \ +--rpc-url https://ethereum-sepolia.publicnode.com +``` + +## LightClient Contract Upgrade + +```bash +forge script contracts/script/UpgradeLightClient.s.sol:UpgradeLightClientScript $admin $mostRecentlyDeployedProxy \ +--sig 'run(address, address)' \ +--ffi \ +--rpc-url https://ethereum-sepolia.publicnode.com +``` + +# Deploy and Upgrade without Defender + +Change the $MNEMONIC in the .env file to the one of the admin + +To Deploy + +```bash +forge script contracts/script/LightClient.s.sol:DeployLightClientContractScript $numBlocksPerEpoch $numInitValidators \ +--sig 'run(uint32, uint32)' \ +--ffi \ +--rpc-url https://ethereum-sepolia.publicnode.com\ +--broadcast --legacy +``` + +To Upgrade (assuming it's the same LightClient.sol file being used (pre-mainnet)) + +```bash +forge script contracts/script/UpgradeSameLightClient.s.sol:UpgradeLightClientScript $mnemonicOffset $mostRecentlyDeployedProxy \ +--sig 'run(uint32, address)' \ +--ffi \ +--rpc-url https://ethereum-sepolia.publicnode.com \ +--broadcast --legacy +``` + +Note: the `$mnemonicOffset` should be zero by default if address referenced by the `$MNEMONIC` in the `.env` is the +first address in that wallet. Otherwise, please specify the correct `$mnemonicOffset` + +# Deploy the Plonk Verifier Library with Defender + +The Plonk Verifier contract is not upgradeable and deploying we deploy with defender as part of our workflow so that we +can also deploy it with a multisig wallet. Each time modifications are made to the Plonk Verifier, contracts that depend +on it such as the Light Client contract have to be upgraded and should use the new PlonkVerifier contract address as +part of the deployment. + +Ensure that you update the salt, `PLONK_VERIFIER_SALT`, in the `.env.contracts` file before each deployment. + +```bash +source .env.contracts && \ +forge clean && \ +forge script contracts/script/PlonkVerifierWithDefender.s.sol:PlonkVerifierDefenderDeployScript \ +--ffi \ +--rpc-url https://ethereum-sepolia.publicnode.com \ +--build-info true +``` diff --git a/contracts/script/Utils.s.sol b/contracts/script/Utils.s.sol index 8ce2701a3..ff2174d2d 100644 --- a/contracts/script/Utils.s.sol +++ b/contracts/script/Utils.s.sol @@ -5,6 +5,8 @@ import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; contract UtilsScript is Script { string public constant SALT_HISTORY_FILE_NAME = "saltHistory.json"; + string public constant DEFENDER_OUTPUT_FILE_PATH = + "/contracts/script/output/defenderDeployments/"; function readFile(string memory path) external returns (bool, string memory) { if (vm.exists(path)) { @@ -32,7 +34,7 @@ contract UtilsScript is Script { return Strings.toHexString(uint256(uint160(address(addr)))); } - function generateDeploymentOutput( + function generateProxyDeploymentOutput( string memory contractName, uint256 contractSalt, address proxy, @@ -42,7 +44,7 @@ contract UtilsScript is Script { ) external returns (string memory filePath, string memory data) { string memory outputDir = string.concat( vm.projectRoot(), - "/contracts/script/output/defenderDeployments/", + DEFENDER_OUTPUT_FILE_PATH, contractName, "/", vm.toString(block.chainid), @@ -62,6 +64,36 @@ contract UtilsScript is Script { return (filePath, obj3); } + function generateDeploymentOutput( + string memory contractName, + uint256 contractSalt, + address contractAddress, + address multisig, + string memory approvalProcessId, + string memory viaType + ) external returns (string memory filePath, string memory data) { + string memory outputDir = string.concat( + vm.projectRoot(), + DEFENDER_OUTPUT_FILE_PATH, + contractName, + "/", + vm.toString(block.chainid), + "/" + ); + filePath = string.concat(outputDir, Strings.toString(contractSalt), ".json"); + + createDir(outputDir); + + string memory obj1 = "object"; + vm.serializeAddress(obj1, "contractAddress", contractAddress); + vm.serializeAddress(obj1, "multisig", multisig); + vm.serializeString(obj1, "approvalProcessId", approvalProcessId); + vm.serializeString(obj1, "approvalType", viaType); + string memory obj3 = vm.serializeUint(obj1, "salt", contractSalt); + + return (filePath, obj3); + } + function generateUpgradeOutput( string memory originalContractName, uint256 contractSalt, @@ -73,7 +105,7 @@ contract UtilsScript is Script { ) external returns (string memory filePath, string memory data) { string memory outputDir = string.concat( vm.projectRoot(), - "/contracts/script/output/defenderDeployments/", + DEFENDER_OUTPUT_FILE_PATH, originalContractName, "/", vm.toString(block.chainid), @@ -103,7 +135,7 @@ contract UtilsScript is Script { { outputDir = string.concat( vm.projectRoot(), - "/contracts/script/output/defenderDeployments/", + DEFENDER_OUTPUT_FILE_PATH, contractName, "/", vm.toString(block.chainid), @@ -137,7 +169,7 @@ contract UtilsScript is Script { { outputDir = string.concat( vm.projectRoot(), - "/contracts/script/output/defenderDeployments/", + DEFENDER_OUTPUT_FILE_PATH, contractName, "/", vm.toString(block.chainid), diff --git a/contracts/script/output/defenderDeployments/LightClient.sol/11155111/14.json b/contracts/script/output/defenderDeployments/LightClient.sol/11155111/14.json new file mode 100644 index 000000000..d269e3fa7 --- /dev/null +++ b/contracts/script/output/defenderDeployments/LightClient.sol/11155111/14.json @@ -0,0 +1,7 @@ +{ + "approvalProcessId": "a0dd5bf1-9766-4a2f-94b1-2a7ceb0dc5be", + "approvalType": "Gnosis Safe", + "multisig": "0xc56fA6505d10bF322e01327e22479DE78C3Bf1cE", + "proxyAddress": "0xfBCb14b42e6dDC81Dd4e02Dc1E35A9581A1F2200", + "salt": 14 +} \ No newline at end of file diff --git a/contracts/script/output/defenderDeployments/LightClient.sol/11155111/saltHistory.json b/contracts/script/output/defenderDeployments/LightClient.sol/11155111/saltHistory.json index 42cc64ab9..b96ced2f9 100644 --- a/contracts/script/output/defenderDeployments/LightClient.sol/11155111/saltHistory.json +++ b/contracts/script/output/defenderDeployments/LightClient.sol/11155111/saltHistory.json @@ -1,4 +1,4 @@ { "contractName": "LightClient.sol", - "previousSalt": 12 + "previousSalt": 14 } \ No newline at end of file diff --git a/contracts/script/output/defenderDeployments/PlonkVerifier.sol/11155111/2.json b/contracts/script/output/defenderDeployments/PlonkVerifier.sol/11155111/2.json new file mode 100644 index 000000000..14c61a5cf --- /dev/null +++ b/contracts/script/output/defenderDeployments/PlonkVerifier.sol/11155111/2.json @@ -0,0 +1,7 @@ +{ + "approvalProcessId": "a0dd5bf1-9766-4a2f-94b1-2a7ceb0dc5be", + "approvalType": "Gnosis Safe", + "multisig": "0xc56fA6505d10bF322e01327e22479DE78C3Bf1cE", + "contractAddress": "0x7807612b7F4D8241E1128F0037d056DA2Eec0242", + "salt": 2 +} \ No newline at end of file diff --git a/contracts/script/output/defenderDeployments/PlonkVerifier.sol/11155111/saltHistory.json b/contracts/script/output/defenderDeployments/PlonkVerifier.sol/11155111/saltHistory.json new file mode 100644 index 000000000..0ef114a29 --- /dev/null +++ b/contracts/script/output/defenderDeployments/PlonkVerifier.sol/11155111/saltHistory.json @@ -0,0 +1,4 @@ +{ + "contractName": "PlonkVerifier.sol", + "previousSalt": 2 +} \ No newline at end of file diff --git a/foundry.toml b/foundry.toml index 061cd3fd9..e5b2026b9 100644 --- a/foundry.toml +++ b/foundry.toml @@ -51,4 +51,4 @@ verbosity = 1 [profile.quick] fuzz = { runs = 10 } invariant = { runs = 10 } -verbosity = 1 +verbosity = 1 \ No newline at end of file