Implementation ERC20 Permit (EIP 2612) compatible with EIP 1271
The best way to implement the new Utils Library of SignatureChecker and the integration with ERC20 Permit, and guarantee compatibility with Smart Contract Wallets
https://docs.openzeppelin.com/contracts/4.x/api/utils#SignatureChecker
Environment
Ethers.js / Hardhart / Node.js / Open Zeppelin Library / ERC20 / Gasless Feature
Details
Proposal a improve and integration of library of open zeppelin for integrating ERC20 Permit EIP 2612 and EIP 1271 for full compatibility with Smart Contract Wallets like Argent, Gnosis Wallets
Code to reproduce
function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual override {
// solhint-disable-next-line not-rely-on-time
require(block.timestamp <= deadline, "ERC20Permit: expired deadline");
bytes32 structHash = keccak256(
abi.encode(
_PERMIT_TYPEHASH,
owner,
spender,
value,
_useNonce(owner),
deadline
)
);
bytes32 hash = _hashTypedDataV4(structHash);
bytes memory signature = rsvToSig(r,s,v);
// address signer = ECDSAUpgradeable.recover(hash, v, r, s);
if (AddressUpgradeable.isContract(owner)) {
try IERC1271Upgradeable(owner).isValidSignature(hash, signature) returns (bytes4 magicValue) {
require(magicValue == IERC1271Upgradeable(owner).isValidSignature.selector, "ERC20Permit: invalid signature");
} catch {
revert("ERC20Permit: invalid signature");
}
} else {
require(ECDSAUpgradeable.recover(hash, v, r, s) == owner , "ERC20Permit: invalid signature");
}
_approve(owner, spender, value);
}
and function for get signature of r,v,s values (ls any best way to do that appreciate the comments)
function rsvToSig(bytes32 _a, bytes32 _b, uint8 _c) public returns (bytes memory){
// string memory str = string(_bytes32);
// TypeError: Explicit type conversion not allowed from "bytes32" to "string storage pointer"
bytes memory bytesArray = new bytes(65);
for (uint256 i; i < 32; i++) {
bytesArray[i] = _a[i];
}
for (uint256 i=32; i < 64; i++) {
bytesArray[i] = _b[i-32];
}
bytes32 b;
assembly { mstore(add(b,32),_c)}
bytesArray[64] = b[31];
console.logBytes32( _a);
console.logBytes32( _b);
console.logUint(_c);
console.logBytes(bytesArray);
return bytesArray;
}