diff --git a/README.md b/README.md index fe856d7..7caadac 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ forge script script/read/RunEVMxRead.s.sol --broadcast --skip-simulation --with- ### 6. Withdraw funds ```bash -forge script script/inbox/RunEVMxRead.s.sol --broadcast --sig "withdrawAppFees()" --legacy --with-gas-price 0 +forge script script/read/RunEVMxRead.s.sol --broadcast --sig "withdrawAppFees()" --legacy --with-gas-price 0 ``` # Deployment Steps for EVMx Inbox Tests @@ -147,5 +147,52 @@ forge script script/write/RunEVMxWrite.s.sol --broadcast --skip-simulation --wit ### 6. Withdraw funds ```bash -forge script script/inbox/RunEVMxWrite.s.sol --broadcast --sig "withdrawAppFees()" --legacy --with-gas-price 0 +forge script script/write/RunEVMxWrite.s.sol --broadcast --sig "withdrawAppFees()" --legacy --with-gas-price 0 +``` +# Deployment Steps for EVMx Deploy Tests + +Follow these steps to deploy and run the EVMx Write tests. + +### 1. **Deploy the EVMx Deploy Tests Script** +Run the following command to deploy the EVMx Deploy tests script: +```bash +forge script script/deploy/RunEVMxDeploy.s.sol --broadcast --skip-simulation --with-gas-price 0 --legacy --sig "deployAppGateway()" +``` + +### 1a. **Verify the Contract** +Verify the `DeployAppGateway` contract on Blockscout: +```bash +forge verify-contract --rpc-url https://rpc-evmx-devnet.socket.tech/ --verifier blockscout --verifier-url https://evmx.cloud.blockscout.com/api src/deploy/DeploymentAppGateway.sol:DeploymentAppGateway +``` + +### 2. **Update the `APP_GATEWAY` in `.env`** +Make sure to update the `APP_GATEWAY` address in your `.env` file. + +### 3. **Pay Fees in Arbitrum ETH** +Run the script to pay fees in Arbitrum ETH: +```bash +forge script lib/socket-protocol/script/helpers/PayFeesInArbitrumETH.s.sol --broadcast --skip-simulation +``` + +### 4. **Deploy Onchain Contracts** +Deploy the onchain contracts using the following script: +```bash +forge script script/deploy/RunEVMxDeploy.s.sol --broadcast --skip-simulation --with-gas-price 0 --legacy --sig "deployOnchainContracts()" +``` + +### 4a. **Verify the Contract** +Verify the `DeployOnchain` contract on Arbitrum Sepolia Blockscout: +```bash +forge verify-contract --rpc-url https://rpc.ankr.com/arbitrum_sepolia --verifier-url https://arbitrum-sepolia.blockscout.com/api --verifier blockscout src/deploy/DeployOnchain.sol:NoPlugNoInitialize +``` + +### 5. **Run EVMx Deploy Script** +Finally, run the EVMx Write script: +```bash +forge script script/deploy/RunEVMxDeploy.s.sol --broadcast --skip-simulation --with-gas-price 0 --legacy --sig "runTests()" +``` + +### 6. Withdraw funds +```bash +forge script script/deploy/RunEVMxDeploy.s.sol --broadcast --sig "withdrawAppFees()" --legacy --with-gas-price 0 ``` diff --git a/script/deploy/RunEVMxDeploy.s.sol b/script/deploy/RunEVMxDeploy.s.sol new file mode 100644 index 0000000..a8d5f4e --- /dev/null +++ b/script/deploy/RunEVMxDeploy.s.sol @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {console} from "forge-std/console.sol"; +import {SetupScript} from "../SetupScript.sol"; +import {DeploymentAppGateway} from "../../src/deploy/DeploymentAppGateway.sol"; +import { + NoPlugNoInititialize, + NoPlugInitialize, + PlugNoInitialize, + PlugInitialize, + PlugInitializeTwice, + PlugNoInitInitialize +} from "../../src/deploy/DeployOnchain.sol"; + +contract RunEVMxDeployment is SetupScript { + DeploymentAppGateway deploymentAppGateway; + + function appGateway() internal view override returns (address) { + return address(deploymentAppGateway); + } + + function deployAppGatewayContract() internal override returns (address) { + // Deploy DeploymentAppGateway + DeploymentAppGateway newGateway = new DeploymentAppGateway(addressResolver, deployFees); + return address(newGateway); + } + + function getForwarderAddresses() internal pure { + return; + } + + function validate() internal { + vm.createSelectFork(rpcEVMx); + vm.startBroadcast(privateKey); + + deploymentAppGateway.contractValidation(arbSepChainId); + + vm.stopBroadcast(); + } + + // Initialize contract references + function init() internal { + deploymentAppGateway = DeploymentAppGateway(appGatewayAddress); + } + + function executeScriptSpecificLogic() internal override { + init(); + getForwarderAddresses(); + validate(); + } + + function run() external pure { + console.log( + "Please call one of these external functions: deployAppGateway(), deployOnchainContracts(), or runTests()" + ); + } + + function deployAppGateway() external { + _deployAppGateway(); + } + + function withdrawAppFees() external { + init(); + _withdrawAppFees(arbSepChainId); + } + + function deployOnchainContracts() external { + init(); + _deployOnchainContracts(); + } + + function runTests() external { + _run(arbSepChainId); + } +} diff --git a/script/deployment-mistakes/RunEVMxDeploymentMistakes.s.sol b/script/deployment-mistakes/RunEVMxDeploymentMistakes.s.sol deleted file mode 100644 index 17d79bd..0000000 --- a/script/deployment-mistakes/RunEVMxDeploymentMistakes.s.sol +++ /dev/null @@ -1,143 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {console} from "forge-std/console.sol"; -import {SetupScript} from "../SetupScript.sol"; -import {DeploymentMistakesAppGateway} from "../../src/deployment-mistakes/DeploymentMistakesAppGateway.sol"; -import { - NoPlugNoInititialize, - NoPlugInitialize, - PlugNoInitialize, - PlugInitialize, - PlugInitializeTwice, - PlugNoInitInitialize -} from "../../src/deployment-mistakes/DeployOnchainMistakes.sol"; - -contract RunEVMxDeploymentMistakes is SetupScript { - DeploymentMistakesAppGateway mistakesAppGateway; - address noPlugNoInititializeForwarder; - address noPlugInitializeForwarder; - address plugNoInitializeForwarder; - address plugInitializeForwarder; - address plugInitializeTwiceForwarder; - address plugNoInitInitializeForwarder; - - function appGateway() internal view override returns (address) { - return address(mistakesAppGateway); - } - - function deployAppGatewayContract() internal override returns (address) { - // Deploy DeploymentMistakesAppGateway - DeploymentMistakesAppGateway newGateway = new DeploymentMistakesAppGateway(addressResolver, deployFees); - return address(newGateway); - } - - function getForwarderAddresses() internal { - vm.createSelectFork(rpcEVMx); - - noPlugNoInititializeForwarder = - mistakesAppGateway.forwarderAddresses(mistakesAppGateway.noPlugNoInititialize(), arbSepChainId); - console.log("No Plug No Init Forwarder:", noPlugNoInititializeForwarder); - - noPlugInitializeForwarder = - mistakesAppGateway.forwarderAddresses(mistakesAppGateway.noPlugInitialize(), arbSepChainId); - console.log("No Plug Init Forwarder:", noPlugInitializeForwarder); - - plugNoInitializeForwarder = - mistakesAppGateway.forwarderAddresses(mistakesAppGateway.plugNoInitialize(), arbSepChainId); - console.log("Plug No Init Forwarder:", plugNoInitializeForwarder); - - plugInitializeForwarder = - mistakesAppGateway.forwarderAddresses(mistakesAppGateway.plugInitialize(), arbSepChainId); - console.log("Plug Init Forwarder:", plugInitializeForwarder); - - plugInitializeTwiceForwarder = - mistakesAppGateway.forwarderAddresses(mistakesAppGateway.plugInitializeTwice(), arbSepChainId); - console.log("Plug Init Init Forwarder:", plugInitializeTwiceForwarder); - - plugNoInitInitializeForwarder = - mistakesAppGateway.forwarderAddresses(mistakesAppGateway.plugNoInitInitialize(), arbSepChainId); - console.log("Plug No Init Init Forwarder:", plugNoInitInitializeForwarder); - } - - function validateMistakes() internal { - NoPlugNoInititialize noPlugNoInititialize = NoPlugNoInititialize(noPlugNoInititializeForwarder); - NoPlugInitialize noPlugInitialize = NoPlugInitialize(noPlugInitializeForwarder); - PlugNoInitialize plugNoInitialize = PlugNoInitialize(plugNoInitializeForwarder); - PlugInitialize plugInitialize = PlugInitialize(plugInitializeForwarder); - PlugInitializeTwice plugInitializeTwice = PlugInitializeTwice(plugInitializeTwiceForwarder); - PlugNoInitInitialize plugNoInitInitialize = PlugNoInitInitialize(plugNoInitInitializeForwarder); - - vm.createSelectFork(rpcArbSepolia); - vm.startBroadcast(privateKey); - - // NoPlugNoInititialize checks - require(noPlugNoInititialize.variable() == 0, "variable should be 0"); - (bool success,) = noPlugNoInititializeForwarder.call(abi.encodeWithSignature("socket__()")); - require(!success, "Should revert on socket__()"); - console.log("NoPlugNoInititialize checks passed"); - - // NoPlugInitialize checks - require(noPlugInitialize.variable() == 10, "variable should be 10"); - (success,) = noPlugInitializeForwarder.call(abi.encodeWithSignature("socket__()")); - require(!success, "Should revert on socket__()"); - console.log("NoPlugInitialize checks passed"); - - // PlugNoInitialize checks - require(plugNoInitialize.variable() == 0, "variable should be 0"); - require(address(plugNoInitialize.socket__()) != address(0), "Should return socket address"); - console.log("PlugNoInitialize checks passed"); - - // PlugInitialize checks - require(plugInitialize.variable() == 10, "variable should be 10"); - require(address(plugInitialize.socket__()) != address(0), "Should return socket address"); - console.log("PlugInitialize checks passed"); - - // PlugInitializeTwice checks - require(address(plugInitializeTwice.socket__()) != address(0), "Should return socket address"); - require(plugInitializeTwice.variable() == 20, "variable should be 20"); - console.log("PlugInitializeTwice checks passed"); - - // PlugNoInitInitialize checks - require(plugNoInitInitialize.variable() == 10, "variable should be 10"); - require(address(plugNoInitInitialize.socket__()) != address(0), "Should return socket address"); - console.log("PlugNoInitInitialize checks passed"); - - vm.stopBroadcast(); - } - - // Initialize contract references - function init() internal { - mistakesAppGateway = DeploymentMistakesAppGateway(appGatewayAddress); - } - - function executeScriptSpecificLogic() internal override { - init(); - getForwarderAddresses(); - validateMistakes(); - } - - function run() external pure { - console.log( - "Please call one of these external functions: deployAppGateway(), deployOnchainContracts(), or runTests()" - ); - } - - function deployAppGateway() external { - _deployAppGateway(); - } - - function withdrawAppFees() external { - init(); - _withdrawAppFees(arbSepChainId); - } - - function deployOnchainContracts() external { - init(); - _deployOnchainContracts(); - } - - function runTests() external { - _run(arbSepChainId); - } -} diff --git a/src/deployment-mistakes/DeployOnchainMistakes.sol b/src/deploy/DeployOnchain.sol similarity index 100% rename from src/deployment-mistakes/DeployOnchainMistakes.sol rename to src/deploy/DeployOnchain.sol diff --git a/src/deploy/DeploymentAppGateway.sol b/src/deploy/DeploymentAppGateway.sol new file mode 100644 index 0000000..6a6d882 --- /dev/null +++ b/src/deploy/DeploymentAppGateway.sol @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.7.0 <0.9.0; + +import "socket-protocol/contracts/base/AppGatewayBase.sol"; +import "./DeployOnchain.sol"; + +interface IDeployOnchain { + function variable() external; + function socket__() external; +} + +contract DeploymentAppGateway is AppGatewayBase { + bytes32 public noPlugNoInititialize = _createContractId("noPlugNoInititialize"); + bytes32 public noPlugInitialize = _createContractId("noPlugInitialize"); + bytes32 public plugNoInitialize = _createContractId("plugNoInitialize"); + bytes32 public plugInitialize = _createContractId("plugInitialize"); + bytes32 public plugInitializeTwice = _createContractId("plugInitializeTwice"); + bytes32 public plugNoInitInitialize = _createContractId("plugNoInitInitialize"); + + constructor(address addressResolver_, Fees memory fees_) AppGatewayBase(addressResolver_) { + creationCodeWithArgs[noPlugNoInititialize] = abi.encodePacked(type(NoPlugNoInititialize).creationCode); + creationCodeWithArgs[noPlugInitialize] = abi.encodePacked(type(NoPlugInitialize).creationCode); + creationCodeWithArgs[plugNoInitialize] = abi.encodePacked(type(PlugNoInitialize).creationCode); + creationCodeWithArgs[plugInitialize] = abi.encodePacked(type(PlugInitialize).creationCode); + creationCodeWithArgs[plugInitializeTwice] = abi.encodePacked(type(PlugInitializeTwice).creationCode); + creationCodeWithArgs[plugNoInitInitialize] = abi.encodePacked(type(PlugNoInitInitialize).creationCode); + _setOverrides(fees_); + } + + function deployContracts(uint32 chainSlug_) external async { + _deploy(noPlugNoInititialize, chainSlug_, IsPlug.NO); + _deploy( + noPlugInitialize, chainSlug_, IsPlug.NO, abi.encodeWithSelector(NoPlugInitialize.initialise.selector, 10) + ); + _deploy(plugNoInitialize, chainSlug_, IsPlug.YES); + _deploy(plugInitialize, chainSlug_, IsPlug.YES, abi.encodeWithSelector(PlugInitialize.initialise.selector, 10)); + _deploy( + plugInitializeTwice, + chainSlug_, + IsPlug.YES, + abi.encodeWithSelector(PlugInitializeTwice.initialise.selector, 10) + ); + _deploy(plugNoInitInitialize, chainSlug_, IsPlug.YES); + } + + function initialize(uint32 chainSlug_) public override async { + PlugInitializeTwice(forwarderAddresses[plugInitializeTwice][chainSlug_]).initialise(10); + PlugNoInitInitialize(forwarderAddresses[plugNoInitInitialize][chainSlug_]).initialise(10); + } + + function contractValidation(uint32 chainSlug_) external async { + address noPlugNoInititializeForwarder = forwarderAddresses[noPlugNoInititialize][chainSlug_]; + address noPlugInitializeForwarder = forwarderAddresses[noPlugInitialize][chainSlug_]; + address plugNoInitializeForwarder = forwarderAddresses[plugNoInitialize][chainSlug_]; + address plugInitializeForwarder = forwarderAddresses[plugInitialize][chainSlug_]; + address plugInitializeTwiceForwarder = forwarderAddresses[plugInitializeTwice][chainSlug_]; + address plugNoInitInitializeForwarder = forwarderAddresses[plugNoInitInitialize][chainSlug_]; + + // NoPlugNoInititialize checks + _setOverrides(Read.ON); + IDeployOnchain(noPlugNoInititializeForwarder).variable(); + IPromise(noPlugNoInititializeForwarder).then(this.validateVariable.selector, abi.encode(0)); + + // NoPlugInitialize checks + IDeployOnchain(noPlugInitializeForwarder).variable(); + IPromise(noPlugInitializeForwarder).then(this.validateVariable.selector, abi.encode(10)); + + // PlugNoInitialize checks + IDeployOnchain(plugNoInitializeForwarder).variable(); + IPromise(plugNoInitializeForwarder).then(this.validateVariable.selector, abi.encode(0)); + IDeployOnchain(plugNoInitializeForwarder).socket__(); + IPromise(plugNoInitializeForwarder).then(this.validateSocket.selector, abi.encode(0)); + + // PlugInitialize checks + IDeployOnchain(plugInitializeForwarder).variable(); + IPromise(plugInitializeForwarder).then(this.validateVariable.selector, abi.encode(10)); + IDeployOnchain(plugInitializeForwarder).socket__(); + IPromise(plugInitializeForwarder).then(this.validateSocket.selector, abi.encode(0)); + + // PlugInitializeTwice checks + IDeployOnchain(plugInitializeTwiceForwarder).variable(); + IPromise(plugInitializeTwiceForwarder).then(this.validateVariable.selector, abi.encode(20)); + IDeployOnchain(plugInitializeTwiceForwarder).socket__(); + IPromise(plugInitializeTwiceForwarder).then(this.validateSocket.selector, abi.encode(0)); + + // PlugNoInitInitialize checks + _setOverrides(Read.ON); + IDeployOnchain(plugNoInitInitializeForwarder).variable(); + IPromise(plugNoInitInitializeForwarder).then(this.validateVariable.selector, abi.encode(10)); + IDeployOnchain(plugNoInitInitializeForwarder).socket__(); + IPromise(plugNoInitInitializeForwarder).then(this.validateSocket.selector, abi.encode(0)); + _setOverrides(Read.OFF); + } + + function validateVariable(bytes memory data, bytes memory returnData) external onlyPromises { + uint256 onchainVariable = abi.decode(returnData, (uint256)); + uint256 expectedVariable = abi.decode(data, (uint256)); + require(onchainVariable == expectedVariable, "unexpected variable value"); + } + + function validateSocket(bytes memory data, bytes memory returnData) external onlyPromises { + address onchainSocket = abi.decode(returnData, (address)); + address notSocket = abi.decode(data, (address)); + require(onchainSocket != notSocket, "Should return socket address"); + } + + function setFees(Fees memory fees_) public { + fees = fees_; + } + + function withdrawFeeTokens(uint32 chainSlug_, address token_, uint256 amount_, address receiver_) external { + _withdrawFeeTokens(chainSlug_, token_, amount_, receiver_); + } +} diff --git a/src/deployment-mistakes/DeploymentMistakesAppGateway.sol b/src/deployment-mistakes/DeploymentMistakesAppGateway.sol deleted file mode 100644 index fa350dc..0000000 --- a/src/deployment-mistakes/DeploymentMistakesAppGateway.sol +++ /dev/null @@ -1,53 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity >=0.7.0 <0.9.0; - -import "socket-protocol/contracts/base/AppGatewayBase.sol"; -import "./DeployOnchainMistakes.sol"; - -contract DeploymentMistakesAppGateway is AppGatewayBase { - bytes32 public noPlugNoInititialize = _createContractId("noPlugNoInititialize"); - bytes32 public noPlugInitialize = _createContractId("noPlugInitialize"); - bytes32 public plugNoInitialize = _createContractId("plugNoInitialize"); - bytes32 public plugInitialize = _createContractId("plugInitialize"); - bytes32 public plugInitializeTwice = _createContractId("plugInitializeTwice"); - bytes32 public plugNoInitInitialize = _createContractId("plugNoInitInitialize"); - - constructor(address addressResolver_, Fees memory fees_) AppGatewayBase(addressResolver_) { - creationCodeWithArgs[noPlugNoInititialize] = abi.encodePacked(type(NoPlugNoInititialize).creationCode); - creationCodeWithArgs[noPlugInitialize] = abi.encodePacked(type(NoPlugInitialize).creationCode); - creationCodeWithArgs[plugNoInitialize] = abi.encodePacked(type(PlugNoInitialize).creationCode); - creationCodeWithArgs[plugInitialize] = abi.encodePacked(type(PlugInitialize).creationCode); - creationCodeWithArgs[plugInitializeTwice] = abi.encodePacked(type(PlugInitializeTwice).creationCode); - creationCodeWithArgs[plugNoInitInitialize] = abi.encodePacked(type(PlugNoInitInitialize).creationCode); - _setOverrides(fees_); - } - - function deployContracts(uint32 chainSlug_) external async { - _deploy(noPlugNoInititialize, chainSlug_, IsPlug.NO); - _deploy( - noPlugInitialize, chainSlug_, IsPlug.NO, abi.encodeWithSelector(NoPlugInitialize.initialise.selector, 10) - ); - _deploy(plugNoInitialize, chainSlug_, IsPlug.YES); - _deploy(plugInitialize, chainSlug_, IsPlug.YES, abi.encodeWithSelector(PlugInitialize.initialise.selector, 10)); - _deploy( - plugInitializeTwice, - chainSlug_, - IsPlug.YES, - abi.encodeWithSelector(PlugInitializeTwice.initialise.selector, 10) - ); - _deploy(plugNoInitInitialize, chainSlug_, IsPlug.YES); - } - - function initialize(uint32 chainSlug_) public override async { - PlugInitializeTwice(forwarderAddresses[plugInitializeTwice][chainSlug_]).initialise(10); - PlugNoInitInitialize(forwarderAddresses[plugNoInitInitialize][chainSlug_]).initialise(10); - } - - function setFees(Fees memory fees_) public { - fees = fees_; - } - - function withdrawFeeTokens(uint32 chainSlug_, address token_, uint256 amount_, address receiver_) external { - _withdrawFeeTokens(chainSlug_, token_, amount_, receiver_); - } -}