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

feat: Delete SwapAndBridge and add submission fees to gasless flow #809

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
01f7e37
feat: add permit2 entrypoints to the periphery
bmzig Nov 29, 2024
c6b08de
Merge branch 'spokepool-periphery-multiple-exchanges' into bz/permit2…
nicholaspai Dec 1, 2024
3542114
Update test/evm/foundry/local/SpokePoolPeriphery.t.sol
nicholaspai Dec 1, 2024
6131d16
Update SpokePoolPeriphery.t.sol
nicholaspai Dec 1, 2024
4262f6e
Merge branch 'spokepool-periphery-multiple-exchanges' into bz/permit2…
nicholaspai Dec 2, 2024
0446725
move permit2 to proxy
nicholaspai Dec 2, 2024
4f3b2d6
fix permit2
bmzig Dec 2, 2024
ff13c12
wip: swap arguments refactor
bmzig Dec 3, 2024
7b6bd44
implement isValidSignature
bmzig Dec 3, 2024
aa31f5b
1271
bmzig Dec 3, 2024
93b90cd
simplify isValidSignature
bmzig Dec 3, 2024
9eda8c3
rebase
nicholaspai Dec 4, 2024
a9f019d
Merge branch 'spokepool-periphery-multiple-exchanges' into bz/permit2…
nicholaspai Dec 4, 2024
761c5f3
rebase /programs on master
nicholaspai Dec 4, 2024
19a38d4
clean up comments
nicholaspai Dec 4, 2024
458f67c
rebase programs
nicholaspai Dec 4, 2024
25366ef
feat: sponsored swap and deposits
bmzig Dec 4, 2024
e5473c5
fix: consolidate structs so that permit2 witnesses cover inputs
bmzig Dec 4, 2024
e116240
begin permit2 unit tests
bmzig Dec 5, 2024
1c42606
wip
nicholaspai Dec 5, 2024
0402a6b
rebase
nicholaspai Dec 5, 2024
9acb4a2
Update SpokePoolPeriphery.t.sol
nicholaspai Dec 5, 2024
1927810
move type definitions to interface
bmzig Dec 5, 2024
7e4611d
fix permit2 test
bmzig Dec 5, 2024
e3cfb18
transfer type tests
bmzig Dec 5, 2024
f773316
rename EIP1271Signature to Permi2Approval
bmzig Dec 6, 2024
40eac15
Merge branch 'bz/permit2Periphery' into bz/gaslessPeriphery
bmzig Dec 6, 2024
4d83179
add mockERC20 which implements permit/receiveWithAuthorization
bmzig Dec 6, 2024
3bc3bc9
update merge and fix EIP712 types
bmzig Dec 17, 2024
735a1b6
add tests for permit, permit2, and receiveWithAuth swaps/deposits
bmzig Dec 17, 2024
eab96ae
add tests for invalid witnesses
bmzig Dec 17, 2024
c633c38
feat: Delete SwapAndBridge and add submission fees to gasless flow
nicholaspai Dec 18, 2024
9d0cc07
Internal refactor
nicholaspai Dec 18, 2024
c32f66d
Merge branch 'spokepool-periphery-multiple-exchanges' of https://gith…
nicholaspai Dec 18, 2024
a742520
Update SpokePoolV3Periphery.sol
nicholaspai Dec 18, 2024
57814a5
Update PeripherySigningLib.sol
nicholaspai Dec 18, 2024
19cdc89
Update SpokePoolV3Periphery.sol
nicholaspai Dec 18, 2024
2ad0887
Update PeripherySigningLib.sol
nicholaspai Dec 19, 2024
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
64 changes: 52 additions & 12 deletions contracts/SpokePoolV3Periphery.sol
Original file line number Diff line number Diff line change
Expand Up @@ -302,15 +302,16 @@ contract SpokePoolV3Periphery is SpokePoolV3PeripheryInterface, Lockable, MultiC
// Load variables used in this function onto the stack.
address _swapToken = swapAndDepositData.swapToken;
uint256 _swapTokenAmount = swapAndDepositData.swapTokenAmount;
uint256 _submissionFeeAmount = swapAndDepositData.submissionFees.amount;
address _submissionFeeRecipient = swapAndDepositData.submissionFees.recipient;
uint256 _pullAmount = _submissionFeeAmount + _swapTokenAmount;

// For permit transactions, we wrap the call in a try/catch block so that the transaction will continue even if the call to
// permit fails. For example, this may be useful if the permit signature, which can be redeemed by anyone, is executed by somebody
// other than this contract.
try
IERC20Permit(_swapToken).permit(signatureOwner, address(this), _swapTokenAmount, deadline, v, r, s)
{} catch {}
IERC20(_swapToken).safeTransferFrom(signatureOwner, address(this), _swapTokenAmount);

try IERC20Permit(_swapToken).permit(signatureOwner, address(this), _pullAmount, deadline, v, r, s) {} catch {}
IERC20(_swapToken).safeTransferFrom(signatureOwner, address(this), _pullAmount);
_paySubmissionFees(_swapToken, _submissionFeeRecipient, _submissionFeeAmount);
// Verify that the signatureOwner signed the input swapAndDepositData.
_validateSignature(
signatureOwner,
Expand All @@ -337,9 +338,10 @@ contract SpokePoolV3Periphery is SpokePoolV3PeripheryInterface, Lockable, MultiC
bytes calldata signature
) external override nonReentrant {
bytes32 witness = PeripherySigningLib.hashSwapAndDepositData(swapAndDepositData);
uint256 _submissionFeeAmount = swapAndDepositData.submissionFees.amount;
IPermit2.SignatureTransferDetails memory transferDetails = IPermit2.SignatureTransferDetails({
to: address(this),
requestedAmount: swapAndDepositData.swapTokenAmount
requestedAmount: swapAndDepositData.swapTokenAmount + _submissionFeeAmount
});

permit2.permitWitnessTransferFrom(
Expand All @@ -350,6 +352,11 @@ contract SpokePoolV3Periphery is SpokePoolV3PeripheryInterface, Lockable, MultiC
PeripherySigningLib.EIP712_SWAP_AND_DEPOSIT_TYPE_STRING,
signature
);
_paySubmissionFees(
swapAndDepositData.swapToken,
swapAndDepositData.submissionFees.recipient,
_submissionFeeAmount
);
_swapAndBridge(swapAndDepositData);
}

Expand All @@ -375,20 +382,26 @@ contract SpokePoolV3Periphery is SpokePoolV3PeripheryInterface, Lockable, MultiC
bytes calldata swapAndDepositDataSignature
) external override nonReentrant {
(bytes32 r, bytes32 s, uint8 v) = PeripherySigningLib.deserializeSignature(receiveWithAuthSignature);
uint256 _submissionFeeAmount = swapAndDepositData.submissionFees.amount;
// While any contract can vacuously implement `transferWithAuthorization` (or just have a fallback),
// if tokens were not sent to this contract, by this call to swapData.swapToken, this function will revert
// when attempting to swap tokens it does not own.
IERC20Auth(address(swapAndDepositData.swapToken)).receiveWithAuthorization(
signatureOwner,
address(this),
swapAndDepositData.swapTokenAmount,
swapAndDepositData.swapTokenAmount + _submissionFeeAmount,
validAfter,
validBefore,
nonce,
v,
r,
s
);
_paySubmissionFees(
swapAndDepositData.swapToken,
swapAndDepositData.submissionFees.recipient,
_submissionFeeAmount
);

// Verify that the signatureOwner signed the input swapAndDepositData.
_validateSignature(
Expand Down Expand Up @@ -419,12 +432,16 @@ contract SpokePoolV3Periphery is SpokePoolV3PeripheryInterface, Lockable, MultiC
// Load variables used in this function onto the stack.
address _inputToken = depositData.baseDepositData.inputToken;
uint256 _inputAmount = depositData.inputAmount;
uint256 _submissionFeeAmount = depositData.submissionFees.amount;
address _submissionFeeRecipient = depositData.submissionFees.recipient;
uint256 _pullAmount = _submissionFeeAmount + _inputAmount;

// For permit transactions, we wrap the call in a try/catch block so that the transaction will continue even if the call to
// permit fails. For example, this may be useful if the permit signature, which can be redeemed by anyone, is executed by somebody
// other than this contract.
try IERC20Permit(_inputToken).permit(signatureOwner, address(this), _inputAmount, deadline, v, r, s) {} catch {}
IERC20(_inputToken).safeTransferFrom(signatureOwner, address(this), _inputAmount);
try IERC20Permit(_inputToken).permit(signatureOwner, address(this), _pullAmount, deadline, v, r, s) {} catch {}
IERC20(_inputToken).safeTransferFrom(signatureOwner, address(this), _pullAmount);
_paySubmissionFees(_inputToken, _submissionFeeRecipient, _submissionFeeAmount);

// Verify that the signatureOwner signed the input depositData.
_validateSignature(signatureOwner, PeripherySigningLib.hashDepositData(depositData), depositDataSignature);
Expand Down Expand Up @@ -460,9 +477,10 @@ contract SpokePoolV3Periphery is SpokePoolV3PeripheryInterface, Lockable, MultiC
bytes calldata signature
) external override nonReentrant {
bytes32 witness = PeripherySigningLib.hashDepositData(depositData);
uint256 _submissionFeeAmount = depositData.submissionFees.amount;
IPermit2.SignatureTransferDetails memory transferDetails = IPermit2.SignatureTransferDetails({
to: address(this),
requestedAmount: depositData.inputAmount
requestedAmount: depositData.inputAmount + _submissionFeeAmount
});

permit2.permitWitnessTransferFrom(
Expand All @@ -473,6 +491,12 @@ contract SpokePoolV3Periphery is SpokePoolV3PeripheryInterface, Lockable, MultiC
PeripherySigningLib.EIP712_DEPOSIT_TYPE_STRING,
signature
);
_paySubmissionFees(
depositData.baseDepositData.inputToken,
depositData.submissionFees.recipient,
_submissionFeeAmount
);

_depositV3(
depositData.baseDepositData.depositor,
depositData.baseDepositData.recipient,
Expand Down Expand Up @@ -511,20 +535,26 @@ contract SpokePoolV3Periphery is SpokePoolV3PeripheryInterface, Lockable, MultiC
) external override nonReentrant {
// Load variables used multiple times onto the stack.
uint256 _inputAmount = depositData.inputAmount;
uint256 _submissionFeeAmount = depositData.submissionFees.amount;

// Redeem the receiveWithAuthSignature.
(bytes32 r, bytes32 s, uint8 v) = PeripherySigningLib.deserializeSignature(receiveWithAuthSignature);
IERC20Auth(depositData.baseDepositData.inputToken).receiveWithAuthorization(
signatureOwner,
address(this),
_inputAmount,
_inputAmount + _submissionFeeAmount,
validAfter,
validBefore,
nonce,
v,
r,
s
);
_paySubmissionFees(
depositData.baseDepositData.inputToken,
depositData.submissionFees.recipient,
_submissionFeeAmount
);

// Verify that the signatureOwner signed the input depositData.
_validateSignature(signatureOwner, PeripherySigningLib.hashDepositData(depositData), depositDataSignature);
Expand Down Expand Up @@ -573,7 +603,7 @@ contract SpokePoolV3Periphery is SpokePoolV3PeripheryInterface, Lockable, MultiC
address signatureOwner,
bytes32 typedDataHash,
bytes calldata signature
) private {
) private view {
if (!SignatureChecker.isValidSignatureNow(signatureOwner, _hashTypedDataV4(typedDataHash), signature))
revert InvalidSignature();
}
Expand Down Expand Up @@ -705,6 +735,16 @@ contract SpokePoolV3Periphery is SpokePoolV3PeripheryInterface, Lockable, MultiC
);
}

function _paySubmissionFees(
address feeToken,
address recipient,
uint256 amount
) private {
if (amount > 0) {
IERC20(feeToken).safeTransfer(recipient, amount);
}
}

/**
* @notice Function to check that the msg.sender is the initialized proxy contract.
*/
Expand Down
Loading
Loading