From d9661135a1938c187d647ad22c7a6741d90d720a Mon Sep 17 00:00:00 2001 From: wirew0lf Date: Wed, 20 Mar 2024 17:44:06 +0100 Subject: [PATCH] Add Transfer With Caller function --- CCTPRelayer/src/CCTPRelayer.sol | 25 +++++++++++++++++++ CCTPRelayer/test/CCTPRelayer.t.sol | 39 ++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/CCTPRelayer/src/CCTPRelayer.sol b/CCTPRelayer/src/CCTPRelayer.sol index 802cdb7..515f6d4 100644 --- a/CCTPRelayer/src/CCTPRelayer.sol +++ b/CCTPRelayer/src/CCTPRelayer.sol @@ -64,6 +64,31 @@ contract CCTPRelayer is ICCTPRelayer, Initializable, UUPSUpgradeable, Ownable2St emit PaymentForRelay(nonce, feeAmount); } + function requestCCTPTransferWithCaller( + uint256 transferAmount, + uint32 destinationDomain, + bytes32 mintRecipient, + address burnToken, + uint256 feeAmount, + bytes32 destinationCaller + ) external { + if (transferAmount == 0) revert PaymentCannotBeZero(); + if (feeAmount == 0) revert PaymentCannotBeZero(); + // In order to save gas do the transfer only once, of both transfer amount and fee amount. + if (!usdc.transferFrom(msg.sender, address(this), transferAmount + feeAmount)) revert TransferFailed(); + + // Only give allowance of the transfer amount, as we want the fee amount to stay in the contract. + usdc.approve(address(messenger), transferAmount); + + // Call deposit for burn and save the nonce. + uint64 nonce = messenger.depositForBurnWithCaller( + transferAmount, destinationDomain, mintRecipient, burnToken, destinationCaller + ); + + // As user already paid for the fee we emit the payment event. + emit PaymentForRelay(nonce, feeAmount); + } + function batchReceiveMessage(ICCTPRelayer.ReceiveCall[] memory receiveCalls) external { // Save gas by not retrieving the length on each loop. uint256 length = receiveCalls.length; diff --git a/CCTPRelayer/test/CCTPRelayer.t.sol b/CCTPRelayer/test/CCTPRelayer.t.sol index 5325bfc..9ef1698 100644 --- a/CCTPRelayer/test/CCTPRelayer.t.sol +++ b/CCTPRelayer/test/CCTPRelayer.t.sol @@ -145,6 +145,23 @@ contract CCTPRelayerTest is Test { } } + function test_requestCCTPTransferWithCaller() public { + uint256 length = forks.length; + + uint32[6] memory domains = [uint32(7), 6, 3, 2, 1, 0]; + + for (uint256 i; i < length; ++i) { + uint32 domain; + if (i < 6) { + domain = domains[i]; + } else { + domain = domains[i - 6]; + } + _switchFork(forks[i]); + _requestCCTPTransferWithCaller(domain); + } + } + function test_withdraw() public { uint256 length = forks.length; @@ -180,6 +197,28 @@ contract CCTPRelayerTest is Test { assertEq(usdc.balanceOf(ACTOR_1), 0, "Balance Remaining After Payment"); } + function _requestCCTPTransferWithCaller(uint32 domain) internal { + uint256 transferAmount = 1_000 * 1e6; + uint256 feeAmount = 10 * 1e6; + uint256 amount = transferAmount + feeAmount; + + _dealUSDC(ACTOR_1, amount); + assertEq(usdc.balanceOf(ACTOR_1), amount, "Balance Before Payment is Wrong"); + + bytes32 mintRecipent = bytes32(abi.encodePacked(ACTOR_1)); + + vm.startPrank(ACTOR_1); + usdc.approve(address(relayer), amount); + relayer.requestCCTPTransferWithCaller( + transferAmount, domain, mintRecipent, address(usdc), feeAmount, keccak256(abi.encodePacked("random caller")) + ); + vm.stopPrank(); + + assertEq(usdc.allowance(address(relayer), address(messenger)), 0, "Messenger Allowance Remaining After Payment"); + assertEq(usdc.allowance(ACTOR_1, address(relayer)), 0, "Relayer Allowance Remaining After Payment"); + assertEq(usdc.balanceOf(ACTOR_1), 0, "Balance Remaining After Payment"); + } + function _switchFork(uint256 id) internal { vm.selectFork(id);