diff --git a/script/deployedContracts.json b/script/deployedContracts.json index d2aec5af..80d5720e 100644 --- a/script/deployedContracts.json +++ b/script/deployedContracts.json @@ -2,21 +2,20 @@ "clientChain": { "beaconOracle": "0xd3D285cd1516038dAED61B8BF7Ae2daD63662492", "beaconProxyBytecode": "0xA15Ce26ba8E50ac21ecDa1791BAa3bf22a95b575", - "bootstrap": "0xDf9caDCfb027d9f6264Ecd5eAEc839a8335d8520", - "bootstrapLogic": "0xB97A39004Ba6900FAE801Ac04F8ce4DA70689879", "capsuleBeacon": "0xB8D032a30a3B950CBcc6c1689E2381ab4290D4BB", - "capsuleImplementation": "0x02266413cdaaaF4092C5e48d6434040B63F62215", - "clientGatewayLogic": "0xf60F5af658C85aF56F6D811c9AA9F94fBe17A67d", - "erc20Token": "0x83E6850591425e3C1E263c054f4466838B9Bd9e4", + "capsuleImplementation": "0x8638502De2001e0dF71BbB5dd503E2008b2Ae948", + "clientChainGateway": "0xDf9caDCfb027d9f6264Ecd5eAEc839a8335d8520", + "clientChainGatewayLogic": "0x92A645a44DFf3e5499F9e6A1d6738520971267AA", "lzEndpoint": "0x6EDCE65403992e310A62460808c4b910D972f10f", "proxyAdmin": "0x4317A7f62dA871E4512424Df8CaE91A6Ccc2afEA", + "rewardVaultBeacon": "0xEe75FF2f3A6E49a7cfd0aa2F729563F8c0F7707b", + "rewardVaultImplementation": "0xAE4Aed8C1A66f89D7c19D7B1021BE027846A51e6", "vaultBeacon": "0x737e311Bf34B838943A30110289C5a9b22eba2A8", - "vaultImplementation": "0x69c1435EF73BA19e11a76481275EE6A8490942Db", - "wstETH": "0xB82381A3fBD3FaFA77B3a7bE693342618240067b" + "vaultImplementation": "0xce7f4AC8D00f5e4aB3BEd9fDD1EDB9cD20516477" }, "exocore": { "exocoreGateway": "0xEAf4E4D09b9CeB936492518A852026c914beb11E", - "exocoreGatewayLogic": "0x42397BFa2601B85E838750A10E652eea2238B5B6", + "exocoreGatewayLogic": "0xe522837eB5AC11a1748046F059FeEE42A5F2F6e9", "exocoreProxyAdmin": "0x9bBDDb68B47b88d3Dd2eF7E1682C1EFE4E2e2315", "lzEndpoint": "0x6EDCE65403992e310A62460808c4b910D972f10f" } diff --git a/src/core/BaseRestakingController.sol b/src/core/BaseRestakingController.sol index 740b78ae..281f52b7 100644 --- a/src/core/BaseRestakingController.sol +++ b/src/core/BaseRestakingController.sol @@ -4,6 +4,8 @@ pragma solidity ^0.8.19; import {IBaseRestakingController} from "../interfaces/IBaseRestakingController.sol"; import {IExoCapsule} from "../interfaces/IExoCapsule.sol"; import {IVault} from "../interfaces/IVault.sol"; + +import {Errors} from "../libraries/Errors.sol"; import {MessagingFee, MessagingReceipt, OAppSenderUpgradeable} from "../lzApp/OAppSenderUpgradeable.sol"; import {ClientChainGatewayStorage} from "../storage/ClientChainGatewayStorage.sol"; import {Action} from "../storage/GatewayStorage.sol"; @@ -81,47 +83,21 @@ abstract contract BaseRestakingController is } /// @inheritdoc IBaseRestakingController - function submitReward(address token, address avs, uint256 amount) - external - payable - isValidAmount(amount) - whenNotPaused - nonReentrant - { - require(token != address(0), "BaseRestakingController: token address cannot be empty or zero address"); - require(avs != address(0), "BaseRestakingController: avs address cannot be empty or zero address"); - // deposit reward to reward vault - rewardVault.deposit(token, msg.sender, avs, amount); - // send request to exocore, and this would not expect a response since deposit is supposed to be must success by - // protocol - bytes memory actionArgs = abi.encodePacked(bytes32(bytes20(token)), bytes32(bytes20(avs)), amount); - _processRequest(Action.REQUEST_SUBMIT_REWARD, actionArgs, bytes("")); + /// @dev Reward functionalities are not yet activated + function submitReward(address, address, uint256) external payable { + revert Errors.NotYetSupported(); } /// @inheritdoc IBaseRestakingController - function claimRewardFromExocore(address token, uint256 amount) - external - payable - isValidAmount(amount) - whenNotPaused - nonReentrant - { - require(token != address(0), "BaseRestakingController: token address cannot be empty or zero address"); - bytes memory actionArgs = abi.encodePacked(bytes32(bytes20(token)), bytes32(bytes20(msg.sender)), amount); - bytes memory encodedRequest = abi.encode(token, msg.sender, amount); - _processRequest(Action.REQUEST_CLAIM_REWARD, actionArgs, encodedRequest); + /// @dev Reward functionalities are not yet activated + function claimRewardFromExocore(address, uint256) external payable { + revert Errors.NotYetSupported(); } /// @inheritdoc IBaseRestakingController - function withdrawReward(address token, address recipient, uint256 amount) - external - isValidAmount(amount) - whenNotPaused - nonReentrant - { - require(token != address(0), "BaseRestakingController: token address cannot be empty or zero address"); - require(recipient != address(0), "BaseRestakingController: recipient address cannot be empty or zero address"); - rewardVault.withdraw(token, msg.sender, recipient, amount); + /// @dev Reward functionalities are not yet activated + function withdrawReward(address, address, uint256) external pure { + revert Errors.NotYetSupported(); } /// @dev Processes the request by sending it to Exocore. diff --git a/test/foundry/WithdrawReward.t.sol b/test/foundry/WithdrawReward.t.sol deleted file mode 100644 index f064d72d..00000000 --- a/test/foundry/WithdrawReward.t.sol +++ /dev/null @@ -1,281 +0,0 @@ -pragma solidity ^0.8.19; - -import "../../src/core/ExocoreGateway.sol"; - -import "../../src/interfaces/precompiles/IReward.sol"; -import {Action, GatewayStorage} from "../../src/storage/GatewayStorage.sol"; -import "../mocks/RewardMock.sol"; -import "./ExocoreDeployer.t.sol"; - -import "@layerzero-v2/protocol/contracts/libs/AddressCast.sol"; -import "@layerzerolabs/lz-evm-protocol-v2/contracts/libs/GUID.sol"; -import "forge-std/Test.sol"; -import "forge-std/console.sol"; - -contract WithdrawRewardTest is ExocoreDeployer { - - using AddressCast for address; - - event RewardOperation( - bool isSubmitReward, - bool indexed success, - bytes32 indexed token, - bytes32 indexed avsOrWithdrawer, - uint256 amount - ); - event Transfer(address indexed from, address indexed to, uint256 amount); - event RewardDeposited(address indexed token, address indexed avs, uint256 amount); - event RewardUnlocked(address indexed token, address indexed staker, uint256 amount); - event RewardWithdrawn(address indexed token, address indexed staker, address indexed recipient, uint256 amount); - - uint256 constant DEFAULT_ENDPOINT_CALL_GAS_LIMIT = 200_000; - - function test_SubmitAndClaimAndWithdrawRewardByLayerZero() public { - Player memory avsDepositor = players[0]; - Player memory staker = players[1]; - Player memory relayer = players[2]; - address avs = address(0xaabb); - - // fund the avs depositor some restake token so that it can deposit reward to reward vault - vm.startPrank(exocoreValidatorSet.addr); - restakeToken.transfer(avsDepositor.addr, 1_000_000); - vm.stopPrank(); - - // fund the depositor, staker, and exocore gateway for gas fee - deal(avsDepositor.addr, 1e22); - deal(staker.addr, 1e22); - deal(address(exocoreGateway), 1e22); - - // the amount of deposit, distribute, and withdraw - uint256 depositAmount = 1000; - uint256 distributeAmount = 500; - uint256 claimAmount = 100; - uint256 withdrawAmount = 100; - - // before withdraw we should add whitelist tokens - test_AddWhitelistTokens(); - - _testSubmitReward(avsDepositor, relayer, staker, avs, depositAmount); - RewardMock(REWARD_PRECOMPILE_ADDRESS).distributeReward( - clientChainId, - _addressToBytes(address(restakeToken)), - _addressToBytes(avs), - _addressToBytes(staker.addr), - distributeAmount - ); - _testClaimReward(staker, relayer, claimAmount); - _testWithdrawReward(staker, withdrawAmount); - } - - function _testSubmitReward( - Player memory depositor, - Player memory relayer, - Player memory staker, - address avs, - uint256 amount - ) internal { - // -- submit reward workflow -- - - // first user call client chain gateway to submit reward on behalf of AVS - - // depositor needs to approve the restake token to the client gateway - vm.startPrank(depositor.addr); - restakeToken.approve(address(rewardVault), amount); - vm.stopPrank(); - - // estimate l0 relay fee that the user should pay - bytes memory submitRewardRequestPayload = abi.encodePacked( - Action.REQUEST_SUBMIT_REWARD, bytes32(bytes20(address(restakeToken))), bytes32(bytes20(avs)), amount - ); - uint256 requestNativeFee = clientGateway.quote(submitRewardRequestPayload); - bytes32 requestId = generateUID(outboundNonces[clientChainId], true); - - // depositor should transfer deposited token to vault - vm.expectEmit(true, true, false, true, address(restakeToken)); - emit Transfer(depositor.addr, address(rewardVault), amount); - vm.expectEmit(true, true, true, true, address(rewardVault)); - emit RewardDeposited(address(restakeToken), avs, amount); - - // client chain layerzero endpoint should emit the message packet including submit reward payload. - vm.expectEmit(true, true, true, true, address(clientChainLzEndpoint)); - emit NewPacket( - exocoreChainId, - address(clientGateway), - address(exocoreGateway).toBytes32(), - outboundNonces[clientChainId], - submitRewardRequestPayload - ); - - // client chain gateway should emit MessageSent event - vm.expectEmit(true, true, true, true, address(clientGateway)); - emit MessageSent(Action.REQUEST_SUBMIT_REWARD, requestId, outboundNonces[clientChainId]++, requestNativeFee); - - vm.startPrank(depositor.addr); - clientGateway.submitReward{value: requestNativeFee}(address(restakeToken), avs, amount); - vm.stopPrank(); - - // assert that withdrawable amount is zero - assertEq(rewardVault.getWithdrawableBalance(address(restakeToken), staker.addr), 0); - assertEq(rewardVault.getWithdrawableBalance(address(restakeToken), depositor.addr), 0); - // assert total deposited amount for the avs is equal to the amount - assertEq(rewardVault.getTotalDepositedRewards(address(restakeToken), avs), amount); - - // second layerzero relayers should watch the request message packet and relay the message to destination - // endpoint - - // exocore gateway should emit RewardOperation event - vm.expectEmit(true, true, true, true, address(exocoreGateway)); - emit RewardOperation(true, true, bytes32(bytes20(address(restakeToken))), bytes32(bytes20(avs)), amount); - - vm.expectEmit(address(exocoreGateway)); - emit MessageExecuted(Action.REQUEST_SUBMIT_REWARD, inboundNonces[exocoreChainId]++); - - vm.startPrank(relayer.addr); - exocoreLzEndpoint.lzReceive( - Origin(clientChainId, address(clientGateway).toBytes32(), inboundNonces[exocoreChainId] - 1), - address(exocoreGateway), - requestId, - submitRewardRequestPayload, - bytes("") - ); - vm.stopPrank(); - - // assert that RewardMock has increased the reward amount for the avs - assertEq( - RewardMock(REWARD_PRECOMPILE_ADDRESS).getRewardAmountForAVS( - clientChainId, _addressToBytes(address(restakeToken)), _addressToBytes(avs) - ), - amount - ); - } - - function _testClaimReward(Player memory withdrawer, Player memory relayer, uint256 amount) internal { - // -- claim reward workflow -- - - uint256 withdrawableAmountBeforeClaim = - rewardVault.getWithdrawableBalance(address(restakeToken), withdrawer.addr); - - // first user call client chain gateway to withdraw - - // estimate l0 relay fee that the user should pay - bytes memory withdrawRequestPayload = abi.encodePacked( - Action.REQUEST_CLAIM_REWARD, - bytes32(bytes20(address(restakeToken))), - bytes32(bytes20(withdrawer.addr)), - amount - ); - uint256 requestNativeFee = clientGateway.quote(withdrawRequestPayload); - bytes32 requestId = generateUID(outboundNonces[clientChainId], true); - // client chain layerzero endpoint should emit the message packet including withdraw payload. - vm.expectEmit(true, true, true, true, address(clientChainLzEndpoint)); - emit NewPacket( - exocoreChainId, - address(clientGateway), - address(exocoreGateway).toBytes32(), - outboundNonces[clientChainId], - withdrawRequestPayload - ); - // client chain gateway should emit MessageSent event - vm.expectEmit(true, true, true, true, address(clientGateway)); - emit MessageSent(Action.REQUEST_CLAIM_REWARD, requestId, outboundNonces[clientChainId]++, requestNativeFee); - - vm.startPrank(withdrawer.addr); - clientGateway.claimRewardFromExocore{value: requestNativeFee}(address(restakeToken), amount); - vm.stopPrank(); - - // assert that withdrawable amount is not increased before receiving response from exocore - assertEq( - rewardVault.getWithdrawableBalance(address(restakeToken), withdrawer.addr), withdrawableAmountBeforeClaim - ); - - // second layerzero relayers should watch the request message packet and relay the message to destination - // endpoint - - // exocore gateway should return response message to exocore network layerzero endpoint - bytes memory withdrawResponsePayload = abi.encodePacked(Action.RESPOND, outboundNonces[clientChainId] - 1, true); - uint256 responseNativeFee = exocoreGateway.quote(clientChainId, withdrawResponsePayload); - bytes32 responseId = generateUID(outboundNonces[exocoreChainId], false); - - // exocore gateway should emit RewardOperation event - vm.expectEmit(true, true, true, true, address(exocoreGateway)); - emit RewardOperation( - false, true, bytes32(bytes20(address(restakeToken))), bytes32(bytes20(withdrawer.addr)), amount - ); - - vm.expectEmit(true, true, true, true, address(exocoreLzEndpoint)); - emit NewPacket( - clientChainId, - address(exocoreGateway), - address(clientGateway).toBytes32(), - outboundNonces[exocoreChainId], - withdrawResponsePayload - ); - // exocore gateway should emit MessageSent event - vm.expectEmit(true, true, true, true, address(exocoreGateway)); - emit MessageSent(Action.RESPOND, responseId, outboundNonces[exocoreChainId]++, responseNativeFee); - - vm.expectEmit(address(exocoreGateway)); - emit MessageExecuted(Action.REQUEST_CLAIM_REWARD, inboundNonces[exocoreChainId]++); - - vm.startPrank(relayer.addr); - exocoreLzEndpoint.lzReceive( - Origin(clientChainId, address(clientGateway).toBytes32(), inboundNonces[exocoreChainId] - 1), - address(exocoreGateway), - requestId, - withdrawRequestPayload, - bytes("") - ); - vm.stopPrank(); - - // third layerzero relayers should watch the response message packet and relay the message to source chain - // endpoint - - // client chain gateway should execute the response hook and emit RequestFinished event - vm.expectEmit(true, true, true, true, address(rewardVault)); - emit RewardUnlocked(address(restakeToken), withdrawer.addr, amount); - vm.expectEmit(true, true, true, true, address(clientGateway)); - emit ResponseProcessed(Action.REQUEST_CLAIM_REWARD, outboundNonces[clientChainId] - 1, true); - - vm.expectEmit(address(clientGateway)); - emit MessageExecuted(Action.RESPOND, inboundNonces[clientChainId]++); - - vm.startPrank(relayer.addr); - clientChainLzEndpoint.lzReceive( - Origin(exocoreChainId, address(exocoreGateway).toBytes32(), inboundNonces[clientChainId] - 1), - address(clientGateway), - responseId, - withdrawResponsePayload, - bytes("") - ); - vm.stopPrank(); - - // assert that the withdrawable amount has been increased by the amount - uint256 withdrawableAmountAfterClaim = - rewardVault.getWithdrawableBalance(address(restakeToken), withdrawer.addr); - assertEq(withdrawableAmountAfterClaim, withdrawableAmountBeforeClaim + amount); - } - - function _testWithdrawReward(Player memory withdrawer, uint256 amount) internal { - // -- withdraw reward workflow -- - - uint256 withdrawableAmountBeforeWithdraw = - rewardVault.getWithdrawableBalance(address(restakeToken), withdrawer.addr); - uint256 balanceBeforeWithdraw = restakeToken.balanceOf(withdrawer.addr); - - vm.expectEmit(true, true, true, true, address(rewardVault)); - emit RewardWithdrawn(address(restakeToken), withdrawer.addr, withdrawer.addr, amount); - - vm.startPrank(withdrawer.addr); - clientGateway.withdrawReward(address(restakeToken), withdrawer.addr, amount); - vm.stopPrank(); - - // assert the withdrawable amount has been decreased by the amount - uint256 withdrawableAmountAfterWithdraw = - rewardVault.getWithdrawableBalance(address(restakeToken), withdrawer.addr); - assertEq(withdrawableAmountAfterWithdraw, withdrawableAmountBeforeWithdraw - amount); - // assert that the balance of the withdrawer has been increased by the amount - uint256 balanceAfterWithdraw = restakeToken.balanceOf(withdrawer.addr); - assertEq(balanceAfterWithdraw, balanceBeforeWithdraw + amount); - } - -}