mirror of
https://github.com/Instadapp/aave-protocol-v2.git
synced 2024-07-29 21:47:30 +00:00
Add permit support in swap adapters
This commit is contained in:
parent
e7183536b3
commit
fa7fa9f948
|
@ -12,6 +12,7 @@ import {ILendingPool} from '../interfaces/ILendingPool.sol';
|
||||||
import {ReserveLogic} from '../libraries/logic/ReserveLogic.sol';
|
import {ReserveLogic} from '../libraries/logic/ReserveLogic.sol';
|
||||||
import {IUniswapV2Router02} from '../interfaces/IUniswapV2Router02.sol';
|
import {IUniswapV2Router02} from '../interfaces/IUniswapV2Router02.sol';
|
||||||
import {IPriceOracleGetter} from '../interfaces/IPriceOracleGetter.sol';
|
import {IPriceOracleGetter} from '../interfaces/IPriceOracleGetter.sol';
|
||||||
|
import {IERC20WithPermit} from '../interfaces/IERC20WithPermit.sol';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @title BaseUniswapAdapter
|
* @title BaseUniswapAdapter
|
||||||
|
@ -25,6 +26,20 @@ contract BaseUniswapAdapter {
|
||||||
|
|
||||||
enum LeftoverAction {DEPOSIT, TRANSFER}
|
enum LeftoverAction {DEPOSIT, TRANSFER}
|
||||||
|
|
||||||
|
struct PermitParams {
|
||||||
|
uint256[] deadline;
|
||||||
|
uint8[] v;
|
||||||
|
bytes32[] r;
|
||||||
|
bytes32[] s;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PermitSignature {
|
||||||
|
uint256 deadline;
|
||||||
|
uint8 v;
|
||||||
|
bytes32 r;
|
||||||
|
bytes32 s;
|
||||||
|
}
|
||||||
|
|
||||||
// Max slippage percent allow by param
|
// Max slippage percent allow by param
|
||||||
uint256 public constant MAX_SLIPPAGE_PERCENT = 3000; // 30%
|
uint256 public constant MAX_SLIPPAGE_PERCENT = 3000; // 30%
|
||||||
// Min slippage percent allow by param
|
// Min slippage percent allow by param
|
||||||
|
@ -221,14 +236,28 @@ contract BaseUniswapAdapter {
|
||||||
* @param reserve address of the asset
|
* @param reserve address of the asset
|
||||||
* @param user address
|
* @param user address
|
||||||
* @param amount of tokens to be transferred to the contract
|
* @param amount of tokens to be transferred to the contract
|
||||||
|
* @param permitSignature struct containing the permit signature
|
||||||
*/
|
*/
|
||||||
function pullAToken(
|
function pullAToken(
|
||||||
address reserve,
|
address reserve,
|
||||||
address user,
|
address user,
|
||||||
uint256 amount
|
uint256 amount,
|
||||||
|
PermitSignature memory permitSignature
|
||||||
) internal {
|
) internal {
|
||||||
address reserveAToken = getAToken(reserve);
|
address reserveAToken = getAToken(reserve);
|
||||||
|
|
||||||
|
if (_usePermit(permitSignature)) {
|
||||||
|
IERC20WithPermit(reserveAToken).permit(
|
||||||
|
user,
|
||||||
|
address(this),
|
||||||
|
amount,
|
||||||
|
permitSignature.deadline,
|
||||||
|
permitSignature.v,
|
||||||
|
permitSignature.r,
|
||||||
|
permitSignature.s
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// transfer from user to adapter
|
// transfer from user to adapter
|
||||||
IERC20(reserveAToken).safeTransferFrom(user, address(this), amount);
|
IERC20(reserveAToken).safeTransferFrom(user, address(this), amount);
|
||||||
|
|
||||||
|
@ -241,15 +270,28 @@ contract BaseUniswapAdapter {
|
||||||
* @param reserve address of the asset
|
* @param reserve address of the asset
|
||||||
* @param user address
|
* @param user address
|
||||||
* @param flashLoanDebt need to be repaid
|
* @param flashLoanDebt need to be repaid
|
||||||
|
* @param permitSignature struct containing the permit signature
|
||||||
*/
|
*/
|
||||||
function pullATokenAndRepayFlashLoan(
|
function pullATokenAndRepayFlashLoan(
|
||||||
address reserve,
|
address reserve,
|
||||||
address user,
|
address user,
|
||||||
uint256 flashLoanDebt
|
uint256 flashLoanDebt,
|
||||||
|
PermitSignature memory permitSignature
|
||||||
) internal {
|
) internal {
|
||||||
pullAToken(reserve, user, flashLoanDebt);
|
pullAToken(reserve, user, flashLoanDebt, permitSignature);
|
||||||
|
|
||||||
// Repay flashloan
|
// Repay flashloan
|
||||||
IERC20(reserve).approve(address(POOL), flashLoanDebt);
|
IERC20(reserve).approve(address(POOL), flashLoanDebt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Tells if the permit method should be called by inspecting if there is a valid signature.
|
||||||
|
* If signature params are set to 0, then permit won't be called.
|
||||||
|
* @param signature struct containing the permit signature
|
||||||
|
* @return whether or not permit should be called
|
||||||
|
*/
|
||||||
|
function _usePermit(PermitSignature memory signature) internal pure returns (bool) {
|
||||||
|
return !(uint256(signature.deadline) == uint256(signature.v) &&
|
||||||
|
uint256(signature.deadline) == 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,12 @@ import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol';
|
||||||
**/
|
**/
|
||||||
contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
|
|
||||||
|
struct SwapParams {
|
||||||
|
address[] assetToSwapToList;
|
||||||
|
uint256 slippage;
|
||||||
|
PermitParams permitParams;
|
||||||
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
ILendingPoolAddressesProvider addressesProvider,
|
ILendingPoolAddressesProvider addressesProvider,
|
||||||
IUniswapV2Router02 uniswapRouter
|
IUniswapV2Router02 uniswapRouter
|
||||||
|
@ -35,6 +41,10 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
* @param params Additional variadic field to include extra params. Expected parameters:
|
* @param params Additional variadic field to include extra params. Expected parameters:
|
||||||
* address[] assetToSwapToList List of the addresses of the reserve to be swapped to and deposited
|
* address[] assetToSwapToList List of the addresses of the reserve to be swapped to and deposited
|
||||||
* uint256 slippage The max slippage percentage allowed for the swap
|
* uint256 slippage The max slippage percentage allowed for the swap
|
||||||
|
* uint256[] deadline List of deadlines for the permit signature
|
||||||
|
* uint8[] v List of v param for the permit signature
|
||||||
|
* bytes32[] r List of r param for the permit signature
|
||||||
|
* bytes32[] s List of s param for the permit signature
|
||||||
*/
|
*/
|
||||||
function executeOperation(
|
function executeOperation(
|
||||||
address[] calldata assets,
|
address[] calldata assets,
|
||||||
|
@ -45,19 +55,46 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
) external override returns (bool) {
|
) external override returns (bool) {
|
||||||
require(msg.sender == address(POOL), "CALLER_MUST_BE_LENDING_POOL");
|
require(msg.sender == address(POOL), "CALLER_MUST_BE_LENDING_POOL");
|
||||||
|
|
||||||
(address[] memory assetToSwapToList, uint256 slippage) = abi.decode(params, (address[], uint256));
|
SwapParams memory decodedParams = _decodeParams(params);
|
||||||
require(slippage < MAX_SLIPPAGE_PERCENT && slippage >= MIN_SLIPPAGE_PERCENT, 'SLIPPAGE_OUT_OF_RANGE');
|
|
||||||
require(assetToSwapToList.length == assets.length, 'INCONSISTENT_PARAMS');
|
require(
|
||||||
|
decodedParams.slippage < MAX_SLIPPAGE_PERCENT && decodedParams.slippage >= MIN_SLIPPAGE_PERCENT,
|
||||||
|
'SLIPPAGE_OUT_OF_RANGE'
|
||||||
|
);
|
||||||
|
|
||||||
|
require(
|
||||||
|
decodedParams.assetToSwapToList.length == assets.length
|
||||||
|
&& assets.length == decodedParams.permitParams.deadline.length
|
||||||
|
&& assets.length == decodedParams.permitParams.v.length
|
||||||
|
&& assets.length == decodedParams.permitParams.r.length
|
||||||
|
&& assets.length == decodedParams.permitParams.s.length,
|
||||||
|
'INCONSISTENT_PARAMS'
|
||||||
|
);
|
||||||
|
|
||||||
for (uint256 i = 0; i < assets.length; i++) {
|
for (uint256 i = 0; i < assets.length; i++) {
|
||||||
uint256 receivedAmount = swapExactTokensForTokens(assets[i], assetToSwapToList[i], amounts[i], slippage);
|
uint256 receivedAmount = swapExactTokensForTokens(
|
||||||
|
assets[i],
|
||||||
|
decodedParams.assetToSwapToList[i],
|
||||||
|
amounts[i],
|
||||||
|
decodedParams.slippage
|
||||||
|
);
|
||||||
|
|
||||||
// Deposit new reserve
|
// Deposit new reserve
|
||||||
IERC20(assetToSwapToList[i]).approve(address(POOL), receivedAmount);
|
IERC20(decodedParams.assetToSwapToList[i]).approve(address(POOL), receivedAmount);
|
||||||
POOL.deposit(assetToSwapToList[i], receivedAmount, initiator, 0);
|
POOL.deposit(decodedParams.assetToSwapToList[i], receivedAmount, initiator, 0);
|
||||||
|
|
||||||
uint256 flashLoanDebt = amounts[i].add(premiums[i]);
|
uint256 flashLoanDebt = amounts[i].add(premiums[i]);
|
||||||
pullATokenAndRepayFlashLoan(assets[i], initiator, flashLoanDebt);
|
pullATokenAndRepayFlashLoan(
|
||||||
|
assets[i],
|
||||||
|
initiator,
|
||||||
|
flashLoanDebt,
|
||||||
|
PermitSignature(
|
||||||
|
decodedParams.permitParams.deadline[i],
|
||||||
|
decodedParams.permitParams.v[i],
|
||||||
|
decodedParams.permitParams.r[i],
|
||||||
|
decodedParams.permitParams.s[i]
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -72,20 +109,32 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
* @param assetToSwapToList List of addresses of the underlying asset to be swap to and deposited
|
* @param assetToSwapToList List of addresses of the underlying asset to be swap to and deposited
|
||||||
* @param amountToSwapList List of amounts to be swapped
|
* @param amountToSwapList List of amounts to be swapped
|
||||||
* @param slippage The max slippage percentage allowed for the swap
|
* @param slippage The max slippage percentage allowed for the swap
|
||||||
|
* uint256[] deadline List of deadlines for the permit signature
|
||||||
|
* uint8[] v List of v param for the permit signature
|
||||||
|
* bytes32[] r List of r param for the permit signature
|
||||||
|
* bytes32[] s List of s param for the permit signature
|
||||||
*/
|
*/
|
||||||
function swapAndDeposit(
|
function swapAndDeposit(
|
||||||
address[] calldata assetToSwapFromList,
|
address[] calldata assetToSwapFromList,
|
||||||
address[] calldata assetToSwapToList,
|
address[] calldata assetToSwapToList,
|
||||||
uint256[] calldata amountToSwapList,
|
uint256[] calldata amountToSwapList,
|
||||||
uint256 slippage
|
uint256 slippage,
|
||||||
|
PermitSignature[] calldata permitParams
|
||||||
) external {
|
) external {
|
||||||
require(
|
require(
|
||||||
assetToSwapFromList.length == assetToSwapToList.length && assetToSwapFromList.length == amountToSwapList.length,
|
assetToSwapFromList.length == assetToSwapToList.length
|
||||||
|
&& assetToSwapFromList.length == amountToSwapList.length
|
||||||
|
&& assetToSwapFromList.length == permitParams.length,
|
||||||
'INCONSISTENT_PARAMS'
|
'INCONSISTENT_PARAMS'
|
||||||
);
|
);
|
||||||
|
|
||||||
for (uint256 i = 0; i < assetToSwapFromList.length; i++) {
|
for (uint256 i = 0; i < assetToSwapFromList.length; i++) {
|
||||||
pullAToken(assetToSwapFromList[i], msg.sender, amountToSwapList[i]);
|
pullAToken(
|
||||||
|
assetToSwapFromList[i],
|
||||||
|
msg.sender,
|
||||||
|
amountToSwapList[i],
|
||||||
|
permitParams[i]
|
||||||
|
);
|
||||||
|
|
||||||
uint256 receivedAmount = swapExactTokensForTokens(
|
uint256 receivedAmount = swapExactTokensForTokens(
|
||||||
assetToSwapFromList[i],
|
assetToSwapFromList[i],
|
||||||
|
@ -99,4 +148,29 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
POOL.deposit(assetToSwapToList[i], receivedAmount, msg.sender, 0);
|
POOL.deposit(assetToSwapToList[i], receivedAmount, msg.sender, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Decodes debt information encoded in flashloan params
|
||||||
|
* @param params Additional variadic field to include extra params. Expected parameters:
|
||||||
|
* address[] assetToSwapToList List of the addresses of the reserve to be swapped to and deposited
|
||||||
|
* uint256 slippage The max slippage percentage allowed for the swap
|
||||||
|
* uint256[] deadline List of deadlines for the permit signature
|
||||||
|
* uint256[] deadline List of deadlines for the permit signature
|
||||||
|
* uint8[] v List of v param for the permit signature
|
||||||
|
* bytes32[] r List of r param for the permit signature
|
||||||
|
* bytes32[] s List of s param for the permit signature
|
||||||
|
* @return SwapParams struct containing decoded params
|
||||||
|
*/
|
||||||
|
function _decodeParams(bytes memory params) internal returns (SwapParams memory) {
|
||||||
|
(
|
||||||
|
address[] memory assetToSwapToList,
|
||||||
|
uint256 slippage,
|
||||||
|
uint256[] memory deadline,
|
||||||
|
uint8[] memory v,
|
||||||
|
bytes32[] memory r,
|
||||||
|
bytes32[] memory s
|
||||||
|
) = abi.decode(params, (address[], uint256, uint256[], uint8[], bytes32[], bytes32[]));
|
||||||
|
|
||||||
|
return SwapParams(assetToSwapToList, slippage, PermitParams(deadline, v, r, s));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ contract UniswapRepayAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
LeftoverAction leftOverAction;
|
LeftoverAction leftOverAction;
|
||||||
uint256[] repayAmounts;
|
uint256[] repayAmounts;
|
||||||
uint256[] rateModes;
|
uint256[] rateModes;
|
||||||
|
PermitParams permitParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
@ -46,6 +47,10 @@ contract UniswapRepayAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
* (1) Direct transfer to user
|
* (1) Direct transfer to user
|
||||||
* uint256[] repayAmounts List of amounts of debt to be repaid
|
* uint256[] repayAmounts List of amounts of debt to be repaid
|
||||||
* uint256[] rateModes List of the rate modes of the debt to be repaid
|
* uint256[] rateModes List of the rate modes of the debt to be repaid
|
||||||
|
* uint256[] deadline List of deadlines for the permit signature
|
||||||
|
* uint8[] v List of v param for the permit signature
|
||||||
|
* bytes32[] r List of r param for the permit signature
|
||||||
|
* bytes32[] s List of s param for the permit signature
|
||||||
*/
|
*/
|
||||||
function executeOperation(
|
function executeOperation(
|
||||||
address[] calldata assets,
|
address[] calldata assets,
|
||||||
|
@ -61,7 +66,11 @@ contract UniswapRepayAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
require(
|
require(
|
||||||
assets.length == decodedParams.assetToSwapToList.length
|
assets.length == decodedParams.assetToSwapToList.length
|
||||||
&& assets.length == decodedParams.repayAmounts.length
|
&& assets.length == decodedParams.repayAmounts.length
|
||||||
&& assets.length == decodedParams.rateModes.length,
|
&& assets.length == decodedParams.rateModes.length
|
||||||
|
&& assets.length == decodedParams.permitParams.deadline.length
|
||||||
|
&& assets.length == decodedParams.permitParams.v.length
|
||||||
|
&& assets.length == decodedParams.permitParams.r.length
|
||||||
|
&& assets.length == decodedParams.permitParams.s.length,
|
||||||
'INCONSISTENT_PARAMS');
|
'INCONSISTENT_PARAMS');
|
||||||
|
|
||||||
for (uint256 i = 0; i < assets.length; i++) {
|
for (uint256 i = 0; i < assets.length; i++) {
|
||||||
|
@ -73,7 +82,13 @@ contract UniswapRepayAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
decodedParams.rateModes[i],
|
decodedParams.rateModes[i],
|
||||||
initiator,
|
initiator,
|
||||||
decodedParams.leftOverAction,
|
decodedParams.leftOverAction,
|
||||||
premiums[i]
|
premiums[i],
|
||||||
|
PermitSignature(
|
||||||
|
decodedParams.permitParams.deadline[i],
|
||||||
|
decodedParams.permitParams.v[i],
|
||||||
|
decodedParams.permitParams.r[i],
|
||||||
|
decodedParams.permitParams.s[i]
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,6 +106,7 @@ contract UniswapRepayAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
* @param initiator Address of the user
|
* @param initiator Address of the user
|
||||||
* @param leftOverAction enum indicating what to do with the left over balance from the swap
|
* @param leftOverAction enum indicating what to do with the left over balance from the swap
|
||||||
* @param premium Fee of the flash loan
|
* @param premium Fee of the flash loan
|
||||||
|
* @param permitSignature struct containing the permit signature
|
||||||
*/
|
*/
|
||||||
function _swapAndRepay(
|
function _swapAndRepay(
|
||||||
address assetFrom,
|
address assetFrom,
|
||||||
|
@ -100,7 +116,8 @@ contract UniswapRepayAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
uint256 rateMode,
|
uint256 rateMode,
|
||||||
address initiator,
|
address initiator,
|
||||||
LeftoverAction leftOverAction,
|
LeftoverAction leftOverAction,
|
||||||
uint256 premium
|
uint256 premium,
|
||||||
|
PermitSignature memory permitSignature
|
||||||
) internal {
|
) internal {
|
||||||
swapTokensForExactTokens(assetFrom, assetTo, amount, repayAmount);
|
swapTokensForExactTokens(assetFrom, assetTo, amount, repayAmount);
|
||||||
|
|
||||||
|
@ -109,7 +126,7 @@ contract UniswapRepayAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
POOL.repay(assetTo, repayAmount, rateMode, initiator);
|
POOL.repay(assetTo, repayAmount, rateMode, initiator);
|
||||||
|
|
||||||
uint256 flashLoanDebt = amount.add(premium);
|
uint256 flashLoanDebt = amount.add(premium);
|
||||||
pullATokenAndRepayFlashLoan(assetFrom, initiator, flashLoanDebt);
|
pullATokenAndRepayFlashLoan(assetFrom, initiator, flashLoanDebt, permitSignature);
|
||||||
|
|
||||||
// Take care of reserve leftover from the swap
|
// Take care of reserve leftover from the swap
|
||||||
sendLeftovers(assetFrom, flashLoanDebt, leftOverAction, initiator);
|
sendLeftovers(assetFrom, flashLoanDebt, leftOverAction, initiator);
|
||||||
|
@ -124,6 +141,10 @@ contract UniswapRepayAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
* (1) Direct transfer to user
|
* (1) Direct transfer to user
|
||||||
* uint256[] repayAmounts List of amounts of debt to be repaid
|
* uint256[] repayAmounts List of amounts of debt to be repaid
|
||||||
* uint256[] rateModes List of the rate modes of the debt to be repaid
|
* uint256[] rateModes List of the rate modes of the debt to be repaid
|
||||||
|
* uint256[] deadline List of deadlines for the permit signature
|
||||||
|
* uint8[] v List of v param for the permit signature
|
||||||
|
* bytes32[] r List of r param for the permit signature
|
||||||
|
* bytes32[] s List of s param for the permit signature
|
||||||
* @return RepayParams struct containing decoded params
|
* @return RepayParams struct containing decoded params
|
||||||
*/
|
*/
|
||||||
function _decodeParams(bytes memory params) internal returns (RepayParams memory) {
|
function _decodeParams(bytes memory params) internal returns (RepayParams memory) {
|
||||||
|
@ -131,9 +152,24 @@ contract UniswapRepayAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
address[] memory assetToSwapToList,
|
address[] memory assetToSwapToList,
|
||||||
LeftoverAction leftOverAction,
|
LeftoverAction leftOverAction,
|
||||||
uint256[] memory repayAmounts,
|
uint256[] memory repayAmounts,
|
||||||
uint256[] memory rateModes
|
uint256[] memory rateModes,
|
||||||
) = abi.decode(params, (address[], LeftoverAction, uint256[], uint256[]));
|
uint256[] memory deadline,
|
||||||
|
uint8[] memory v,
|
||||||
|
bytes32[] memory r,
|
||||||
|
bytes32[] memory s
|
||||||
|
) = abi.decode(params, (address[], LeftoverAction, uint256[], uint256[], uint256[], uint8[], bytes32[], bytes32[]));
|
||||||
|
|
||||||
return RepayParams(assetToSwapToList, leftOverAction, repayAmounts, rateModes);
|
return RepayParams(
|
||||||
|
assetToSwapToList,
|
||||||
|
leftOverAction,
|
||||||
|
repayAmounts,
|
||||||
|
rateModes,
|
||||||
|
PermitParams(
|
||||||
|
deadline,
|
||||||
|
v,
|
||||||
|
r,
|
||||||
|
s
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
16
contracts/interfaces/IERC20WithPermit.sol
Normal file
16
contracts/interfaces/IERC20WithPermit.sol
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
// SPDX-License-Identifier: agpl-3.0
|
||||||
|
pragma solidity ^0.6.8;
|
||||||
|
|
||||||
|
import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol';
|
||||||
|
|
||||||
|
interface IERC20WithPermit is IERC20 {
|
||||||
|
function permit(
|
||||||
|
address owner,
|
||||||
|
address spender,
|
||||||
|
uint256 value,
|
||||||
|
uint256 deadline,
|
||||||
|
uint8 v,
|
||||||
|
bytes32 r,
|
||||||
|
bytes32 s
|
||||||
|
) external;
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user