-
Notifications
You must be signed in to change notification settings - Fork 505
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
581d96d
commit 324976e
Showing
9 changed files
with
265 additions
and
0 deletions.
There are no files selected for viewing
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 |
---|---|---|
@@ -0,0 +1,33 @@ | ||
// SPDX-License-Identifier: GPL-2.0-or-later | ||
pragma solidity ^0.8.19; | ||
|
||
import {IMulticall} from "../interfaces/IMulticall.sol"; | ||
|
||
/// @title Multicall | ||
/// @notice Enables calling multiple methods in a single call to the contract | ||
abstract contract Multicall is IMulticall { | ||
/// @inheritdoc IMulticall | ||
function multicall(bytes[] calldata data) public payable override returns (bytes[] memory results) { | ||
results = new bytes[](data.length); | ||
for (uint256 i = 0; i < data.length; i++) { | ||
(bool success, bytes memory result) = address(this).delegatecall(data[i]); | ||
|
||
if (!success) { | ||
// handle custom errors | ||
if (result.length == 4) { | ||
assembly { | ||
revert(add(result, 0x20), mload(result)) | ||
} | ||
} | ||
// Next 5 lines from https://ethereum.stackexchange.com/a/83577 | ||
if (result.length < 68) revert(); | ||
assembly { | ||
result := add(result, 0x04) | ||
} | ||
revert(abi.decode(result, (string))); | ||
} | ||
|
||
results[i] = result; | ||
} | ||
} | ||
} |
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 |
---|---|---|
@@ -0,0 +1,41 @@ | ||
// SPDX-License-Identifier: UNLICENSED | ||
pragma solidity ^0.8.19; | ||
|
||
import {ERC20} from "solmate/tokens/ERC20.sol"; | ||
import {Currency, CurrencyLibrary} from "@uniswap/v4-core/contracts/types/Currency.sol"; | ||
import {SafeTransferLib} from "solmate/utils/SafeTransferLib.sol"; | ||
import {IPeripheryPayments} from "../interfaces/IPeripheryPayments.sol"; | ||
|
||
abstract contract PeripheryPayments is IPeripheryPayments { | ||
using CurrencyLibrary for Currency; | ||
using SafeTransferLib for address; | ||
using SafeTransferLib for ERC20; | ||
|
||
error InsufficientToken(); | ||
error NativeTokenTransferFrom(); | ||
|
||
/// @inheritdoc IPeripheryPayments | ||
function sweepToken(Currency currency, uint256 amountMinimum, address recipient) public payable override { | ||
uint256 balanceCurrency = currency.balanceOfSelf(); | ||
if (balanceCurrency < amountMinimum) revert InsufficientToken(); | ||
|
||
if (balanceCurrency > 0) { | ||
currency.transfer(recipient, balanceCurrency); | ||
} | ||
} | ||
|
||
/// @param currency The currency to pay | ||
/// @param payer The entity that must pay | ||
/// @param recipient The entity that will receive payment | ||
/// @param value The amount to pay | ||
function pay(Currency currency, address payer, address recipient, uint256 value) internal { | ||
if (payer == address(this)) { | ||
// pay with tokens already in the contract (for the exact input multihop case) | ||
currency.transfer(recipient, value); | ||
} else { | ||
if (currency.isNative()) revert NativeTokenTransferFrom(); | ||
// pull payment | ||
ERC20(Currency.unwrap(currency)).safeTransferFrom(payer, recipient, value); | ||
} | ||
} | ||
} |
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 |
---|---|---|
@@ -0,0 +1,11 @@ | ||
// SPDX-License-Identifier: UNLICENSED | ||
pragma solidity ^0.8.19; | ||
|
||
abstract contract PeripheryValidation { | ||
error TransactionTooOld(); | ||
|
||
modifier checkDeadline(uint256 deadline) { | ||
if (block.timestamp > deadline) revert TransactionTooOld(); | ||
_; | ||
} | ||
} |
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 |
---|---|---|
@@ -0,0 +1,52 @@ | ||
// SPDX-License-Identifier: UNLICENSED | ||
pragma solidity ^0.8.19; | ||
|
||
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; | ||
import {IERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol"; | ||
|
||
import {IERC20PermitAllowed} from "../interfaces/external/IERC20PermitAllowed.sol"; | ||
import {ISelfPermit} from "../interfaces/ISelfPermit.sol"; | ||
|
||
/// @title Self Permit | ||
/// @notice Functionality to call permit on any EIP-2612-compliant token for use in the route | ||
/// @dev These functions are expected to be embedded in multicalls to allow EOAs to approve a contract and call a function | ||
/// that requires an approval in a single transaction. | ||
abstract contract SelfPermit is ISelfPermit { | ||
/// @inheritdoc ISelfPermit | ||
function selfPermit(address token, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) | ||
public | ||
payable | ||
override | ||
{ | ||
IERC20Permit(token).permit(msg.sender, address(this), value, deadline, v, r, s); | ||
} | ||
|
||
/// @inheritdoc ISelfPermit | ||
function selfPermitIfNecessary(address token, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) | ||
external | ||
payable | ||
override | ||
{ | ||
if (IERC20(token).allowance(msg.sender, address(this)) < value) selfPermit(token, value, deadline, v, r, s); | ||
} | ||
|
||
/// @inheritdoc ISelfPermit | ||
function selfPermitAllowed(address token, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) | ||
public | ||
payable | ||
override | ||
{ | ||
IERC20PermitAllowed(token).permit(msg.sender, address(this), nonce, expiry, true, v, r, s); | ||
} | ||
|
||
/// @inheritdoc ISelfPermit | ||
function selfPermitAllowedIfNecessary(address token, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) | ||
external | ||
payable | ||
override | ||
{ | ||
if (IERC20(token).allowance(msg.sender, address(this)) < type(uint256).max) { | ||
selfPermitAllowed(token, nonce, expiry, v, r, s); | ||
} | ||
} | ||
} |
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 |
---|---|---|
@@ -0,0 +1,12 @@ | ||
// SPDX-License-Identifier: UNLICENSED | ||
pragma solidity ^0.8.19; | ||
|
||
/// @title Multicall interface | ||
/// @notice Enables calling multiple methods in a single call to the contract | ||
interface IMulticall { | ||
/// @notice Call multiple functions in the current contract and return the data from all of them if they all succeed | ||
/// @dev The `msg.value` should not be trusted for any method callable from multicall. | ||
/// @param data The encoded function data for each of the calls to make to this contract | ||
/// @return results The results from each of the calls passed in via data | ||
function multicall(bytes[] calldata data) external payable returns (bytes[] memory results); | ||
} |
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 |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// SPDX-License-Identifier: UNLICENSED | ||
pragma solidity ^0.8.19; | ||
|
||
import {Currency} from "@uniswap/v4-core/contracts/types/Currency.sol"; | ||
|
||
/// @title Periphery Payments | ||
/// @notice Functions to ease deposits and withdrawals of ETH | ||
interface IPeripheryPayments { | ||
// TODO: figure out if we still need unwrapWETH9 from v3? | ||
|
||
/// @notice Transfers the full amount of a token held by this contract to recipient | ||
/// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users | ||
/// @param currency The contract address of the token which will be transferred to `recipient` | ||
/// @param amountMinimum The minimum amount of token required for a transfer | ||
/// @param recipient The destination address of the token | ||
function sweepToken(Currency currency, uint256 amountMinimum, address recipient) external payable; | ||
} |
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 |
---|---|---|
@@ -0,0 +1,56 @@ | ||
// SPDX-License-Identifier: UNLICENSED | ||
pragma solidity >=0.5.0; | ||
|
||
/// @title Self Permit | ||
/// @notice Functionality to call permit on any EIP-2612-compliant token for use in the route | ||
interface ISelfPermit { | ||
/// @notice Permits this contract to spend a given token from `msg.sender` | ||
/// @dev The `owner` is always msg.sender and the `spender` is always address(this). | ||
/// @param token The address of the token spent | ||
/// @param value The amount that can be spent of token | ||
/// @param deadline A timestamp, the current blocktime must be less than or equal to this timestamp | ||
/// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s` | ||
/// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s` | ||
/// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v` | ||
function selfPermit(address token, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) | ||
external | ||
payable; | ||
|
||
/// @notice Permits this contract to spend a given token from `msg.sender` | ||
/// @dev The `owner` is always msg.sender and the `spender` is always address(this). | ||
/// Can be used instead of #selfPermit to prevent calls from failing due to a frontrun of a call to #selfPermit | ||
/// @param token The address of the token spent | ||
/// @param value The amount that can be spent of token | ||
/// @param deadline A timestamp, the current blocktime must be less than or equal to this timestamp | ||
/// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s` | ||
/// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s` | ||
/// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v` | ||
function selfPermitIfNecessary(address token, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) | ||
external | ||
payable; | ||
|
||
/// @notice Permits this contract to spend the sender's tokens for permit signatures that have the `allowed` parameter | ||
/// @dev The `owner` is always msg.sender and the `spender` is always address(this) | ||
/// @param token The address of the token spent | ||
/// @param nonce The current nonce of the owner | ||
/// @param expiry The timestamp at which the permit is no longer valid | ||
/// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s` | ||
/// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s` | ||
/// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v` | ||
function selfPermitAllowed(address token, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) | ||
external | ||
payable; | ||
|
||
/// @notice Permits this contract to spend the sender's tokens for permit signatures that have the `allowed` parameter | ||
/// @dev The `owner` is always msg.sender and the `spender` is always address(this) | ||
/// Can be used instead of #selfPermitAllowed to prevent calls from failing due to a frontrun of a call to #selfPermitAllowed. | ||
/// @param token The address of the token spent | ||
/// @param nonce The current nonce of the owner | ||
/// @param expiry The timestamp at which the permit is no longer valid | ||
/// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s` | ||
/// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s` | ||
/// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v` | ||
function selfPermitAllowedIfNecessary(address token, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) | ||
external | ||
payable; | ||
} |
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 |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// SPDX-License-Identifier: UNLICENSED | ||
pragma solidity >=0.5.0; | ||
|
||
/// @title Interface for verifying contract-based account signatures | ||
/// @notice Interface that verifies provided signature for the data | ||
/// @dev Interface defined by EIP-1271 | ||
interface IERC1271 { | ||
/// @notice Returns whether the provided signature is valid for the provided data | ||
/// @dev MUST return the bytes4 magic value 0x1626ba7e when function passes. | ||
/// MUST NOT modify state (using STATICCALL for solc < 0.5, view modifier for solc > 0.5). | ||
/// MUST allow external calls. | ||
/// @param hash Hash of the data to be signed | ||
/// @param signature Signature byte array associated with _data | ||
/// @return magicValue The bytes4 magic value 0x1626ba7e | ||
function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue); | ||
} |
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 |
---|---|---|
@@ -0,0 +1,27 @@ | ||
// SPDX-License-Identifier: UNLICENSED | ||
pragma solidity >=0.5.0; | ||
|
||
/// @title Interface for permit | ||
/// @notice Interface used by DAI/CHAI for permit | ||
interface IERC20PermitAllowed { | ||
/// @notice Approve the spender to spend some tokens via the holder signature | ||
/// @dev This is the permit interface used by DAI and CHAI | ||
/// @param holder The address of the token holder, the token owner | ||
/// @param spender The address of the token spender | ||
/// @param nonce The holder's nonce, increases at each call to permit | ||
/// @param expiry The timestamp at which the permit is no longer valid | ||
/// @param allowed Boolean that sets approval amount, true for type(uint256).max and false for 0 | ||
/// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s` | ||
/// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s` | ||
/// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v` | ||
function permit( | ||
address holder, | ||
address spender, | ||
uint256 nonce, | ||
uint256 expiry, | ||
bool allowed, | ||
uint8 v, | ||
bytes32 r, | ||
bytes32 s | ||
) external; | ||
} |