mirror of
https://github.com/lux-amm/v4-periphery.git
synced 2026-10-30 20:54:39 +00:00
133 lines
5.1 KiB
Solidity
133 lines
5.1 KiB
Solidity
// SPDX-License-Identifier: MIT
|
|
pragma solidity ^0.8.17;
|
|
|
|
import {Vm} from "forge-std/Vm.sol";
|
|
import {EIP712} from "openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol";
|
|
import {ECDSA} from "openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol";
|
|
import {IAllowanceTransfer} from "permit2/src/interfaces/IAllowanceTransfer.sol";
|
|
import {ISignatureTransfer} from "permit2/src/interfaces/ISignatureTransfer.sol";
|
|
|
|
/// taken from permit2 utils PermitSignature files
|
|
contract Permit2SignatureHelpers {
|
|
Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
|
|
|
|
bytes32 public constant _PERMIT_DETAILS_TYPEHASH =
|
|
keccak256("PermitDetails(address token,uint160 amount,uint48 expiration,uint48 nonce)");
|
|
|
|
bytes32 public constant _PERMIT_SINGLE_TYPEHASH = keccak256(
|
|
"PermitSingle(PermitDetails details,address spender,uint256 sigDeadline)PermitDetails(address token,uint160 amount,uint48 expiration,uint48 nonce)"
|
|
);
|
|
|
|
bytes32 public constant _PERMIT_BATCH_TYPEHASH = keccak256(
|
|
"PermitBatch(PermitDetails[] details,address spender,uint256 sigDeadline)PermitDetails(address token,uint160 amount,uint48 expiration,uint48 nonce)"
|
|
);
|
|
|
|
function getPermitSignatureRaw(
|
|
IAllowanceTransfer.PermitSingle memory permit,
|
|
uint256 privateKey,
|
|
bytes32 domainSeparator
|
|
) internal pure returns (uint8 v, bytes32 r, bytes32 s) {
|
|
bytes32 permitHash = keccak256(abi.encode(_PERMIT_DETAILS_TYPEHASH, permit.details));
|
|
|
|
bytes32 msgHash = keccak256(
|
|
abi.encodePacked(
|
|
"\x19\x01",
|
|
domainSeparator,
|
|
keccak256(abi.encode(_PERMIT_SINGLE_TYPEHASH, permitHash, permit.spender, permit.sigDeadline))
|
|
)
|
|
);
|
|
|
|
(v, r, s) = vm.sign(privateKey, msgHash);
|
|
}
|
|
|
|
function getPermitSignature(
|
|
IAllowanceTransfer.PermitSingle memory permit,
|
|
uint256 privateKey,
|
|
bytes32 domainSeparator
|
|
) internal pure returns (bytes memory sig) {
|
|
(uint8 v, bytes32 r, bytes32 s) = getPermitSignatureRaw(permit, privateKey, domainSeparator);
|
|
return bytes.concat(r, s, bytes1(v));
|
|
}
|
|
|
|
function getCompactPermitSignature(
|
|
IAllowanceTransfer.PermitSingle memory permit,
|
|
uint256 privateKey,
|
|
bytes32 domainSeparator
|
|
) internal pure returns (bytes memory sig) {
|
|
(uint8 v, bytes32 r, bytes32 s) = getPermitSignatureRaw(permit, privateKey, domainSeparator);
|
|
bytes32 vs;
|
|
(r, vs) = _getCompactSignature(v, r, s);
|
|
return bytes.concat(r, vs);
|
|
}
|
|
|
|
function _getCompactSignature(uint8 vRaw, bytes32 rRaw, bytes32 sRaw)
|
|
internal
|
|
pure
|
|
returns (bytes32 r, bytes32 vs)
|
|
{
|
|
uint8 v = vRaw - 27; // 27 is 0, 28 is 1
|
|
vs = bytes32(uint256(v) << 255) | sRaw;
|
|
return (rRaw, vs);
|
|
}
|
|
|
|
function getPermitBatchSignature(
|
|
IAllowanceTransfer.PermitBatch memory permit,
|
|
uint256 privateKey,
|
|
bytes32 domainSeparator
|
|
) internal pure returns (bytes memory sig) {
|
|
bytes32[] memory permitHashes = new bytes32[](permit.details.length);
|
|
for (uint256 i = 0; i < permit.details.length; ++i) {
|
|
permitHashes[i] = keccak256(abi.encode(_PERMIT_DETAILS_TYPEHASH, permit.details[i]));
|
|
}
|
|
bytes32 msgHash = keccak256(
|
|
abi.encodePacked(
|
|
"\x19\x01",
|
|
domainSeparator,
|
|
keccak256(
|
|
abi.encode(
|
|
_PERMIT_BATCH_TYPEHASH,
|
|
keccak256(abi.encodePacked(permitHashes)),
|
|
permit.spender,
|
|
permit.sigDeadline
|
|
)
|
|
)
|
|
)
|
|
);
|
|
|
|
(uint8 v, bytes32 r, bytes32 s) = vm.sign(privateKey, msgHash);
|
|
return bytes.concat(r, s, bytes1(v));
|
|
}
|
|
|
|
function defaultERC20PermitAllowance(address token0, uint160 amount, uint48 expiration, uint48 nonce)
|
|
internal
|
|
view
|
|
returns (IAllowanceTransfer.PermitSingle memory)
|
|
{
|
|
IAllowanceTransfer.PermitDetails memory details =
|
|
IAllowanceTransfer.PermitDetails({token: token0, amount: amount, expiration: expiration, nonce: nonce});
|
|
return
|
|
IAllowanceTransfer.PermitSingle({
|
|
details: details, spender: address(this), sigDeadline: block.timestamp + 100
|
|
});
|
|
}
|
|
|
|
function defaultERC20PermitBatchAllowance(address[] memory tokens, uint160 amount, uint48 expiration, uint48 nonce)
|
|
internal
|
|
view
|
|
returns (IAllowanceTransfer.PermitBatch memory)
|
|
{
|
|
IAllowanceTransfer.PermitDetails[] memory details = new IAllowanceTransfer.PermitDetails[](tokens.length);
|
|
|
|
for (uint256 i = 0; i < tokens.length; ++i) {
|
|
details[i] = IAllowanceTransfer.PermitDetails({
|
|
token: tokens[i], amount: amount, expiration: expiration, nonce: nonce
|
|
});
|
|
}
|
|
|
|
return
|
|
IAllowanceTransfer.PermitBatch({
|
|
details: details, spender: address(this), sigDeadline: block.timestamp + 100
|
|
});
|
|
}
|
|
}
|