From 2e34a3a24b430322de95a788e4dc93eca4b488d7 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Tue, 23 Jul 2024 16:57:38 +0530 Subject: [PATCH 01/23] feat: added bytes32ToAddress in BaseHelper lib --- contracts/libraries/BaseHelper.sol | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/contracts/libraries/BaseHelper.sol b/contracts/libraries/BaseHelper.sol index 6dcce75e..2ae4c27f 100644 --- a/contracts/libraries/BaseHelper.sol +++ b/contracts/libraries/BaseHelper.sol @@ -32,23 +32,45 @@ library BaseHelper { return bytes32(uint256(uint160(_addr))); } + /** + * @notice This function converts a bytes32 value to an address + * @dev This function performs type casting to convert a bytes32 to an address. + * It first converts the bytes32 to a uint256, then to a uint160, and finally to an address. + * This conversion involves truncation from left side. + * For example, given a bytes32 value of 0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCC: + * - Using address(uint160(uint256(b))) results in an address of 0x777788889999AaAAbBbbCcccddDdeeeEfFFfCcCc + * @param _bytes The bytes32 value to be converted to an address + * @return address The address representation of the bytes32 value + */ + function bytes32ToAddress(bytes32 _bytes) internal pure returns (address) { + return address(uint160(uint256(_bytes))); + } + /** * @notice This function calculates the percentage of a given amount using a Percentage struct. * @dev This function performs a simple percentage calculation. - * It multiplies the amount by the percentage number and divides the result by 10 raised to the power of decimal places. + * It multiplies the amount by the percentage number and divides the result by 10 raised to the power of + * decimal places. * It reverts if the percentage exceeds 100. * @param _amount The amount for which the percentage is calculated. * @param _percentage The percentage to be calculated, represented as a Percentage struct. * @return uint256 The calculated percentage value. - * + * * Examples: * - If _amount is 1000 and _percentage is {percentageNumber: 20, decimalPlaces: 0}, it means (20% of 1000). * - If _amount is 1000 and _percentage is {percentageNumber: 2345, decimalPlaces: 2}, it means (23.45% of 1000). * - If _amount is 1000 and _percentage is {percentageNumber: 56789, decimalPlaces: 3}, it means (56.789% of 1000). */ - function calcPercentage(uint256 _amount, GenericTypes.Percentage memory _percentage) internal pure returns (uint256) { + function calcPercentage( + uint256 _amount, + GenericTypes.Percentage memory _percentage + ) + internal + pure + returns (uint256) + { uint256 divisor = 10 ** _percentage.decimalPlaces; require(_percentage.percentageNumber <= 100 * divisor, "Percentage exceeds 100%"); - return (_amount * _percentage.percentageNumber) / ( divisor * 100); + return (_amount * _percentage.percentageNumber) / (divisor * 100); } } From 0d85aa60217b955238ba98fa9fc499d69ada265f Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Tue, 23 Jul 2024 16:58:24 +0530 Subject: [PATCH 02/23] refactor: updated address parameters to bytes32 in CCR payloads decoding --- contracts/PushCore/PushCoreV3.sol | 35 ++++++++++++++++++------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/contracts/PushCore/PushCoreV3.sol b/contracts/PushCore/PushCoreV3.sol index 5803e4ed..0a6ce765 100644 --- a/contracts/PushCore/PushCoreV3.sol +++ b/contracts/PushCore/PushCoreV3.sol @@ -229,10 +229,8 @@ contract PushCoreV3 is if (channelInfo[_channel].channelState != 0) { revert Errors.Core_InvalidChannel(); } - - if ( - uint8(_channelType) < 2 - ) { + + if (uint8(_channelType) < 2) { revert Errors.Core_InvalidChannelType(); } @@ -856,26 +854,33 @@ contract PushCoreV3 is CrossChainRequestTypes.CrossChainFunction functionType, bytes memory structPayload, uint256 amount, - address sender - ) = abi.decode(payload, (CrossChainRequestTypes.CrossChainFunction, bytes, uint256, address)); + bytes32 sender + ) = abi.decode(payload, (CrossChainRequestTypes.CrossChainFunction, bytes, uint256, bytes32)); if (functionType == CrossChainRequestTypes.CrossChainFunction.AddChannel) { // Specific Request: Add Channel (CoreTypes.ChannelType channelType, bytes memory channelIdentity, uint256 channelExpiry) = abi.decode(structPayload, (CoreTypes.ChannelType, bytes, uint256)); - bytes32 _channelBytesID = BaseHelper.addressToBytes32(sender); - emit ChannelCreated(_channelBytesID, channelType, channelIdentity); - _createChannel(_channelBytesID, channelType, amount, channelExpiry); + emit ChannelCreated(sender, channelType, channelIdentity); + _createChannel(sender, channelType, amount, channelExpiry); } else if (functionType == CrossChainRequestTypes.CrossChainFunction.IncentivizedChat) { // Specific Request: Incentivized Chat - (address amountRecipient) = abi.decode(structPayload, (address)); - _handleIncentivizedChat(sender, amountRecipient, amount); + (bytes32 amountRecipient) = abi.decode(structPayload, (bytes32)); + _handleIncentivizedChat( + BaseHelper.bytes32ToAddress(sender), BaseHelper.bytes32ToAddress(amountRecipient), amount + ); } else if (functionType == CrossChainRequestTypes.CrossChainFunction.ArbitraryRequest) { // Arbitrary Request - (uint8 feeId, GenericTypes.Percentage memory feePercentage, address amountRecipient) = - abi.decode(structPayload, (uint8, GenericTypes.Percentage, address)); - - _handleArbitraryRequest(sender, feeId, feePercentage, amountRecipient, amount); + (uint8 feeId, GenericTypes.Percentage memory feePercentage, bytes32 amountRecipient) = + abi.decode(structPayload, (uint8, GenericTypes.Percentage, bytes32)); + + _handleArbitraryRequest( + BaseHelper.bytes32ToAddress(sender), + feeId, + feePercentage, + BaseHelper.bytes32ToAddress(amountRecipient), + amount + ); } else if (functionType == CrossChainRequestTypes.CrossChainFunction.AdminRequest_AddPoolFee) { // Admin Request PROTOCOL_POOL_FEES += amount; From 2f92165a3b2b8decd76f1328a7ab1309fe867c68 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Tue, 23 Jul 2024 16:59:19 +0530 Subject: [PATCH 03/23] test: updated tests as per bytes32 new changes --- .../ArbitraryRequest/ArbitraryRequest.t.sol | 13 ++++++++----- .../CreateChannelCCR/CreateChannelCCR.t.sol | 18 +++++++++++------- .../CreateChatCCR/CreateChatCCR.t.sol | 8 +++++--- 3 files changed, 24 insertions(+), 15 deletions(-) diff --git a/test/CCR/ArbitraryRequest/ArbitraryRequest.t.sol b/test/CCR/ArbitraryRequest/ArbitraryRequest.t.sol index 80b44f58..a2b6c384 100644 --- a/test/CCR/ArbitraryRequest/ArbitraryRequest.t.sol +++ b/test/CCR/ArbitraryRequest/ArbitraryRequest.t.sol @@ -10,20 +10,22 @@ import "./../../../../contracts/libraries/wormhole-lib/TrimmedAmount.sol"; import { TransceiverStructs } from "./../../../../contracts/libraries/wormhole-lib/TransceiverStructs.sol"; import { BaseHelper } from "./../../../contracts/libraries/BaseHelper.sol"; + contract ArbitraryRequesttsol is BaseCCRTest { uint256 amount = 100e18; + function setUp() public override { BaseCCRTest.setUp(); - percentage = GenericTypes.Percentage(2322, 2); + percentage = GenericTypes.Percentage(2322, 2); (_payload, requestPayload) = getSpecificPayload( CrossChainRequestTypes.CrossChainFunction.ArbitraryRequest, - actor.charlie_channel_owner, + BaseHelper.addressToBytes32(actor.charlie_channel_owner), amount, 1, percentage, - actor.bob_channel_owner + BaseHelper.addressToBytes32(actor.bob_channel_owner) ); } @@ -148,8 +150,9 @@ contract ArbitraryRequesttsol is BaseCCRTest { (address sourceNttManager, bytes32 recipient, uint256 _amount, uint16 recipientChain) = getMessagefromLog(vm.getRecordedLogs()); bytes[] memory a; - - (bytes memory transceiverMessage, bytes32 hash) = getRequestPayload(_amount, recipient, recipientChain, sourceNttManager); + + (bytes memory transceiverMessage, bytes32 hash) = + getRequestPayload(_amount, recipient, recipientChain, sourceNttManager); changePrank(DestChain.WORMHOLE_RELAYER_DEST); DestChain.wormholeTransceiverChain2.receiveWormholeMessages( diff --git a/test/CCR/SpecificRequest/CreateChannelCCR/CreateChannelCCR.t.sol b/test/CCR/SpecificRequest/CreateChannelCCR/CreateChannelCCR.t.sol index 6f205d3e..0765ae3c 100644 --- a/test/CCR/SpecificRequest/CreateChannelCCR/CreateChannelCCR.t.sol +++ b/test/CCR/SpecificRequest/CreateChannelCCR/CreateChannelCCR.t.sol @@ -7,6 +7,7 @@ import { Errors } from ".././../../../contracts/libraries/Errors.sol"; import { console } from "forge-std/console.sol"; import "./../../../../contracts/libraries/wormhole-lib/TrimmedAmount.sol"; import { TransceiverStructs } from "./../../../../contracts/libraries/wormhole-lib/TransceiverStructs.sol"; +import { BaseHelper } from "contracts/libraries/BaseHelper.sol"; contract CreateChannelCCR is BaseCCRTest { uint256 amount = ADD_CHANNEL_MIN_FEES; @@ -15,7 +16,12 @@ contract CreateChannelCCR is BaseCCRTest { BaseCCRTest.setUp(); sourceAddress = toWormholeFormat(address(commProxy)); (_payload, requestPayload) = getSpecificPayload( - CrossChainRequestTypes.CrossChainFunction.AddChannel, address(0), amount, 0, percentage, actor.charlie_channel_owner + CrossChainRequestTypes.CrossChainFunction.AddChannel, + BaseHelper.addressToBytes32(address(0)), + amount, + 0, + percentage, + BaseHelper.addressToBytes32(actor.charlie_channel_owner) ); } @@ -145,16 +151,14 @@ contract CreateChannelCCR is BaseCCRTest { vm.recordLogs(); test_whenReceiveChecksPass(); - ( - address sourceNttManager, - bytes32 recipient, - uint256 _amount, - uint16 recipientChain )= getMessagefromLog(vm.getRecordedLogs()); + (address sourceNttManager, bytes32 recipient, uint256 _amount, uint16 recipientChain) = + getMessagefromLog(vm.getRecordedLogs()); console.log(pushNttToken.balanceOf(address(coreProxy))); bytes[] memory a; - (bytes memory transceiverMessage, bytes32 hash) = getRequestPayload(_amount, recipient, recipientChain, sourceNttManager); + (bytes memory transceiverMessage, bytes32 hash) = + getRequestPayload(_amount, recipient, recipientChain, sourceNttManager); changePrank(DestChain.WORMHOLE_RELAYER_DEST); DestChain.wormholeTransceiverChain2.receiveWormholeMessages( diff --git a/test/CCR/SpecificRequest/CreateChatCCR/CreateChatCCR.t.sol b/test/CCR/SpecificRequest/CreateChatCCR/CreateChatCCR.t.sol index 5da8a4fc..a14963ea 100644 --- a/test/CCR/SpecificRequest/CreateChatCCR/CreateChatCCR.t.sol +++ b/test/CCR/SpecificRequest/CreateChatCCR/CreateChatCCR.t.sol @@ -8,6 +8,7 @@ import { console } from "forge-std/console.sol"; import { CrossChainRequestTypes } from "../../../../contracts/libraries/DataTypes.sol"; import "./../../../../contracts/libraries/wormhole-lib/TrimmedAmount.sol"; import { TransceiverStructs } from "./../../../../contracts/libraries/wormhole-lib/TransceiverStructs.sol"; +import { BaseHelper } from "contracts/libraries/BaseHelper.sol"; contract CreateChatCCR is BaseCCRTest { uint256 amount = 100e18; @@ -17,11 +18,11 @@ contract CreateChatCCR is BaseCCRTest { sourceAddress = toWormholeFormat(address(commProxy)); (_payload, requestPayload) = getSpecificPayload( CrossChainRequestTypes.CrossChainFunction.IncentivizedChat, - actor.charlie_channel_owner, + BaseHelper.addressToBytes32(actor.charlie_channel_owner), amount, 0, percentage, - actor.bob_channel_owner + BaseHelper.addressToBytes32(actor.bob_channel_owner) ); } @@ -129,7 +130,8 @@ contract CreateChatCCR is BaseCCRTest { console.log(pushNttToken.balanceOf(address(coreProxy))); bytes[] memory a; - (bytes memory transceiverMessage, bytes32 hash) = getRequestPayload(_amount, recipient, recipientChain, sourceNttManager); + (bytes memory transceiverMessage, bytes32 hash) = + getRequestPayload(_amount, recipient, recipientChain, sourceNttManager); changePrank(DestChain.WORMHOLE_RELAYER_DEST); DestChain.wormholeTransceiverChain2.receiveWormholeMessages( From e218655c76008ff113c6ccc134eeb322292bc3f1 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Tue, 23 Jul 2024 17:47:56 +0530 Subject: [PATCH 04/23] fix: updated sender as bytes32 --- contracts/PushCore/PushCoreV3.sol | 12 ++++++------ contracts/interfaces/IPushCoreV3.sol | 4 ++-- test/CCR/ArbitraryRequest/ArbitraryRequest.t.sol | 2 +- test/CCR/CCRutils/Helper.sol | 4 ++-- .../CreateChatCCR/CreateChatCCR.t.sol | 2 +- test/utils/Events.sol | 4 ++-- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/contracts/PushCore/PushCoreV3.sol b/contracts/PushCore/PushCoreV3.sol index 0a6ce765..29097c56 100644 --- a/contracts/PushCore/PushCoreV3.sol +++ b/contracts/PushCore/PushCoreV3.sol @@ -767,7 +767,7 @@ contract PushCoreV3 is if (msg.sender != epnsCommunicator) { revert Errors.UnauthorizedCaller(msg.sender); } - _handleIncentivizedChat(requestSender, requestReceiver, amount); + _handleIncentivizedChat(BaseHelper.addressToBytes32(requestSender), requestReceiver, amount); } /** @@ -778,7 +778,7 @@ contract PushCoreV3 is * @param requestReceiver The address of the receiver who is the target of the chat request. * @param amount The total amount sent by the sender for the incentivized chat. */ - function _handleIncentivizedChat(address requestSender, address requestReceiver, uint256 amount) private { + function _handleIncentivizedChat(bytes32 requestSender, address requestReceiver, uint256 amount) private { uint256 poolFeeAmount = FEE_AMOUNT; uint256 requestReceiverAmount = amount - poolFeeAmount; @@ -867,7 +867,7 @@ contract PushCoreV3 is // Specific Request: Incentivized Chat (bytes32 amountRecipient) = abi.decode(structPayload, (bytes32)); _handleIncentivizedChat( - BaseHelper.bytes32ToAddress(sender), BaseHelper.bytes32ToAddress(amountRecipient), amount + sender, BaseHelper.bytes32ToAddress(amountRecipient), amount ); } else if (functionType == CrossChainRequestTypes.CrossChainFunction.ArbitraryRequest) { // Arbitrary Request @@ -875,7 +875,7 @@ contract PushCoreV3 is abi.decode(structPayload, (uint8, GenericTypes.Percentage, bytes32)); _handleArbitraryRequest( - BaseHelper.bytes32ToAddress(sender), + sender, feeId, feePercentage, BaseHelper.bytes32ToAddress(amountRecipient), @@ -904,7 +904,7 @@ contract PushCoreV3 is IERC20(PUSH_TOKEN_ADDRESS).safeTransferFrom(msg.sender, address(this), amount); // Call the private function to process the arbitrary request - _handleArbitraryRequest(msg.sender, feeId, feePercentage, amountRecipient, amount); + _handleArbitraryRequest(BaseHelper.addressToBytes32(msg.sender), feeId, feePercentage, amountRecipient, amount); } /** @@ -917,7 +917,7 @@ contract PushCoreV3 is * @param amount The total amount sent by the sender for the arbitrary request. */ function _handleArbitraryRequest( - address sender, + bytes32 sender, uint8 feeId, GenericTypes.Percentage memory feePercentage, address amountRecipient, diff --git a/contracts/interfaces/IPushCoreV3.sol b/contracts/interfaces/IPushCoreV3.sol index beb30331..af16b1be 100644 --- a/contracts/interfaces/IPushCoreV3.sol +++ b/contracts/interfaces/IPushCoreV3.sol @@ -37,7 +37,7 @@ interface IPushCoreV3 { event RewardsHarvested(address indexed user, uint256 indexed rewardAmount, uint256 fromEpoch, uint256 tillEpoch); /// @notice emits whenever any user receives an incentivized chat request from another user event IncentivizeChatReqReceived( - address requestSender, + bytes32 requestSender, address requestReceiver, uint256 amountForReqReceiver, uint256 feePoolAmount, @@ -50,7 +50,7 @@ interface IPushCoreV3 { event ChannelStateUpdate(bytes32 indexed channel, uint256 amountRefunded, uint256 amountDeposited); /// @notice emits when arbitray cross chain request is received event ArbitraryRequest( - address indexed sender, + bytes32 indexed sender, address indexed receiver, uint256 amountDeposited, GenericTypes.Percentage feePercent, diff --git a/test/CCR/ArbitraryRequest/ArbitraryRequest.t.sol b/test/CCR/ArbitraryRequest/ArbitraryRequest.t.sol index a2b6c384..34fb53c0 100644 --- a/test/CCR/ArbitraryRequest/ArbitraryRequest.t.sol +++ b/test/CCR/ArbitraryRequest/ArbitraryRequest.t.sol @@ -131,7 +131,7 @@ contract ArbitraryRequesttsol is BaseCCRTest { (uint256 poolFunds, uint256 poolFees) = getPoolFundsAndFees(amount); vm.expectEmit(true, true, false, true); - emit ArbitraryRequest(actor.bob_channel_owner, actor.charlie_channel_owner, amount, percentage, 1); + emit ArbitraryRequest(BaseHelper.addressToBytes32(actor.bob_channel_owner), actor.charlie_channel_owner, amount, percentage, 1); coreProxy.receiveWormholeMessages( requestPayload, additionalVaas, sourceAddress, SourceChain.SourceChainId, deliveryHash diff --git a/test/CCR/CCRutils/Helper.sol b/test/CCR/CCRutils/Helper.sol index 838fd6e9..16bcc908 100644 --- a/test/CCR/CCRutils/Helper.sol +++ b/test/CCR/CCRutils/Helper.sol @@ -89,11 +89,11 @@ contract Helper is BasePushCommTest, CCRConfig { function getSpecificPayload( CrossChainRequestTypes.CrossChainFunction typeOfReq, - address amountRecipient, + bytes32 amountRecipient, uint256 amount, uint8 _feeId, GenericTypes.Percentage memory _percentage, - address sender + bytes32 sender ) internal pure diff --git a/test/CCR/SpecificRequest/CreateChatCCR/CreateChatCCR.t.sol b/test/CCR/SpecificRequest/CreateChatCCR/CreateChatCCR.t.sol index a14963ea..9220acf6 100644 --- a/test/CCR/SpecificRequest/CreateChatCCR/CreateChatCCR.t.sol +++ b/test/CCR/SpecificRequest/CreateChatCCR/CreateChatCCR.t.sol @@ -112,7 +112,7 @@ contract CreateChatCCR is BaseCCRTest { vm.expectEmit(false, false, false, true); emit IncentivizeChatReqReceived( - actor.bob_channel_owner, actor.charlie_channel_owner, amount - poolFeeAmount, poolFeeAmount, block.timestamp + BaseHelper.addressToBytes32(actor.bob_channel_owner), actor.charlie_channel_owner, amount - poolFeeAmount, poolFeeAmount, block.timestamp ); receiveWormholeMessage(requestPayload); diff --git a/test/utils/Events.sol b/test/utils/Events.sol index 00ea5a0e..55659084 100644 --- a/test/utils/Events.sol +++ b/test/utils/Events.sol @@ -11,7 +11,7 @@ abstract contract CoreEvents { event ChannelBlocked(bytes32 indexed channel); event TimeBoundChannelDestroyed(address indexed channel, uint256 indexed amountRefunded); event IncentivizeChatReqReceived( - address requestSender, + bytes32 requestSender, address requestReceiver, uint256 amountForReqReceiver, uint256 feePoolAmount, @@ -22,7 +22,7 @@ abstract contract CoreEvents { event ChannelVerificationRevoked(bytes32 indexed channel, address indexed revoker); event ChannelStateUpdate(bytes32 indexed channel, uint256 amountRefunded, uint256 amountDeposited); event ArbitraryRequest( - address indexed sender, + bytes32 indexed sender, address indexed receiver, uint256 amountDeposited, GenericTypes.Percentage feePercent, From 9178079e1f3928b83c205e66ba640d694961ffcb Mon Sep 17 00:00:00 2001 From: Md Zartaj Afser Date: Wed, 24 Jul 2024 11:11:08 +0530 Subject: [PATCH 05/23] support bytes32 for address --- contracts/PushCore/PushCoreStorageV2.sol | 3 +- contracts/PushCore/PushCoreV3.sol | 38 +++++++++++------------- 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/contracts/PushCore/PushCoreStorageV2.sol b/contracts/PushCore/PushCoreStorageV2.sol index ab73c051..5ce718ba 100644 --- a/contracts/PushCore/PushCoreStorageV2.sol +++ b/contracts/PushCore/PushCoreStorageV2.sol @@ -48,5 +48,6 @@ contract PushCoreStorageV2 { mapping(address => uint256) public arbitraryReqFees; // ToDo: Could be replaced with nonces(unused) mapping instead // of adding new state - mapping(bytes32 => CoreTypes.Channel) public channelInfo; + mapping(bytes32 => CoreTypes.Channel) public channelInfo; + mapping(bytes32 => uint256) public ChannelUpdateCounter; } diff --git a/contracts/PushCore/PushCoreV3.sol b/contracts/PushCore/PushCoreV3.sol index 5803e4ed..3d256b52 100644 --- a/contracts/PushCore/PushCoreV3.sol +++ b/contracts/PushCore/PushCoreV3.sol @@ -68,16 +68,15 @@ contract PushCoreV3 is } } - function onlyActivatedChannels(address _channel) private view { - bytes32 _channelBytesID = BaseHelper.addressToBytes32(_channel); + function onlyActivatedChannels(bytes32 _channel) private view { - if (channelInfo[_channelBytesID].channelState != 1) { + if (channelInfo[_channel].channelState != 1) { revert Errors.Core_InvalidChannel(); } } function addSubGraph(bytes calldata _subGraphData) external { - onlyActivatedChannels(msg.sender); + onlyActivatedChannels(BaseHelper.addressToBytes32(msg.sender)); emit AddSubGraph(msg.sender, _subGraphData); } @@ -160,14 +159,16 @@ contract PushCoreV3 is ///@inheritdoc IPushCoreV3 // ToDo: Check if updateChannelMeta is required for Cross-Chain-Req feature. If yes, it needs its own private // function - function updateChannelMeta(address _channel, bytes calldata _newIdentity, uint256 _amount) external whenNotPaused { - onlyActivatedChannels(_channel); + function updateChannelMeta(bytes calldata _newIdentity, uint256 _amount) external whenNotPaused { + bytes32 _channel = BaseHelper.addressToBytes32(msg.sender); - if (msg.sender != _channel) { - revert Errors.UnauthorizedCaller(msg.sender); - } + IERC20(PUSH_TOKEN_ADDRESS).safeTransferFrom(msg.sender, address(this), _amount); + _updateChannelMeta( _channel,_newIdentity, _amount); + } - uint256 updateCounter = channelUpdateCounter[_channel] + 1; + function _updateChannelMeta(bytes32 _channel, bytes calldata _newIdentity, uint256 _amount) internal { + onlyActivatedChannels(_channel); + uint256 updateCounter = ChannelUpdateCounter[_channel] + 1; uint256 requiredFees = ADD_CHANNEL_MIN_FEES * updateCounter; if (_amount < requiredFees) { @@ -175,13 +176,11 @@ contract PushCoreV3 is } PROTOCOL_POOL_FEES = PROTOCOL_POOL_FEES + _amount; - channelUpdateCounter[_channel] = updateCounter; + ChannelUpdateCounter[_channel] = updateCounter; - bytes32 _channelBytesID = BaseHelper.addressToBytes32(msg.sender); - channelInfo[_channelBytesID].channelUpdateBlock = block.number; + channelInfo[_channel].channelUpdateBlock = block.number; - IERC20(PUSH_TOKEN_ADDRESS).safeTransferFrom(_channel, address(this), _amount); - emit UpdateChannel(_channelBytesID, _newIdentity, _amount); + emit UpdateChannel(_channel, _newIdentity, _amount); } /// @inheritdoc IPushCoreV3 @@ -270,7 +269,7 @@ contract PushCoreV3 is ) external { - onlyActivatedChannels(msg.sender); + onlyActivatedChannels(BaseHelper.addressToBytes32(msg.sender)); if (_amountDeposited < ADD_CHANNEL_MIN_FEES) { revert Errors.InvalidArg_LessThanExpected(ADD_CHANNEL_MIN_FEES, _amountDeposited); } @@ -386,10 +385,9 @@ contract PushCoreV3 is *************** */ /// @inheritdoc IPushCoreV3 - function getChannelVerfication(address _channel) public view returns (uint8 verificationStatus) { - bytes32 _channelBytesID = BaseHelper.addressToBytes32(_channel); + function getChannelVerfication(bytes32 _channel) public view returns (uint8 verificationStatus) { - address verifiedBy = channelInfo[_channelBytesID].verifiedBy; + address verifiedBy = channelInfo[_channel].verifiedBy; bool logicComplete = false; // Check if it's primary verification @@ -434,7 +432,7 @@ contract PushCoreV3 is } /// @inheritdoc IPushCoreV3 - function verifyChannel(address _channel) public { + function verifyChannel(bytes32 _channel) public { onlyActivatedChannels(_channel); // Check if caller is verified first uint8 callerVerified = getChannelVerfication(msg.sender); From e8096408892433c2d7c60336502aabb338018309 Mon Sep 17 00:00:00 2001 From: Md Zartaj Afser Date: Thu, 25 Jul 2024 11:49:17 +0530 Subject: [PATCH 06/23] Address to Bytes related changes --- contracts/PushCore/PushCoreV3.sol | 51 +++++------ contracts/interfaces/IPushCoreV3.sol | 17 ++-- test/BaseTest.t.sol | 4 + test/CCR/CCRutils/Helper.sol | 4 - .../blockChannel/blockChannel.t.sol | 20 +++-- .../deactivateChannel/deactivateChannel.t.sol | 2 +- .../reactivateChannel/reactivateChannel.t.sol | 2 +- .../ChannelUnverification.t.sol | 89 ++++++++++--------- .../ChannelVerification.t.sol | 85 ++++++++++-------- .../contractPausability.t.sol | 4 +- 10 files changed, 146 insertions(+), 132 deletions(-) diff --git a/contracts/PushCore/PushCoreV3.sol b/contracts/PushCore/PushCoreV3.sol index 19e804c9..51e753e7 100644 --- a/contracts/PushCore/PushCoreV3.sol +++ b/contracts/PushCore/PushCoreV3.sol @@ -159,16 +159,14 @@ contract PushCoreV3 is ///@inheritdoc IPushCoreV3 // ToDo: Check if updateChannelMeta is required for Cross-Chain-Req feature. If yes, it needs its own private // function - function updateChannelMeta(bytes calldata _newIdentity, uint256 _amount) external whenNotPaused { - bytes32 _channel = BaseHelper.addressToBytes32(msg.sender); + function updateChannelMeta(address _channel, bytes calldata _newIdentity, uint256 _amount) external whenNotPaused { + onlyActivatedChannels(BaseHelper.addressToBytes32(_channel)); - IERC20(PUSH_TOKEN_ADDRESS).safeTransferFrom(msg.sender, address(this), _amount); - _updateChannelMeta( _channel,_newIdentity, _amount); - } + if (msg.sender != _channel) { + revert Errors.UnauthorizedCaller(msg.sender); + } - function _updateChannelMeta(bytes32 _channel, bytes calldata _newIdentity, uint256 _amount) internal { - onlyActivatedChannels(_channel); - uint256 updateCounter = ChannelUpdateCounter[_channel] + 1; + uint256 updateCounter = channelUpdateCounter[_channel] + 1; uint256 requiredFees = ADD_CHANNEL_MIN_FEES * updateCounter; if (_amount < requiredFees) { @@ -176,11 +174,13 @@ contract PushCoreV3 is } PROTOCOL_POOL_FEES = PROTOCOL_POOL_FEES + _amount; - ChannelUpdateCounter[_channel] = updateCounter; + channelUpdateCounter[_channel] = updateCounter; - channelInfo[_channel].channelUpdateBlock = block.number; + bytes32 _channelBytesID = BaseHelper.addressToBytes32(msg.sender); + channelInfo[_channelBytesID].channelUpdateBlock = block.number; - emit UpdateChannel(_channel, _newIdentity, _amount); + IERC20(PUSH_TOKEN_ADDRESS).safeTransferFrom(_channel, address(this), _amount); + emit UpdateChannel(_channelBytesID, _newIdentity, _amount); } /// @inheritdoc IPushCoreV3 @@ -353,14 +353,13 @@ contract PushCoreV3 is } /// @inheritdoc IPushCoreV3 - function blockChannel(address _channelAddress) external whenNotPaused { + function blockChannel(bytes32 _channelAddress) external whenNotPaused { onlyGovernance(); - bytes32 _channelBytesID = BaseHelper.addressToBytes32(_channelAddress); - if (((channelInfo[_channelBytesID].channelState == 3) || (channelInfo[_channelBytesID].channelState == 0))) { + if (((channelInfo[_channelAddress].channelState == 3) || (channelInfo[_channelAddress].channelState == 0))) { revert Errors.Core_InvalidChannel(); } uint256 minPoolContribution = MIN_POOL_CONTRIBUTION; - CoreTypes.Channel storage channelData = channelInfo[_channelBytesID]; + CoreTypes.Channel storage channelData = channelInfo[_channelAddress]; // add channel's currentPoolContribution to PoolFees - (no refunds if Channel is blocked) // Decrease CHANNEL_POOL_FUNDS by currentPoolContribution uint256 currentPoolContribution = channelData.poolContribution - minPoolContribution; @@ -375,7 +374,7 @@ contract PushCoreV3 is channelData.channelUpdateBlock = block.number; channelData.poolContribution = minPoolContribution; - emit ChannelBlocked(_channelBytesID); + emit ChannelBlocked(_channelAddress); } /* ************** @@ -389,7 +388,7 @@ contract PushCoreV3 is bool logicComplete = false; // Check if it's primary verification - if (verifiedBy == pushChannelAdmin || _channel == pushChannelAdmin) { + if (verifiedBy == pushChannelAdmin || _channel == BaseHelper.addressToBytes32(pushChannelAdmin)) { // primary verification, mark and exit verificationStatus = 1; } else { @@ -413,7 +412,7 @@ contract PushCoreV3 is function batchVerification( uint256 _startIndex, uint256 _endIndex, - address[] calldata _channelList + bytes32[] calldata _channelList ) external returns (bool) @@ -433,7 +432,7 @@ contract PushCoreV3 is function verifyChannel(bytes32 _channel) public { onlyActivatedChannels(_channel); // Check if caller is verified first - uint8 callerVerified = getChannelVerfication(msg.sender); + uint8 callerVerified = getChannelVerfication(BaseHelper.addressToBytes32(msg.sender)); if (callerVerified == 0) { revert Errors.UnauthorizedCaller(msg.sender); } @@ -445,25 +444,23 @@ contract PushCoreV3 is } // Verify channel - bytes32 _channelBytesID = BaseHelper.addressToBytes32(_channel); - channelInfo[_channelBytesID].verifiedBy = msg.sender; + channelInfo[_channel].verifiedBy = msg.sender; // Emit event - emit ChannelVerified(_channelBytesID, msg.sender); + emit ChannelVerified(_channel, msg.sender); } /// @inheritdoc IPushCoreV3 - function unverifyChannel(address _channel) public { - bytes32 _channelBytesID = BaseHelper.addressToBytes32(_channel); - if (!(channelInfo[_channelBytesID].verifiedBy == msg.sender || msg.sender == pushChannelAdmin)) { + function unverifyChannel(bytes32 _channel) public { + if (!(channelInfo[_channel].verifiedBy == msg.sender || msg.sender == pushChannelAdmin)) { revert Errors.CallerNotAdmin(); } // Unverify channel - channelInfo[_channelBytesID].verifiedBy = address(0x0); + channelInfo[_channel].verifiedBy = address(0x0); // Emit Event - emit ChannelVerificationRevoked(_channelBytesID, msg.sender); + emit ChannelVerificationRevoked(_channel, msg.sender); } /** diff --git a/contracts/interfaces/IPushCoreV3.sol b/contracts/interfaces/IPushCoreV3.sol index af16b1be..a80cdcd9 100644 --- a/contracts/interfaces/IPushCoreV3.sol +++ b/contracts/interfaces/IPushCoreV3.sol @@ -67,12 +67,12 @@ interface IPushCoreV3 { /** * @notice Function is designed to tell if a channel is verified or not * @dev Get if channel is verified or not - * @param _channel Address of the channel to be Verified + * @param _channel Address of the channel to be Verified, in bytes32 format * @return verificationStatus Returns 0 for not verified, 1 for primary verification, 2 for secondary * verification * */ - function getChannelVerfication(address _channel) external view returns (uint8 verificationStatus); + function getChannelVerfication(bytes32 _channel) external view returns (uint8 verificationStatus); /* ***************************** @@ -99,7 +99,6 @@ interface IPushCoreV3 { * Records the Block Number of the Block at which the Channel is being updated * Emits an event with the new identity for the respective Channel Address * - * @param _channel address of the Channel * @param _newIdentity bytes Value for the New Identity of the Channel * @param _amount amount of PUSH Token required for updating channel details. * @@ -212,27 +211,27 @@ interface IPushCoreV3 { * - Since there is no refund, the channel's poolContribution is added to PROTOCOL_POOL_FEES and Removed * from CHANNEL_POOL_FUNDS * - Emit 'ChannelBlocked' Event - * @param _channelAddress Address of the Channel to be blocked + * @param _channelAddress Address of the Channel to be blocked, in bytes32 format * */ - function blockChannel(address _channelAddress) external; + function blockChannel(bytes32 _channelAddress) external; /** * @notice Function is designed to verify a channel * @dev Channel will be verified by primary or secondary verification, will fail or upgrade if already * verified - * @param _channel Address of the channel to be Verified + * @param _channel Address of the channel to be Verified, in bytes32 format * */ - function verifyChannel(address _channel) external; + function verifyChannel(bytes32 _channel) external; /** * @notice Function is designed to unverify a channel * @dev Channel who verified this channel or Push Channel Admin can only revoke - * @param _channel Address of the channel to be unverified + * @param _channel Address of the channel to be unverified, in bytes32 format * */ - function unverifyChannel(address _channel) external; + function unverifyChannel(bytes32 _channel) external; /** * @notice Designed to handle the incoming Incentivized Chat Request Data and PUSH tokens. diff --git a/test/BaseTest.t.sol b/test/BaseTest.t.sol index b2f8a3df..6b9f15f2 100644 --- a/test/BaseTest.t.sol +++ b/test/BaseTest.t.sol @@ -224,4 +224,8 @@ abstract contract BaseTest is Test, Constants, Events { function createChannelCreatorsID(address _actor) internal pure returns (bytes32 _channelCreatorBytes32) { _channelCreatorBytes32 = BaseHelper.addressToBytes32(_actor); } + + function toWormholeFormat(address addr) internal pure returns (bytes32) { + return bytes32(uint256(uint160(addr))); + } } diff --git a/test/CCR/CCRutils/Helper.sol b/test/CCR/CCRutils/Helper.sol index 16bcc908..8317c016 100644 --- a/test/CCR/CCRutils/Helper.sol +++ b/test/CCR/CCRutils/Helper.sol @@ -71,10 +71,6 @@ contract Helper is BasePushCommTest, CCRConfig { coreProxy.setRegisteredSender(SourceChain.SourceChainId, toWormholeFormat(address(commProxy))); } - function toWormholeFormat(address addr) internal pure returns (bytes32) { - return bytes32(uint256(uint160(addr))); - } - function getPoolFundsAndFees(uint256 _amountDeposited) internal view diff --git a/test/PushCore/unit_tests/ChannelStateCycle/blockChannel/blockChannel.t.sol b/test/PushCore/unit_tests/ChannelStateCycle/blockChannel/blockChannel.t.sol index bda45d81..65a8397d 100644 --- a/test/PushCore/unit_tests/ChannelStateCycle/blockChannel/blockChannel.t.sol +++ b/test/PushCore/unit_tests/ChannelStateCycle/blockChannel/blockChannel.t.sol @@ -4,10 +4,14 @@ import { BasePushCoreTest } from "../../BasePushCoreTest.t.sol"; import { Errors } from "contracts/libraries/Errors.sol"; contract BlockChannel_Test is BasePushCoreTest { + bytes32 bobBytes; + bytes32 charlieBytes; function setUp() public virtual override { BasePushCoreTest.setUp(); _createChannel(actor.bob_channel_owner); + bobBytes = toWormholeFormat(actor.bob_channel_owner); + charlieBytes = toWormholeFormat(actor.charlie_channel_owner); } modifier whenNotPaused() { @@ -21,7 +25,7 @@ contract BlockChannel_Test is BasePushCoreTest { function test_Revertwhen_BlockCallerNotGovernance() public whenNotPaused whenCallerIsAdmin { vm.expectRevert(Errors.CallerNotGovernance.selector); - coreProxy.blockChannel(actor.bob_channel_owner); + coreProxy.blockChannel(bobBytes); } function test_AdminCanBlockActivatedChannel() public whenNotPaused whenCallerIsAdmin { @@ -29,7 +33,7 @@ contract BlockChannel_Test is BasePushCoreTest { emit ChannelBlocked(channelCreators.bob_channel_owner_Bytes32); vm.prank(actor.admin); - coreProxy.blockChannel(actor.bob_channel_owner); + coreProxy.blockChannel(bobBytes); } function test_AdminCanBlockDeactivatedChannel() public whenNotPaused whenCallerIsAdmin { @@ -40,28 +44,28 @@ contract BlockChannel_Test is BasePushCoreTest { emit ChannelBlocked(channelCreators.bob_channel_owner_Bytes32); vm.prank(actor.admin); - coreProxy.blockChannel(actor.bob_channel_owner); + coreProxy.blockChannel(bobBytes); } function test_Revertwhen_BlockInactiveChannel() public whenNotPaused whenCallerIsAdmin { vm.prank(actor.admin); vm.expectRevert(Errors.Core_InvalidChannel.selector); - coreProxy.blockChannel(actor.charlie_channel_owner); + coreProxy.blockChannel(charlieBytes); } function test_Revertwhen_AlreadyBlockedChannel() public whenNotPaused whenCallerIsAdmin { vm.startPrank(actor.admin); - coreProxy.blockChannel(actor.bob_channel_owner); + coreProxy.blockChannel(bobBytes); vm.expectRevert(Errors.Core_InvalidChannel.selector); - coreProxy.blockChannel(actor.bob_channel_owner); + coreProxy.blockChannel(bobBytes); vm.stopPrank(); } function test_ChannelDetailsUpdation() public whenNotPaused whenCallerIsAdmin { uint256 channelsCountBeforeBlocked = coreProxy.channelsCount(); vm.prank(actor.admin); - coreProxy.blockChannel(actor.bob_channel_owner); + coreProxy.blockChannel(bobBytes); ( , @@ -96,7 +100,7 @@ contract BlockChannel_Test is BasePushCoreTest { uint256 poolFundsBeforeBlocked = coreProxy.CHANNEL_POOL_FUNDS(); vm.prank(actor.admin); - coreProxy.blockChannel(actor.bob_channel_owner); + coreProxy.blockChannel(bobBytes); uint256 actualChannelFundsAfterBlocked = coreProxy.CHANNEL_POOL_FUNDS(); uint256 actualPoolFeesAfterBlocked = coreProxy.PROTOCOL_POOL_FEES(); diff --git a/test/PushCore/unit_tests/ChannelStateCycle/deactivateChannel/deactivateChannel.t.sol b/test/PushCore/unit_tests/ChannelStateCycle/deactivateChannel/deactivateChannel.t.sol index 42617c73..d15a4380 100644 --- a/test/PushCore/unit_tests/ChannelStateCycle/deactivateChannel/deactivateChannel.t.sol +++ b/test/PushCore/unit_tests/ChannelStateCycle/deactivateChannel/deactivateChannel.t.sol @@ -34,7 +34,7 @@ contract DeactivateChannel_Test is BasePushCoreTest { function test_Revertwhen_DeactivatingBlockedChannel() public whenNotPaused { vm.prank(actor.admin); - coreProxy.blockChannel(actor.bob_channel_owner); + coreProxy.blockChannel(toWormholeFormat(actor.bob_channel_owner)); vm.prank(actor.bob_channel_owner); vm.expectRevert(Errors.Core_InvalidChannel.selector); diff --git a/test/PushCore/unit_tests/ChannelStateCycle/reactivateChannel/reactivateChannel.t.sol b/test/PushCore/unit_tests/ChannelStateCycle/reactivateChannel/reactivateChannel.t.sol index a3a37613..fe9a7d2c 100644 --- a/test/PushCore/unit_tests/ChannelStateCycle/reactivateChannel/reactivateChannel.t.sol +++ b/test/PushCore/unit_tests/ChannelStateCycle/reactivateChannel/reactivateChannel.t.sol @@ -20,7 +20,7 @@ contract ReactivateChannel_Test is BasePushCoreTest { approveTokens(actor.bob_channel_owner, address(coreProxy), ADD_CHANNEL_MIN_FEES); vm.prank(actor.admin); - coreProxy.blockChannel(actor.bob_channel_owner); + coreProxy.blockChannel(toWormholeFormat(actor.bob_channel_owner)); vm.prank(actor.bob_channel_owner); vm.expectRevert(Errors.Core_InvalidChannel.selector); diff --git a/test/PushCore/unit_tests/ChannelVerifyTag/ChannelUnverification/ChannelUnverification.t.sol b/test/PushCore/unit_tests/ChannelVerifyTag/ChannelUnverification/ChannelUnverification.t.sol index 7187cf44..afed301f 100644 --- a/test/PushCore/unit_tests/ChannelVerifyTag/ChannelUnverification/ChannelUnverification.t.sol +++ b/test/PushCore/unit_tests/ChannelVerifyTag/ChannelUnverification/ChannelUnverification.t.sol @@ -4,27 +4,34 @@ import { BasePushCoreTest } from "../../BasePushCoreTest.t.sol"; import { Errors } from "contracts/libraries/Errors.sol"; contract ChannelUnverification_Test is BasePushCoreTest { + bytes32 bobBytes; + bytes32 aliceBytes; + bytes32 charlieBytes; function setUp() public virtual override { BasePushCoreTest.setUp(); _createChannel(actor.bob_channel_owner); _createChannel(actor.alice_channel_owner); _createChannel(actor.charlie_channel_owner); + + bobBytes = toWormholeFormat(actor.bob_channel_owner); + aliceBytes = toWormholeFormat(actor.alice_channel_owner); + charlieBytes = toWormholeFormat(actor.charlie_channel_owner); } function test_WhenAdminUnverifies_AChannelVerifiedBy_AdminItself() external { // it should be able to unverify changePrank(actor.admin); - coreProxy.verifyChannel(actor.bob_channel_owner); + coreProxy.verifyChannel(bobBytes); - uint8 bobVerificationBefore = coreProxy.getChannelVerfication(actor.bob_channel_owner); + uint8 bobVerificationBefore = coreProxy.getChannelVerfication(bobBytes); assertEq(bobVerificationBefore, 1); changePrank(actor.admin); vm.expectEmit(true, true, false, false); emit ChannelVerificationRevoked(channelCreators.bob_channel_owner_Bytes32, actor.admin); - coreProxy.unverifyChannel(actor.bob_channel_owner); + coreProxy.unverifyChannel(bobBytes); - uint8 bobVerificationAfter = coreProxy.getChannelVerfication(actor.bob_channel_owner); + uint8 bobVerificationAfter = coreProxy.getChannelVerfication(bobBytes); assertEq(bobVerificationAfter, 0); address Bob_verifiedBy = _getVerifiedBy(actor.bob_channel_owner); @@ -34,19 +41,19 @@ contract ChannelUnverification_Test is BasePushCoreTest { function test_WhenAdminUnverifies_AChannelVerifiedBy_AnotherChannel() external { // it should be able to unverify changePrank(actor.admin); - coreProxy.verifyChannel(actor.bob_channel_owner); + coreProxy.verifyChannel(bobBytes); changePrank(actor.bob_channel_owner); - coreProxy.verifyChannel(actor.alice_channel_owner); + coreProxy.verifyChannel(aliceBytes); - uint8 aliceVerification = coreProxy.getChannelVerfication(actor.alice_channel_owner); + uint8 aliceVerification = coreProxy.getChannelVerfication(aliceBytes); assertEq(aliceVerification, 2); changePrank(actor.admin); vm.expectEmit(true, true, false, false); emit ChannelVerificationRevoked(channelCreators.alice_channel_owner_Bytes32, actor.admin); - coreProxy.unverifyChannel(actor.alice_channel_owner); + coreProxy.unverifyChannel(aliceBytes); - uint8 aliceVerificationAfter = coreProxy.getChannelVerfication(actor.alice_channel_owner); + uint8 aliceVerificationAfter = coreProxy.getChannelVerfication(aliceBytes); assertEq(aliceVerificationAfter, 0); address Alice_verifiedBy = _getVerifiedBy(actor.alice_channel_owner); @@ -56,19 +63,19 @@ contract ChannelUnverification_Test is BasePushCoreTest { function test_WhenAChannelUnverifies_ASecondaryVerifiedChannel_VerifiedByItself() external { // it should be able to unverify changePrank(actor.admin); - coreProxy.verifyChannel(actor.bob_channel_owner); + coreProxy.verifyChannel(bobBytes); changePrank(actor.bob_channel_owner); - coreProxy.verifyChannel(actor.alice_channel_owner); + coreProxy.verifyChannel(aliceBytes); - uint8 aliceVerification = coreProxy.getChannelVerfication(actor.alice_channel_owner); + uint8 aliceVerification = coreProxy.getChannelVerfication(aliceBytes); assertEq(aliceVerification, 2); changePrank(actor.bob_channel_owner); vm.expectEmit(true, true, false, false); emit ChannelVerificationRevoked(channelCreators.alice_channel_owner_Bytes32, actor.bob_channel_owner); - coreProxy.unverifyChannel(actor.alice_channel_owner); + coreProxy.unverifyChannel(aliceBytes); - uint8 aliceVerificationAfter = coreProxy.getChannelVerfication(actor.alice_channel_owner); + uint8 aliceVerificationAfter = coreProxy.getChannelVerfication(aliceBytes); assertEq(aliceVerificationAfter, 0); address Alice_verifiedBy = _getVerifiedBy(actor.alice_channel_owner); @@ -78,20 +85,20 @@ contract ChannelUnverification_Test is BasePushCoreTest { function test_RevertWhen_AChannelUnverifies_ASecondaryVerifiedChannel_VerifiedByAnotherChannel() external { // it should REVERT changePrank(actor.admin); - coreProxy.verifyChannel(actor.bob_channel_owner); - coreProxy.verifyChannel(actor.charlie_channel_owner); + coreProxy.verifyChannel(bobBytes); + coreProxy.verifyChannel(charlieBytes); changePrank(actor.bob_channel_owner); - coreProxy.verifyChannel(actor.alice_channel_owner); + coreProxy.verifyChannel(aliceBytes); - uint8 aliceVerification = coreProxy.getChannelVerfication(actor.alice_channel_owner); + uint8 aliceVerification = coreProxy.getChannelVerfication(aliceBytes); assertEq(aliceVerification, 2); vm.expectRevert(Errors.CallerNotAdmin.selector); changePrank(actor.charlie_channel_owner); - coreProxy.unverifyChannel(actor.alice_channel_owner); + coreProxy.unverifyChannel(aliceBytes); - uint8 aliceVerificationAfter = coreProxy.getChannelVerfication(actor.alice_channel_owner); + uint8 aliceVerificationAfter = coreProxy.getChannelVerfication(aliceBytes); assertEq(aliceVerificationAfter, 2); address Alice_verifiedBy = _getVerifiedBy(actor.alice_channel_owner); @@ -101,23 +108,23 @@ contract ChannelUnverification_Test is BasePushCoreTest { function test_WhenASecondaryVerifiedChannel_UnverifiesAnotherSecondaryChannel_VerifiedByItself() external { // it should unverify those channels changePrank(actor.admin); - coreProxy.verifyChannel(actor.bob_channel_owner); + coreProxy.verifyChannel(bobBytes); changePrank(actor.bob_channel_owner); - coreProxy.verifyChannel(actor.charlie_channel_owner); + coreProxy.verifyChannel(charlieBytes); changePrank(actor.charlie_channel_owner); - coreProxy.verifyChannel(actor.alice_channel_owner); + coreProxy.verifyChannel(aliceBytes); - uint8 aliceVerification = coreProxy.getChannelVerfication(actor.alice_channel_owner); + uint8 aliceVerification = coreProxy.getChannelVerfication(aliceBytes); assertEq(aliceVerification, 2); changePrank(actor.charlie_channel_owner); vm.expectEmit(true, true, false, false); emit ChannelVerificationRevoked(channelCreators.alice_channel_owner_Bytes32, actor.charlie_channel_owner); - coreProxy.unverifyChannel(actor.alice_channel_owner); + coreProxy.unverifyChannel(aliceBytes); - uint8 aliceVerificationAfter = coreProxy.getChannelVerfication(actor.alice_channel_owner); + uint8 aliceVerificationAfter = coreProxy.getChannelVerfication(aliceBytes); assertEq(aliceVerificationAfter, 0); address Alice_verifiedBy = _getVerifiedBy(actor.alice_channel_owner); @@ -127,24 +134,24 @@ contract ChannelUnverification_Test is BasePushCoreTest { function test_WhenASecondaryVerifiedChannel_GetsUnverifed() external { // it should unverify any other secondary verified channel that is verified by this channel changePrank(actor.admin); - coreProxy.verifyChannel(actor.bob_channel_owner); + coreProxy.verifyChannel(bobBytes); changePrank(actor.bob_channel_owner); - coreProxy.verifyChannel(actor.charlie_channel_owner); + coreProxy.verifyChannel(charlieBytes); changePrank(actor.charlie_channel_owner); - coreProxy.verifyChannel(actor.alice_channel_owner); + coreProxy.verifyChannel(aliceBytes); - uint8 aliceVerification = coreProxy.getChannelVerfication(actor.alice_channel_owner); + uint8 aliceVerification = coreProxy.getChannelVerfication(aliceBytes); assertEq(aliceVerification, 2); changePrank(actor.bob_channel_owner); vm.expectEmit(true, true, false, false); emit ChannelVerificationRevoked(channelCreators.charlie_channel_owner_Bytes32, actor.bob_channel_owner); - coreProxy.unverifyChannel(actor.charlie_channel_owner); + coreProxy.unverifyChannel(charlieBytes); - uint8 charlieVerificationAfter = coreProxy.getChannelVerfication(actor.charlie_channel_owner); - uint8 aliceVerificationAfter = coreProxy.getChannelVerfication(actor.alice_channel_owner); + uint8 charlieVerificationAfter = coreProxy.getChannelVerfication(charlieBytes); + uint8 aliceVerificationAfter = coreProxy.getChannelVerfication(aliceBytes); assertEq(charlieVerificationAfter, 0, "charlie"); assertEq(aliceVerificationAfter, 0, "alice"); @@ -158,25 +165,25 @@ contract ChannelUnverification_Test is BasePushCoreTest { function test_WhenAdminUnverifies_AnyChannelPrimaryOrSecondary() external { // it should unverify all of them as well as any secondary channel verified by those channels changePrank(actor.admin); - coreProxy.verifyChannel(actor.bob_channel_owner); + coreProxy.verifyChannel(bobBytes); changePrank(actor.bob_channel_owner); - coreProxy.verifyChannel(actor.charlie_channel_owner); + coreProxy.verifyChannel(charlieBytes); changePrank(actor.charlie_channel_owner); - coreProxy.verifyChannel(actor.alice_channel_owner); + coreProxy.verifyChannel(aliceBytes); - uint8 aliceVerification = coreProxy.getChannelVerfication(actor.alice_channel_owner); + uint8 aliceVerification = coreProxy.getChannelVerfication(aliceBytes); assertEq(aliceVerification, 2); changePrank(actor.admin); vm.expectEmit(true, true, false, false); emit ChannelVerificationRevoked(channelCreators.bob_channel_owner_Bytes32, actor.admin); - coreProxy.unverifyChannel(actor.bob_channel_owner); + coreProxy.unverifyChannel(bobBytes); - uint8 bobVerificationAfter = coreProxy.getChannelVerfication(actor.bob_channel_owner); - uint8 charlieVerificationAfter = coreProxy.getChannelVerfication(actor.charlie_channel_owner); - uint8 aliceVerificationAfter = coreProxy.getChannelVerfication(actor.alice_channel_owner); + uint8 bobVerificationAfter = coreProxy.getChannelVerfication(bobBytes); + uint8 charlieVerificationAfter = coreProxy.getChannelVerfication(charlieBytes); + uint8 aliceVerificationAfter = coreProxy.getChannelVerfication(aliceBytes); assertEq(charlieVerificationAfter, 0, "charlie"); assertEq(aliceVerificationAfter, 0, "alice"); diff --git a/test/PushCore/unit_tests/ChannelVerifyTag/ChannelVerification/ChannelVerification.t.sol b/test/PushCore/unit_tests/ChannelVerifyTag/ChannelVerification/ChannelVerification.t.sol index 0177d7ff..6445b735 100644 --- a/test/PushCore/unit_tests/ChannelVerifyTag/ChannelVerification/ChannelVerification.t.sol +++ b/test/PushCore/unit_tests/ChannelVerifyTag/ChannelVerification/ChannelVerification.t.sol @@ -4,11 +4,18 @@ import { BasePushCoreTest } from "../../BasePushCoreTest.t.sol"; import { Errors } from "contracts/libraries/Errors.sol"; contract ChannelVerification_Test is BasePushCoreTest { + bytes32 bobBytes; + bytes32 aliceBytes; + bytes32 charlieBytes; function setUp() public virtual override { BasePushCoreTest.setUp(); _createChannel(actor.bob_channel_owner); _createChannel(actor.alice_channel_owner); _createChannel(actor.charlie_channel_owner); + + bobBytes = toWormholeFormat(actor.bob_channel_owner); + aliceBytes = toWormholeFormat(actor.alice_channel_owner); + charlieBytes = toWormholeFormat(actor.charlie_channel_owner); } modifier whenCheckedTheDefaultVerificationStatus() { @@ -19,8 +26,8 @@ contract ChannelVerification_Test is BasePushCoreTest { external whenCheckedTheDefaultVerificationStatus { - uint8 adminVerification = coreProxy.getChannelVerfication(actor.admin); - uint8 zeroAddressVerification = coreProxy.getChannelVerfication(address(0)); + uint8 adminVerification = coreProxy.getChannelVerfication(toWormholeFormat(actor.admin)); + uint8 zeroAddressVerification = coreProxy.getChannelVerfication(toWormholeFormat(address(0))); assertEq(adminVerification, 1); @@ -34,8 +41,8 @@ contract ChannelVerification_Test is BasePushCoreTest { whenCheckedTheDefaultVerificationStatus { // it should return 0 for unverified Channels - uint8 bobVerification = coreProxy.getChannelVerfication(actor.bob_channel_owner); - uint8 aliceVerification = coreProxy.getChannelVerfication(actor.alice_channel_owner); + uint8 bobVerification = coreProxy.getChannelVerfication(bobBytes); + uint8 aliceVerification = coreProxy.getChannelVerfication(aliceBytes); assertEq(aliceVerification, 0); assertEq(bobVerification, aliceVerification); @@ -51,9 +58,9 @@ contract ChannelVerification_Test is BasePushCoreTest { // it should return primary verified for channels verified by admin changePrank(actor.admin); vm.expectRevert(Errors.Core_InvalidChannel.selector); - coreProxy.verifyChannel(actor.tim_push_holder); + coreProxy.verifyChannel(toWormholeFormat(actor.tim_push_holder)); - uint8 timVerification = coreProxy.getChannelVerfication(actor.tim_push_holder); + uint8 timVerification = coreProxy.getChannelVerfication(toWormholeFormat(actor.tim_push_holder)); assertEq(timVerification, 0); address Tim_verifiedBy = _getVerifiedBy(actor.tim_push_holder); @@ -65,9 +72,9 @@ contract ChannelVerification_Test is BasePushCoreTest { changePrank(actor.admin); vm.expectEmit(true, true, false, false); emit ChannelVerified(channelCreators.bob_channel_owner_Bytes32, actor.admin); - coreProxy.verifyChannel(actor.bob_channel_owner); + coreProxy.verifyChannel(bobBytes); - uint8 bobVerification = coreProxy.getChannelVerfication(actor.bob_channel_owner); + uint8 bobVerification = coreProxy.getChannelVerfication(bobBytes); assertEq(bobVerification, 1); address Bob_verifiedBy = _getVerifiedBy(actor.bob_channel_owner); @@ -79,14 +86,14 @@ contract ChannelVerification_Test is BasePushCoreTest { changePrank(actor.admin); vm.expectEmit(true, true, false, false); emit ChannelVerified(channelCreators.bob_channel_owner_Bytes32, actor.admin); - coreProxy.verifyChannel(actor.bob_channel_owner); + coreProxy.verifyChannel(bobBytes); changePrank(actor.bob_channel_owner); vm.expectEmit(true, true, false, false); emit ChannelVerified(channelCreators.alice_channel_owner_Bytes32, actor.bob_channel_owner); - coreProxy.verifyChannel(actor.alice_channel_owner); + coreProxy.verifyChannel(aliceBytes); - uint8 aliceVerification = coreProxy.getChannelVerfication(actor.alice_channel_owner); + uint8 aliceVerification = coreProxy.getChannelVerfication(aliceBytes); assertEq(aliceVerification, 2); address Alice_verifiedBy = _getVerifiedBy(actor.alice_channel_owner); @@ -97,9 +104,9 @@ contract ChannelVerification_Test is BasePushCoreTest { // it should REVERT vm.expectRevert(abi.encodeWithSelector(Errors.UnauthorizedCaller.selector, actor.bob_channel_owner)); changePrank(actor.bob_channel_owner); - coreProxy.verifyChannel(actor.alice_channel_owner); + coreProxy.verifyChannel(aliceBytes); - uint8 aliceVerification = coreProxy.getChannelVerfication(actor.alice_channel_owner); + uint8 aliceVerification = coreProxy.getChannelVerfication(aliceBytes); assertEq(aliceVerification, 0); address Alice_verifiedBy = _getVerifiedBy(actor.alice_channel_owner); @@ -111,14 +118,14 @@ contract ChannelVerification_Test is BasePushCoreTest { changePrank(actor.admin); vm.expectEmit(true, true, false, false); emit ChannelVerified(channelCreators.bob_channel_owner_Bytes32, actor.admin); - coreProxy.verifyChannel(actor.bob_channel_owner); + coreProxy.verifyChannel(bobBytes); vm.expectEmit(true, true, false, false); emit ChannelVerified(channelCreators.alice_channel_owner_Bytes32, actor.bob_channel_owner); changePrank(actor.bob_channel_owner); - coreProxy.verifyChannel(actor.alice_channel_owner); + coreProxy.verifyChannel(aliceBytes); - uint8 aliceVerificationBefore = coreProxy.getChannelVerfication(actor.alice_channel_owner); + uint8 aliceVerificationBefore = coreProxy.getChannelVerfication(aliceBytes); assertEq(aliceVerificationBefore, 2); address Alice_verifiedByBefore = _getVerifiedBy(actor.alice_channel_owner); @@ -127,9 +134,9 @@ contract ChannelVerification_Test is BasePushCoreTest { changePrank(actor.admin); vm.expectEmit(true, true, false, false); emit ChannelVerified(channelCreators.alice_channel_owner_Bytes32, actor.admin); - coreProxy.verifyChannel(actor.alice_channel_owner); + coreProxy.verifyChannel(aliceBytes); - uint8 aliceVerificationAfter = coreProxy.getChannelVerfication(actor.alice_channel_owner); + uint8 aliceVerificationAfter = coreProxy.getChannelVerfication(aliceBytes); assertEq(aliceVerificationAfter, 1); address Alice_verifiedByAfter = _getVerifiedBy(actor.alice_channel_owner); @@ -142,13 +149,13 @@ contract ChannelVerification_Test is BasePushCoreTest { changePrank(actor.admin); vm.expectEmit(true, true, false, false); emit ChannelVerified(channelCreators.bob_channel_owner_Bytes32, actor.admin); - coreProxy.verifyChannel(actor.bob_channel_owner); + coreProxy.verifyChannel(bobBytes); vm.expectEmit(true, true, false, false); emit ChannelVerified(channelCreators.alice_channel_owner_Bytes32, actor.admin); - coreProxy.verifyChannel(actor.alice_channel_owner); + coreProxy.verifyChannel(aliceBytes); - uint8 aliceVerificationBefore = coreProxy.getChannelVerfication(actor.alice_channel_owner); + uint8 aliceVerificationBefore = coreProxy.getChannelVerfication(aliceBytes); assertEq(aliceVerificationBefore, 1); address Alice_verifiedByBefore = _getVerifiedBy(actor.alice_channel_owner); @@ -156,9 +163,9 @@ contract ChannelVerification_Test is BasePushCoreTest { vm.expectRevert(Errors.Core_InvalidChannel.selector); changePrank(actor.bob_channel_owner); - coreProxy.verifyChannel(actor.alice_channel_owner); + coreProxy.verifyChannel(aliceBytes); - uint8 aliceVerificationAfter = coreProxy.getChannelVerfication(actor.alice_channel_owner); + uint8 aliceVerificationAfter = coreProxy.getChannelVerfication(aliceBytes); assertEq(aliceVerificationAfter, 1); address Alice_verifiedByAfter = _getVerifiedBy(actor.alice_channel_owner); @@ -170,19 +177,19 @@ contract ChannelVerification_Test is BasePushCoreTest { changePrank(actor.admin); vm.expectEmit(true, true, false, false); emit ChannelVerified(channelCreators.bob_channel_owner_Bytes32, actor.admin); - coreProxy.verifyChannel(actor.bob_channel_owner); + coreProxy.verifyChannel(bobBytes); changePrank(actor.bob_channel_owner); vm.expectEmit(true, true, false, false); emit ChannelVerified(channelCreators.charlie_channel_owner_Bytes32, actor.bob_channel_owner); - coreProxy.verifyChannel(actor.charlie_channel_owner); + coreProxy.verifyChannel(charlieBytes); changePrank(actor.charlie_channel_owner); vm.expectEmit(true, true, false, false); emit ChannelVerified(channelCreators.alice_channel_owner_Bytes32, actor.charlie_channel_owner); - coreProxy.verifyChannel(actor.alice_channel_owner); + coreProxy.verifyChannel(aliceBytes); - uint8 aliceVerification = coreProxy.getChannelVerfication(actor.alice_channel_owner); + uint8 aliceVerification = coreProxy.getChannelVerfication(aliceBytes); assertEq(aliceVerification, 2); address Alice_verifiedBy = _getVerifiedBy(actor.alice_channel_owner); @@ -191,15 +198,15 @@ contract ChannelVerification_Test is BasePushCoreTest { function test_RevertWhen_NonAdminCalls_BatchVerification() external { // it should REVERT- not allowing anyone other than Admin - address[] memory _channels = new address[](2); - _channels[0] = actor.charlie_channel_owner; - _channels[1] = actor.alice_channel_owner; + bytes32[] memory _channels = new bytes32[](2); + _channels[0] = charlieBytes; + _channels[1] = aliceBytes; vm.expectRevert(Errors.CallerNotAdmin.selector); changePrank(actor.bob_channel_owner); coreProxy.batchVerification(0, 2, _channels); - uint8 charlieVerificationAfter = coreProxy.getChannelVerfication(actor.charlie_channel_owner); - uint8 aliceVerificationAfter = coreProxy.getChannelVerfication(actor.alice_channel_owner); + uint8 charlieVerificationAfter = coreProxy.getChannelVerfication(charlieBytes); + uint8 aliceVerificationAfter = coreProxy.getChannelVerfication(aliceBytes); assertEq(charlieVerificationAfter, 0, "charlie"); assertEq(aliceVerificationAfter, 0, "alice"); @@ -207,10 +214,10 @@ contract ChannelVerification_Test is BasePushCoreTest { function test_WhenAdminCalls_BatchVerification() external { // it should execute and set the verifications to primary - address[] memory _channels = new address[](3); - _channels[0] = actor.charlie_channel_owner; - _channels[1] = actor.bob_channel_owner; - _channels[2] = actor.alice_channel_owner; + bytes32[] memory _channels = new bytes32[](3); + _channels[0] = charlieBytes; + _channels[1] = bobBytes; + _channels[2] = aliceBytes; changePrank(actor.admin); vm.expectEmit(true, true, false, false); @@ -221,9 +228,9 @@ contract ChannelVerification_Test is BasePushCoreTest { emit ChannelVerified(channelCreators.alice_channel_owner_Bytes32, actor.admin); coreProxy.batchVerification(0, 3, _channels); - uint8 charlieVerificationAfter = coreProxy.getChannelVerfication(actor.charlie_channel_owner); - uint8 aliceVerificationAfter = coreProxy.getChannelVerfication(actor.alice_channel_owner); - uint8 bobVerificationAfter = coreProxy.getChannelVerfication(actor.bob_channel_owner); + uint8 charlieVerificationAfter = coreProxy.getChannelVerfication(charlieBytes); + uint8 aliceVerificationAfter = coreProxy.getChannelVerfication(aliceBytes); + uint8 bobVerificationAfter = coreProxy.getChannelVerfication(bobBytes); assertEq(charlieVerificationAfter, 1, "charlie"); assertEq(aliceVerificationAfter, 1, "alice"); diff --git a/test/PushCore/unit_tests/ContractPausability/contractPausability.t.sol b/test/PushCore/unit_tests/ContractPausability/contractPausability.t.sol index ee64c97c..4354bf86 100644 --- a/test/PushCore/unit_tests/ContractPausability/contractPausability.t.sol +++ b/test/PushCore/unit_tests/ContractPausability/contractPausability.t.sol @@ -83,7 +83,7 @@ contract ContractPausability_Test is BasePushCoreTest { vm.expectRevert("Pausable: paused"); vm.prank(actor.admin); - coreProxy.blockChannel(actor.bob_channel_owner); + coreProxy.blockChannel(toWormholeFormat(actor.bob_channel_owner)); } function test_ChannelFunctionsAfterPauseUnpause() public { @@ -99,6 +99,6 @@ contract ContractPausability_Test is BasePushCoreTest { vm.stopPrank(); vm.prank(actor.admin); - coreProxy.blockChannel(actor.bob_channel_owner); + coreProxy.blockChannel(toWormholeFormat(actor.bob_channel_owner)); } } From e8e17b1f5924ce27958e1dad005b7af51f3ec70e Mon Sep 17 00:00:00 2001 From: Md Zartaj Afser Date: Fri, 26 Jul 2024 12:58:06 +0530 Subject: [PATCH 07/23] Add CCR support for updateChannelMeta --- contracts/PushComm/PushCommV3.sol | 2 - contracts/PushCore/PushCoreStorageV2.sol | 4 +- contracts/PushCore/PushCoreV3.sol | 35 ++--- contracts/interfaces/IPushCoreV3.sol | 2 +- contracts/libraries/DataTypes.sol | 3 +- test/CCR/CCRutils/Helper.sol | 9 +- .../UpdateChannelMetaCCR.t.sol | 145 ++++++++++++++++++ .../UpdateChannelMetaCCR.tree | 17 ++ .../ChannelUpdation/updateChannelMeta.t.sol | 40 ++--- 9 files changed, 200 insertions(+), 57 deletions(-) create mode 100644 test/CCR/SpecificRequest/UpdateChannelMetaCCR/UpdateChannelMetaCCR.t.sol create mode 100644 test/CCR/SpecificRequest/UpdateChannelMetaCCR/UpdateChannelMetaCCR.tree diff --git a/contracts/PushComm/PushCommV3.sol b/contracts/PushComm/PushCommV3.sol index 38dc561d..4ed5501d 100644 --- a/contracts/PushComm/PushCommV3.sol +++ b/contracts/PushComm/PushCommV3.sol @@ -627,8 +627,6 @@ contract PushCommV3 is Initializable, PushCommStorageV2, IPushCommV3, PausableUp if (amount == 0) { revert Errors.InvalidArg_LessThanExpected(1, amount); } - } else { - revert Errors.Comm_InvalidCrossChain_Function(); } bytes memory requestPayload = abi.encode(functionType, payload, amount, msg.sender); diff --git a/contracts/PushCore/PushCoreStorageV2.sol b/contracts/PushCore/PushCoreStorageV2.sol index 5ce718ba..d76dc3e1 100644 --- a/contracts/PushCore/PushCoreStorageV2.sol +++ b/contracts/PushCore/PushCoreStorageV2.sol @@ -11,7 +11,7 @@ contract PushCoreStorageV2 { ); mapping(address => uint256) public nonces; // NOT IN USE Anymore - mapping(address => uint256) public channelUpdateCounter; + mapping(address => uint256) public oldChannelUpdateCounter;//NOT in use anymore /** * Staking V2 state variables * */ @@ -49,5 +49,5 @@ contract PushCoreStorageV2 { // of adding new state mapping(bytes32 => CoreTypes.Channel) public channelInfo; - mapping(bytes32 => uint256) public ChannelUpdateCounter; + mapping(bytes32 => uint256) public channelUpdateCounter; } diff --git a/contracts/PushCore/PushCoreV3.sol b/contracts/PushCore/PushCoreV3.sol index 51e753e7..f23f5d19 100644 --- a/contracts/PushCore/PushCoreV3.sol +++ b/contracts/PushCore/PushCoreV3.sol @@ -157,15 +157,15 @@ contract PushCoreV3 is **************************************/ ///@inheritdoc IPushCoreV3 - // ToDo: Check if updateChannelMeta is required for Cross-Chain-Req feature. If yes, it needs its own private - // function - function updateChannelMeta(address _channel, bytes calldata _newIdentity, uint256 _amount) external whenNotPaused { - onlyActivatedChannels(BaseHelper.addressToBytes32(_channel)); + function updateChannelMeta(bytes calldata _newIdentity, uint256 _amount) external whenNotPaused { + bytes32 _channel = BaseHelper.addressToBytes32(msg.sender); - if (msg.sender != _channel) { - revert Errors.UnauthorizedCaller(msg.sender); - } + IERC20(PUSH_TOKEN_ADDRESS).safeTransferFrom(msg.sender, address(this), _amount); + _updateChannelMeta(_channel, _newIdentity, _amount); + } + function _updateChannelMeta(bytes32 _channel, bytes memory _newIdentity, uint256 _amount) internal { + onlyActivatedChannels(_channel); uint256 updateCounter = channelUpdateCounter[_channel] + 1; uint256 requiredFees = ADD_CHANNEL_MIN_FEES * updateCounter; @@ -176,11 +176,9 @@ contract PushCoreV3 is PROTOCOL_POOL_FEES = PROTOCOL_POOL_FEES + _amount; channelUpdateCounter[_channel] = updateCounter; - bytes32 _channelBytesID = BaseHelper.addressToBytes32(msg.sender); - channelInfo[_channelBytesID].channelUpdateBlock = block.number; + channelInfo[_channel].channelUpdateBlock = block.number; - IERC20(PUSH_TOKEN_ADDRESS).safeTransferFrom(_channel, address(this), _amount); - emit UpdateChannel(_channelBytesID, _newIdentity, _amount); + emit UpdateChannel(_channel, _newIdentity, _amount); } /// @inheritdoc IPushCoreV3 @@ -861,21 +859,16 @@ contract PushCoreV3 is } else if (functionType == CrossChainRequestTypes.CrossChainFunction.IncentivizedChat) { // Specific Request: Incentivized Chat (bytes32 amountRecipient) = abi.decode(structPayload, (bytes32)); - _handleIncentivizedChat( - sender, BaseHelper.bytes32ToAddress(amountRecipient), amount - ); + _handleIncentivizedChat(sender, BaseHelper.bytes32ToAddress(amountRecipient), amount); + } else if (functionType == CrossChainRequestTypes.CrossChainFunction.UpdateChannelMeta) { + (bytes memory _newIdentity) = abi.decode(structPayload, (bytes)); + _updateChannelMeta(sender, _newIdentity, amount); } else if (functionType == CrossChainRequestTypes.CrossChainFunction.ArbitraryRequest) { // Arbitrary Request (uint8 feeId, GenericTypes.Percentage memory feePercentage, bytes32 amountRecipient) = abi.decode(structPayload, (uint8, GenericTypes.Percentage, bytes32)); - _handleArbitraryRequest( - sender, - feeId, - feePercentage, - BaseHelper.bytes32ToAddress(amountRecipient), - amount - ); + _handleArbitraryRequest(sender, feeId, feePercentage, BaseHelper.bytes32ToAddress(amountRecipient), amount); } else if (functionType == CrossChainRequestTypes.CrossChainFunction.AdminRequest_AddPoolFee) { // Admin Request PROTOCOL_POOL_FEES += amount; diff --git a/contracts/interfaces/IPushCoreV3.sol b/contracts/interfaces/IPushCoreV3.sol index a80cdcd9..da6b9272 100644 --- a/contracts/interfaces/IPushCoreV3.sol +++ b/contracts/interfaces/IPushCoreV3.sol @@ -103,7 +103,7 @@ interface IPushCoreV3 { * @param _amount amount of PUSH Token required for updating channel details. * */ - function updateChannelMeta(address _channel, bytes calldata _newIdentity, uint256 _amount) external; + function updateChannelMeta(bytes calldata _newIdentity, uint256 _amount) external; /** * @notice An external function that allows users to Create their Own Channels by depositing a valid amount of PUSH diff --git a/contracts/libraries/DataTypes.sol b/contracts/libraries/DataTypes.sol index d5bacb21..cffb9e85 100644 --- a/contracts/libraries/DataTypes.sol +++ b/contracts/libraries/DataTypes.sol @@ -116,7 +116,8 @@ library CrossChainRequestTypes { AddChannel, IncentivizedChat, ArbitraryRequest, - AdminRequest_AddPoolFee + AdminRequest_AddPoolFee, + UpdateChannelMeta } } diff --git a/test/CCR/CCRutils/Helper.sol b/test/CCR/CCRutils/Helper.sol index 8317c016..b2d4b30c 100644 --- a/test/CCR/CCRutils/Helper.sol +++ b/test/CCR/CCRutils/Helper.sol @@ -15,6 +15,7 @@ import { Vm } from "forge-std/Vm.sol"; contract Helper is BasePushCommTest, CCRConfig { // Set Source and dest chains + bytes _newTestChannelIdentity = bytes("test-updated-channel-hello-world"); SourceConfig SourceChain = ArbSepolia; DestConfig DestChain = EthSepolia; @@ -92,7 +93,7 @@ contract Helper is BasePushCommTest, CCRConfig { bytes32 sender ) internal - pure + view returns (bytes memory payload, bytes memory reqPayload) { if (typeOfReq == CrossChainRequestTypes.CrossChainFunction.AddChannel) { @@ -106,6 +107,12 @@ contract Helper is BasePushCommTest, CCRConfig { } else if (typeOfReq == CrossChainRequestTypes.CrossChainFunction.ArbitraryRequest) { payload = abi.encode(_feeId, _percentage, amountRecipient); + reqPayload = abi.encode(typeOfReq, payload, amount, sender); + } + else if (typeOfReq == CrossChainRequestTypes.CrossChainFunction.UpdateChannelMeta) { + + payload = abi.encode(_newTestChannelIdentity); + reqPayload = abi.encode(typeOfReq, payload, amount, sender); } } diff --git a/test/CCR/SpecificRequest/UpdateChannelMetaCCR/UpdateChannelMetaCCR.t.sol b/test/CCR/SpecificRequest/UpdateChannelMetaCCR/UpdateChannelMetaCCR.t.sol new file mode 100644 index 00000000..8e919dd1 --- /dev/null +++ b/test/CCR/SpecificRequest/UpdateChannelMetaCCR/UpdateChannelMetaCCR.t.sol @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +import { BaseCCRTest } from "../../BaseCCR.t.sol"; +import { Errors } from ".././../../../contracts/libraries/Errors.sol"; +import { console } from "forge-std/console.sol"; + +import { CrossChainRequestTypes } from "../../../../contracts/libraries/DataTypes.sol"; +import { BaseHelper } from "contracts/libraries/BaseHelper.sol"; + +contract CreateChatCCR is BaseCCRTest { + uint256 amount; + + function setUp() public override { + BaseCCRTest.setUp(); + amount = (coreProxy.channelUpdateCounter(toWormholeFormat(actor.bob_channel_owner)) + 1) * ADD_CHANNEL_MIN_FEES; + sourceAddress = toWormholeFormat(address(commProxy)); + (_payload, requestPayload) = getSpecificPayload( + CrossChainRequestTypes.CrossChainFunction.UpdateChannelMeta, + BaseHelper.addressToBytes32(address(0)), + amount, + 0, + percentage, + BaseHelper.addressToBytes32(actor.bob_channel_owner) + ); + } + + modifier whencreateCrossChainReqIsCalled() { + _; + } + + function test_WhenContractIsPaused() external whencreateCrossChainReqIsCalled { + // it should Revert + + changePrank(actor.admin); + commProxy.pauseContract(); + vm.expectRevert("Pausable: paused"); + changePrank(actor.bob_channel_owner); + commProxy.createCrossChainRequest( + CrossChainRequestTypes.CrossChainFunction.UpdateChannelMeta, _payload, amount, GasLimit + ); + } + + function test_RevertWhen_EtherPassedIsLess() external whencreateCrossChainReqIsCalled { + // it should revert + vm.expectRevert(abi.encodeWithSelector(Errors.InsufficientFunds.selector)); + changePrank(actor.bob_channel_owner); + commProxy.createCrossChainRequest( + CrossChainRequestTypes.CrossChainFunction.UpdateChannelMeta, _payload, amount, GasLimit + ); + } + + function test_WhenAllChecksPasses() public whencreateCrossChainReqIsCalled { + // it should successfully create the CCR + vm.expectEmit(true, false, false, false); + emit LogMessagePublished(SourceChain.WORMHOLE_RELAYER_SOURCE, 2105, 0, requestPayload, 15); + changePrank(actor.bob_channel_owner); + commProxy.createCrossChainRequest{ value: 1e18 }( + CrossChainRequestTypes.CrossChainFunction.UpdateChannelMeta, _payload, amount, GasLimit + ); + } + + modifier whenReceiveFunctionIsCalledInCore() { + test_WhenAllChecksPasses(); + setUpDestChain(); + _; + } + + function test_WhenSenderIsNotRegistered() external whenReceiveFunctionIsCalledInCore { + // it should Revert + + //set sender to zero address + coreProxy.setRegisteredSender(SourceChain.SourceChainId, toWormholeFormat(address(0))); + + vm.expectRevert("Not registered sender"); + receiveWormholeMessage(requestPayload); + } + + function test_WhenSenderIsNotRelayer() external whenReceiveFunctionIsCalledInCore { + // it should Revert + + coreProxy.setWormholeRelayer(address(0)); + vm.expectRevert(abi.encodeWithSelector(Errors.CallerNotAdmin.selector)); + receiveWormholeMessage(requestPayload); + } + + function test_WhenDeliveryHashIsUsedAlready() external whenReceiveFunctionIsCalledInCore { + // it should Revert + + receiveWormholeMessage(requestPayload); + vm.expectRevert(abi.encodeWithSelector(Errors.Payload_Duplicacy_Error.selector)); + receiveWormholeMessage(requestPayload); + } + + function test_whenReceiveChecksPass() public whenReceiveFunctionIsCalledInCore { + // it should emit event and create Channel + + uint256 PROTOCOL_POOL_FEES = coreProxy.PROTOCOL_POOL_FEES(); + uint256 oldCounter = coreProxy.channelUpdateCounter(toWormholeFormat(actor.bob_channel_owner)); + + vm.expectEmit(true, true, false, true); + emit UpdateChannel(toWormholeFormat(actor.bob_channel_owner), _newTestChannelIdentity, amount); + + receiveWormholeMessage(requestPayload); + ( + , + , + , + , + , + , + , + , + uint256 channelUpdateBlock, + , + ) = coreProxy.channelInfo(toWormholeFormat(actor.bob_channel_owner)); + assertEq(coreProxy.PROTOCOL_POOL_FEES(), PROTOCOL_POOL_FEES + amount); + assertEq(coreProxy.channelUpdateCounter(toWormholeFormat(actor.bob_channel_owner)), oldCounter + 1); + assertEq(channelUpdateBlock, block.number); + } + + function test_whenTokensAreTransferred() external { + vm.recordLogs(); + test_whenReceiveChecksPass(); + (address sourceNttManager, bytes32 recipient, uint256 _amount, uint16 recipientChain) = + getMessagefromLog(vm.getRecordedLogs()); + + console.log(pushNttToken.balanceOf(address(coreProxy))); + + bytes[] memory a; + (bytes memory transceiverMessage, bytes32 hash) = + getRequestPayload(_amount, recipient, recipientChain, sourceNttManager); + + changePrank(DestChain.WORMHOLE_RELAYER_DEST); + DestChain.wormholeTransceiverChain2.receiveWormholeMessages( + transceiverMessage, // Verified + a, // Should be zero + bytes32(uint256(uint160(address(SourceChain.wormholeTransceiverChain1)))), // Must be a wormhole peers + 10_003, // ChainID from the call + hash // Hash of the VAA being used + ); + + assertEq(pushNttToken.balanceOf(address(coreProxy)), amount); + } +} diff --git a/test/CCR/SpecificRequest/UpdateChannelMetaCCR/UpdateChannelMetaCCR.tree b/test/CCR/SpecificRequest/UpdateChannelMetaCCR/UpdateChannelMetaCCR.tree new file mode 100644 index 00000000..c0680ed2 --- /dev/null +++ b/test/CCR/SpecificRequest/UpdateChannelMetaCCR/UpdateChannelMetaCCR.tree @@ -0,0 +1,17 @@ +CreateChatCCR.t.sol +├── when createCrossChainReq is called +│ ├── when contract is paused +│ │ └── it should Revert +│ ├── when ether passed is less +│ │ └── it should revert +│ └── when all checks passes +│ └── it should successfully create the CCR +└── when receive function is called in core + ├── when sender is not registered + │ └── it should Revert + ├── when sender is not relayer + │ └── it should Revert + ├── when deliveryHash is used already + │ └── it should Revert + └── when all checks pass + └── it should emit event and update storage \ No newline at end of file diff --git a/test/PushCore/unit_tests/ChannelUpdation/updateChannelMeta.t.sol b/test/PushCore/unit_tests/ChannelUpdation/updateChannelMeta.t.sol index adbda38d..5fcc6d88 100644 --- a/test/PushCore/unit_tests/ChannelUpdation/updateChannelMeta.t.sol +++ b/test/PushCore/unit_tests/ChannelUpdation/updateChannelMeta.t.sol @@ -17,7 +17,7 @@ contract UpdateChannelMeta_Test is BasePushCoreTest { vm.prank(actor.bob_channel_owner); vm.expectRevert(abi.encodeWithSelector(Errors.Core_InvalidChannel.selector)); - coreProxy.updateChannelMeta(actor.bob_channel_owner, _testChannelUpdatedIdentity, _amountBeingTransferred); + coreProxy.updateChannelMeta( _testChannelUpdatedIdentity, _amountBeingTransferred); } // Todo - fix updateChannelState function - Test case fails until then @@ -29,25 +29,7 @@ contract UpdateChannelMeta_Test is BasePushCoreTest { vm.prank(actor.bob_channel_owner); vm.expectRevert(abi.encodeWithSelector(Errors.Core_InvalidChannel.selector)); - coreProxy.updateChannelMeta(actor.bob_channel_owner, _testChannelUpdatedIdentity, _amountBeingTransferred); - } - - function test_Revertwhen_CallerNotChannelOwner() public whenNotPaused { - uint256 _amountBeingTransferred = ADD_CHANNEL_MIN_FEES; - _createChannel(actor.bob_channel_owner); - - vm.prank(actor.charlie_channel_owner); - vm.expectRevert(abi.encodeWithSelector(Errors.UnauthorizedCaller.selector, actor.charlie_channel_owner)); - coreProxy.updateChannelMeta(actor.bob_channel_owner, _testChannelUpdatedIdentity, _amountBeingTransferred); - } - - function test_Revertwhen_UpdateZeroAddressChannel() public whenNotPaused { - uint256 _amountBeingTransferred = ADD_CHANNEL_MIN_FEES; - address _channelAddress = address(0x0); - - vm.prank(actor.bob_channel_owner); - vm.expectRevert(abi.encodeWithSelector(Errors.Core_InvalidChannel.selector)); - coreProxy.updateChannelMeta(_channelAddress, _testChannelUpdatedIdentity, _amountBeingTransferred); + coreProxy.updateChannelMeta( _testChannelUpdatedIdentity, _amountBeingTransferred); } function test_Revertwhen_AmountLessThanRequiredFees() public whenNotPaused { @@ -60,7 +42,7 @@ contract UpdateChannelMeta_Test is BasePushCoreTest { Errors.InvalidArg_LessThanExpected.selector, ADD_CHANNEL_MIN_FEES, _amountBeingTransferred ) ); - coreProxy.updateChannelMeta(actor.bob_channel_owner, _testChannelUpdatedIdentity, _amountBeingTransferred); + coreProxy.updateChannelMeta( _testChannelUpdatedIdentity, _amountBeingTransferred); } function test_Revertwhen_AmountLessThanRequiredFeesForSecondUpdate() public whenNotPaused { @@ -68,14 +50,14 @@ contract UpdateChannelMeta_Test is BasePushCoreTest { _createChannel(actor.bob_channel_owner); vm.startPrank(actor.bob_channel_owner); - coreProxy.updateChannelMeta(actor.bob_channel_owner, _testChannelUpdatedIdentity, _amountBeingTransferred); + coreProxy.updateChannelMeta( _testChannelUpdatedIdentity, _amountBeingTransferred); vm.expectRevert( abi.encodeWithSelector( Errors.InvalidArg_LessThanExpected.selector, ADD_CHANNEL_MIN_FEES * 2, _amountBeingTransferred ) ); - coreProxy.updateChannelMeta(actor.bob_channel_owner, _testChannelUpdatedIdentity, _amountBeingTransferred); + coreProxy.updateChannelMeta( _testChannelUpdatedIdentity, _amountBeingTransferred); vm.stopPrank(); } @@ -89,7 +71,7 @@ contract UpdateChannelMeta_Test is BasePushCoreTest { approveTokens(actor.bob_channel_owner, address(coreProxy), _amountBeingTransferred); vm.prank(actor.bob_channel_owner); - coreProxy.updateChannelMeta(actor.bob_channel_owner, _testChannelUpdatedIdentity, _amountBeingTransferred); + coreProxy.updateChannelMeta( _testChannelUpdatedIdentity, _amountBeingTransferred); } } @@ -105,7 +87,7 @@ contract UpdateChannelMeta_Test is BasePushCoreTest { uint256 _balanceOfPushTokensBeforeUpdateInProxy = pushToken.balanceOf(address(coreProxy)); vm.prank(actor.bob_channel_owner); - coreProxy.updateChannelMeta(actor.bob_channel_owner, _testChannelUpdatedIdentity, _amountBeingTransferred); + coreProxy.updateChannelMeta( _testChannelUpdatedIdentity, _amountBeingTransferred); uint256 _balanceOfPushTokensAfterUpdateInProxy = pushToken.balanceOf(address(coreProxy)); assertEq( @@ -125,9 +107,9 @@ contract UpdateChannelMeta_Test is BasePushCoreTest { approveTokens(actor.bob_channel_owner, address(coreProxy), _amountBeingTransferred); vm.prank(actor.bob_channel_owner); - coreProxy.updateChannelMeta(actor.bob_channel_owner, _testChannelUpdatedIdentity, _amountBeingTransferred); + coreProxy.updateChannelMeta( _testChannelUpdatedIdentity, _amountBeingTransferred); - uint256 _channelUpdateCounterAfter = coreProxy.channelUpdateCounter(actor.bob_channel_owner); + uint256 _channelUpdateCounterAfter = coreProxy.channelUpdateCounter(toWormholeFormat(actor.bob_channel_owner)); uint256 _channelUpdateBlock = _getChannelUpdateBlock(actor.bob_channel_owner); assertEq(_channelUpdateCounterAfter, i + 1); assertEq(_channelUpdateBlock, block.number); @@ -142,7 +124,7 @@ contract UpdateChannelMeta_Test is BasePushCoreTest { uint256 channelPoolFundsBeforeUpdate = coreProxy.CHANNEL_POOL_FUNDS(); vm.prank(actor.bob_channel_owner); - coreProxy.updateChannelMeta(actor.bob_channel_owner, _testChannelUpdatedIdentity, _amountBeingTransferred); + coreProxy.updateChannelMeta( _testChannelUpdatedIdentity, _amountBeingTransferred); uint256 expectedProtocolPoolFees = poolFeesBeforeUpdate + _amountBeingTransferred; uint256 expectedChannelPoolFunds = channelPoolFundsBeforeUpdate; @@ -161,7 +143,7 @@ contract UpdateChannelMeta_Test is BasePushCoreTest { ); vm.prank(actor.bob_channel_owner); - coreProxy.updateChannelMeta(actor.bob_channel_owner, _testChannelUpdatedIdentity, _amountBeingTransferred); + coreProxy.updateChannelMeta( _testChannelUpdatedIdentity, _amountBeingTransferred); } // Zero-Address Channel Support - Now Deprecated From f93cdb55d683516809ca8ed9275d64e0ef5f94ca Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Fri, 26 Jul 2024 15:06:59 +0530 Subject: [PATCH 08/23] feat: add ccr support for createChannelSettings fn --- contracts/PushComm/PushCommV3.sol | 6 +- contracts/PushCore/PushCoreV3.sol | 14 +- contracts/libraries/DataTypes.sol | 1 + .../ArbitraryRequest/ArbitraryRequest.t.sol | 3 + test/CCR/CCRutils/Helper.sol | 12 +- .../CreateChannelCCR/CreateChannelCCR.t.sol | 3 + .../CreateChannelSettingsCCR.sol | 158 ++++++++++++++++++ .../CreateChannelSettingsCCR.tree | 19 +++ .../CreateChatCCR/CreateChatCCR.t.sol | 3 + test/utils/Events.sol | 1 + 10 files changed, 208 insertions(+), 12 deletions(-) create mode 100644 test/CCR/SpecificRequest/CreateChannelSettingsCCR/CreateChannelSettingsCCR.sol create mode 100644 test/CCR/SpecificRequest/CreateChannelSettingsCCR/CreateChannelSettingsCCR.tree diff --git a/contracts/PushComm/PushCommV3.sol b/contracts/PushComm/PushCommV3.sol index 38dc561d..b679b0d6 100644 --- a/contracts/PushComm/PushCommV3.sol +++ b/contracts/PushComm/PushCommV3.sol @@ -623,12 +623,14 @@ contract PushCommV3 is Initializable, PushCommStorageV2, IPushCommV3, PausableUp if (amount < FEE_AMOUNT) { revert Errors.InvalidArg_LessThanExpected(FEE_AMOUNT, amount); } + } else if (functionType == CrossChainRequestTypes.CrossChainFunction.CreateChannelSettings) { + if (amount < ADD_CHANNEL_MIN_FEES) { + revert Errors.InvalidArg_LessThanExpected(ADD_CHANNEL_MIN_FEES, amount); + } } else if (functionType == CrossChainRequestTypes.CrossChainFunction.ArbitraryRequest) { if (amount == 0) { revert Errors.InvalidArg_LessThanExpected(1, amount); } - } else { - revert Errors.Comm_InvalidCrossChain_Function(); } bytes memory requestPayload = abi.encode(functionType, payload, amount, msg.sender); diff --git a/contracts/PushCore/PushCoreV3.sol b/contracts/PushCore/PushCoreV3.sol index 51e753e7..d6ea181e 100644 --- a/contracts/PushCore/PushCoreV3.sol +++ b/contracts/PushCore/PushCoreV3.sol @@ -271,21 +271,23 @@ contract PushCoreV3 is if (_amountDeposited < ADD_CHANNEL_MIN_FEES) { revert Errors.InvalidArg_LessThanExpected(ADD_CHANNEL_MIN_FEES, _amountDeposited); } - PROTOCOL_POOL_FEES = PROTOCOL_POOL_FEES + _amountDeposited; + IERC20(PUSH_TOKEN_ADDRESS).safeTransferFrom(msg.sender, address(this), _amountDeposited); bytes32 _channelBytesID = BaseHelper.addressToBytes32(msg.sender); - _createSettings(_channelBytesID, _notifOptions, _notifSettings, _notifDescription); + _createSettings(_channelBytesID, _notifOptions, _amountDeposited, _notifSettings, _notifDescription); } function _createSettings( bytes32 _channel, uint256 _notifOptions, - string calldata _notifSettings, - string calldata _notifDescription + uint256 _amountDeposited, + string memory _notifSettings, + string memory _notifDescription ) private { + PROTOCOL_POOL_FEES = PROTOCOL_POOL_FEES + _amountDeposited; string memory notifSetting = string(abi.encodePacked(Strings.toString(_notifOptions), "+", _notifSettings)); emit ChannelNotifcationSettingsAdded(_channel, _notifOptions, notifSetting, _notifDescription); @@ -864,6 +866,10 @@ contract PushCoreV3 is _handleIncentivizedChat( sender, BaseHelper.bytes32ToAddress(amountRecipient), amount ); + } else if (functionType == CrossChainRequestTypes.CrossChainFunction.CreateChannelSettings) { + (uint256 _notifOptions, string memory _notifSettings, string memory _notifDescription) = + abi.decode(structPayload, (uint256, string, string)); + _createSettings(sender, _notifOptions, amount, _notifSettings, _notifDescription); } else if (functionType == CrossChainRequestTypes.CrossChainFunction.ArbitraryRequest) { // Arbitrary Request (uint8 feeId, GenericTypes.Percentage memory feePercentage, bytes32 amountRecipient) = diff --git a/contracts/libraries/DataTypes.sol b/contracts/libraries/DataTypes.sol index d5bacb21..4d11e59b 100644 --- a/contracts/libraries/DataTypes.sol +++ b/contracts/libraries/DataTypes.sol @@ -116,6 +116,7 @@ library CrossChainRequestTypes { AddChannel, IncentivizedChat, ArbitraryRequest, + CreateChannelSettings, AdminRequest_AddPoolFee } } diff --git a/test/CCR/ArbitraryRequest/ArbitraryRequest.t.sol b/test/CCR/ArbitraryRequest/ArbitraryRequest.t.sol index 34fb53c0..a9516b9d 100644 --- a/test/CCR/ArbitraryRequest/ArbitraryRequest.t.sol +++ b/test/CCR/ArbitraryRequest/ArbitraryRequest.t.sol @@ -25,6 +25,9 @@ contract ArbitraryRequesttsol is BaseCCRTest { amount, 1, percentage, + 0, + "", + "", BaseHelper.addressToBytes32(actor.bob_channel_owner) ); } diff --git a/test/CCR/CCRutils/Helper.sol b/test/CCR/CCRutils/Helper.sol index 8317c016..231a2301 100644 --- a/test/CCR/CCRutils/Helper.sol +++ b/test/CCR/CCRutils/Helper.sol @@ -89,6 +89,9 @@ contract Helper is BasePushCommTest, CCRConfig { uint256 amount, uint8 _feeId, GenericTypes.Percentage memory _percentage, + uint256 _notifOptions, + string memory _notifSettings, + string memory _notifDescription, bytes32 sender ) internal @@ -97,17 +100,14 @@ contract Helper is BasePushCommTest, CCRConfig { { if (typeOfReq == CrossChainRequestTypes.CrossChainFunction.AddChannel) { payload = abi.encode(CoreTypes.ChannelType.InterestBearingMutual, _testChannelUpdatedIdentity, 0); - - reqPayload = abi.encode(typeOfReq, payload, amount, sender); } else if (typeOfReq == CrossChainRequestTypes.CrossChainFunction.IncentivizedChat) { payload = abi.encode(amountRecipient); - - reqPayload = abi.encode(typeOfReq, payload, amount, sender); + } else if (typeOfReq == CrossChainRequestTypes.CrossChainFunction.CreateChannelSettings) { + payload = abi.encode(_notifOptions, _notifSettings, _notifDescription); } else if (typeOfReq == CrossChainRequestTypes.CrossChainFunction.ArbitraryRequest) { payload = abi.encode(_feeId, _percentage, amountRecipient); - - reqPayload = abi.encode(typeOfReq, payload, amount, sender); } + reqPayload = abi.encode(typeOfReq, payload, amount, sender); } function receiveWormholeMessage(bytes memory _requestPayload) internal { diff --git a/test/CCR/SpecificRequest/CreateChannelCCR/CreateChannelCCR.t.sol b/test/CCR/SpecificRequest/CreateChannelCCR/CreateChannelCCR.t.sol index 0765ae3c..ab0e2f27 100644 --- a/test/CCR/SpecificRequest/CreateChannelCCR/CreateChannelCCR.t.sol +++ b/test/CCR/SpecificRequest/CreateChannelCCR/CreateChannelCCR.t.sol @@ -21,6 +21,9 @@ contract CreateChannelCCR is BaseCCRTest { amount, 0, percentage, + 0, + "", + "", BaseHelper.addressToBytes32(actor.charlie_channel_owner) ); } diff --git a/test/CCR/SpecificRequest/CreateChannelSettingsCCR/CreateChannelSettingsCCR.sol b/test/CCR/SpecificRequest/CreateChannelSettingsCCR/CreateChannelSettingsCCR.sol new file mode 100644 index 00000000..a7b3a96a --- /dev/null +++ b/test/CCR/SpecificRequest/CreateChannelSettingsCCR/CreateChannelSettingsCCR.sol @@ -0,0 +1,158 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +import { BaseCCRTest } from "../../BaseCCR.t.sol"; +import "forge-std/console.sol"; +import { CoreTypes, CrossChainRequestTypes } from "contracts/libraries/DataTypes.sol"; +import { Errors } from "contracts/libraries/Errors.sol"; +import { console } from "forge-std/console.sol"; +import "contracts/libraries/wormhole-lib/TrimmedAmount.sol"; +import { TransceiverStructs } from "contracts/libraries/wormhole-lib/TransceiverStructs.sol"; +import { BaseHelper } from "contracts/libraries/BaseHelper.sol"; +import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; + +contract CreateChannelSettingsCCR is BaseCCRTest { + uint256 amount = ADD_CHANNEL_MIN_FEES; + uint256 notifOptions = 2; + string notifSettings = "1-0+2-50-20-100"; + string notifDescription = "description"; + + function setUp() public override { + BaseCCRTest.setUp(); + sourceAddress = toWormholeFormat(address(commProxy)); + (_payload, requestPayload) = getSpecificPayload( + CrossChainRequestTypes.CrossChainFunction.CreateChannelSettings, + BaseHelper.addressToBytes32(address(0)), + amount, + 0, + percentage, + notifOptions, + notifSettings, + notifDescription, + BaseHelper.addressToBytes32(actor.charlie_channel_owner) + ); + } + + modifier whenCreateChannelSettingsIsCalled() { + _; + } + + function test_WhenContractIsPaused() external whenCreateChannelSettingsIsCalled { + // it should Revert + + changePrank(actor.admin); + commProxy.pauseContract(); + vm.expectRevert("Pausable: paused"); + changePrank(actor.charlie_channel_owner); + commProxy.createCrossChainRequest( + CrossChainRequestTypes.CrossChainFunction.CreateChannelSettings, _payload, amount, GasLimit + ); + } + + function test_RevertWhen_AmountIsLessThanMinimumFees() external whenCreateChannelSettingsIsCalled { + // it should revert + amount = 49e18; + vm.expectRevert( + abi.encodeWithSelector(Errors.InvalidArg_LessThanExpected.selector, ADD_CHANNEL_MIN_FEES, amount) + ); + changePrank(actor.charlie_channel_owner); + commProxy.createCrossChainRequest( + CrossChainRequestTypes.CrossChainFunction.CreateChannelSettings, _payload, amount, GasLimit + ); + } + + function test_RevertWhen_EtherPassedIsLess() external whenCreateChannelSettingsIsCalled { + // it should revert + vm.expectRevert(abi.encodeWithSelector(Errors.InsufficientFunds.selector)); + changePrank(actor.charlie_channel_owner); + commProxy.createCrossChainRequest( + CrossChainRequestTypes.CrossChainFunction.CreateChannelSettings, _payload, amount, GasLimit + ); + } + + function test_WhenAllChecksPasses() public whenCreateChannelSettingsIsCalled { + // it should successfully create the CCR + + vm.expectEmit(true, false, false, false); + emit LogMessagePublished(SourceChain.WORMHOLE_RELAYER_SOURCE, 2105, 0, requestPayload, 15); + changePrank(actor.charlie_channel_owner); + commProxy.createCrossChainRequest{ value: 1e18 }( + CrossChainRequestTypes.CrossChainFunction.CreateChannelSettings, _payload, amount, GasLimit + ); + } + + modifier whenReceiveFunctionIsCalledInCore() { + test_WhenAllChecksPasses(); + + setUpDestChain(); + _; + } + + function test_WhenSenderIsNotRegistered() external whenReceiveFunctionIsCalledInCore { + // it should Revert + + //set sender to zero address + coreProxy.setRegisteredSender(SourceChain.SourceChainId, toWormholeFormat(address(0))); + + vm.expectRevert("Not registered sender"); + receiveWormholeMessage(requestPayload); + } + + function test_WhenSenderIsNotRelayer() external whenReceiveFunctionIsCalledInCore { + // it should Revert + + coreProxy.setWormholeRelayer(address(0)); + vm.expectRevert(abi.encodeWithSelector(Errors.CallerNotAdmin.selector)); + receiveWormholeMessage(requestPayload); + } + + function test_WhenDeliveryHashIsUsedAlreadyw() external whenReceiveFunctionIsCalledInCore { + // it should Revert + + receiveWormholeMessage(requestPayload); + vm.expectRevert(abi.encodeWithSelector(Errors.Payload_Duplicacy_Error.selector)); + receiveWormholeMessage(requestPayload); + } + + function test_whenReceiveChecksPassa() public whenReceiveFunctionIsCalledInCore { + + uint256 PROTOCOL_POOL_FEES = coreProxy.PROTOCOL_POOL_FEES(); + changePrank(DestChain.WORMHOLE_RELAYER_DEST); + + string memory notifSettingRes = string(abi.encodePacked(Strings.toString(notifOptions), "+", notifSettings)); + + vm.expectEmit(true, true, false, true); + emit ChannelNotifcationSettingsAdded(BaseHelper.addressToBytes32(actor.charlie_channel_owner), notifOptions, notifSettingRes, notifDescription); + + coreProxy.receiveWormholeMessages( + requestPayload, additionalVaas, sourceAddress, SourceChain.SourceChainId, deliveryHash + ); + // Update states based on Fee Percentage calculation + assertEq(coreProxy.PROTOCOL_POOL_FEES(), PROTOCOL_POOL_FEES + amount); + } + + function test_whenTokensAreTransferred() external { + vm.recordLogs(); + test_whenReceiveChecksPassa(); + + (address sourceNttManager, bytes32 recipient, uint256 _amount, uint16 recipientChain) = + getMessagefromLog(vm.getRecordedLogs()); + + console.log(pushNttToken.balanceOf(address(coreProxy))); + + bytes[] memory a; + (bytes memory transceiverMessage, bytes32 hash) = + getRequestPayload(_amount, recipient, recipientChain, sourceNttManager); + + changePrank(DestChain.WORMHOLE_RELAYER_DEST); + DestChain.wormholeTransceiverChain2.receiveWormholeMessages( + transceiverMessage, // Verified + a, // Should be zero + bytes32(uint256(uint160(address(SourceChain.wormholeTransceiverChain1)))), // Must be a wormhole peers + 10_003, // ChainID from the call + hash // Hash of the VAA being used + ); + + assertEq(pushNttToken.balanceOf(address(coreProxy)), amount); + } +} diff --git a/test/CCR/SpecificRequest/CreateChannelSettingsCCR/CreateChannelSettingsCCR.tree b/test/CCR/SpecificRequest/CreateChannelSettingsCCR/CreateChannelSettingsCCR.tree new file mode 100644 index 00000000..1f27c54c --- /dev/null +++ b/test/CCR/SpecificRequest/CreateChannelSettingsCCR/CreateChannelSettingsCCR.tree @@ -0,0 +1,19 @@ +CreateChannelSettingsCCR.t.sol +├── when createChannelSettings is called +│ ├── when contract is paused +│ │ └── it should Revert +│ ├── when amount is less than minimum fees +│ │ └── it should revert +│ ├── when ether passed is less +│ │ └── it should revert +│ ├── when all checks passes +│ │ └── it should successfully create the channel settings +└── when receive function is called in core + ├── when sender is not registered + │ └── it should Revert + ├── when sender is not relayer + │ └── it should Revert + ├── when deliveryHash is used already + │ └── it should Revert + └── when all checks pass + └── it should emit event and create channel settings \ No newline at end of file diff --git a/test/CCR/SpecificRequest/CreateChatCCR/CreateChatCCR.t.sol b/test/CCR/SpecificRequest/CreateChatCCR/CreateChatCCR.t.sol index 9220acf6..2d3f5df5 100644 --- a/test/CCR/SpecificRequest/CreateChatCCR/CreateChatCCR.t.sol +++ b/test/CCR/SpecificRequest/CreateChatCCR/CreateChatCCR.t.sol @@ -22,6 +22,9 @@ contract CreateChatCCR is BaseCCRTest { amount, 0, percentage, + 0, + "", + "", BaseHelper.addressToBytes32(actor.bob_channel_owner) ); } diff --git a/test/utils/Events.sol b/test/utils/Events.sol index 55659084..b8941920 100644 --- a/test/utils/Events.sol +++ b/test/utils/Events.sol @@ -29,6 +29,7 @@ abstract contract CoreEvents { uint256 indexed feeId ); event ArbitraryRequestFeesClaimed(address indexed user, uint256 indexed amountClaimed); + event ChannelNotifcationSettingsAdded(bytes32 _channel, uint256 totalNotifOptions, string _notifSettings, string _notifDescription); } abstract contract CommEvents { From 9d2f3359f7b74d74c47415c5d27b5e6bf86f5fbe Mon Sep 17 00:00:00 2001 From: Md Zartaj Afser Date: Mon, 29 Jul 2024 17:07:16 +0530 Subject: [PATCH 09/23] name update --- .../UpdateChannelMetaCCR/UpdateChannelMetaCCR.t.sol | 2 +- .../UpdateChannelMetaCCR/UpdateChannelMetaCCR.tree | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/CCR/SpecificRequest/UpdateChannelMetaCCR/UpdateChannelMetaCCR.t.sol b/test/CCR/SpecificRequest/UpdateChannelMetaCCR/UpdateChannelMetaCCR.t.sol index 8e919dd1..e6f08a48 100644 --- a/test/CCR/SpecificRequest/UpdateChannelMetaCCR/UpdateChannelMetaCCR.t.sol +++ b/test/CCR/SpecificRequest/UpdateChannelMetaCCR/UpdateChannelMetaCCR.t.sol @@ -8,7 +8,7 @@ import { console } from "forge-std/console.sol"; import { CrossChainRequestTypes } from "../../../../contracts/libraries/DataTypes.sol"; import { BaseHelper } from "contracts/libraries/BaseHelper.sol"; -contract CreateChatCCR is BaseCCRTest { +contract UpdateChannelCCR is BaseCCRTest { uint256 amount; function setUp() public override { diff --git a/test/CCR/SpecificRequest/UpdateChannelMetaCCR/UpdateChannelMetaCCR.tree b/test/CCR/SpecificRequest/UpdateChannelMetaCCR/UpdateChannelMetaCCR.tree index c0680ed2..b09c1a34 100644 --- a/test/CCR/SpecificRequest/UpdateChannelMetaCCR/UpdateChannelMetaCCR.tree +++ b/test/CCR/SpecificRequest/UpdateChannelMetaCCR/UpdateChannelMetaCCR.tree @@ -1,4 +1,4 @@ -CreateChatCCR.t.sol +UpdateChannelMetaCCR.t.sol ├── when createCrossChainReq is called │ ├── when contract is paused │ │ └── it should Revert From 5ac31b4c00c512c75018cd9be77f564f627eab36 Mon Sep 17 00:00:00 2001 From: Md Zartaj Afser Date: Tue, 30 Jul 2024 13:09:46 +0530 Subject: [PATCH 10/23] Add CCR for UpdateChannelState --- contracts/PushComm/PushCommV3.sol | 39 ++-- contracts/PushCore/PushCoreV3.sol | 24 +- contracts/libraries/DataTypes.sol | 3 +- test/CCR/CCRutils/Helper.sol | 8 +- .../UpdateChannelStateCCR.t.sol | 216 ++++++++++++++++++ .../UpdateChannelStateCCR.tree | 21 ++ 6 files changed, 281 insertions(+), 30 deletions(-) create mode 100644 test/CCR/SpecificRequest/UpdateChannelStateCCR/UpdateChannelStateCCR.t.sol create mode 100644 test/CCR/SpecificRequest/UpdateChannelStateCCR/UpdateChannelStateCCR.tree diff --git a/contracts/PushComm/PushCommV3.sol b/contracts/PushComm/PushCommV3.sol index 38dc561d..f9df77e3 100644 --- a/contracts/PushComm/PushCommV3.sol +++ b/contracts/PushComm/PushCommV3.sol @@ -615,6 +615,7 @@ contract PushCommV3 is Initializable, PushCommStorageV2, IPushCommV3, PausableUp whenNotPaused { // Implement restrictions based on functionType + if (functionType == CrossChainRequestTypes.CrossChainFunction.AddChannel) { if (amount < ADD_CHANNEL_MIN_FEES) { revert Errors.InvalidArg_LessThanExpected(ADD_CHANNEL_MIN_FEES, amount); @@ -627,10 +628,7 @@ contract PushCommV3 is Initializable, PushCommStorageV2, IPushCommV3, PausableUp if (amount == 0) { revert Errors.InvalidArg_LessThanExpected(1, amount); } - } else { - revert Errors.Comm_InvalidCrossChain_Function(); } - bytes memory requestPayload = abi.encode(functionType, payload, amount, msg.sender); // Call the internal function to create the cross-chain request @@ -650,25 +648,28 @@ contract PushCommV3 is Initializable, PushCommStorageV2, IPushCommV3, PausableUp uint256 messageBridgeCost = quoteMsgRelayCost(recipientChain, gasLimit); uint256 tokenBridgeCost = quoteTokenBridgingCost(); - if (msg.value < (messageBridgeCost + tokenBridgeCost)) { + address coreAddress = EPNSCoreAddress; + if (amount != 0) { + if (msg.value < (messageBridgeCost + tokenBridgeCost)) { + revert Errors.InsufficientFunds(); + } + IERC20 PushNtt = PUSH_NTT; + INttManager NttManager = NTT_MANAGER; + + PushNtt.transferFrom(msg.sender, address(this), amount); + PushNtt.approve(address(NttManager), amount); + NttManager.transfer{ value: tokenBridgeCost }( + amount, + recipientChain, + BaseHelper.addressToBytes32(coreAddress), + BaseHelper.addressToBytes32(msg.sender), + false, + new bytes(1) + ); + } else if (msg.value < (messageBridgeCost)) { revert Errors.InsufficientFunds(); } - IERC20 PushNtt = PUSH_NTT; - INttManager NttManager = NTT_MANAGER; - address coreAddress = EPNSCoreAddress; - - PushNtt.transferFrom(msg.sender, address(this), amount); - PushNtt.approve(address(NttManager), amount); - NttManager.transfer{ value: tokenBridgeCost }( - amount, - recipientChain, - BaseHelper.addressToBytes32(coreAddress), - BaseHelper.addressToBytes32(msg.sender), - false, - new bytes(1) - ); - // Relay the RequestData Payload WORMHOLE_RELAYER.sendPayloadToEvm{ value: messageBridgeCost }( recipientChain, diff --git a/contracts/PushCore/PushCoreV3.sol b/contracts/PushCore/PushCoreV3.sol index 51e753e7..89d3ad51 100644 --- a/contracts/PushCore/PushCoreV3.sol +++ b/contracts/PushCore/PushCoreV3.sol @@ -15,7 +15,6 @@ import { PushCoreStorageV1_5 } from "./PushCoreStorageV1_5.sol"; import { PushCoreStorageV2 } from "./PushCoreStorageV2.sol"; import "../interfaces/IPUSH.sol"; import { IPushCoreV3 } from "../interfaces/IPushCoreV3.sol"; -import { IPushCommV3 } from "../interfaces/IPushCommV3.sol"; import { BaseHelper } from "../libraries/BaseHelper.sol"; import { Errors } from "../libraries/Errors.sol"; import { CoreTypes, CrossChainRequestTypes, GenericTypes } from "../libraries/DataTypes.sol"; @@ -296,6 +295,18 @@ contract PushCoreV3 is // Check channel's current state bytes32 _channelBytesID = BaseHelper.addressToBytes32(msg.sender); + if(channelInfo[_channelBytesID].channelState == 2) { + if (_amount < ADD_CHANNEL_MIN_FEES) { + revert Errors.InvalidArg_LessThanExpected(ADD_CHANNEL_MIN_FEES, _amount); + } + + IERC20(PUSH_TOKEN_ADDRESS).safeTransferFrom(msg.sender, address(this), _amount); + } + _updateChannelState( _channelBytesID, _amount, msg.sender); + } + + function _updateChannelState(bytes32 _channelBytesID, uint256 _amount, address recipient) internal { + CoreTypes.Channel storage channelData = channelInfo[_channelBytesID]; uint8 channelCurrentState = channelData.channelState; // Prevent INACTIVE or BLOCKED Channels @@ -328,14 +339,9 @@ contract PushCoreV3 is emit ChannelStateUpdate(_channelBytesID, totalRefundableAmount, 0); } CHANNEL_POOL_FUNDS = CHANNEL_POOL_FUNDS - totalRefundableAmount; - IERC20(PUSH_TOKEN_ADDRESS).safeTransfer(msg.sender, totalRefundableAmount); + IERC20(PUSH_TOKEN_ADDRESS).safeTransfer(recipient, totalRefundableAmount); } // RE-ACTIVATION PHASE else { - if (_amount < ADD_CHANNEL_MIN_FEES) { - revert Errors.InvalidArg_LessThanExpected(ADD_CHANNEL_MIN_FEES, _amount); - } - - IERC20(PUSH_TOKEN_ADDRESS).safeTransferFrom(msg.sender, address(this), _amount); uint256 poolFeeAmount = FEE_AMOUNT; uint256 poolFundAmount = _amount - poolFeeAmount; //store funds in pool_funds & pool_fees @@ -864,6 +870,10 @@ contract PushCoreV3 is _handleIncentivizedChat( sender, BaseHelper.bytes32ToAddress(amountRecipient), amount ); + }else if (functionType == CrossChainRequestTypes.CrossChainFunction.UpdateChannelState) { + // Specific Request: Updating Channel State + (address recipient) = abi.decode(structPayload, (address)); + _updateChannelState(sender, amount, recipient); } else if (functionType == CrossChainRequestTypes.CrossChainFunction.ArbitraryRequest) { // Arbitrary Request (uint8 feeId, GenericTypes.Percentage memory feePercentage, bytes32 amountRecipient) = diff --git a/contracts/libraries/DataTypes.sol b/contracts/libraries/DataTypes.sol index d5bacb21..9837a793 100644 --- a/contracts/libraries/DataTypes.sol +++ b/contracts/libraries/DataTypes.sol @@ -116,7 +116,8 @@ library CrossChainRequestTypes { AddChannel, IncentivizedChat, ArbitraryRequest, - AdminRequest_AddPoolFee + AdminRequest_AddPoolFee, + UpdateChannelState } } diff --git a/test/CCR/CCRutils/Helper.sol b/test/CCR/CCRutils/Helper.sol index 8317c016..88a1fba5 100644 --- a/test/CCR/CCRutils/Helper.sol +++ b/test/CCR/CCRutils/Helper.sol @@ -98,16 +98,18 @@ contract Helper is BasePushCommTest, CCRConfig { if (typeOfReq == CrossChainRequestTypes.CrossChainFunction.AddChannel) { payload = abi.encode(CoreTypes.ChannelType.InterestBearingMutual, _testChannelUpdatedIdentity, 0); - reqPayload = abi.encode(typeOfReq, payload, amount, sender); } else if (typeOfReq == CrossChainRequestTypes.CrossChainFunction.IncentivizedChat) { payload = abi.encode(amountRecipient); - reqPayload = abi.encode(typeOfReq, payload, amount, sender); } else if (typeOfReq == CrossChainRequestTypes.CrossChainFunction.ArbitraryRequest) { payload = abi.encode(_feeId, _percentage, amountRecipient); - reqPayload = abi.encode(typeOfReq, payload, amount, sender); + + }else if (typeOfReq == CrossChainRequestTypes.CrossChainFunction.UpdateChannelState) { + payload = abi.encode(amountRecipient); + } + reqPayload = abi.encode(typeOfReq, payload, amount, sender); } function receiveWormholeMessage(bytes memory _requestPayload) internal { diff --git a/test/CCR/SpecificRequest/UpdateChannelStateCCR/UpdateChannelStateCCR.t.sol b/test/CCR/SpecificRequest/UpdateChannelStateCCR/UpdateChannelStateCCR.t.sol new file mode 100644 index 00000000..5d46e076 --- /dev/null +++ b/test/CCR/SpecificRequest/UpdateChannelStateCCR/UpdateChannelStateCCR.t.sol @@ -0,0 +1,216 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +import { BaseCCRTest } from "../../BaseCCR.t.sol"; +import { Errors } from ".././../../../contracts/libraries/Errors.sol"; +import { console } from "forge-std/console.sol"; + +import { CrossChainRequestTypes } from "../../../../contracts/libraries/DataTypes.sol"; +import { BaseHelper } from "contracts/libraries/BaseHelper.sol"; + +contract UpdateChannelStateCCR is BaseCCRTest { + uint256 amount; + + function setUp() public override { + BaseCCRTest.setUp(); + sourceAddress = toWormholeFormat(address(commProxy)); + (_payload, requestPayload) = getSpecificPayload( + CrossChainRequestTypes.CrossChainFunction.UpdateChannelState, + BaseHelper.addressToBytes32(actor.bob_channel_owner), + amount, + 0, + percentage, + BaseHelper.addressToBytes32(actor.bob_channel_owner) + ); + } + + modifier whencreateCrossChainReqIsCalled() { + _; + } + + function test_WhenContractIsPaused() external whencreateCrossChainReqIsCalled { + // it should Revert + + changePrank(actor.admin); + commProxy.pauseContract(); + vm.expectRevert("Pausable: paused"); + changePrank(actor.bob_channel_owner); + commProxy.createCrossChainRequest( + CrossChainRequestTypes.CrossChainFunction.UpdateChannelState, _payload, amount, GasLimit + ); + } + + function test_RevertWhen_EtherPassedIsLess() external whencreateCrossChainReqIsCalled { + // it should revert + vm.expectRevert(abi.encodeWithSelector(Errors.InsufficientFunds.selector)); + changePrank(actor.bob_channel_owner); + commProxy.createCrossChainRequest( + CrossChainRequestTypes.CrossChainFunction.UpdateChannelState, _payload, amount, GasLimit + ); + } + + function test_WhenAllChecksPasses() public whencreateCrossChainReqIsCalled { + // it should successfully create the CCR + vm.expectEmit(true, false, false, false); + emit LogMessagePublished(SourceChain.WORMHOLE_RELAYER_SOURCE, 2105, 0, requestPayload, 15); + changePrank(actor.bob_channel_owner); + commProxy.createCrossChainRequest{ value: 1e18 }( + CrossChainRequestTypes.CrossChainFunction.UpdateChannelState, _payload, amount, GasLimit + ); + } + + modifier whenReceiveFunctionIsCalledInCore() { + test_WhenAllChecksPasses(); + setUpDestChain(); + _; + } + + function test_WhenSenderIsNotRegistered() external whenReceiveFunctionIsCalledInCore { + // it should Revert + + //set sender to zero address + coreProxy.setRegisteredSender(SourceChain.SourceChainId, toWormholeFormat(address(0))); + + vm.expectRevert("Not registered sender"); + receiveWormholeMessage(requestPayload); + } + + function test_WhenSenderIsNotRelayer() external whenReceiveFunctionIsCalledInCore { + // it should Revert + + coreProxy.setWormholeRelayer(address(0)); + vm.expectRevert(abi.encodeWithSelector(Errors.CallerNotAdmin.selector)); + receiveWormholeMessage(requestPayload); + } + + function test_WhenDeliveryHashIsUsedAlready() external whenReceiveFunctionIsCalledInCore { + // it should Revert + + receiveWormholeMessage(requestPayload); + vm.expectRevert(abi.encodeWithSelector(Errors.Payload_Duplicacy_Error.selector)); + receiveWormholeMessage(requestPayload); + } + + function test_WhenChannelIsActive() public whenReceiveFunctionIsCalledInCore { + // it should deactivate Channel + uint256 CHANNEL_POOL_FUNDS = coreProxy.CHANNEL_POOL_FUNDS(); + + ( + , + , + , + uint256 poolContributionBefore, + , + , + , + , + , + , + ) = coreProxy.channelInfo(toWormholeFormat(actor.bob_channel_owner)); + + uint refundableAmount = poolContributionBefore - MIN_POOL_CONTRIBUTION; + + vm.expectEmit(true, true, false, true); + emit ChannelStateUpdate(toWormholeFormat(actor.bob_channel_owner), refundableAmount, amount); + + receiveWormholeMessage(requestPayload); + ( + , + uint8 channelState, + , + uint256 poolContribution, + , + , + , + , + , + uint256 channelWeight, + + ) = coreProxy.channelInfo(toWormholeFormat(actor.bob_channel_owner)); + assertEq(coreProxy.CHANNEL_POOL_FUNDS(), CHANNEL_POOL_FUNDS - refundableAmount,"Channel Pool Funcds"); + assertEq(channelState, 2, "Channel State"); + assertEq(poolContribution, MIN_POOL_CONTRIBUTION, "Pool contribution " ); + assertEq(channelWeight, (MIN_POOL_CONTRIBUTION * ADJUST_FOR_FLOAT)/MIN_POOL_CONTRIBUTION, "Channel Weight"); + } + + function test_WhenChannelIsDeactivated() public whenReceiveFunctionIsCalledInCore { + // it should activate Channel + changePrank(actor.bob_channel_owner); + coreProxy.updateChannelState(0); + uint256 CHANNEL_POOL_FUNDS = coreProxy.CHANNEL_POOL_FUNDS(); + amount = ADD_CHANNEL_MIN_FEES; + + (_payload, requestPayload) = getSpecificPayload( + CrossChainRequestTypes.CrossChainFunction.UpdateChannelState, + BaseHelper.addressToBytes32(actor.bob_channel_owner), + amount, + 0, + percentage, + BaseHelper.addressToBytes32(actor.bob_channel_owner) + ); + vm.expectEmit(true, true, false, true); + emit ChannelStateUpdate(toWormholeFormat(actor.bob_channel_owner), 0, amount); + + receiveWormholeMessage(requestPayload); + ( + , + uint8 channelState, + , + uint256 poolContribution, + , + , + , + , + , + uint256 channelWeight, + + ) = coreProxy.channelInfo(toWormholeFormat(actor.bob_channel_owner)); + assertEq(coreProxy.CHANNEL_POOL_FUNDS(), CHANNEL_POOL_FUNDS + ADD_CHANNEL_MIN_FEES - FEE_AMOUNT,"Channel Pool Funcds"); + assertEq(channelState, 1, "Channel State"); + assertEq(poolContribution, MIN_POOL_CONTRIBUTION + ADD_CHANNEL_MIN_FEES - FEE_AMOUNT, "Pool contribution " ); + assertEq(channelWeight, (poolContribution * ADJUST_FOR_FLOAT)/MIN_POOL_CONTRIBUTION, "Channel Weight"); + } + + function test_WhenChannelIsTimebound() external whenReceiveFunctionIsCalledInCore { + // it should delete channel + } + + function test_whenTokensAreTransferred() external { + amount = ADD_CHANNEL_MIN_FEES; + (_payload, requestPayload) = getSpecificPayload( + CrossChainRequestTypes.CrossChainFunction.UpdateChannelState, + BaseHelper.addressToBytes32(actor.bob_channel_owner), + amount, + 0, + percentage, + BaseHelper.addressToBytes32(actor.bob_channel_owner) + ); + + changePrank(actor.bob_channel_owner); + vm.recordLogs(); + commProxy.createCrossChainRequest{ value: 1e18 }( + CrossChainRequestTypes.CrossChainFunction.UpdateChannelState, _payload, amount, GasLimit + ); + + (address sourceNttManager, bytes32 recipient, uint256 _amount, uint16 recipientChain) = + getMessagefromLog(vm.getRecordedLogs()); + + console.log(pushNttToken.balanceOf(address(coreProxy))); + + bytes[] memory a; + (bytes memory transceiverMessage, bytes32 hash) = + getRequestPayload(_amount, recipient, recipientChain, sourceNttManager); + + setUpDestChain(); + changePrank(DestChain.WORMHOLE_RELAYER_DEST); + DestChain.wormholeTransceiverChain2.receiveWormholeMessages( + transceiverMessage, // Verified + a, // Should be zero + bytes32(uint256(uint160(address(SourceChain.wormholeTransceiverChain1)))), // Must be a wormhole peers + 10_003, // ChainID from the call + hash // Hash of the VAA being used + ); + + assertEq(pushNttToken.balanceOf(address(coreProxy)), amount); + } +} diff --git a/test/CCR/SpecificRequest/UpdateChannelStateCCR/UpdateChannelStateCCR.tree b/test/CCR/SpecificRequest/UpdateChannelStateCCR/UpdateChannelStateCCR.tree new file mode 100644 index 00000000..b7c6c193 --- /dev/null +++ b/test/CCR/SpecificRequest/UpdateChannelStateCCR/UpdateChannelStateCCR.tree @@ -0,0 +1,21 @@ +UpdateChannelStateCCR.t.sol +├── when createCrossChainReq is called +│ ├── when contract is paused +│ │ └── it should Revert +│ ├── when ether passed is less +│ │ └── it should revert +│ └── when all checks passes +│ └── it should successfully create the CCR +└── when receive function is called in core + ├── when sender is not registered + │ └── it should Revert + ├── when sender is not relayer + │ └── it should Revert + ├── when deliveryHash is used already + │ └── it should Revert + ├── when Channel is active + │ └── it should deactivate Channel + ├── when channel is deactivated + │ └── it should activate Channel + └── when channel is timebound + └── it should delete channel \ No newline at end of file From 53b998275caf6a32dc1d69ec648b26c422b2ee7a Mon Sep 17 00:00:00 2001 From: Md Zartaj Afser Date: Tue, 30 Jul 2024 16:15:57 +0530 Subject: [PATCH 11/23] file name fix --- ...eChannelSettingsCCR.sol => CreateChannelSettingsCCR.t.sol} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename test/CCR/SpecificRequest/CreateChannelSettingsCCR/{CreateChannelSettingsCCR.sol => CreateChannelSettingsCCR.t.sol} (98%) diff --git a/test/CCR/SpecificRequest/CreateChannelSettingsCCR/CreateChannelSettingsCCR.sol b/test/CCR/SpecificRequest/CreateChannelSettingsCCR/CreateChannelSettingsCCR.t.sol similarity index 98% rename from test/CCR/SpecificRequest/CreateChannelSettingsCCR/CreateChannelSettingsCCR.sol rename to test/CCR/SpecificRequest/CreateChannelSettingsCCR/CreateChannelSettingsCCR.t.sol index a7b3a96a..a635e8df 100644 --- a/test/CCR/SpecificRequest/CreateChannelSettingsCCR/CreateChannelSettingsCCR.sol +++ b/test/CCR/SpecificRequest/CreateChannelSettingsCCR/CreateChannelSettingsCCR.t.sol @@ -114,7 +114,7 @@ contract CreateChannelSettingsCCR is BaseCCRTest { receiveWormholeMessage(requestPayload); } - function test_whenReceiveChecksPassa() public whenReceiveFunctionIsCalledInCore { + function test_whenReceiveChecksPass() public whenReceiveFunctionIsCalledInCore { uint256 PROTOCOL_POOL_FEES = coreProxy.PROTOCOL_POOL_FEES(); changePrank(DestChain.WORMHOLE_RELAYER_DEST); @@ -133,7 +133,7 @@ contract CreateChannelSettingsCCR is BaseCCRTest { function test_whenTokensAreTransferred() external { vm.recordLogs(); - test_whenReceiveChecksPassa(); + test_whenReceiveChecksPass(); (address sourceNttManager, bytes32 recipient, uint256 _amount, uint16 recipientChain) = getMessagefromLog(vm.getRecordedLogs()); From 705b69f64c357eb9fcf3aa9c20766aa62356c1b7 Mon Sep 17 00:00:00 2001 From: Md Zartaj Afser Date: Wed, 31 Jul 2024 13:33:05 +0530 Subject: [PATCH 12/23] test fix --- .../UpdateChannelStateCCR/UpdateChannelStateCCR.t.sol | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/CCR/SpecificRequest/UpdateChannelStateCCR/UpdateChannelStateCCR.t.sol b/test/CCR/SpecificRequest/UpdateChannelStateCCR/UpdateChannelStateCCR.t.sol index 5d46e076..deec3013 100644 --- a/test/CCR/SpecificRequest/UpdateChannelStateCCR/UpdateChannelStateCCR.t.sol +++ b/test/CCR/SpecificRequest/UpdateChannelStateCCR/UpdateChannelStateCCR.t.sol @@ -20,6 +20,9 @@ contract UpdateChannelStateCCR is BaseCCRTest { amount, 0, percentage, + 0, + "", + "", BaseHelper.addressToBytes32(actor.bob_channel_owner) ); } @@ -146,6 +149,9 @@ contract UpdateChannelStateCCR is BaseCCRTest { amount, 0, percentage, + 0, + "", + "", BaseHelper.addressToBytes32(actor.bob_channel_owner) ); vm.expectEmit(true, true, false, true); @@ -183,6 +189,9 @@ contract UpdateChannelStateCCR is BaseCCRTest { amount, 0, percentage, + 0, + "", + "", BaseHelper.addressToBytes32(actor.bob_channel_owner) ); From 3ede041a8c8881cb6d39fe1ccc677ee2c9c68330 Mon Sep 17 00:00:00 2001 From: Md Zartaj Afser Date: Thu, 1 Aug 2024 16:47:11 +0530 Subject: [PATCH 13/23] Re factor functions --- contracts/PushComm/PushCommV3.sol | 4 + contracts/PushCore/PushCoreV3.sol | 35 ++-- contracts/libraries/DataTypes.sol | 3 +- test/CCR/CCRutils/Helper.sol | 5 +- .../DeactivateDeleteChannelCCR.t.sol} | 66 ++----- .../DeactivateDeleteChannelCCR.tree} | 0 .../ReactivateChannelCCR.t.sol | 166 ++++++++++++++++++ .../ReactivateChannelCCR.tree | 18 ++ 8 files changed, 223 insertions(+), 74 deletions(-) rename test/CCR/SpecificRequest/UpdateChannelStateCCR/{UpdateChannelStateCCR.t.sol => DeactivateDeleteChannelCCR/DeactivateDeleteChannelCCR.t.sol} (69%) rename test/CCR/SpecificRequest/UpdateChannelStateCCR/{UpdateChannelStateCCR.tree => DeactivateDeleteChannelCCR/DeactivateDeleteChannelCCR.tree} (100%) create mode 100644 test/CCR/SpecificRequest/UpdateChannelStateCCR/ReactivateChannelCCR/ReactivateChannelCCR.t.sol create mode 100644 test/CCR/SpecificRequest/UpdateChannelStateCCR/ReactivateChannelCCR/ReactivateChannelCCR.tree diff --git a/contracts/PushComm/PushCommV3.sol b/contracts/PushComm/PushCommV3.sol index d0d69ad7..e12848c6 100644 --- a/contracts/PushComm/PushCommV3.sol +++ b/contracts/PushComm/PushCommV3.sol @@ -632,6 +632,10 @@ contract PushCommV3 is Initializable, PushCommStorageV2, IPushCommV3, PausableUp if (amount == 0) { revert Errors.InvalidArg_LessThanExpected(1, amount); } + } else if (functionType == CrossChainRequestTypes.CrossChainFunction.ReactivateChannel) { + if (amount < ADD_CHANNEL_MIN_FEES) { + revert Errors.InvalidArg_LessThanExpected(ADD_CHANNEL_MIN_FEES, amount); + } } bytes memory requestPayload = abi.encode(functionType, payload, amount, msg.sender); diff --git a/contracts/PushCore/PushCoreV3.sol b/contracts/PushCore/PushCoreV3.sol index 1dc2ce44..f5223742 100644 --- a/contracts/PushCore/PushCoreV3.sol +++ b/contracts/PushCore/PushCoreV3.sol @@ -301,25 +301,25 @@ contract PushCoreV3 is } IERC20(PUSH_TOKEN_ADDRESS).safeTransferFrom(msg.sender, address(this), _amount); - } - _updateChannelState( _channelBytesID, _amount, msg.sender); + reactivateChanel( _channelBytesID, _amount); + }else { + deactivateDeleteChannel( _channelBytesID, msg.sender); + } } - function _updateChannelState(bytes32 _channelBytesID, uint256 _amount, address recipient) internal { + function deactivateDeleteChannel(bytes32 _channelBytesID, address recipient) internal { CoreTypes.Channel storage channelData = channelInfo[_channelBytesID]; uint8 channelCurrentState = channelData.channelState; // Prevent INACTIVE or BLOCKED Channels - if (channelCurrentState != 1 && channelCurrentState != 2) { + if (channelCurrentState != 1) { revert Errors.Core_InvalidChannel(); } uint256 minPoolContribution = MIN_POOL_CONTRIBUTION; // If Active State , Enter the Time-Bound Deletion/Deactivate Channel Phase - if (channelCurrentState == 1) { uint256 totalRefundableAmount; - bool isTimeBound = channelData.channelType == CoreTypes.ChannelType.TimeBound; - if (!isTimeBound) { + if (!(channelData.channelType == CoreTypes.ChannelType.TimeBound)) { // DEACTIVATION PHASE totalRefundableAmount = channelData.poolContribution - minPoolContribution; @@ -327,7 +327,6 @@ contract PushCoreV3 is channelData.channelState = 2; channelData.channelWeight = _newChannelWeight; channelData.poolContribution = minPoolContribution; - emit ChannelStateUpdate(_channelBytesID, totalRefundableAmount, 0); } else { // TIME-BOUND CHANNEL DELETION PHASE if (channelData.expiryTime >= block.timestamp) { @@ -336,12 +335,14 @@ contract PushCoreV3 is totalRefundableAmount = channelData.poolContribution; channelsCount = channelsCount - 1; delete channelInfo[_channelBytesID]; - emit ChannelStateUpdate(_channelBytesID, totalRefundableAmount, 0); } + emit ChannelStateUpdate(_channelBytesID, totalRefundableAmount, 0); CHANNEL_POOL_FUNDS = CHANNEL_POOL_FUNDS - totalRefundableAmount; IERC20(PUSH_TOKEN_ADDRESS).safeTransfer(recipient, totalRefundableAmount); - } // RE-ACTIVATION PHASE - else { + } + + function reactivateChanel(bytes32 _channelBytesID, uint256 _amount) internal { + CoreTypes.Channel storage channelData = channelInfo[_channelBytesID]; uint256 poolFeeAmount = FEE_AMOUNT; uint256 poolFundAmount = _amount - poolFeeAmount; //store funds in pool_funds & pool_fees @@ -349,13 +350,12 @@ contract PushCoreV3 is PROTOCOL_POOL_FEES = PROTOCOL_POOL_FEES + poolFeeAmount; uint256 _newPoolContribution = channelData.poolContribution + poolFundAmount; - uint256 _newChannelWeight = (_newPoolContribution * ADJUST_FOR_FLOAT) / minPoolContribution; + uint256 _newChannelWeight = (_newPoolContribution * ADJUST_FOR_FLOAT) / MIN_POOL_CONTRIBUTION; channelData.channelState = 1; channelData.poolContribution = _newPoolContribution; channelData.channelWeight = _newChannelWeight; emit ChannelStateUpdate(_channelBytesID, 0, _amount); - } } /// @inheritdoc IPushCoreV3 @@ -877,10 +877,13 @@ contract PushCoreV3 is } else if (functionType == CrossChainRequestTypes.CrossChainFunction.UpdateChannelMeta) { (bytes memory _newIdentity) = abi.decode(structPayload, (bytes)); _updateChannelMeta(sender, _newIdentity, amount); - }else if (functionType == CrossChainRequestTypes.CrossChainFunction.UpdateChannelState) { - // Specific Request: Updating Channel State + } else if (functionType == CrossChainRequestTypes.CrossChainFunction.DeactivateDeleteChannel) { + // Specific Request: Deactivating or Deleting Channel (address recipient) = abi.decode(structPayload, (address)); - _updateChannelState(sender, amount, recipient); + deactivateDeleteChannel(sender, recipient); + } else if (functionType == CrossChainRequestTypes.CrossChainFunction.ReactivateChannel) { + // Specific Request: Deactivating or Deleting Channel + reactivateChanel(sender, amount); } else if (functionType == CrossChainRequestTypes.CrossChainFunction.ArbitraryRequest) { // Arbitrary Request (uint8 feeId, GenericTypes.Percentage memory feePercentage, bytes32 amountRecipient) = diff --git a/contracts/libraries/DataTypes.sol b/contracts/libraries/DataTypes.sol index 918b7ac8..64dba682 100644 --- a/contracts/libraries/DataTypes.sol +++ b/contracts/libraries/DataTypes.sol @@ -118,7 +118,8 @@ library CrossChainRequestTypes { ArbitraryRequest, CreateChannelSettings, AdminRequest_AddPoolFee, - UpdateChannelState, + ReactivateChannel, + DeactivateDeleteChannel, UpdateChannelMeta } } diff --git a/test/CCR/CCRutils/Helper.sol b/test/CCR/CCRutils/Helper.sol index 1b6f3877..baa29c84 100644 --- a/test/CCR/CCRutils/Helper.sol +++ b/test/CCR/CCRutils/Helper.sol @@ -111,8 +111,11 @@ contract Helper is BasePushCommTest, CCRConfig { }else if (typeOfReq == CrossChainRequestTypes.CrossChainFunction.ArbitraryRequest) { payload = abi.encode(_feeId, _percentage, amountRecipient); - }else if (typeOfReq == CrossChainRequestTypes.CrossChainFunction.UpdateChannelState) { + }else if (typeOfReq == CrossChainRequestTypes.CrossChainFunction.DeactivateDeleteChannel) { payload = abi.encode(amountRecipient); + } + else if (typeOfReq == CrossChainRequestTypes.CrossChainFunction.ReactivateChannel) { + payload = new bytes(0); }else if (typeOfReq == CrossChainRequestTypes.CrossChainFunction.UpdateChannelMeta) { diff --git a/test/CCR/SpecificRequest/UpdateChannelStateCCR/UpdateChannelStateCCR.t.sol b/test/CCR/SpecificRequest/UpdateChannelStateCCR/DeactivateDeleteChannelCCR/DeactivateDeleteChannelCCR.t.sol similarity index 69% rename from test/CCR/SpecificRequest/UpdateChannelStateCCR/UpdateChannelStateCCR.t.sol rename to test/CCR/SpecificRequest/UpdateChannelStateCCR/DeactivateDeleteChannelCCR/DeactivateDeleteChannelCCR.t.sol index deec3013..c8b4827e 100644 --- a/test/CCR/SpecificRequest/UpdateChannelStateCCR/UpdateChannelStateCCR.t.sol +++ b/test/CCR/SpecificRequest/UpdateChannelStateCCR/DeactivateDeleteChannelCCR/DeactivateDeleteChannelCCR.t.sol @@ -1,21 +1,21 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; -import { BaseCCRTest } from "../../BaseCCR.t.sol"; -import { Errors } from ".././../../../contracts/libraries/Errors.sol"; +import { BaseCCRTest } from "../../../BaseCCR.t.sol"; +import { Errors } from "contracts/libraries/Errors.sol"; import { console } from "forge-std/console.sol"; -import { CrossChainRequestTypes } from "../../../../contracts/libraries/DataTypes.sol"; +import { CrossChainRequestTypes } from "contracts/libraries/DataTypes.sol"; import { BaseHelper } from "contracts/libraries/BaseHelper.sol"; -contract UpdateChannelStateCCR is BaseCCRTest { +contract DeactivateDeleteChannelCCR is BaseCCRTest { uint256 amount; function setUp() public override { BaseCCRTest.setUp(); sourceAddress = toWormholeFormat(address(commProxy)); (_payload, requestPayload) = getSpecificPayload( - CrossChainRequestTypes.CrossChainFunction.UpdateChannelState, + CrossChainRequestTypes.CrossChainFunction.DeactivateDeleteChannel, BaseHelper.addressToBytes32(actor.bob_channel_owner), amount, 0, @@ -39,7 +39,7 @@ contract UpdateChannelStateCCR is BaseCCRTest { vm.expectRevert("Pausable: paused"); changePrank(actor.bob_channel_owner); commProxy.createCrossChainRequest( - CrossChainRequestTypes.CrossChainFunction.UpdateChannelState, _payload, amount, GasLimit + CrossChainRequestTypes.CrossChainFunction.DeactivateDeleteChannel, _payload, amount, GasLimit ); } @@ -48,7 +48,7 @@ contract UpdateChannelStateCCR is BaseCCRTest { vm.expectRevert(abi.encodeWithSelector(Errors.InsufficientFunds.selector)); changePrank(actor.bob_channel_owner); commProxy.createCrossChainRequest( - CrossChainRequestTypes.CrossChainFunction.UpdateChannelState, _payload, amount, GasLimit + CrossChainRequestTypes.CrossChainFunction.DeactivateDeleteChannel, _payload, amount, GasLimit ); } @@ -58,7 +58,7 @@ contract UpdateChannelStateCCR is BaseCCRTest { emit LogMessagePublished(SourceChain.WORMHOLE_RELAYER_SOURCE, 2105, 0, requestPayload, 15); changePrank(actor.bob_channel_owner); commProxy.createCrossChainRequest{ value: 1e18 }( - CrossChainRequestTypes.CrossChainFunction.UpdateChannelState, _payload, amount, GasLimit + CrossChainRequestTypes.CrossChainFunction.DeactivateDeleteChannel, _payload, amount, GasLimit ); } @@ -135,56 +135,10 @@ contract UpdateChannelStateCCR is BaseCCRTest { assertEq(poolContribution, MIN_POOL_CONTRIBUTION, "Pool contribution " ); assertEq(channelWeight, (MIN_POOL_CONTRIBUTION * ADJUST_FOR_FLOAT)/MIN_POOL_CONTRIBUTION, "Channel Weight"); } - - function test_WhenChannelIsDeactivated() public whenReceiveFunctionIsCalledInCore { - // it should activate Channel - changePrank(actor.bob_channel_owner); - coreProxy.updateChannelState(0); - uint256 CHANNEL_POOL_FUNDS = coreProxy.CHANNEL_POOL_FUNDS(); - amount = ADD_CHANNEL_MIN_FEES; - - (_payload, requestPayload) = getSpecificPayload( - CrossChainRequestTypes.CrossChainFunction.UpdateChannelState, - BaseHelper.addressToBytes32(actor.bob_channel_owner), - amount, - 0, - percentage, - 0, - "", - "", - BaseHelper.addressToBytes32(actor.bob_channel_owner) - ); - vm.expectEmit(true, true, false, true); - emit ChannelStateUpdate(toWormholeFormat(actor.bob_channel_owner), 0, amount); - - receiveWormholeMessage(requestPayload); - ( - , - uint8 channelState, - , - uint256 poolContribution, - , - , - , - , - , - uint256 channelWeight, - - ) = coreProxy.channelInfo(toWormholeFormat(actor.bob_channel_owner)); - assertEq(coreProxy.CHANNEL_POOL_FUNDS(), CHANNEL_POOL_FUNDS + ADD_CHANNEL_MIN_FEES - FEE_AMOUNT,"Channel Pool Funcds"); - assertEq(channelState, 1, "Channel State"); - assertEq(poolContribution, MIN_POOL_CONTRIBUTION + ADD_CHANNEL_MIN_FEES - FEE_AMOUNT, "Pool contribution " ); - assertEq(channelWeight, (poolContribution * ADJUST_FOR_FLOAT)/MIN_POOL_CONTRIBUTION, "Channel Weight"); - } - - function test_WhenChannelIsTimebound() external whenReceiveFunctionIsCalledInCore { - // it should delete channel - } - function test_whenTokensAreTransferred() external { amount = ADD_CHANNEL_MIN_FEES; (_payload, requestPayload) = getSpecificPayload( - CrossChainRequestTypes.CrossChainFunction.UpdateChannelState, + CrossChainRequestTypes.CrossChainFunction.DeactivateDeleteChannel, BaseHelper.addressToBytes32(actor.bob_channel_owner), amount, 0, @@ -198,7 +152,7 @@ contract UpdateChannelStateCCR is BaseCCRTest { changePrank(actor.bob_channel_owner); vm.recordLogs(); commProxy.createCrossChainRequest{ value: 1e18 }( - CrossChainRequestTypes.CrossChainFunction.UpdateChannelState, _payload, amount, GasLimit + CrossChainRequestTypes.CrossChainFunction.DeactivateDeleteChannel, _payload, amount, GasLimit ); (address sourceNttManager, bytes32 recipient, uint256 _amount, uint16 recipientChain) = diff --git a/test/CCR/SpecificRequest/UpdateChannelStateCCR/UpdateChannelStateCCR.tree b/test/CCR/SpecificRequest/UpdateChannelStateCCR/DeactivateDeleteChannelCCR/DeactivateDeleteChannelCCR.tree similarity index 100% rename from test/CCR/SpecificRequest/UpdateChannelStateCCR/UpdateChannelStateCCR.tree rename to test/CCR/SpecificRequest/UpdateChannelStateCCR/DeactivateDeleteChannelCCR/DeactivateDeleteChannelCCR.tree diff --git a/test/CCR/SpecificRequest/UpdateChannelStateCCR/ReactivateChannelCCR/ReactivateChannelCCR.t.sol b/test/CCR/SpecificRequest/UpdateChannelStateCCR/ReactivateChannelCCR/ReactivateChannelCCR.t.sol new file mode 100644 index 00000000..76091f4e --- /dev/null +++ b/test/CCR/SpecificRequest/UpdateChannelStateCCR/ReactivateChannelCCR/ReactivateChannelCCR.t.sol @@ -0,0 +1,166 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +import { BaseCCRTest } from "../../../BaseCCR.t.sol"; +import { Errors } from "contracts/libraries/Errors.sol"; +import { console } from "forge-std/console.sol"; + +import { CrossChainRequestTypes } from "contracts/libraries/DataTypes.sol"; +import { BaseHelper } from "contracts/libraries/BaseHelper.sol"; + +contract ReactivateChannelCCR is BaseCCRTest { + uint256 amount = ADD_CHANNEL_MIN_FEES; + + function setUp() public override { + BaseCCRTest.setUp(); + sourceAddress = toWormholeFormat(address(commProxy)); + (_payload, requestPayload) = getSpecificPayload( + CrossChainRequestTypes.CrossChainFunction.ReactivateChannel, + BaseHelper.addressToBytes32(actor.bob_channel_owner), + amount, + 0, + percentage, + 0, + "", + "", + BaseHelper.addressToBytes32(actor.bob_channel_owner) + ); + } + + modifier whencreateCrossChainReqIsCalled() { + _; + } + + function test_WhenContractIsPaused() external whencreateCrossChainReqIsCalled { + // it should Revert + + changePrank(actor.admin); + commProxy.pauseContract(); + vm.expectRevert("Pausable: paused"); + changePrank(actor.bob_channel_owner); + commProxy.createCrossChainRequest( + CrossChainRequestTypes.CrossChainFunction.ReactivateChannel, _payload, amount, GasLimit + ); + } + + function test_RevertWhen_EtherPassedIsLess() external whencreateCrossChainReqIsCalled { + // it should revert + vm.expectRevert(abi.encodeWithSelector(Errors.InsufficientFunds.selector)); + changePrank(actor.bob_channel_owner); + commProxy.createCrossChainRequest( + CrossChainRequestTypes.CrossChainFunction.ReactivateChannel, _payload, amount, GasLimit + ); + } + + function test_WhenAllChecksPasses() public whencreateCrossChainReqIsCalled { + // it should successfully create the CCR + vm.expectEmit(true, false, false, false); + emit LogMessagePublished(SourceChain.WORMHOLE_RELAYER_SOURCE, 2105, 0, requestPayload, 15); + changePrank(actor.bob_channel_owner); + commProxy.createCrossChainRequest{ value: 1e18 }( + CrossChainRequestTypes.CrossChainFunction.ReactivateChannel, _payload, amount, GasLimit + ); + } + + modifier whenReceiveFunctionIsCalledInCore() { + test_WhenAllChecksPasses(); + setUpDestChain(); + _; + } + + function test_WhenSenderIsNotRegistered() external whenReceiveFunctionIsCalledInCore { + // it should Revert + + //set sender to zero address + coreProxy.setRegisteredSender(SourceChain.SourceChainId, toWormholeFormat(address(0))); + + vm.expectRevert("Not registered sender"); + receiveWormholeMessage(requestPayload); + } + + function test_WhenSenderIsNotRelayer() external whenReceiveFunctionIsCalledInCore { + // it should Revert + + coreProxy.setWormholeRelayer(address(0)); + vm.expectRevert(abi.encodeWithSelector(Errors.CallerNotAdmin.selector)); + receiveWormholeMessage(requestPayload); + } + + function test_WhenDeliveryHashIsUsedAlready() external whenReceiveFunctionIsCalledInCore { + // it should Revert + + receiveWormholeMessage(requestPayload); + vm.expectRevert(abi.encodeWithSelector(Errors.Payload_Duplicacy_Error.selector)); + receiveWormholeMessage(requestPayload); + } + + function test_WhenChannelIsDeactivated() public whenReceiveFunctionIsCalledInCore { + // it should activate Channel + changePrank(actor.bob_channel_owner); + coreProxy.updateChannelState(0); + uint256 CHANNEL_POOL_FUNDS = coreProxy.CHANNEL_POOL_FUNDS(); + vm.expectEmit(true, true, false, true); + emit ChannelStateUpdate(toWormholeFormat(actor.bob_channel_owner), 0, amount); + + receiveWormholeMessage(requestPayload); + ( + , + uint8 channelState, + , + uint256 poolContribution, + , + , + , + , + , + uint256 channelWeight, + + ) = coreProxy.channelInfo(toWormholeFormat(actor.bob_channel_owner)); + assertEq(coreProxy.CHANNEL_POOL_FUNDS(), CHANNEL_POOL_FUNDS + ADD_CHANNEL_MIN_FEES - FEE_AMOUNT,"Channel Pool Funcds"); + assertEq(channelState, 1, "Channel State"); + assertEq(poolContribution, MIN_POOL_CONTRIBUTION + ADD_CHANNEL_MIN_FEES - FEE_AMOUNT, "Pool contribution " ); + assertEq(channelWeight, (poolContribution * ADJUST_FOR_FLOAT)/MIN_POOL_CONTRIBUTION, "Channel Weight"); + } + + function test_whenTokensAreTransferred() external { + amount = ADD_CHANNEL_MIN_FEES; + (_payload, requestPayload) = getSpecificPayload( + CrossChainRequestTypes.CrossChainFunction.ReactivateChannel, + BaseHelper.addressToBytes32(actor.bob_channel_owner), + amount, + 0, + percentage, + 0, + "", + "", + BaseHelper.addressToBytes32(actor.bob_channel_owner) + ); + + changePrank(actor.bob_channel_owner); + vm.recordLogs(); + commProxy.createCrossChainRequest{ value: 1e18 }( + CrossChainRequestTypes.CrossChainFunction.ReactivateChannel, _payload, amount, GasLimit + ); + + (address sourceNttManager, bytes32 recipient, uint256 _amount, uint16 recipientChain) = + getMessagefromLog(vm.getRecordedLogs()); + + console.log(pushNttToken.balanceOf(address(coreProxy))); + + bytes[] memory a; + (bytes memory transceiverMessage, bytes32 hash) = + getRequestPayload(_amount, recipient, recipientChain, sourceNttManager); + + setUpDestChain(); + changePrank(DestChain.WORMHOLE_RELAYER_DEST); + DestChain.wormholeTransceiverChain2.receiveWormholeMessages( + transceiverMessage, // Verified + a, // Should be zero + bytes32(uint256(uint160(address(SourceChain.wormholeTransceiverChain1)))), // Must be a wormhole peers + 10_003, // ChainID from the call + hash // Hash of the VAA being used + ); + + assertEq(pushNttToken.balanceOf(address(coreProxy)), amount); + } +} diff --git a/test/CCR/SpecificRequest/UpdateChannelStateCCR/ReactivateChannelCCR/ReactivateChannelCCR.tree b/test/CCR/SpecificRequest/UpdateChannelStateCCR/ReactivateChannelCCR/ReactivateChannelCCR.tree new file mode 100644 index 00000000..206a9e58 --- /dev/null +++ b/test/CCR/SpecificRequest/UpdateChannelStateCCR/ReactivateChannelCCR/ReactivateChannelCCR.tree @@ -0,0 +1,18 @@ +UpdateChannelStateCCR.t.sol +├── when createCrossChainReq is called +│ ├── when contract is paused +│ │ └── it should Revert +│ ├── when ether passed is less +│ │ └── it should revert +│ └── when all checks passes +│ └── it should successfully create the CCR +└── when receive function is called in core + ├── when sender is not registered + │ └── it should Revert + ├── when sender is not relayer + │ └── it should Revert + ├── when deliveryHash is used already + │ └── it should Revert + └── when channel is deactivated + └── it should activate Channel + \ No newline at end of file From 79dc380923f41e0fad5302be1afc49ca0a0ed5e4 Mon Sep 17 00:00:00 2001 From: Md Zartaj Afser Date: Fri, 2 Aug 2024 23:49:37 +0530 Subject: [PATCH 14/23] merged similar checks --- contracts/PushComm/PushCommV3.sol | 10 +--------- contracts/libraries/DataTypes.sol | 4 ++-- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/contracts/PushComm/PushCommV3.sol b/contracts/PushComm/PushCommV3.sol index e12848c6..64888f49 100644 --- a/contracts/PushComm/PushCommV3.sol +++ b/contracts/PushComm/PushCommV3.sol @@ -616,7 +616,7 @@ contract PushCommV3 is Initializable, PushCommStorageV2, IPushCommV3, PausableUp { // Implement restrictions based on functionType - if (functionType == CrossChainRequestTypes.CrossChainFunction.AddChannel) { + if (uint8(functionType) < 3) { if (amount < ADD_CHANNEL_MIN_FEES) { revert Errors.InvalidArg_LessThanExpected(ADD_CHANNEL_MIN_FEES, amount); } @@ -624,18 +624,10 @@ contract PushCommV3 is Initializable, PushCommStorageV2, IPushCommV3, PausableUp if (amount < FEE_AMOUNT) { revert Errors.InvalidArg_LessThanExpected(FEE_AMOUNT, amount); } - } else if (functionType == CrossChainRequestTypes.CrossChainFunction.CreateChannelSettings) { - if (amount < ADD_CHANNEL_MIN_FEES) { - revert Errors.InvalidArg_LessThanExpected(ADD_CHANNEL_MIN_FEES, amount); - } } else if (functionType == CrossChainRequestTypes.CrossChainFunction.ArbitraryRequest) { if (amount == 0) { revert Errors.InvalidArg_LessThanExpected(1, amount); } - } else if (functionType == CrossChainRequestTypes.CrossChainFunction.ReactivateChannel) { - if (amount < ADD_CHANNEL_MIN_FEES) { - revert Errors.InvalidArg_LessThanExpected(ADD_CHANNEL_MIN_FEES, amount); - } } bytes memory requestPayload = abi.encode(functionType, payload, amount, msg.sender); diff --git a/contracts/libraries/DataTypes.sol b/contracts/libraries/DataTypes.sol index 64dba682..eb7c6719 100644 --- a/contracts/libraries/DataTypes.sol +++ b/contracts/libraries/DataTypes.sol @@ -114,11 +114,11 @@ library CrossChainRequestTypes { // Payload enum CrossChainFunction { AddChannel, + CreateChannelSettings, + ReactivateChannel, IncentivizedChat, ArbitraryRequest, - CreateChannelSettings, AdminRequest_AddPoolFee, - ReactivateChannel, DeactivateDeleteChannel, UpdateChannelMeta } From b60fc89ea9bd3395cfb82ac5b84afce82ab86460 Mon Sep 17 00:00:00 2001 From: Md Zartaj Afser Date: Fri, 2 Aug 2024 23:54:47 +0530 Subject: [PATCH 15/23] name fix and check shift --- contracts/PushCore/PushCoreV3.sol | 21 +++++++++---------- contracts/libraries/DataTypes.sol | 2 +- test/CCR/CCRutils/Helper.sol | 2 +- .../DeactivateDeleteChannelCCR.t.sol | 14 ++++++------- 4 files changed, 19 insertions(+), 20 deletions(-) diff --git a/contracts/PushCore/PushCoreV3.sol b/contracts/PushCore/PushCoreV3.sol index f5223742..4e6f5cf1 100644 --- a/contracts/PushCore/PushCoreV3.sol +++ b/contracts/PushCore/PushCoreV3.sol @@ -296,18 +296,14 @@ contract PushCoreV3 is bytes32 _channelBytesID = BaseHelper.addressToBytes32(msg.sender); if(channelInfo[_channelBytesID].channelState == 2) { - if (_amount < ADD_CHANNEL_MIN_FEES) { - revert Errors.InvalidArg_LessThanExpected(ADD_CHANNEL_MIN_FEES, _amount); - } - IERC20(PUSH_TOKEN_ADDRESS).safeTransferFrom(msg.sender, address(this), _amount); - reactivateChanel( _channelBytesID, _amount); + _reactivateChannel( _channelBytesID, _amount); }else { - deactivateDeleteChannel( _channelBytesID, msg.sender); + _deactivateChannel( _channelBytesID, msg.sender); } } - function deactivateDeleteChannel(bytes32 _channelBytesID, address recipient) internal { + function _deactivateChannel(bytes32 _channelBytesID, address recipient) internal { CoreTypes.Channel storage channelData = channelInfo[_channelBytesID]; uint8 channelCurrentState = channelData.channelState; @@ -341,7 +337,10 @@ contract PushCoreV3 is IERC20(PUSH_TOKEN_ADDRESS).safeTransfer(recipient, totalRefundableAmount); } - function reactivateChanel(bytes32 _channelBytesID, uint256 _amount) internal { + function _reactivateChannel(bytes32 _channelBytesID, uint256 _amount) internal { + if (_amount < ADD_CHANNEL_MIN_FEES) { + revert Errors.InvalidArg_LessThanExpected(ADD_CHANNEL_MIN_FEES, _amount); + } CoreTypes.Channel storage channelData = channelInfo[_channelBytesID]; uint256 poolFeeAmount = FEE_AMOUNT; uint256 poolFundAmount = _amount - poolFeeAmount; @@ -877,13 +876,13 @@ contract PushCoreV3 is } else if (functionType == CrossChainRequestTypes.CrossChainFunction.UpdateChannelMeta) { (bytes memory _newIdentity) = abi.decode(structPayload, (bytes)); _updateChannelMeta(sender, _newIdentity, amount); - } else if (functionType == CrossChainRequestTypes.CrossChainFunction.DeactivateDeleteChannel) { + } else if (functionType == CrossChainRequestTypes.CrossChainFunction.DeactivateChannel) { // Specific Request: Deactivating or Deleting Channel (address recipient) = abi.decode(structPayload, (address)); - deactivateDeleteChannel(sender, recipient); + _deactivateChannel(sender, recipient); } else if (functionType == CrossChainRequestTypes.CrossChainFunction.ReactivateChannel) { // Specific Request: Deactivating or Deleting Channel - reactivateChanel(sender, amount); + _reactivateChannel(sender, amount); } else if (functionType == CrossChainRequestTypes.CrossChainFunction.ArbitraryRequest) { // Arbitrary Request (uint8 feeId, GenericTypes.Percentage memory feePercentage, bytes32 amountRecipient) = diff --git a/contracts/libraries/DataTypes.sol b/contracts/libraries/DataTypes.sol index eb7c6719..a1bf4fbd 100644 --- a/contracts/libraries/DataTypes.sol +++ b/contracts/libraries/DataTypes.sol @@ -119,7 +119,7 @@ library CrossChainRequestTypes { IncentivizedChat, ArbitraryRequest, AdminRequest_AddPoolFee, - DeactivateDeleteChannel, + DeactivateChannel, UpdateChannelMeta } } diff --git a/test/CCR/CCRutils/Helper.sol b/test/CCR/CCRutils/Helper.sol index baa29c84..27ad3ddd 100644 --- a/test/CCR/CCRutils/Helper.sol +++ b/test/CCR/CCRutils/Helper.sol @@ -111,7 +111,7 @@ contract Helper is BasePushCommTest, CCRConfig { }else if (typeOfReq == CrossChainRequestTypes.CrossChainFunction.ArbitraryRequest) { payload = abi.encode(_feeId, _percentage, amountRecipient); - }else if (typeOfReq == CrossChainRequestTypes.CrossChainFunction.DeactivateDeleteChannel) { + }else if (typeOfReq == CrossChainRequestTypes.CrossChainFunction.DeactivateChannel) { payload = abi.encode(amountRecipient); } else if (typeOfReq == CrossChainRequestTypes.CrossChainFunction.ReactivateChannel) { diff --git a/test/CCR/SpecificRequest/UpdateChannelStateCCR/DeactivateDeleteChannelCCR/DeactivateDeleteChannelCCR.t.sol b/test/CCR/SpecificRequest/UpdateChannelStateCCR/DeactivateDeleteChannelCCR/DeactivateDeleteChannelCCR.t.sol index c8b4827e..99bc6c32 100644 --- a/test/CCR/SpecificRequest/UpdateChannelStateCCR/DeactivateDeleteChannelCCR/DeactivateDeleteChannelCCR.t.sol +++ b/test/CCR/SpecificRequest/UpdateChannelStateCCR/DeactivateDeleteChannelCCR/DeactivateDeleteChannelCCR.t.sol @@ -8,14 +8,14 @@ import { console } from "forge-std/console.sol"; import { CrossChainRequestTypes } from "contracts/libraries/DataTypes.sol"; import { BaseHelper } from "contracts/libraries/BaseHelper.sol"; -contract DeactivateDeleteChannelCCR is BaseCCRTest { +contract DeactivateChannelCCR is BaseCCRTest { uint256 amount; function setUp() public override { BaseCCRTest.setUp(); sourceAddress = toWormholeFormat(address(commProxy)); (_payload, requestPayload) = getSpecificPayload( - CrossChainRequestTypes.CrossChainFunction.DeactivateDeleteChannel, + CrossChainRequestTypes.CrossChainFunction.DeactivateChannel, BaseHelper.addressToBytes32(actor.bob_channel_owner), amount, 0, @@ -39,7 +39,7 @@ contract DeactivateDeleteChannelCCR is BaseCCRTest { vm.expectRevert("Pausable: paused"); changePrank(actor.bob_channel_owner); commProxy.createCrossChainRequest( - CrossChainRequestTypes.CrossChainFunction.DeactivateDeleteChannel, _payload, amount, GasLimit + CrossChainRequestTypes.CrossChainFunction.DeactivateChannel, _payload, amount, GasLimit ); } @@ -48,7 +48,7 @@ contract DeactivateDeleteChannelCCR is BaseCCRTest { vm.expectRevert(abi.encodeWithSelector(Errors.InsufficientFunds.selector)); changePrank(actor.bob_channel_owner); commProxy.createCrossChainRequest( - CrossChainRequestTypes.CrossChainFunction.DeactivateDeleteChannel, _payload, amount, GasLimit + CrossChainRequestTypes.CrossChainFunction.DeactivateChannel, _payload, amount, GasLimit ); } @@ -58,7 +58,7 @@ contract DeactivateDeleteChannelCCR is BaseCCRTest { emit LogMessagePublished(SourceChain.WORMHOLE_RELAYER_SOURCE, 2105, 0, requestPayload, 15); changePrank(actor.bob_channel_owner); commProxy.createCrossChainRequest{ value: 1e18 }( - CrossChainRequestTypes.CrossChainFunction.DeactivateDeleteChannel, _payload, amount, GasLimit + CrossChainRequestTypes.CrossChainFunction.DeactivateChannel, _payload, amount, GasLimit ); } @@ -138,7 +138,7 @@ contract DeactivateDeleteChannelCCR is BaseCCRTest { function test_whenTokensAreTransferred() external { amount = ADD_CHANNEL_MIN_FEES; (_payload, requestPayload) = getSpecificPayload( - CrossChainRequestTypes.CrossChainFunction.DeactivateDeleteChannel, + CrossChainRequestTypes.CrossChainFunction.DeactivateChannel, BaseHelper.addressToBytes32(actor.bob_channel_owner), amount, 0, @@ -152,7 +152,7 @@ contract DeactivateDeleteChannelCCR is BaseCCRTest { changePrank(actor.bob_channel_owner); vm.recordLogs(); commProxy.createCrossChainRequest{ value: 1e18 }( - CrossChainRequestTypes.CrossChainFunction.DeactivateDeleteChannel, _payload, amount, GasLimit + CrossChainRequestTypes.CrossChainFunction.DeactivateChannel, _payload, amount, GasLimit ); (address sourceNttManager, bytes32 recipient, uint256 _amount, uint16 recipientChain) = From 83a51309b840d83ddcd282d6fb9d1510fc7e881e Mon Sep 17 00:00:00 2001 From: Md Zartaj Afser Date: Sat, 3 Aug 2024 00:06:43 +0530 Subject: [PATCH 16/23] fix tree --- .../DeactivateDeleteChannelCCR/DeactivateDeleteChannelCCR.tree | 2 +- .../ReactivateChannelCCR/ReactivateChannelCCR.tree | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/CCR/SpecificRequest/UpdateChannelStateCCR/DeactivateDeleteChannelCCR/DeactivateDeleteChannelCCR.tree b/test/CCR/SpecificRequest/UpdateChannelStateCCR/DeactivateDeleteChannelCCR/DeactivateDeleteChannelCCR.tree index b7c6c193..2e25825f 100644 --- a/test/CCR/SpecificRequest/UpdateChannelStateCCR/DeactivateDeleteChannelCCR/DeactivateDeleteChannelCCR.tree +++ b/test/CCR/SpecificRequest/UpdateChannelStateCCR/DeactivateDeleteChannelCCR/DeactivateDeleteChannelCCR.tree @@ -1,4 +1,4 @@ -UpdateChannelStateCCR.t.sol +DeactivateChannelCCR.t.sol ├── when createCrossChainReq is called │ ├── when contract is paused │ │ └── it should Revert diff --git a/test/CCR/SpecificRequest/UpdateChannelStateCCR/ReactivateChannelCCR/ReactivateChannelCCR.tree b/test/CCR/SpecificRequest/UpdateChannelStateCCR/ReactivateChannelCCR/ReactivateChannelCCR.tree index 206a9e58..f79d3703 100644 --- a/test/CCR/SpecificRequest/UpdateChannelStateCCR/ReactivateChannelCCR/ReactivateChannelCCR.tree +++ b/test/CCR/SpecificRequest/UpdateChannelStateCCR/ReactivateChannelCCR/ReactivateChannelCCR.tree @@ -1,4 +1,4 @@ -UpdateChannelStateCCR.t.sol +ReactivateChannelCCR.t.sol ├── when createCrossChainReq is called │ ├── when contract is paused │ │ └── it should Revert From 4ed2b4e0fdff6234ea73e5e15c82b7cc987c40c8 Mon Sep 17 00:00:00 2001 From: Md Zartaj Afser Date: Tue, 6 Aug 2024 19:02:50 +0530 Subject: [PATCH 17/23] fix if block --- contracts/PushComm/PushCommV3.sol | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/contracts/PushComm/PushCommV3.sol b/contracts/PushComm/PushCommV3.sol index 64888f49..aa775140 100644 --- a/contracts/PushComm/PushCommV3.sol +++ b/contracts/PushComm/PushCommV3.sol @@ -616,7 +616,9 @@ contract PushCommV3 is Initializable, PushCommStorageV2, IPushCommV3, PausableUp { // Implement restrictions based on functionType - if (uint8(functionType) < 3) { + if (functionType == CrossChainRequestTypes.CrossChainFunction.AddChannel || + functionType == CrossChainRequestTypes.CrossChainFunction.CreateChannelSettings || + functionType == CrossChainRequestTypes.CrossChainFunction.ReactivateChannel ) { if (amount < ADD_CHANNEL_MIN_FEES) { revert Errors.InvalidArg_LessThanExpected(ADD_CHANNEL_MIN_FEES, amount); } From 35b7639ce1b1b71ad5ea63bd94ba5f9e1ed2538d Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Wed, 7 Aug 2024 15:57:14 +0530 Subject: [PATCH 18/23] refactor: updated address param in events to bytes32 for consistency --- contracts/PushCore/PushCoreV3.sol | 14 +++++++------- contracts/interfaces/IPushCoreV3.sol | 14 +++++++------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/contracts/PushCore/PushCoreV3.sol b/contracts/PushCore/PushCoreV3.sol index 4e6f5cf1..a1daea7c 100644 --- a/contracts/PushCore/PushCoreV3.sol +++ b/contracts/PushCore/PushCoreV3.sol @@ -76,7 +76,7 @@ contract PushCoreV3 is function addSubGraph(bytes calldata _subGraphData) external { onlyActivatedChannels(BaseHelper.addressToBytes32(msg.sender)); - emit AddSubGraph(msg.sender, _subGraphData); + emit AddSubGraph(BaseHelper.addressToBytes32(msg.sender), _subGraphData); } function setEpnsCommunicatorAddress(address _commAddress) external { @@ -452,7 +452,7 @@ contract PushCoreV3 is channelInfo[_channel].verifiedBy = msg.sender; // Emit event - emit ChannelVerified(_channel, msg.sender); + emit ChannelVerified(_channel, BaseHelper.addressToBytes32(msg.sender)); } /// @inheritdoc IPushCoreV3 @@ -465,7 +465,7 @@ contract PushCoreV3 is channelInfo[_channel].verifiedBy = address(0x0); // Emit Event - emit ChannelVerificationRevoked(_channel, msg.sender); + emit ChannelVerificationRevoked(_channel, BaseHelper.addressToBytes32(msg.sender)); } /** @@ -786,7 +786,7 @@ contract PushCoreV3 is PROTOCOL_POOL_FEES = PROTOCOL_POOL_FEES + poolFeeAmount; emit IncentivizeChatReqReceived( - requestSender, requestReceiver, requestReceiverAmount, poolFeeAmount, block.timestamp + requestSender, BaseHelper.addressToBytes32(requestReceiver), requestReceiverAmount, poolFeeAmount, block.timestamp ); } @@ -799,7 +799,7 @@ contract PushCoreV3 is celebUserFunds[msg.sender] -= _amount; IERC20(PUSH_TOKEN_ADDRESS).safeTransfer(msg.sender, _amount); - emit ChatIncentiveClaimed(msg.sender, _amount); + emit ChatIncentiveClaimed(BaseHelper.addressToBytes32(msg.sender), _amount); } /* ***************************** @@ -941,7 +941,7 @@ contract PushCoreV3 is arbitraryReqFees[amountRecipient] += amount - feeAmount; // Emit an event for the arbitrary request - emit ArbitraryRequest(sender, amountRecipient, amount, feePercentage, feeId); + emit ArbitraryRequest(sender, BaseHelper.addressToBytes32(amountRecipient), amount, feePercentage, feeId); } /** @@ -963,7 +963,7 @@ contract PushCoreV3 is arbitraryReqFees[msg.sender] = userFeesBalance - _amount; IERC20(PUSH_TOKEN_ADDRESS).safeTransfer(msg.sender, _amount); - emit ArbitraryRequestFeesClaimed(msg.sender, _amount); + emit ArbitraryRequestFeesClaimed(BaseHelper.addressToBytes32(msg.sender), _amount); } function migrateAddressToBytes32(address[] calldata _channels) external whenPaused { diff --git a/contracts/interfaces/IPushCoreV3.sol b/contracts/interfaces/IPushCoreV3.sol index da6b9272..5808cb3b 100644 --- a/contracts/interfaces/IPushCoreV3.sol +++ b/contracts/interfaces/IPushCoreV3.sol @@ -12,9 +12,9 @@ interface IPushCoreV3 { /// @notice emits whenever a channel updates its metadata event UpdateChannel(bytes32 indexed channel, bytes identity, uint256 indexed amountDeposited); /// @notice emits whenever a channel is verified either by admin or any otherchannel with primary verification - event ChannelVerified(bytes32 indexed channel, address indexed verifier); + event ChannelVerified(bytes32 indexed channel, bytes32 indexed verifier); /// @notice emits whenever the verification is revoked for a channel - event ChannelVerificationRevoked(bytes32 indexed channel, address indexed revoker); + event ChannelVerificationRevoked(bytes32 indexed channel, bytes32 indexed revoker); /// @notice emits whenever any channel is blocked by admin event ChannelBlocked(bytes32 indexed channel); /// @notice emits whenever a new channel is created - ToDo: Remove this event @@ -26,7 +26,7 @@ interface IPushCoreV3 { bytes32 _channel, uint256 totalNotifOptions, string _notifSettings, string _notifDescription ); /// @notice emits whenever a subgraph is added(handled by backend) - event AddSubGraph(address indexed channel, bytes _subGraphData); + event AddSubGraph(bytes32 indexed channel, bytes _subGraphData); /// @notice emits whenever any time bound channel is deleted permanently // event TimeBoundChannelDestroyed(address indexed channel, uint256 indexed amountRefunded); /// @notice emits whenever a user stakes in the staking program @@ -38,26 +38,26 @@ interface IPushCoreV3 { /// @notice emits whenever any user receives an incentivized chat request from another user event IncentivizeChatReqReceived( bytes32 requestSender, - address requestReceiver, + bytes32 requestReceiver, uint256 amountForReqReceiver, uint256 feePoolAmount, uint256 timestamp ); /// @notice emits whenever a user claims the remianing funds that they got from incentivized chat - event ChatIncentiveClaimed(address indexed user, uint256 indexed amountClaimed); + event ChatIncentiveClaimed(bytes32 indexed user, uint256 indexed amountClaimed); /// @notice emits when the state of a channel is updated from Active State to either Deactivated, Reactivated, /// Blocked or Deleted event ChannelStateUpdate(bytes32 indexed channel, uint256 amountRefunded, uint256 amountDeposited); /// @notice emits when arbitray cross chain request is received event ArbitraryRequest( bytes32 indexed sender, - address indexed receiver, + bytes32 indexed receiver, uint256 amountDeposited, GenericTypes.Percentage feePercent, uint256 indexed feeId ); /// @notice emits whenever a user claims the funds that they got from arbirary request fees - event ArbitraryRequestFeesClaimed(address indexed user, uint256 indexed amountClaimed); + event ArbitraryRequestFeesClaimed(bytes32 indexed user, uint256 indexed amountClaimed); /* ***************************** From 4a0467ec2098e52cf9e4dc7f67e5603ced7698e4 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Wed, 7 Aug 2024 15:57:40 +0530 Subject: [PATCH 19/23] tests: updated test cases with event changes --- .../ArbitraryRequest/ArbitraryRequest.t.sol | 2 +- .../CreateChatCCR/CreateChatCCR.t.sol | 2 +- .../ChannelUnverification.t.sol | 14 +++++---- .../ChannelVerification.t.sol | 30 ++++++++++--------- test/utils/Events.sol | 8 ++--- 5 files changed, 30 insertions(+), 26 deletions(-) diff --git a/test/CCR/ArbitraryRequest/ArbitraryRequest.t.sol b/test/CCR/ArbitraryRequest/ArbitraryRequest.t.sol index a9516b9d..33a63191 100644 --- a/test/CCR/ArbitraryRequest/ArbitraryRequest.t.sol +++ b/test/CCR/ArbitraryRequest/ArbitraryRequest.t.sol @@ -134,7 +134,7 @@ contract ArbitraryRequesttsol is BaseCCRTest { (uint256 poolFunds, uint256 poolFees) = getPoolFundsAndFees(amount); vm.expectEmit(true, true, false, true); - emit ArbitraryRequest(BaseHelper.addressToBytes32(actor.bob_channel_owner), actor.charlie_channel_owner, amount, percentage, 1); + emit ArbitraryRequest(BaseHelper.addressToBytes32(actor.bob_channel_owner), BaseHelper.addressToBytes32(actor.charlie_channel_owner), amount, percentage, 1); coreProxy.receiveWormholeMessages( requestPayload, additionalVaas, sourceAddress, SourceChain.SourceChainId, deliveryHash diff --git a/test/CCR/SpecificRequest/CreateChatCCR/CreateChatCCR.t.sol b/test/CCR/SpecificRequest/CreateChatCCR/CreateChatCCR.t.sol index 2d3f5df5..50aceb94 100644 --- a/test/CCR/SpecificRequest/CreateChatCCR/CreateChatCCR.t.sol +++ b/test/CCR/SpecificRequest/CreateChatCCR/CreateChatCCR.t.sol @@ -115,7 +115,7 @@ contract CreateChatCCR is BaseCCRTest { vm.expectEmit(false, false, false, true); emit IncentivizeChatReqReceived( - BaseHelper.addressToBytes32(actor.bob_channel_owner), actor.charlie_channel_owner, amount - poolFeeAmount, poolFeeAmount, block.timestamp + BaseHelper.addressToBytes32(actor.bob_channel_owner), BaseHelper.addressToBytes32(actor.charlie_channel_owner), amount - poolFeeAmount, poolFeeAmount, block.timestamp ); receiveWormholeMessage(requestPayload); diff --git a/test/PushCore/unit_tests/ChannelVerifyTag/ChannelUnverification/ChannelUnverification.t.sol b/test/PushCore/unit_tests/ChannelVerifyTag/ChannelUnverification/ChannelUnverification.t.sol index afed301f..369e6060 100644 --- a/test/PushCore/unit_tests/ChannelVerifyTag/ChannelUnverification/ChannelUnverification.t.sol +++ b/test/PushCore/unit_tests/ChannelVerifyTag/ChannelUnverification/ChannelUnverification.t.sol @@ -7,6 +7,7 @@ contract ChannelUnverification_Test is BasePushCoreTest { bytes32 bobBytes; bytes32 aliceBytes; bytes32 charlieBytes; + bytes32 adminBytes; function setUp() public virtual override { BasePushCoreTest.setUp(); _createChannel(actor.bob_channel_owner); @@ -16,6 +17,7 @@ contract ChannelUnverification_Test is BasePushCoreTest { bobBytes = toWormholeFormat(actor.bob_channel_owner); aliceBytes = toWormholeFormat(actor.alice_channel_owner); charlieBytes = toWormholeFormat(actor.charlie_channel_owner); + adminBytes = toWormholeFormat(actor.admin); } function test_WhenAdminUnverifies_AChannelVerifiedBy_AdminItself() external { @@ -28,7 +30,7 @@ contract ChannelUnverification_Test is BasePushCoreTest { changePrank(actor.admin); vm.expectEmit(true, true, false, false); - emit ChannelVerificationRevoked(channelCreators.bob_channel_owner_Bytes32, actor.admin); + emit ChannelVerificationRevoked(channelCreators.bob_channel_owner_Bytes32, adminBytes); coreProxy.unverifyChannel(bobBytes); uint8 bobVerificationAfter = coreProxy.getChannelVerfication(bobBytes); @@ -50,7 +52,7 @@ contract ChannelUnverification_Test is BasePushCoreTest { changePrank(actor.admin); vm.expectEmit(true, true, false, false); - emit ChannelVerificationRevoked(channelCreators.alice_channel_owner_Bytes32, actor.admin); + emit ChannelVerificationRevoked(channelCreators.alice_channel_owner_Bytes32, adminBytes); coreProxy.unverifyChannel(aliceBytes); uint8 aliceVerificationAfter = coreProxy.getChannelVerfication(aliceBytes); @@ -72,7 +74,7 @@ contract ChannelUnverification_Test is BasePushCoreTest { changePrank(actor.bob_channel_owner); vm.expectEmit(true, true, false, false); - emit ChannelVerificationRevoked(channelCreators.alice_channel_owner_Bytes32, actor.bob_channel_owner); + emit ChannelVerificationRevoked(channelCreators.alice_channel_owner_Bytes32, bobBytes); coreProxy.unverifyChannel(aliceBytes); uint8 aliceVerificationAfter = coreProxy.getChannelVerfication(aliceBytes); @@ -121,7 +123,7 @@ contract ChannelUnverification_Test is BasePushCoreTest { changePrank(actor.charlie_channel_owner); vm.expectEmit(true, true, false, false); - emit ChannelVerificationRevoked(channelCreators.alice_channel_owner_Bytes32, actor.charlie_channel_owner); + emit ChannelVerificationRevoked(channelCreators.alice_channel_owner_Bytes32, charlieBytes); coreProxy.unverifyChannel(aliceBytes); uint8 aliceVerificationAfter = coreProxy.getChannelVerfication(aliceBytes); @@ -147,7 +149,7 @@ contract ChannelUnverification_Test is BasePushCoreTest { changePrank(actor.bob_channel_owner); vm.expectEmit(true, true, false, false); - emit ChannelVerificationRevoked(channelCreators.charlie_channel_owner_Bytes32, actor.bob_channel_owner); + emit ChannelVerificationRevoked(channelCreators.charlie_channel_owner_Bytes32, bobBytes); coreProxy.unverifyChannel(charlieBytes); uint8 charlieVerificationAfter = coreProxy.getChannelVerfication(charlieBytes); @@ -178,7 +180,7 @@ contract ChannelUnverification_Test is BasePushCoreTest { changePrank(actor.admin); vm.expectEmit(true, true, false, false); - emit ChannelVerificationRevoked(channelCreators.bob_channel_owner_Bytes32, actor.admin); + emit ChannelVerificationRevoked(channelCreators.bob_channel_owner_Bytes32, adminBytes); coreProxy.unverifyChannel(bobBytes); uint8 bobVerificationAfter = coreProxy.getChannelVerfication(bobBytes); diff --git a/test/PushCore/unit_tests/ChannelVerifyTag/ChannelVerification/ChannelVerification.t.sol b/test/PushCore/unit_tests/ChannelVerifyTag/ChannelVerification/ChannelVerification.t.sol index 6445b735..50db9e24 100644 --- a/test/PushCore/unit_tests/ChannelVerifyTag/ChannelVerification/ChannelVerification.t.sol +++ b/test/PushCore/unit_tests/ChannelVerifyTag/ChannelVerification/ChannelVerification.t.sol @@ -7,6 +7,7 @@ contract ChannelVerification_Test is BasePushCoreTest { bytes32 bobBytes; bytes32 aliceBytes; bytes32 charlieBytes; + bytes32 adminBytes; function setUp() public virtual override { BasePushCoreTest.setUp(); _createChannel(actor.bob_channel_owner); @@ -16,6 +17,7 @@ contract ChannelVerification_Test is BasePushCoreTest { bobBytes = toWormholeFormat(actor.bob_channel_owner); aliceBytes = toWormholeFormat(actor.alice_channel_owner); charlieBytes = toWormholeFormat(actor.charlie_channel_owner); + adminBytes = toWormholeFormat(actor.admin); } modifier whenCheckedTheDefaultVerificationStatus() { @@ -71,7 +73,7 @@ contract ChannelVerification_Test is BasePushCoreTest { // it should return primary verified for channels verified by admin changePrank(actor.admin); vm.expectEmit(true, true, false, false); - emit ChannelVerified(channelCreators.bob_channel_owner_Bytes32, actor.admin); + emit ChannelVerified(channelCreators.bob_channel_owner_Bytes32, adminBytes); coreProxy.verifyChannel(bobBytes); uint8 bobVerification = coreProxy.getChannelVerfication(bobBytes); @@ -85,12 +87,12 @@ contract ChannelVerification_Test is BasePushCoreTest { // it should give secondary verification(2) to that channel changePrank(actor.admin); vm.expectEmit(true, true, false, false); - emit ChannelVerified(channelCreators.bob_channel_owner_Bytes32, actor.admin); + emit ChannelVerified(channelCreators.bob_channel_owner_Bytes32, adminBytes); coreProxy.verifyChannel(bobBytes); changePrank(actor.bob_channel_owner); vm.expectEmit(true, true, false, false); - emit ChannelVerified(channelCreators.alice_channel_owner_Bytes32, actor.bob_channel_owner); + emit ChannelVerified(channelCreators.alice_channel_owner_Bytes32, bobBytes); coreProxy.verifyChannel(aliceBytes); uint8 aliceVerification = coreProxy.getChannelVerfication(aliceBytes); @@ -117,11 +119,11 @@ contract ChannelVerification_Test is BasePushCoreTest { // it should allow admin to give primary verification changePrank(actor.admin); vm.expectEmit(true, true, false, false); - emit ChannelVerified(channelCreators.bob_channel_owner_Bytes32, actor.admin); + emit ChannelVerified(channelCreators.bob_channel_owner_Bytes32, adminBytes); coreProxy.verifyChannel(bobBytes); vm.expectEmit(true, true, false, false); - emit ChannelVerified(channelCreators.alice_channel_owner_Bytes32, actor.bob_channel_owner); + emit ChannelVerified(channelCreators.alice_channel_owner_Bytes32, bobBytes); changePrank(actor.bob_channel_owner); coreProxy.verifyChannel(aliceBytes); @@ -133,7 +135,7 @@ contract ChannelVerification_Test is BasePushCoreTest { changePrank(actor.admin); vm.expectEmit(true, true, false, false); - emit ChannelVerified(channelCreators.alice_channel_owner_Bytes32, actor.admin); + emit ChannelVerified(channelCreators.alice_channel_owner_Bytes32, adminBytes); coreProxy.verifyChannel(aliceBytes); uint8 aliceVerificationAfter = coreProxy.getChannelVerfication(aliceBytes); @@ -148,11 +150,11 @@ contract ChannelVerification_Test is BasePushCoreTest { changePrank(actor.admin); vm.expectEmit(true, true, false, false); - emit ChannelVerified(channelCreators.bob_channel_owner_Bytes32, actor.admin); + emit ChannelVerified(channelCreators.bob_channel_owner_Bytes32, adminBytes); coreProxy.verifyChannel(bobBytes); vm.expectEmit(true, true, false, false); - emit ChannelVerified(channelCreators.alice_channel_owner_Bytes32, actor.admin); + emit ChannelVerified(channelCreators.alice_channel_owner_Bytes32, adminBytes); coreProxy.verifyChannel(aliceBytes); uint8 aliceVerificationBefore = coreProxy.getChannelVerfication(aliceBytes); @@ -176,17 +178,17 @@ contract ChannelVerification_Test is BasePushCoreTest { // it should give secondary verification to that channel changePrank(actor.admin); vm.expectEmit(true, true, false, false); - emit ChannelVerified(channelCreators.bob_channel_owner_Bytes32, actor.admin); + emit ChannelVerified(channelCreators.bob_channel_owner_Bytes32, adminBytes); coreProxy.verifyChannel(bobBytes); changePrank(actor.bob_channel_owner); vm.expectEmit(true, true, false, false); - emit ChannelVerified(channelCreators.charlie_channel_owner_Bytes32, actor.bob_channel_owner); + emit ChannelVerified(channelCreators.charlie_channel_owner_Bytes32, bobBytes); coreProxy.verifyChannel(charlieBytes); changePrank(actor.charlie_channel_owner); vm.expectEmit(true, true, false, false); - emit ChannelVerified(channelCreators.alice_channel_owner_Bytes32, actor.charlie_channel_owner); + emit ChannelVerified(channelCreators.alice_channel_owner_Bytes32, charlieBytes); coreProxy.verifyChannel(aliceBytes); uint8 aliceVerification = coreProxy.getChannelVerfication(aliceBytes); @@ -221,11 +223,11 @@ contract ChannelVerification_Test is BasePushCoreTest { changePrank(actor.admin); vm.expectEmit(true, true, false, false); - emit ChannelVerified(channelCreators.charlie_channel_owner_Bytes32, actor.admin); + emit ChannelVerified(channelCreators.charlie_channel_owner_Bytes32, adminBytes); vm.expectEmit(true, true, false, false); - emit ChannelVerified(channelCreators.bob_channel_owner_Bytes32, actor.admin); + emit ChannelVerified(channelCreators.bob_channel_owner_Bytes32, adminBytes); vm.expectEmit(true, true, false, false); - emit ChannelVerified(channelCreators.alice_channel_owner_Bytes32, actor.admin); + emit ChannelVerified(channelCreators.alice_channel_owner_Bytes32, adminBytes); coreProxy.batchVerification(0, 3, _channels); uint8 charlieVerificationAfter = coreProxy.getChannelVerfication(charlieBytes); diff --git a/test/utils/Events.sol b/test/utils/Events.sol index b8941920..541f96d1 100644 --- a/test/utils/Events.sol +++ b/test/utils/Events.sol @@ -12,18 +12,18 @@ abstract contract CoreEvents { event TimeBoundChannelDestroyed(address indexed channel, uint256 indexed amountRefunded); event IncentivizeChatReqReceived( bytes32 requestSender, - address requestReceiver, + bytes32 requestReceiver, uint256 amountForReqReceiver, uint256 feePoolAmount, uint256 timestamp ); event ChatIncentiveClaimed(address indexed user, uint256 indexed amountClaimed); - event ChannelVerified(bytes32 indexed channel, address indexed verifier); - event ChannelVerificationRevoked(bytes32 indexed channel, address indexed revoker); + event ChannelVerified(bytes32 indexed channel, bytes32 indexed verifier); + event ChannelVerificationRevoked(bytes32 indexed channel, bytes32 indexed revoker); event ChannelStateUpdate(bytes32 indexed channel, uint256 amountRefunded, uint256 amountDeposited); event ArbitraryRequest( bytes32 indexed sender, - address indexed receiver, + bytes32 indexed receiver, uint256 amountDeposited, GenericTypes.Percentage feePercent, uint256 indexed feeId From 092be1166283212c06ddb132e3931a92d11e814f Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Wed, 7 Aug 2024 16:51:34 +0530 Subject: [PATCH 20/23] git: resolve merge conflicts --- README.md | 32 ++ contracts/PushComm/PushCommETHV3.sol | 123 +++---- contracts/PushComm/PushCommEthStorageV2.sol | 4 +- contracts/PushComm/PushCommStorageV2.sol | 7 +- contracts/PushComm/PushCommV3.sol | 136 +++++--- contracts/PushCore/PushCoreV3.sol | 22 +- contracts/interfaces/IPushCommV3.sol | 12 +- contracts/interfaces/IPushCoreV3.sol | 7 +- .../interfaces/wormhole/IRateLimiter.sol | 98 ++++++ .../wormhole/IWormholeTransceiver.sol | 6 +- contracts/libraries/DataTypes.sol | 2 +- contracts/libraries/EnumerableSet.sol | 230 +++++++++++++ contracts/libraries/Errors.sol | 2 + contracts/mocks/MockERC721.sol | 18 + contracts/mocks/MockNttManager.sol | 10 + contracts/mocks/PushCoreMock.sol | 84 +---- contracts/token/PushMigration.sol | 12 +- env/.env.sample | 41 +++ env/testnet/sepolia.env | 41 +++ scripts/Deployment/DeployPushComm.s.sol | 68 ++++ scripts/Deployment/DeployPushCommEth.s.sol | 68 ++++ scripts/Deployment/DeployPushCore.s.sol | 105 ++++++ scripts/Deployment/DeployPushMigration.s.sol | 63 ++++ scripts/Deployment/DeployPushNtt.s.sol | 46 +++ scripts/Deployment/DeployPushToken.s.sol | 27 ++ scripts/Deployment/UpgradePushComm.s.sol | 57 ++++ scripts/Deployment/UpgradePushCommEth.s.sol | 57 ++++ scripts/Deployment/UpgradePushCore.s.sol | 57 ++++ scripts/Deployment/UpgradePushMigration.s.sol | 57 ++++ scripts/Deployment/UpgradePushNtt.s.sol | 57 ++++ scripts/Deployment/helpers/DeployBase.s.sol | 30 ++ sh/deploy.sh | 69 ++++ test/BaseTest.t.sol | 44 +-- .../ArbitraryRequest/ArbitraryRequest.t.sol | 41 ++- .../ArbitraryRequest/ArbitraryRequest.tree | 8 +- test/CCR/BaseCCR.t.sol | 5 +- test/CCR/CCRutils/CCRConfig.sol | 47 +-- test/CCR/CCRutils/Helper.sol | 23 +- .../NttTransferTest.t.sol | 15 +- test/CCR/NTT/RateLimit.t.sol | 42 +++ .../CreateChannelCCR/CreateChannelCCR.t.sol | 26 +- .../CreateChannelCCR/CreateChannelCCR.tree | 12 +- .../CreateChannelSettingsCCR.t.sol | 2 +- .../CreateChatCCR/CreateChatCCR.t.sol | 39 ++- .../CreateChatCCR/CreateChatCCR.tree | 14 +- .../UpdateChannelMetaCCR.t.sol | 2 +- .../DeactivateDeleteChannelCCR.t.sol | 2 +- .../ReactivateChannelCCR.t.sol | 2 +- .../unit_tests/BasePushCommTest.t.sol | 2 +- .../CommAdminActions/CommAdminActions.t.sol | 4 +- .../WalletPGPActions/walletPGP.t.sol | 318 ++++++++++++++++++ .../WalletPGPActions/walletPGP.tree | 29 ++ .../WalletPGPActions/walletPGPforETH.t.sol | 290 ++++++++++++++++ .../unit_tests/BasePushCoreTest.t.sol | 2 +- .../createChannelWithPUSH.t.sol | 2 +- .../ChannelMigration/ChannelMigration.t.sol | 2 +- .../deactivateChannel/deactivateChannel.t.sol | 2 +- .../createIncentivizedChat.t.sol | 89 +++++ .../createIncentivizedChat.tree | 15 + .../HandleArbitraryReq.t.sol | 53 +++ .../HandleArbitraryReq.tree | 8 + .../TimeBoundChannel/timeBoundChannel.t.sol | 2 +- test/utils/Events.sol | 16 +- .../v2/core/IncentivizedChatRequest.test.js | 4 +- 64 files changed, 2474 insertions(+), 336 deletions(-) create mode 100644 contracts/interfaces/wormhole/IRateLimiter.sol create mode 100644 contracts/libraries/EnumerableSet.sol create mode 100644 contracts/mocks/MockERC721.sol create mode 100644 contracts/mocks/MockNttManager.sol create mode 100644 env/.env.sample create mode 100644 env/testnet/sepolia.env create mode 100644 scripts/Deployment/DeployPushComm.s.sol create mode 100644 scripts/Deployment/DeployPushCommEth.s.sol create mode 100644 scripts/Deployment/DeployPushCore.s.sol create mode 100644 scripts/Deployment/DeployPushMigration.s.sol create mode 100644 scripts/Deployment/DeployPushNtt.s.sol create mode 100644 scripts/Deployment/DeployPushToken.s.sol create mode 100644 scripts/Deployment/UpgradePushComm.s.sol create mode 100644 scripts/Deployment/UpgradePushCommEth.s.sol create mode 100644 scripts/Deployment/UpgradePushCore.s.sol create mode 100644 scripts/Deployment/UpgradePushMigration.s.sol create mode 100644 scripts/Deployment/UpgradePushNtt.s.sol create mode 100644 scripts/Deployment/helpers/DeployBase.s.sol create mode 100644 sh/deploy.sh rename test/CCR/{NTTtransfer => NTT}/NttTransferTest.t.sol (80%) create mode 100644 test/CCR/NTT/RateLimit.t.sol create mode 100644 test/PushComm/unit_tests/WalletPGPActions/walletPGP.t.sol create mode 100644 test/PushComm/unit_tests/WalletPGPActions/walletPGP.tree create mode 100644 test/PushComm/unit_tests/WalletPGPActions/walletPGPforETH.t.sol create mode 100644 test/PushCore/unit_tests/CreateIncentivizedChat/createIncentivizedChat.t.sol create mode 100644 test/PushCore/unit_tests/CreateIncentivizedChat/createIncentivizedChat.tree create mode 100644 test/PushCore/unit_tests/HandleArbitraryRequest/HandleArbitraryReq.t.sol create mode 100644 test/PushCore/unit_tests/HandleArbitraryRequest/HandleArbitraryReq.tree diff --git a/README.md b/README.md index d973ec4e..ab2828bc 100644 --- a/README.md +++ b/README.md @@ -130,6 +130,38 @@ cd contracts npx hardhat test ``` +## Deploy & verify + +### Environment Setup + +Copy the sample environment file located in `env/` into the target subdirectory of your choice (e.g., `testnet` or `mainnet`) and prefix the filename with your blockchain of choice: + +``` +mkdir env/testnet +cp env/.env.sample env/testnet/sepolia.env +``` + +Do this for each blockchain network that the contracts will be deployed to. Then configure each `.env` file. + +### Deploy + +Deploy the contracts by running the following command for each target network: + +``` +bash sh/deploy.sh -n NETWORK_TYPE -c CHAIN_NAME -k PRIVATE_KEY -s DEPLOYMENT_SCRIPT -v VERIFICATION_KEY +``` + +``` +# Argument examples +-n testnet, mainnet +-c avalanche, ethereum, sepolia +-s DeployPushNtt.s.sol, child/UpgradePushNtt.s.sol +``` + +The deployments are stored in ./broadcast + +See the [Foundry Book for available options](https://book.getfoundry.sh/reference/forge/forge-create.html). + --- ## Resources diff --git a/contracts/PushComm/PushCommETHV3.sol b/contracts/PushComm/PushCommETHV3.sol index eab995bb..f6f44cd8 100644 --- a/contracts/PushComm/PushCommETHV3.sol +++ b/contracts/PushComm/PushCommETHV3.sol @@ -21,6 +21,7 @@ import { IPushCommV3 } from "../interfaces/IPushCommV3.sol"; import { BaseHelper } from "../libraries/BaseHelper.sol"; import { CommTypes } from "../libraries/DataTypes.sol"; import { IERC1271 } from "../interfaces/signatures/IERC1271.sol"; +import { IERC721 } from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; @@ -139,50 +140,6 @@ contract PushCommETHV3 is Initializable, PushCommEthStorageV2, IPushCommV3 { return true; } - /** - * @notice This Function helps in migrating the already existing Subscriber's data to the New protocol - * - * @dev Can only be called by pushChannelAdmin - * Can only be called if the Migration is not yet complete, i.e., "isMigrationComplete" boolean must be - * false - * Subscribes the Users to the respective Channels as per the arguments passed to the function - * - * @param _startIndex starting Index for the LOOP - * @param _endIndex Last Index for the LOOP - * @param _channelList array of addresses of the channels - * @param _usersList array of addresses of the Users or Subscribers of the Channels - * - */ - // function migrateSubscribeData( - // uint256 _startIndex, - // uint256 _endIndex, - // address[] calldata _channelList, - // address[] calldata _usersList - // ) - // external - // onlyPushChannelAdmin - // returns (bool) - // { - // if (isMigrationComplete || _channelList.length != _usersList.length) { - // revert Errors.InvalidArg_ArrayLengthMismatch(); - // } - - // for (uint256 i = _startIndex; i < _endIndex;) { - // if (isUserSubscribed(_channelList[i], _usersList[i])) { - // unchecked { - // i++; - // } - // continue; - // } else { - // _subscribe(_channelList[i], _usersList[i]); - // } - // unchecked { - // i++; - // } - // } - // return true; - // } - /** * @notice Base Subscribe Function that allows users to Subscribe to a Particular Channel * @@ -516,25 +473,71 @@ contract PushCommETHV3 is Initializable, PushCommEthStorageV2, IPushCommV3 { emit UserNotifcationSettingsAdded(_channel, msg.sender, _notifID, notifSetting); } - function createIncentivizeChatRequest(address requestReceiver, uint256 amount) external { - if (amount == 0) { - revert Errors.InvalidArg_LessThanExpected(1, amount); + function setFeeAmount(uint256 _feeAmount) external onlyPushChannelAdmin { + FEE_AMOUNT = _feeAmount; + } + + /* ***************************** + + USER PGP Registry Functions + + ***************************** */ + function registerUserPGP(bytes calldata _caipData, string calldata _pgp, bool _isNFT) external { + uint256 fee = FEE_AMOUNT; + IERC20(PUSH_TOKEN_ADDRESS).safeTransferFrom(msg.sender, address(this), fee); + IERC20(PUSH_TOKEN_ADDRESS).approve(address(EPNSCoreAddress), fee); + IPushCoreV3(EPNSCoreAddress).addPoolFees(fee); + + bytes32 caipHash = keccak256(_caipData); + + if (!_isNFT) { + (, uint256 _chainId, address _wallet) = abi.decode(_caipData, (string, uint256, address)); + + if (bytes(walletToPGP[caipHash]).length != 0 || _wallet != msg.sender) { + revert Errors.Comm_InvalidArguments(); + } + emit UserPGPRegistered(_pgp, _wallet, chainName, chainID); + } else { + (,,, address _nft, uint256 _id,) = + abi.decode(_caipData, (string, string, uint256, address, uint256, uint256)); + require(IERC721(_nft).ownerOf(_id) == msg.sender, "NFT not owned"); + + if (bytes(walletToPGP[caipHash]).length != 0) { + string memory _previousPgp = walletToPGP[caipHash]; + emit UserPGPRemoved(_previousPgp, _nft, _id, chainName, chainID); + } + emit UserPGPRegistered(_pgp, _nft, _id, chainName, chainID); } - address requestSender = msg.sender; - address coreContract = EPNSCoreAddress; - // Transfer incoming PUSH Token to core contract - IERC20(PUSH_TOKEN_ADDRESS).safeTransferFrom(requestSender, coreContract, amount); - - CommTypes.ChatDetails storage chatData = userChatData[requestSender]; - if (chatData.amountDeposited == 0) { - chatData.requestSender = requestSender; + walletToPGP[caipHash] = _pgp; + } + + function removeWalletFromUser(bytes calldata _caipData, bool _isNFT) public { + bytes32 caipHash = keccak256(_caipData); + if (bytes(walletToPGP[caipHash]).length == 0) { + revert("Invalid Call"); } - chatData.timestamp = block.timestamp; - chatData.amountDeposited += amount; - // Trigger handleChatRequestData() on core directly from comm - IPushCoreV3(coreContract).handleChatRequestData(requestSender, requestReceiver, amount); + uint256 fee = FEE_AMOUNT; + IERC20(PUSH_TOKEN_ADDRESS).safeTransferFrom(msg.sender, address(this), fee); + IERC20(PUSH_TOKEN_ADDRESS).approve(address(EPNSCoreAddress), fee); + IPushCoreV3(EPNSCoreAddress).addPoolFees(fee); + + string memory pgp = walletToPGP[caipHash]; - emit IncentivizeChatReqInitiated(requestSender, requestReceiver, amount, block.timestamp); + if (!_isNFT) { + (, uint256 _chainId, address _wallet) = abi.decode(_caipData, (string, uint256, address)); + + if (_wallet != msg.sender) { + revert Errors.Comm_InvalidArguments(); + } + emit UserPGPRemoved(pgp, _wallet, chainName, chainID); + } else { + (,,, address _nft, uint256 _id,) = + abi.decode(_caipData, (string, string, uint256, address, uint256, uint256)); + + require(IERC721(_nft).ownerOf(_id) == msg.sender, "NFT not owned"); + emit UserPGPRemoved(pgp, _nft, _id, chainName, chainID); + } + delete walletToPGP[caipHash]; } } diff --git a/contracts/PushComm/PushCommEthStorageV2.sol b/contracts/PushComm/PushCommEthStorageV2.sol index 17ad011b..4394ae06 100644 --- a/contracts/PushComm/PushCommEthStorageV2.sol +++ b/contracts/PushComm/PushCommEthStorageV2.sol @@ -36,4 +36,6 @@ contract PushCommEthStorageV2 { address public PUSH_TOKEN_ADDRESS; mapping(address => CommTypes.ChatDetails) public userChatData; -} \ No newline at end of file + mapping(bytes32 => string) public walletToPGP; + uint256 FEE_AMOUNT; +} diff --git a/contracts/PushComm/PushCommStorageV2.sol b/contracts/PushComm/PushCommStorageV2.sol index f4aea524..13efa8c8 100644 --- a/contracts/PushComm/PushCommStorageV2.sol +++ b/contracts/PushComm/PushCommStorageV2.sol @@ -39,21 +39,20 @@ contract PushCommStorageV2 { bytes32 public constant SEND_NOTIFICATION_TYPEHASH = keccak256("SendNotification(address channel,address recipient,bytes identity,uint256 nonce,uint256 expiry)"); // New State Variables - address public PUSH_TOKEN_ADDRESS; + IERC20 public PUSH_NTT; mapping(address => CommTypes.ChatDetails) public userChatData; + mapping(bytes32 => string) public walletToPGP; // WORMHOLE CROSS-CHAIN STATE VARIABLES - IERC20 public PUSH_NTT; INttManager public NTT_MANAGER; IWormholeTransceiver public WORMHOLE_TRANSCEIVER; IWormholeRelayer public WORMHOLE_RELAYER; uint16 public WORMHOLE_RECIPIENT_CHAIN; // Wormhole's Core contract recipient Chain ID - // uint256 public GAS_LIMIT = 100_000; //@audit-info Should be checked if really needed uint256 public ADD_CHANNEL_MIN_FEES; - uint256 public FEE_AMOUNT; uint256 public PROTOCOL_POOL_FEE; + uint256 public MIN_POOL_CONTRIBUTION; } diff --git a/contracts/PushComm/PushCommV3.sol b/contracts/PushComm/PushCommV3.sol index aa775140..fbfa3935 100644 --- a/contracts/PushComm/PushCommV3.sol +++ b/contracts/PushComm/PushCommV3.sol @@ -22,9 +22,10 @@ import { BaseHelper } from "../libraries/BaseHelper.sol"; import { CommTypes, CrossChainRequestTypes } from "../libraries/DataTypes.sol"; import { IERC1271 } from "../interfaces/signatures/IERC1271.sol"; -import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { IERC721 } from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; import { PausableUpgradeable, Initializable } from "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol"; @@ -87,13 +88,6 @@ contract PushCommV3 is Initializable, PushCommStorageV2, IPushCommV3, PausableUp emit ChannelAlias(chainName, chainID, msg.sender, _channelAddress); } - function removeChannelAlias(string memory _channelAddress) external { - emit RemoveChannelAlias(chainName, chainID, msg.sender, _channelAddress); - } - - // function completeMigration() external onlyPushChannelAdmin { - // isMigrationComplete = true; - // } function setEPNSCoreAddress(address _coreAddress) external onlyPushChannelAdmin { EPNSCoreAddress = _coreAddress; @@ -104,7 +98,7 @@ contract PushCommV3 is Initializable, PushCommStorageV2, IPushCommV3, PausableUp } function setPushTokenAddress(address _tokenAddress) external onlyPushChannelAdmin { - PUSH_TOKEN_ADDRESS = _tokenAddress; + PUSH_NTT = IERC20(_tokenAddress); } function transferPushChannelAdminControl(address _newAdmin) external onlyPushChannelAdmin { @@ -154,50 +148,6 @@ contract PushCommV3 is Initializable, PushCommStorageV2, IPushCommV3, PausableUp return true; } - /** - * @notice This Function helps in migrating the already existing Subscriber's data to the New protocol - * - * @dev Can only be called by pushChannelAdmin - * Can only be called if the Migration is not yet complete, i.e., "isMigrationComplete" boolean must be - * false - * Subscribes the Users to the respective Channels as per the arguments passed to the function - * - * @param _startIndex starting Index for the LOOP - * @param _endIndex Last Index for the LOOP - * @param _channelList array of addresses of the channels - * @param _usersList array of addresses of the Users or Subscribers of the Channels - * - */ - // function migrateSubscribeData( - // uint256 _startIndex, - // uint256 _endIndex, - // address[] calldata _channelList, - // address[] calldata _usersList - // ) - // external - // onlyPushChannelAdmin - // returns (bool) - // { - // if (isMigrationComplete || _channelList.length != _usersList.length) { - // revert Errors.InvalidArg_ArrayLengthMismatch(); - // } - - // for (uint256 i = _startIndex; i < _endIndex;) { - // if (isUserSubscribed(_channelList[i], _usersList[i])) { - // unchecked { - // i++; - // } - // continue; - // } else { - // _subscribe(_channelList[i], _usersList[i]); - // } - // unchecked { - // i++; - // } - // } - // return true; - // } - /** * @notice Base Subscribe Function that allows users to Subscribe to a Particular Channel * @@ -569,7 +519,21 @@ contract PushCommV3 is Initializable, PushCommStorageV2, IPushCommV3, PausableUp * @param _minChannelCreationFee The minimum fee for creating a channel * @param _feeAmount The amount of the fee */ - function setCoreFeeConfig(uint256 _minChannelCreationFee, uint256 _feeAmount) external onlyPushChannelAdmin { + function setCoreFeeConfig( + uint256 _minChannelCreationFee, + uint256 _feeAmount, + uint256 _minPoolContribution + ) + external + onlyPushChannelAdmin + { + if (_minPoolContribution == 0 || _feeAmount == 0) { + revert Errors.InvalidArg_LessThanExpected(1, _minPoolContribution); + } + if (_minChannelCreationFee < _feeAmount + _minPoolContribution) { + revert Errors.InvalidArg_LessThanExpected(_feeAmount + _minPoolContribution, _minChannelCreationFee); + } + MIN_POOL_CONTRIBUTION = _minPoolContribution; ADD_CHANNEL_MIN_FEES = _minChannelCreationFee; FEE_AMOUNT = _feeAmount; } @@ -734,4 +698,68 @@ contract PushCommV3 is Initializable, PushCommStorageV2, IPushCommV3, PausableUp msg.sender // Refund address is of the sender ); } + ///@notice Wallet PGP attach code starts here + + /* ***************************** + + USER PGP Registry Functions + + ***************************** */ + + function registerUserPGP(bytes calldata _caipData, string calldata _pgp, bool _isNFT) external { + uint256 fee = FEE_AMOUNT; + PROTOCOL_POOL_FEE += fee; + PUSH_NTT.safeTransferFrom(msg.sender, address(this), fee); + + bytes32 caipHash = keccak256(_caipData); + + if (!_isNFT) { + (, uint256 _chainId, address _wallet) = abi.decode(_caipData, (string, uint256, address)); + + if (bytes(walletToPGP[caipHash]).length != 0 || _wallet != msg.sender) { + revert Errors.Comm_InvalidArguments(); + } + emit UserPGPRegistered(_pgp, _wallet, chainName, chainID); + } else { + (,,, address _nft, uint256 _id,) = + abi.decode(_caipData, (string, string, uint256, address, uint256, uint256)); + require(IERC721(_nft).ownerOf(_id) == msg.sender, "NFT not owned"); + + if (bytes(walletToPGP[caipHash]).length != 0) { + string memory _previousPgp = walletToPGP[caipHash]; + emit UserPGPRemoved(_previousPgp, _nft, _id, chainName, chainID); + } + emit UserPGPRegistered(_pgp, _nft, _id, chainName, chainID); + } + walletToPGP[caipHash] = _pgp; + } + + function removeWalletFromUser(bytes calldata _caipData, bool _isNFT) public { + bytes32 caipHash = keccak256(_caipData); + if (bytes(walletToPGP[caipHash]).length == 0) { + revert("Invalid Call"); + } + + uint256 fee = FEE_AMOUNT; + PROTOCOL_POOL_FEE += fee; + PUSH_NTT.safeTransferFrom(msg.sender, address(this), fee); + + string memory pgp = walletToPGP[caipHash]; + + if (!_isNFT) { + (, uint256 _chainId, address _wallet) = abi.decode(_caipData, (string, uint256, address)); + + if (_wallet != msg.sender) { + revert Errors.Comm_InvalidArguments(); + } + emit UserPGPRemoved(pgp, _wallet, chainName, chainID); + } else { + (,,, address _nft, uint256 _id,) = + abi.decode(_caipData, (string, string, uint256, address, uint256, uint256)); + + require(IERC721(_nft).ownerOf(_id) == msg.sender, "NFT not owned"); + emit UserPGPRemoved(pgp, _nft, _id, chainName, chainID); + } + delete walletToPGP[caipHash]; + } } diff --git a/contracts/PushCore/PushCoreV3.sol b/contracts/PushCore/PushCoreV3.sol index a1daea7c..57c02da9 100644 --- a/contracts/PushCore/PushCoreV3.sol +++ b/contracts/PushCore/PushCoreV3.sol @@ -763,11 +763,20 @@ contract PushCoreV3 is } /// @inheritdoc IPushCoreV3 - function handleChatRequestData(address requestSender, address requestReceiver, uint256 amount) external { - if (msg.sender != epnsCommunicator) { - revert Errors.UnauthorizedCaller(msg.sender); + function createIncentivizedChatRequest(address requestReceiver, uint256 amount) external { + if (amount < FEE_AMOUNT) { + revert Errors.InvalidArg_LessThanExpected(FEE_AMOUNT, amount); + } + + if (requestReceiver == address(0)) { + revert Errors.InvalidArgument_WrongAddress(requestReceiver); } - _handleIncentivizedChat(BaseHelper.addressToBytes32(requestSender), requestReceiver, amount); + + // Transfer tokens from the caller to the contract + IERC20(PUSH_TOKEN_ADDRESS).safeTransferFrom(msg.sender, address(this), amount); + + // Process the incentivized chat request + _handleIncentivizedChat(BaseHelper.addressToBytes32(msg.sender), requestReceiver, amount); } /** @@ -785,7 +794,7 @@ contract PushCoreV3 is celebUserFunds[requestReceiver] += requestReceiverAmount; PROTOCOL_POOL_FEES = PROTOCOL_POOL_FEES + poolFeeAmount; - emit IncentivizeChatReqReceived( + emit IncentivizedChatReqReceived( requestSender, BaseHelper.addressToBytes32(requestReceiver), requestReceiverAmount, poolFeeAmount, block.timestamp ); } @@ -908,6 +917,9 @@ contract PushCoreV3 is ) external { + if (amount == 0) { + revert Errors.InvalidArg_LessThanExpected(1, amount); + } // Transfer tokens from the caller to the contract IERC20(PUSH_TOKEN_ADDRESS).safeTransferFrom(msg.sender, address(this), amount); diff --git a/contracts/interfaces/IPushCommV3.sol b/contracts/interfaces/IPushCommV3.sol index 006b19c2..4c34a9b9 100644 --- a/contracts/interfaces/IPushCommV3.sol +++ b/contracts/interfaces/IPushCommV3.sol @@ -30,14 +30,18 @@ interface IPushCommV3 { address indexed _channelOwnerAddress, string _ethereumChannelAddress ); - /// @notice emits whenever a user initiates an incentivized chat - event IncentivizeChatReqInitiated( - address requestSender, address requestReceiver, uint256 amountDeposited, uint256 timestamp - ); event RemoveChannelAlias( string _chainName, uint256 indexed _chainID, address indexed _channelOwnerAddress, string _baseChannelAddress ); + ///@notice emits whenever a Wallet or NFT is linked OR unlinked to a PGP hash + event UserPGPRegistered(string indexed PgpHash, address indexed wallet, string chainName, uint256 chainID); + event UserPGPRegistered( + string indexed PgpHash, address indexed nft, uint256 nftId, string chainName, uint256 chainID + ); + + event UserPGPRemoved(string indexed PgpHash, address indexed wallet, string chainName, uint256 chainID); + event UserPGPRemoved(string indexed PgpHash, address indexed nft, uint256 nftId, string chainName, uint256 chainID); /* ***************************** diff --git a/contracts/interfaces/IPushCoreV3.sol b/contracts/interfaces/IPushCoreV3.sol index 5808cb3b..d275458f 100644 --- a/contracts/interfaces/IPushCoreV3.sol +++ b/contracts/interfaces/IPushCoreV3.sol @@ -36,7 +36,7 @@ interface IPushCoreV3 { /// @notice emits whenever a users claims the rewards from the staking program(not unstake) event RewardsHarvested(address indexed user, uint256 indexed rewardAmount, uint256 fromEpoch, uint256 tillEpoch); /// @notice emits whenever any user receives an incentivized chat request from another user - event IncentivizeChatReqReceived( + event IncentivizedChatReqReceived( bytes32 requestSender, bytes32 requestReceiver, uint256 amountForReqReceiver, @@ -240,11 +240,10 @@ interface IPushCoreV3 { * - Can only be called by Communicator contract * - Records and keeps track of Pool Funds and Pool Fees * - Stores the PUSH tokens for the Celeb User, which can be claimed later only by that specific user. - * @param requestSender Address that initiates the incentivized chat request * @param requestReceiver Address of the target user for whom the request is activated. * @param amount Amount of PUSH tokens deposited for activating the chat request */ - function handleChatRequestData(address requestSender, address requestReceiver, uint256 amount) external; + function createIncentivizedChatRequest(address requestReceiver, uint256 amount) external; /** * @notice Allows the Celeb User(for whom chat requests were triggered) to claim their PUSH token earings. @@ -276,4 +275,6 @@ interface IPushCoreV3 { uint256 amount ) external; + + function addPoolFees(uint256 _rewardAmount) external; } diff --git a/contracts/interfaces/wormhole/IRateLimiter.sol b/contracts/interfaces/wormhole/IRateLimiter.sol new file mode 100644 index 00000000..9d4dd3e6 --- /dev/null +++ b/contracts/interfaces/wormhole/IRateLimiter.sol @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: Apache 2 +pragma solidity ^0.8.20; + +import "../../libraries/wormhole-lib/TransceiverStructs.sol"; +import "../../libraries/wormhole-lib/TrimmedAmount.sol"; + +interface IRateLimiter { + /// @notice Not enough capacity to send the transfer. + /// @dev Selector 0x26fb55dd. + /// @param currentCapacity The current capacity. + /// @param amount The amount of the transfer. + error NotEnoughCapacity(uint256 currentCapacity, uint256 amount); + + /// @notice Outbound transfer is not longer queued. + /// @dev Selector 0xbfd5f462. + /// @param queueSequence The sequence of the queue. + error OutboundQueuedTransferNotFound(uint64 queueSequence); + + /// @notice Cannot complete the outbound transfer, the transfer is still queued. + /// @dev Selector 0xc06cf05f. + /// @param queueSequence The sequence of the queue. + /// @param transferTimestamp The timestamp of when the transfer was queued. + error OutboundQueuedTransferStillQueued(uint64 queueSequence, uint256 transferTimestamp); + + /// @notice The inbound transfer is not longer queued. + /// @dev Selector 0xc06f2bc0. + /// @param digest The digest of the transfer. + error InboundQueuedTransferNotFound(bytes32 digest); + + /// @notice The transfer is still queued. + /// @dev Selector 0xe5b9ce80. + /// @param digest The digest of the transfer. + /// @param transferTimestamp The timestamp of the transfer. + error InboundQueuedTransferStillQueued(bytes32 digest, uint256 transferTimestamp); + + /// @notice The new capacity cannot exceed the limit. + /// @dev Selector 0x0f85ba52. + /// @param newCurrentCapacity The new current capacity. + /// @param newLimit The new limit. + error CapacityCannotExceedLimit(TrimmedAmount newCurrentCapacity, TrimmedAmount newLimit); + + /// @notice If the rate limiting behaviour isn't explicitly defined in the constructor. + /// @dev Selector 0xe543ef05. + error UndefinedRateLimiting(); + + /// @notice Parameters used in determining rate limits and queuing. + /// @dev + /// - limit: current rate limit value. + /// - currentCapacity: the current capacity left. + /// - lastTxTimestamp: the timestamp of when the + /// capacity was previously consumption. + struct RateLimitParams { + TrimmedAmount limit; + TrimmedAmount currentCapacity; + uint64 lastTxTimestamp; + } + + /// @notice Parameters for an outbound queued transfer. + /// @dev + /// - recipient: the recipient of the transfer. + /// - amount: the amount of the transfer, trimmed. + /// - txTimestamp: the timestamp of the transfer. + /// - recipientChain: the chain of the recipient. + /// - sender: the sender of the transfer. + /// - transceiverInstructions: additional instructions to be forwarded to the recipient chain. + struct OutboundQueuedTransfer { + bytes32 recipient; + bytes32 refundAddress; + TrimmedAmount amount; + uint64 txTimestamp; + uint16 recipientChain; + address sender; + bytes transceiverInstructions; + } + + /// @notice Parameters for an inbound queued transfer. + /// @dev + /// - amount: the amount of the transfer, trimmed. + /// - txTimestamp: the timestamp of the transfer. + /// - recipient: the recipient of the transfer. + struct InboundQueuedTransfer { + TrimmedAmount amount; + uint64 txTimestamp; + address recipient; + } + + function getCurrentOutboundCapacity() external view returns (uint256); + + function getOutboundQueuedTransfer(uint64 queueSequence) external view returns (OutboundQueuedTransfer memory); + + function getCurrentInboundCapacity(uint16 chainId) external view returns (uint256); + + function getInboundQueuedTransfer(bytes32 digest) external view returns (InboundQueuedTransfer memory); + + function getInboundLimitParams(uint16 chainId_) external view returns (RateLimitParams memory); + + function getOutboundLimitParams() external pure returns (RateLimitParams memory); +} diff --git a/contracts/interfaces/wormhole/IWormholeTransceiver.sol b/contracts/interfaces/wormhole/IWormholeTransceiver.sol index 33e995ec..220cffec 100644 --- a/contracts/interfaces/wormhole/IWormholeTransceiver.sol +++ b/contracts/interfaces/wormhole/IWormholeTransceiver.sol @@ -17,12 +17,14 @@ interface IWormholeTransceiver is ITransceiver { external pure returns (bytes memory); - + function receiveWormholeMessages( bytes memory payload, bytes[] memory additionalMessages, bytes32 sourceAddress, uint16 sourceChain, bytes32 deliveryHash - ) external payable; + ) + external + payable; } diff --git a/contracts/libraries/DataTypes.sol b/contracts/libraries/DataTypes.sol index a1bf4fbd..7a31d6b7 100644 --- a/contracts/libraries/DataTypes.sol +++ b/contracts/libraries/DataTypes.sol @@ -129,4 +129,4 @@ library GenericTypes { uint256 percentageNumber; uint256 decimalPlaces; } -} \ No newline at end of file +} diff --git a/contracts/libraries/EnumerableSet.sol b/contracts/libraries/EnumerableSet.sol new file mode 100644 index 00000000..d54ed480 --- /dev/null +++ b/contracts/libraries/EnumerableSet.sol @@ -0,0 +1,230 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol) +// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. + +pragma solidity ^0.8.20; + +/** + * @dev Library for managing + * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive + * types. + * + * Sets have the following properties: + * + * - Elements are added, removed, and checked for existence in constant time + * (O(1)). + * - Elements are enumerated in O(n). No guarantees are made on the ordering. + * + * ```solidity + * contract Example { + * // Add the library methods + * using EnumerableSet for EnumerableSet.AddressSet; + * + * // Declare a set state variable + * EnumerableSet.AddressSet private mySet; + * } + * ``` + * + * As of v3.3.0, sets of type `bytes ` (`bytes Set`), `address` (`AddressSet`) + * and `uint256` (`UintSet`) are supported. + * + * [WARNING] + * ==== + * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure + * unusable. + * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. + * + * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an + * array of EnumerableSet. + * ==== + */ +library EnumerableSet { + // To implement this library for multiple types with as little code + // repetition as possible, we write it in terms of a generic Set type with + // bytes memory values. + // The Set implementation uses private functions, and user-facing + // implementations (such as AddressSet) are just wrappers around the + // underlying Set. + // This means that we can only create new EnumerableSets for types that fit + // in bytes . + + struct Set { + // Storage of set values + bytes[] _values; + // Position is the index of the value in the `values` array plus 1. + // Position 0 is used to mean a value is not in the set. + mapping(bytes value => uint256) _positions; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function _add(Set storage set, bytes memory value) private returns (bool) { + if (!_contains(set, value)) { + set._values.push(value); + // The value is stored at length-1, but we add 1 to all indexes + // and use 0 as a sentinel value + set._positions[value] = set._values.length; + return true; + } else { + return false; + } + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function _remove(Set storage set, bytes memory value) private returns (bool) { + // We cache the value's position to prevent multiple reads from the same storage slot + uint256 position = set._positions[value]; + + if (position != 0) { + // Equivalent to contains(set, value) + // To delete an element from the _values array in O(1), we swap the element to delete with the last one in + // the array, and then remove the last element (sometimes called as 'swap and pop'). + // This modifies the order of the array, as noted in {at}. + + uint256 valueIndex = position - 1; + uint256 lastIndex = set._values.length - 1; + + if (valueIndex != lastIndex) { + bytes memory lastValue = set._values[lastIndex]; + + // Move the lastValue to the index where the value to delete is + set._values[valueIndex] = lastValue; + // Update the tracked position of the lastValue (that was just moved) + set._positions[lastValue] = position; + } + + // Delete the slot where the moved value was stored + set._values.pop(); + + // Delete the tracked position for the deleted slot + delete set._positions[value]; + + return true; + } else { + return false; + } + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function _contains(Set storage set, bytes memory value) private view returns (bool) { + return set._positions[value] != 0; + } + + /** + * @dev Returns the number of values on the set. O(1). + */ + function _length(Set storage set) private view returns (uint256) { + return set._values.length; + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function _at(Set storage set, uint256 index) private view returns (bytes memory) { + return set._values[index]; + } + + /** + * @dev Return the entire set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function _values(Set storage set) private view returns (bytes[] memory) { + return set._values; + } + + // bytes Set + + struct bytesSet { + Set _inner; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function add(bytesSet storage set, bytes memory value) internal returns (bool) { + return _add(set._inner, value); + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function remove(bytesSet storage set, bytes memory value) internal returns (bool) { + return _remove(set._inner, value); + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function contains(bytesSet storage set, bytes memory value) internal view returns (bool) { + return _contains(set._inner, value); + } + + /** + * @dev Returns the number of values in the set. O(1). + */ + function length(bytesSet storage set) internal view returns (uint256) { + return _length(set._inner); + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(bytesSet storage set, uint256 index) internal view returns (bytes memory) { + return _at(set._inner, index); + } + + /** + * @dev Return the entire set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function values(bytesSet storage set) internal view returns (bytes[] memory) { + bytes[] memory store = _values(set._inner); + bytes[] memory result; + + /// @solidity memory-safe-assembly + assembly { + result := store + } + + return result; + } +} diff --git a/contracts/libraries/Errors.sol b/contracts/libraries/Errors.sol index 7d10ec44..97883a10 100644 --- a/contracts/libraries/Errors.sol +++ b/contracts/libraries/Errors.sol @@ -51,6 +51,8 @@ library Errors { error Comm_InvalidSignature_FromEOA(); /// @notice Comm Contract Error: Reverts whenever the signature is invalid from EIP-1271 perspective. error Comm_InvalidSignature_FromContract(); + ///@notice Comm contract Error: Reverts whenever user tries to add PGP to a wallet with already existing pgp. + error Comm_InvalidArguments(); /// @notice Comm Contract Error: Reverts whenever the cross-chain function to be invoked is invalid. error Comm_InvalidCrossChain_Function(); diff --git a/contracts/mocks/MockERC721.sol b/contracts/mocks/MockERC721.sol new file mode 100644 index 00000000..6c5eaca7 --- /dev/null +++ b/contracts/mocks/MockERC721.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: SEE LICENSE IN LICENSE +pragma solidity ^0.8.20; + +import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; + +contract MockERC721 is ERC721 { + uint256 _id; + + constructor(address _initial) ERC721("MockERC721", "MCK") { + _safeMint(_initial, _id); + _id++; + } + + function mint() external { + _mint(msg.sender, _id); + _id++; + } +} diff --git a/contracts/mocks/MockNttManager.sol b/contracts/mocks/MockNttManager.sol new file mode 100644 index 00000000..59e19917 --- /dev/null +++ b/contracts/mocks/MockNttManager.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +import { INttManager } from "contracts/interfaces/wormhole/INttManager.sol"; +import { IRateLimiter } from "contracts/interfaces/wormhole/IRateLimiter.sol"; + +abstract contract MockNttManager is INttManager, IRateLimiter { + /// @dev The duration (in seconds) it takes for the limits to fully replenish. + uint64 public rateLimitDuration; +} diff --git a/contracts/mocks/PushCoreMock.sol b/contracts/mocks/PushCoreMock.sol index 9a433bbc..a6d88ece 100644 --- a/contracts/mocks/PushCoreMock.sol +++ b/contracts/mocks/PushCoreMock.sol @@ -11,8 +11,6 @@ pragma solidity ^0.8.20; * The Push Core is more inclined towards the storing and handling the Channel related functionalties. * */ -import { PushCoreStorageV1_5 } from "../PushCore/PushCoreStorageV1_5.sol"; -import { PushCoreStorageV2 } from "../PushCore/PushCoreStorageV2.sol"; import { CoreTypes } from "../libraries/DataTypes.sol"; import { Errors } from "../libraries/Errors.sol"; @@ -22,7 +20,9 @@ import { PausableUpgradeable, Initializable } from "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol"; -contract PushCoreMock is Initializable, PushCoreStorageV1_5, PausableUpgradeable, PushCoreStorageV2 { +import { PushCoreV3 } from "./../PushCore/PushCoreV3.sol"; + +contract PushCoreMock is PushCoreV3 { using SafeERC20 for IERC20; event AddChannel(address indexed channel, CoreTypes.ChannelType indexed channelType, bytes identity); @@ -68,81 +68,7 @@ contract PushCoreMock is Initializable, PushCoreStorageV1_5, PausableUpgradeable success = true; } - function createChannelWithPUSH( - CoreTypes.ChannelType _channelType, - bytes calldata _identity, - uint256 _amount, - uint256 _channelExpiryTime - ) - external - whenNotPaused - { - if (_amount < ADD_CHANNEL_MIN_FEES) { - revert Errors.InvalidArg_LessThanExpected(ADD_CHANNEL_MIN_FEES, _amount); - } - if (channels[msg.sender].channelState != 0) { - revert Errors.Core_InvalidChannel(); - } - if ( - !( - _channelType == CoreTypes.ChannelType.InterestBearingOpen - || _channelType == CoreTypes.ChannelType.InterestBearingMutual - || _channelType == CoreTypes.ChannelType.TimeBound || _channelType == CoreTypes.ChannelType.TokenGated - ) - ) { - revert Errors.Core_InvalidChannelType(); - } - - emit AddChannel(msg.sender, _channelType, _identity); - - IERC20(PUSH_TOKEN_ADDRESS).safeTransferFrom(msg.sender, address(this), _amount); - _createChannel(msg.sender, _channelType, _amount, _channelExpiryTime); - } - - /** - * @notice Base Channel Creation Function that allows users to Create Their own Channels and Stores crucial details - * about the Channel being created - * @dev -Initializes the Channel Struct - * -Subscribes the Channel's Owner to Imperative EPNS Channels as well as their Own Channels - * - Updates the CHANNEL_POOL_FUNDS and PROTOCOL_POOL_FEES in the contract. - * - * @param _channel address of the channel being Created - * @param _channelType The type of the Channel - * @param _amountDeposited The total amount being deposited while Channel Creation - * @param _channelExpiryTime the expiry time for time bound channels - * - */ - function _createChannel( - address _channel, - CoreTypes.ChannelType _channelType, - uint256 _amountDeposited, - uint256 _channelExpiryTime - ) - private - { - uint256 poolFeeAmount = FEE_AMOUNT; - uint256 poolFundAmount = _amountDeposited - poolFeeAmount; - //store funds in pool_funds & pool_fees - CHANNEL_POOL_FUNDS = CHANNEL_POOL_FUNDS + poolFundAmount; - PROTOCOL_POOL_FEES = PROTOCOL_POOL_FEES + poolFeeAmount; - - // Calculate channel weight - uint256 _channelWeight = (poolFundAmount * ADJUST_FOR_FLOAT) / MIN_POOL_CONTRIBUTION; - // Next create the channel and mark user as channellized - channels[_channel].channelState = 1; - channels[_channel].poolContribution = poolFundAmount; - channels[_channel].channelType = _channelType; - channels[_channel].channelStartBlock = block.number; - channels[_channel].channelUpdateBlock = block.number; - channels[_channel].channelWeight = _channelWeight; - // Add to map of addresses and increment channel count - channelsCount = channelsCount + 1; - - if (_channelType == CoreTypes.ChannelType.TimeBound) { - if (_channelExpiryTime <= block.timestamp) { - revert Errors.Core_InvalidExpiryTime(); - } - channels[_channel].expiryTime = _channelExpiryTime; - } + function setEpnsTokenAddress(address _epnsAddress) external { + PUSH_TOKEN_ADDRESS = _epnsAddress; } } diff --git a/contracts/token/PushMigration.sol b/contracts/token/PushMigration.sol index ff664755..9b8c9783 100644 --- a/contracts/token/PushMigration.sol +++ b/contracts/token/PushMigration.sol @@ -17,11 +17,11 @@ contract PushMigrationHelper is OwnableUpgradeable, PausableUpgradeable { /// @notice thrown when a user attempts to unmigrate while unmigration is locked error UnmigrationPaused(); - event TokenMigrated(address indexed _tokenHolder, address indexed _tokenReceiver, uint256 _amountMigrated); - event TokenUnmigrated(address indexed _tokenHolder, uint256 _amountUnmigrated); - event TokenUnmigrationStatusUpdated(bool _status); - event NewPushTokenUpdated(address indexed _newTokenAddress); - + event TokenMigrated(address indexed _tokenHolder, address indexed _tokenReceiver, uint256 _amountMigrated); + event TokenUnmigrated(address indexed _tokenHolder, uint256 _amountUnmigrated); + event TokenUnmigrationStatusUpdated(bool _status); + event NewPushTokenUpdated(address indexed _newTokenAddress); + modifier whenUnMigrationIsAllowed() { if (unMigrationPaused) { revert UnmigrationPaused(); @@ -34,7 +34,7 @@ contract PushMigrationHelper is OwnableUpgradeable, PausableUpgradeable { _disableInitializers(); } - function initialize(address _owner, address _oldToken) external initializer { + function initialize(address _oldToken) external initializer { oldPushToken = IERC20(_oldToken); __Ownable_init(); diff --git a/env/.env.sample b/env/.env.sample new file mode 100644 index 00000000..e2ef3a64 --- /dev/null +++ b/env/.env.sample @@ -0,0 +1,41 @@ +# RPC URL for the network you are connecting to (e.g., Infura, Alchemy, etc.) +export RPC="YOUR_RPC_URL" ### Your RPC URL + + +# -------------------------- PUSH CORE -------------------------- + +## REQUIRED for new PUSH CORE Deployment +export PUSH_TOKEN_ADDRESS="0x0000000000000000000000000000000000000000" ### Push Token Address +export WETH_ADDRESS="0x0000000000000000000000000000000000000000" ### WETH Address +export UNISWAP_V2_ROUTER="0x0000000000000000000000000000000000000000" ### Uniswap V2 Router Address +export LENDING_POOL_AAVE="0x0000000000000000000000000000000000000000" ### Lending Pool Aave Address +export DAI_ADDRESS="0x0000000000000000000000000000000000000000" ### DAI Address +export ADAI_ADDRESS="0x0000000000000000000000000000000000000000" ### aDAI Address +export REFERRAL_CODE=0 ### Referral Code + +## REQUIRED for upgrading PUSH CORE deployment +export PUSH_CORE_PROXY="0x0000000000000000000000000000000000000000" ### Push Core Proxy + + +# -------------------------- PUSH COMM -------------------------- + +## REQUIRED for new PUSH COMM Deployment +export CHAIN_NAME="" ### Chain name + +## REQUIRED for upgrading PUSH COMM deployment +export PUSH_COMM_PROXY="0x0000000000000000000000000000000000000000" ### Push Comm Proxy + + +# -------------------------- PUSH NTT -------------------------- + +## REQUIRED for upgrading PUSH NTT Deployment +export PUSH_NTT_PROXY="0x0000000000000000000000000000000000000000" ### Push NTT Proxy Address + + +# -------------------------- PUSH MIGRATION -------------------------- + +## REQUIRED for new PUSH MIGRATION Deployment +export OLD_PUSH_TOKEN_ADDRESS="0x0000000000000000000000000000000000000000" ### Old Push Token Address + +## REQUIRED for upgrading PUSH MIGRATION Deployment +export PUSH_MIGRATION_PROXY="0x0000000000000000000000000000000000000000" ### Push Migration Proxy diff --git a/env/testnet/sepolia.env b/env/testnet/sepolia.env new file mode 100644 index 00000000..47e51b83 --- /dev/null +++ b/env/testnet/sepolia.env @@ -0,0 +1,41 @@ +# RPC URL for the network you are connecting to (e.g., Infura, Alchemy, etc.) +export RPC="https://ethereum-sepolia-rpc.publicnode.com" + + +# -------------------------- PUSH CORE -------------------------- + +## REQUIRED for new PUSH CORE Deployment +export PUSH_TOKEN_ADDRESS="0x0000000000000000000000000000000000000000" ### Push Token Address +export WETH_ADDRESS="0x0000000000000000000000000000000000000000" ### WETH Address +export UNISWAP_V2_ROUTER="0x0000000000000000000000000000000000000000" ### Uniswap V2 Router Address +export LENDING_POOL_AAVE="0x0000000000000000000000000000000000000000" ### Lending Pool Aave Address +export DAI_ADDRESS="0x0000000000000000000000000000000000000000" ### DAI Address +export ADAI_ADDRESS="0x0000000000000000000000000000000000000000" ### aDAI Address +export REFERRAL_CODE=0 ### Referral Code + +## REQUIRED for upgrading PUSH CORE deployment +export PUSH_CORE_PROXY="0x0000000000000000000000000000000000000000" ### Push Core Proxy + + +# -------------------------- PUSH COMM -------------------------- + +## REQUIRED for new PUSH COMM Deployment +export CHAIN_NAME="" ### Chain name + +## REQUIRED for upgrading PUSH COMM deployment +export PUSH_COMM_PROXY="0x0000000000000000000000000000000000000000" ### Push Comm Proxy + + +# -------------------------- PUSH NTT -------------------------- + +## REQUIRED for upgrading PUSH NTT Deployment +export PUSH_NTT_PROXY="0x0000000000000000000000000000000000000000" ### Push NTT Proxy Address + + +# -------------------------- PUSH MIGRATION -------------------------- + +## REQUIRED for new PUSH MIGRATION Deployment +export OLD_PUSH_TOKEN_ADDRESS="0x0000000000000000000000000000000000000000" ### Old Push Token Address + +## REQUIRED for upgrading PUSH MIGRATION Deployment +export PUSH_MIGRATION_PROXY="0x0000000000000000000000000000000000000000" ### Push Migration Proxy diff --git a/scripts/Deployment/DeployPushComm.s.sol b/scripts/Deployment/DeployPushComm.s.sol new file mode 100644 index 00000000..88cd5c41 --- /dev/null +++ b/scripts/Deployment/DeployPushComm.s.sol @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import { Script, console2 } from "forge-std/Script.sol"; +import { PushCommV3 } from "contracts/PushComm/PushCommV3.sol"; +import { EPNSCommProxy } from "contracts/PushComm/EPNSCommProxy.sol"; +import { EPNSCommAdmin } from "contracts/PushComm/EPNSCommAdmin.sol"; +import { DeployBase } from './helpers/DeployBase.s.sol'; + +contract DeployPushComm is DeployBase { + struct ConfigParams { + address coreProxy; + address pushToken; + string chainName; + } + + PushCommV3 public commImpl; + EPNSCommProxy public commProxy; + EPNSCommAdmin public commProxyAdmin; + + function run() public { + vm.startBroadcast(vm.envUint("PRIVATE_KEY")); + + // Sanity check deployment parameters. + ConfigParams memory configParams = _readEnvVariables(); + + // Deploy PushComm and its Proxy + _deployPushComm(configParams); + + vm.stopBroadcast(); + } + + function _deployPushComm(ConfigParams memory configParams) internal { + address account = vm.addr(vm.envUint("PRIVATE_KEY")); + + console2.log("Deploying PushComm Implementation..."); + commImpl = new PushCommV3(); + console2.log("PushComm Implementation deployed at: ", address(commImpl)); + + console2.log("Deploying PushComm ProxyAdmin..."); + commProxyAdmin = new EPNSCommAdmin(account); + console2.log("PushComm ProxyAdmin deployed at: ", address(commProxyAdmin)); + + console2.log("Deploying PushComm Proxy..."); + commProxy = new EPNSCommProxy( + address(commImpl), + address(commProxyAdmin), + account, + configParams.chainName + ); + console2.log("PushComm Proxy deployed at: ", address(commProxy)); + + console2.log("All contracts deployed:"); + console2.log("PushComm Implementation: ", address(commImpl)); + console2.log("PushComm ProxyAdmin: ", address(commProxyAdmin)); + console2.log("PushComm Proxy: ", address(commProxy)); + } + + function _readEnvVariables() internal view returns (ConfigParams memory configParams) { + console2.log("Reading environment variables..."); + configParams.chainName = vm.envString('CHAIN_NAME'); + + // Validate the addresses + require(configParams.chainName != "", "Empty CHAIN_NAME"); + + console2.log("CHAIN_NAME: ", configParams.chainName); + } +} diff --git a/scripts/Deployment/DeployPushCommEth.s.sol b/scripts/Deployment/DeployPushCommEth.s.sol new file mode 100644 index 00000000..7a604892 --- /dev/null +++ b/scripts/Deployment/DeployPushCommEth.s.sol @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import { Script, console2 } from "forge-std/Script.sol"; +import { PushCommETHV3 } from "contracts/PushComm/PushCommETHV3.sol"; +import { EPNSCommProxy } from "contracts/PushComm/EPNSCommProxy.sol"; +import { EPNSCommAdmin } from "contracts/PushComm/EPNSCommAdmin.sol"; +import { DeployBase } from './helpers/DeployBase.s.sol'; + +contract DeployPushCommEth is DeployBase { + struct ConfigParams { + address coreProxy; + address pushToken; + string chainName; + } + + PushCommETHV3 public commImpl; + EPNSCommProxy public commProxy; + EPNSCommAdmin public commProxyAdmin; + + function run() public { + vm.startBroadcast(vm.envUint("PRIVATE_KEY")); + + // Sanity check deployment parameters. + ConfigParams memory configParams = _readEnvVariables(); + + // Deploy PushComm and its Proxy + _deployPushComm(configParams); + + vm.stopBroadcast(); + } + + function _deployPushComm(ConfigParams memory configParams) internal { + address account = vm.addr(vm.envUint("PRIVATE_KEY")); + + console2.log("Deploying PushComm Implementation..."); + commImpl = new PushCommETHV3(); + console2.log("PushComm Implementation deployed at: ", address(commImpl)); + + console2.log("Deploying PushComm ProxyAdmin..."); + commProxyAdmin = new EPNSCommAdmin(account); + console2.log("PushComm ProxyAdmin deployed at: ", address(commProxyAdmin)); + + console2.log("Deploying PushComm Proxy..."); + commProxy = new EPNSCommProxy( + address(commImpl), + address(commProxyAdmin), + account, + configParams.chainName + ); + console2.log("PushComm Proxy deployed at: ", address(commProxy)); + + console2.log("All contracts deployed:"); + console2.log("PushComm Implementation: ", address(commImpl)); + console2.log("PushComm ProxyAdmin: ", address(commProxyAdmin)); + console2.log("PushComm Proxy: ", address(commProxy)); + } + + function _readEnvVariables() internal view returns (ConfigParams memory configParams) { + console2.log("Reading environment variables..."); + configParams.chainName = vm.envString('CHAIN_NAME'); + + // Validate the addresses + require(configParams.chainName != "", "Empty CHAIN_NAME"); + + console2.log("CHAIN_NAME: ", configParams.chainName); + } +} diff --git a/scripts/Deployment/DeployPushCore.s.sol b/scripts/Deployment/DeployPushCore.s.sol new file mode 100644 index 00000000..95a8c415 --- /dev/null +++ b/scripts/Deployment/DeployPushCore.s.sol @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import { Script, console2 } from "forge-std/Script.sol"; +import { PushCoreV3 } from "contracts/PushCore/PushCoreV3.sol"; +import { PushCoreMock } from "contracts/mocks/PushCoreMock.sol"; +import { EPNSCoreProxy, ITransparentUpgradeableProxy } from "contracts/PushCore/EPNSCoreProxy.sol"; +import { EPNSCoreAdmin } from "contracts/PushCore/EPNSCoreAdmin.sol"; +import { TransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; +import { ProxyAdmin } from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; +import { DeployBase } from './helpers/DeployBase.s.sol'; + +contract DeployPushNtt is DeployBase { + struct ConfigParams { + address pushToken; + address weth; + address uniswapV2Router; + address lendingPoolAave; + address dai; + address adai; + uint256 referralCode; + } + + PushCoreV3 public pushCoreImpl; + PushCoreMock public pushCoreMock; + EPNSCoreProxy public pushCoreProxy; + EPNSCoreAdmin public pushCoreProxyAdmin; + + function run() public { + vm.startBroadcast(vm.envUint("PRIVATE_KEY")); + + // Sanity check deployment parameters. + ConfigParams memory configParams = _readEnvVariables(); + + // Deploy PushCore and its Proxy + _deployPushCore(configParams); + + vm.stopBroadcast(); + } + + function _deployPushCore(ConfigParams memory configParams) internal { + address account = vm.addr(vm.envUint("PRIVATE_KEY")); + + console2.log("Deploying PushCore Implementation..."); + pushCoreMock = new PushCoreMock(); + pushCoreImpl = new PushCoreV3(); + console2.log("PushCore Implementation deployed at: ", address(pushCoreImpl)); + + console2.log("Deploying PushCore ProxyAdmin..."); + pushCoreProxyAdmin = new EPNSCoreAdmin(account); + console2.log("PushCore ProxyAdmin deployed at: ", address(pushCoreProxyAdmin)); + + console2.log("Deploying PushCore Proxy..."); + pushCoreProxy = new EPNSCoreProxy( + address(pushCoreMock), + address(pushCoreProxyAdmin), + account, + configParams.pushToken, + configParams.weth, + configParams.uniswapV2Router, + configParams.lendingPoolAave, + configParams.dai, + configParams.adai, + configParams.referralCode + ); + console2.log("PushCore Proxy deployed at: ", address(pushCoreProxy)); + + pushCoreProxyAdmin.upgrade( + ITransparentUpgradeableProxy(address(pushCoreProxy)), + address(pushCoreImpl) + ); + + console2.log("All contracts deployed:"); + console2.log("PushCore Implementation: ", address(pushCoreImpl)); + console2.log("PushCore ProxyAdmin: ", address(pushCoreProxyAdmin)); + console2.log("PushCore Proxy: ", address(pushCoreProxy)); + } + + function _readEnvVariables() internal view returns (ConfigParams memory configParams) { + console2.log("Reading environment variables..."); + configParams.pushToken = vm.envAddress('PUSH_TOKEN_ADDRESS'); + configParams.weth = vm.envAddress('WETH_ADDRESS'); + configParams.uniswapV2Router = vm.envAddress('UNISWAP_V2_ROUTER'); + configParams.lendingPoolAave = vm.envAddress('LENDING_POOL_AAVE'); + configParams.dai = vm.envAddress('DAI_ADDRESS'); + configParams.adai = vm.envAddress('ADAI_ADDRESS'); + configParams.referralCode = vm.envUint('REFERRAL_CODE'); + + // Validate the addresses + require(configParams.pushToken != address(0), "Invalid PUSH_TOKEN_ADDRESS"); + require(configParams.weth != address(0), "Invalid WETH_ADDRESS"); + require(configParams.uniswapV2Router != address(0), "Invalid UNISWAP_V2_ROUTER"); + require(configParams.lendingPoolAave != address(0), "Invalid LENDING_POOL_AAVE"); + require(configParams.dai != address(0), "Invalid DAI_ADDRESS"); + require(configParams.adai != address(0), "Invalid ADAI_ADDRESS"); + + console2.log("PUSH_TOKEN_ADDRESS: ", configParams.pushToken); + console2.log("WETH_ADDRESS: ", configParams.weth); + console2.log("UNISWAP_V2_ROUTER: ", configParams.uniswapV2Router); + console2.log("LENDING_POOL_AAVE: ", configParams.lendingPoolAave); + console2.log("DAI_ADDRESS: ", configParams.dai); + console2.log("ADAI_ADDRESS: ", configParams.adai); + console2.log("REFERRAL_CODE: ", configParams.referralCode); + } +} diff --git a/scripts/Deployment/DeployPushMigration.s.sol b/scripts/Deployment/DeployPushMigration.s.sol new file mode 100644 index 00000000..8da90193 --- /dev/null +++ b/scripts/Deployment/DeployPushMigration.s.sol @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import { Script, console2 } from "forge-std/Script.sol"; +import { PushMigrationHelper } from "contracts/token/PushMigration.sol"; +import { TransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; +import { ProxyAdmin } from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; +import { DeployBase } from './helpers/DeployBase.s.sol'; + +contract DeployPushMigration is DeployBase { + struct ConfigParams { + address oldPushToken; + } + + PushMigrationHelper public pushMigrationImpl; + ProxyAdmin public pushMigrationProxyAdmin; + TransparentUpgradeableProxy public pushMigrationProxy; + + function run() public { + vm.startBroadcast(vm.envUint("PRIVATE_KEY")); + + // Sanity check deployment parameters. + ConfigParams memory configParams = _readEnvVariables(); + + // Deploy PushMigration + _deployPushMigration(configParams); + + vm.stopBroadcast(); + } + + function _deployPushMigration(ConfigParams memory configParams) internal { + console2.log("Deploying PushMigrationHelper Implementation..."); + pushMigrationImpl = new PushMigrationHelper(); + console2.log("PushMigrationHelper Implementation deployed at: ", address(pushMigrationImpl)); + + console2.log("Deploying ProxyAdmin..."); + pushMigrationProxyAdmin = new ProxyAdmin(); + console2.log("ProxyAdmin deployed at: ", address(pushMigrationProxyAdmin)); + + console2.log("Deploying PushMigrationHelper Proxy..."); + pushMigrationProxy = new TransparentUpgradeableProxy( + address(pushMigrationImpl), + address(pushMigrationProxyAdmin), + abi.encodeWithSignature("initialize(address)", address(configParams.oldPushToken)) + ); + console2.log("PushMigrationHelper Proxy deployed at: ", address(pushMigrationProxy)); + + console2.log("All contracts deployed:"); + console2.log("PushMigrationHelperImpl: ", address(pushMigrationImpl)); + console2.log("ProxyAdmin: ", address(pushMigrationProxyAdmin)); + console2.log("PushMigrationHelperProxy: ", address(pushMigrationProxy)); + } + + function _readEnvVariables() internal view returns (ConfigParams memory configParams) { + console2.log("Reading environment variables..."); + configParams.oldPushToken = vm.envAddress('OLD_PUSH_TOKEN_ADDRESS'); + if (configParams.oldPushToken == address(0)) { + console2.log("Invalid OLD_PUSH_TOKEN_ADDRESS: ", configParams.oldPushToken); + revert InvalidAddress(); + } + console2.log("OLD_PUSH_TOKEN_ADDRESS: ", configParams.oldPushToken); + } +} diff --git a/scripts/Deployment/DeployPushNtt.s.sol b/scripts/Deployment/DeployPushNtt.s.sol new file mode 100644 index 00000000..2609f7e4 --- /dev/null +++ b/scripts/Deployment/DeployPushNtt.s.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import { Script, console2 } from "forge-std/Script.sol"; +import { Push } from "contracts/token/Push.sol"; +import { TransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; +import { ProxyAdmin } from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; +import { DeployBase } from './helpers/DeployBase.s.sol'; + +contract DeployPushNtt is DeployBase { + Push public pushNttImpl; + ProxyAdmin public pushNttProxyAdmin; + TransparentUpgradeableProxy public pushNttProxy; + + function run() public { + vm.startBroadcast(vm.envUint("PRIVATE_KEY")); + + // Deploy PushNtt and its Proxy + _deployPushNtt(); + + vm.stopBroadcast(); + } + + function _deployPushNtt() internal { + console2.log("Deploying PushNtt Implementation..."); + pushNttImpl = new Push(); + console2.log("PushNtt Implementation deployed at: ", address(pushNttImpl)); + + console2.log("Deploying ProxyAdmin..."); + pushNttProxyAdmin = new ProxyAdmin(); + console2.log("ProxyAdmin deployed at: ", address(pushNttProxyAdmin)); + + console2.log("Deploying PushNtt Proxy..."); + pushNttProxy = new TransparentUpgradeableProxy( + address(pushNttImpl), + address(pushNttProxyAdmin), + abi.encodeWithSignature("initialize()") + ); + console2.log("PushNtt Proxy deployed at: ", address(pushNttProxy)); + + console2.log("All contracts deployed:"); + console2.log("PushNtt Implementation: ", address(pushNttImpl)); + console2.log("ProxyAdmin: ", address(pushNttProxyAdmin)); + console2.log("PushNtt Proxy: ", address(pushNttProxy)); + } +} diff --git a/scripts/Deployment/DeployPushToken.s.sol b/scripts/Deployment/DeployPushToken.s.sol new file mode 100644 index 00000000..8db5ce63 --- /dev/null +++ b/scripts/Deployment/DeployPushToken.s.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import { Script, console2 } from "forge-std/Script.sol"; +import { EPNS } from "contracts/token/EPNS.sol"; +import { DeployBase } from './helpers/DeployBase.s.sol'; + +contract DeployPushToken is DeployBase { + EPNS public pushToken; + + function run() public { + vm.startBroadcast(vm.envUint("PRIVATE_KEY")); + + // Deploy PushToken + _deployPushToken(); + + vm.stopBroadcast(); + } + + function _deployPushToken() internal { + address account = vm.addr(vm.envUint("PRIVATE_KEY")); + + console2.log("Deploying Push Token..."); + pushToken = new EPNS(account); + console2.log("Push Token deployed at: ", address(pushToken)); + } +} diff --git a/scripts/Deployment/UpgradePushComm.s.sol b/scripts/Deployment/UpgradePushComm.s.sol new file mode 100644 index 00000000..b856eec1 --- /dev/null +++ b/scripts/Deployment/UpgradePushComm.s.sol @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import { console2, Script } from "forge-std/Script.sol"; +import { PushCommV3 } from "contracts/PushComm/PushCommV3.sol"; +import { ITransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; +import { EPNSCommAdmin } from "contracts/PushComm/EPNSCommAdmin.sol"; +import { DeployBase } from "./helpers/DeployBase.s.sol"; + +contract UpgradePushComm is DeployBase { + struct ConfigParams { + address pushCommProxyAddr; + } + + PushCommV3 public pushCommImpl; + EPNSCommAdmin public pushCommProxyAdmin; + ITransparentUpgradeableProxy public pushCommProxy; + + function run() public { + vm.startBroadcast(vm.envUint("PRIVATE_KEY")); + + // Sanity check deployment parameters. + ConfigParams memory configParams = _readEnvVariables(); + + // Deploy new PushCommV3 implementation + _deployPushCommImplementation(); + + // Upgrade the proxy to use the new implementation + _upgradePushCommProxy(configParams); + + vm.stopBroadcast(); + } + + function _deployPushCommImplementation() internal { + console2.log("Deploying new PushCommV3 Implementation..."); + pushCommImpl = new PushCommV3(); + console2.log("PushCommV3 Implementation deployed at: ", address(pushCommImpl)); + } + + function _upgradePushCommProxy(ConfigParams memory configParams) internal { + console2.log("Upgrading PushComm Proxy..."); + + _upgradeContract(configParams.pushCommProxyAddr, address(pushCommImpl)); + + console2.log("PushComm Proxy upgraded to new implementation at: ", address(pushCommImpl)); + } + + function _readEnvVariables() internal view returns (ConfigParams memory configParams) { + console2.log("Reading environment variables..."); + configParams.pushCommProxyAddr = vm.envAddress("PUSH_COMM_PROXY"); + if (configParams.pushCommProxyAddr == address(0)) { + console2.log("Invalid PUSH_COMM_PROXY: ", configParams.pushCommProxyAddr); + revert InvalidAddress(); + } + console2.log("PUSH_COMM_PROXY: ", configParams.pushCommProxyAddr); + } +} diff --git a/scripts/Deployment/UpgradePushCommEth.s.sol b/scripts/Deployment/UpgradePushCommEth.s.sol new file mode 100644 index 00000000..1fd03ba0 --- /dev/null +++ b/scripts/Deployment/UpgradePushCommEth.s.sol @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import { console2, Script } from "forge-std/Script.sol"; +import { PushCommETHV3 } from "contracts/PushComm/PushCommETHV3.sol"; +import { ITransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; +import { EPNSCommAdmin } from "contracts/PushComm/EPNSCommAdmin.sol"; +import { DeployBase } from "./helpers/DeployBase.s.sol"; + +contract UpgradePushCommEth is DeployBase { + struct ConfigParams { + address pushCommProxyAddr; + } + + PushCommETHV3 public pushCommEthImpl; + EPNSCommAdmin public pushCommProxyAdmin; + ITransparentUpgradeableProxy public pushCommProxy; + + function run() public { + vm.startBroadcast(vm.envUint("PRIVATE_KEY")); + + // Sanity check deployment parameters. + ConfigParams memory configParams = _readEnvVariables(); + + // Deploy new PushCommETHV3 implementation + _deployPushCommEthImplementation(); + + // Upgrade the proxy to use the new implementation + _upgradePushCommProxy(configParams); + + vm.stopBroadcast(); + } + + function _deployPushCommEthImplementation() internal { + console2.log("Deploying new PushCommETHV3 Implementation..."); + pushCommEthImpl = new PushCommETHV3(); + console2.log("PushCommETHV3 Implementation deployed at: ", address(pushCommEthImpl)); + } + + function _upgradePushCommProxy(ConfigParams memory configParams) internal { + console2.log("Upgrading PushComm Proxy..."); + + _upgradeContract(configParams.pushCommProxyAddr, address(pushCommEthImpl)); + + console2.log("PushComm Proxy upgraded to new implementation at: ", address(pushCommImpl)); + } + + function _readEnvVariables() internal view returns (ConfigParams memory configParams) { + console2.log("Reading environment variables..."); + configParams.pushCommProxyAddr = vm.envAddress("PUSH_COMM_PROXY"); + if (configParams.pushCommProxyAddr == address(0)) { + console2.log("Invalid PUSH_COMM_PROXY: ", configParams.pushCommProxyAddr); + revert InvalidAddress(); + } + console2.log("PUSH_COMM_PROXY: ", configParams.pushCommProxyAddr); + } +} diff --git a/scripts/Deployment/UpgradePushCore.s.sol b/scripts/Deployment/UpgradePushCore.s.sol new file mode 100644 index 00000000..8bb3e5aa --- /dev/null +++ b/scripts/Deployment/UpgradePushCore.s.sol @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import { console2, Script } from "forge-std/Script.sol"; +import { PushCoreV3 } from "contracts/PushCore/PushCoreV3.sol"; +import { ITransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; +import { EPNSCoreAdmin } from "contracts/PushCore/EPNSCoreAdmin.sol"; +import { DeployBase } from "./helpers/DeployBase.s.sol"; + +contract UpgradePushCore is DeployBase { + struct ConfigParams { + address pushCoreProxyAddr; + } + + PushCoreV3 public pushCoreImpl; + EPNSCoreAdmin public pushCoreProxyAdmin; + ITransparentUpgradeableProxy public pushCoreProxy; + + function run() public { + vm.startBroadcast(vm.envUint("PRIVATE_KEY")); + + // Sanity check deployment parameters. + ConfigParams memory configParams = _readEnvVariables(); + + // Deploy new PushCoreV3 implementation + _deployPushCoreImplementation(); + + // Upgrade the proxy to use the new implementation + _upgradePushCoreProxy(configParams); + + vm.stopBroadcast(); + } + + function _deployPushCoreImplementation() internal { + console2.log("Deploying new PushCoreV3 Implementation..."); + pushCoreImpl = new PushCoreV3(); + console2.log("PushCoreV3 Implementation deployed at: ", address(pushCoreImpl)); + } + + function _upgradePushCoreProxy(ConfigParams memory configParams) internal { + console2.log("Upgrading PushCore Proxy..."); + + _upgradeContract(configParams.pushCoreProxyAddr, address(pushCoreImpl)); + + console2.log("PushCore Proxy upgraded to new implementation at: ", address(pushCoreImpl)); + } + + function _readEnvVariables() internal view returns (ConfigParams memory configParams) { + console2.log("Reading environment variables..."); + configParams.pushCoreProxyAddr = vm.envAddress("PUSH_CORE_PROXY"); + if (configParams.pushCoreProxyAddr == address(0)) { + console2.log("Invalid PUSH_CORE_PROXY: ", configParams.pushCoreProxyAddr); + revert InvalidAddress(); + } + console2.log("PUSH_CORE_PROXY: ", configParams.pushCoreProxyAddr); + } +} diff --git a/scripts/Deployment/UpgradePushMigration.s.sol b/scripts/Deployment/UpgradePushMigration.s.sol new file mode 100644 index 00000000..842669e8 --- /dev/null +++ b/scripts/Deployment/UpgradePushMigration.s.sol @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import { console2, Script } from "forge-std/Script.sol"; +import { PushMigrationHelper } from "contracts/token/PushMigration.sol"; +import { ITransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; +import { ProxyAdmin } from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; +import { DeployBase } from "./helpers/DeployBase.s.sol"; + +contract UpgradePushMigration is DeployBase { + struct ConfigParams { + address pushMigrationProxyAddr; + } + + PushMigrationHelper public pushMigrationImpl; + ProxyAdmin public pushMigrationProxyAdmin; + ITransparentUpgradeableProxy public pushMigrationProxy; + + function run() public { + vm.startBroadcast(vm.envUint("PRIVATE_KEY")); + + // Sanity check deployment parameters. + ConfigParams memory configParams = _readEnvVariables(); + + // Deploy new PushMigrationHelper implementation + _deployPushMigrationImplementation(); + + // Upgrade the proxy to use the new implementation + _upgradePushMigrationProxy(configParams); + + vm.stopBroadcast(); + } + + function _deployPushMigrationImplementation() internal { + console2.log("Deploying new PushMigrationHelper Implementation..."); + pushMigrationImpl = new PushMigrationHelper(); + console2.log("PushMigrationHelper Implementation deployed at: ", address(pushMigrationImpl)); + } + + function _upgradePushMigrationProxy(ConfigParams memory configParams) internal { + console2.log("Upgrading PushMigrationHelper Proxy..."); + + _upgradeContract(configParams.pushMigrationProxyAddr, address(pushMigrationImpl)); + + console2.log("PushMigrationHelper Proxy upgraded to new implementation at: ", address(pushMigrationImpl)); + } + + function _readEnvVariables() internal view returns (ConfigParams memory configParams) { + console2.log("Reading environment variables..."); + configParams.pushMigrationProxyAddr = vm.envAddress("PUSH_MIGRATION_PROXY"); + if (configParams.pushMigrationProxyAddr == address(0)) { + console2.log("Invalid PUSH_MIGRATION_PROXY: ", configParams.pushMigrationProxyAddr); + revert InvalidAddress(); + } + console2.log("PUSH_MIGRATION_PROXY: ", configParams.pushMigrationProxyAddr); + } +} diff --git a/scripts/Deployment/UpgradePushNtt.s.sol b/scripts/Deployment/UpgradePushNtt.s.sol new file mode 100644 index 00000000..fb173ac5 --- /dev/null +++ b/scripts/Deployment/UpgradePushNtt.s.sol @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import { console2, Script } from "forge-std/Script.sol"; +import { Push } from "contracts/token/Push.sol"; +import { ITransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; +import { ProxyAdmin } from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; +import { DeployBase } from "./helpers/DeployBase.s.sol"; + +contract UpgradePushNtt is DeployBase { + struct ConfigParams { + address pushNttProxyAddr; + } + + Push public pushNttImpl; + ProxyAdmin public pushNttProxyAdmin; + ITransparentUpgradeableProxy public pushNttProxy; + + function run() public { + vm.startBroadcast(vm.envUint("PRIVATE_KEY")); + + // Sanity check deployment parameters. + ConfigParams memory configParams = _readEnvVariables(); + + // Deploy new PushNtt implementation + _deployPushNttImplementation(); + + // Upgrade the proxy to use the new implementation + _upgradePushNttProxy(configParams); + + vm.stopBroadcast(); + } + + function _deployPushNttImplementation() internal { + console2.log("Deploying new PushNtt Implementation..."); + pushNttImpl = new Push(); + console2.log("PushNtt Implementation deployed at: ", address(pushNttImpl)); + } + + function _upgradePushNttProxy(ConfigParams memory configParams) internal { + console2.log("Upgrading PushNtt Proxy..."); + + _upgradeContract(configParams.pushNttProxyAddr, address(pushNttImpl)); + + console2.log("PushNtt Proxy upgraded to new implementation at: ", address(pushNttImpl)); + } + + function _readEnvVariables() internal view returns (ConfigParams memory configParams) { + console2.log("Reading environment variables..."); + configParams.pushNttProxyAddr = vm.envAddress("PUSH_NTT_PROXY"); + if (configParams.pushNttProxyAddr == address(0)) { + console2.log("Invalid PUSH_NTT_PROXY: ", configParams.pushNttProxyAddr); + revert InvalidAddress(); + } + console2.log("PUSH_NTT_PROXY: ", configParams.pushNttProxyAddr); + } +} diff --git a/scripts/Deployment/helpers/DeployBase.s.sol b/scripts/Deployment/helpers/DeployBase.s.sol new file mode 100644 index 00000000..d32ecd0a --- /dev/null +++ b/scripts/Deployment/helpers/DeployBase.s.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import { Script } from "forge-std/Script.sol"; +import { ITransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; +import { ProxyAdmin } from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; + +contract DeployBase is Script { + // Custom errors + error InvalidAddress(); // Error for invalid address + + function _upgradeContract(address _proxyAddr, address _newImplementation) internal { + // Load the ProxyAdmin address from the proxy contract's storage + address proxyAdminAddr = address( + uint160( + uint256( + vm.load( + _proxyAddr, + 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103 + ) + ) + ) + ); + ProxyAdmin proxyAdmin = ProxyAdmin(payable(proxyAdminAddr)); + ITransparentUpgradeableProxy proxy = ITransparentUpgradeableProxy(payable(_proxyAddr)); + + // Upgrade the proxy to the new implementation + proxyAdmin.upgrade(proxy, address(_newImplementation)); + } +} diff --git a/sh/deploy.sh b/sh/deploy.sh new file mode 100644 index 00000000..3967345a --- /dev/null +++ b/sh/deploy.sh @@ -0,0 +1,69 @@ +#!/bin/bash + +while getopts ":n:c:u:k:s:v:" opt; do + case $opt in + n) network="$OPTARG" + ;; + c) chain="$OPTARG" + ;; + k) private_key="$OPTARG" + ;; + s) deployment_script="$OPTARG" + ;; + v) verification_key="$OPTARG" + ;; + \?) echo "Invalid option -$OPTARG" >&2 + exit 1 + ;; + esac + + case $OPTARG in + -*) echo "Option $opt needs a valid argument" >&2 + exit 1 + ;; + esac +done + +if [ -z ${network+x} ]; then + echo "network (-n) is unset" >&2 + exit 1 +fi + +if [ -z ${chain+x} ]; then + echo "chain (-c) is unset" >&2 + exit 1 +fi + +if [ -z ${deployment_script+x} ]; then + echo "deployment script file (-s) is unset" >&2 + exit 1 +fi + +if [ -z ${private_key+x} ]; then + echo "private key (-k) is unset" >&2 + exit 1 +fi + +set -euo pipefail + +ROOT=$(dirname $0) +ENV=$ROOT/../env +FORGE_SCRIPTS=$ROOT/../scripts + +. $ENV/$network/$chain.env + +# Construct the base command +forge_command="forge script $FORGE_SCRIPTS/Deployment/$deployment_script \ + --rpc-url $RPC \ + --broadcast \ + --private-key $private_key \ + --slow \ + --skip test" + +# Conditionally add the --verify and --etherscan-api-key options +if [ -n "${verification_key+x}" ]; then + forge_command+=" --verify --etherscan-api-key $verification_key" +fi + +# Execute the command +eval $forge_command \ No newline at end of file diff --git a/test/BaseTest.t.sol b/test/BaseTest.t.sol index 6b9f15f2..20031f08 100644 --- a/test/BaseTest.t.sol +++ b/test/BaseTest.t.sol @@ -6,9 +6,8 @@ import "forge-std/Test.sol"; import "contracts/token/EPNS.sol"; import "contracts/token/Push.sol"; import "contracts/interfaces/uniswap/IUniswapV2Router.sol"; -import { PushCoreV3 } from "contracts/PushCore/PushCoreV3.sol"; import { PushCoreMock } from "contracts/mocks/PushCoreMock.sol"; -import { EPNSCoreProxy, ITransparentUpgradeableProxy } from "contracts/PushCore/EPNSCoreProxy.sol"; +import { EPNSCoreProxy} from "contracts/PushCore/EPNSCoreProxy.sol"; import { EPNSCoreAdmin } from "contracts/PushCore/EPNSCoreAdmin.sol"; import { PushCommETHV3 } from "contracts/PushComm/PushCommEthV3.sol"; import { PushCommV3 } from "contracts/PushComm/PushCommV3.sol"; @@ -21,14 +20,13 @@ import { ProxyAdmin } from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin import { Actors, ChannelCreators } from "./utils/Actors.sol"; import { Events } from "./utils/Events.sol"; import { Constants } from "./utils/Constants.sol"; -import { BaseHelper } from "../../../../contracts/libraries/BaseHelper.sol"; +import { BaseHelper } from "contracts/libraries/BaseHelper.sol"; abstract contract BaseTest is Test, Constants, Events { Push public pushNtt; Push public pushNttToken; EPNS public pushToken; - PushCoreMock public coreMock; - PushCoreV3 public coreProxy; + PushCoreMock public coreProxy; PushCommV3 public comm; PushCommV3 public commProxy; PushCommETHV3 public commEth; @@ -60,7 +58,7 @@ abstract contract BaseTest is Test, Constants, Events { uint256 ADD_CHANNEL_MIN_FEES = 50 ether; uint256 ADD_CHANNEL_MAX_POOL_CONTRIBUTION = 250 ether; uint256 FEE_AMOUNT = 10 ether; - uint256 MIN_POOL_CONTRIBUTION = 50 ether; + uint256 MIN_POOL_CONTRIBUTION = 1 ether; uint256 ADJUST_FOR_FLOAT = 10 ** 7; mapping(address => uint256) privateKeys; @@ -72,8 +70,7 @@ abstract contract BaseTest is Test, Constants, Events { tokenDistributor = makeAddr("tokenDistributor"); pushToken = new EPNS(tokenDistributor); - coreMock = new PushCoreMock(); - coreProxy = new PushCoreV3(); + coreProxy = new PushCoreMock(); comm = new PushCommV3(); commEth = new PushCommETHV3(); pushMigrationHelper = new PushMigrationHelper(); @@ -106,18 +103,16 @@ abstract contract BaseTest is Test, Constants, Events { changePrank(actor.admin); nttProxyAdmin = new ProxyAdmin(); pushNttProxy = new TransparentUpgradeableProxy( - address(pushNtt), - address(nttProxyAdmin), - abi.encodeWithSignature("initialize()") + address(pushNtt), address(nttProxyAdmin), abi.encodeWithSignature("initialize()") ); pushNttToken = Push(address(pushNttProxy)); nttMigrationProxyAdmin = new ProxyAdmin(); - + // Initialize pushMigration proxy admin and proxy contract pushMigrationProxy = new TransparentUpgradeableProxy( address(pushMigrationHelper), address(nttMigrationProxyAdmin), - abi.encodeWithSignature("initialize(address,address)", actor.admin, address(pushToken)) + abi.encodeWithSignature("initialize(address)", address(pushToken)) ); pushMigrationHelperProxy = PushMigrationHelper(address(pushMigrationProxy)); // set governance as minter of ntt token @@ -125,9 +120,10 @@ abstract contract BaseTest is Test, Constants, Events { pushNttToken.setMinter(actor.governance); epnsCoreProxyAdmin = new EPNSCoreAdmin(actor.admin); + epnsCoreProxyAdmin = new EPNSCoreAdmin(actor.admin); // Initialize coreMock proxy admin and coreProxy contract epnsCoreProxy = new EPNSCoreProxy( - address(coreMock), + address(coreProxy), address(epnsCoreProxyAdmin), actor.admin, address(pushToken), @@ -139,12 +135,7 @@ abstract contract BaseTest is Test, Constants, Events { 0 ); - epnsCoreProxyAdmin.upgrade( - ITransparentUpgradeableProxy(address(epnsCoreProxy)), - address(coreProxy) - ); - - coreProxy = PushCoreV3(address(epnsCoreProxy)); + coreProxy = PushCoreMock(address(epnsCoreProxy)); changePrank(tokenDistributor); pushToken.transfer(address(coreProxy), 1 ether); @@ -155,22 +146,23 @@ abstract contract BaseTest is Test, Constants, Events { commProxy = PushCommV3(address(epnsCommProxy)); // Set-up Core Address in Comm & Vice-Versa - vm.startPrank(actor.admin); + changePrank(actor.admin); commProxy.setEPNSCoreAddress(address(coreProxy)); commProxy.setPushTokenAddress(address(pushToken)); - coreProxy.setEpnsCommunicatorAddress(address(commProxy)); vm.stopPrank(); // Initialize comm proxy admin and commProxy contract epnsCommEthProxyAdmin = new EPNSCommAdmin(actor.admin); epnsCommEthProxy = - new EPNSCommProxy(address(comm), address(epnsCommEthProxyAdmin), actor.admin, "FOUNDRY_TEST_NETWORK"); + new EPNSCommProxy(address(commEth), address(epnsCommEthProxyAdmin), actor.admin, "FOUNDRY_TEST_NETWORK"); commEthProxy = PushCommETHV3(address(epnsCommEthProxy)); // Set-up Core Address in Comm Eth - vm.startPrank(actor.admin); + changePrank(actor.admin); commEthProxy.setEPNSCoreAddress(address(coreProxy)); commEthProxy.setPushTokenAddress(address(pushToken)); + coreProxy.setEpnsCommunicatorAddress(address(commEthProxy)); + commProxy.setCoreFeeConfig(ADD_CHANNEL_MIN_FEES, FEE_AMOUNT, MIN_POOL_CONTRIBUTION); vm.stopPrank(); // Approve tokens of actors now to core contract proxy address @@ -194,14 +186,14 @@ abstract contract BaseTest is Test, Constants, Events { } function approveTokens(address from, address to, uint256 amount) internal { - vm.startPrank(from); + changePrank(from); pushToken.approve(to, amount); pushToken.setHolderDelegation(to, true); vm.stopPrank(); } function approveNttTokens(address from, address to, uint256 amount) internal { - vm.startPrank(from); + changePrank(from); pushNttToken.approve(to, amount); pushNttToken.setHolderDelegation(to, true); vm.stopPrank(); diff --git a/test/CCR/ArbitraryRequest/ArbitraryRequest.t.sol b/test/CCR/ArbitraryRequest/ArbitraryRequest.t.sol index 33a63191..d4ccec7e 100644 --- a/test/CCR/ArbitraryRequest/ArbitraryRequest.t.sol +++ b/test/CCR/ArbitraryRequest/ArbitraryRequest.t.sol @@ -2,14 +2,13 @@ pragma solidity ^0.8.0; import { BaseCCRTest } from "../BaseCCR.t.sol"; -import { Errors } from ".././../../../contracts/libraries/Errors.sol"; +import { Errors } from "contracts/libraries/Errors.sol"; +import { Errors } from "contracts/libraries/Errors.sol"; import { console } from "forge-std/console.sol"; -import { CrossChainRequestTypes, GenericTypes } from "../../../../contracts/libraries/DataTypes.sol"; +import { CrossChainRequestTypes, GenericTypes } from "contracts/libraries/DataTypes.sol"; -import "./../../../../contracts/libraries/wormhole-lib/TrimmedAmount.sol"; -import { TransceiverStructs } from "./../../../../contracts/libraries/wormhole-lib/TransceiverStructs.sol"; - -import { BaseHelper } from "./../../../contracts/libraries/BaseHelper.sol"; +import { IRateLimiter } from "contracts/interfaces/wormhole/IRateLimiter.sol"; +import { BaseHelper } from "contracts/libraries/BaseHelper.sol"; contract ArbitraryRequesttsol is BaseCCRTest { uint256 amount = 100e18; @@ -65,6 +64,19 @@ contract ArbitraryRequesttsol is BaseCCRTest { ); } + function test_revertWhen_OutboundQueueDisabled() external whencreateCrossChainRequestIsCalled { + changePrank(SourceChain.NTT_MANAGER); + uint256 transferTooLarge = MAX_WINDOW + 1e18; // one token more than the outbound capacity + pushNttToken.mint(actor.bob_channel_owner, transferTooLarge); + + changePrank(actor.bob_channel_owner); + // test revert on a transfer that is larger than max window size without enabling queueing + vm.expectRevert(abi.encodeWithSelector(IRateLimiter.NotEnoughCapacity.selector, MAX_WINDOW, transferTooLarge)); + commProxy.createCrossChainRequest{ value: 1e18 }( + CrossChainRequestTypes.CrossChainFunction.ArbitraryRequest, _payload, transferTooLarge, GasLimit + ); + } + function test_WhenAllChecksPasses() public whencreateCrossChainRequestIsCalled { // it should successfully create the CCR vm.expectEmit(true, false, false, false); @@ -131,8 +143,6 @@ contract ArbitraryRequesttsol is BaseCCRTest { uint256 arbitraryFees = coreProxy.arbitraryReqFees(actor.charlie_channel_owner); changePrank(DestChain.WORMHOLE_RELAYER_DEST); - (uint256 poolFunds, uint256 poolFees) = getPoolFundsAndFees(amount); - vm.expectEmit(true, true, false, true); emit ArbitraryRequest(BaseHelper.addressToBytes32(actor.bob_channel_owner), BaseHelper.addressToBytes32(actor.charlie_channel_owner), amount, percentage, 1); @@ -147,7 +157,7 @@ contract ArbitraryRequesttsol is BaseCCRTest { assertEq(coreProxy.arbitraryReqFees(actor.charlie_channel_owner), arbitraryFees + amount - feeAmount); } - function test_whenTokensAreTransferred() external { + function test_whenTokensAreTransferred() public { vm.recordLogs(); test_whenReceiveChecksPass(); (address sourceNttManager, bytes32 recipient, uint256 _amount, uint16 recipientChain) = @@ -166,6 +176,17 @@ contract ArbitraryRequesttsol is BaseCCRTest { hash // Hash of the VAA being used ); - assertEq(pushNttToken.balanceOf(address(coreProxy)), amount); + assertEq(pushToken.balanceOf(address(coreProxy)), amount); + } + + function test_when_UserTries_ClaimingArbitraryTokens() external { + // it should transfer the tokens to celeb user + test_whenTokensAreTransferred(); + uint256 balanceBefore = pushToken.balanceOf(address(actor.charlie_channel_owner)); + changePrank(actor.charlie_channel_owner); + coreProxy.claimArbitraryRequestFees(coreProxy.arbitraryReqFees(actor.charlie_channel_owner)); + uint256 feeAmount = BaseHelper.calcPercentage(amount, percentage); + assertEq(pushToken.balanceOf(address(actor.charlie_channel_owner)), balanceBefore + amount - feeAmount); + assertEq(coreProxy.arbitraryReqFees(actor.charlie_channel_owner), 0); } } diff --git a/test/CCR/ArbitraryRequest/ArbitraryRequest.tree b/test/CCR/ArbitraryRequest/ArbitraryRequest.tree index 1f3343a3..20960b63 100644 --- a/test/CCR/ArbitraryRequest/ArbitraryRequest.tree +++ b/test/CCR/ArbitraryRequest/ArbitraryRequest.tree @@ -8,6 +8,8 @@ ArbitraryRequest.t.sol │ │ └── it should revert │ ├── when ether passed is less │ │ └── it should revert +│ ├── when amount transferred is more than max outbound rate limit +│ │ └── it should revert │ └── when all checks passes │ └── it should successfully create the CCR └── when receive function is called in core @@ -17,5 +19,7 @@ ArbitraryRequest.t.sol │ └── it should Revert ├── when deliveryHash is used already │ └── it should Revert - └── when all checks pass - └── it should emit event and update storage \ No newline at end of file + ├── when all checks pass + │ └── it should emit event and update storage + └── when recipient user tries to claim the Arbitrary tokens + └── it should transfer the tokens to the user \ No newline at end of file diff --git a/test/CCR/BaseCCR.t.sol b/test/CCR/BaseCCR.t.sol index 185081ed..42eeee18 100644 --- a/test/CCR/BaseCCR.t.sol +++ b/test/CCR/BaseCCR.t.sol @@ -1,14 +1,11 @@ pragma solidity ^0.8.20; pragma experimental ABIEncoderV2; -import { console } from "forge-std/console.sol"; import "contracts/token/Push.sol"; -import {CrossChainRequestTypes } from "../../../../contracts/libraries/DataTypes.sol"; -import {Helper} from "./CCRutils/Helper.sol"; +import { Helper } from "./CCRutils/Helper.sol"; contract BaseCCRTest is Helper { - ///@notice start with forking the arbitrum testnet /// Wrap the token contract with the one deployed on arbitrum testnet /// getting the push tokens from whale address diff --git a/test/CCR/CCRutils/CCRConfig.sol b/test/CCR/CCRutils/CCRConfig.sol index 58a445cd..eaa93c65 100644 --- a/test/CCR/CCRutils/CCRConfig.sol +++ b/test/CCR/CCRutils/CCRConfig.sol @@ -72,28 +72,33 @@ contract CCRConfig { // "https://sepolia.base.org" // ); + /// NEWEST DEPLOYED CONTRACT /// - /// NEWEST DEPLOYED CONTRACT /// + // SourceConfig ArbSepolia = SourceConfig( + // IWormhole(0x6b9C8671cdDC8dEab9c719bB87cBd3e782bA6a35), + // IWormholeTransceiver(0x4F532db1ce4f33170b21F6a97A8973e9499BbD75), + // 0x5e1989B8681C91A90F33A82b22cf51210a7C31C0, + // 0x4F532db1ce4f33170b21F6a97A8973e9499BbD75, + // 0x7B1bD7a6b4E61c2a123AC6BC2cbfC614437D0470, + // 0x70c3C79d33A9b08F1bc1e7DB113D1588Dad7d8Bc, + // 0x778D3206374f8AC265728E18E3fE2Ae6b93E4ce4, + // 10_003, + // "https://sepolia-rollup.arbitrum.io/rpc" + // ); -// SourceConfig ArbSepolia = SourceConfig( -// IWormhole(0x6b9C8671cdDC8dEab9c719bB87cBd3e782bA6a35), -// IWormholeTransceiver(0x4F532db1ce4f33170b21F6a97A8973e9499BbD75), -// 0x5e1989B8681C91A90F33A82b22cf51210a7C31C0, -// 0x4F532db1ce4f33170b21F6a97A8973e9499BbD75, -// 0x7B1bD7a6b4E61c2a123AC6BC2cbfC614437D0470, -// 0x70c3C79d33A9b08F1bc1e7DB113D1588Dad7d8Bc, -// 0x778D3206374f8AC265728E18E3fE2Ae6b93E4ce4, -// 10_003, -// "https://sepolia-rollup.arbitrum.io/rpc" -// ); + // DestConfig EthSepolia = DestConfig( + // IWormhole(0x4a8bc80Ed5a4067f1CCf107057b8270E0cC11A78), + // IWormholeTransceiver(0x3cc5553e0ABfF03743c9c2cc785D184e72D45852), + // 0x76c636cb502Aa7eed6784Fde38b955bC15CC6bc1, + // 0x7B1bD7a6b4E61c2a123AC6BC2cbfC614437D0470, + // 0xe1327FE9b457Ad1b4601FdD2afcAdAef198d6BA6, + // 10_002, + // "https://eth-sepolia.public.blastapi.io" + // ); -// DestConfig EthSepolia = DestConfig( -// IWormhole(0x4a8bc80Ed5a4067f1CCf107057b8270E0cC11A78), -// IWormholeTransceiver(0x3cc5553e0ABfF03743c9c2cc785D184e72D45852), -// 0x76c636cb502Aa7eed6784Fde38b955bC15CC6bc1, -// 0x7B1bD7a6b4E61c2a123AC6BC2cbfC614437D0470, -// 0xe1327FE9b457Ad1b4601FdD2afcAdAef198d6BA6, -// 10_002, -// "https://eth-sepolia.public.blastapi.io" -// ); + // chain agnostic constants + // ToDo: to be changed + uint256 public constant MAX_WINDOW = 100_000 ether; // considering both inbound and outbound + // limits are same + uint256 public constant RATE_LIMIT_DURATION = 900; } diff --git a/test/CCR/CCRutils/Helper.sol b/test/CCR/CCRutils/Helper.sol index 27ad3ddd..fb2f92cf 100644 --- a/test/CCR/CCRutils/Helper.sol +++ b/test/CCR/CCRutils/Helper.sol @@ -9,8 +9,9 @@ import "contracts/libraries/wormhole-lib/TrimmedAmount.sol"; import { TransceiverStructs } from "contracts/libraries/wormhole-lib/TransceiverStructs.sol"; import "contracts/interfaces/wormhole/IWormholeRelayer.sol"; import { CCRConfig } from "./CCRConfig.sol"; -import { IWormholeTransceiver } from "./../../../contracts/interfaces/wormhole/IWormholeTransceiver.sol"; +import { IWormholeTransceiver } from "contracts/interfaces/wormhole/IWormholeTransceiver.sol"; import { Vm } from "forge-std/Vm.sol"; +import { EPNS } from "contracts/token/EPNS.sol"; contract Helper is BasePushCommTest, CCRConfig { // Set Source and dest chains @@ -28,7 +29,7 @@ contract Helper is BasePushCommTest, CCRConfig { bytes32 sourceAddress; uint16 sourceChain = SourceChain.SourceChainId; GenericTypes.Percentage percentage; - uint256 GasLimit = 10_000_000; + uint256 GasLimit = 10_000_000; // ToDo: to be finalised bytes4 constant TEST_TRANSCEIVER_PAYLOAD_PREFIX = 0x9945ff10; @@ -60,15 +61,15 @@ contract Helper is BasePushCommTest, CCRConfig { IWormholeRelayer(SourceChain.WORMHOLE_RELAYER_SOURCE), DestChain.DestChainId ); - commProxy.setCoreFeeConfig(ADD_CHANNEL_MIN_FEES, FEE_AMOUNT); } function setUpDestChain() internal { switchChains(DestChain.rpc); BasePushCommTest.setUp(); - pushNttToken = Push(DestChain.PUSH_NTT_DEST); + pushToken = EPNS(DestChain.PUSH_NTT_DEST); changePrank(actor.admin); coreProxy.setWormholeRelayer(DestChain.WORMHOLE_RELAYER_DEST); + coreProxy.setEpnsTokenAddress(address(pushToken)); coreProxy.setRegisteredSender(SourceChain.SourceChainId, toWormholeFormat(address(commProxy))); } @@ -210,9 +211,17 @@ contract Helper is BasePushCommTest, CCRConfig { (recipient,, _amount,, recipientChain,) = abi.decode(data, (bytes32, bytes32, uint256, uint256, uint16, uint64)); } - function getRequestPayload(uint256 _amount, bytes32 recipient, uint16 recipientChain, address sourceNttManager) internal view returns(bytes memory transceiverMessage, bytes32 hash) { - - TrimmedAmount _amt = _trimTransferAmount(_amount); + function getRequestPayload( + uint256 _amount, + bytes32 recipient, + uint16 recipientChain, + address sourceNttManager + ) + internal + view + returns (bytes memory transceiverMessage, bytes32 hash) + { + TrimmedAmount _amt = _trimTransferAmount(_amount); bytes memory tokenTransferMessage = TransceiverStructs.encodeNativeTokenTransfer( TransceiverStructs.NativeTokenTransfer({ amount: _amt, diff --git a/test/CCR/NTTtransfer/NttTransferTest.t.sol b/test/CCR/NTT/NttTransferTest.t.sol similarity index 80% rename from test/CCR/NTTtransfer/NttTransferTest.t.sol rename to test/CCR/NTT/NttTransferTest.t.sol index eca4b045..81566b26 100644 --- a/test/CCR/NTTtransfer/NttTransferTest.t.sol +++ b/test/CCR/NTT/NttTransferTest.t.sol @@ -28,19 +28,19 @@ contract CreateChannelCCR is BaseCCRTest { changePrank(SourceChain.PushHolder); pushNttToken.approve(address(SourceChain.NTT_MANAGER), 100e18); - INttManager(SourceChain.NTT_MANAGER).transfer{ value: 12_260_834_040_000 }( + uint256 costOfTransfer = commProxy.quoteTokenBridgingCost(); + + INttManager(SourceChain.NTT_MANAGER).transfer{ value: costOfTransfer }( 100e18, DestChain.DestChainId, toWormholeFormat(actor.bob_channel_owner) ); - ( - address sourceNttManager, - bytes32 recipient, - uint256 _amount, - uint16 recipientChain )= getMessagefromLog(vm.getRecordedLogs()); + (address sourceNttManager, bytes32 recipient, uint256 _amount, uint16 recipientChain) = + getMessagefromLog(vm.getRecordedLogs()); setUpDestChain(); bytes[] memory a; - (bytes memory transceiverMessage, bytes32 hash) = getRequestPayload(_amount, recipient, recipientChain, sourceNttManager); + (bytes memory transceiverMessage, bytes32 hash) = + getRequestPayload(_amount, recipient, recipientChain, sourceNttManager); changePrank(DestChain.WORMHOLE_RELAYER_DEST); DestChain.wormholeTransceiverChain2.receiveWormholeMessages( @@ -52,6 +52,5 @@ contract CreateChannelCCR is BaseCCRTest { ); console.log(pushNttToken.balanceOf(actor.bob_channel_owner)); - } } diff --git a/test/CCR/NTT/RateLimit.t.sol b/test/CCR/NTT/RateLimit.t.sol new file mode 100644 index 00000000..41172d78 --- /dev/null +++ b/test/CCR/NTT/RateLimit.t.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +import { BaseCCRTest } from "../BaseCCR.t.sol"; + +import { console } from "forge-std/console.sol"; + +import { WormholeSimulator } from "wormhole-solidity-sdk/testing/helpers/WormholeSimulator.sol"; +import { TransceiverStructs } from "contracts/libraries/wormhole-lib/TransceiverStructs.sol"; +import { TrimmedAmountLib, TrimmedAmount, eq } from "contracts/libraries/wormhole-lib/TrimmedAmount.sol"; +import { INttManager } from "contracts/interfaces/wormhole/INttManager.sol"; +import { MockNttManager } from "contracts/mocks/MockNttManager.sol"; + +import { Vm } from "forge-std/Vm.sol"; + +contract RateLimitNtt is BaseCCRTest { + using TrimmedAmountLib for uint256; + using TrimmedAmountLib for TrimmedAmount; + + TrimmedAmount public maxWindowTrimmedAmount; + + function setUp() public override { + BaseCCRTest.setUp(); + sourceAddress = toWormholeFormat(address(commProxy)); + + maxWindowTrimmedAmount = MAX_WINDOW.trim(18, 18); + } + + function testRateLimitConfigs() public { + checkRateLimitConfigs(SourceChain.NTT_MANAGER, DestChain.DestChainId); + + setUpDestChain(); + checkRateLimitConfigs(DestChain.NTT_MANAGER, SourceChain.SourceChainId); + } + + function checkRateLimitConfigs(address nttManager, uint16 peerId) public { + assertEq(MockNttManager(nttManager).rateLimitDuration(), RATE_LIMIT_DURATION); + + assertTrue(eq(MockNttManager(nttManager).getOutboundLimitParams().limit, maxWindowTrimmedAmount)); + assertTrue(eq(MockNttManager(nttManager).getInboundLimitParams(peerId).limit, maxWindowTrimmedAmount)); + } +} diff --git a/test/CCR/SpecificRequest/CreateChannelCCR/CreateChannelCCR.t.sol b/test/CCR/SpecificRequest/CreateChannelCCR/CreateChannelCCR.t.sol index ab0e2f27..c253a5e3 100644 --- a/test/CCR/SpecificRequest/CreateChannelCCR/CreateChannelCCR.t.sol +++ b/test/CCR/SpecificRequest/CreateChannelCCR/CreateChannelCCR.t.sol @@ -2,12 +2,13 @@ pragma solidity ^0.8.0; import { BaseCCRTest } from "../../BaseCCR.t.sol"; -import { CoreTypes, CrossChainRequestTypes } from "../../../../contracts/libraries/DataTypes.sol"; -import { Errors } from ".././../../../contracts/libraries/Errors.sol"; +import { CoreTypes, CrossChainRequestTypes } from "contracts/libraries/DataTypes.sol"; +import { Errors } from "contracts/libraries/Errors.sol"; import { console } from "forge-std/console.sol"; -import "./../../../../contracts/libraries/wormhole-lib/TrimmedAmount.sol"; -import { TransceiverStructs } from "./../../../../contracts/libraries/wormhole-lib/TransceiverStructs.sol"; +import "contracts/libraries/wormhole-lib/TrimmedAmount.sol"; +import { TransceiverStructs } from "contracts/libraries/wormhole-lib/TransceiverStructs.sol"; import { BaseHelper } from "contracts/libraries/BaseHelper.sol"; +import { IRateLimiter } from "contracts/interfaces/wormhole/IRateLimiter.sol"; contract CreateChannelCCR is BaseCCRTest { uint256 amount = ADD_CHANNEL_MIN_FEES; @@ -65,6 +66,19 @@ contract CreateChannelCCR is BaseCCRTest { ); } + function test_revertWhen_OutboundQueueDisabled() external whenCreateChannelIsCalled { + changePrank(SourceChain.NTT_MANAGER); + uint256 transferTooLarge = MAX_WINDOW + 1e18; // one token more than the outbound capacity + pushNttToken.mint(actor.bob_channel_owner, transferTooLarge); + + changePrank(actor.bob_channel_owner); + // test revert on a transfer that is larger than max window size without enabling queueing + vm.expectRevert(abi.encodeWithSelector(IRateLimiter.NotEnoughCapacity.selector, MAX_WINDOW, transferTooLarge)); + commProxy.createCrossChainRequest{ value: 1e18 }( + CrossChainRequestTypes.CrossChainFunction.ArbitraryRequest, _payload, transferTooLarge, GasLimit + ); + } + function test_WhenAllChecksPasses() public whenCreateChannelIsCalled { // it should successfully create the CCR @@ -157,7 +171,7 @@ contract CreateChannelCCR is BaseCCRTest { (address sourceNttManager, bytes32 recipient, uint256 _amount, uint16 recipientChain) = getMessagefromLog(vm.getRecordedLogs()); - console.log(pushNttToken.balanceOf(address(coreProxy))); + console.log(pushToken.balanceOf(address(coreProxy))); bytes[] memory a; (bytes memory transceiverMessage, bytes32 hash) = @@ -172,6 +186,6 @@ contract CreateChannelCCR is BaseCCRTest { hash // Hash of the VAA being used ); - assertEq(pushNttToken.balanceOf(address(coreProxy)), amount); + assertEq(pushToken.balanceOf(address(coreProxy)), amount); } } diff --git a/test/CCR/SpecificRequest/CreateChannelCCR/CreateChannelCCR.tree b/test/CCR/SpecificRequest/CreateChannelCCR/CreateChannelCCR.tree index 0035abda..6354e057 100644 --- a/test/CCR/SpecificRequest/CreateChannelCCR/CreateChannelCCR.tree +++ b/test/CCR/SpecificRequest/CreateChannelCCR/CreateChannelCCR.tree @@ -6,8 +6,10 @@ CreateChannelCCR.t.sol │ │ └── it should revert │ ├── when ether passed is less │ │ └── it should revert -│ ├── when all checks passes -│ │ └── it should successfully create the CCR +│ ├── when amount transferred is more than max outbound rate limit +│ │ └── it should revert +│ └── when all checks passes +│ └── it should successfully create the CCR └── when receive function is called in core ├── when sender is not registered │ └── it should Revert @@ -15,5 +17,7 @@ CreateChannelCCR.t.sol │ └── it should Revert ├── when deliveryHash is used already │ └── it should Revert - └── when all checks pass - └── it should emit event and create Channel \ No newline at end of file + ├── when all checks pass + │ └── it should emit event and create Channel + └── when Tokens are transferred by NTT + └── it should recieve the tokens in core \ No newline at end of file diff --git a/test/CCR/SpecificRequest/CreateChannelSettingsCCR/CreateChannelSettingsCCR.t.sol b/test/CCR/SpecificRequest/CreateChannelSettingsCCR/CreateChannelSettingsCCR.t.sol index a635e8df..a2495c15 100644 --- a/test/CCR/SpecificRequest/CreateChannelSettingsCCR/CreateChannelSettingsCCR.t.sol +++ b/test/CCR/SpecificRequest/CreateChannelSettingsCCR/CreateChannelSettingsCCR.t.sol @@ -153,6 +153,6 @@ contract CreateChannelSettingsCCR is BaseCCRTest { hash // Hash of the VAA being used ); - assertEq(pushNttToken.balanceOf(address(coreProxy)), amount); + assertEq(pushToken.balanceOf(address(coreProxy)), amount); } } diff --git a/test/CCR/SpecificRequest/CreateChatCCR/CreateChatCCR.t.sol b/test/CCR/SpecificRequest/CreateChatCCR/CreateChatCCR.t.sol index 50aceb94..582e8f58 100644 --- a/test/CCR/SpecificRequest/CreateChatCCR/CreateChatCCR.t.sol +++ b/test/CCR/SpecificRequest/CreateChatCCR/CreateChatCCR.t.sol @@ -2,13 +2,14 @@ pragma solidity ^0.8.0; import { BaseCCRTest } from "../../BaseCCR.t.sol"; -import { Errors } from ".././../../../contracts/libraries/Errors.sol"; +import { Errors } from "contracts/libraries/Errors.sol"; import { console } from "forge-std/console.sol"; -import { CrossChainRequestTypes } from "../../../../contracts/libraries/DataTypes.sol"; -import "./../../../../contracts/libraries/wormhole-lib/TrimmedAmount.sol"; -import { TransceiverStructs } from "./../../../../contracts/libraries/wormhole-lib/TransceiverStructs.sol"; +import { CrossChainRequestTypes } from "contracts/libraries/DataTypes.sol"; +import "contracts/libraries/wormhole-lib/TrimmedAmount.sol"; +import { TransceiverStructs } from "contracts/libraries/wormhole-lib/TransceiverStructs.sol"; import { BaseHelper } from "contracts/libraries/BaseHelper.sol"; +import { IRateLimiter } from "contracts/interfaces/wormhole/IRateLimiter.sol"; contract CreateChatCCR is BaseCCRTest { uint256 amount = 100e18; @@ -64,6 +65,19 @@ contract CreateChatCCR is BaseCCRTest { ); } + function test_revertWhen_OutboundQueueDisabled() external whenCreateChatIsCalled { + changePrank(SourceChain.NTT_MANAGER); + uint256 transferTooLarge = MAX_WINDOW + 1e18; // one token more than the outbound capacity + pushNttToken.mint(actor.bob_channel_owner, transferTooLarge); + + changePrank(actor.bob_channel_owner); + // test revert on a transfer that is larger than max window size without enabling queueing + vm.expectRevert(abi.encodeWithSelector(IRateLimiter.NotEnoughCapacity.selector, MAX_WINDOW, transferTooLarge)); + commProxy.createCrossChainRequest{ value: 1e18 }( + CrossChainRequestTypes.CrossChainFunction.IncentivizedChat, _payload, transferTooLarge, GasLimit + ); + } + function test_WhenAllChecksPasses() public whenCreateChatIsCalled { // it should successfully create the CCR vm.expectEmit(true, false, false, false); @@ -114,7 +128,7 @@ contract CreateChatCCR is BaseCCRTest { uint256 PROTOCOL_POOL_FEES = coreProxy.PROTOCOL_POOL_FEES(); vm.expectEmit(false, false, false, true); - emit IncentivizeChatReqReceived( + emit IncentivizedChatReqReceived( BaseHelper.addressToBytes32(actor.bob_channel_owner), BaseHelper.addressToBytes32(actor.charlie_channel_owner), amount - poolFeeAmount, poolFeeAmount, block.timestamp ); @@ -124,13 +138,13 @@ contract CreateChatCCR is BaseCCRTest { assertEq(coreProxy.PROTOCOL_POOL_FEES(), PROTOCOL_POOL_FEES + poolFeeAmount); } - function test_whenTokensAreTransferred() external { + function test_whenTokensAreTransferred() public { vm.recordLogs(); test_whenReceiveChecksPass(); (address sourceNttManager, bytes32 recipient, uint256 _amount, uint16 recipientChain) = getMessagefromLog(vm.getRecordedLogs()); - console.log(pushNttToken.balanceOf(address(coreProxy))); + console.log(pushToken.balanceOf(address(coreProxy))); bytes[] memory a; (bytes memory transceiverMessage, bytes32 hash) = @@ -145,6 +159,15 @@ contract CreateChatCCR is BaseCCRTest { hash // Hash of the VAA being used ); - assertEq(pushNttToken.balanceOf(address(coreProxy)), amount); + assertEq(pushToken.balanceOf(address(coreProxy)), amount); + } + + function test_when_celebUserTries_ClaimingTokens() external { + // it should transfer the tokens to celeb user + test_whenTokensAreTransferred(); + uint256 balanceBefore = pushToken.balanceOf(address(actor.charlie_channel_owner)); + changePrank(actor.charlie_channel_owner); + coreProxy.claimChatIncentives(coreProxy.celebUserFunds(actor.charlie_channel_owner)); + assertEq(pushToken.balanceOf(address(actor.charlie_channel_owner)), balanceBefore + amount - FEE_AMOUNT); } } diff --git a/test/CCR/SpecificRequest/CreateChatCCR/CreateChatCCR.tree b/test/CCR/SpecificRequest/CreateChatCCR/CreateChatCCR.tree index 82a1c128..670e1ca3 100644 --- a/test/CCR/SpecificRequest/CreateChatCCR/CreateChatCCR.tree +++ b/test/CCR/SpecificRequest/CreateChatCCR/CreateChatCCR.tree @@ -6,8 +6,10 @@ CreateChatCCR.t.sol │ │ └── it should revert │ ├── when ether passed is less │ │ └── it should revert -│ ├── when all checks passes -│ │ └── it should successfully create the CCR +│ ├── when amount transferred is more than max outbound rate limit +│ │ └── it should revert +│ └── when all checks passes +│ └── it should successfully create the CCR └── when receive function is called in core ├── when sender is not registered │ └── it should Revert @@ -15,5 +17,9 @@ CreateChatCCR.t.sol │ └── it should Revert ├── when deliveryHash is used already │ └── it should Revert - └── when all checks pass - └── it should emit event and update storage \ No newline at end of file + ├── when all checks pass + │ └── it should emit event and update storage + ├── when Tokens are transferred by NTT + │ └── it should recieve the tokens in core + └── when celeb user tries to claim the tokens + └── it should transfer the tokens to celeb user \ No newline at end of file diff --git a/test/CCR/SpecificRequest/UpdateChannelMetaCCR/UpdateChannelMetaCCR.t.sol b/test/CCR/SpecificRequest/UpdateChannelMetaCCR/UpdateChannelMetaCCR.t.sol index a0da8445..e60777ae 100644 --- a/test/CCR/SpecificRequest/UpdateChannelMetaCCR/UpdateChannelMetaCCR.t.sol +++ b/test/CCR/SpecificRequest/UpdateChannelMetaCCR/UpdateChannelMetaCCR.t.sol @@ -143,6 +143,6 @@ contract UpdateChannelCCR is BaseCCRTest { hash // Hash of the VAA being used ); - assertEq(pushNttToken.balanceOf(address(coreProxy)), amount); + assertEq(pushToken.balanceOf(address(coreProxy)), amount); } } diff --git a/test/CCR/SpecificRequest/UpdateChannelStateCCR/DeactivateDeleteChannelCCR/DeactivateDeleteChannelCCR.t.sol b/test/CCR/SpecificRequest/UpdateChannelStateCCR/DeactivateDeleteChannelCCR/DeactivateDeleteChannelCCR.t.sol index 99bc6c32..c6432c31 100644 --- a/test/CCR/SpecificRequest/UpdateChannelStateCCR/DeactivateDeleteChannelCCR/DeactivateDeleteChannelCCR.t.sol +++ b/test/CCR/SpecificRequest/UpdateChannelStateCCR/DeactivateDeleteChannelCCR/DeactivateDeleteChannelCCR.t.sol @@ -174,6 +174,6 @@ contract DeactivateChannelCCR is BaseCCRTest { hash // Hash of the VAA being used ); - assertEq(pushNttToken.balanceOf(address(coreProxy)), amount); + assertEq(pushToken.balanceOf(address(coreProxy)), amount); } } diff --git a/test/CCR/SpecificRequest/UpdateChannelStateCCR/ReactivateChannelCCR/ReactivateChannelCCR.t.sol b/test/CCR/SpecificRequest/UpdateChannelStateCCR/ReactivateChannelCCR/ReactivateChannelCCR.t.sol index 76091f4e..5b6b7b39 100644 --- a/test/CCR/SpecificRequest/UpdateChannelStateCCR/ReactivateChannelCCR/ReactivateChannelCCR.t.sol +++ b/test/CCR/SpecificRequest/UpdateChannelStateCCR/ReactivateChannelCCR/ReactivateChannelCCR.t.sol @@ -161,6 +161,6 @@ contract ReactivateChannelCCR is BaseCCRTest { hash // Hash of the VAA being used ); - assertEq(pushNttToken.balanceOf(address(coreProxy)), amount); + assertEq(pushToken.balanceOf(address(coreProxy)), amount); } } diff --git a/test/PushComm/unit_tests/BasePushCommTest.t.sol b/test/PushComm/unit_tests/BasePushCommTest.t.sol index bb4087c7..b9d77e3d 100644 --- a/test/PushComm/unit_tests/BasePushCommTest.t.sol +++ b/test/PushComm/unit_tests/BasePushCommTest.t.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.0; import { BasePushCoreTest } from "../../PushCore/unit_tests/BasePushCoreTest.t.sol"; import { SignatureVerifier } from "contracts/mocks/MockERC1271.sol"; -import { CoreTypes } from "../../../contracts/libraries/DataTypes.sol"; +import { CoreTypes } from "contracts/libraries/DataTypes.sol"; contract BasePushCommTest is BasePushCoreTest { SignatureVerifier verifierContract; diff --git a/test/PushComm/unit_tests/CommAdminActions/CommAdminActions.t.sol b/test/PushComm/unit_tests/CommAdminActions/CommAdminActions.t.sol index 97ddc1ca..34a20d99 100644 --- a/test/PushComm/unit_tests/CommAdminActions/CommAdminActions.t.sol +++ b/test/PushComm/unit_tests/CommAdminActions/CommAdminActions.t.sol @@ -74,7 +74,7 @@ contract CommAdminActions_Test is BasePushCommTest { changePrank(actor.bob_channel_owner); vm.expectRevert(Errors.CallerNotAdmin.selector); commProxy.setPushTokenAddress(address(123)); - assertEq(commProxy.PUSH_TOKEN_ADDRESS(), address(pushToken)); + assertEq(address(commProxy.PUSH_NTT()), address(pushToken)); } function test_WhenAdminSets_ThePushTokenAddress() external { @@ -82,6 +82,6 @@ contract CommAdminActions_Test is BasePushCommTest { changePrank(actor.admin); commProxy.setPushTokenAddress(address(123)); - assertEq(commProxy.PUSH_TOKEN_ADDRESS(), address(123)); + assertEq(address(commProxy.PUSH_NTT()), address(123)); } } diff --git a/test/PushComm/unit_tests/WalletPGPActions/walletPGP.t.sol b/test/PushComm/unit_tests/WalletPGPActions/walletPGP.t.sol new file mode 100644 index 00000000..5eb40de2 --- /dev/null +++ b/test/PushComm/unit_tests/WalletPGPActions/walletPGP.t.sol @@ -0,0 +1,318 @@ +pragma solidity ^0.8.0; + +import { BasePushCommTest } from "../BasePushCommTest.t.sol"; +import { Errors } from "contracts/libraries/Errors.sol"; +import { MockERC721 } from "contracts/mocks/MockERC721.sol"; + +import "forge-std/console.sol"; + +contract walletPGP_Test is BasePushCommTest { + string pgp1 = "PGP1"; + string pgp2 = "PGP2"; + string pgp3 = "PGP3"; + string pgp4 = "PGP4"; + MockERC721 firstERC721; + MockERC721 secondERC721; + MockERC721 thirdERC721; + + function setUp() public override { + BasePushCommTest.setUp(); + + changePrank(actor.admin); + // minting 3 NFTs + firstERC721 = new MockERC721(actor.bob_channel_owner); + secondERC721 = new MockERC721(actor.bob_channel_owner); + thirdERC721 = new MockERC721(actor.bob_channel_owner); + // minting 10 push tokens to the commProxy + approveTokens(actor.admin, address(commProxy), 50_000 ether); + approveTokens(actor.governance, address(commProxy), 50_000 ether); + approveTokens(actor.bob_channel_owner, address(commProxy), 50_000 ether); + approveTokens(actor.alice_channel_owner, address(commProxy), 50_000 ether); + approveTokens(actor.charlie_channel_owner, address(commProxy), 50_000 ether); + approveTokens(actor.dan_push_holder, address(commProxy), 50_000 ether); + approveTokens(actor.tim_push_holder, address(commProxy), 50_000 ether); + } + + modifier whenAUserTriesToAddAnEOAToPGP() { + _; + } + + function test_When_TheEOA_IsNotOwned_ByCaller() external whenAUserTriesToAddAnEOAToPGP { + // it REVERTS + bytes memory _data = getEncodedData(actor.bob_channel_owner); + + vm.expectRevert(abi.encodeWithSelector(Errors.Comm_InvalidArguments.selector)); + changePrank(actor.alice_channel_owner); + commProxy.registerUserPGP(_data, pgp1, false); + } + + function test_When_EOAIsOwned_AndDoesntHavePGP() external whenAUserTriesToAddAnEOAToPGP { + // it should execute and set update the mappings + bytes memory _data = getEncodedData(actor.bob_channel_owner); + + changePrank(actor.bob_channel_owner); + + vm.expectEmit(true, true, false, true); + emit UserPGPRegistered(pgp1, actor.bob_channel_owner, commProxy.chainName(), block.chainid); + + commProxy.registerUserPGP(_data, pgp1, false); + string memory _storedPgp = getWalletToPgp(_data); + assertEq(_storedPgp, pgp1); + + assertEq(pushToken.balanceOf(address(commProxy)), 10e18); + } + + function test_When_TheEOAIsOwned_ButAlreadyHasAPGP() external whenAUserTriesToAddAnEOAToPGP { + // it REVERTS + bytes memory _data = getEncodedData(actor.bob_channel_owner); + + changePrank(actor.bob_channel_owner); + vm.expectEmit(true, true, false, true); + emit UserPGPRegistered(pgp1, actor.bob_channel_owner, commProxy.chainName(), block.chainid); + + commProxy.registerUserPGP(_data, pgp1, false); + string memory _storedPgp = getWalletToPgp(_data); + assertEq(_storedPgp, pgp1); + + vm.expectRevert(abi.encodeWithSelector(Errors.Comm_InvalidArguments.selector)); + changePrank(actor.bob_channel_owner); + commProxy.registerUserPGP(_data, pgp2, false); + + string memory _storedPgp1 = getWalletToPgp(_data); + assertEq(_storedPgp1, pgp1); + + assertEq(pushToken.balanceOf(address(commProxy)), 10e18); + } + + modifier whenAUserTriesToAddAnNFTToPGP() { + _; + } + + function test_WhenCaller_DoesntOwnTheNFT() external whenAUserTriesToAddAnNFTToPGP { + // it REVERTS + + bytes memory _data = getEncodedData(address(firstERC721), 0); + + vm.expectRevert("NFT not owned"); + changePrank(actor.alice_channel_owner); + commProxy.registerUserPGP(_data, pgp1, true); + string memory _storedPgp = getWalletToPgp(_data); + } + + function test_WhenCaller_OwnsAnNFT_ThatsNotRegistered() external whenAUserTriesToAddAnNFTToPGP { + // it should execute and update mappings + + bytes memory _data = getEncodedData(address(firstERC721), 0); + + changePrank(actor.bob_channel_owner); + vm.expectEmit(true, true, false, true); + emit UserPGPRegistered(pgp1, address(firstERC721), 0, commProxy.chainName(), block.chainid); + + commProxy.registerUserPGP(_data, pgp1, true); + string memory _storedPgp = getWalletToPgp(_data); + assertEq(_storedPgp, pgp1); + assertEq(pushToken.balanceOf(address(commProxy)), 10e18); + } + + function test_WhenCaller_OwnsAnNFT_ThatsRegistered() external whenAUserTriesToAddAnNFTToPGP { + // it should delete old PGP and update new + + bytes memory _data = getEncodedData(address(firstERC721), 0); + + changePrank(actor.bob_channel_owner); + + vm.expectEmit(true, true, false, true); + emit UserPGPRegistered(pgp1, address(firstERC721), 0, commProxy.chainName(), block.chainid); + + commProxy.registerUserPGP(_data, pgp1, true); + string memory _storedPgp = getWalletToPgp(_data); + assertEq(_storedPgp, pgp1); + + firstERC721.transferFrom(actor.bob_channel_owner, actor.alice_channel_owner, 0); + + changePrank(actor.alice_channel_owner); + + for (uint256 i = 0; i < 1; i++) { + vm.expectEmit(true, true, false, true); + if (i == 0) { + emit UserPGPRemoved(pgp1, address(firstERC721), 0, commProxy.chainName(), block.chainid); + } else { + emit UserPGPRegistered(pgp2, address(firstERC721), 0, commProxy.chainName(), block.chainid); + } + } + commProxy.registerUserPGP(_data, pgp2, true); + string memory _storedPgpAlice = getWalletToPgp(_data); + assertEq(_storedPgpAlice, pgp2); + + assertEq(pushToken.balanceOf(address(commProxy)), 20e18); + } + + modifier whenAUserTriesToRemoveAnEOAFromPGP() { + _; + } + + function test_WhenTheCaller_IsNotOwner() external whenAUserTriesToRemoveAnEOAFromPGP { + // it REVERTS + bytes memory _data = getEncodedData(actor.bob_channel_owner); + changePrank(actor.bob_channel_owner); + commProxy.registerUserPGP(_data, pgp1, false); + + vm.expectRevert(abi.encodeWithSelector(Errors.Comm_InvalidArguments.selector)); + changePrank(actor.alice_channel_owner); + commProxy.removeWalletFromUser(_data, false); + } + + function test_WhenTheEOA_IsOwnedAnd_AlreadyHasAPGP() external whenAUserTriesToRemoveAnEOAFromPGP { + // it Removes the stored data + bytes memory _data = getEncodedData(actor.bob_channel_owner); + + changePrank(actor.bob_channel_owner); + commProxy.registerUserPGP(_data, pgp1, false); + string memory _storedPgp = getWalletToPgp(_data); + assertEq(_storedPgp, pgp1); + + vm.expectEmit(true, true, false, true); + emit UserPGPRemoved(pgp1, actor.bob_channel_owner, commProxy.chainName(), block.chainid); + + commProxy.removeWalletFromUser(_data, false); + string memory _storedPgpAfter = getWalletToPgp(_data); + assertEq(_storedPgpAfter, ""); + + assertEq(pushToken.balanceOf(address(commProxy)), 20e18); + } + + function test_WhenEOA_IsOwned_ButDoesntHaveAPGP() external whenAUserTriesToRemoveAnEOAFromPGP { + // it should REVERT + bytes memory _data = getEncodedData(actor.bob_channel_owner); + + vm.expectRevert("Invalid Call"); + changePrank(actor.bob_channel_owner); + commProxy.removeWalletFromUser(_data, false); + } + + modifier whenAUserTriesToRemoveAnNFTFromPGP() { + _; + } + + function test_WhenTheNFT_IsNotOwned_ByTheCaller() external whenAUserTriesToRemoveAnNFTFromPGP { + // it REVERTS + bytes memory _data = getEncodedData(address(firstERC721), 0); + changePrank(actor.bob_channel_owner); + commProxy.registerUserPGP(_data, pgp1, true); + + vm.expectRevert("NFT not owned"); + changePrank(actor.alice_channel_owner); + commProxy.removeWalletFromUser(_data, true); + } + + function test_WhenTheNFT_IsOwned_AndAlreadyHasAPGP() external whenAUserTriesToRemoveAnNFTFromPGP { + // it renoves the stored data + + bytes memory _data = getEncodedData(address(firstERC721), 0); + + changePrank(actor.bob_channel_owner); + commProxy.registerUserPGP(_data, pgp1, true); + string memory _storedPgp = getWalletToPgp(_data); + assertEq(_storedPgp, pgp1); + + vm.expectEmit(true, true, false, true); + emit UserPGPRemoved(pgp1, address(firstERC721), 0, commProxy.chainName(), block.chainid); + + commProxy.removeWalletFromUser(_data, true); + string memory _storedPgpAfter = getWalletToPgp(_data); + assertEq(_storedPgpAfter, ""); + + assertEq(pushToken.balanceOf(address(commProxy)), 20e18); + } + + function test_WhenNFTIsOwnedButDoesntHaveAPGP() external whenAUserTriesToRemoveAnNFTFromPGP { + // it should REVERT + bytes memory _data = getEncodedData(address(firstERC721), 0); + + vm.expectRevert("Invalid Call"); + changePrank(actor.bob_channel_owner); + commProxy.removeWalletFromUser(_data, true); + } + + function test_multipleAddresses_andFullRun(address _addr1, address _addr2) external { + vm.assume(_addr1 != _addr2 && _addr1 != actor.admin); + vm.assume(_addr2 != address(0) && _addr1 != address(0)); + bytes memory _dataNft1 = getEncodedData(address(firstERC721), 1); + bytes memory _dataNft2 = getEncodedData(address(secondERC721), 1); + bytes memory _dataEoa1 = getEncodedData(_addr1); + bytes memory _dataEoa2 = getEncodedData(_addr2); + + changePrank(tokenDistributor); + pushToken.transfer(_addr1, 50_000 ether); + pushToken.transfer(_addr2, 50_000 ether); + + approveTokens(_addr1, address(commProxy), 50_000 ether); + approveTokens(_addr2, address(commProxy), 50_000 ether); + + mintNft(_addr1, firstERC721); + mintNft(_addr2, secondERC721); + + // addr1 registers Wallet and NFT with PGP + changePrank(_addr1); + vm.expectEmit(true, true, false, true); + emit UserPGPRegistered(pgp1, _addr1, commProxy.chainName(), block.chainid); + commProxy.registerUserPGP(_dataEoa1, pgp1, false); + string memory _storedPgpEoa = getWalletToPgp(_dataEoa1); + assertEq(_storedPgpEoa, pgp1); + + vm.expectEmit(true, true, false, true); + emit UserPGPRegistered(pgp1, address(firstERC721), 1, commProxy.chainName(), block.chainid); + commProxy.registerUserPGP(_dataNft1, pgp1, true); + string memory _storedPgp = getWalletToPgp(_dataNft1); + assertEq(_storedPgp, pgp1); + + // addr2 registers Wallet and NFT with PGP + changePrank(_addr2); + vm.expectEmit(true, true, false, true); + emit UserPGPRegistered(pgp2, _addr2, commProxy.chainName(), block.chainid); + commProxy.registerUserPGP(_dataEoa2, pgp2, false); + string memory _storedPgpEoa2 = getWalletToPgp(_dataEoa2); + assertEq(_storedPgpEoa2, pgp2); + + vm.expectEmit(true, true, false, true); + emit UserPGPRegistered(pgp2, address(secondERC721), 1, commProxy.chainName(), block.chainid); + commProxy.registerUserPGP(_dataNft2, pgp2, true); + string memory _storedPgp2 = getWalletToPgp(_dataNft2); + assertEq(_storedPgp2, pgp2); + + // addr1 transfers NFT to addr2 and addr2 registers it with PGP + changePrank(_addr1); + firstERC721.transferFrom(_addr1, _addr2, 1); + + string memory _storedPgpTransfer = getWalletToPgp(_dataNft1); + assertEq(_storedPgpTransfer, pgp1); + + changePrank(_addr2); + vm.expectEmit(true, true, false, true); + emit UserPGPRemoved(pgp1, address(firstERC721), 1, commProxy.chainName(), block.chainid); + commProxy.registerUserPGP(_dataNft1, pgp2, true); + string memory _storedPgpTransferAndRegister = getWalletToPgp(_dataNft1); + assertEq(_storedPgpTransferAndRegister, pgp2); + + assertEq(pushToken.balanceOf(address(commProxy)), 50e18); + } + + //Helper Functions + + function getWalletToPgp(bytes memory _data) internal view returns (string memory) { + return commProxy.walletToPGP(keccak256(_data)); + } + + function getEncodedData(address _wallet) internal view returns (bytes memory _data) { + _data = abi.encode("eip155", block.chainid, _wallet); + } + + function getEncodedData(address _nft, uint256 _id) internal view returns (bytes memory _data) { + _data = abi.encode("nft", "eip155", block.chainid, _nft, _id, block.timestamp); + } + + function mintNft(address _addr, MockERC721 _nft) internal { + changePrank(_addr); + _nft.mint(); + } +} diff --git a/test/PushComm/unit_tests/WalletPGPActions/walletPGP.tree b/test/PushComm/unit_tests/WalletPGPActions/walletPGP.tree new file mode 100644 index 00000000..411482bc --- /dev/null +++ b/test/PushComm/unit_tests/WalletPGPActions/walletPGP.tree @@ -0,0 +1,29 @@ +walletPGP.t.sol +├── when a user tries to add an EOA to PGP +│ ├── when the EOA is not owned by the caller +│ │ └── it REVERTS +│ ├── when the EOA is owned but already has a PGP +│ │ └── it REVERTS +│ └── when EOA is owned and doesn't have a PGP +│ └── it should execute and set update the mappings +├── when a user tries to add an NFT to PGP +│ ├── when caller doesn't own the NFT +│ │ └── it REVERTS +│ ├── when caller owns an NFT that's not already attached +│ │ └── it should execute and update mappings +│ └── when caller owns an NFT that's already attached +│ └── it should delete old PGP and update new +├── when a user tries to remove an EOA from PGP +│ ├── when the caller is Not Owner +│ │ └── it REVERTS +│ ├── when the EOA is owned and already has a PGP +│ │ └── it Removes the stored data +│ └── when EOA is owned but doesn't have a PGP +│ └── it should REVERT +└── when a user tries to remove an NFT from PGP + ├── when the NFT is not owned by the caller + │ └── it REVERTS + ├── when the NFT is owned and already has a PGP + │ └── it removes the stored data + └── when NFT is owned But doesn't have a PGP + └── it should REVERT \ No newline at end of file diff --git a/test/PushComm/unit_tests/WalletPGPActions/walletPGPforETH.t.sol b/test/PushComm/unit_tests/WalletPGPActions/walletPGPforETH.t.sol new file mode 100644 index 00000000..ea0b2a8e --- /dev/null +++ b/test/PushComm/unit_tests/WalletPGPActions/walletPGPforETH.t.sol @@ -0,0 +1,290 @@ +pragma solidity ^0.8.0; + +import { BasePushCommTest } from "../BasePushCommTest.t.sol"; +import { Errors } from "contracts/libraries/Errors.sol"; +import { MockERC721 } from "contracts/mocks/MockERC721.sol"; +import { PushCommETHV3 } from "contracts/PushComm/PushCommETHV3.sol"; +import { EPNSCommProxy } from "contracts/PushComm/EPNSCommProxy.sol"; + +import "forge-std/console.sol"; + +contract walletPGPforETH_Test is BasePushCommTest { + string pgp1 = "PGP1"; + string pgp2 = "PGP2"; + string pgp3 = "PGP3"; + string pgp4 = "PGP4"; + MockERC721 firstERC721; + MockERC721 secondERC721; + MockERC721 thirdERC721; + // PushCommETHV3 public commEth; + PushCommETHV3 public commProxyEth; + + function setUp() public override { + BasePushCommTest.setUp(); + // commEth = new PushCommEthV3(); + epnsCommProxy = + new EPNSCommProxy(address(commEth), address(epnsCommProxyAdmin), actor.admin, "FOUNDRY_TEST_NETWORK"); + changePrank(actor.admin); + commProxyEth = PushCommETHV3(address(epnsCommProxy)); + commProxyEth.setEPNSCoreAddress(address(coreProxy)); + commProxyEth.setPushTokenAddress(address(pushToken)); + coreProxy.setEpnsCommunicatorAddress(address(commProxyEth)); + + commProxyEth.setFeeAmount(10e18); + firstERC721 = new MockERC721(actor.bob_channel_owner); + secondERC721 = new MockERC721(actor.bob_channel_owner); + thirdERC721 = new MockERC721(actor.bob_channel_owner); + approveTokens(actor.admin, address(commProxyEth), 50_000 ether); + approveTokens(actor.governance, address(commProxyEth), 50_000 ether); + approveTokens(actor.bob_channel_owner, address(commProxyEth), 50_000 ether); + approveTokens(actor.alice_channel_owner, address(commProxyEth), 50_000 ether); + approveTokens(actor.charlie_channel_owner, address(commProxyEth), 50_000 ether); + approveTokens(actor.dan_push_holder, address(commProxyEth), 50_000 ether); + approveTokens(actor.tim_push_holder, address(commProxyEth), 50_000 ether); + } + + modifier whenAUserTriesToAddAnEOAToPGP() { + _; + } + + function test_When_TheEOA_IsNotOwned_ByCaller() external whenAUserTriesToAddAnEOAToPGP { + // it REVERTS + bytes memory _data = getEncodedData(actor.bob_channel_owner); + + vm.expectRevert(abi.encodeWithSelector(Errors.Comm_InvalidArguments.selector)); + changePrank(actor.alice_channel_owner); + commProxyEth.registerUserPGP(_data, pgp1, false); + } + + function test_WhenEOAIsOwnedAndDoesntHaveAPGP() external whenAUserTriesToAddAnEOAToPGP { + uint256 coreBalanceBefore = pushToken.balanceOf(address(coreProxy)); + + // it should execute and set update the mappings + bytes memory _data = getEncodedData(actor.bob_channel_owner); + + changePrank(actor.bob_channel_owner); + commProxyEth.registerUserPGP(_data, pgp1, false); + string memory _storedPgp = getWalletToPgp(_data); + assertEq(_storedPgp, pgp1); + + assertEq(pushToken.balanceOf(address(coreProxy)), coreBalanceBefore + 10e18); + } + + function test_WhenTheEOAIsOwnedButAlreadyHasAPGP() external whenAUserTriesToAddAnEOAToPGP { + // it + uint256 coreBalanceBefore = pushToken.balanceOf(address(coreProxy)); + + bytes memory _data = getEncodedData(actor.bob_channel_owner); + + changePrank(actor.bob_channel_owner); + commProxyEth.registerUserPGP(_data, pgp1, false); + string memory _storedPgp = getWalletToPgp(_data); + assertEq(_storedPgp, pgp1); + + vm.expectRevert(abi.encodeWithSelector(Errors.Comm_InvalidArguments.selector)); + changePrank(actor.bob_channel_owner); + commProxyEth.registerUserPGP(_data, pgp2, false); + + string memory _storedPgp1 = getWalletToPgp(_data); + assertEq(_storedPgp1, pgp1); + + assertEq(pushToken.balanceOf(address(coreProxy)), coreBalanceBefore + 10e18); + } + + modifier whenAUserTriesToAddAnNFTToPGP() { + _; + } + + function test_WhenCallerDoesntOwnTheNFT() external whenAUserTriesToAddAnNFTToPGP { + // it REVERTS + + bytes memory _data = getEncodedData(address(firstERC721), 0); + + vm.expectRevert("NFT not owned"); + changePrank(actor.alice_channel_owner); + commProxyEth.registerUserPGP(_data, pgp1, true); + string memory _storedPgp = getWalletToPgp(_data); + } + + function test_WhenCallerOwnsAnNFTThatsNotAlreadyAttached() external whenAUserTriesToAddAnNFTToPGP { + // it should execute and update mappings + uint256 coreBalanceBefore = pushToken.balanceOf(address(coreProxy)); + bytes memory _data = getEncodedData(address(firstERC721), 0); + + changePrank(actor.bob_channel_owner); + commProxyEth.registerUserPGP(_data, pgp1, true); + string memory _storedPgp = getWalletToPgp(_data); + assertEq(_storedPgp, pgp1); + assertEq(pushToken.balanceOf(address(coreProxy)), coreBalanceBefore + 10e18); + } + + function test_WhenCaller_OwnsAnNFT_ThatsAlreadyAttached() external whenAUserTriesToAddAnNFTToPGP { + // it should delete old PGP and update new + + uint256 coreBalanceBefore = pushToken.balanceOf(address(coreProxy)); + bytes memory _data = getEncodedData(address(firstERC721), 0); + + changePrank(actor.bob_channel_owner); + commProxyEth.registerUserPGP(_data, pgp1, true); + string memory _storedPgp = getWalletToPgp(_data); + assertEq(_storedPgp, pgp1); + + firstERC721.transferFrom(actor.bob_channel_owner, actor.alice_channel_owner, 0); + changePrank(actor.alice_channel_owner); + commProxyEth.registerUserPGP(_data, pgp2, true); + string memory _storedPgpAlice = getWalletToPgp(_data); + assertEq(_storedPgpAlice, pgp2); + + assertEq(pushToken.balanceOf(address(coreProxy)), coreBalanceBefore + 20e18); + } + + modifier whenAUserTriesToRemoveAnEOAFromPGP() { + _; + } + + function test_WhenTheCallerIsNotOwner() external whenAUserTriesToRemoveAnEOAFromPGP { + // it REVERTS + bytes memory _data = getEncodedData(actor.bob_channel_owner); + changePrank(actor.bob_channel_owner); + commProxyEth.registerUserPGP(_data, pgp1, false); + + vm.expectRevert(abi.encodeWithSelector(Errors.Comm_InvalidArguments.selector)); + changePrank(actor.alice_channel_owner); + commProxyEth.removeWalletFromUser(_data, false); + } + + function test_WhenTheEOAIsOwnedAndAlreadyHasAPGP() external whenAUserTriesToRemoveAnEOAFromPGP { + // it Removes the stored data + uint256 coreBalanceBefore = pushToken.balanceOf(address(coreProxy)); + bytes memory _data = getEncodedData(actor.bob_channel_owner); + + changePrank(actor.bob_channel_owner); + commProxyEth.registerUserPGP(_data, pgp1, false); + string memory _storedPgp = getWalletToPgp(_data); + assertEq(_storedPgp, pgp1); + + commProxyEth.removeWalletFromUser(_data, false); + string memory _storedPgpAfter = getWalletToPgp(_data); + assertEq(_storedPgpAfter, ""); + + assertEq(pushToken.balanceOf(address(coreProxy)), coreBalanceBefore + 20e18); + } + + function test_WhenEOAIsOwnedButDoesntHaveAPGP() external whenAUserTriesToRemoveAnEOAFromPGP { + // it should REVERT + bytes memory _data = getEncodedData(actor.bob_channel_owner); + + vm.expectRevert("Invalid Call"); + changePrank(actor.bob_channel_owner); + commProxyEth.removeWalletFromUser(_data, false); + } + + modifier whenAUserTriesToRemoveAnNFTFromPGP() { + _; + } + + function test_WhenTheNFTIsNotOwnedByTheCaller() external whenAUserTriesToRemoveAnNFTFromPGP { + // it REVERTS + bytes memory _data = getEncodedData(address(firstERC721), 0); + changePrank(actor.bob_channel_owner); + commProxyEth.registerUserPGP(_data, pgp1, true); + + vm.expectRevert("NFT not owned"); + changePrank(actor.alice_channel_owner); + commProxyEth.removeWalletFromUser(_data, true); + } + + function test_WhenTheNFTIsOwnedAndAlreadyHasAPGP() external whenAUserTriesToRemoveAnNFTFromPGP { + // it renoves the stored data + uint256 coreBalanceBefore = pushToken.balanceOf(address(coreProxy)); + bytes memory _data = getEncodedData(address(firstERC721), 0); + + changePrank(actor.bob_channel_owner); + commProxyEth.registerUserPGP(_data, pgp1, true); + string memory _storedPgp = getWalletToPgp(_data); + assertEq(_storedPgp, pgp1); + + commProxyEth.removeWalletFromUser(_data, true); + string memory _storedPgpAfter = getWalletToPgp(_data); + assertEq(_storedPgpAfter, ""); + assertEq(pushToken.balanceOf(address(coreProxy)), coreBalanceBefore + 20e18); + } + + function test_WhenNFTIsOwnedButDoesntHaveAPGP() external whenAUserTriesToRemoveAnNFTFromPGP { + // it should REVERT + uint256 coreBalanceBefore = pushToken.balanceOf(address(coreProxy)); + bytes memory _data = getEncodedData(address(firstERC721), 0); + + vm.expectRevert("Invalid Call"); + changePrank(actor.bob_channel_owner); + commProxyEth.removeWalletFromUser(_data, true); + } + + function test_multipleAddresses_andFullRun(address _addr1, address _addr2) external { + uint256 coreBalanceBefore = pushToken.balanceOf(address(coreProxy)); + + vm.assume(_addr1 != _addr2 && _addr1 != actor.admin); + vm.assume(_addr2 != address(0) && _addr1 != address(0)); + bytes memory _dataNft1 = getEncodedData(address(firstERC721), 1); + bytes memory _dataNft2 = getEncodedData(address(secondERC721), 1); + bytes memory _dataNft3 = getEncodedData(address(thirdERC721), 1); + bytes memory _dataEoa1 = getEncodedData(_addr1); + bytes memory _dataEoa2 = getEncodedData(_addr2); + + changePrank(tokenDistributor); + pushToken.transfer(_addr1, 50_000 ether); + pushToken.transfer(_addr2, 50_000 ether); + + approveTokens(_addr1, address(commProxyEth), 50_000 ether); + approveTokens(_addr2, address(commProxyEth), 50_000 ether); + + mintNft(_addr1, firstERC721); + mintNft(_addr2, secondERC721); + + changePrank(_addr1); + commProxyEth.registerUserPGP(_dataEoa1, pgp1, false); + string memory _storedPgpEoa = getWalletToPgp(_dataEoa1); + assertEq(_storedPgpEoa, pgp1); + commProxyEth.registerUserPGP(_dataNft1, pgp1, true); + string memory _storedPgp = getWalletToPgp(_dataNft1); + assertEq(_storedPgp, pgp1); + + changePrank(_addr2); + commProxyEth.registerUserPGP(_dataEoa2, pgp2, false); + string memory _storedPgpEoa2 = getWalletToPgp(_dataEoa2); + assertEq(_storedPgpEoa2, pgp2); + commProxyEth.registerUserPGP(_dataNft2, pgp2, true); + string memory _storedPgp2 = getWalletToPgp(_dataNft2); + assertEq(_storedPgp2, pgp2); + + changePrank(_addr1); + firstERC721.transferFrom(_addr1, _addr2, 1); + string memory _storedPgpTransfer = getWalletToPgp(_dataNft1); + assertEq(_storedPgpTransfer, pgp1); + changePrank(_addr2); + commProxyEth.registerUserPGP(_dataNft1, pgp2, true); + string memory _storedPgpTransferAndRegister = getWalletToPgp(_dataNft1); + assertEq(_storedPgpTransferAndRegister, pgp2); + + assertEq(pushToken.balanceOf(address(coreProxy)), coreBalanceBefore + 50e18); + } + + //Helper Functions + + function getWalletToPgp(bytes memory _data) internal view returns (string memory) { + return commProxyEth.walletToPGP(keccak256(_data)); + } + + function getEncodedData(address _wallet) internal view returns (bytes memory _data) { + _data = abi.encode("eip155", block.chainid, _wallet); + } + + function getEncodedData(address _nft, uint256 _id) internal view returns (bytes memory _data) { + _data = abi.encode("nft", "eip155", block.chainid, _nft, _id, block.timestamp); + } + + function mintNft(address _addr, MockERC721 _nft) internal { + changePrank(_addr); + _nft.mint(); + } +} diff --git a/test/PushCore/unit_tests/BasePushCoreTest.t.sol b/test/PushCore/unit_tests/BasePushCoreTest.t.sol index 7cd6455e..ac82967a 100644 --- a/test/PushCore/unit_tests/BasePushCoreTest.t.sol +++ b/test/PushCore/unit_tests/BasePushCoreTest.t.sol @@ -4,7 +4,7 @@ pragma experimental ABIEncoderV2; import "forge-std/Test.sol"; import { BaseTest } from "../../BaseTest.t.sol"; -import { CoreTypes } from "../../../contracts/libraries/DataTypes.sol"; +import { CoreTypes } from "contracts/libraries/DataTypes.sol"; contract BasePushCoreTest is BaseTest { bytes constant _testChannelUpdatedIdentity = bytes("test-updated-channel-hello-world"); diff --git a/test/PushCore/unit_tests/ChannelCreationPush/createChannelWithPUSH.t.sol b/test/PushCore/unit_tests/ChannelCreationPush/createChannelWithPUSH.t.sol index d6d8d098..d72806d6 100644 --- a/test/PushCore/unit_tests/ChannelCreationPush/createChannelWithPUSH.t.sol +++ b/test/PushCore/unit_tests/ChannelCreationPush/createChannelWithPUSH.t.sol @@ -1,7 +1,7 @@ pragma solidity ^0.8.20; import { BasePushCoreTest } from "../BasePushCoreTest.t.sol"; -import { CoreTypes } from "../../../../contracts/libraries/DataTypes.sol"; +import { CoreTypes } from "contracts/libraries/DataTypes.sol"; import { Errors } from "contracts/libraries/Errors.sol"; contract CreateChannelWithPUSH_Test is BasePushCoreTest { diff --git a/test/PushCore/unit_tests/ChannelMigration/ChannelMigration.t.sol b/test/PushCore/unit_tests/ChannelMigration/ChannelMigration.t.sol index 2b30f7f4..10c49003 100644 --- a/test/PushCore/unit_tests/ChannelMigration/ChannelMigration.t.sol +++ b/test/PushCore/unit_tests/ChannelMigration/ChannelMigration.t.sol @@ -1,7 +1,7 @@ pragma solidity ^0.8.20; import { BasePushCoreTest } from "../BasePushCoreTest.t.sol"; -import { CoreTypes } from "../../../../contracts/libraries/DataTypes.sol"; +import { CoreTypes } from "contracts/libraries/DataTypes.sol"; import { EPNSCoreProxy, ITransparentUpgradeableProxy } from "contracts/PushCore/EPNSCoreProxy.sol"; import { PushCoreMock } from "contracts/mocks/PushCoreMock.sol"; import { console } from "forge-std/console.sol"; diff --git a/test/PushCore/unit_tests/ChannelStateCycle/deactivateChannel/deactivateChannel.t.sol b/test/PushCore/unit_tests/ChannelStateCycle/deactivateChannel/deactivateChannel.t.sol index d15a4380..9287e552 100644 --- a/test/PushCore/unit_tests/ChannelStateCycle/deactivateChannel/deactivateChannel.t.sol +++ b/test/PushCore/unit_tests/ChannelStateCycle/deactivateChannel/deactivateChannel.t.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.20; import { BasePushCoreTest } from "../../BasePushCoreTest.t.sol"; import { Errors } from "contracts/libraries/Errors.sol"; -import { CoreTypes } from "../../../../../contracts/libraries/DataTypes.sol"; +import { CoreTypes } from "contracts/libraries/DataTypes.sol"; contract DeactivateChannel_Test is BasePushCoreTest { function setUp() public virtual override { diff --git a/test/PushCore/unit_tests/CreateIncentivizedChat/createIncentivizedChat.t.sol b/test/PushCore/unit_tests/CreateIncentivizedChat/createIncentivizedChat.t.sol new file mode 100644 index 00000000..9ed30d50 --- /dev/null +++ b/test/PushCore/unit_tests/CreateIncentivizedChat/createIncentivizedChat.t.sol @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +import { BasePushCoreTest } from "../BasePushCoreTest.t.sol"; +import { Errors } from "contracts/libraries/Errors.sol"; +import { console } from "forge-std/console.sol"; +import { BaseHelper } from "contracts/libraries/BaseHelper.sol"; + +contract test_createIncentivizedChat is BasePushCoreTest { + function setUp() public override { + BasePushCoreTest.setUp(); + } + + modifier whenUserCreatesIncentivizedChat() { + approveTokens(actor.bob_channel_owner, address(coreProxy), 100 ether); + _; + } + + function test_WhenPassedAmountIsZero() external whenUserCreatesIncentivizedChat { + // it should Revert + changePrank(actor.bob_channel_owner); + vm.expectRevert(abi.encodeWithSelector(Errors.InvalidArg_LessThanExpected.selector, coreProxy.FEE_AMOUNT(), 0)); + coreProxy.createIncentivizedChatRequest(actor.charlie_channel_owner, 0); + } + + function test_WhenPassedReceiver_IsZeroAddress() external whenUserCreatesIncentivizedChat { + // it should Revert + changePrank(actor.bob_channel_owner); + vm.expectRevert(abi.encodeWithSelector(Errors.InvalidArgument_WrongAddress.selector, address(0))); + coreProxy.createIncentivizedChatRequest(address(0), 100e18); + } + + function test_WhenParametersAreCorrect() public whenUserCreatesIncentivizedChat { + // it should update chatInfo and call core and emit event + uint256 bobBalanceBefore = pushToken.balanceOf(actor.bob_channel_owner); + uint256 coreBalanceBefore = pushToken.balanceOf(address(coreProxy)); + + // it should update storage and emit event + uint256 previousAmount = coreProxy.celebUserFunds(actor.charlie_channel_owner); + uint256 PROTOCOL_POOL_FEES = coreProxy.PROTOCOL_POOL_FEES(); + + changePrank(actor.bob_channel_owner); + + vm.expectEmit(false, false, false, true); + emit IncentivizedChatReqReceived( + BaseHelper.addressToBytes32(actor.bob_channel_owner), BaseHelper.addressToBytes32(actor.charlie_channel_owner), 100e18 - FEE_AMOUNT, FEE_AMOUNT, block.timestamp + ); + coreProxy.createIncentivizedChatRequest(actor.charlie_channel_owner, 100e18); + + assertEq(bobBalanceBefore - 100e18, pushToken.balanceOf(actor.bob_channel_owner)); + assertEq(coreBalanceBefore + 100e18, pushToken.balanceOf(address(coreProxy))); + + assertEq(previousAmount + 100e18 - FEE_AMOUNT, coreProxy.celebUserFunds(actor.charlie_channel_owner)); + assertEq(PROTOCOL_POOL_FEES + FEE_AMOUNT, coreProxy.PROTOCOL_POOL_FEES()); + } + + modifier whenCelebTriesToClaimTheTokens() { + _; + } + + function test_WhenRequestedAmountIsMoreThanBalance() external whenCelebTriesToClaimTheTokens { + // it should Revert + test_WhenParametersAreCorrect(); + uint256 claimAmount = coreProxy.celebUserFunds(actor.charlie_channel_owner); + + changePrank(actor.charlie_channel_owner); + vm.expectRevert( + abi.encodeWithSelector( + Errors.InvalidArg_MoreThanExpected.selector, + coreProxy.celebUserFunds(actor.charlie_channel_owner), + claimAmount + 1 + ) + ); + coreProxy.claimChatIncentives(claimAmount + 1); + } + + function test_WhenRequestedAmountIsCorrect() external whenCelebTriesToClaimTheTokens { + // it should transfer the tokens to celebUser + uint256 claimAmount = coreProxy.celebUserFunds(actor.charlie_channel_owner); + uint256 charlieBalanceBefore = pushToken.balanceOf(actor.charlie_channel_owner); + uint256 coreBalanceBefore = pushToken.balanceOf(address(coreProxy)); + + changePrank(actor.charlie_channel_owner); + coreProxy.claimChatIncentives(claimAmount); + + assertEq(charlieBalanceBefore + claimAmount, pushToken.balanceOf(actor.charlie_channel_owner)); + assertEq(coreBalanceBefore - claimAmount, pushToken.balanceOf(address(coreProxy))); + } +} diff --git a/test/PushCore/unit_tests/CreateIncentivizedChat/createIncentivizedChat.tree b/test/PushCore/unit_tests/CreateIncentivizedChat/createIncentivizedChat.tree new file mode 100644 index 00000000..2d1631f9 --- /dev/null +++ b/test/PushCore/unit_tests/CreateIncentivizedChat/createIncentivizedChat.tree @@ -0,0 +1,15 @@ +. +├── test_createIncentivizedChat +├── when user creates incentivized chat +│ ├── when passed amount is less than fee_amount +│ │ └── it should Revert +│ └── when passed amount is more than fee_amount +│ ├── when requestReceiver parameter is zero address +│ │ └── it should revert +│ └── when parameters are correct +│ └── it should update storage and emit event +└── when celeb tries to claim the tokens + ├── when requested amount is more than balance + │ └── it should Revert + └── when requested amount is correct + └── it should transfer the tokens to celebUser \ No newline at end of file diff --git a/test/PushCore/unit_tests/HandleArbitraryRequest/HandleArbitraryReq.t.sol b/test/PushCore/unit_tests/HandleArbitraryRequest/HandleArbitraryReq.t.sol new file mode 100644 index 00000000..e08fca1c --- /dev/null +++ b/test/PushCore/unit_tests/HandleArbitraryRequest/HandleArbitraryReq.t.sol @@ -0,0 +1,53 @@ +import { BasePushCoreTest } from "../BasePushCoreTest.t.sol"; +import { GenericTypes } from "contracts/libraries/DataTypes.sol"; +import { Errors } from "contracts/libraries/Errors.sol"; +import { BaseHelper } from "contracts/libraries/BaseHelper.sol"; +import { console } from "forge-std/console.sol"; + +contract HandleArbitraryReq is BasePushCoreTest { + GenericTypes.Percentage feePercentage = GenericTypes.Percentage(2322, 2); + uint256 amount = 100e18; + + function setUp() public virtual override { + BasePushCoreTest.setUp(); + } + + modifier whenUserCreatesAnArbitraryRequest() { + _; + } + + function test_RevertWhen_TheySend_ZeroTokens() external whenUserCreatesAnArbitraryRequest { + // it should revert + vm.expectRevert(abi.encodeWithSelector(Errors.InvalidArg_LessThanExpected.selector, 1, 0)); + changePrank(actor.bob_channel_owner); + coreProxy.handleArbitraryRequestData(1, feePercentage, actor.charlie_channel_owner, 0); + } + + function test_WhenTheySendAmount_GreaterThanZero() public whenUserCreatesAnArbitraryRequest { + // it should execute and update storage + uint256 PROTOCOL_POOL_FEES = coreProxy.PROTOCOL_POOL_FEES(); + uint256 arbitraryFees = coreProxy.arbitraryReqFees(actor.charlie_channel_owner); + + vm.expectEmit(true, true, false, true); + emit ArbitraryRequest(BaseHelper.addressToBytes32(actor.bob_channel_owner), BaseHelper.addressToBytes32(actor.charlie_channel_owner), amount, feePercentage, 1); + changePrank(actor.bob_channel_owner); + coreProxy.handleArbitraryRequestData(1, feePercentage, actor.charlie_channel_owner, amount); + uint256 feeAmount = BaseHelper.calcPercentage(amount, feePercentage); + + // Update states based on Fee Percentage calculation + assertEq(coreProxy.PROTOCOL_POOL_FEES(), PROTOCOL_POOL_FEES + feeAmount); + assertEq(coreProxy.arbitraryReqFees(actor.charlie_channel_owner), arbitraryFees + amount - feeAmount); + } + + function test_whenUserTries_ToClaimArbitraryFees() external { + //it should send the tokens to user + test_WhenTheySendAmount_GreaterThanZero(); + uint256 balanceBefore = pushToken.balanceOf(address(actor.charlie_channel_owner)); + changePrank(actor.charlie_channel_owner); + coreProxy.claimArbitraryRequestFees(coreProxy.arbitraryReqFees(actor.charlie_channel_owner)); + uint256 feeAmount = BaseHelper.calcPercentage(amount, feePercentage); + console.log(pushToken.balanceOf(address(actor.charlie_channel_owner)), balanceBefore, amount, feeAmount); + assertEq(pushToken.balanceOf(address(actor.charlie_channel_owner)), balanceBefore + amount - feeAmount); + assertEq(coreProxy.arbitraryReqFees(actor.charlie_channel_owner), 0); + } +} diff --git a/test/PushCore/unit_tests/HandleArbitraryRequest/HandleArbitraryReq.tree b/test/PushCore/unit_tests/HandleArbitraryRequest/HandleArbitraryReq.tree new file mode 100644 index 00000000..88585425 --- /dev/null +++ b/test/PushCore/unit_tests/HandleArbitraryRequest/HandleArbitraryReq.tree @@ -0,0 +1,8 @@ +HandleArbitraryReq +├── when user creates an arbitrary request +│ ├── when they send zero tokens +│ │ └── it should revert +│ └── when they send amount greater than zero +│ └── it should execute and update storage +└── when user tries to claim arbitrary fees + └── it should send the tokens to user \ No newline at end of file diff --git a/test/PushCore/unit_tests/TimeBoundChannel/timeBoundChannel.t.sol b/test/PushCore/unit_tests/TimeBoundChannel/timeBoundChannel.t.sol index b02f8be5..6221ce74 100644 --- a/test/PushCore/unit_tests/TimeBoundChannel/timeBoundChannel.t.sol +++ b/test/PushCore/unit_tests/TimeBoundChannel/timeBoundChannel.t.sol @@ -1,7 +1,7 @@ pragma solidity ^0.8.20; import { BasePushCoreTest } from "../BasePushCoreTest.t.sol"; -import { CoreTypes } from "../../../../contracts/libraries/DataTypes.sol"; +import { CoreTypes } from "contracts/libraries/DataTypes.sol"; import { Errors } from "contracts/libraries/Errors.sol"; contract TimeBoundChannel_Test is BasePushCoreTest { diff --git a/test/utils/Events.sol b/test/utils/Events.sol index 541f96d1..7f7ca2a6 100644 --- a/test/utils/Events.sol +++ b/test/utils/Events.sol @@ -1,6 +1,6 @@ pragma solidity ^0.8.20; -import { CoreTypes, GenericTypes } from "../../contracts/libraries/DataTypes.sol"; +import { CoreTypes, GenericTypes } from "../../contracts/libraries/DataTypes.sol"; abstract contract CoreEvents { event AddChannel(address indexed channel, CoreTypes.ChannelType indexed channelType, bytes identity); @@ -10,7 +10,7 @@ abstract contract CoreEvents { event DeactivateChannel(address indexed channel, uint256 indexed amountRefunded); event ChannelBlocked(bytes32 indexed channel); event TimeBoundChannelDestroyed(address indexed channel, uint256 indexed amountRefunded); - event IncentivizeChatReqReceived( + event IncentivizedChatReqReceived( bytes32 requestSender, bytes32 requestReceiver, uint256 amountForReqReceiver, @@ -38,7 +38,17 @@ abstract contract CommEvents { ); event Subscribe(address indexed channel, address indexed user); event Unsubscribe(address indexed channel, address indexed user); - event LogMessagePublished(address indexed sender, uint64 sequence, uint32 nonce, bytes payload, uint8 consistencyLevel); + ///@notice emits whenever a Wallet or NFT is linked OR unlinked to a PGP hash + event UserPGPRegistered(string indexed PgpHash, address indexed wallet, string chainName, uint256 chainID); + event UserPGPRegistered( + string indexed PgpHash, address indexed nft, uint256 nftId, string chainName, uint256 chainID + ); + + event UserPGPRemoved(string indexed PgpHash, address indexed wallet, string chainName, uint256 chainID); + event UserPGPRemoved(string indexed PgpHash, address indexed nft, uint256 nftId, string chainName, uint256 chainID); + event LogMessagePublished( + address indexed sender, uint64 sequence, uint32 nonce, bytes payload, uint8 consistencyLevel + ); } abstract contract ProxyEvents { diff --git a/test_legacy/v2/core/IncentivizedChatRequest.test.js b/test_legacy/v2/core/IncentivizedChatRequest.test.js index 843006b3..3c4f6770 100644 --- a/test_legacy/v2/core/IncentivizedChatRequest.test.js +++ b/test_legacy/v2/core/IncentivizedChatRequest.test.js @@ -116,7 +116,7 @@ describe("Incentivized chats", function () { it("should call handleChatRequest in core and it should fail if caller is not Comm ", async () => { await expect( - EPNSCoreV1Proxy.handleChatRequestData( + EPNSCoreV1Proxy.createIncentivizedChatRequest( BOB, ALICE, ethers.utils.parseEther("100") @@ -157,7 +157,7 @@ describe("Incentivized chats", function () { ); await expect(txn) - .to.emit(EPNSCoreV1Proxy, "IncentivizeChatReqReceived") + .to.emit(EPNSCoreV1Proxy, "IncentivizedChatReqReceived") .withArgs( BOB, ALICE, From d3d5a7ba14cbccb32480c6830e3902bc477f731d Mon Sep 17 00:00:00 2001 From: Md Zartaj Afser Date: Thu, 8 Aug 2024 15:58:04 +0530 Subject: [PATCH 21/23] fix test cases and structure --- .../ArbitraryRequest/ArbitraryRequest.t.sol | 4 +- test/CCR/CCRutils/CCRConfig.sol | 47 +------------------ test/CCR/CCRutils/Helper.sol | 30 +++++++++--- .../CreateChannelCCR/CreateChannelCCR.t.sol | 8 ++-- .../CreateChannelSettingsCCR.t.sol | 10 ++-- .../CreateChatCCR/CreateChatCCR.t.sol | 6 +-- .../UpdateChannelMetaCCR.t.sol | 5 +- .../DeactivateDeleteChannelCCR.t.sol | 6 +-- .../ReactivateChannelCCR.t.sol | 7 +-- .../unit_tests/BasePushCommTest.t.sol | 3 -- 10 files changed, 47 insertions(+), 79 deletions(-) diff --git a/test/CCR/ArbitraryRequest/ArbitraryRequest.t.sol b/test/CCR/ArbitraryRequest/ArbitraryRequest.t.sol index d4ccec7e..8a1fb630 100644 --- a/test/CCR/ArbitraryRequest/ArbitraryRequest.t.sol +++ b/test/CCR/ArbitraryRequest/ArbitraryRequest.t.sol @@ -167,6 +167,8 @@ contract ArbitraryRequesttsol is BaseCCRTest { (bytes memory transceiverMessage, bytes32 hash) = getRequestPayload(_amount, recipient, recipientChain, sourceNttManager); + uint balanceCoreBefore = pushToken.balanceOf(address(coreProxy)); + changePrank(DestChain.WORMHOLE_RELAYER_DEST); DestChain.wormholeTransceiverChain2.receiveWormholeMessages( transceiverMessage, // Verified @@ -176,7 +178,7 @@ contract ArbitraryRequesttsol is BaseCCRTest { hash // Hash of the VAA being used ); - assertEq(pushToken.balanceOf(address(coreProxy)), amount); + assertEq(pushToken.balanceOf(address(coreProxy)), balanceCoreBefore + amount, "Tokens in Core"); } function test_when_UserTries_ClaimingArbitraryTokens() external { diff --git a/test/CCR/CCRutils/CCRConfig.sol b/test/CCR/CCRutils/CCRConfig.sol index eaa93c65..b40dfb53 100644 --- a/test/CCR/CCRutils/CCRConfig.sol +++ b/test/CCR/CCRutils/CCRConfig.sol @@ -24,6 +24,7 @@ contract CCRConfig { address NTT_MANAGER; address WORMHOLE_RELAYER_DEST; address PUSH_NTT_DEST; + address DestPushHolder; uint16 DestChainId; string rpc; } @@ -41,60 +42,16 @@ contract CCRConfig { "https://sepolia-rollup.arbitrum.io/rpc" ); - // SourceConfig ArbSepolia = SourceConfig( - // IWormhole(0x6b9C8671cdDC8dEab9c719bB87cBd3e782bA6a35), - // IWormholeTransceiver(0xEFBeAAF530653576acf8a78a19fB7b28b085AF9F), - // 0xFAB6A0Cb264D34B939A7eDcF83f5e8D447C21812, - // 0xEFBeAAF530653576acf8a78a19fB7b28b085AF9F, - // 0x7B1bD7a6b4E61c2a123AC6BC2cbfC614437D0470, - // 0xa58F4F5FB4977151E99291FCa5b92d95021be0f4, - // 0x778D3206374f8AC265728E18E3fE2Ae6b93E4ce4, - // 10_003, - // "https://sepolia-rollup.arbitrum.io/rpc" - // ); - DestConfig EthSepolia = DestConfig( IWormhole(0x4a8bc80Ed5a4067f1CCf107057b8270E0cC11A78), IWormholeTransceiver(0x9D85E6467d5069A7144E4f251E540bf9fA7ea5C6), 0xCFA54a96fE19d9EB9395642225C62d0abe6Cd835, 0x7B1bD7a6b4E61c2a123AC6BC2cbfC614437D0470, 0xe1327FE9b457Ad1b4601FdD2afcAdAef198d6BA6, + 0x778D3206374f8AC265728E18E3fE2Ae6b93E4ce4, 10_002, "https://eth-sepolia.public.blastapi.io" ); - // DestConfig BaseSepolia = DestConfig( - // IWormhole(0x4a8bc80Ed5a4067f1CCf107057b8270E0cC11A78), - // IWormholeTransceiver(0xE175E3aBa428d028D2CEdE8e1cB338D1f1D50d13), - // 0x63Dd783A353ad0f8a654ba7a21D7Fd8637E278a1, - // 0x93BAD53DDfB6132b0aC8E37f6029163E63372cEE, - // 0x527F3692F5C53CfA83F7689885995606F93b6164, - // 10004, - // "https://sepolia.base.org" - // ); - - /// NEWEST DEPLOYED CONTRACT /// - - // SourceConfig ArbSepolia = SourceConfig( - // IWormhole(0x6b9C8671cdDC8dEab9c719bB87cBd3e782bA6a35), - // IWormholeTransceiver(0x4F532db1ce4f33170b21F6a97A8973e9499BbD75), - // 0x5e1989B8681C91A90F33A82b22cf51210a7C31C0, - // 0x4F532db1ce4f33170b21F6a97A8973e9499BbD75, - // 0x7B1bD7a6b4E61c2a123AC6BC2cbfC614437D0470, - // 0x70c3C79d33A9b08F1bc1e7DB113D1588Dad7d8Bc, - // 0x778D3206374f8AC265728E18E3fE2Ae6b93E4ce4, - // 10_003, - // "https://sepolia-rollup.arbitrum.io/rpc" - // ); - - // DestConfig EthSepolia = DestConfig( - // IWormhole(0x4a8bc80Ed5a4067f1CCf107057b8270E0cC11A78), - // IWormholeTransceiver(0x3cc5553e0ABfF03743c9c2cc785D184e72D45852), - // 0x76c636cb502Aa7eed6784Fde38b955bC15CC6bc1, - // 0x7B1bD7a6b4E61c2a123AC6BC2cbfC614437D0470, - // 0xe1327FE9b457Ad1b4601FdD2afcAdAef198d6BA6, - // 10_002, - // "https://eth-sepolia.public.blastapi.io" - // ); // chain agnostic constants // ToDo: to be changed diff --git a/test/CCR/CCRutils/Helper.sol b/test/CCR/CCRutils/Helper.sol index fb2f92cf..1817beb2 100644 --- a/test/CCR/CCRutils/Helper.sol +++ b/test/CCR/CCRutils/Helper.sol @@ -37,12 +37,21 @@ contract Helper is BasePushCommTest, CCRConfig { vm.createSelectFork(url); } - function getPushTokenOnfork(address _addr, uint256 _amount) public { - changePrank(SourceChain.PushHolder); - pushNttToken.transfer(_addr, _amount); + function getPushTokenOnfork(address _addr, uint256 _amount, address _token) public { + if(_token == SourceChain.PUSH_NTT_SOURCE){ - changePrank(_addr); - pushNttToken.approve(address(commProxy), type(uint256).max); + changePrank(SourceChain.PushHolder); + pushNttToken.transfer(_addr, _amount); + + changePrank(_addr); + pushNttToken.approve(address(commProxy), type(uint256).max); + } else if(_token == DestChain.PUSH_NTT_DEST){ + changePrank(DestChain.DestPushHolder); + pushToken.transfer(_addr, _amount); + + changePrank(_addr); + pushToken.approve(address(coreProxy), type(uint256).max); + } } function setUpSourceChain() internal { @@ -50,8 +59,8 @@ contract Helper is BasePushCommTest, CCRConfig { BasePushCommTest.setUp(); pushNttToken = Push(SourceChain.PUSH_NTT_SOURCE); - getPushTokenOnfork(actor.bob_channel_owner, 1000e18); - getPushTokenOnfork(actor.charlie_channel_owner, 1000e18); + getPushTokenOnfork(actor.bob_channel_owner, 1000e18, address(pushNttToken)); + getPushTokenOnfork(actor.charlie_channel_owner, 1000e18,address(pushNttToken)); changePrank(actor.admin); commProxy.setBridgeConfig( @@ -67,10 +76,17 @@ contract Helper is BasePushCommTest, CCRConfig { switchChains(DestChain.rpc); BasePushCommTest.setUp(); pushToken = EPNS(DestChain.PUSH_NTT_DEST); + changePrank(actor.admin); coreProxy.setWormholeRelayer(DestChain.WORMHOLE_RELAYER_DEST); coreProxy.setEpnsTokenAddress(address(pushToken)); coreProxy.setRegisteredSender(SourceChain.SourceChainId, toWormholeFormat(address(commProxy))); + + getPushTokenOnfork(actor.bob_channel_owner, 1000e18, address(pushToken)); + getPushTokenOnfork(actor.charlie_channel_owner, 1000e18,address(pushToken)); + changePrank(actor.bob_channel_owner); + coreProxy.createChannelWithPUSH(CoreTypes.ChannelType.InterestBearingOpen, _testChannelIdentity, 50e18, 0); + changePrank(actor.admin); } function getPoolFundsAndFees(uint256 _amountDeposited) diff --git a/test/CCR/SpecificRequest/CreateChannelCCR/CreateChannelCCR.t.sol b/test/CCR/SpecificRequest/CreateChannelCCR/CreateChannelCCR.t.sol index c253a5e3..13582640 100644 --- a/test/CCR/SpecificRequest/CreateChannelCCR/CreateChannelCCR.t.sol +++ b/test/CCR/SpecificRequest/CreateChannelCCR/CreateChannelCCR.t.sol @@ -5,8 +5,6 @@ import { BaseCCRTest } from "../../BaseCCR.t.sol"; import { CoreTypes, CrossChainRequestTypes } from "contracts/libraries/DataTypes.sol"; import { Errors } from "contracts/libraries/Errors.sol"; import { console } from "forge-std/console.sol"; -import "contracts/libraries/wormhole-lib/TrimmedAmount.sol"; -import { TransceiverStructs } from "contracts/libraries/wormhole-lib/TransceiverStructs.sol"; import { BaseHelper } from "contracts/libraries/BaseHelper.sol"; import { IRateLimiter } from "contracts/interfaces/wormhole/IRateLimiter.sol"; @@ -171,12 +169,12 @@ contract CreateChannelCCR is BaseCCRTest { (address sourceNttManager, bytes32 recipient, uint256 _amount, uint16 recipientChain) = getMessagefromLog(vm.getRecordedLogs()); - console.log(pushToken.balanceOf(address(coreProxy))); - bytes[] memory a; (bytes memory transceiverMessage, bytes32 hash) = getRequestPayload(_amount, recipient, recipientChain, sourceNttManager); + uint balanceCoreBefore = pushToken.balanceOf(address(coreProxy)); + changePrank(DestChain.WORMHOLE_RELAYER_DEST); DestChain.wormholeTransceiverChain2.receiveWormholeMessages( transceiverMessage, // Verified @@ -186,6 +184,6 @@ contract CreateChannelCCR is BaseCCRTest { hash // Hash of the VAA being used ); - assertEq(pushToken.balanceOf(address(coreProxy)), amount); + assertEq(pushToken.balanceOf(address(coreProxy)), balanceCoreBefore + amount, "Tokens in Core"); } } diff --git a/test/CCR/SpecificRequest/CreateChannelSettingsCCR/CreateChannelSettingsCCR.t.sol b/test/CCR/SpecificRequest/CreateChannelSettingsCCR/CreateChannelSettingsCCR.t.sol index a2495c15..2379841a 100644 --- a/test/CCR/SpecificRequest/CreateChannelSettingsCCR/CreateChannelSettingsCCR.t.sol +++ b/test/CCR/SpecificRequest/CreateChannelSettingsCCR/CreateChannelSettingsCCR.t.sol @@ -3,11 +3,9 @@ pragma solidity ^0.8.0; import { BaseCCRTest } from "../../BaseCCR.t.sol"; import "forge-std/console.sol"; -import { CoreTypes, CrossChainRequestTypes } from "contracts/libraries/DataTypes.sol"; +import {CrossChainRequestTypes } from "contracts/libraries/DataTypes.sol"; import { Errors } from "contracts/libraries/Errors.sol"; import { console } from "forge-std/console.sol"; -import "contracts/libraries/wormhole-lib/TrimmedAmount.sol"; -import { TransceiverStructs } from "contracts/libraries/wormhole-lib/TransceiverStructs.sol"; import { BaseHelper } from "contracts/libraries/BaseHelper.sol"; import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; @@ -138,12 +136,12 @@ contract CreateChannelSettingsCCR is BaseCCRTest { (address sourceNttManager, bytes32 recipient, uint256 _amount, uint16 recipientChain) = getMessagefromLog(vm.getRecordedLogs()); - console.log(pushNttToken.balanceOf(address(coreProxy))); - bytes[] memory a; (bytes memory transceiverMessage, bytes32 hash) = getRequestPayload(_amount, recipient, recipientChain, sourceNttManager); + uint balanceCoreBefore = pushToken.balanceOf(address(coreProxy)); + changePrank(DestChain.WORMHOLE_RELAYER_DEST); DestChain.wormholeTransceiverChain2.receiveWormholeMessages( transceiverMessage, // Verified @@ -153,6 +151,6 @@ contract CreateChannelSettingsCCR is BaseCCRTest { hash // Hash of the VAA being used ); - assertEq(pushToken.balanceOf(address(coreProxy)), amount); + assertEq(pushToken.balanceOf(address(coreProxy)), balanceCoreBefore + amount, "Tokens in Core"); } } diff --git a/test/CCR/SpecificRequest/CreateChatCCR/CreateChatCCR.t.sol b/test/CCR/SpecificRequest/CreateChatCCR/CreateChatCCR.t.sol index 582e8f58..d1b6d25b 100644 --- a/test/CCR/SpecificRequest/CreateChatCCR/CreateChatCCR.t.sol +++ b/test/CCR/SpecificRequest/CreateChatCCR/CreateChatCCR.t.sol @@ -6,8 +6,6 @@ import { Errors } from "contracts/libraries/Errors.sol"; import { console } from "forge-std/console.sol"; import { CrossChainRequestTypes } from "contracts/libraries/DataTypes.sol"; -import "contracts/libraries/wormhole-lib/TrimmedAmount.sol"; -import { TransceiverStructs } from "contracts/libraries/wormhole-lib/TransceiverStructs.sol"; import { BaseHelper } from "contracts/libraries/BaseHelper.sol"; import { IRateLimiter } from "contracts/interfaces/wormhole/IRateLimiter.sol"; @@ -144,7 +142,7 @@ contract CreateChatCCR is BaseCCRTest { (address sourceNttManager, bytes32 recipient, uint256 _amount, uint16 recipientChain) = getMessagefromLog(vm.getRecordedLogs()); - console.log(pushToken.balanceOf(address(coreProxy))); + uint balanceCoreBefore = pushToken.balanceOf(address(coreProxy)); bytes[] memory a; (bytes memory transceiverMessage, bytes32 hash) = @@ -159,7 +157,7 @@ contract CreateChatCCR is BaseCCRTest { hash // Hash of the VAA being used ); - assertEq(pushToken.balanceOf(address(coreProxy)), amount); + assertEq(pushToken.balanceOf(address(coreProxy)), balanceCoreBefore + amount, "Tokens in Core"); } function test_when_celebUserTries_ClaimingTokens() external { diff --git a/test/CCR/SpecificRequest/UpdateChannelMetaCCR/UpdateChannelMetaCCR.t.sol b/test/CCR/SpecificRequest/UpdateChannelMetaCCR/UpdateChannelMetaCCR.t.sol index e60777ae..f3b6aff9 100644 --- a/test/CCR/SpecificRequest/UpdateChannelMetaCCR/UpdateChannelMetaCCR.t.sol +++ b/test/CCR/SpecificRequest/UpdateChannelMetaCCR/UpdateChannelMetaCCR.t.sol @@ -128,13 +128,14 @@ contract UpdateChannelCCR is BaseCCRTest { (address sourceNttManager, bytes32 recipient, uint256 _amount, uint16 recipientChain) = getMessagefromLog(vm.getRecordedLogs()); - console.log(pushNttToken.balanceOf(address(coreProxy))); bytes[] memory a; (bytes memory transceiverMessage, bytes32 hash) = getRequestPayload(_amount, recipient, recipientChain, sourceNttManager); changePrank(DestChain.WORMHOLE_RELAYER_DEST); + uint balanceCoreBefore = pushToken.balanceOf(address(coreProxy)); + DestChain.wormholeTransceiverChain2.receiveWormholeMessages( transceiverMessage, // Verified a, // Should be zero @@ -143,6 +144,6 @@ contract UpdateChannelCCR is BaseCCRTest { hash // Hash of the VAA being used ); - assertEq(pushToken.balanceOf(address(coreProxy)), amount); + assertEq(pushToken.balanceOf(address(coreProxy)), balanceCoreBefore + amount, "Tokens in Core"); } } diff --git a/test/CCR/SpecificRequest/UpdateChannelStateCCR/DeactivateDeleteChannelCCR/DeactivateDeleteChannelCCR.t.sol b/test/CCR/SpecificRequest/UpdateChannelStateCCR/DeactivateDeleteChannelCCR/DeactivateDeleteChannelCCR.t.sol index c6432c31..a9b21755 100644 --- a/test/CCR/SpecificRequest/UpdateChannelStateCCR/DeactivateDeleteChannelCCR/DeactivateDeleteChannelCCR.t.sol +++ b/test/CCR/SpecificRequest/UpdateChannelStateCCR/DeactivateDeleteChannelCCR/DeactivateDeleteChannelCCR.t.sol @@ -158,13 +158,13 @@ contract DeactivateChannelCCR is BaseCCRTest { (address sourceNttManager, bytes32 recipient, uint256 _amount, uint16 recipientChain) = getMessagefromLog(vm.getRecordedLogs()); - console.log(pushNttToken.balanceOf(address(coreProxy))); - bytes[] memory a; (bytes memory transceiverMessage, bytes32 hash) = getRequestPayload(_amount, recipient, recipientChain, sourceNttManager); setUpDestChain(); + uint balanceCoreBefore = pushToken.balanceOf(address(coreProxy)); + changePrank(DestChain.WORMHOLE_RELAYER_DEST); DestChain.wormholeTransceiverChain2.receiveWormholeMessages( transceiverMessage, // Verified @@ -174,6 +174,6 @@ contract DeactivateChannelCCR is BaseCCRTest { hash // Hash of the VAA being used ); - assertEq(pushToken.balanceOf(address(coreProxy)), amount); + assertEq(pushToken.balanceOf(address(coreProxy)), balanceCoreBefore + amount, "Tokens in Core"); } } diff --git a/test/CCR/SpecificRequest/UpdateChannelStateCCR/ReactivateChannelCCR/ReactivateChannelCCR.t.sol b/test/CCR/SpecificRequest/UpdateChannelStateCCR/ReactivateChannelCCR/ReactivateChannelCCR.t.sol index 5b6b7b39..0f4d93a8 100644 --- a/test/CCR/SpecificRequest/UpdateChannelStateCCR/ReactivateChannelCCR/ReactivateChannelCCR.t.sol +++ b/test/CCR/SpecificRequest/UpdateChannelStateCCR/ReactivateChannelCCR/ReactivateChannelCCR.t.sol @@ -145,13 +145,14 @@ contract ReactivateChannelCCR is BaseCCRTest { (address sourceNttManager, bytes32 recipient, uint256 _amount, uint16 recipientChain) = getMessagefromLog(vm.getRecordedLogs()); - console.log(pushNttToken.balanceOf(address(coreProxy))); - bytes[] memory a; (bytes memory transceiverMessage, bytes32 hash) = getRequestPayload(_amount, recipient, recipientChain, sourceNttManager); setUpDestChain(); + + uint balanceCoreBefore = pushToken.balanceOf(address(coreProxy)); + changePrank(DestChain.WORMHOLE_RELAYER_DEST); DestChain.wormholeTransceiverChain2.receiveWormholeMessages( transceiverMessage, // Verified @@ -161,6 +162,6 @@ contract ReactivateChannelCCR is BaseCCRTest { hash // Hash of the VAA being used ); - assertEq(pushToken.balanceOf(address(coreProxy)), amount); + assertEq(pushToken.balanceOf(address(coreProxy)), balanceCoreBefore + amount, "Tokens in Core"); } } diff --git a/test/PushComm/unit_tests/BasePushCommTest.t.sol b/test/PushComm/unit_tests/BasePushCommTest.t.sol index b9d77e3d..06cc83e0 100644 --- a/test/PushComm/unit_tests/BasePushCommTest.t.sol +++ b/test/PushComm/unit_tests/BasePushCommTest.t.sol @@ -12,9 +12,6 @@ contract BasePushCommTest is BasePushCoreTest { BasePushCoreTest.setUp(); changePrank(actor.tim_push_holder); verifierContract = new SignatureVerifier(); - - changePrank(actor.bob_channel_owner); - coreProxy.createChannelWithPUSH(CoreTypes.ChannelType.InterestBearingOpen, _testChannelIdentity, 50e18, 0); } //Helper Functions From d5661c04f78961ae174b4ed0af952b0ddcee536b Mon Sep 17 00:00:00 2001 From: Zaryab Date: Tue, 13 Aug 2024 17:30:19 +0400 Subject: [PATCH 22/23] removed unUsed state --- contracts/PushCore/PushCoreStorageV2.sol | 3 --- 1 file changed, 3 deletions(-) diff --git a/contracts/PushCore/PushCoreStorageV2.sol b/contracts/PushCore/PushCoreStorageV2.sol index d76dc3e1..77e7d77a 100644 --- a/contracts/PushCore/PushCoreStorageV2.sol +++ b/contracts/PushCore/PushCoreStorageV2.sol @@ -36,9 +36,6 @@ contract PushCoreStorageV2 { */ mapping(address => uint256) public celebUserFunds; - /* *** v2.5 State variables *** */ - address public feePoolStakingContract; - /* *** V3 State variables *** */ // WORMHOLE Cross-Chain State From bdd1c05a1fd64aef1c0d0c689d1cd5d54626cb85 Mon Sep 17 00:00:00 2001 From: Zaryab Date: Wed, 14 Aug 2024 23:37:45 +0400 Subject: [PATCH 23/23] removed ChatDetails+userChatData --- contracts/PushComm/PushCommEthStorageV2.sol | 1 - contracts/PushComm/PushCommStorageV2.sol | 1 - contracts/libraries/DataTypes.sol | 6 ------ test/gas_snapshots/CommGasSnapshots/CompleteGasReport | 3 +-- 4 files changed, 1 insertion(+), 10 deletions(-) diff --git a/contracts/PushComm/PushCommEthStorageV2.sol b/contracts/PushComm/PushCommEthStorageV2.sol index 4394ae06..0f4a6d4b 100644 --- a/contracts/PushComm/PushCommEthStorageV2.sol +++ b/contracts/PushComm/PushCommEthStorageV2.sol @@ -35,7 +35,6 @@ contract PushCommEthStorageV2 { // New State Variables address public PUSH_TOKEN_ADDRESS; - mapping(address => CommTypes.ChatDetails) public userChatData; mapping(bytes32 => string) public walletToPGP; uint256 FEE_AMOUNT; } diff --git a/contracts/PushComm/PushCommStorageV2.sol b/contracts/PushComm/PushCommStorageV2.sol index 13efa8c8..59659fee 100644 --- a/contracts/PushComm/PushCommStorageV2.sol +++ b/contracts/PushComm/PushCommStorageV2.sol @@ -41,7 +41,6 @@ contract PushCommStorageV2 { // New State Variables IERC20 public PUSH_NTT; - mapping(address => CommTypes.ChatDetails) public userChatData; mapping(bytes32 => string) public walletToPGP; // WORMHOLE CROSS-CHAIN STATE VARIABLES diff --git a/contracts/libraries/DataTypes.sol b/contracts/libraries/DataTypes.sol index 7a31d6b7..c0fa7f03 100644 --- a/contracts/libraries/DataTypes.sol +++ b/contracts/libraries/DataTypes.sol @@ -86,12 +86,6 @@ library CommTypes { ///@notice Maps ID to the Channel mapping(uint256 => address) mapAddressSubscribed; } - - struct ChatDetails { - address requestSender; - uint256 timestamp; - uint256 amountDeposited; - } } library StakingTypes { diff --git a/test/gas_snapshots/CommGasSnapshots/CompleteGasReport b/test/gas_snapshots/CommGasSnapshots/CompleteGasReport index 0120c566..11092109 100644 --- a/test/gas_snapshots/CommGasSnapshots/CompleteGasReport +++ b/test/gas_snapshots/CommGasSnapshots/CompleteGasReport @@ -22,5 +22,4 @@ | subscribeViaCore | 44267 | 109255 | 139166 | 167566 | 432 | | transferPushChannelAdminControl | 7470 | 8332 | 7607 | 10645 | 4 | | unSubscribeViaCore | 4010 | 4010 | 4010 | 4010 | 30 | -| unsubscribeBySig | 9498 | 16569 | 16569 | 23641 | 2 | -| userChatData | 1342 | 4842 | 1342 | 11842 | 3 | \ No newline at end of file +| unsubscribeBySig | 9498 | 16569 | 16569 | 23641 | 2 | \ No newline at end of file