From 4fc8161decaca91f92cf0e93d20dc40cf43dc7f8 Mon Sep 17 00:00:00 2001 From: Rookmate <14072042+rookmate@users.noreply.github.com> Date: Tue, 3 Jun 2025 18:29:59 +0100 Subject: [PATCH 01/15] Update socket-protocol submodule to latest dev --- .gitmodules | 2 +- lib/socket-protocol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 05d66fc..6995c1a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,4 @@ [submodule "lib/socket-protocol"] path = lib/socket-protocol url = https://github.com/SocketDotTech/socket-protocol.git - branch = master + branch = dev diff --git a/lib/socket-protocol b/lib/socket-protocol index 38accd5..dc173ae 160000 --- a/lib/socket-protocol +++ b/lib/socket-protocol @@ -1 +1 @@ -Subproject commit 38accd5f8a4144297048940122d56a08578c1783 +Subproject commit dc173aea1bfcec23d39c16b9e1ec43333f7fba72 From 4f569b7d8fa1ba0a5e2052422ec8dd5b6c67e6b8 Mon Sep 17 00:00:00 2001 From: Rookmate <14072042+rookmate@users.noreply.github.com> Date: Wed, 4 Jun 2025 13:14:08 +0100 Subject: [PATCH 02/15] chore: update for new devnet --- .env.sample | 13 ++++++--- .../WithdrawFeesArbitrumFeesPlug.s.sol | 11 ++++---- script/helpers/AppGatewayFeeBalance.s.sol | 2 +- src/counter/CounterAppGateway.sol | 13 ++++----- test/apps/Counter.t.sol | 27 ++++++++----------- 5 files changed, 33 insertions(+), 33 deletions(-) diff --git a/.env.sample b/.env.sample index 5caa12b..03b17df 100644 --- a/.env.sample +++ b/.env.sample @@ -1,17 +1,22 @@ # RPCs EVMX_RPC="https://rpc-evmx-devnet.socket.tech/" + SEPOLIA_RPC="https://ethereum-sepolia-rpc.publicnode.com" ARBITRUM_SEPOLIA_RPC="https://sepolia-rollup.arbitrum.io/rpc" OPTIMISM_SEPOLIA_RPC="https://sepolia.optimism.io" BASE_SEPOLIA_RPC="https://sepolia.base.org" +ARBITRUM_RPC="https://arbitrum.drpc.org" +OPTIMISM_RPC="https://optimism.drpc.org" +BASE_RPC="https://base.drpc.org" + # EVMx key addresses # Find the most up to date addresses at: # https://github.com/SocketDotTech/socket-protocol/blob/master/deployments/stage_addresses.json -ADDRESS_RESOLVER="0x21a9AFDfbEb0399D4a12f3AA1324042Be2B57F8e" -FEES_MANAGER="0x30e07016eB24570629Bc8765CA307394Af90B27C" -ARBITRUM_FEES_PLUG="0xDfE94B9b14de382Ed13C8A7F387884808D0f7E0b" -ARBITRUM_TEST_USDC="0xa03Cbf13f331aF7c0fD7F2E28E6Cbc13F879E3F3" +ADDRESS_RESOLVER="0x935b06902cA5C8bb4C76e18738561c294D377A93" +FEES_MANAGER="0xA07208F9e7aE243F922317ab6604DC9F86822406" +ARBITRUM_FEES_PLUG="0xee1Aef0b06f63Aa1c881838794Dd0876462c2B0d" +ARBITRUM_USDC="0xaf88d065e77c8cC2239327C5EDb3A432268e5831" # Add your deployer private key here # or remove it from this file if it is already an env var diff --git a/script/counter/WithdrawFeesArbitrumFeesPlug.s.sol b/script/counter/WithdrawFeesArbitrumFeesPlug.s.sol index 7b35584..306073b 100644 --- a/script/counter/WithdrawFeesArbitrumFeesPlug.s.sol +++ b/script/counter/WithdrawFeesArbitrumFeesPlug.s.sol @@ -3,8 +3,7 @@ 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/evmx/payload-delivery/FeesManager.sol"; -import {TestUSDC} from "socket-protocol/contracts/evmx/helpers/TestUSDC.sol"; +import {FeesManager} from "socket-protocol/contracts/evmx/fees/FeesManager.sol"; import {CounterAppGateway} from "../../src/counter/CounterAppGateway.sol"; @@ -35,10 +34,10 @@ contract WithdrawFees is Script { vm.createSelectFork(vm.envString("EVMX_RPC")); FeesManager feesManager = FeesManager(payable(vm.envAddress("FEES_MANAGER"))); address appGatewayAddress = vm.envAddress("APP_GATEWAY"); - TestUSDC testUSDCContract = TestUSDC(vm.envAddress("ARBITRUM_TEST_USDC")); + address token = vm.envAddress("USDC"); CounterAppGateway appGateway = CounterAppGateway(appGatewayAddress); - uint256 availableFees = feesManager.getMaxCreditsAvailableForWithdraw(appGatewayAddress); + uint256 availableFees = feesManager.getAvailableCredits(appGatewayAddress); console.log("Available fees:", availableFees); if (availableFees > 0) { @@ -49,7 +48,7 @@ contract WithdrawFees is Script { // Gas price from Arbitrum uint256 arbitrumGasPrice = block.basefee + 0.1 gwei; // With buffer - uint256 gasLimit = 50_000_000_000; // Estimate + uint256 gasLimit = 5_000_000; // Estimate uint256 estimatedGasCost = gasLimit * arbitrumGasPrice; console.log("Arbitrum gas price (wei):", arbitrumGasPrice); @@ -64,7 +63,7 @@ contract WithdrawFees is Script { vm.createSelectFork(vm.envString("EVMX_RPC")); vm.startBroadcast(privateKey); console.log("Withdrawing amount:", amountToWithdraw); - appGateway.withdrawFeeTokens(421614, address(testUSDCContract), amountToWithdraw, sender); + appGateway.withdrawCredits(421614, token, amountToWithdraw, sender); vm.stopBroadcast(); } else { console.log("Available fees less than estimated gas cost"); diff --git a/script/helpers/AppGatewayFeeBalance.s.sol b/script/helpers/AppGatewayFeeBalance.s.sol index b1bb48e..1ab2e39 100644 --- a/script/helpers/AppGatewayFeeBalance.s.sol +++ b/script/helpers/AppGatewayFeeBalance.s.sol @@ -3,7 +3,7 @@ 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/evmx/payload-delivery/FeesManager.sol"; +import {FeesManager} from "socket-protocol/contracts/evmx/fees/FeesManager.sol"; contract CheckDepositedFees is Script { function run() external { diff --git a/src/counter/CounterAppGateway.sol b/src/counter/CounterAppGateway.sol index b7c8798..dc53e0b 100644 --- a/src/counter/CounterAppGateway.sol +++ b/src/counter/CounterAppGateway.sol @@ -29,10 +29,11 @@ contract CounterAppGateway is AppGatewayBase, Ownable { * @param addressResolver_ Address of the SOCKET Protocol's AddressResolver contract * @param fees_ Fee configuration for multi-chain operations */ - constructor(address addressResolver_, uint256 fees_) AppGatewayBase(addressResolver_) { + constructor(address addressResolver_, uint256 fees_) { creationCodeWithArgs[counter] = abi.encodePacked(type(Counter).creationCode); _setMaxFees(fees_); _initializeOwner(msg.sender); + _initializeAppGateway(addressResolver_); } /** @@ -42,7 +43,7 @@ contract CounterAppGateway is AppGatewayBase, Ownable { * https://docs.socket.tech/writing-apps#onchain-contract-deployment-with-the-appgateway-contract * @param chainSlug_ The identifier of the target chain */ - function deployContracts(uint32 chainSlug_) external async(bytes("")) { + function deployContracts(uint32 chainSlug_) external async { _deploy(counter, chainSlug_, IsPlug.YES); } @@ -53,7 +54,7 @@ contract CounterAppGateway is AppGatewayBase, Ownable { * For more information on the initialize function, see: * https://docs.socket.tech/deploy#initialize */ - function initialize(uint32 /* chainSlug_ */ ) public pure override { + function initializeOnChain(uint32 /* chainSlug_ */ ) public pure override { return; } @@ -62,7 +63,7 @@ contract CounterAppGateway is AppGatewayBase, Ownable { * @dev Calls the increase function on each counter instance provided * @param instances_ Array of counter contract addresses to increment */ - function incrementCounters(address[] memory instances_) public async(bytes("")) { + function incrementCounters(address[] memory instances_) public async { for (uint256 i = 0; i < instances_.length; i++) { ICounter(instances_[i]).increase(); } @@ -85,7 +86,7 @@ contract CounterAppGateway is AppGatewayBase, Ownable { * @param amount_ The amount to withdraw * @param receiver_ The address that will receive the withdrawn fees */ - function withdrawFeeTokens(uint32 chainSlug_, address token_, uint256 amount_, address receiver_) external { - _withdrawFeeTokens(chainSlug_, token_, amount_, receiver_); + function withdrawCredits(uint32 chainSlug_, address token_, uint256 amount_, address receiver_) external { + _withdrawCredits(chainSlug_, token_, amount_, receiver_); } } diff --git a/test/apps/Counter.t.sol b/test/apps/Counter.t.sol index 066c298..da1327e 100644 --- a/test/apps/Counter.t.sol +++ b/test/apps/Counter.t.sol @@ -3,35 +3,32 @@ pragma solidity ^0.8.21; import {CounterAppGateway} from "../../src/counter/CounterAppGateway.sol"; import {Counter} from "../../src/counter/Counter.sol"; -import "socket-protocol/test/DeliveryHelper.t.sol"; +import "socket-protocol/test/SetupTest.t.sol"; -contract CounterTest is DeliveryHelperTest { +contract CounterTest is AppGatewayBaseSetup { uint256 feesAmount = 0.01 ether; bytes32 counterId; bytes32[] contractIds = new bytes32[](1); - CounterAppGateway counterGateway; - function deploySetup() internal { - setUpDeliveryHelper(); + event CounterScheduleResolved(uint256 creationTimestamp, uint256 executionTimestamp); - counterGateway = new CounterAppGateway(address(addressResolver), feesAmount); - depositUSDCFees( - address(counterGateway), - OnChainFees({chainSlug: arbChainSlug, token: address(arbConfig.feesTokenUSDC), amount: 1 ether}) - ); + function setUp() public { + deploy(); + counterGateway = new CounterAppGateway(address(addressResolver), feesAmount); + depositNativeAndCredits(arbChainSlug, 1 ether, 0, address(counterGateway)); counterId = counterGateway.counter(); contractIds[0] = counterId; } function deployCounterApp(uint32 chainSlug) internal returns (uint40 requestCount) { - requestCount = _deploy(chainSlug, counterGateway, contractIds); + counterGateway.deployContracts(chainSlug); + requestCount = executeDeploy(counterGateway, chainSlug, contractIds); } function testCounterDeployment() external { - deploySetup(); deployCounterApp(arbChainSlug); (address onChain, address forwarder) = getOnChainAndForwarderAddresses(arbChainSlug, counterId, counterGateway); @@ -41,7 +38,6 @@ contract CounterTest is DeliveryHelperTest { } function testCounterIncrement() external { - deploySetup(); deployCounterApp(arbChainSlug); (address arbCounter, address arbCounterForwarder) = @@ -52,13 +48,12 @@ contract CounterTest is DeliveryHelperTest { address[] memory instances = new address[](1); instances[0] = arbCounterForwarder; counterGateway.incrementCounters(instances); - executeRequest(new bytes[](0)); + executeRequest(); assertEq(Counter(arbCounter).counter(), arbCounterBefore + 1); } function testCounterIncrementMultipleChains() public { - deploySetup(); deployCounterApp(arbChainSlug); deployCounterApp(optChainSlug); @@ -79,7 +74,7 @@ contract CounterTest is DeliveryHelperTest { chains[0] = arbChainSlug; chains[1] = optChainSlug; - executeRequest(new bytes[](0)); + executeRequest(); assertEq(Counter(arbCounter).counter(), arbCounterBefore + 1); assertEq(Counter(optCounter).counter(), optCounterBefore + 1); } From 9e861468d58ff5a67f2f22435f9f6b660d4ca4d1 Mon Sep 17 00:00:00 2001 From: Rookmate <14072042+rookmate@users.noreply.github.com> Date: Wed, 4 Jun 2025 13:40:54 +0100 Subject: [PATCH 03/15] fix: deposit USDC for EVMx credits --- script/helpers/DepositCreditAndNative.s.sol | 41 +++++++++++++++++++ .../helpers/PayFeesInArbitrumTestUSDC.s.sol | 36 ---------------- 2 files changed, 41 insertions(+), 36 deletions(-) create mode 100644 script/helpers/DepositCreditAndNative.s.sol delete mode 100644 script/helpers/PayFeesInArbitrumTestUSDC.s.sol diff --git a/script/helpers/DepositCreditAndNative.s.sol b/script/helpers/DepositCreditAndNative.s.sol new file mode 100644 index 0000000..6458fc5 --- /dev/null +++ b/script/helpers/DepositCreditAndNative.s.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: GPL-3.0-only +pragma solidity ^0.8.21; + +import {Script} from "forge-std/Script.sol"; +import {console} from "forge-std/console.sol"; +import {FeesPlug} from "socket-protocol/contracts/evmx/plugs/FeesPlug.sol"; +// source .env && forge script script/helpers/DepositCreditAndNative.s.sol --broadcast --skip-simulation + +interface IERC20 { + function approve(address spender, uint256 value) external returns (bool); + function balanceOf(address account) external view returns (uint256); +} + +contract DepositCredit is Script { + function run() external { + uint256 feesAmount = 1000000; // 1 USDC + console.log("Fees Amount:", feesAmount, "1 USDC"); + FeesPlug feesPlug = FeesPlug(payable(vm.envAddress("ARBITRUM_FEES_PLUG"))); + console.log("Fees Plug:", address(feesPlug)); + + uint256 privateKey = vm.envUint("PRIVATE_KEY"); + address sender = vm.addr(privateKey); + console.log("Sender address:", sender); + + address arbitrumUSDC = vm.envAddress("ARBITRUM_USDC"); + IERC20 USDCContract = IERC20(arbitrumUSDC); + USDCContract.approve(address(feesPlug), feesAmount); + uint256 balance = USDCContract.balanceOf(sender); + console.log("Sender USDC balance:", balance); + if (balance < feesAmount) { + revert("Sender does not have enough USDC"); + } + + vm.createSelectFork(vm.envString("ARBITRUM_RPC")); + vm.startBroadcast(privateKey); + + address appGateway = vm.envAddress("APP_GATEWAY"); + console.log("App Gateway:", appGateway); + feesPlug.depositCreditAndNative(arbitrumUSDC, appGateway, feesAmount); + } +} diff --git a/script/helpers/PayFeesInArbitrumTestUSDC.s.sol b/script/helpers/PayFeesInArbitrumTestUSDC.s.sol deleted file mode 100644 index b1f56a9..0000000 --- a/script/helpers/PayFeesInArbitrumTestUSDC.s.sol +++ /dev/null @@ -1,36 +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 {FeesPlug} from "socket-protocol/contracts/evmx/payload-delivery/FeesPlug.sol"; -import {TestUSDC} from "socket-protocol/contracts/evmx/helpers/TestUSDC.sol"; - -contract DepositFees is Script { - function run() external { - vm.createSelectFork(vm.envString("ARBITRUM_SEPOLIA_RPC")); - - uint256 privateKey = vm.envUint("PRIVATE_KEY"); - address sender = vm.addr(privateKey); - - uint256 feesAmount = 100000000; // 10 USDC - FeesPlug feesPlug = FeesPlug(payable(vm.envAddress("ARBITRUM_FEES_PLUG"))); - address appGateway = vm.envAddress("APP_GATEWAY"); - TestUSDC testUSDCContract = TestUSDC(vm.envAddress("ARBITRUM_TEST_USDC")); - - vm.startBroadcast(privateKey); - // mint test USDC to sender - testUSDCContract.mint(sender, feesAmount); - console.log("Minting 100 TestUSDC to %s", sender); - // approve fees plug to spend test USDC - testUSDCContract.approve(address(feesPlug), feesAmount); - - uint256 balance = testUSDCContract.balanceOf(sender); - console.log("Using address %s with %s TestUSDC balance in wei", sender, balance); - - console.log("Depositing 100 TestUSDC on Arbitrum FeesPlug %s", address(feesPlug)); - feesPlug.depositToFeeAndNative(address(testUSDCContract), appGateway, feesAmount); - console.log("Added 90 credits for fee balance and 10 native credits for AppGateway %s", appGateway); - console.log("If you want to deposit to fees only, it can be deposited using `depositToFee`"); - } -} From 52aacf17d1dda30d3b35227bf1dda235b64b3fe1 Mon Sep 17 00:00:00 2001 From: Rookmate <14072042+rookmate@users.noreply.github.com> Date: Wed, 4 Jun 2025 13:59:21 +0100 Subject: [PATCH 04/15] chore: rename script --- .../{AppGatewayFeeBalance.s.sol => CheckDepositedCredits.s.sol} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename script/helpers/{AppGatewayFeeBalance.s.sol => CheckDepositedCredits.s.sol} (100%) diff --git a/script/helpers/AppGatewayFeeBalance.s.sol b/script/helpers/CheckDepositedCredits.s.sol similarity index 100% rename from script/helpers/AppGatewayFeeBalance.s.sol rename to script/helpers/CheckDepositedCredits.s.sol From 3ac013a18baeae2a6f90001a31cba9acc173318d Mon Sep 17 00:00:00 2001 From: Rookmate <14072042+rookmate@users.noreply.github.com> Date: Wed, 4 Jun 2025 14:00:04 +0100 Subject: [PATCH 05/15] chore: set msg.sender as sponsor of async txs --- src/counter/CounterAppGateway.sol | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/counter/CounterAppGateway.sol b/src/counter/CounterAppGateway.sol index dc53e0b..01c345d 100644 --- a/src/counter/CounterAppGateway.sol +++ b/src/counter/CounterAppGateway.sol @@ -44,6 +44,9 @@ contract CounterAppGateway is AppGatewayBase, Ownable { * @param chainSlug_ The identifier of the target chain */ function deployContracts(uint32 chainSlug_) external async { + // This ensures the msg.sender is the one paying for the fees + // for more information see: https://docs.socket.tech/fees + _setOverrides(msg.sender); _deploy(counter, chainSlug_, IsPlug.YES); } @@ -64,6 +67,9 @@ contract CounterAppGateway is AppGatewayBase, Ownable { * @param instances_ Array of counter contract addresses to increment */ function incrementCounters(address[] memory instances_) public async { + // This ensures the msg.sender is the one paying for the fees + // for more information see: https://docs.socket.tech/fees + _setOverrides(msg.sender); for (uint256 i = 0; i < instances_.length; i++) { ICounter(instances_[i]).increase(); } @@ -77,16 +83,4 @@ contract CounterAppGateway is AppGatewayBase, Ownable { function setMaxFees(uint256 fees_) public { maxFees = fees_; } - - /** - * @notice Withdraws fee tokens from the SOCKET Protocol - * @dev Allows withdrawal of accumulated fees to a specified receiver - * @param chainSlug_ The chain from which to withdraw fees - * @param token_ The token address to withdraw - * @param amount_ The amount to withdraw - * @param receiver_ The address that will receive the withdrawn fees - */ - function withdrawCredits(uint32 chainSlug_, address token_, uint256 amount_, address receiver_) external { - _withdrawCredits(chainSlug_, token_, amount_, receiver_); - } } From 344ef916e63937209a08db85c0145061b5cd3851 Mon Sep 17 00:00:00 2001 From: Rookmate <14072042+rookmate@users.noreply.github.com> Date: Wed, 4 Jun 2025 14:20:51 +0100 Subject: [PATCH 06/15] chore: update deposit USDC script --- script/helpers/DepositCreditAndNative.s.sol | 26 ++++++++++----------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/script/helpers/DepositCreditAndNative.s.sol b/script/helpers/DepositCreditAndNative.s.sol index 6458fc5..83b4ed8 100644 --- a/script/helpers/DepositCreditAndNative.s.sol +++ b/script/helpers/DepositCreditAndNative.s.sol @@ -13,29 +13,29 @@ interface IERC20 { contract DepositCredit is Script { function run() external { - uint256 feesAmount = 1000000; // 1 USDC - console.log("Fees Amount:", feesAmount, "1 USDC"); - FeesPlug feesPlug = FeesPlug(payable(vm.envAddress("ARBITRUM_FEES_PLUG"))); - console.log("Fees Plug:", address(feesPlug)); - uint256 privateKey = vm.envUint("PRIVATE_KEY"); address sender = vm.addr(privateKey); console.log("Sender address:", sender); + FeesPlug feesPlug = FeesPlug(payable(vm.envAddress("ARBITRUM_FEES_PLUG"))); address arbitrumUSDC = vm.envAddress("ARBITRUM_USDC"); IERC20 USDCContract = IERC20(arbitrumUSDC); - USDCContract.approve(address(feesPlug), feesAmount); + + vm.createSelectFork(vm.envString("ARBITRUM_RPC")); + vm.startBroadcast(privateKey); uint256 balance = USDCContract.balanceOf(sender); - console.log("Sender USDC balance:", balance); + + uint256 feesAmount = 1000000; // 1 USDC if (balance < feesAmount) { - revert("Sender does not have enough USDC"); + console.log("Sender USDC balance:", balance); + revert("Sender does not have enough USDC. Requires 1 USDC."); } - vm.createSelectFork(vm.envString("ARBITRUM_RPC")); - vm.startBroadcast(privateKey); + console.log("Depositing", feesAmount, " - 1 USDC to Arbitrum FeesPlug:", address(feesPlug)); + console.log("Approving Spending..."); + USDCContract.approve(address(feesPlug), feesAmount); - address appGateway = vm.envAddress("APP_GATEWAY"); - console.log("App Gateway:", appGateway); - feesPlug.depositCreditAndNative(arbitrumUSDC, appGateway, feesAmount); + feesPlug.depositCreditAndNative(arbitrumUSDC, sender, feesAmount); + console.log("Corresponding EVMx credits will show up on your account"); } } From fc0d1e6156a935348ac7f46ee2b20f5897f0b30c Mon Sep 17 00:00:00 2001 From: Rookmate <14072042+rookmate@users.noreply.github.com> Date: Wed, 4 Jun 2025 14:26:29 +0100 Subject: [PATCH 07/15] chore: update check credits script --- script/helpers/CheckDepositedCredits.s.sol | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/script/helpers/CheckDepositedCredits.s.sol b/script/helpers/CheckDepositedCredits.s.sol index 1ab2e39..c613923 100644 --- a/script/helpers/CheckDepositedCredits.s.sol +++ b/script/helpers/CheckDepositedCredits.s.sol @@ -5,18 +5,21 @@ import {Script} from "forge-std/Script.sol"; import {console} from "forge-std/console.sol"; import {FeesManager} from "socket-protocol/contracts/evmx/fees/FeesManager.sol"; -contract CheckDepositedFees is Script { +contract CheckAvailableCredits 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.userCredits(appGateway); - console.log("AppGateway:", appGateway); - console.log("Total balance of available fees for this AppGateway: %s", deposited); - console.log("Fees being locked due to existing transactions: %s", blocked); + uint256 privateKey = vm.envUint("PRIVATE_KEY"); + address sender = vm.addr(privateKey); + console.log("Sender address:", sender); + + vm.createSelectFork(vm.envString("EVMX_RPC")); + + (uint256 deposited, uint256 blocked) = feesManager.userCredits(sender); + console.log("Total balance of available credits for this address: %s", deposited); + console.log("Credits being locked due to existing transactions: %s", blocked); - uint256 availableFees = feesManager.getAvailableCredits(appGateway); - console.log("Fees available to be spent on transactions: %s", availableFees); + uint256 availableFees = feesManager.getAvailableCredits(sender); + console.log("Credits available to be spent on transactions: %s", availableFees); } } From 2a7298f21c402bbbd1b1ed506450844a18971ce6 Mon Sep 17 00:00:00 2001 From: Rookmate <14072042+rookmate@users.noreply.github.com> Date: Wed, 4 Jun 2025 14:35:00 +0100 Subject: [PATCH 08/15] chore: add reminder on deploy AppGateway --- script/counter/DeployEVMxCounterApp.s.sol | 1 + .../{CheckDepositedCredits.s.sol => CheckAvailableCredits.s.sol} | 0 2 files changed, 1 insertion(+) rename script/helpers/{CheckDepositedCredits.s.sol => CheckAvailableCredits.s.sol} (100%) diff --git a/script/counter/DeployEVMxCounterApp.s.sol b/script/counter/DeployEVMxCounterApp.s.sol index bf17987..ed84866 100644 --- a/script/counter/DeployEVMxCounterApp.s.sol +++ b/script/counter/DeployEVMxCounterApp.s.sol @@ -36,5 +36,6 @@ contract CounterDeploy is Script { console.log("CounterAppGateway contract:", address(appGateway)); console.log("See AppGateway on EVMx: https://evmx.cloud.blockscout.com/address/%s", address(appGateway)); + console.log("Do not forget to add the contract address to the .env file!"); } } diff --git a/script/helpers/CheckDepositedCredits.s.sol b/script/helpers/CheckAvailableCredits.s.sol similarity index 100% rename from script/helpers/CheckDepositedCredits.s.sol rename to script/helpers/CheckAvailableCredits.s.sol From 8c626000a5237d155bbf8bd2c901ee615f8f24eb Mon Sep 17 00:00:00 2001 From: Rookmate <14072042+rookmate@users.noreply.github.com> Date: Wed, 4 Jun 2025 15:02:20 +0100 Subject: [PATCH 09/15] chore: add approval for app gateway --- script/counter/DeployEVMxCounterApp.s.sol | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/script/counter/DeployEVMxCounterApp.s.sol b/script/counter/DeployEVMxCounterApp.s.sol index ed84866..e0963bd 100644 --- a/script/counter/DeployEVMxCounterApp.s.sol +++ b/script/counter/DeployEVMxCounterApp.s.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.0; import {Script} from "forge-std/Script.sol"; import {console} from "forge-std/console.sol"; +import "socket-protocol/contracts/evmx/interfaces/IFeesManager.sol"; import {CounterAppGateway} from "../../src/counter/CounterAppGateway.sol"; /** @@ -23,19 +24,24 @@ import {CounterAppGateway} from "../../src/counter/CounterAppGateway.sol"; contract CounterDeploy is Script { function run() external { address addressResolver = vm.envAddress("ADDRESS_RESOLVER"); + IFeesManager feesManager = IFeesManager(payable(vm.envAddress("FEES_MANAGER"))); 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 - uint256 fees = 10 ether; + uint256 fees = 0.1 ether; CounterAppGateway appGateway = new CounterAppGateway(addressResolver, fees); console.log("CounterAppGateway contract:", address(appGateway)); console.log("See AppGateway on EVMx: https://evmx.cloud.blockscout.com/address/%s", address(appGateway)); console.log("Do not forget to add the contract address to the .env file!"); + + console.log("Approving AppGateway to spend from funds in EOA"); + AppGatewayApprovals[] memory approvals = new AppGatewayApprovals[](1); + approvals[0] = AppGatewayApprovals({appGateway: address(appGateway), approval: true}); + feesManager.approveAppGateways(approvals); } } From 152331677f833051ebd3bbf95021e619b70c054c Mon Sep 17 00:00:00 2001 From: Rookmate <14072042+rookmate@users.noreply.github.com> Date: Wed, 4 Jun 2025 15:31:26 +0100 Subject: [PATCH 10/15] chore: rename script --- .../WithdrawCreditsArbitrumFeesPlug.s.sol} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename script/{counter/WithdrawFeesArbitrumFeesPlug.s.sol => helpers/WithdrawCreditsArbitrumFeesPlug.s.sol} (100%) diff --git a/script/counter/WithdrawFeesArbitrumFeesPlug.s.sol b/script/helpers/WithdrawCreditsArbitrumFeesPlug.s.sol similarity index 100% rename from script/counter/WithdrawFeesArbitrumFeesPlug.s.sol rename to script/helpers/WithdrawCreditsArbitrumFeesPlug.s.sol From 3f64f47437627301556e2bbbdcec4564ba480db3 Mon Sep 17 00:00:00 2001 From: Rookmate <14072042+rookmate@users.noreply.github.com> Date: Wed, 4 Jun 2025 16:49:50 +0100 Subject: [PATCH 11/15] chore: update withdraw script --- .../WithdrawCreditsArbitrumFeesPlug.s.sol | 62 ++++++------------- 1 file changed, 20 insertions(+), 42 deletions(-) diff --git a/script/helpers/WithdrawCreditsArbitrumFeesPlug.s.sol b/script/helpers/WithdrawCreditsArbitrumFeesPlug.s.sol index 306073b..4698490 100644 --- a/script/helpers/WithdrawCreditsArbitrumFeesPlug.s.sol +++ b/script/helpers/WithdrawCreditsArbitrumFeesPlug.s.sol @@ -3,67 +3,45 @@ 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/evmx/fees/FeesManager.sol"; +import "socket-protocol/contracts/evmx/interfaces/IFeesManager.sol"; import {CounterAppGateway} from "../../src/counter/CounterAppGateway.sol"; /** - * @title WithdrawFees Script + * @title WithdrawCredits Script * @notice Withdraws accumulated fees from EVMX to Arbitrum Sepolia * @dev This script: * 1. Checks available fees on EVMX - * 2. Switches to Arbitrum Sepolia to estimate gas costs - * 3. Calculates a safe amount to withdraw (fees minus estimated gas costs) - * 4. Performs the withdrawal if the amount is positive - * 5. Verifies final balance on Arbitrum Sepolia + * 2. Performs the withdrawal if the amount is positive * * This demonstrates how developers can retrieve fees that their application has earned - * through Socket Protocol's fee system. - * - * Required environment variables: - * - EVMX_RPC: RPC URL for the EVMx network - * - ARBITRUM_SEPOLIA_RPC: RPC URL for Arbitrum Sepolia - * - PRIVATE_KEY: Private key of the deployer account - * - FEES_MANAGER: Address of Socket Protocol's FeesManager contract - * - APP_GATEWAY: Address of the deployed CounterAppGateway - * @notice Ensure your app has withdrawFeeTokens() function implemented. You can check its implementation in CounterAppGateway.sol + * through SOCKET Protocol's fee system. */ -contract WithdrawFees is Script { +contract WithdrawCredits 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"); - address token = vm.envAddress("USDC"); - - CounterAppGateway appGateway = CounterAppGateway(appGatewayAddress); - uint256 availableFees = feesManager.getAvailableCredits(appGatewayAddress); - 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 = 5_000_000; // Estimate - uint256 estimatedGasCost = gasLimit * arbitrumGasPrice; + IFeesManager feesManager = IFeesManager(payable(vm.envAddress("FEES_MANAGER"))); + address token = vm.envAddress("ARBITRUM_USDC"); + uint256 privateKey = vm.envUint("PRIVATE_KEY"); + address sender = vm.addr(privateKey); - console.log("Arbitrum gas price (wei):", arbitrumGasPrice); - console.log("Gas limit:", gasLimit); - console.log("Estimated gas cost:", estimatedGasCost); + uint256 availableCredits = feesManager.getAvailableCredits(sender); + console.log("Available credits:", availableCredits); + //consfeesManager.tokenOntokenOnChainBalances[42161][token]; - // Calculate amount to withdraw - uint256 amountToWithdraw = availableFees > estimatedGasCost ? availableFees - estimatedGasCost : 0; + if (availableCredits > 0) { + uint256 maxFees = 10000000000000000; // Static 1 cent USDC credit (18 decimals) + // TODO: Also wrap native amount to be able to max withdraw + uint256 amountToWithdraw = 900000000000000000; // availableCredits - maxFees; if (amountToWithdraw > 0) { - // Switch back to EVMX to perform withdrawal - vm.createSelectFork(vm.envString("EVMX_RPC")); vm.startBroadcast(privateKey); + AppGatewayApprovals[] memory approvals = new AppGatewayApprovals[](1); + approvals[0] = AppGatewayApprovals({appGateway: address(feesManager), approval: true}); + feesManager.approveAppGateways(approvals); console.log("Withdrawing amount:", amountToWithdraw); - appGateway.withdrawCredits(421614, token, amountToWithdraw, sender); + feesManager.withdrawCredits(42161, token, amountToWithdraw, maxFees, sender); vm.stopBroadcast(); } else { console.log("Available fees less than estimated gas cost"); From ce31536c70c67eb002a0f03b73c792b865940ffe Mon Sep 17 00:00:00 2001 From: Rookmate <14072042+rookmate@users.noreply.github.com> Date: Wed, 4 Jun 2025 17:31:23 +0100 Subject: [PATCH 12/15] fix: wrong amount --- script/helpers/WithdrawCreditsArbitrumFeesPlug.s.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/helpers/WithdrawCreditsArbitrumFeesPlug.s.sol b/script/helpers/WithdrawCreditsArbitrumFeesPlug.s.sol index 4698490..454f0b3 100644 --- a/script/helpers/WithdrawCreditsArbitrumFeesPlug.s.sol +++ b/script/helpers/WithdrawCreditsArbitrumFeesPlug.s.sol @@ -33,7 +33,7 @@ contract WithdrawCredits is Script { if (availableCredits > 0) { uint256 maxFees = 10000000000000000; // Static 1 cent USDC credit (18 decimals) // TODO: Also wrap native amount to be able to max withdraw - uint256 amountToWithdraw = 900000000000000000; // availableCredits - maxFees; + uint256 amountToWithdraw = availableCredits - maxFees; if (amountToWithdraw > 0) { vm.startBroadcast(privateKey); From 42ed956b47c9e2cfd171dc1c083d9a1f2a16a424 Mon Sep 17 00:00:00 2001 From: Rookmate <14072042+rookmate@users.noreply.github.com> Date: Wed, 4 Jun 2025 17:43:06 +0100 Subject: [PATCH 13/15] fix: counter tests --- test/apps/Counter.t.sol | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/test/apps/Counter.t.sol b/test/apps/Counter.t.sol index da1327e..bb2b39a 100644 --- a/test/apps/Counter.t.sol +++ b/test/apps/Counter.t.sol @@ -1,9 +1,11 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.21; +import "socket-protocol/test/SetupTest.t.sol"; +import "socket-protocol/contracts/evmx/interfaces/IFeesManager.sol"; + import {CounterAppGateway} from "../../src/counter/CounterAppGateway.sol"; import {Counter} from "../../src/counter/Counter.sol"; -import "socket-protocol/test/SetupTest.t.sol"; contract CounterTest is AppGatewayBaseSetup { uint256 feesAmount = 0.01 ether; @@ -18,7 +20,10 @@ contract CounterTest is AppGatewayBaseSetup { deploy(); counterGateway = new CounterAppGateway(address(addressResolver), feesAmount); - depositNativeAndCredits(arbChainSlug, 1 ether, 0, address(counterGateway)); + depositNativeAndCredits(arbChainSlug, 1 ether, 0, address(this)); + AppGatewayApprovals[] memory approvals = new AppGatewayApprovals[](1); + approvals[0] = AppGatewayApprovals({appGateway: address(counterGateway), approval: true}); + feesManager.approveAppGateways(approvals); counterId = counterGateway.counter(); contractIds[0] = counterId; } From d4bdf2ffe18cb1cae600b40eaec6af4ee6674f80 Mon Sep 17 00:00:00 2001 From: Rookmate <14072042+rookmate@users.noreply.github.com> Date: Wed, 4 Jun 2025 19:03:41 +0100 Subject: [PATCH 14/15] chore: update fee plug address --- .env.sample | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env.sample b/.env.sample index 03b17df..7faa2fb 100644 --- a/.env.sample +++ b/.env.sample @@ -15,7 +15,7 @@ BASE_RPC="https://base.drpc.org" # https://github.com/SocketDotTech/socket-protocol/blob/master/deployments/stage_addresses.json ADDRESS_RESOLVER="0x935b06902cA5C8bb4C76e18738561c294D377A93" FEES_MANAGER="0xA07208F9e7aE243F922317ab6604DC9F86822406" -ARBITRUM_FEES_PLUG="0xee1Aef0b06f63Aa1c881838794Dd0876462c2B0d" +ARBITRUM_FEES_PLUG="0xfA768B7E490524475B5B96521d4C61D5b976c3C9" ARBITRUM_USDC="0xaf88d065e77c8cC2239327C5EDb3A432268e5831" # Add your deployer private key here From 7ea04b673cbc3a1c2bf372a9933c6d3cb75f6309 Mon Sep 17 00:00:00 2001 From: Rookmate <14072042+rookmate@users.noreply.github.com> Date: Wed, 4 Jun 2025 20:02:12 +0100 Subject: [PATCH 15/15] chore: update fee plug address --- .env.sample | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env.sample b/.env.sample index 7faa2fb..0483bd7 100644 --- a/.env.sample +++ b/.env.sample @@ -15,7 +15,7 @@ BASE_RPC="https://base.drpc.org" # https://github.com/SocketDotTech/socket-protocol/blob/master/deployments/stage_addresses.json ADDRESS_RESOLVER="0x935b06902cA5C8bb4C76e18738561c294D377A93" FEES_MANAGER="0xA07208F9e7aE243F922317ab6604DC9F86822406" -ARBITRUM_FEES_PLUG="0xfA768B7E490524475B5B96521d4C61D5b976c3C9" +ARBITRUM_FEES_PLUG="0x501bdF8C7163ddD32172575C2836c5A7F556cbE7" ARBITRUM_USDC="0xaf88d065e77c8cC2239327C5EDb3A432268e5831" # Add your deployer private key here