diff --git a/script/deployment-mistakes/DeployEVMxDeploymentMistakesApp.s.sol b/script/deployment-mistakes/DeployEVMxDeploymentMistakesApp.s.sol new file mode 100644 index 0000000..4f9e2e0 --- /dev/null +++ b/script/deployment-mistakes/DeployEVMxDeploymentMistakesApp.s.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {Script} from "forge-std/Script.sol"; +import {console} from "forge-std/console.sol"; +import {Fees} from "socket-protocol/contracts/protocol/utils/common/Structs.sol"; +import {ETH_ADDRESS, FAST} from "socket-protocol/contracts/protocol/utils/common/Constants.sol"; + +import {DeploymentMistakesAppGateway} from "../../src/deployment-mistakes/DeploymentMistakesAppGateway.sol"; +import {DeploymentMistakesDeployer} from "../../src/deployment-mistakes/DeploymentMistakesDeployer.sol"; + +contract DeployMistakes is Script { + function run() external { + address addressResolver = vm.envAddress("ADDRESS_RESOLVER"); + address auctionManager = vm.envAddress("AUCTION_MANAGER"); + string memory rpc = vm.envString("EVMX_RPC"); + vm.createSelectFork(rpc); + + uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + vm.startBroadcast(deployerPrivateKey); + + Fees memory fees = Fees({feePoolChain: 421614, feePoolToken: ETH_ADDRESS, amount: 0.001 ether}); + + DeploymentMistakesDeployer deployer = + new DeploymentMistakesDeployer(addressResolver, auctionManager, FAST, fees); + + DeploymentMistakesAppGateway gateway = + new DeploymentMistakesAppGateway(addressResolver, address(deployer), auctionManager, fees); + + console.log("Contracts deployed:"); + console.log("DeploymentMistakesDeployer:", address(deployer)); + console.log("DeploymentMistakesAppGateway:", address(gateway)); + + console.log("DeploymentMistakesDeployer contract ids:"); + console.log("noPlugNoInititialize"); + console.logBytes32(deployer.noPlugNoInititialize()); + console.log("noPlugInitialize"); + console.logBytes32(deployer.noPlugInitialize()); + console.log("plugNoInitialize"); + console.logBytes32(deployer.plugNoInitialize()); + console.log("plugInitialize"); + console.logBytes32(deployer.plugInitialize()); + console.log("plugInitializeTwice"); + console.logBytes32(deployer.plugInitializeTwice()); + console.log("plugNoInitInitialize"); + console.logBytes32(deployer.plugNoInitInitialize()); + } +} diff --git a/script/deployment-mistakes/RunEVMxDeploymentMistakes.s.sol b/script/deployment-mistakes/RunEVMxDeploymentMistakes.s.sol new file mode 100644 index 0000000..8d7d308 --- /dev/null +++ b/script/deployment-mistakes/RunEVMxDeploymentMistakes.s.sol @@ -0,0 +1,198 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {Script} from "forge-std/Script.sol"; +import {console} from "forge-std/console.sol"; +import {DepositFees} from "socket-protocol/script/PayFeesInArbitrumETH.s.sol"; +import {Fees} from "socket-protocol/contracts/protocol/utils/common/Structs.sol"; +import {FeesPlug} from "socket-protocol/contracts/protocol/payload-delivery/FeesPlug.sol"; +import {ETH_ADDRESS, FAST} from "socket-protocol/contracts/protocol/utils/common/Constants.sol"; +import {FeesManager} from "socket-protocol/contracts/protocol/payload-delivery/app-gateway/FeesManager.sol"; + +import {DeploymentMistakesAppGateway} from "../../src/deployment-mistakes/DeploymentMistakesAppGateway.sol"; +import {DeploymentMistakesDeployer} from "../../src/deployment-mistakes/DeploymentMistakesDeployer.sol"; +import { + NoPlugNoInititialize, + NoPlugInitialize, + PlugNoInitialize, + PlugInitialize, + PlugInitializeTwice, + PlugNoInitInitialize +} from "../../src/deployment-mistakes/DeployOnchainMistakes.sol"; + +contract RunEVMxDeploy is Script { + // ----- ENVIRONMENT VARIABLES ----- + string rpcEVMx = vm.envString("EVMX_RPC"); + string rpcArbSepolia = vm.envString("ARBITRUM_SEPOLIA_RPC"); + address addressResolver = vm.envAddress("ADDRESS_RESOLVER"); + address auctionManager = vm.envAddress("AUCTION_MANAGER"); + address feesPlugArbSepolia = vm.envAddress("ARBITRUM_FEES_PLUG"); + address feesManagerAddress = vm.envAddress("FEES_MANAGER"); + uint256 privateKey = vm.envUint("PRIVATE_KEY"); + address deployerAddress = vm.envAddress("DEPLOYER"); + address appGatewayAddress = vm.envAddress("APP_GATEWAY"); + + // ----- SCRIPT VARIABLES ----- + uint32 arbSepChainId = 411614; + uint32 opSepChainId = 11155420; + + Fees fees = Fees({feePoolChain: arbSepChainId, feePoolToken: ETH_ADDRESS, amount: 0.001 ether}); + FeesManager feesManager = FeesManager(payable(feesManagerAddress)); + FeesPlug feesPlug = FeesPlug(payable(feesPlugArbSepolia)); + + DeploymentMistakesDeployer deployer = DeploymentMistakesDeployer(deployerAddress); + DeploymentMistakesAppGateway appGateway = DeploymentMistakesAppGateway(appGatewayAddress); + address noPlugNoInititializeForwarder; + address noPlugInitializeForwarder; + address plugNoInitializeForwarder; + address plugInitializeForwarder; + address plugInitializeTwiceForwarder; + address plugNoInitInitializeForwarder; + + function checkDepositedFees(uint32 chainId) internal returns (uint256 availableFees) { + vm.createSelectFork(rpcEVMx); + + (uint256 deposited, uint256 blocked) = + feesManager.appGatewayFeeBalances(appGatewayAddress, chainId, ETH_ADDRESS); + console.log("App Gateway:", appGatewayAddress); + console.log("Deposited fees:", deposited); + console.log("Blocked fees:", blocked); + + availableFees = feesManager.getAvailableFees(chainId, appGatewayAddress, ETH_ADDRESS); + console.log("Available fees:", availableFees); + } + + function withdrawAppFees(uint32 chainId) internal { + // EVMX Check available fees + vm.createSelectFork(rpcEVMx); + + uint256 availableFees = feesManager.getAvailableFees(chainId, appGatewayAddress, ETH_ADDRESS); + console.log("Available fees:", availableFees); + + if (availableFees > 0) { + // Switch to Arbitrum Sepolia to get gas price + vm.createSelectFork(rpcArbSepolia); + + // Gas price from Arbitrum + uint256 arbitrumGasPrice = block.basefee + 0.1 gwei; // With buffer + uint256 gasLimit = 5_000_000; // Estimate + uint256 estimatedGasCost = gasLimit * arbitrumGasPrice; + + console.log("Arbitrum gas price (wei):", arbitrumGasPrice); + console.log("Gas limit:", gasLimit); + console.log("Estimated gas cost:", estimatedGasCost); + + // Calculate amount to withdraw + uint256 amountToWithdraw = availableFees > estimatedGasCost ? availableFees - estimatedGasCost : 0; + + if (amountToWithdraw > 0) { + // Switch back to EVMX to perform withdrawal + vm.createSelectFork(rpcEVMx); + vm.startBroadcast(privateKey); + address sender = vm.addr(privateKey); + console.log("Withdrawing amount:", amountToWithdraw); + appGateway.withdrawFeeTokens(chainId, ETH_ADDRESS, amountToWithdraw, sender); + vm.stopBroadcast(); + + // Switch back to Arbitrum Sepolia to check final balance + vm.createSelectFork(rpcArbSepolia); + console.log("Final sender balance:", sender.balance); + } else { + console.log("Available fees less than estimated gas cost"); + } + } + } + + function deployOnchainContracts() internal { + vm.createSelectFork(rpcEVMx); + vm.startBroadcast(privateKey); + deployer.deployContracts(arbSepChainId); + vm.stopBroadcast(); + + console.log("Contracts deployed"); + } + + function getForwarderAddresses() internal { + vm.createSelectFork(rpcEVMx); + + noPlugNoInititializeForwarder = deployer.forwarderAddresses(deployer.noPlugNoInititialize(), arbSepChainId); + console.log("No Plug No Init Forwarder:", noPlugNoInititializeForwarder); + + noPlugInitializeForwarder = deployer.forwarderAddresses(deployer.noPlugInitialize(), arbSepChainId); + console.log("No Plug Init Forwarder:", noPlugInitializeForwarder); + + plugNoInitializeForwarder = deployer.forwarderAddresses(deployer.plugNoInitialize(), arbSepChainId); + console.log("Plug No Init Forwarder:", plugNoInitializeForwarder); + + plugInitializeForwarder = deployer.forwarderAddresses(deployer.plugInitialize(), arbSepChainId); + console.log("Plug Init Forwarder:", plugInitializeForwarder); + + plugInitializeTwiceForwarder = deployer.forwarderAddresses(deployer.plugInitializeTwice(), arbSepChainId); + console.log("Plug Init Init Forwarder:", plugInitializeTwiceForwarder); + + plugNoInitInitializeForwarder = deployer.forwarderAddresses(deployer.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(); + } + + function run() external { + uint256 availableFees = checkDepositedFees(arbSepChainId); + + if (availableFees > 0) { + // Set up onchain deployments + deployOnchainContracts(); + getForwarderAddresses(); + + validateMistakes(); + + withdrawAppFees(arbSepChainId); + } else { + console.log("NO AVAILABLE FEES - Please deposit fees before running this script"); + } + } +} diff --git a/script/robust/deployEVMx.sol b/script/robust/DeployEVMxRobustnessTests.sol similarity index 99% rename from script/robust/deployEVMx.sol rename to script/robust/DeployEVMxRobustnessTests.sol index 9cac1f1..4e57518 100644 --- a/script/robust/deployEVMx.sol +++ b/script/robust/DeployEVMxRobustnessTests.sol @@ -3,11 +3,12 @@ pragma solidity ^0.8.0; import {Script} from "forge-std/Script.sol"; import {console} from "forge-std/console.sol"; -import {RobustnessDeployer} from "../../src/robustness/RobustnessDeployer.sol"; -import {RobustnessAppGateway} from "../../src/robustness/RobustnessAppGateway.sol"; import {Fees} from "socket-protocol/contracts/protocol/utils/common/Structs.sol"; import {ETH_ADDRESS, FAST} from "socket-protocol/contracts/protocol/utils/common/Constants.sol"; +import {RobustnessDeployer} from "../../src/robustness/RobustnessDeployer.sol"; +import {RobustnessAppGateway} from "../../src/robustness/RobustnessAppGateway.sol"; + contract DeployEVMxContracts is Script { function run() external { address addressResolver = vm.envAddress("ADDRESS_RESOLVER"); diff --git a/script/robust/RunEVMxRobustness.s.sol b/script/robust/RunEVMxRobustness.s.sol index bbfd07f..ca7d929 100644 --- a/script/robust/RunEVMxRobustness.s.sol +++ b/script/robust/RunEVMxRobustness.s.sol @@ -3,14 +3,15 @@ pragma solidity ^0.8.0; import {Script} from "forge-std/Script.sol"; import {console} from "forge-std/console.sol"; -import {RobustnessDeployer} from "../../src/robustness/RobustnessDeployer.sol"; -import {RobustnessAppGateway} from "../../src/robustness/RobustnessAppGateway.sol"; import {DepositFees} from "socket-protocol/script/PayFeesInArbitrumETH.s.sol"; import {Fees} from "socket-protocol/contracts/protocol/utils/common/Structs.sol"; import {FeesPlug} from "socket-protocol/contracts/protocol/payload-delivery/FeesPlug.sol"; import {ETH_ADDRESS, FAST} from "socket-protocol/contracts/protocol/utils/common/Constants.sol"; import {FeesManager} from "socket-protocol/contracts/protocol/payload-delivery/app-gateway/FeesManager.sol"; +import {RobustnessDeployer} from "../../src/robustness/RobustnessDeployer.sol"; +import {RobustnessAppGateway} from "../../src/robustness/RobustnessAppGateway.sol"; + contract RunEVMxRobustness is Script { // ----- ENVIRONMENT VARIABLES ----- string rpcEVMx = vm.envString("EVMX_RPC"); diff --git a/src/deployment-mistakes/DeployOnchainMistakes.sol b/src/deployment-mistakes/DeployOnchainMistakes.sol new file mode 100644 index 0000000..7280d77 --- /dev/null +++ b/src/deployment-mistakes/DeployOnchainMistakes.sol @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.7.0 <0.9.0; + +import "socket-protocol/contracts/base/PlugBase.sol"; + +// for tests, variable should be 0 +// should revert on getting socket address +contract NoPlugNoInititialize { + uint256 public variable; +} + +// for tests, variable should be 10 +// should revert on getting socket address +contract NoPlugInitialize { + uint256 public variable; + + function initialise(uint256 variable_) external { + variable += variable_; + } +} + +// for tests, variable should be 0 +// should return socket address +contract PlugNoInitialize is PlugBase { + uint256 public variable; +} + +// for tests, variable should be 10 +// should return socket address +contract PlugInitialize is PlugBase { + uint256 public variable; + + function initialise(uint256 variable_) external { + variable += variable_; + } +} + +// for tests, counter should be 20 (init called twice: initialize on _deploy and then on initialize from AppGateway) +// should return socket address +contract PlugInitializeTwice is PlugBase { + uint256 public variable; + + function initialise(uint256 variable_) external { + variable += variable_; + } +} + +// for tests, variable should be 10 (init data not passed) +// should return socket address +contract PlugNoInitInitialize is PlugBase { + uint256 public variable; + + function initialise(uint256 variable_) external { + variable += variable_; + } +} diff --git a/src/deployment-mistakes/DeploymentMistakesAppGateway.sol b/src/deployment-mistakes/DeploymentMistakesAppGateway.sol new file mode 100644 index 0000000..98b1b47 --- /dev/null +++ b/src/deployment-mistakes/DeploymentMistakesAppGateway.sol @@ -0,0 +1,22 @@ +// 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 { + constructor(address addressResolver_, address deployerContract_, address auctionManager_, Fees memory fees_) + AppGatewayBase(addressResolver_, auctionManager_) + { + addressResolver__.setContractsToGateways(deployerContract_); + _setOverrides(fees_); + } + + 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/DeploymentMistakesDeployer.sol b/src/deployment-mistakes/DeploymentMistakesDeployer.sol new file mode 100644 index 0000000..5476d75 --- /dev/null +++ b/src/deployment-mistakes/DeploymentMistakesDeployer.sol @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.7.0 <0.9.0; + +import "./DeployOnchainMistakes.sol"; +import "socket-protocol/contracts/base/AppDeployerBase.sol"; + +contract DeploymentMistakesDeployer is AppDeployerBase { + 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_, + address auctionManager_, + bytes32 sbType_, + Fees memory fees_ + ) AppDeployerBase(addressResolver_, auctionManager_, sbType_) { + 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_; + } +}