From ccde60fc3d05473fcf63d8dd5cc5e01fd6b78396 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6ren?= Date: Thu, 16 Nov 2023 18:52:53 -0600 Subject: [PATCH 1/5] Clean up PolygonContractABIs Move commented ABI to new file that is not part of the deployment. --- src/lib/polygon/PolygonContractABIs.full.js | 181 ++++++++++++++++++ src/lib/polygon/PolygonContractABIs.js | 161 ---------------- .../SignPolygonTransactionApi.js | 10 +- 3 files changed, 185 insertions(+), 167 deletions(-) create mode 100644 src/lib/polygon/PolygonContractABIs.full.js diff --git a/src/lib/polygon/PolygonContractABIs.full.js b/src/lib/polygon/PolygonContractABIs.full.js new file mode 100644 index 000000000..3266a464c --- /dev/null +++ b/src/lib/polygon/PolygonContractABIs.full.js @@ -0,0 +1,181 @@ +/* eslint-disable max-len */ +const PolygonContractABIsFull = { // eslint-disable-line no-unused-vars + USDC_CONTRACT_ABI: [ + 'event Approval(address indexed owner, address indexed spender, uint256 value)', + 'event AuthorizationCanceled(address indexed authorizer, bytes32 indexed nonce)', + 'event AuthorizationUsed(address indexed authorizer, bytes32 indexed nonce)', + 'event Blacklisted(address indexed account)', + 'event MetaTransactionExecuted(address userAddress, address relayerAddress, bytes functionSignature)', + 'event Pause()', + 'event RescuerChanged(address indexed newRescuer)', + 'event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole)', + 'event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender)', + 'event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender)', + 'event Transfer(address indexed from, address indexed to, uint256 value)', + 'event UnBlacklisted(address indexed account)', + 'event Unpause()', + 'function APPROVE_WITH_AUTHORIZATION_TYPEHASH() view returns (bytes32)', + 'function BLACKLISTER_ROLE() view returns (bytes32)', + 'function CANCEL_AUTHORIZATION_TYPEHASH() view returns (bytes32)', + 'function DECREASE_ALLOWANCE_WITH_AUTHORIZATION_TYPEHASH() view returns (bytes32)', + 'function DEFAULT_ADMIN_ROLE() view returns (bytes32)', + 'function DEPOSITOR_ROLE() view returns (bytes32)', + 'function DOMAIN_SEPARATOR() view returns (bytes32)', + 'function EIP712_VERSION() view returns (string)', + 'function INCREASE_ALLOWANCE_WITH_AUTHORIZATION_TYPEHASH() view returns (bytes32)', + 'function META_TRANSACTION_TYPEHASH() view returns (bytes32)', + 'function PAUSER_ROLE() view returns (bytes32)', + 'function PERMIT_TYPEHASH() view returns (bytes32)', + 'function RESCUER_ROLE() view returns (bytes32)', + 'function TRANSFER_WITH_AUTHORIZATION_TYPEHASH() view returns (bytes32)', + 'function WITHDRAW_WITH_AUTHORIZATION_TYPEHASH() view returns (bytes32)', + 'function allowance(address owner, address spender) view returns (uint256)', + 'function approve(address spender, uint256 amount) returns (bool)', + 'function approveWithAuthorization(address owner, address spender, uint256 value, uint256 validAfter, uint256 validBefore, bytes32 nonce, uint8 v, bytes32 r, bytes32 s)', + 'function authorizationState(address authorizer, bytes32 nonce) view returns (uint8)', + 'function balanceOf(address account) view returns (uint256)', + 'function blacklist(address account)', + 'function blacklisters() view returns (address[])', + 'function cancelAuthorization(address authorizer, bytes32 nonce, uint8 v, bytes32 r, bytes32 s)', + 'function decimals() view returns (uint8)', + 'function decreaseAllowance(address spender, uint256 subtractedValue) returns (bool)', + 'function decreaseAllowanceWithAuthorization(address owner, address spender, uint256 decrement, uint256 validAfter, uint256 validBefore, bytes32 nonce, uint8 v, bytes32 r, bytes32 s)', + 'function deposit(address user, bytes depositData)', + 'function executeMetaTransaction(address userAddress, bytes functionSignature, bytes32 sigR, bytes32 sigS, uint8 sigV) payable returns (bytes)', + 'function getRoleAdmin(bytes32 role) view returns (bytes32)', + 'function getRoleMember(bytes32 role, uint256 index) view returns (address)', + 'function getRoleMemberCount(bytes32 role) view returns (uint256)', + 'function grantRole(bytes32 role, address account)', + 'function hasRole(bytes32 role, address account) view returns (bool)', + 'function increaseAllowance(address spender, uint256 addedValue) returns (bool)', + 'function increaseAllowanceWithAuthorization(address owner, address spender, uint256 increment, uint256 validAfter, uint256 validBefore, bytes32 nonce, uint8 v, bytes32 r, bytes32 s)', + 'function initialize(string newName, string newSymbol, uint8 newDecimals, address childChainManager)', + 'function initialized() view returns (bool)', + 'function isBlacklisted(address account) view returns (bool)', + 'function name() view returns (string)', + 'function nonces(address owner) view returns (uint256)', + 'function pause()', + 'function paused() view returns (bool)', + 'function pausers() view returns (address[])', + 'function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)', + 'function renounceRole(bytes32 role, address account)', + 'function rescueERC20(address tokenContract, address to, uint256 amount)', + 'function rescuers() view returns (address[])', + 'function revokeRole(bytes32 role, address account)', + 'function symbol() view returns (string)', + 'function totalSupply() view returns (uint256)', + 'function transfer(address recipient, uint256 amount) returns (bool)', + 'function transferFrom(address sender, address recipient, uint256 amount) returns (bool)', + 'function transferWithAuthorization(address from, address to, uint256 value, uint256 validAfter, uint256 validBefore, bytes32 nonce, uint8 v, bytes32 r, bytes32 s)', + 'function unBlacklist(address account)', + 'function unpause()', + 'function updateMetadata(string newName, string newSymbol)', + 'function withdraw(uint256 amount)', + 'function withdrawWithAuthorization(address owner, uint256 value, uint256 validAfter, uint256 validBefore, bytes32 nonce, uint8 v, bytes32 r, bytes32 s)', + ], + + USDC_TRANSFER_CONTRACT_ABI: [ + 'constructor()', + 'event DomainRegistered(bytes32 indexed domainSeparator, bytes domainValue)', + 'event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)', + 'event RequestTypeRegistered(bytes32 indexed typeHash, string typeStr)', + 'function EIP712_DOMAIN_TYPE() view returns (string)', + 'function deposits(address) view returns (uint256)', + 'function domains(bytes32) view returns (bool)', + 'function execute(tuple(address from, address to, uint256 value, uint256 gas, uint256 nonce, bytes data, uint256 validUntil) request, bytes32 domainSeparator, bytes32 requestTypeHash, bytes suffixData, bytes signature) payable returns (bool success, bytes ret)', + 'function getGasAndDataLimits() view returns (tuple(uint256 acceptanceBudget, uint256 preRelayedCallGasLimit, uint256 postRelayedCallGasLimit, uint256 calldataSizeLimit) limits)', + 'function getHubAddr() view returns (address)', + 'function getMinimumRelayFee(tuple(uint256 gasPrice, uint256 pctRelayFee, uint256 baseRelayFee, address relayWorker, address paymaster, address forwarder, bytes paymasterData, uint256 clientId) relayData) view returns (uint256 amount)', + 'function getNonce(address from) view returns (uint256)', + 'function getRelayHubDeposit() view returns (uint256)', + 'function getRequiredRelayFee(tuple(uint256 gasPrice, uint256 pctRelayFee, uint256 baseRelayFee, address relayWorker, address paymaster, address forwarder, bytes paymasterData, uint256 clientId) relayData, bytes4 methodId) view returns (uint256 amount)', + 'function getRequiredRelayGas(bytes4 methodId) view returns (uint256 gas)', + 'function isTrustedForwarder(address forwarder) view returns (bool)', + 'function owner() view returns (address)', + 'function postRelayedCall(bytes context, bool success, uint256 gasUseWithoutPost, tuple(uint256 gasPrice, uint256 pctRelayFee, uint256 baseRelayFee, address relayWorker, address paymaster, address forwarder, bytes paymasterData, uint256 clientId) relayData)', + 'function preRelayedCall(tuple(tuple(address from, address to, uint256 value, uint256 gas, uint256 nonce, bytes data, uint256 validUntil) request, tuple(uint256 gasPrice, uint256 pctRelayFee, uint256 baseRelayFee, address relayWorker, address paymaster, address forwarder, bytes paymasterData, uint256 clientId) relayData) relayRequest, bytes signature, bytes approvalData, uint256 maxPossibleGas) returns (bytes context, bool revertOnRecipientRevert)', + 'function registerDomainSeparator(string name, string version)', + 'function registerRequestType(string typeName, string typeSuffix)', + 'function registerToken(address token, address pool)', + 'function registeredTokenPool(address) view returns (address)', + 'function registeredTokenPoolFee(address token) view returns (uint24 fee)', + 'function renounceOwnership()', + 'function requiredRelayGas() view returns (uint256)', + 'function setGasAndDataLimits(tuple(uint256 acceptanceBudget, uint256 preRelayedCallGasLimit, uint256 postRelayedCallGasLimit, uint256 calldataSizeLimit) limits)', + 'function setMaxRequiredRelayGas(uint256 gas)', + 'function setRelayHub(address hub)', + 'function setRequiredRelayGas(bytes4 methodId, uint256 gas)', + 'function setWrappedChainToken(address _wrappedChainToken)', + 'function transfer(address token, uint256 amount, address target, uint256 fee)', + 'function transferOwnership(address newOwner)', + 'function transferWithApproval(address token, uint256 amount, address target, uint256 fee, uint256 approval, bytes32 sigR, bytes32 sigS, uint8 sigV)', + 'function trustedForwarder() view returns (address forwarder)', + 'function typeHashes(bytes32) view returns (bool)', + 'function uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes _data)', + 'function unregisterToken(address token)', + 'function verify(tuple(address from, address to, uint256 value, uint256 gas, uint256 nonce, bytes data, uint256 validUntil) forwardRequest, bytes32 domainSeparator, bytes32 requestTypeHash, bytes suffixData, bytes signature) view', + 'function versionPaymaster() view returns (string)', + 'function versionRecipient() view returns (string)', + 'function withdraw(uint256 amount, address target)', + 'function withdrawRelayHubDeposit(uint256 amount, address target)', + 'function withdrawToken(address token, uint256 amount, address target)', + 'function wrappedChainToken() view returns (address)', + ], + + USDC_HTLC_CONTRACT_ABI: [ + 'constructor()', + 'event DomainRegistered(bytes32 indexed domainSeparator, bytes domainValue)', + 'event Open(bytes32 indexed id, address token, uint256 amount, address recipient, bytes32 hash, uint256 timeout)', + 'event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)', + 'event Redeem(bytes32 indexed id, bytes32 secret)', + 'event Refund(bytes32 indexed id)', + 'event RequestTypeRegistered(bytes32 indexed typeHash, string typeStr)', + 'function EIP712_DOMAIN_TYPE() view returns (string)', + 'function deposits(address) view returns (uint256)', + 'function domains(bytes32) view returns (bool)', + 'function execute(tuple(address from, address to, uint256 value, uint256 gas, uint256 nonce, bytes data, uint256 validUntil) request, bytes32 domainSeparator, bytes32 requestTypeHash, bytes suffixData, bytes signature) payable returns (bool success, bytes ret)', + 'function getGasAndDataLimits() view returns (tuple(uint256 acceptanceBudget, uint256 preRelayedCallGasLimit, uint256 postRelayedCallGasLimit, uint256 calldataSizeLimit) limits)', + 'function getHubAddr() view returns (address)', + 'function getMinimumRelayFee(tuple(uint256 gasPrice, uint256 pctRelayFee, uint256 baseRelayFee, address relayWorker, address paymaster, address forwarder, bytes paymasterData, uint256 clientId) relayData) view returns (uint256 amount)', + 'function getNonce(address from) view returns (uint256)', + 'function getRelayHubDeposit() view returns (uint256)', + 'function getRequiredRelayFee(tuple(uint256 gasPrice, uint256 pctRelayFee, uint256 baseRelayFee, address relayWorker, address paymaster, address forwarder, bytes paymasterData, uint256 clientId) relayData, bytes4 methodId) view returns (uint256 amount)', + 'function getRequiredRelayGas(bytes4 methodId) view returns (uint256 gas)', + 'function htlcs(bytes32) view returns (address token, uint256 amount, address refund, address recipient, bytes32 hash, uint256 timeout)', + 'function isTrustedForwarder(address forwarder) view returns (bool)', + 'function open(bytes32 id, address token, uint256 amount, address refundAddress, address recipientAddress, bytes32 hash, uint256 timeout, uint256 fee)', + 'function openWithApproval(bytes32 id, address token, uint256 amount, address refundAddress, address recipientAddress, bytes32 hash, uint256 timeout, uint256 fee, uint256 approval, bytes32 sigR, bytes32 sigS, uint8 sigV)', + 'function owner() view returns (address)', + 'function postRelayedCall(bytes context, bool success, uint256 gasUseWithoutPost, tuple(uint256 gasPrice, uint256 pctRelayFee, uint256 baseRelayFee, address relayWorker, address paymaster, address forwarder, bytes paymasterData, uint256 clientId) relayData)', + 'function preRelayedCall(tuple(tuple(address from, address to, uint256 value, uint256 gas, uint256 nonce, bytes data, uint256 validUntil) request, tuple(uint256 gasPrice, uint256 pctRelayFee, uint256 baseRelayFee, address relayWorker, address paymaster, address forwarder, bytes paymasterData, uint256 clientId) relayData) relayRequest, bytes signature, bytes approvalData, uint256 maxPossibleGas) returns (bytes context, bool revertOnRecipientRevert)', + 'function redeem(bytes32 id, address target, bytes32 secret, uint256 fee)', + 'function redeemWithSecretInData(bytes32 id, address target, uint256 fee)', + 'function refund(bytes32 id, address target, uint256 fee)', + 'function registerDomainSeparator(string name, string version)', + 'function registerRequestType(string typeName, string typeSuffix)', + 'function registerToken(address token, address pool)', + 'function registeredTokenPool(address) view returns (address)', + 'function registeredTokenPoolFee(address token) view returns (uint24 fee)', + 'function relayWithoutGsn(tuple(tuple(address from, address to, uint256 value, uint256 gas, uint256 nonce, bytes data, uint256 validUntil) request, tuple(uint256 gasPrice, uint256 pctRelayFee, uint256 baseRelayFee, address relayWorker, address paymaster, address forwarder, bytes paymasterData, uint256 clientId) relayData) relayRequest, bytes signature, bytes approvalData, address relay)', + 'function renounceOwnership()', + 'function requiredRelayGas() view returns (uint256)', + 'function setGasAndDataLimits(tuple(uint256 acceptanceBudget, uint256 preRelayedCallGasLimit, uint256 postRelayedCallGasLimit, uint256 calldataSizeLimit) limits)', + 'function setMaxRequiredRelayGas(uint256 gas)', + 'function setRelayHub(address hub)', + 'function setRequiredRelayGas(bytes4 methodId, uint256 gas)', + 'function setWrappedChainToken(address _wrappedChainToken)', + 'function transferOwnership(address newOwner)', + 'function trustedForwarder() view returns (address forwarder)', + 'function typeHashes(bytes32) view returns (bool)', + 'function uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes _data)', + 'function unregisterToken(address token)', + 'function verify(tuple(address from, address to, uint256 value, uint256 gas, uint256 nonce, bytes data, uint256 validUntil) forwardRequest, bytes32 domainSeparator, bytes32 requestTypeHash, bytes suffixData, bytes signature) view', + 'function versionPaymaster() view returns (string)', + 'function versionRecipient() view returns (string)', + 'function withdraw(uint256 amount, address target)', + 'function withdrawRelayHubDeposit(uint256 amount, address target)', + 'function withdrawToken(address token, uint256 amount, address target)', + 'function wrappedChainToken() view returns (address)', + ], +}; +/* eslint-enable max-len */ diff --git a/src/lib/polygon/PolygonContractABIs.js b/src/lib/polygon/PolygonContractABIs.js index 4aaa0ac37..5bfa71c81 100644 --- a/src/lib/polygon/PolygonContractABIs.js +++ b/src/lib/polygon/PolygonContractABIs.js @@ -1,181 +1,20 @@ /* eslint-disable max-len */ const PolygonContractABIs = { // eslint-disable-line no-unused-vars USDC_CONTRACT_ABI: [ - // 'event Approval(address indexed owner, address indexed spender, uint256 value)', - // 'event AuthorizationCanceled(address indexed authorizer, bytes32 indexed nonce)', - // 'event AuthorizationUsed(address indexed authorizer, bytes32 indexed nonce)', - // 'event Blacklisted(address indexed account)', - // 'event MetaTransactionExecuted(address userAddress, address relayerAddress, bytes functionSignature)', - // 'event Pause()', - // 'event RescuerChanged(address indexed newRescuer)', - // 'event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole)', - // 'event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender)', - // 'event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender)', - // 'event Transfer(address indexed from, address indexed to, uint256 value)', - // 'event UnBlacklisted(address indexed account)', - // 'event Unpause()', - // 'function APPROVE_WITH_AUTHORIZATION_TYPEHASH() view returns (bytes32)', - // 'function BLACKLISTER_ROLE() view returns (bytes32)', - // 'function CANCEL_AUTHORIZATION_TYPEHASH() view returns (bytes32)', - // 'function DECREASE_ALLOWANCE_WITH_AUTHORIZATION_TYPEHASH() view returns (bytes32)', - // 'function DEFAULT_ADMIN_ROLE() view returns (bytes32)', - // 'function DEPOSITOR_ROLE() view returns (bytes32)', - // 'function DOMAIN_SEPARATOR() view returns (bytes32)', - // 'function EIP712_VERSION() view returns (string)', - // 'function INCREASE_ALLOWANCE_WITH_AUTHORIZATION_TYPEHASH() view returns (bytes32)', - // 'function META_TRANSACTION_TYPEHASH() view returns (bytes32)', - // 'function PAUSER_ROLE() view returns (bytes32)', - // 'function PERMIT_TYPEHASH() view returns (bytes32)', - // 'function RESCUER_ROLE() view returns (bytes32)', - // 'function TRANSFER_WITH_AUTHORIZATION_TYPEHASH() view returns (bytes32)', - // 'function WITHDRAW_WITH_AUTHORIZATION_TYPEHASH() view returns (bytes32)', - // 'function allowance(address owner, address spender) view returns (uint256)', 'function approve(address spender, uint256 amount) returns (bool)', - // 'function approveWithAuthorization(address owner, address spender, uint256 value, uint256 validAfter, uint256 validBefore, bytes32 nonce, uint8 v, bytes32 r, bytes32 s)', - // 'function authorizationState(address authorizer, bytes32 nonce) view returns (uint8)', - // 'function balanceOf(address account) view returns (uint256)', - // 'function blacklist(address account)', - // 'function blacklisters() view returns (address[])', - // 'function cancelAuthorization(address authorizer, bytes32 nonce, uint8 v, bytes32 r, bytes32 s)', - // 'function decimals() view returns (uint8)', - // 'function decreaseAllowance(address spender, uint256 subtractedValue) returns (bool)', - // 'function decreaseAllowanceWithAuthorization(address owner, address spender, uint256 decrement, uint256 validAfter, uint256 validBefore, bytes32 nonce, uint8 v, bytes32 r, bytes32 s)', - // 'function deposit(address user, bytes depositData)', - // 'function executeMetaTransaction(address userAddress, bytes functionSignature, bytes32 sigR, bytes32 sigS, uint8 sigV) payable returns (bytes)', - // 'function getRoleAdmin(bytes32 role) view returns (bytes32)', - // 'function getRoleMember(bytes32 role, uint256 index) view returns (address)', - // 'function getRoleMemberCount(bytes32 role) view returns (uint256)', - // 'function grantRole(bytes32 role, address account)', - // 'function hasRole(bytes32 role, address account) view returns (bool)', - // 'function increaseAllowance(address spender, uint256 addedValue) returns (bool)', - // 'function increaseAllowanceWithAuthorization(address owner, address spender, uint256 increment, uint256 validAfter, uint256 validBefore, bytes32 nonce, uint8 v, bytes32 r, bytes32 s)', - // 'function initialize(string newName, string newSymbol, uint8 newDecimals, address childChainManager)', - // 'function initialized() view returns (bool)', - // 'function isBlacklisted(address account) view returns (bool)', - // 'function name() view returns (string)', - // 'function nonces(address owner) view returns (uint256)', - // 'function pause()', - // 'function paused() view returns (bool)', - // 'function pausers() view returns (address[])', - // 'function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)', - // 'function renounceRole(bytes32 role, address account)', - // 'function rescueERC20(address tokenContract, address to, uint256 amount)', - // 'function rescuers() view returns (address[])', - // 'function revokeRole(bytes32 role, address account)', - // 'function symbol() view returns (string)', - // 'function totalSupply() view returns (uint256)', - // 'function transfer(address recipient, uint256 amount) returns (bool)', - // 'function transferFrom(address sender, address recipient, uint256 amount) returns (bool)', - // 'function transferWithAuthorization(address from, address to, uint256 value, uint256 validAfter, uint256 validBefore, bytes32 nonce, uint8 v, bytes32 r, bytes32 s)', - // 'function unBlacklist(address account)', - // 'function unpause()', - // 'function updateMetadata(string newName, string newSymbol)', - // 'function withdraw(uint256 amount)', - // 'function withdrawWithAuthorization(address owner, uint256 value, uint256 validAfter, uint256 validBefore, bytes32 nonce, uint8 v, bytes32 r, bytes32 s)', ], USDC_TRANSFER_CONTRACT_ABI: [ - // 'constructor()', - // 'event DomainRegistered(bytes32 indexed domainSeparator, bytes domainValue)', - // 'event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)', - // 'event RequestTypeRegistered(bytes32 indexed typeHash, string typeStr)', - // 'function EIP712_DOMAIN_TYPE() view returns (string)', - // 'function deposits(address) view returns (uint256)', - // 'function domains(bytes32) view returns (bool)', - // 'function execute(tuple(address from, address to, uint256 value, uint256 gas, uint256 nonce, bytes data, uint256 validUntil) request, bytes32 domainSeparator, bytes32 requestTypeHash, bytes suffixData, bytes signature) payable returns (bool success, bytes ret)', - // 'function getGasAndDataLimits() view returns (tuple(uint256 acceptanceBudget, uint256 preRelayedCallGasLimit, uint256 postRelayedCallGasLimit, uint256 calldataSizeLimit) limits)', - // 'function getHubAddr() view returns (address)', - // 'function getMinimumRelayFee(tuple(uint256 gasPrice, uint256 pctRelayFee, uint256 baseRelayFee, address relayWorker, address paymaster, address forwarder, bytes paymasterData, uint256 clientId) relayData) view returns (uint256 amount)', - // 'function getNonce(address from) view returns (uint256)', - // 'function getRelayHubDeposit() view returns (uint256)', - // 'function getRequiredRelayFee(tuple(uint256 gasPrice, uint256 pctRelayFee, uint256 baseRelayFee, address relayWorker, address paymaster, address forwarder, bytes paymasterData, uint256 clientId) relayData, bytes4 methodId) view returns (uint256 amount)', - // 'function getRequiredRelayGas(bytes4 methodId) view returns (uint256 gas)', - // 'function isTrustedForwarder(address forwarder) view returns (bool)', - // 'function owner() view returns (address)', - // 'function postRelayedCall(bytes context, bool success, uint256 gasUseWithoutPost, tuple(uint256 gasPrice, uint256 pctRelayFee, uint256 baseRelayFee, address relayWorker, address paymaster, address forwarder, bytes paymasterData, uint256 clientId) relayData)', - // 'function preRelayedCall(tuple(tuple(address from, address to, uint256 value, uint256 gas, uint256 nonce, bytes data, uint256 validUntil) request, tuple(uint256 gasPrice, uint256 pctRelayFee, uint256 baseRelayFee, address relayWorker, address paymaster, address forwarder, bytes paymasterData, uint256 clientId) relayData) relayRequest, bytes signature, bytes approvalData, uint256 maxPossibleGas) returns (bytes context, bool revertOnRecipientRevert)', - // 'function registerDomainSeparator(string name, string version)', - // 'function registerRequestType(string typeName, string typeSuffix)', - // 'function registerToken(address token, address pool)', - // 'function registeredTokenPool(address) view returns (address)', - // 'function registeredTokenPoolFee(address token) view returns (uint24 fee)', - // 'function renounceOwnership()', - // 'function requiredRelayGas() view returns (uint256)', - // 'function setGasAndDataLimits(tuple(uint256 acceptanceBudget, uint256 preRelayedCallGasLimit, uint256 postRelayedCallGasLimit, uint256 calldataSizeLimit) limits)', - // 'function setMaxRequiredRelayGas(uint256 gas)', - // 'function setRelayHub(address hub)', - // 'function setRequiredRelayGas(bytes4 methodId, uint256 gas)', - // 'function setWrappedChainToken(address _wrappedChainToken)', 'function transfer(address token, uint256 amount, address target, uint256 fee)', - // 'function transferOwnership(address newOwner)', 'function transferWithApproval(address token, uint256 amount, address target, uint256 fee, uint256 approval, bytes32 sigR, bytes32 sigS, uint8 sigV)', - // 'function trustedForwarder() view returns (address forwarder)', - // 'function typeHashes(bytes32) view returns (bool)', - // 'function uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes _data)', - // 'function unregisterToken(address token)', - // 'function verify(tuple(address from, address to, uint256 value, uint256 gas, uint256 nonce, bytes data, uint256 validUntil) forwardRequest, bytes32 domainSeparator, bytes32 requestTypeHash, bytes suffixData, bytes signature) view', - // 'function versionPaymaster() view returns (string)', - // 'function versionRecipient() view returns (string)', - // 'function withdraw(uint256 amount, address target)', - // 'function withdrawRelayHubDeposit(uint256 amount, address target)', - // 'function withdrawToken(address token, uint256 amount, address target)', - // 'function wrappedChainToken() view returns (address)', ], USDC_HTLC_CONTRACT_ABI: [ - // 'constructor()', - // 'event DomainRegistered(bytes32 indexed domainSeparator, bytes domainValue)', - // 'event Open(bytes32 indexed id, address token, uint256 amount, address recipient, bytes32 hash, uint256 timeout)', - // 'event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)', - // 'event Redeem(bytes32 indexed id, bytes32 secret)', - // 'event Refund(bytes32 indexed id)', - // 'event RequestTypeRegistered(bytes32 indexed typeHash, string typeStr)', - // 'function EIP712_DOMAIN_TYPE() view returns (string)', - // 'function deposits(address) view returns (uint256)', - // 'function domains(bytes32) view returns (bool)', - // 'function execute(tuple(address from, address to, uint256 value, uint256 gas, uint256 nonce, bytes data, uint256 validUntil) request, bytes32 domainSeparator, bytes32 requestTypeHash, bytes suffixData, bytes signature) payable returns (bool success, bytes ret)', - // 'function getGasAndDataLimits() view returns (tuple(uint256 acceptanceBudget, uint256 preRelayedCallGasLimit, uint256 postRelayedCallGasLimit, uint256 calldataSizeLimit) limits)', - // 'function getHubAddr() view returns (address)', - // 'function getMinimumRelayFee(tuple(uint256 gasPrice, uint256 pctRelayFee, uint256 baseRelayFee, address relayWorker, address paymaster, address forwarder, bytes paymasterData, uint256 clientId) relayData) view returns (uint256 amount)', - // 'function getNonce(address from) view returns (uint256)', - // 'function getRelayHubDeposit() view returns (uint256)', - // 'function getRequiredRelayFee(tuple(uint256 gasPrice, uint256 pctRelayFee, uint256 baseRelayFee, address relayWorker, address paymaster, address forwarder, bytes paymasterData, uint256 clientId) relayData, bytes4 methodId) view returns (uint256 amount)', - // 'function getRequiredRelayGas(bytes4 methodId) view returns (uint256 gas)', - // 'function htlcs(bytes32) view returns (address token, uint256 amount, address refund, address recipient, bytes32 hash, uint256 timeout)', - // 'function isTrustedForwarder(address forwarder) view returns (bool)', 'function open(bytes32 id, address token, uint256 amount, address refundAddress, address recipientAddress, bytes32 hash, uint256 timeout, uint256 fee)', 'function openWithApproval(bytes32 id, address token, uint256 amount, address refundAddress, address recipientAddress, bytes32 hash, uint256 timeout, uint256 fee, uint256 approval, bytes32 sigR, bytes32 sigS, uint8 sigV)', - // 'function owner() view returns (address)', - // 'function postRelayedCall(bytes context, bool success, uint256 gasUseWithoutPost, tuple(uint256 gasPrice, uint256 pctRelayFee, uint256 baseRelayFee, address relayWorker, address paymaster, address forwarder, bytes paymasterData, uint256 clientId) relayData)', - // 'function preRelayedCall(tuple(tuple(address from, address to, uint256 value, uint256 gas, uint256 nonce, bytes data, uint256 validUntil) request, tuple(uint256 gasPrice, uint256 pctRelayFee, uint256 baseRelayFee, address relayWorker, address paymaster, address forwarder, bytes paymasterData, uint256 clientId) relayData) relayRequest, bytes signature, bytes approvalData, uint256 maxPossibleGas) returns (bytes context, bool revertOnRecipientRevert)', 'function redeem(bytes32 id, address target, bytes32 secret, uint256 fee)', 'function redeemWithSecretInData(bytes32 id, address target, uint256 fee)', 'function refund(bytes32 id, address target, uint256 fee)', - // 'function registerDomainSeparator(string name, string version)', - // 'function registerRequestType(string typeName, string typeSuffix)', - // 'function registerToken(address token, address pool)', - // 'function registeredTokenPool(address) view returns (address)', - // 'function registeredTokenPoolFee(address token) view returns (uint24 fee)', - // 'function relayWithoutGsn(tuple(tuple(address from, address to, uint256 value, uint256 gas, uint256 nonce, bytes data, uint256 validUntil) request, tuple(uint256 gasPrice, uint256 pctRelayFee, uint256 baseRelayFee, address relayWorker, address paymaster, address forwarder, bytes paymasterData, uint256 clientId) relayData) relayRequest, bytes signature, bytes approvalData, address relay)', - // 'function renounceOwnership()', - // 'function requiredRelayGas() view returns (uint256)', - // 'function setGasAndDataLimits(tuple(uint256 acceptanceBudget, uint256 preRelayedCallGasLimit, uint256 postRelayedCallGasLimit, uint256 calldataSizeLimit) limits)', - // 'function setMaxRequiredRelayGas(uint256 gas)', - // 'function setRelayHub(address hub)', - // 'function setRequiredRelayGas(bytes4 methodId, uint256 gas)', - // 'function setWrappedChainToken(address _wrappedChainToken)', - // 'function transferOwnership(address newOwner)', - // 'function trustedForwarder() view returns (address forwarder)', - // 'function typeHashes(bytes32) view returns (bool)', - // 'function uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes _data)', - // 'function unregisterToken(address token)', - // 'function verify(tuple(address from, address to, uint256 value, uint256 gas, uint256 nonce, bytes data, uint256 validUntil) forwardRequest, bytes32 domainSeparator, bytes32 requestTypeHash, bytes suffixData, bytes signature) view', - // 'function versionPaymaster() view returns (string)', - // 'function versionRecipient() view returns (string)', - // 'function withdraw(uint256 amount, address target)', - // 'function withdrawRelayHubDeposit(uint256 amount, address target)', - // 'function withdrawToken(address token, uint256 amount, address target)', - // 'function wrappedChainToken() view returns (address)', ], }; /* eslint-enable max-len */ diff --git a/src/request/sign-polygon-transaction/SignPolygonTransactionApi.js b/src/request/sign-polygon-transaction/SignPolygonTransactionApi.js index c7c022218..af4db928b 100644 --- a/src/request/sign-polygon-transaction/SignPolygonTransactionApi.js +++ b/src/request/sign-polygon-transaction/SignPolygonTransactionApi.js @@ -72,6 +72,10 @@ class SignPolygonTransactionApi extends PolygonRequestParserMixin(TopLevelApi) { data: forwardRequest.data, value: forwardRequest.value, })); + + if (description.args.token !== CONFIG.USDC_CONTRACT_ADDRESS) { + throw new Errors.InvalidRequestError('Invalid USDC token contract in request data'); + } } else if (forwardRequest.to === CONFIG.USDC_HTLC_CONTRACT_ADDRESS) { const usdcHtlcContract = new ethers.Contract( CONFIG.USDC_HTLC_CONTRACT_ADDRESS, @@ -91,12 +95,6 @@ class SignPolygonTransactionApi extends PolygonRequestParserMixin(TopLevelApi) { throw new Errors.InvalidRequestError('Requested Polygon contract method is invalid'); } - if (description.name === 'transfer' || description.name === 'transferWithApproval') { - if (description.args.token !== CONFIG.USDC_CONTRACT_ADDRESS) { - throw new Errors.InvalidRequestError('Invalid USDC token contract in request data'); - } - } - // Check that amount exists when method is 'refund', and unset for other methods. if ((description.name === 'refund') !== !!request.amount) { throw new Errors.InvalidRequestError('`amount` is only allowed for contract method "refund"'); From fc48649ae82856bf26b97b76bf35f7a2eca26b0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6ren?= Date: Wed, 6 Dec 2023 11:07:14 +0100 Subject: [PATCH 2/5] Add support for sending native USDC with transferWithPermit --- client/src/PublicRequest.ts | 8 ++ src/config/config.local.js | 3 + src/config/config.mainnet.js | 3 + src/config/config.testnet.js | 3 + src/lib/polygon/PolygonContractABIs.full.js | 118 ++++++++++++++++++ src/lib/polygon/PolygonContractABIs.js | 7 ++ src/lib/polygon/PolygonKey.js | 49 ++++++++ .../SignPolygonTransaction.js | 40 +++++- .../SignPolygonTransactionApi.js | 46 ++++++- types/Keyguard.d.ts | 15 +++ 10 files changed, 283 insertions(+), 9 deletions(-) diff --git a/client/src/PublicRequest.ts b/client/src/PublicRequest.ts index cda4faee5..5ff9ed9ec 100644 --- a/client/src/PublicRequest.ts +++ b/client/src/PublicRequest.ts @@ -226,6 +226,14 @@ export type PolygonTransactionInfo = { approval?: { tokenNonce: number, }, + + /** + * The sender's nonce in the token contract, required when calling the + * contract function `transferWithPermit`. + */ + permit?: { + tokenNonce: number, + }, }; export type SignPolygonTransactionRequest = Omit & PolygonTransactionInfo & { diff --git a/src/config/config.local.js b/src/config/config.local.js index e8f29e1de..4eee1fb41 100644 --- a/src/config/config.local.js +++ b/src/config/config.local.js @@ -20,4 +20,7 @@ const CONFIG = { // eslint-disable-line no-unused-vars USDC_CONTRACT_ADDRESS: '0x0FA8781a83E46826621b3BC094Ea2A0212e71B23', USDC_TRANSFER_CONTRACT_ADDRESS: '0x2805f3187dcDfa424EFA8c55Db6012Cf08Fa6eEc', // v3 USDC_HTLC_CONTRACT_ADDRESS: '0x2EB7cd7791b947A25d629219ead941fCd8f364BF', + + NATIVE_USDC_CONTRACT_ADDRESS: '0x9999f7Fea5938fD3b1E26A12c3f2fb024e194f97', + NATIVE_USDC_TRANSFER_CONTRACT_ADDRESS: '0x5D101A320547f8D640c44fDfe5d1f35224f00B8B', // v1 }; diff --git a/src/config/config.mainnet.js b/src/config/config.mainnet.js index 00260aa77..dd9ca7ffd 100644 --- a/src/config/config.mainnet.js +++ b/src/config/config.mainnet.js @@ -11,4 +11,7 @@ const CONFIG = { // eslint-disable-line no-unused-vars USDC_CONTRACT_ADDRESS: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174', USDC_TRANSFER_CONTRACT_ADDRESS: '0x98E69a6927747339d5E543586FC0262112eBe4BD', USDC_HTLC_CONTRACT_ADDRESS: '0xF615bD7EA00C4Cc7F39Faad0895dB5f40891359f', + + NATIVE_USDC_CONTRACT_ADDRESS: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359', + NATIVE_USDC_TRANSFER_CONTRACT_ADDRESS: '', // v1 }; diff --git a/src/config/config.testnet.js b/src/config/config.testnet.js index a3715f712..cf13e7271 100644 --- a/src/config/config.testnet.js +++ b/src/config/config.testnet.js @@ -11,4 +11,7 @@ const CONFIG = { // eslint-disable-line no-unused-vars USDC_CONTRACT_ADDRESS: '0x0FA8781a83E46826621b3BC094Ea2A0212e71B23', USDC_TRANSFER_CONTRACT_ADDRESS: '0x2805f3187dcDfa424EFA8c55Db6012Cf08Fa6eEc', USDC_HTLC_CONTRACT_ADDRESS: '0x2EB7cd7791b947A25d629219ead941fCd8f364BF', + + NATIVE_USDC_CONTRACT_ADDRESS: '0x9999f7Fea5938fD3b1E26A12c3f2fb024e194f97', + NATIVE_USDC_TRANSFER_CONTRACT_ADDRESS: '0x5D101A320547f8D640c44fDfe5d1f35224f00B8B', // v1 }; diff --git a/src/lib/polygon/PolygonContractABIs.full.js b/src/lib/polygon/PolygonContractABIs.full.js index 3266a464c..0f731aa89 100644 --- a/src/lib/polygon/PolygonContractABIs.full.js +++ b/src/lib/polygon/PolygonContractABIs.full.js @@ -177,5 +177,123 @@ const PolygonContractABIsFull = { // eslint-disable-line no-unused-vars 'function withdrawToken(address token, uint256 amount, address target)', 'function wrappedChainToken() view returns (address)', ], + + NATIVE_USDC_CONTRACT_ABI: [ + 'event Approval(address indexed owner, address indexed spender, uint256 value)', + 'event AuthorizationCanceled(address indexed authorizer, bytes32 indexed nonce)', + 'event AuthorizationUsed(address indexed authorizer, bytes32 indexed nonce)', + 'event Blacklisted(address indexed _account)', + 'event BlacklisterChanged(address indexed newBlacklister)', + 'event Burn(address indexed burner, uint256 amount)', + 'event MasterMinterChanged(address indexed newMasterMinter)', + 'event Mint(address indexed minter, address indexed to, uint256 amount)', + 'event MinterConfigured(address indexed minter, uint256 minterAllowedAmount)', + 'event MinterRemoved(address indexed oldMinter)', + 'event OwnershipTransferred(address previousOwner, address newOwner)', + 'event Pause()', + 'event PauserChanged(address indexed newAddress)', + 'event RescuerChanged(address indexed newRescuer)', + 'event Transfer(address indexed from, address indexed to, uint256 value)', + 'event UnBlacklisted(address indexed _account)', + 'event Unpause()', + 'function CANCEL_AUTHORIZATION_TYPEHASH() view returns (bytes32)', + 'function DOMAIN_SEPARATOR() view returns (bytes32)', + 'function PERMIT_TYPEHASH() view returns (bytes32)', + 'function RECEIVE_WITH_AUTHORIZATION_TYPEHASH() view returns (bytes32)', + 'function TRANSFER_WITH_AUTHORIZATION_TYPEHASH() view returns (bytes32)', + 'function allowance(address owner, address spender) view returns (uint256)', + 'function approve(address spender, uint256 value) returns (bool)', + 'function authorizationState(address authorizer, bytes32 nonce) view returns (bool)', + 'function balanceOf(address account) view returns (uint256)', + 'function blacklist(address _account)', + 'function blacklister() view returns (address)', + 'function burn(uint256 _amount)', + 'function cancelAuthorization(address authorizer, bytes32 nonce, uint8 v, bytes32 r, bytes32 s)', + 'function configureMinter(address minter, uint256 minterAllowedAmount) returns (bool)', + 'function currency() view returns (string)', + 'function decimals() view returns (uint8)', + 'function decreaseAllowance(address spender, uint256 decrement) returns (bool)', + 'function increaseAllowance(address spender, uint256 increment) returns (bool)', + 'function initialize(string tokenName, string tokenSymbol, string tokenCurrency, uint8 tokenDecimals, address newMasterMinter, address newPauser, address newBlacklister, address newOwner)', + 'function initializeV2(string newName)', + 'function initializeV2_1(address lostAndFound)', + 'function isBlacklisted(address _account) view returns (bool)', + 'function isMinter(address account) view returns (bool)', + 'function masterMinter() view returns (address)', + 'function mint(address _to, uint256 _amount) returns (bool)', + 'function minterAllowance(address minter) view returns (uint256)', + 'function name() view returns (string)', + 'function nonces(address owner) view returns (uint256)', + 'function owner() view returns (address)', + 'function pause()', + 'function paused() view returns (bool)', + 'function pauser() view returns (address)', + 'function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)', + 'function receiveWithAuthorization(address from, address to, uint256 value, uint256 validAfter, uint256 validBefore, bytes32 nonce, uint8 v, bytes32 r, bytes32 s)', + 'function removeMinter(address minter) returns (bool)', + 'function rescueERC20(address tokenContract, address to, uint256 amount)', + 'function rescuer() view returns (address)', + 'function symbol() view returns (string)', + 'function totalSupply() view returns (uint256)', + 'function transfer(address to, uint256 value) returns (bool)', + 'function transferFrom(address from, address to, uint256 value) returns (bool)', + 'function transferOwnership(address newOwner)', + 'function transferWithAuthorization(address from, address to, uint256 value, uint256 validAfter, uint256 validBefore, bytes32 nonce, uint8 v, bytes32 r, bytes32 s)', + 'function unBlacklist(address _account)', + 'function unpause()', + 'function updateBlacklister(address _newBlacklister)', + 'function updateMasterMinter(address _newMasterMinter)', + 'function updatePauser(address _newPauser)', + 'function updateRescuer(address newRescuer)', + 'function version() view returns (string)', + ], + + NATIVE_USDC_TRANSFER_CONTRACT_ABI: [ + 'constructor()', + 'event DomainRegistered(bytes32 indexed domainSeparator, bytes domainValue)', + 'event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)', + 'event RequestTypeRegistered(bytes32 indexed typeHash, string typeStr)', + 'function EIP712_DOMAIN_TYPE() view returns (string)', + 'function deposits(address) view returns (uint256)', + 'function domains(bytes32) view returns (bool)', + 'function execute(tuple(address from, address to, uint256 value, uint256 gas, uint256 nonce, bytes data, uint256 validUntil) request, bytes32 domainSeparator, bytes32 requestTypeHash, bytes suffixData, bytes signature) payable returns (bool success, bytes ret)', + 'function getGasAndDataLimits() view returns (tuple(uint256 acceptanceBudget, uint256 preRelayedCallGasLimit, uint256 postRelayedCallGasLimit, uint256 calldataSizeLimit) limits)', + 'function getHubAddr() view returns (address)', + 'function getMinimumRelayFee(tuple(uint256 gasPrice, uint256 pctRelayFee, uint256 baseRelayFee, address relayWorker, address paymaster, address forwarder, bytes paymasterData, uint256 clientId) relayData) view returns (uint256 amount)', + 'function getNonce(address from) view returns (uint256)', + 'function getRelayHubDeposit() view returns (uint256)', + 'function getRequiredRelayFee(tuple(uint256 gasPrice, uint256 pctRelayFee, uint256 baseRelayFee, address relayWorker, address paymaster, address forwarder, bytes paymasterData, uint256 clientId) relayData, bytes4 methodId) view returns (uint256 amount)', + 'function getRequiredRelayGas(bytes4 methodId) view returns (uint256 gas)', + 'function isTrustedForwarder(address forwarder) view returns (bool)', + 'function owner() view returns (address)', + 'function postRelayedCall(bytes context, bool success, uint256 gasUseWithoutPost, tuple(uint256 gasPrice, uint256 pctRelayFee, uint256 baseRelayFee, address relayWorker, address paymaster, address forwarder, bytes paymasterData, uint256 clientId) relayData)', + 'function preRelayedCall(tuple(tuple(address from, address to, uint256 value, uint256 gas, uint256 nonce, bytes data, uint256 validUntil) request, tuple(uint256 gasPrice, uint256 pctRelayFee, uint256 baseRelayFee, address relayWorker, address paymaster, address forwarder, bytes paymasterData, uint256 clientId) relayData) relayRequest, bytes signature, bytes approvalData, uint256 maxPossibleGas) returns (bytes context, bool revertOnRecipientRevert)', + 'function registerDomainSeparator(string name, string version)', + 'function registerRequestType(string typeName, string typeSuffix)', + 'function registerToken(address token, address pool)', + 'function registeredTokenPool(address) view returns (address)', + 'function registeredTokenPoolFee(address token) view returns (uint24 fee)', + 'function renounceOwnership()', + 'function requiredRelayGas() view returns (uint256)', + 'function setGasAndDataLimits(tuple(uint256 acceptanceBudget, uint256 preRelayedCallGasLimit, uint256 postRelayedCallGasLimit, uint256 calldataSizeLimit) limits)', + 'function setMaxRequiredRelayGas(uint256 gas)', + 'function setRelayHub(address hub)', + 'function setRequiredRelayGas(bytes4 methodId, uint256 gas)', + 'function setWrappedChainToken(address _wrappedChainToken)', + 'function transfer(address token, uint256 amount, address target, uint256 fee)', + 'function transferOwnership(address newOwner)', + 'function transferWithPermit(address token, uint256 amount, address target, uint256 fee, uint256 value, bytes32 sigR, bytes32 sigS, uint8 sigV)', + 'function trustedForwarder() view returns (address forwarder)', + 'function typeHashes(bytes32) view returns (bool)', + 'function uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes _data)', + 'function unregisterToken(address token)', + 'function verify(tuple(address from, address to, uint256 value, uint256 gas, uint256 nonce, bytes data, uint256 validUntil) forwardRequest, bytes32 domainSeparator, bytes32 requestTypeHash, bytes suffixData, bytes signature) view', + 'function versionPaymaster() view returns (string)', + 'function versionRecipient() view returns (string)', + 'function withdraw(uint256 amount, address target)', + 'function withdrawRelayHubDeposit(uint256 amount, address target)', + 'function withdrawToken(address token, uint256 amount, address target)', + 'function wrappedChainToken() view returns (address)', + ], }; /* eslint-enable max-len */ diff --git a/src/lib/polygon/PolygonContractABIs.js b/src/lib/polygon/PolygonContractABIs.js index 5bfa71c81..30516a83c 100644 --- a/src/lib/polygon/PolygonContractABIs.js +++ b/src/lib/polygon/PolygonContractABIs.js @@ -16,5 +16,12 @@ const PolygonContractABIs = { // eslint-disable-line no-unused-vars 'function redeemWithSecretInData(bytes32 id, address target, uint256 fee)', 'function refund(bytes32 id, address target, uint256 fee)', ], + + NATIVE_USDC_CONTRACT_ABI: [], + + NATIVE_USDC_TRANSFER_CONTRACT_ABI: [ + 'function transfer(address token, uint256 amount, address target, uint256 fee)', + 'function transferWithPermit(address token, uint256 amount, address target, uint256 fee, uint256 value, bytes32 sigR, bytes32 sigS, uint8 sigV)', + ], }; /* eslint-enable max-len */ diff --git a/src/lib/polygon/PolygonKey.js b/src/lib/polygon/PolygonKey.js index 5297b3dff..93b15c82e 100644 --- a/src/lib/polygon/PolygonKey.js +++ b/src/lib/polygon/PolygonKey.js @@ -97,6 +97,55 @@ class PolygonKey { // eslint-disable-line no-unused-vars return { sigR, sigS, sigV }; } + /** + * @param {string} path + * @param {string} forwarderContractAddress + * @param {ethers.BigNumber} approvalAmount + * @param {number} tokenNonce + * @param {string} ownerAddress + * @returns {Promise<{sigR: string, sigS: string, sigV: number}>} + */ + async signUsdcPermit(path, forwarderContractAddress, approvalAmount, tokenNonce, ownerAddress) { + // TODO: Make the domain parameters configurable in the request? + const domain = { + name: 'USD Coin', // This is currently the same for testnet and mainnet + version: '2', // This is currently the same for testnet and mainnet + verifyingContract: CONFIG.NATIVE_USDC_CONTRACT_ADDRESS, + chainId: CONFIG.POLYGON_CHAIN_ID, + }; + + const types = { + Permit: [ + { name: 'owner', type: 'address' }, + { name: 'spender', type: 'address' }, + { name: 'value', type: 'uint256' }, + { name: 'nonce', type: 'uint256' }, + { name: 'deadline', type: 'uint256' }, + ], + }; + + const message = { + owner: ownerAddress, + spender: forwarderContractAddress, + value: approvalAmount, + nonce: tokenNonce, + deadline: ethers.constants.MaxUint256, + }; + + const signature = await this.signTypedData( + path, + domain, + types, + message, + ); + + const sigR = signature.slice(0, 66); // 0x prefix plus 32 bytes = 66 characters + const sigS = `0x${signature.slice(66, 130)}`; // 32 bytes = 64 characters + const sigV = parseInt(signature.slice(130, 132), 16); // last byte = 2 characters + + return { sigR, sigS, sigV }; + } + /** * @param {string} path * @param {Uint8Array} message - A byte array diff --git a/src/request/sign-polygon-transaction/SignPolygonTransaction.js b/src/request/sign-polygon-transaction/SignPolygonTransaction.js index 93c5e4568..c3834b2cb 100644 --- a/src/request/sign-polygon-transaction/SignPolygonTransaction.js +++ b/src/request/sign-polygon-transaction/SignPolygonTransaction.js @@ -117,6 +117,9 @@ class SignPolygonTransaction { const polygonKey = new PolygonKey(key); + // Has been validated to be an approved transfer contract address + const transferContract = request.request.to; + if (request.description.name === 'transferWithApproval') { const { sigR, sigS, sigV } = await polygonKey.signUsdcApproval( request.keyPath, @@ -124,7 +127,7 @@ class SignPolygonTransaction { CONFIG.USDC_CONTRACT_ADDRESS, PolygonContractABIs.USDC_CONTRACT_ABI, ), - CONFIG.USDC_TRANSFER_CONTRACT_ADDRESS, + transferContract, request.description.args.approval, // Has been validated to be defined when function called is `transferWithApproval` /** @type {{ tokenNonce: number }} */ (request.approval).tokenNonce, @@ -132,7 +135,7 @@ class SignPolygonTransaction { ); const usdcTransfer = new ethers.Contract( - CONFIG.USDC_TRANSFER_CONTRACT_ADDRESS, + transferContract, PolygonContractABIs.USDC_TRANSFER_CONTRACT_ABI, ); @@ -148,11 +151,38 @@ class SignPolygonTransaction { ]); } + if (request.description.name === 'transferWithPermit') { + const { sigR, sigS, sigV } = await polygonKey.signUsdcPermit( + request.keyPath, + transferContract, + // `value` is the permit approval amount - the transaction value is called `amount` + request.description.args.value, + // Has been validated to be defined when function called is `transferWithPermit` + /** @type {{ tokenNonce: number }} */ (request.permit).tokenNonce, + request.request.from, + ); + + const nativeUsdcTransfer = new ethers.Contract( + transferContract, + PolygonContractABIs.NATIVE_USDC_TRANSFER_CONTRACT_ABI, + ); + + request.request.data = nativeUsdcTransfer.interface.encodeFunctionData(request.description.name, [ + /* address token */ request.description.args.token, + /* uint256 amount */ request.description.args.amount, + /* address target */ request.description.args.target, + /* uint256 fee */ request.description.args.fee, + // `value` is the permit approval amount - the transaction value is called `amount` (above) + /* uint256 value */ request.description.args.value, + /* bytes32 sigR */ sigR, + /* bytes32 sigS */ sigS, + /* uint8 sigV */ sigV, + ]); + } + const typedData = new OpenGSN.TypedRequestData( CONFIG.POLYGON_CHAIN_ID, - request.description.name === 'refund' - ? CONFIG.USDC_HTLC_CONTRACT_ADDRESS - : CONFIG.USDC_TRANSFER_CONTRACT_ADDRESS, + transferContract, { request: request.request, relayData: request.relayData, diff --git a/src/request/sign-polygon-transaction/SignPolygonTransactionApi.js b/src/request/sign-polygon-transaction/SignPolygonTransactionApi.js index af4db928b..c158e07c7 100644 --- a/src/request/sign-polygon-transaction/SignPolygonTransactionApi.js +++ b/src/request/sign-polygon-transaction/SignPolygonTransactionApi.js @@ -24,7 +24,7 @@ class SignPolygonTransactionApi extends PolygonRequestParserMixin(TopLevelApi) { parsedRequest.keyPath = this.parsePolygonPath(request.keyPath, 'keyPath'); [parsedRequest.request, parsedRequest.description] = this.parseOpenGsnForwardRequest( request, - ['transfer', 'transferWithApproval', 'refund'], + ['transfer', 'transferWithApproval', 'transferWithPermit', 'refund'], ); parsedRequest.relayData = this.parseOpenGsnRelayData(request.relayData); parsedRequest.senderLabel = this.parseLabel(request.senderLabel); // Used for HTLC refunds @@ -41,6 +41,15 @@ class SignPolygonTransactionApi extends PolygonRequestParserMixin(TopLevelApi) { ), }; } + if (request.permit !== undefined) { + parsedRequest.permit = { + tokenNonce: this.parsePositiveInteger( + request.permit.tokenNonce, + true, + 'permit.tokenNonce', + ), + }; + } return parsedRequest; } @@ -49,16 +58,24 @@ class SignPolygonTransactionApi extends PolygonRequestParserMixin(TopLevelApi) { /** * * @param {KeyguardRequest.PolygonTransactionInfo} request - * @param {Array<'transfer' | 'transferWithApproval' | 'refund'>} allowedMethods + * @param {Array<'transfer' | 'transferWithApproval' | 'transferWithPermit' | 'refund'>} allowedMethods * @returns {[ * KeyguardRequest.OpenGsnForwardRequest, - * PolygonTransferDescription | PolygonTransferWithApprovalDescription | PolygonRefundDescription, + * PolygonTransferDescription + * | PolygonTransferWithApprovalDescription + * | PolygonTransferWithPermitDescription + * | PolygonRefundDescription, * ]} */ parseOpenGsnForwardRequest(request, allowedMethods) { const forwardRequest = this.parseOpenGsnForwardRequestRoot(request.request); - /** @type {PolygonTransferDescription | PolygonTransferWithApprovalDescription | PolygonRefundDescription} */ + /** + * @type {PolygonTransferDescription + * | PolygonTransferWithApprovalDescription + * | PolygonTransferWithPermitDescription + * | PolygonRefundDescription} + */ let description; if (forwardRequest.to === CONFIG.USDC_TRANSFER_CONTRACT_ADDRESS) { @@ -76,6 +93,21 @@ class SignPolygonTransactionApi extends PolygonRequestParserMixin(TopLevelApi) { if (description.args.token !== CONFIG.USDC_CONTRACT_ADDRESS) { throw new Errors.InvalidRequestError('Invalid USDC token contract in request data'); } + } else if (forwardRequest.to === CONFIG.NATIVE_USDC_TRANSFER_CONTRACT_ADDRESS) { + const nativeUsdcTransferContract = new ethers.Contract( + CONFIG.NATIVE_USDC_TRANSFER_CONTRACT_ADDRESS, + PolygonContractABIs.NATIVE_USDC_TRANSFER_CONTRACT_ABI, + ); + + /** @type {PolygonTransferDescription | PolygonTransferWithPermitDescription} */ + description = (nativeUsdcTransferContract.interface.parseTransaction({ + data: forwardRequest.data, + value: forwardRequest.value, + })); + + if (description.args.token !== CONFIG.NATIVE_USDC_CONTRACT_ADDRESS) { + throw new Errors.InvalidRequestError('Invalid native USDC token contract in request data'); + } } else if (forwardRequest.to === CONFIG.USDC_HTLC_CONTRACT_ADDRESS) { const usdcHtlcContract = new ethers.Contract( CONFIG.USDC_HTLC_CONTRACT_ADDRESS, @@ -106,6 +138,12 @@ class SignPolygonTransactionApi extends PolygonRequestParserMixin(TopLevelApi) { + '"transferWithApproval"'); } + // Check that permit object exists when method is 'transferWithPermit', and unset for other methods. + if ((description.name === 'transferWithPermit') !== !!request.permit) { + throw new Errors.InvalidRequestError('`permit` object is only allowed for contract method ' + + '"transferWithPermit"'); + } + return [forwardRequest, description]; } diff --git a/types/Keyguard.d.ts b/types/Keyguard.d.ts index 3959d1e3f..dde5d8a0a 100644 --- a/types/Keyguard.d.ts +++ b/types/Keyguard.d.ts @@ -62,6 +62,13 @@ interface PolygonUsdcApproval { readonly sigV: ethers.BigNumber, } +interface PolygonUsdcPermit { + readonly value: ethers.BigNumber, // amount to be approved + readonly sigR: string, + readonly sigS: string, + readonly sigV: ethers.BigNumber, +} + interface PolygonTransferArgs extends ReadonlyArray { readonly token: string, readonly amount: ethers.BigNumber, @@ -81,6 +88,13 @@ type PolygonTransferWithApprovalDescription = ethers.utils.TransactionDescriptio readonly args: PolygonTransferWithApprovalArgs, }; +interface PolygonTransferWithPermitArgs extends PolygonTransferArgs, PolygonUsdcPermit {} + +type PolygonTransferWithPermitDescription = ethers.utils.TransactionDescription & { + readonly name: 'transferWithPermit', + readonly args: PolygonTransferWithPermitArgs, +}; + interface PolygonOpenArgs extends ReadonlyArray { readonly id: string, readonly token: string, @@ -279,6 +293,7 @@ type Parsed = KeyId2KeyInfo & { description: PolygonTransferDescription | PolygonTransferWithApprovalDescription + | PolygonTransferWithPermitDescription | PolygonRefundDescription } : T extends Is ? KeyId2KeyInfo> From dda1b644de2bf94090504dd5bf3699228cabdd4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6ren?= Date: Wed, 6 Dec 2023 11:04:03 +0100 Subject: [PATCH 3/5] Specialize allowed methods depending on contract --- .../SignPolygonTransactionApi.js | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/request/sign-polygon-transaction/SignPolygonTransactionApi.js b/src/request/sign-polygon-transaction/SignPolygonTransactionApi.js index c158e07c7..12d2c7571 100644 --- a/src/request/sign-polygon-transaction/SignPolygonTransactionApi.js +++ b/src/request/sign-polygon-transaction/SignPolygonTransactionApi.js @@ -22,10 +22,7 @@ class SignPolygonTransactionApi extends PolygonRequestParserMixin(TopLevelApi) { parsedRequest.keyInfo = await this.parseKeyId(request.keyId); parsedRequest.keyLabel = /** @type {string} */ (this.parseLabel(request.keyLabel, false, 'keyLabel')); parsedRequest.keyPath = this.parsePolygonPath(request.keyPath, 'keyPath'); - [parsedRequest.request, parsedRequest.description] = this.parseOpenGsnForwardRequest( - request, - ['transfer', 'transferWithApproval', 'transferWithPermit', 'refund'], - ); + [parsedRequest.request, parsedRequest.description] = this.parseOpenGsnForwardRequest(request); parsedRequest.relayData = this.parseOpenGsnRelayData(request.relayData); parsedRequest.senderLabel = this.parseLabel(request.senderLabel); // Used for HTLC refunds parsedRequest.recipientLabel = this.parseLabel(request.recipientLabel); @@ -58,7 +55,6 @@ class SignPolygonTransactionApi extends PolygonRequestParserMixin(TopLevelApi) { /** * * @param {KeyguardRequest.PolygonTransactionInfo} request - * @param {Array<'transfer' | 'transferWithApproval' | 'transferWithPermit' | 'refund'>} allowedMethods * @returns {[ * KeyguardRequest.OpenGsnForwardRequest, * PolygonTransferDescription @@ -67,7 +63,7 @@ class SignPolygonTransactionApi extends PolygonRequestParserMixin(TopLevelApi) { * | PolygonRefundDescription, * ]} */ - parseOpenGsnForwardRequest(request, allowedMethods) { + parseOpenGsnForwardRequest(request) { const forwardRequest = this.parseOpenGsnForwardRequestRoot(request.request); /** @@ -93,6 +89,10 @@ class SignPolygonTransactionApi extends PolygonRequestParserMixin(TopLevelApi) { if (description.args.token !== CONFIG.USDC_CONTRACT_ADDRESS) { throw new Errors.InvalidRequestError('Invalid USDC token contract in request data'); } + + if (!['transfer', 'transferWithApproval'].includes(description.name)) { + throw new Errors.InvalidRequestError('Requested Polygon contract method is invalid'); + } } else if (forwardRequest.to === CONFIG.NATIVE_USDC_TRANSFER_CONTRACT_ADDRESS) { const nativeUsdcTransferContract = new ethers.Contract( CONFIG.NATIVE_USDC_TRANSFER_CONTRACT_ADDRESS, @@ -108,6 +108,10 @@ class SignPolygonTransactionApi extends PolygonRequestParserMixin(TopLevelApi) { if (description.args.token !== CONFIG.NATIVE_USDC_CONTRACT_ADDRESS) { throw new Errors.InvalidRequestError('Invalid native USDC token contract in request data'); } + + if (!['transfer', 'transferWithPermit'].includes(description.name)) { + throw new Errors.InvalidRequestError('Requested Polygon contract method is invalid'); + } } else if (forwardRequest.to === CONFIG.USDC_HTLC_CONTRACT_ADDRESS) { const usdcHtlcContract = new ethers.Contract( CONFIG.USDC_HTLC_CONTRACT_ADDRESS, @@ -119,14 +123,14 @@ class SignPolygonTransactionApi extends PolygonRequestParserMixin(TopLevelApi) { data: forwardRequest.data, value: forwardRequest.value, })); + + if (!['refund'].includes(description.name)) { + throw new Errors.InvalidRequestError('Requested Polygon contract method is invalid'); + } } else { throw new Errors.InvalidRequestError('request.to address is not allowed'); } - if (!allowedMethods.includes(description.name)) { - throw new Errors.InvalidRequestError('Requested Polygon contract method is invalid'); - } - // Check that amount exists when method is 'refund', and unset for other methods. if ((description.name === 'refund') !== !!request.amount) { throw new Errors.InvalidRequestError('`amount` is only allowed for contract method "refund"'); From 166daa3308724e9d689c4521c7a23bbb14bf4e9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6ren?= Date: Fri, 5 Jan 2024 18:16:30 +0100 Subject: [PATCH 4/5] Dedupe signature splitting --- src/lib/polygon/PolygonKey.js | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/lib/polygon/PolygonKey.js b/src/lib/polygon/PolygonKey.js index 93b15c82e..3ea2c81f7 100644 --- a/src/lib/polygon/PolygonKey.js +++ b/src/lib/polygon/PolygonKey.js @@ -90,11 +90,7 @@ class PolygonKey { // eslint-disable-line no-unused-vars message, ); - const sigR = signature.slice(0, 66); // 0x prefix plus 32 bytes = 66 characters - const sigS = `0x${signature.slice(66, 130)}`; // 32 bytes = 64 characters - const sigV = parseInt(signature.slice(130, 132), 16); // last byte = 2 characters - - return { sigR, sigS, sigV }; + return this._signatureToParts(signature); } /** @@ -139,11 +135,7 @@ class PolygonKey { // eslint-disable-line no-unused-vars message, ); - const sigR = signature.slice(0, 66); // 0x prefix plus 32 bytes = 66 characters - const sigS = `0x${signature.slice(66, 130)}`; // 32 bytes = 64 characters - const sigV = parseInt(signature.slice(130, 132), 16); // last byte = 2 characters - - return { sigR, sigS, sigV }; + return this._signatureToParts(signature); } /** @@ -171,6 +163,18 @@ class PolygonKey { // eslint-disable-line no-unused-vars return this._key; } + /** + * @param {string} signature + * @returns {{sigR: string, sigS: string, sigV: number}} + */ + _signatureToParts(signature) { + const sigR = signature.slice(0, 66); // 0x prefix plus 32 bytes = 66 characters + const sigS = `0x${signature.slice(66, 130)}`; // 32 bytes = 64 characters + const sigV = parseInt(signature.slice(130, 132), 16); // last byte = 2 characters + + return { sigR, sigS, sigV }; + } + /** * @type {string} */ From 926582c98909784099c660a9d6a53a9c49761893 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6ren?= Date: Fri, 5 Jan 2024 18:19:05 +0100 Subject: [PATCH 5/5] Add clarifying comment, change ABI reference file to txt format --- client/src/PublicRequest.ts | 4 ++-- ...onContractABIs.full.js => PolygonContractABIs.full.js.txt} | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename src/lib/polygon/{PolygonContractABIs.full.js => PolygonContractABIs.full.js.txt} (100%) diff --git a/client/src/PublicRequest.ts b/client/src/PublicRequest.ts index 5ff9ed9ec..34e71678a 100644 --- a/client/src/PublicRequest.ts +++ b/client/src/PublicRequest.ts @@ -221,7 +221,7 @@ export type PolygonTransactionInfo = { /** * The sender's nonce in the token contract, required when calling the - * contract function `transferWithApproval`. + * contract function `transferWithApproval` for bridged USDC.e. */ approval?: { tokenNonce: number, @@ -229,7 +229,7 @@ export type PolygonTransactionInfo = { /** * The sender's nonce in the token contract, required when calling the - * contract function `transferWithPermit`. + * contract function `transferWithPermit` for native USDC. */ permit?: { tokenNonce: number, diff --git a/src/lib/polygon/PolygonContractABIs.full.js b/src/lib/polygon/PolygonContractABIs.full.js.txt similarity index 100% rename from src/lib/polygon/PolygonContractABIs.full.js rename to src/lib/polygon/PolygonContractABIs.full.js.txt