Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding tests for Crosschain_Base and PP_Connext_Crosschain - DRAFT #694

Draft
wants to merge 108 commits into
base: feature/crosschain-paymentProcessor
Choose a base branch
from
Draft
Changes from 1 commit
Commits
Show all changes
108 commits
Select commit Hold shift + click to select a range
dc03239
add cross-chain module, contracts compile
leeftk Oct 30, 2024
b4b0c1f
refactor tempalte module
leeftk Nov 1, 2024
7041fa4
fix compile issues
zzzuhaibmohd Nov 4, 2024
6cd983c
add todo's for implementation contract
leeftk Nov 5, 2024
07e9b81
added notes handoff
leeftk Nov 5, 2024
a12749e
fix compile issues before everclear impl
zzzuhaibmohd Nov 5, 2024
793d8a7
add everclear poc impl
zzzuhaibmohd Nov 5, 2024
af340d1
add everclear logic impl
zzzuhaibmohd Nov 7, 2024
b565de2
remove old templates
leeftk Nov 7, 2024
7da377d
code compile issue solved
zzzuhaibmohd Nov 7, 2024
865e268
fix minor dependency
zzzuhaibmohd Nov 7, 2024
960fcd2
remove file
zzzuhaibmohd Nov 7, 2024
fc33b2e
added contract for bridge testing
leeftk Nov 8, 2024
7584abb
add tests for base contracts
leeftk Nov 8, 2024
7f20d42
fix file structure
leeftk Nov 8, 2024
5ff8e1c
uncomment bridge return value and run fmt
leeftk Nov 9, 2024
dfdb828
change contract to abstract
leeftk Nov 12, 2024
0fa97c5
add logic to PP_Connext_Crosschain
leeftk Nov 13, 2024
c06d6ec
fix inheritance chain
leeftk Nov 14, 2024
802f3b5
remove function impl
leeftk Nov 15, 2024
e0608ea
seperate interfaces
leeftk Nov 15, 2024
6909a38
remove unecessary state variables
leeftk Nov 18, 2024
54f1eea
remove unecessary state variables
leeftk Nov 18, 2024
09047da
add unit tests for Connext
zzzuhaibmohd Nov 8, 2024
d8f88b9
unit test processPayments & xcall
zzzuhaibmohd Nov 8, 2024
46df46a
fix directory structure
leeftk Nov 12, 2024
a5a10bf
unit test chainid test
zzzuhaibmohd Nov 11, 2024
5a78d5f
unit test processpayments test
zzzuhaibmohd Nov 11, 2024
ac662d5
unit test paymentId check and test
zzzuhaibmohd Nov 11, 2024
4b74169
unit test chainId and ProcessPayment
zzzuhaibmohd Nov 12, 2024
32b2c05
unit test paymentId check and test
zzzuhaibmohd Nov 12, 2024
567815e
resolve conflicts
zzzuhaibmohd Nov 13, 2024
af9df30
add unit test verify bridgeData
zzzuhaibmohd Nov 13, 2024
2c96138
add unit test process payments insufficient balance
zzzuhaibmohd Nov 13, 2024
330cbc2
add feedback comment
leeftk Nov 18, 2024
be2fc27
fixed unit tests after rebase
zzzuhaibmohd Nov 19, 2024
6928ec0
add comments and fuzz tests
leeftk Nov 20, 2024
ca1b6a8
refrator test file and add unit tests
zzzuhaibmohd Nov 20, 2024
3468df9
verify executionData & add unit tests
zzzuhaibmohd Nov 20, 2024
293db4f
add ttl validation
leeftk Nov 21, 2024
e96b3fb
refractor unit tests
zzzuhaibmohd Nov 22, 2024
45816bf
add unit tests CrosschainBase_v1
zzzuhaibmohd Nov 22, 2024
f460be3
singlePayment fuzz tests added
zzzuhaibmohd Nov 25, 2024
c251997
move balance setup internal function
zzzuhaibmohd Nov 25, 2024
01f5ff8
multiplePayment fuzz tests added
zzzuhaibmohd Nov 25, 2024
8e0b414
camelcase changes for CrossChainBase contract
zzzuhaibmohd Nov 26, 2024
6300df5
add gherking comments
leeftk Nov 27, 2024
084e594
remove unecessary variables and add comments
leeftk Nov 27, 2024
3fff1b7
add more gherkin to each test
leeftk Nov 27, 2024
8fc2cd8
add validation of ttl
leeftk Nov 27, 2024
d3d0af3
add getbridgedata and natspec
leeftk Nov 27, 2024
24ba1ce
chore: cleaned code changed event name
leeftk Nov 27, 2024
eb14eeb
add templates folder
leeftk Nov 28, 2024
167f624
emit PaymentProcessed via Interface
zzzuhaibmohd Nov 28, 2024
66f5208
chore: use exposed payment processor
zzzuhaibmohd Nov 28, 2024
bdb3c65
update gherkin for tests
leeftk Dec 9, 2024
ee1e448
add assertions to payment processor test
leeftk Dec 9, 2024
918b836
update gherkin and remove vs code settings
leeftk Dec 9, 2024
3c98fa7
feat: add cancel payments
leeftk Dec 11, 2024
855f6f2
feat:add cancel payment & test
leeftk Dec 12, 2024
d64d977
feat:add retry payments & test
leeftk Dec 12, 2024
cedbb59
fix:retry payments test
leeftk Dec 12, 2024
f1e0e69
fix:format
leeftk Dec 12, 2024
a15150f
fix:fmt and standard updates
leeftk Dec 12, 2024
c3fbdf8
chore:delete bridging folder
leeftk Dec 13, 2024
197a65a
fix:rebase onto feature
leeftk Dec 17, 2024
90615c2
chore:remove redundant files
leeftk Dec 17, 2024
8f34e00
fix:add standard to test file
leeftk Dec 17, 2024
18aa1f4
chore:remove redundant files
leeftk Dec 17, 2024
102cbd4
fix:update crosschain base format
leeftk Dec 17, 2024
b93500c
fix:delete console import
leeftk Dec 17, 2024
9bdbf8a
fix:move files to proper directories
leeftk Dec 17, 2024
d6bdba6
fix:remove impl for functions
leeftk Jan 6, 2025
bd55516
fix: fix retry failed payments
leeftk Jan 6, 2025
ed26634
chore:add comments for clarity
leeftk Jan 6, 2025
81e4275
fix:remove files
leeftk Jan 7, 2025
54e595f
add tests for unhappy paths
leeftk Jan 7, 2025
a22d76b
chore:change mapping name
leeftk Jan 7, 2025
d986ff1
remove redundant file
leeftk Jan 7, 2025
c9a9d9a
chore:rename file
leeftk Jan 7, 2025
e17ae52
add base test file
leeftk Jan 7, 2025
a3d5311
fix: remove chainid impl
zzzuhaibmohd Jan 13, 2025
6d0378c
chore: add unit tests
zzzuhaibmohd Jan 13, 2025
f4164af
chore: add unit tests
zzzuhaibmohd Jan 16, 2025
89184cd
fix: make unit tests generic input
zzzuhaibmohd Jan 16, 2025
3e76524
fix: process payment if else
zzzuhaibmohd Jan 17, 2025
3a753d4
chore: add unit tests for PP_Crosschain_v1
zzzuhaibmohd Jan 20, 2025
7adcca7
fix: add auth checks and retrypayment issue and format unit tests
zzzuhaibmohd Jan 23, 2025
238254c
fix: change test to fuzz tests, fix minor bugs
zzzuhaibmohd Jan 24, 2025
e7d0660
fix: code format invertor standard
zzzuhaibmohd Jan 24, 2025
002b3f6
fix: change the _validateTransferRequest msg.sender to client
zzzuhaibmohd Jan 27, 2025
4e5b488
fix: refractor the unit tests
zzzuhaibmohd Jan 29, 2025
d400668
chore: add unit tests for client.amountPaid functionality
zzzuhaibmohd Feb 7, 2025
a3564ea
fix: track processedIntentId fix
zzzuhaibmohd Feb 12, 2025
b4d9f77
feat: add unclaimed amount impl
zzzuhaibmohd Feb 13, 2025
85ca775
fix: format code
zzzuhaibmohd Feb 13, 2025
8a406cd
fix: follow invertor standard
zzzuhaibmohd Feb 17, 2025
baf13d7
Merge remote-tracking branch 'upstream/feature/crosschain-paymentProc…
Zitzak Feb 19, 2025
289221e
Merge remote-tracking branch 'upstream/feature/crosschain-paymentProc…
Zitzak Feb 19, 2025
377f888
refactor: Rename ERC20PaymentClientBase_v1 to v2
Zitzak Feb 19, 2025
6c351c8
refactor: adapt implementation and tests to new Payment order struct
Zitzak Feb 19, 2025
27dd77c
feat(IERC20PaymentClientBase_v2): add maxFee and TTL to payment order…
Zitzak Feb 19, 2025
e53ebb5
refactor: CrossChainBase_v1 & ICrossChainBase_v1
Zitzak Feb 19, 2025
7dfb039
refactor: PP_Crosschain_v1 & IPP_Crosschain_v1
Zitzak Feb 19, 2025
b9e7168
refactor: PP_Connext_Crosschain_v1 & IPP_Connext_Crosschain_v1
Zitzak Feb 19, 2025
a3534bb
test: WIP
Zitzak Feb 19, 2025
db1ec3e
fix: code refactor & fix unit tests
zzzuhaibmohd Feb 24, 2025
34961e1
fix: code refactor & fix unit tests
zzzuhaibmohd Feb 25, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fix:retry payments test
leeftk committed Dec 17, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
commit cedbb592fe14075965c18b276490ec940d8281a9
239 changes: 118 additions & 121 deletions src/modules/paymentProcessor/PP_Connext_Crosschain_v1.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {console} from "forge-std/console.sol";
// External Imports
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// External Imports
// External

import {IERC20} from "@oz/token/ERC20/IERC20.sol";
import {Module_v1} from "src/modules/base/Module_v1.sol";

// Internal Imports
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Internal Imports
// Internal

import {CrossChainBase_v1} from
"src/modules/paymentProcessor/abstracts/CrossChainBase_v1.sol";
import {ICrossChainBase_v1} from
@@ -9,15 +14,13 @@ import {IPP_Connext_Crosschain_v1} from
"src/modules/paymentProcessor/interfaces/IPP_Connext_Crosschain_v1.sol";
import {IERC20PaymentClientBase_v1} from
"@lm/interfaces/IERC20PaymentClientBase_v1.sol";
import {IERC20} from "@oz/token/ERC20/IERC20.sol";
import {PP_Crosschain_v1} from
"src/modules/paymentProcessor/abstracts/PP_Crosschain_v1.sol";
import {IWETH} from "src/modules/paymentProcessor/interfaces/IWETH.sol";
import {IEverclearSpoke} from
"src/modules/paymentProcessor/interfaces/IEverclear.sol";
import {IOrchestrator_v1} from
"src/orchestrator/interfaces/IOrchestrator_v1.sol";
import {Module_v1} from "src/modules/base/Module_v1.sol";

/**
* @title Connext Cross-chain Payment Processor
@@ -35,28 +38,35 @@ import {Module_v1} from "src/modules/base/Module_v1.sol";
* @custom:security-contact [email protected]
* In case of any concerns or findings, please refer to our Security Policy
* at security.inverter.network
*
* @custom:version 1.0.0
* @custom:standard-version 1.0.0
* @author Inverter Network
*/
contract PP_Connext_Crosschain_v1 is PP_Crosschain_v1 {
// Storage Variables
IEverclearSpoke public everClearSpoke;
IWETH public weth;

error FailedTransfer();

/// @dev Tracks all details for all payment orders of a paymentReceiver for a specific paymentClient.
/// paymentClient => paymentReceiver => intentId.
/// @dev Tracks all details for all payment orders of a paymentReceiver for a specific paymentClient.
/// paymentClient => paymentReceiver => intentId.
mapping(
address paymentClient => mapping(address recipient => bytes32 intentId)
) public intentId;

/// @dev Tracks failed transfers that can be retried
/// paymentClient => recipient => intentId => amount
/// paymentClient => recipient => intentId => amount
mapping(
address paymentClient
=> mapping(
address recipient => mapping(bytes32 intentId => uint amount)
)
) public failedTransfers;

// Errors
error FailedTransfer();

// External Functions
/// @notice Initializes the payment processor module
/// @param orchestrator_ The address of the orchestrator contract
/// @param metadata Module metadata
@@ -74,42 +84,6 @@ contract PP_Connext_Crosschain_v1 is PP_Crosschain_v1 {
weth = IWETH(weth_);
}

/// @notice Retrieves the bridge data for a specific payment ID
/// @param paymentId The unique identifier of the payment
/// @return The bridge data associated with the payment (encoded intentId)
function getBridgeData(uint paymentId)
public
view
override
returns (bytes memory)
{
return _bridgeData[paymentId];
}

/// @notice Execute the cross-chain bridge transfer
/// @dev Override this function to implement specific bridge logic
/// @param order The payment order containing all necessary transfer details
/// @return bridgeData Arbitrary data returned by the bridge implementation
function _executeBridgeTransfer(
IERC20PaymentClientBase_v1.PaymentOrder memory order,
bytes memory executionData,
address client
) internal returns (bytes memory) {
bytes32 _intentId = createCrossChainIntent(order, executionData);
if (_intentId == bytes32(0)) {
// Track failed transfer
failedTransfers[client][order.recipient][_intentId] = order.amount;
emit TransferFailed(
client, order.recipient, _intentId, order.amount
);

// revert Module__PP_Crosschain__MessageDeliveryFailed(
// 8453, 8453, executionData
// );
}
return abi.encode(_intentId);
}

/// @notice Processes multiple payment orders through the bridge
/// @param client The payment client contract interface
/// @param executionData Additional data needed for execution (encoded maxFee and TTL)
@@ -143,51 +117,113 @@ contract PP_Connext_Crosschain_v1 is PP_Crosschain_v1 {
}
}

/// @notice Executes a cross-chain transfer through the Connext bridge
/// @param order The payment order to be processed
/// @param executionData Encoded data containing maxFee and TTL for the transfer
/// @return intentId The unique identifier for the cross-chain transfer
/// @notice Cancels a pending transfer and returns funds to the client
/// @param client The payment client address
/// @param recipient The recipient address
/// @param pendingIntentId The intentId to cancel
function cancelTransfer(
address client,
address recipient,
bytes32 pendingIntentId,
IERC20PaymentClientBase_v1.PaymentOrder memory order
) external {
_validateTransferRequest(client, recipient, pendingIntentId);
_cleanupFailedTransfer(client, recipient, pendingIntentId);
//Set approval to 0
IERC20(order.paymentToken).approve(address(everClearSpoke), 0);
// Just do the transfer inline
if (!IERC20(order.paymentToken).transfer(recipient, order.amount)) {
revert FailedTransfer();
}

emit TransferCancelled(client, recipient, pendingIntentId, order.amount);
}

function retryFailedTransfer(
address client,
address recipient,
bytes32 pendingIntentId,
IERC20PaymentClientBase_v1.PaymentOrder memory order,
bytes memory executionData
) external {
_validateTransferRequest(client, recipient, pendingIntentId);

bytes32 newIntentId = createCrossChainIntent(order, executionData);
if (newIntentId == bytes32(0)) {
revert Module__PP_Crosschain__MessageDeliveryFailed(
8453, 8453, executionData
);
}

_cleanupFailedTransfer(client, recipient, pendingIntentId);
intentId[client][recipient] = newIntentId;
}

// Public Functions
/// @notice Retrieves the bridge data for a specific payment ID
/// @param paymentId The unique identifier of the payment
/// @return The bridge data associated with the payment (encoded intentId)
function getBridgeData(uint paymentId)
public
view
override
returns (bytes memory)
{
return _bridgeData[paymentId];
}

// Internal Functions
/// @notice Execute the cross-chain bridge transfer
/// @dev Override this function to implement specific bridge logic
/// @param order The payment order containing all necessary transfer details
/// @return bridgeData Arbitrary data returned by the bridge implementation
function _executeBridgeTransfer(
IERC20PaymentClientBase_v1.PaymentOrder memory order,
bytes memory executionData,
address client
) internal returns (bytes memory) {
bytes32 _intentId = createCrossChainIntent(order, executionData);

if (_intentId == bytes32(0)) {
failedTransfers[client][order.recipient][_intentId] = order.amount;
intentId[client][order.recipient] = _intentId;
emit TransferFailed(
client, order.recipient, _intentId, order.amount
);
}

return abi.encode(_intentId);
}

function createCrossChainIntent(
IERC20PaymentClientBase_v1.PaymentOrder memory order,
bytes memory executionData
) internal returns (bytes32) {
_validateOrder(order);

if (executionData.length == 0) {
revert
ICrossChainBase_v1
.Module__CrossChainBase_InvalidExecutionData();
}
if (order.amount == 0) {
revert ICrossChainBase_v1.Module__CrossChainBase__InvalidAmount();
}
if (order.recipient == address(0)) {
revert ICrossChainBase_v1.Module__CrossChainBase__InvalidRecipient();
}
// Decode the execution data
(uint maxFee, uint ttl) = abi.decode(executionData, (uint, uint));
if (ttl == 0) {
revert
IPP_Connext_Crosschain_v1
.Module__PP_Connext_Crosschain__InvalidTTL();
}

// Wrap ETH into WETH to send with the xcall
IERC20(order.paymentToken).transferFrom(
msg.sender, address(this), order.amount
);

// This contract approves transfer to EverClearSpoke
IERC20(order.paymentToken).approve(
address(everClearSpoke), order.amount
);

// Create destinations array with the target chain
uint32[] memory destinations = new uint32[](1);
destinations[0] = 8453;
// @note -> hardcode for now -> order.destinationChainId when the
// new struct is created for us

// Call newIntent on the EverClearSpoke contract
(bytes32 intentId) = everClearSpoke.newIntent(
return everClearSpoke.newIntent(
destinations,
order.recipient,
order.paymentToken,
@@ -197,87 +233,48 @@ contract PP_Connext_Crosschain_v1 is PP_Crosschain_v1 {
uint48(ttl),
""
);
return intentId;
}
/// @notice Cancels a pending transfer and returns funds to the client
/// @param client The payment client address
/// @param recipient The recipient address
/// @param pendingIntentId The intentId to cancel

function cancelTransfer(
/// @dev Common validation for transfer-related operations
function _validateTransferRequest(
address client,
address recipient,
bytes32 pendingIntentId,
IERC20PaymentClientBase_v1.PaymentOrder memory order
) external {
// Verify the caller is the intended recipient of the transfer
bytes32 pendingIntentId
) internal view returns (uint) {
if (msg.sender != client) {
revert Module__InvalidAddress();
}

// Verify the transfer exists and matches the provided intentId
if (intentId[client][recipient] != pendingIntentId) {
revert Module__PP_Crosschain__InvalidIntentId();
}

// Verify the order details by checking if there's a failed transfer record
uint failedAmount = failedTransfers[client][recipient][pendingIntentId];

if (failedAmount == 0) {
//@audit - change this to something
revert Module__CrossChainBase__InvalidAmount();
}

// Clean up storage
delete intentId[client][recipient];
delete failedTransfers[client][recipient][pendingIntentId];

// // Update client's payment records
// IERC20PaymentClientBase_v1(client).amountPaid(
// order.paymentToken, order.amount
// );

// Transfer tokens to the recipient since they are cancelling their own failed transfer
if (!IERC20(order.paymentToken).transfer(recipient, order.amount)) {
revert FailedTransfer();
}

emit TransferCancelled(client, recipient, pendingIntentId, order.amount);
return failedAmount;
}

function retryFailedTransfer(
/// @dev Helper function to clean up storage after handling a failed transfer
function _cleanupFailedTransfer(
address client,
address recipient,
bytes32 pendingIntentId,
IERC20PaymentClientBase_v1.PaymentOrder memory order,
bytes memory executionData
) external {
//verify the caller is the intended recipient of the transfer
if (msg.sender != client) {
revert Module__InvalidAddress();
}

//verify the transfer exists and matches the provided intentId
if (intentId[client][recipient] != pendingIntentId) {
revert Module__PP_Crosschain__InvalidIntentId();
}
bytes32 pendingIntentId
) internal {
delete intentId[client][recipient];
delete failedTransfers[client][recipient][pendingIntentId];
}

//verify the order details by checking if there's a failed transfer record
uint failedAmount = failedTransfers[client][recipient][pendingIntentId];
if (failedAmount == 0) {
revert Module__CrossChainBase__InvalidAmount();
function _validateOrder(
IERC20PaymentClientBase_v1.PaymentOrder memory order
) internal pure {
if (order.amount == 0) {
revert ICrossChainBase_v1.Module__CrossChainBase__InvalidAmount();
}
//create a new intent with the updated execution data
bytes32 newIntentId = createCrossChainIntent(order, executionData);
if (newIntentId == bytes32(0)) {
revert Module__PP_Crosschain__MessageDeliveryFailed(
8453, 8453, executionData
);
if (order.recipient == address(0)) {
revert ICrossChainBase_v1.Module__CrossChainBase__InvalidRecipient();
}
// delete the failed transfer record
delete failedTransfers[client][recipient][pendingIntentId];

// update the intentId with the new intentId
intentId[client][recipient] = newIntentId;
}
}
Original file line number Diff line number Diff line change
@@ -192,16 +192,21 @@ contract PP_Connext_Crosschain_v1_Test is ModuleTest {
uint96 baseAmount
) public {
// Assumptions to keep the test manageable and within bounds
vm.assume(numRecipients > 0 && numRecipients <= type(uint8).max); // Limit array size
vm.assume(numRecipients > 0 && numRecipients <= 10);
vm.assume(testRecipient != address(0));
vm.assume(baseAmount > 0 && baseAmount <= MINTED_SUPPLY / numRecipients); // Ensure total amount won't exceed MINTED_SUPPLY

// Just make sure baseAmount * numRecipients doesn't exceed MINTED_SUPPLY
vm.assume(
baseAmount > 0 && baseAmount <= MINTED_SUPPLY / (numRecipients * 2)
);

// Setup mock payment orders
address[] memory setupRecipients = new address[](numRecipients);
uint[] memory setupAmounts = new uint[](numRecipients);

for (uint i = 0; i < numRecipients; i++) {
setupRecipients[i] = testRecipient;
// Simple amount calculation without any Math.min nonsense
setupAmounts[i] =
1 + (uint(keccak256(abi.encode(i, baseAmount))) % baseAmount);
}