-
Notifications
You must be signed in to change notification settings - Fork 53
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add permit2 entrypoints to the periphery (#782)
* feat: add permit2 entrypoints to the periphery Signed-off-by: Bennett <[email protected]> * Update test/evm/foundry/local/SpokePoolPeriphery.t.sol * Update SpokePoolPeriphery.t.sol * move permit2 to proxy * fix permit2 Signed-off-by: bennett <[email protected]> * wip: swap arguments refactor Signed-off-by: bennett <[email protected]> * implement isValidSignature Signed-off-by: bennett <[email protected]> * 1271 Signed-off-by: bennett <[email protected]> * simplify isValidSignature Signed-off-by: bennett <[email protected]> * rebase /programs on master Signed-off-by: nicholaspai <[email protected]> * clean up comments * rebase programs * fix: consolidate structs so that permit2 witnesses cover inputs Signed-off-by: bennett <[email protected]> * begin permit2 unit tests Signed-off-by: bennett <[email protected]> * rebase * Update SpokePoolPeriphery.t.sol * move type definitions to interface Signed-off-by: bennett <[email protected]> * fix permit2 test Signed-off-by: bennett <[email protected]> * transfer type tests Signed-off-by: bennett <[email protected]> * rename EIP1271Signature to Permi2Approval Signed-off-by: bennett <[email protected]> --------- Signed-off-by: Bennett <[email protected]> Signed-off-by: bennett <[email protected]> Signed-off-by: nicholaspai <[email protected]> Co-authored-by: nicholaspai <[email protected]> Co-authored-by: nicholaspai <[email protected]>
- Loading branch information
1 parent
3a16809
commit 022a8ec
Showing
6 changed files
with
1,076 additions
and
520 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,32 +5,11 @@ import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; | |
import { IERC20Permit } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol"; | ||
import { IERC20Auth } from "../external/interfaces/IERC20Auth.sol"; | ||
import { SpokePoolV3Periphery } from "../SpokePoolV3Periphery.sol"; | ||
import { PeripherySigningLib } from "../libraries/PeripherySigningLib.sol"; | ||
import { IPermit2 } from "../external/interfaces/IPermit2.sol"; | ||
|
||
interface SpokePoolV3PeripheryProxyInterface { | ||
/** | ||
* @notice Swaps tokens on this chain via specified router before submitting Across deposit atomically. | ||
* Caller can specify their slippage tolerance for the swap and Across deposit params. | ||
* @dev If swapToken or acrossInputToken are the native token for this chain then this function might fail. | ||
* the assumption is that this function will handle only ERC20 tokens. | ||
* @param swapToken Address of the token that will be swapped for acrossInputToken. | ||
* @param acrossInputToken Address of the token that will be bridged via Across as the inputToken. | ||
* @param exchange Address of the exchange contract to call. | ||
* @param routerCalldata ABI encoded function data to call on router. Should form a swap of swapToken for | ||
* enough of acrossInputToken, otherwise this function will revert. | ||
* @param swapTokenAmount Amount of swapToken to swap for a minimum amount of depositData.inputToken. | ||
* @param minExpectedInputTokenAmount Minimum amount of received depositData.inputToken that we'll submit bridge | ||
* deposit with. | ||
* @param depositData Specifies the Across deposit params we'll send after the swap. | ||
*/ | ||
function swapAndBridge( | ||
IERC20 swapToken, | ||
IERC20 acrossInputToken, | ||
address exchange, | ||
bytes calldata routerCalldata, | ||
uint256 swapTokenAmount, | ||
uint256 minExpectedInputTokenAmount, | ||
SpokePoolV3Periphery.DepositData calldata depositData | ||
) external; | ||
function swapAndBridge(SpokePoolV3PeripheryInterface.SwapAndDepositData calldata swapAndDepositData) external; | ||
} | ||
|
||
/** | ||
|
@@ -41,27 +20,75 @@ interface SpokePoolV3PeripheryProxyInterface { | |
* @custom:security-contact [email protected] | ||
*/ | ||
interface SpokePoolV3PeripheryInterface { | ||
/** | ||
* @notice Passthrough function to `depositV3()` on the SpokePool contract. | ||
* @dev Protects the caller from losing their ETH (or other native token) by reverting if the SpokePool address | ||
* they intended to call does not exist on this chain. Because this contract can be deployed at the same address | ||
* everywhere callers should be protected even if the transaction is submitted to an unintended network. | ||
* This contract should only be used for native token deposits, as this problem only exists for native tokens. | ||
* @param recipient Address to receive funds at on destination chain. | ||
* @param inputToken Token to lock into this contract to initiate deposit. | ||
* @param inputAmount Amount of tokens to deposit. | ||
* @param outputAmount Amount of tokens to receive on destination chain. | ||
* @param destinationChainId Denotes network where user will receive funds from SpokePool by a relayer. | ||
* @param quoteTimestamp Timestamp used by relayers to compute this deposit's realizedLPFeePct which is paid | ||
* to LP pool on HubPool. | ||
* @param message Arbitrary data that can be used to pass additional information to the recipient along with the tokens. | ||
* Note: this is intended to be used to pass along instructions for how a contract should use or allocate the tokens. | ||
* @param exclusiveRelayer Address of the relayer who has exclusive rights to fill this deposit. Can be set to | ||
* 0x0 if no period is desired. If so, then must set exclusivityParameter to 0. | ||
* @param exclusivityParameter Timestamp or offset, after which any relayer can fill this deposit. Must set | ||
* to 0 if exclusiveRelayer is set to 0x0, and vice versa. | ||
* @param fillDeadline Timestamp after which this deposit can no longer be filled. | ||
*/ | ||
// Enum describing the method of transferring tokens to an exchange. | ||
enum TransferType { | ||
// Approve the exchange so that it may transfer tokens from this contract. | ||
Approval, | ||
// Transfer tokens to the exchange before calling it in this contract. | ||
Transfer, | ||
// Approve the exchange by authorizing a transfer with Permit2. | ||
Permit2Approval | ||
} | ||
|
||
// Params we'll need caller to pass in to specify an Across Deposit. The input token will be swapped into first | ||
// before submitting a bridge deposit, which is why we don't include the input token amount as it is not known | ||
// until after the swap. | ||
struct BaseDepositData { | ||
// Token deposited on origin chain. | ||
address inputToken; | ||
// Token received on destination chain. | ||
address outputToken; | ||
// Amount of output token to be received by recipient. | ||
uint256 outputAmount; | ||
// The account credited with deposit who can submit speedups to the Across deposit. | ||
address depositor; | ||
// The account that will receive the output token on the destination chain. If the output token is | ||
// wrapped native token, then if this is an EOA then they will receive native token on the destination | ||
// chain and if this is a contract then they will receive an ERC20. | ||
address recipient; | ||
// The destination chain identifier. | ||
uint256 destinationChainId; | ||
// The account that can exclusively fill the deposit before the exclusivity parameter. | ||
address exclusiveRelayer; | ||
// Timestamp of the deposit used by system to charge fees. Must be within short window of time into the past | ||
// relative to this chain's current time or deposit will revert. | ||
uint32 quoteTimestamp; | ||
// The timestamp on the destination chain after which this deposit can no longer be filled. | ||
uint32 fillDeadline; | ||
// The timestamp or offset on the destination chain after which anyone can fill the deposit. A detailed description on | ||
// how the parameter is interpreted by the V3 spoke pool can be found at https://github.com/across-protocol/contracts/blob/fa67f5e97eabade68c67127f2261c2d44d9b007e/contracts/SpokePool.sol#L476 | ||
uint32 exclusivityParameter; | ||
// Data that is forwarded to the recipient if the recipient is a contract. | ||
bytes message; | ||
} | ||
|
||
// Minimum amount of parameters needed to perform a swap on an exchange specified. We include information beyond just the router calldata | ||
// and exchange address so that we may ensure that the swap was performed properly. | ||
struct SwapAndDepositData { | ||
// Deposit data to use when interacting with the Across spoke pool. | ||
BaseDepositData depositData; | ||
// Token to swap. | ||
address swapToken; | ||
// Address of the exchange to use in the swap. | ||
address exchange; | ||
// Method of transferring tokens to the exchange. | ||
TransferType transferType; | ||
// Amount of the token to swap on the exchange. | ||
uint256 swapTokenAmount; | ||
// Minimum output amount of the exchange, and, by extension, the minimum required amount to deposit into an Across spoke pool. | ||
uint256 minExpectedInputTokenAmount; | ||
// The calldata to use when calling the exchange. | ||
bytes routerCalldata; | ||
} | ||
|
||
// Extended deposit data to be used specifically for signing off on periphery deposits. | ||
struct DepositData { | ||
// Deposit data describing the parameters for the V3 Across deposit. | ||
BaseDepositData baseDepositData; | ||
// The precise input amount to deposit into the spoke pool. | ||
uint256 inputAmount; | ||
} | ||
|
||
function deposit( | ||
address recipient, | ||
address inputToken, | ||
|
@@ -75,144 +102,47 @@ interface SpokePoolV3PeripheryInterface { | |
bytes memory message | ||
) external payable; | ||
|
||
/** | ||
* @notice Swaps tokens on this chain via specified router before submitting Across deposit atomically. | ||
* Caller can specify their slippage tolerance for the swap and Across deposit params. | ||
* @dev If msg.value is 0, then this function is only callable by the proxy contract, to protect against | ||
* approval abuse attacks where a user has set an approval on this contract to spend any ERC20 token. | ||
* @dev If swapToken or acrossInputToken are the native token for this chain then this function might fail. | ||
* the assumption is that this function will handle only ERC20 tokens. | ||
* @param swapToken Address of the token that will be swapped for acrossInputToken. | ||
* @param acrossInputToken Address of the token that will be bridged via Across as the inputToken. | ||
* @param exchange Address of the exchange contract to call. | ||
* @param routerCalldata ABI encoded function data to call on router. Should form a swap of swapToken for | ||
* enough of acrossInputToken, otherwise this function will revert. | ||
* @param swapTokenAmount Amount of swapToken to swap for a minimum amount of depositData.inputToken. | ||
* @param minExpectedInputTokenAmount Minimum amount of received depositData.inputToken that we'll submit bridge | ||
* deposit with. | ||
* @param depositData Specifies the Across deposit params we'll send after the swap. | ||
*/ | ||
function swapAndBridge( | ||
IERC20 swapToken, | ||
IERC20 acrossInputToken, | ||
address exchange, | ||
bytes calldata routerCalldata, | ||
uint256 swapTokenAmount, | ||
uint256 minExpectedInputTokenAmount, | ||
SpokePoolV3Periphery.DepositData calldata depositData | ||
) external payable; | ||
function swapAndBridge(SwapAndDepositData calldata swapAndDepositData) external payable; | ||
|
||
/** | ||
* @notice Swaps an EIP-2612 token on this chain via specified router before submitting Across deposit atomically. | ||
* Caller can specify their slippage tolerance for the swap and Across deposit params. | ||
* @dev If swapToken does not implement `permit` to the specifications of EIP-2612, this function will fail. | ||
* @param swapToken Address of the token that will be swapped for acrossInputToken. | ||
* @param acrossInputToken Address of the token that will be bridged via Across as the inputToken. | ||
* @param exchange Address of the exchange contract to call. | ||
* @param routerCalldata ABI encoded function data to call on router. Should form a swap of swapToken for | ||
* enough of acrossInputToken, otherwise this function will revert. | ||
* @param swapTokenAmount Amount of swapToken to swap for a minimum amount of depositData.inputToken. | ||
* @param minExpectedInputTokenAmount Minimum amount of received depositData.inputToken that we'll submit bridge | ||
* deposit with. | ||
* @param depositData Specifies the Across deposit params we'll send after the swap. | ||
* @param deadline Deadline before which the permit signature is valid. | ||
* @param v v of the permit signature. | ||
* @param r r of the permit signature. | ||
* @param s s of the permit signature. | ||
*/ | ||
function swapAndBridgeWithPermit( | ||
IERC20Permit swapToken, | ||
IERC20 acrossInputToken, | ||
address exchange, | ||
bytes calldata routerCalldata, | ||
uint256 swapTokenAmount, | ||
uint256 minExpectedInputTokenAmount, | ||
SpokePoolV3Periphery.DepositData calldata depositData, | ||
SwapAndDepositData calldata swapAndDepositData, | ||
uint256 deadline, | ||
uint8 v, | ||
bytes32 r, | ||
bytes32 s | ||
bytes calldata permitSignature | ||
) external; | ||
|
||
function swapAndBridgeWithPermit2( | ||
address signatureOwner, | ||
SwapAndDepositData calldata swapAndDepositData, | ||
IPermit2.PermitTransferFrom calldata permit, | ||
bytes calldata signature | ||
) external; | ||
|
||
/** | ||
* @notice Swaps an EIP-3009 token on this chain via specified router before submitting Across deposit atomically. | ||
* Caller can specify their slippage tolerance for the swap and Across deposit params. | ||
* @dev If swapToken does not implement `receiveWithAuthorization` to the specifications of EIP-3009, this call will revert. | ||
* @param swapToken Address of the token that will be swapped for acrossInputToken. | ||
* @param acrossInputToken Address of the token that will be bridged via Across as the inputToken. | ||
* @param exchange Address of the exchange contract to call. | ||
* @param routerCalldata ABI encoded function data to call on router. Should form a swap of swapToken for | ||
* enough of acrossInputToken, otherwise this function will revert. | ||
* @param swapTokenAmount Amount of swapToken to swap for a minimum amount of depositData.inputToken. | ||
* @param minExpectedInputTokenAmount Minimum amount of received depositData.inputToken that we'll submit bridge | ||
* deposit with. | ||
* @param depositData Specifies the Across deposit params we'll send after the swap. | ||
* @param validAfter The unix time after which the `receiveWithAuthorization` signature is valid. | ||
* @param validBefore The unix time before which the `receiveWithAuthorization` signature is valid. | ||
* @param nonce Unique nonce used in the `receiveWithAuthorization` signature. | ||
* @param v v of the EIP-3009 signature. | ||
* @param r r of the EIP-3009 signature. | ||
* @param s s of the EIP-3009 signature. | ||
*/ | ||
function swapAndBridgeWithAuthorization( | ||
IERC20Auth swapToken, | ||
IERC20 acrossInputToken, | ||
address exchange, | ||
bytes calldata routerCalldata, | ||
uint256 swapTokenAmount, | ||
uint256 minExpectedInputTokenAmount, | ||
SpokePoolV3Periphery.DepositData calldata depositData, | ||
SwapAndDepositData calldata swapAndDepositData, | ||
uint256 validAfter, | ||
uint256 validBefore, | ||
bytes32 nonce, | ||
uint8 v, | ||
bytes32 r, | ||
bytes32 s | ||
bytes calldata receiveWithAuthSignature | ||
) external; | ||
|
||
/** | ||
* @notice Deposits an EIP-2612 token Across input token into the Spoke Pool contract. | ||
* @dev If `acrossInputToken` does not implement `permit` to the specifications of EIP-2612, this function will fail. | ||
* @param acrossInputToken EIP-2612 compliant token to deposit. | ||
* @param acrossInputAmount Amount of the input token to deposit. | ||
* @param depositData Specifies the Across deposit params to send. | ||
* @param deadline Deadline before which the permit signature is valid. | ||
* @param v v of the permit signature. | ||
* @param r r of the permit signature. | ||
* @param s s of the permit signature. | ||
*/ | ||
function depositWithPermit( | ||
IERC20Permit acrossInputToken, | ||
uint256 acrossInputAmount, | ||
SpokePoolV3Periphery.DepositData calldata depositData, | ||
DepositData calldata depositData, | ||
uint256 deadline, | ||
uint8 v, | ||
bytes32 r, | ||
bytes32 s | ||
bytes calldata permitSignature | ||
) external; | ||
|
||
function depositWithPermit2( | ||
address signatureOwner, | ||
DepositData calldata depositData, | ||
IPermit2.PermitTransferFrom calldata permit, | ||
bytes calldata signature | ||
) external; | ||
|
||
/** | ||
* @notice Deposits an EIP-3009 compliant Across input token into the Spoke Pool contract. | ||
* @dev If `acrossInputToken` does not implement `receiveWithAuthorization` to the specifications of EIP-3009, this call will revert. | ||
* @param acrossInputToken EIP-3009 compliant token to deposit. | ||
* @param acrossInputAmount Amount of the input token to deposit. | ||
* @param depositData Specifies the Across deposit params to send. | ||
* @param validAfter The unix time after which the `receiveWithAuthorization` signature is valid. | ||
* @param validBefore The unix time before which the `receiveWithAuthorization` signature is valid. | ||
* @param nonce Unique nonce used in the `receiveWithAuthorization` signature. | ||
* @param v v of the EIP-3009 signature. | ||
* @param r r of the EIP-3009 signature. | ||
* @param s s of the EIP-3009 signature. | ||
*/ | ||
function depositWithAuthorization( | ||
IERC20Auth acrossInputToken, | ||
uint256 acrossInputAmount, | ||
SpokePoolV3Periphery.DepositData calldata depositData, | ||
DepositData calldata depositData, | ||
uint256 validAfter, | ||
uint256 validBefore, | ||
bytes32 nonce, | ||
uint8 v, | ||
bytes32 r, | ||
bytes32 s | ||
bytes calldata receiveWithAuthSignature | ||
) external; | ||
} |
Oops, something went wrong.