diff --git a/.env.sample b/.env.sample index 8aab70e..7baff03 100644 --- a/.env.sample +++ b/.env.sample @@ -1,23 +1,23 @@ -PRIVATE_KEY="0x" -WALLET_ADDRESS="0x" - -OFF_CHAIN_VM_RPC="https://rpc-socket-composer-testnet.t.conduit.xyz" - +# RPCs +EVMX_RPC="https://rpc-evmx-devnet.socket.tech/" SEPOLIA_RPC="https://rpc.ankr.com/eth_sepolia/" -SEPOLIA_API_KEY="empty" - ARBITRUM_SEPOLIA_RPC="https://rpc.ankr.com/arbitrum_sepolia" -ARBITRUM_API_KEY="empty" - OPTIMISM_SEPOLIA_RPC="https://rpc.ankr.com/optimism_sepolia" -OPTIMISM_API_KEY="empty" - BASE_SEPOLIA_RPC="https://rpc.ankr.com/base_sepolia" -BASE_API_KEY="empty" -ADDRESS_RESOLVER="0x6f60df8CD3Bb76C33ebc9E2E2Fe577edD62e3938" -AUCTION_MANAGER="0xDC81d1BE1E8d92C5a98a15D89A16134D74121FC2" +# EVMx key addresses +# Find the most up to date addresses in deployments/dev_addresses.json +ADDRESS_RESOLVER="0xf3046B22F98C25305E8040286fB1b33378BA10a1" +FEES_MANAGER="0x603723100172D30171B7Fd9870ba80F8baf6FaD4" +ARBITRUM_FEES_PLUG="0x89324F93d852cB4fcDC4Ee202456be466ce096bb" + +# Add your deployer private key here +# or remove it from this file if it is already an env var +PRIVATE_KEY="0x" + +# Set app related values after deployment on EVMx +APP_GATEWAY="0x" -# Set values after deployment -COUNTER_DEPLOYER="" -COUNTER_APP_GATEWAY="" +# FOR INFRASTRUCTURE DEPLOYMENT ONLY +# Removes hardhat issues related to linting and syntax checking +SOCKET_SIGNER_KEY="0000dead0000dead0000dead0000dead0000dead0000dead0000dead0000dead" diff --git a/.gitmodules b/.gitmodules index 2b0d3f1..b41225c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -3,4 +3,5 @@ url = https://github.com/foundry-rs/forge-std [submodule "lib/socket-protocol"] path = lib/socket-protocol - url = https://github.com/SocketDotTech/socket-protocol + url = https://github.com/SocketDotTech/socket-protocol.git + branch = master diff --git a/foundry.toml b/foundry.toml index 25b918f..43d9d0c 100644 --- a/foundry.toml +++ b/foundry.toml @@ -1,6 +1,15 @@ [profile.default] +solc_version = "0.8.22" src = "src" out = "out" libs = ["lib"] +ffi = true +optimizer = true +optimizer_runs = 200 +evm_version = 'paris' # See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options +[etherscan] +43 = { key = "empty", url = "https://evmx.cloud.blockscout.com/api?" } +421614 = { key = "${ARBISCAN_API_KEY}", url = "https://api-sepolia.arbiscan.io/api?" } +11155420 = { key = "${OPTIMISM_API_KEY}", url = "https://optimism-sepolia.blockscout.com/api?" } diff --git a/lib/socket-protocol b/lib/socket-protocol index bf6212c..a8608e2 160000 --- a/lib/socket-protocol +++ b/lib/socket-protocol @@ -1 +1 @@ -Subproject commit bf6212c6563e180a8a2dd942d8fb5357beb459fb +Subproject commit a8608e2138a6d6759e6bfec68eac6c0b7d90e32e diff --git a/remappings.txt b/remappings.txt new file mode 100644 index 0000000..9b23047 --- /dev/null +++ b/remappings.txt @@ -0,0 +1,5 @@ +ds-test/=lib/socket-protocol/lib/forge-std/lib/ds-test/src/ +forge-std/=lib/forge-std/src/ +socket-protocol/=lib/socket-protocol/ +solady/=lib/socket-protocol/lib/solady/src/ +solmate/=lib/socket-protocol/lib/solmate/src/ diff --git a/script/counter/DeployEVMxCounterApp.s.sol b/script/counter/DeployEVMxCounterApp.s.sol new file mode 100644 index 0000000..1c4c6ee --- /dev/null +++ b/script/counter/DeployEVMxCounterApp.s.sol @@ -0,0 +1,33 @@ +// 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} from "socket-protocol/contracts/protocol/utils/common/Constants.sol"; + +import {CounterAppGateway} from "../../src/counter/CounterAppGateway.sol"; + +contract CounterDeploy is Script { + function run() external { + address addressResolver = vm.envAddress("ADDRESS_RESOLVER"); + string memory rpc = vm.envString("EVMX_RPC"); + vm.createSelectFork(rpc); + + uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + vm.startBroadcast(deployerPrivateKey); + + // Setting fee payment on Arbitrum Sepolia + // amount: Minimum fee required in contract and maximum user is willing to pay + // User must have deposited >= amount, ensuring transmitter gets compensated for including this tx in a batch + // Current Counter example costs 0.000105 eth + Fees memory fees = Fees({feePoolChain: 421614, feePoolToken: ETH_ADDRESS, amount: 0.0005 ether}); + + CounterAppGateway gateway = new CounterAppGateway(addressResolver, fees); + + console.log("Contracts deployed:"); + console.log("CounterAppGateway:", address(gateway)); + console.log("counterId:"); + console.logBytes32(gateway.counter()); + } +} diff --git a/script/counter/DeployOnchainCounters.s.sol b/script/counter/DeployOnchainCounters.s.sol new file mode 100644 index 0000000..3430653 --- /dev/null +++ b/script/counter/DeployOnchainCounters.s.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {Script} from "forge-std/Script.sol"; +import {console} from "forge-std/console.sol"; +import {ETH_ADDRESS} from "socket-protocol/contracts/protocol/utils/common/Constants.sol"; + +import {CounterAppGateway} from "../../src/counter/CounterAppGateway.sol"; + +contract CounterDeployOnchain is Script { + function run() external { + string memory rpc = vm.envString("EVMX_RPC"); + console.log(rpc); + vm.createSelectFork(rpc); + + uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + vm.startBroadcast(deployerPrivateKey); + + CounterAppGateway appGateway = CounterAppGateway(vm.envAddress("APP_GATEWAY")); + + console.log("Counter Gateway:", address(appGateway)); + + console.log("Deploying contracts on Arbitrum Sepolia..."); + appGateway.deployContracts(421614); + console.log("Deploying contracts on Optimism Sepolia..."); + appGateway.deployContracts(11155420); + console.log("Deploying contracts on Base Sepolia..."); + appGateway.deployContracts(84532); + } +} diff --git a/script/counter/IncrementCountersFromApp.s.sol b/script/counter/IncrementCountersFromApp.s.sol new file mode 100644 index 0000000..ec5f081 --- /dev/null +++ b/script/counter/IncrementCountersFromApp.s.sol @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {Script} from "forge-std/Script.sol"; +import {console} from "forge-std/console.sol"; + +import {CounterAppGateway} from "../../src/counter/CounterAppGateway.sol"; + +contract IncrementCounters is Script { + function run() external { + string memory socketRPC = vm.envString("EVMX_RPC"); + uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + + vm.createSelectFork(socketRPC); + + CounterAppGateway gateway = CounterAppGateway(vm.envAddress("APP_GATEWAY")); + + address counterForwarderArbitrumSepolia = gateway.forwarderAddresses(gateway.counter(), 421614); + address counterForwarderOptimismSepolia = gateway.forwarderAddresses(gateway.counter(), 11155420); + address counterForwarderBaseSepolia = gateway.forwarderAddresses(gateway.counter(), 84532); + + // Count non-zero addresses + uint256 nonZeroCount = 0; + if (counterForwarderArbitrumSepolia != address(0)) nonZeroCount++; + if (counterForwarderOptimismSepolia != address(0)) nonZeroCount++; + if (counterForwarderBaseSepolia != address(0)) nonZeroCount++; + + address[] memory instances = new address[](nonZeroCount); + uint256 index = 0; + if (counterForwarderArbitrumSepolia != address(0)) { + instances[index] = counterForwarderArbitrumSepolia; + index++; + } else { + console.log("Arbitrum Sepolia forwarder not yet deployed"); + } + if (counterForwarderOptimismSepolia != address(0)) { + instances[index] = counterForwarderOptimismSepolia; + index++; + } else { + console.log("Optimism Sepolia forwarder not yet deployed"); + } + if (counterForwarderBaseSepolia != address(0)) { + instances[index] = counterForwarderBaseSepolia; + index++; + } else { + console.log("Base Sepolia forwarder not yet deployed"); + } + + if (instances.length > 0) { + vm.startBroadcast(deployerPrivateKey); + gateway.incrementCounters(instances); + } else { + console.log("No forwarder addresses found"); + } + } +} diff --git a/script/counter/ReadOnchainCounters.s.sol b/script/counter/ReadOnchainCounters.s.sol new file mode 100644 index 0000000..20673b2 --- /dev/null +++ b/script/counter/ReadOnchainCounters.s.sol @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {Script} from "forge-std/Script.sol"; +import {console} from "forge-std/console.sol"; + +import {CounterAppGateway} from "../../src/counter/CounterAppGateway.sol"; +import {Counter} from "../../src/counter/Counter.sol"; + +contract CheckCounters is Script { + function run() external { + CounterAppGateway gateway = CounterAppGateway(vm.envAddress("APP_GATEWAY")); + + vm.createSelectFork(vm.envString("EVMX_RPC")); + address counterInstanceArbitrumSepolia = gateway.getOnChainAddress(gateway.counter(), 421614); + address counterInstanceOptimismSepolia = gateway.getOnChainAddress(gateway.counter(), 11155420); + address counterInstanceBaseSepolia = gateway.getOnChainAddress(gateway.counter(), 84532); + + if (counterInstanceArbitrumSepolia != address(0)) { + vm.createSelectFork(vm.envString("ARBITRUM_SEPOLIA_RPC")); + uint256 counterValueArbitrumSepolia = Counter(counterInstanceArbitrumSepolia).counter(); + console.log("Counter value on Arbitrum Sepolia: ", counterValueArbitrumSepolia); + } else { + console.log("Counter not yet deployed on Arbitrum Sepolia"); + } + + if (counterInstanceOptimismSepolia != address(0)) { + vm.createSelectFork(vm.envString("OPTIMISM_SEPOLIA_RPC")); + uint256 counterValueOptimismSepolia = Counter(counterInstanceOptimismSepolia).counter(); + console.log("Counter value on Optimism Sepolia: ", counterValueOptimismSepolia); + } else { + console.log("Counter not yet deployed on Optimism Sepolia"); + } + + if (counterInstanceBaseSepolia != address(0)) { + vm.createSelectFork(vm.envString("BASE_SEPOLIA_RPC")); + uint256 counterValueBaseSepolia = Counter(counterInstanceBaseSepolia).counter(); + console.log("Counter value on Base Sepolia: ", counterValueBaseSepolia); + } else { + console.log("Counter not yet deployed on Base Sepolia"); + } + } +} diff --git a/script/counter/WithdrawFeesArbitrumFeesPlug.s.sol b/script/counter/WithdrawFeesArbitrumFeesPlug.s.sol new file mode 100644 index 0000000..580e035 --- /dev/null +++ b/script/counter/WithdrawFeesArbitrumFeesPlug.s.sol @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {Script} from "forge-std/Script.sol"; +import {console} from "forge-std/console.sol"; +import {FeesManager} from "socket-protocol/contracts/protocol/payload-delivery/FeesManager.sol"; +import {ETH_ADDRESS} from "socket-protocol/contracts/protocol/utils/common/Constants.sol"; + +import {CounterAppGateway} from "../../src/counter/CounterAppGateway.sol"; + +// @notice This script is used to withdraw fees from EVMX to Arbitrum Sepolia +// @dev Make sure your app has withdrawFeeTokens() function implemented. You can check its implementation in CounterAppGateway.sol +contract WithdrawFees is Script { + function run() external { + // EVMX Check available fees + vm.createSelectFork(vm.envString("EVMX_RPC")); + FeesManager feesManager = FeesManager(payable(vm.envAddress("FEES_MANAGER"))); + address appGatewayAddress = vm.envAddress("APP_GATEWAY"); + + CounterAppGateway appGateway = CounterAppGateway(appGatewayAddress); + uint256 availableFees = feesManager.getAvailableFees(421614, appGatewayAddress, ETH_ADDRESS); + console.log("Available fees:", availableFees); + + if (availableFees > 0) { + // Switch to Arbitrum Sepolia to get gas price + vm.createSelectFork(vm.envString("ARBITRUM_SEPOLIA_RPC")); + uint256 privateKey = vm.envUint("PRIVATE_KEY"); + address sender = vm.addr(privateKey); + + // Gas price from Arbitrum + uint256 arbitrumGasPrice = block.basefee + 0.1 gwei; // With buffer + uint256 gasLimit = 3_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(vm.envString("EVMX_RPC")); + vm.startBroadcast(privateKey); + console.log("Withdrawing amount:", amountToWithdraw); + appGateway.withdrawFeeTokens(421614, ETH_ADDRESS, amountToWithdraw, sender); + vm.stopBroadcast(); + + // Switch back to Arbitrum Sepolia to check final balance + vm.createSelectFork(vm.envString("ARBITRUM_SEPOLIA_RPC")); + console.log("Final sender balance:", sender.balance); + } else { + console.log("Available fees less than estimated gas cost"); + } + } + } +} diff --git a/script/counter/checkCounters.s.sol b/script/counter/checkCounters.s.sol deleted file mode 100644 index 8d49cfe..0000000 --- a/script/counter/checkCounters.s.sol +++ /dev/null @@ -1,59 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {Script} from "forge-std/Script.sol"; -import {console} from "forge-std/console.sol"; -import {CounterDeployer} from "socket-protocol/contracts/apps/counter/CounterDeployer.sol"; -import {Counter} from "socket-protocol/contracts/apps//counter/Counter.sol"; - -contract CheckCounters is Script { - function run() external { - CounterDeployer deployer = CounterDeployer(vm.envAddress("COUNTER_DEPLOYER")); - - vm.createSelectFork(vm.envString("OFF_CHAIN_VM_RPC")); - address counterInstanceArbitrumSepolia = deployer.getOnChainAddress(deployer.counter(), 421614); - address counterInstanceOptimismSepolia = deployer.getOnChainAddress(deployer.counter(), 11155420); - //address counterInstanceBaseSepolia = deployer.getOnChainAddress(deployer.counter(), 84532); - //address counterInstanceSepolia = deployer.getOnChainAddress( - // deployer.counter(), - // 11155111 - //); - - if (counterInstanceArbitrumSepolia != address(0)) { - vm.createSelectFork(vm.envString("ARBITRUM_SEPOLIA_RPC")); - uint256 counterValueArbitrumSepolia = Counter(counterInstanceArbitrumSepolia).counter(); - console.log("Counter value on Arbitrum Sepolia: ", counterValueArbitrumSepolia); - } else { - console.log("Counter not yet deployed on Arbitrum Sepolia"); - } - - if (counterInstanceOptimismSepolia != address(0)) { - vm.createSelectFork(vm.envString("OPTIMISM_SEPOLIA_RPC")); - uint256 counterValueOptimismSepolia = Counter(counterInstanceOptimismSepolia).counter(); - console.log("Counter value on Optimism Sepolia: ", counterValueOptimismSepolia); - } else { - console.log("Counter not yet deployed on Optimism Sepolia"); - } - - //if (counterInstanceBaseSepolia != address(0)) { - // vm.createSelectFork(vm.envString("BASE_SEPOLIA_RPC")); - // uint256 counterValueBaseSepolia = Counter(counterInstanceBaseSepolia).counter(); - // console.log("Counter value on Base Sepolia: ", counterValueBaseSepolia); - //} else { - // console.log("Counter not yet deployed on Base Sepolia"); - //} - - //if (counterInstanceSepolia != address(0)) { - // vm.createSelectFork(vm.envString("SEPOLIA_RPC")); - // uint256 counterValueOptimismSepolia = Counter( - // counterInstanceOptimismSepolia - // ).counter(); - // console.log( - // "Counter value on Ethereum Sepolia: ", - // counterValueOptimismSepolia - // ); - //} else { - // console.log("Counter not yet deployed on Ethereum Sepolia"); - //} - } -} diff --git a/script/counter/deployCounterOffchain.s.sol b/script/counter/deployCounterOffchain.s.sol deleted file mode 100644 index af47c94..0000000 --- a/script/counter/deployCounterOffchain.s.sol +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {Script} from "forge-std/Script.sol"; -import {console} from "forge-std/console.sol"; -import {CounterAppGateway} from "../../src/apps/counter/CounterAppGateway.sol"; -import {CounterDeployer} from "../../src/apps//counter/CounterDeployer.sol"; -import {FeesData} from "socket-protocol/contracts/common/Structs.sol"; -import {ETH_ADDRESS, FAST} from "socket-protocol/contracts/common/Constants.sol"; - -contract CounterDeploy is Script { - function run() external { - address addressResolver = vm.envAddress("ADDRESS_RESOLVER"); - address auctionManager = vm.envAddress("AUCTION_MANAGER"); - string memory rpc = vm.envString("OFF_CHAIN_VM_RPC"); - vm.createSelectFork(rpc); - - uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); - vm.startBroadcast(deployerPrivateKey); - - // Setting fee payment on Arbitrum Sepolia - FeesData memory feesData = FeesData({feePoolChain: 421614, feePoolToken: ETH_ADDRESS, maxFees: 0.01 ether}); - - CounterDeployer deployer = new CounterDeployer(addressResolver, auctionManager, FAST, feesData); - - CounterAppGateway gateway = new CounterAppGateway(addressResolver, address(deployer), auctionManager, feesData); - - console.log("Contracts deployed:"); - console.log("CounterDeployer:", address(deployer)); - console.log("CounterAppGateway:", address(gateway)); - } -} diff --git a/script/counter/deployCounterOnchain.s.sol b/script/counter/deployCounterOnchain.s.sol deleted file mode 100644 index 05a4728..0000000 --- a/script/counter/deployCounterOnchain.s.sol +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {Script} from "forge-std/Script.sol"; -import {console} from "forge-std/console.sol"; -import {CounterDeployer} from "socket-protocol/contracts/apps//counter/CounterDeployer.sol"; -import {ETH_ADDRESS} from "socket-protocol/contracts/common/Constants.sol"; - -contract CounterDeployOnchain is Script { - function run() external { - string memory rpc = vm.envString("OFF_CHAIN_VM_RPC"); - console.log(rpc); - vm.createSelectFork(rpc); - - uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); - vm.startBroadcast(deployerPrivateKey); - - CounterDeployer deployer = CounterDeployer(vm.envAddress("COUNTER_DEPLOYER")); - - console.log("Counter Deployer:", address(deployer)); - - console.log("Deploying contracts on Arbitrum Sepolia..."); - deployer.deployContracts(421614); - console.log("Deploying contracts on Optimism Sepolia..."); - deployer.deployContracts(11155420); - // console.log("Deploying contracts on Base Sepolia..."); - // deployer.deployContracts(84532); - //console.log("Deploying contracts on Ethereum Sepolia..."); - //deployer.deployContracts(11155111); - } -} diff --git a/script/counter/incrementCounters.s.sol b/script/counter/incrementCounters.s.sol deleted file mode 100644 index c0a1ca5..0000000 --- a/script/counter/incrementCounters.s.sol +++ /dev/null @@ -1,61 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {Script} from "forge-std/Script.sol"; -import {console} from "forge-std/console.sol"; -import {CounterDeployer} from "socket-protocol/contracts/apps//counter/CounterDeployer.sol"; -import {CounterAppGateway} from "socket-protocol/contracts/apps//counter/CounterAppGateway.sol"; - -contract IncrementCounters is Script { - function run() external { - string memory socketRPC = vm.envString("OFF_CHAIN_VM_RPC"); - uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); - - vm.createSelectFork(socketRPC); - - CounterDeployer deployer = CounterDeployer(vm.envAddress("COUNTER_DEPLOYER")); - CounterAppGateway gateway = CounterAppGateway(vm.envAddress("COUNTER_APP_GATEWAY")); - - address counterForwarderArbitrumSepolia = deployer.forwarderAddresses(deployer.counter(), 421614); - address counterForwarderOptimismSepolia = deployer.forwarderAddresses(deployer.counter(), 11155420); - //address counterForwarderBaseSepolia = deployer.forwarderAddresses(deployer.counter(), 84532); - //address counterForwarderSepolia = deployer.forwarderAddresses(deployer.counter(), 11155111); - - // Count non-zero addresses - uint256 nonZeroCount = 0; - if (counterForwarderArbitrumSepolia != address(0)) nonZeroCount++; - if (counterForwarderOptimismSepolia != address(0)) nonZeroCount++; - //if (counterForwarderBaseSepolia != address(0)) nonZeroCount++; - //if (counterForwarderSepolia != address(0)) nonZeroCount++; - - address[] memory instances = new address[](nonZeroCount); - uint256 index = 0; - if (counterForwarderArbitrumSepolia != address(0)) { - instances[index] = counterForwarderArbitrumSepolia; - index++; - } else { - console.log("Arbitrum Sepolia forwarder not yet deployed"); - } - if (counterForwarderOptimismSepolia != address(0)) { - instances[index] = counterForwarderOptimismSepolia; - index++; - } else { - console.log("Optimism Sepolia forwarder not yet deployed"); - } - //if (counterForwarderBaseSepolia != address(0)) { - // instances[index] = counterForwarderBaseSepolia; - // index++; - //} else { - // console.log("Base Sepolia forwarder not yet deployed"); - //} - //if (counterForwarderSepolia != address(0)) { - // instances[index] = counterForwarderSepolia; - // index++; - //} else { - // console.log("Ethereum Sepolia forwarder not yet deployed"); - //} - - vm.startBroadcast(deployerPrivateKey); - gateway.incrementCounters(instances); - } -} diff --git a/script/helpers/AppGatewayFeeBalance.s.sol b/script/helpers/AppGatewayFeeBalance.s.sol new file mode 100644 index 0000000..71c29d4 --- /dev/null +++ b/script/helpers/AppGatewayFeeBalance.s.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {Script} from "forge-std/Script.sol"; +import {console} from "forge-std/console.sol"; +import {FeesManager} from "socket-protocol/contracts/protocol/payload-delivery/FeesManager.sol"; +import {Fees} from "socket-protocol/contracts/protocol/utils/common/Structs.sol"; +import {ETH_ADDRESS} from "socket-protocol/contracts/protocol/utils/common/Constants.sol"; + +contract CheckDepositedFees is Script { + function run() external { + vm.createSelectFork(vm.envString("EVMX_RPC")); + FeesManager feesManager = FeesManager(payable(vm.envAddress("FEES_MANAGER"))); + address appGateway = vm.envAddress("APP_GATEWAY"); + + (uint256 deposited, uint256 blocked) = feesManager.appGatewayFeeBalances(appGateway, 421614, ETH_ADDRESS); + console.log("AppGateway:", appGateway); + console.log("Deposited fees:", deposited); + console.log("Blocked fees:", blocked); + + uint256 availableFees = feesManager.getAvailableFees(421614, appGateway, ETH_ADDRESS); + console.log("Available fees:", availableFees); + } +} diff --git a/script/helpers/CheckAppEVMxLimits.s.sol b/script/helpers/CheckAppEVMxLimits.s.sol new file mode 100644 index 0000000..03072cb --- /dev/null +++ b/script/helpers/CheckAppEVMxLimits.s.sol @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.13; + +import "forge-std/Script.sol"; +import {WatcherPrecompile} from "socket-protocol/contracts/protocol/watcherPrecompile/WatcherPrecompile.sol"; +import {LimitParams} from "socket-protocol/contracts/protocol/utils/common/Structs.sol"; +import {SCHEDULE, QUERY, FINALIZE} from "socket-protocol/contracts/protocol/utils/common/Constants.sol"; + +contract CheckLimitsScript is Script { + function run() external { + string memory rpc = vm.envString("EVMX_RPC"); + vm.createSelectFork(rpc); + + address watcherPrecompile = vm.envAddress("WATCHER_PRECOMPILE"); + address appGateway = vm.envAddress("APP_GATEWAY"); + + console.log("WatcherPrecompile address:", watcherPrecompile); + console.log("AppGateway address:", appGateway); + WatcherPrecompile watcherContract = WatcherPrecompile(watcherPrecompile); + + LimitParams memory scheduleLimit = watcherContract.getLimitParams(SCHEDULE, appGateway); + LimitParams memory queryLimit = watcherContract.getLimitParams(QUERY, appGateway); + LimitParams memory finalizeLimit = watcherContract.getLimitParams(FINALIZE, appGateway); + + uint256 scheduleCurrentLimit = watcherContract.getCurrentLimit(SCHEDULE, appGateway); + uint256 queryCurrentLimit = watcherContract.getCurrentLimit(QUERY, appGateway); + uint256 finalizeCurrentLimit = watcherContract.getCurrentLimit(FINALIZE, appGateway); + + console.log("Schedule max limit:"); + console.log(scheduleLimit.maxLimit); + console.log("Schedule rate per second:"); + console.log(scheduleLimit.ratePerSecond); + console.log("Schedule current limit:"); + console.log(scheduleCurrentLimit); + + console.log("Query max limit:"); + console.log(queryLimit.maxLimit); + console.log("Query rate per second:"); + console.log(queryLimit.ratePerSecond); + console.log("Query current limit:"); + console.log(queryCurrentLimit); + + console.log("Finalize max limit:"); + console.log(finalizeLimit.maxLimit); + console.log("Finalize rate per second:"); + console.log(finalizeLimit.ratePerSecond); + console.log("Finalize current limit:"); + console.log(finalizeCurrentLimit); + } +} diff --git a/script/helpers/PayFeesInArbitrumETH.s.sol b/script/helpers/PayFeesInArbitrumETH.s.sol new file mode 100644 index 0000000..247c718 --- /dev/null +++ b/script/helpers/PayFeesInArbitrumETH.s.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {Script} from "forge-std/Script.sol"; +import {console} from "forge-std/console.sol"; +import {FeesPlug} from "socket-protocol/contracts/protocol/payload-delivery/FeesPlug.sol"; +import {Fees} from "socket-protocol/contracts/protocol/utils/common/Structs.sol"; +import {ETH_ADDRESS} from "socket-protocol/contracts/protocol/utils/common/Constants.sol"; + +contract DepositFees is Script { + function run() external { + vm.createSelectFork(vm.envString("ARBITRUM_SEPOLIA_RPC")); + + uint256 privateKey = vm.envUint("PRIVATE_KEY"); + vm.startBroadcast(privateKey); + FeesPlug feesPlug = FeesPlug(payable(vm.envAddress("ARBITRUM_FEES_PLUG"))); + address appGateway = vm.envAddress("APP_GATEWAY"); + + address sender = vm.addr(privateKey); + console.log("Sender address:", sender); + uint256 balance = sender.balance; + console.log("Sender balance in wei:", balance); + + uint256 feesAmount = 0.001 ether; + feesPlug.deposit{value: feesAmount}(ETH_ADDRESS, appGateway, feesAmount); + console.log("Added %s wei for AppGateway %s", feesAmount, appGateway); + } +} diff --git a/script/transactionStatus.js b/script/transactionStatus.js index 7680d5b..42eb3aa 100644 --- a/script/transactionStatus.js +++ b/script/transactionStatus.js @@ -1,6 +1,7 @@ const fs = require('fs'); const path = require('path'); +const chainId = 43; // Read script name from command-line arguments const scriptName = process.argv[2]; // The argument passed to the script if (!scriptName) { @@ -13,7 +14,7 @@ if (!scriptName) { const jsonFilePath = path.join( 'broadcast', `${scriptName}.s.sol`, - '7625382', + `${chainId}`, 'run-latest.json' ); @@ -30,7 +31,7 @@ const jsonData = JSON.parse(fs.readFileSync(jsonFilePath, 'utf-8')); const transactions = jsonData.transactions.map(tx => tx.hash); console.log(`Found ${transactions.length} transactions to process.`); -const apiUrl = 'https://apiv2.dev.socket.tech/getDetailsByTxHash?txHash='; +const apiUrl = ' https://api-evmx-devnet.socket.tech/getDetailsByTxHash?txHash='; let intervalId; // Track statuses for each hash @@ -97,27 +98,31 @@ const checkTransactionStatus = async () => { const transactionResponse = data.response[0]; // First response object const status = transactionResponse.status || 'UNKNOWN'; - const payloads = transactionResponse.payloads || []; + const writePayloads = transactionResponse.writePayloads || []; // Update tracker tx.status = status; if (status === 'COMPLETED' && !tx.printed) { - processMultiplePayloads(payloads, tx); + processMultiplePayloads(writePayloads, tx); - const deployerDetails = payloads[0].deployerDetails || {}; + const deployerDetails = writePayloads[0].deployerDetails || {}; if (Object.keys(deployerDetails).length !== 0) { - console.log(`Hash: ${tx.hash}, Status: ${status}, ChainId: ${payloads[0].chainSlug}`); + console.log(`Hash: ${tx.hash}, Status: ${status}, ChainId: ${writePayloads[0].chainSlug}`); console.log(`OnChainAddress: ${deployerDetails.onChainAddress}`); console.log(`ForwarderAddress: ${deployerDetails.forwarderAddress}`); + if (deployerDetails.isForwarderDeployed !== true) { + console.error(`ERROR: ForwarderAddress NOT deployed. Please reach out to the SOCKET team.`); + process.exit(1); + } } else { - console.log(`Hash: ${tx.hash}, Status: ${status}, ChainId: 7625382`); + console.log(`Hash: ${tx.hash}, Status: ${status}, ChainId: ${chainId}`); } tx.printed = true; } else if (status === 'IN_PROGRESS') { - processMultiplePayloads(payloads, tx); + processMultiplePayloads(writePayloads, tx); } } else { console.error(`Invalid or empty response for hash: ${tx.hash}`); diff --git a/script/update-socket-protocol-commit.sh b/script/update-socket-protocol-commit.sh new file mode 100644 index 0000000..0336997 --- /dev/null +++ b/script/update-socket-protocol-commit.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +# Check for modified or staged files, but ignore untracked files +if [[ -n $(git status --porcelain | grep '^[ MRAUCD]') ]]; then + echo "Error: You have modified or staged files. Commit or stash them before running this script." + exit 1 +fi + +# Nuke the submodule +git submodule deinit -f lib/socket-protocol +rm -rf .git/modules/lib/socket-protocol +git rm -rf lib/socket-protocol + +# Re-add the submodule +git submodule add -b master https://github.com/SocketDotTech/socket-protocol.git lib/socket-protocol +git submodule update --init --recursive + +# Commit the update +git commit -m "Update socket-protocol submodule" + +echo "SOCKET Protocol submodule updated successfully!" diff --git a/src/apps/counter/Counter.sol b/src/apps/counter/Counter.sol deleted file mode 100644 index da7b45d..0000000 --- a/src/apps/counter/Counter.sol +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity >=0.7.0 <0.9.0; - -import "socket-protocol/contracts/utils/OwnableTwoStep.sol"; -import "socket-protocol/contracts/base/PlugBase.sol"; - -contract Counter is OwnableTwoStep, PlugBase { - uint256 public counter; - - constructor() PlugBase(msg.sender) { - _claimOwner(msg.sender); - } - - function increase() external onlySocket { - counter++; - } - - function connectSocket(address appGateway_, address socket_, address switchboard_) external onlyOwner { - _claimOwner(socket_); - _connectSocket(appGateway_, socket_, switchboard_); - } -} diff --git a/src/apps/counter/CounterAppGateway.sol b/src/apps/counter/CounterAppGateway.sol deleted file mode 100644 index 2afe142..0000000 --- a/src/apps/counter/CounterAppGateway.sol +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity >=0.7.0 <0.9.0; - -import "socket-protocol/contracts/base/AppGatewayBase.sol"; -import "./Counter.sol"; - -contract CounterAppGateway is AppGatewayBase { - constructor(address addressResolver_, address deployerContract_, address auctionManager_, FeesData memory feesData_) - AppGatewayBase(addressResolver_, auctionManager_) - { - addressResolver__.setContractsToGateways(deployerContract_); - _setFeesData(feesData_); - } - - function incrementCounters(address[] memory instances_) public async { - // the increase function is called on given list of instances - // this - for (uint256 i = 0; i < instances_.length; i++) { - Counter(instances_[i]).increase(); - } - } - - function setFees(FeesData memory feesData_) public { - feesData = feesData_; - } - - function withdrawFeeTokens(uint32 chainSlug_, address token_, uint256 amount_, address receiver_) external { - _withdrawFeeTokens(chainSlug_, token_, amount_, receiver_); - } -} diff --git a/src/apps/counter/CounterDeployer.sol b/src/apps/counter/CounterDeployer.sol deleted file mode 100644 index 5115ab4..0000000 --- a/src/apps/counter/CounterDeployer.sol +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity >=0.7.0 <0.9.0; - -import "./Counter.sol"; -import "socket-protocol/contracts/base/AppDeployerBase.sol"; -import "socket-protocol/contracts/utils/OwnableTwoStep.sol"; - -contract CounterDeployer is AppDeployerBase, OwnableTwoStep { - bytes32 public counter = _createContractId("counter"); - - constructor(address addressResolver_, address auctionManager_, bytes32 sbType_, FeesData memory feesData_) - AppDeployerBase(addressResolver_, auctionManager_, sbType_) - { - creationCodeWithArgs[counter] = abi.encodePacked(type(Counter).creationCode); - _setFeesData(feesData_); - _claimOwner(msg.sender); - } - - function deployContracts(uint32 chainSlug_) external async { - _deploy(counter, chainSlug_); - } - - function initialize(uint32) public pure override { - return; - } - - function setFees(FeesData memory feesData_) public { - feesData = feesData_; - } -} diff --git a/src/counter/Counter.sol b/src/counter/Counter.sol new file mode 100644 index 0000000..fe7e616 --- /dev/null +++ b/src/counter/Counter.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.7.0 <0.9.0; + +import "solady/auth/Ownable.sol"; +import "socket-protocol/contracts/base/PlugBase.sol"; + +contract Counter is Ownable, PlugBase { + uint256 public counter; + + function increase() external onlySocket { + counter++; + } + + function getCounter() external view returns (uint256) { + return counter; + } + + function increaseOnGateway(uint256 value_) external returns (bytes32) { + return _callAppGateway(abi.encode(value_), bytes32(0)); + } +} diff --git a/src/counter/CounterAppGateway.sol b/src/counter/CounterAppGateway.sol new file mode 100644 index 0000000..3ded573 --- /dev/null +++ b/src/counter/CounterAppGateway.sol @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.7.0 <0.9.0; + +import "socket-protocol/contracts/base/AppGatewayBase.sol"; +import "socket-protocol/contracts/interfaces/IForwarder.sol"; +import "socket-protocol/contracts/interfaces/IPromise.sol"; +import "./Counter.sol"; +import "./ICounter.sol"; + +contract CounterAppGateway is AppGatewayBase, Ownable { + bytes32 public counter = _createContractId("counter"); + bytes32 public counter1 = _createContractId("counter1"); + + uint256 public counterVal; + + uint256 arbCounter; + uint256 optCounter; + + event TimeoutResolved(uint256 creationTimestamp, uint256 executionTimestamp); + + constructor(address addressResolver_, Fees memory fees_) AppGatewayBase(addressResolver_) { + creationCodeWithArgs[counter] = abi.encodePacked(type(Counter).creationCode); + creationCodeWithArgs[counter1] = abi.encodePacked(type(Counter).creationCode); + _setOverrides(fees_); + _initializeOwner(msg.sender); + } + + // deploy contracts + function deployContracts(uint32 chainSlug_) external async { + _deploy(counter, chainSlug_, IsPlug.YES); + } + + function deployParallelContracts(uint32 chainSlug_) external async { + _setOverrides(Parallel.ON); + _deploy(counter, chainSlug_, IsPlug.YES); + _deploy(counter1, chainSlug_, IsPlug.YES); + _setOverrides(Parallel.OFF); + } + + function deployMultiChainContracts(uint32[] memory chainSlugs_) external async { + _setOverrides(Parallel.ON); + for (uint32 i = 0; i < chainSlugs_.length; i++) { + _deploy(counter, chainSlugs_[i], IsPlug.YES); + _deploy(counter1, chainSlugs_[i], IsPlug.YES); + } + _setOverrides(Parallel.OFF); + } + + function initialize(uint32) public pure override { + return; + } + + function incrementCounters(address[] memory instances_) public async { + // the increase function is called on given list of instances + // this + for (uint256 i = 0; i < instances_.length; i++) { + ICounter(instances_[i]).increase(); + } + } + + // for testing purposes + function incrementCountersWithoutAsync(address[] memory instances_) public { + // the increase function is called on given list of instances + for (uint256 i = 0; i < instances_.length; i++) { + Counter(instances_[i]).increase(); + } + } + + function readCounters(address[] memory instances_) public async { + // the increase function is called on given list of instances + _setOverrides(Read.ON, Parallel.ON); + for (uint256 i = 0; i < instances_.length; i++) { + uint32 chainSlug = IForwarder(instances_[i]).getChainSlug(); + ICounter(instances_[i]).getCounter(); + IPromise(instances_[i]).then(this.setCounterValues.selector, abi.encode(chainSlug)); + } + _setOverrides(Read.OFF, Parallel.OFF); + ICounter(instances_[0]).increase(); + } + + function setCounterValues(bytes memory data, bytes memory returnData) external onlyPromises { + uint256 counterValue = abi.decode(returnData, (uint256)); + uint32 chainSlug = abi.decode(data, (uint32)); + if (chainSlug == 421614) { + arbCounter = counterValue; + } else if (chainSlug == 11155420) { + optCounter = counterValue; + } + } + + // INBOX + function setIsValidPlug(uint32 chainSlug_, address plug_) public { + watcherPrecompile__().setIsValidPlug(chainSlug_, plug_, true); + } + + function callFromChain(uint32, address, bytes calldata payload_, bytes32) external override onlyWatcherPrecompile { + uint256 value = abi.decode(payload_, (uint256)); + counterVal += value; + } + + // TIMEOUT + function setTimeout(uint256 delayInSeconds_) public { + bytes memory payload = abi.encodeWithSelector(this.resolveTimeout.selector, block.timestamp); + watcherPrecompile__().setTimeout(address(this), payload, delayInSeconds_); + } + + function resolveTimeout(uint256 creationTimestamp_) external onlyWatcherPrecompile { + emit TimeoutResolved(creationTimestamp_, block.timestamp); + } + + // UTILS + 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/counter/ICounter.sol b/src/counter/ICounter.sol new file mode 100644 index 0000000..6e25497 --- /dev/null +++ b/src/counter/ICounter.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.7.0 <0.9.0; + +interface ICounter { + function increase() external; + + function getCounter() external; +} diff --git a/test/apps/Counter.t.sol b/test/apps/Counter.t.sol index b2a25be..6d27808 100644 --- a/test/apps/Counter.t.sol +++ b/test/apps/Counter.t.sol @@ -1,9 +1,8 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.21; -import {CounterAppGateway} from "socket-protocol/contracts/apps/counter/CounterAppGateway.sol"; -import {CounterDeployer} from "socket-protocol/contracts/apps/counter/CounterDeployer.sol"; -import {Counter} from "socket-protocol/contracts/apps/counter/Counter.sol"; +import {CounterAppGateway} from "../../src/counter/CounterAppGateway.sol"; +import {Counter} from "../../src/counter/Counter.sol"; import "socket-protocol/test/DeliveryHelper.t.sol"; contract CounterTest is DeliveryHelperTest { @@ -13,32 +12,26 @@ contract CounterTest is DeliveryHelperTest { bytes32[] contractIds = new bytes32[](1); CounterAppGateway counterGateway; - CounterDeployer counterDeployer; function deploySetup() internal { setUpDeliveryHelper(); - counterDeployer = - new CounterDeployer(address(addressResolver), address(auctionManager), FAST, createFeesData(feesAmount)); + counterGateway = new CounterAppGateway(address(addressResolver), createFees(feesAmount)); + depositFees(address(counterGateway), createFees(1 ether)); - counterGateway = new CounterAppGateway( - address(addressResolver), address(counterDeployer), address(auctionManager), createFeesData(feesAmount) - ); - setLimit(address(counterGateway)); - - counterId = counterDeployer.counter(); + counterId = counterGateway.counter(); contractIds[0] = counterId; } function deployCounterApp(uint32 chainSlug) internal returns (bytes32 asyncId) { - asyncId = _deploy(contractIds, chainSlug, 1, IAppDeployer(counterDeployer), address(counterGateway)); + asyncId = _deploy(contractIds, chainSlug, 1, IAppGateway(counterGateway)); } function testCounterDeployment() external { deploySetup(); deployCounterApp(arbChainSlug); - (address onChain, address forwarder) = getOnChainAndForwarderAddresses(arbChainSlug, counterId, counterDeployer); + (address onChain, address forwarder) = getOnChainAndForwarderAddresses(arbChainSlug, counterId, counterGateway); assertEq(IForwarder(forwarder).getChainSlug(), arbChainSlug, "Forwarder chainSlug should be correct"); assertEq(IForwarder(forwarder).getOnChainAddress(), onChain, "Forwarder onChainAddress should be correct"); @@ -49,7 +42,7 @@ contract CounterTest is DeliveryHelperTest { deployCounterApp(arbChainSlug); (address arbCounter, address arbCounterForwarder) = - getOnChainAndForwarderAddresses(arbChainSlug, counterId, counterDeployer); + getOnChainAndForwarderAddresses(arbChainSlug, counterId, counterGateway); uint256 arbCounterBefore = Counter(arbCounter).counter(); @@ -61,15 +54,15 @@ contract CounterTest is DeliveryHelperTest { assertEq(Counter(arbCounter).counter(), arbCounterBefore + 1); } - function testCounterIncrementMultipleChains() external { + function testCounterIncrementMultipleChains() public { deploySetup(); deployCounterApp(arbChainSlug); deployCounterApp(optChainSlug); (address arbCounter, address arbCounterForwarder) = - getOnChainAndForwarderAddresses(arbChainSlug, counterId, counterDeployer); + getOnChainAndForwarderAddresses(arbChainSlug, counterId, counterGateway); (address optCounter, address optCounterForwarder) = - getOnChainAndForwarderAddresses(optChainSlug, counterId, counterDeployer); + getOnChainAndForwarderAddresses(optChainSlug, counterId, counterGateway); uint256 arbCounterBefore = Counter(arbCounter).counter(); uint256 optCounterBefore = Counter(optCounter).counter(); @@ -83,7 +76,37 @@ contract CounterTest is DeliveryHelperTest { chains[0] = arbChainSlug; chains[1] = optChainSlug; _executeWriteBatchMultiChain(chains); + assertEq(Counter(arbCounter).counter(), arbCounterBefore + 1); assertEq(Counter(optCounter).counter(), optCounterBefore + 1); } + + function testCounterReadMultipleChains() external { + testCounterIncrementMultipleChains(); + + (address arbCounter, address arbCounterForwarder) = + getOnChainAndForwarderAddresses(arbChainSlug, counterId, counterGateway); + (address optCounter, address optCounterForwarder) = + getOnChainAndForwarderAddresses(optChainSlug, counterId, counterGateway); + + address[] memory instances = new address[](2); + instances[0] = arbCounterForwarder; + instances[1] = optCounterForwarder; + + bytes32 bridgeAsyncId = getNextAsyncId(); + + bytes32[] memory payloadIds = new bytes32[](3); + payloadIds[0] = _encodeId(evmxSlug, address(watcherPrecompile), payloadIdCounter++); + payloadIds[1] = _encodeId(evmxSlug, address(watcherPrecompile), payloadIdCounter++); + + payloadIds[2] = + getWritePayloadId(arbChainSlug, address(getSocketConfig(arbChainSlug).switchboard), payloadIdCounter++); + + counterGateway.readCounters(instances); + + bidAndEndAuction(bridgeAsyncId); + finalizeQuery(payloadIds[0], abi.encode(Counter(arbCounter).counter())); + finalizeQuery(payloadIds[1], abi.encode(Counter(optCounter).counter())); + finalizeAndExecute(payloadIds[2]); + } }