Files
v4-periphery/test/shared/Permit2SignatureHelpers.sol

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
});
}
}