From 2290c66c85d15094df9d3159d96932cdbbd293f1 Mon Sep 17 00:00:00 2001 From: Alfetopito Date: Mon, 16 Oct 2023 17:41:06 +0100 Subject: [PATCH 1/8] chore: remove unused prop `gasLimit` from SupportedPermitInfo --- apps/cowswap-frontend/src/modules/permit/types.ts | 1 - .../src/modules/permit/utils/checkIsTokenPermittable.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/apps/cowswap-frontend/src/modules/permit/types.ts b/apps/cowswap-frontend/src/modules/permit/types.ts index d1cc15571f..92cdd414c6 100644 --- a/apps/cowswap-frontend/src/modules/permit/types.ts +++ b/apps/cowswap-frontend/src/modules/permit/types.ts @@ -13,7 +13,6 @@ export type PermitType = 'dai-like' | 'eip-2612' export type SupportedPermitInfo = { type: PermitType - gasLimit: number } type UnsupportedPermitInfo = false export type PermitInfo = SupportedPermitInfo | UnsupportedPermitInfo diff --git a/apps/cowswap-frontend/src/modules/permit/utils/checkIsTokenPermittable.ts b/apps/cowswap-frontend/src/modules/permit/utils/checkIsTokenPermittable.ts index 8093044c24..a0fca515ad 100644 --- a/apps/cowswap-frontend/src/modules/permit/utils/checkIsTokenPermittable.ts +++ b/apps/cowswap-frontend/src/modules/permit/utils/checkIsTokenPermittable.ts @@ -136,7 +136,6 @@ async function estimateTokenPermit(params: EstimateParams): Promise PERMIT_GAS_LIMIT_MIN[chainId] ? { - gasLimit, type, } : false From d9703c40b25fc9db031f4abec26ed8e4a910a374 Mon Sep 17 00:00:00 2001 From: Alfetopito Date: Mon, 16 Oct 2023 18:00:08 +0100 Subject: [PATCH 2/8] feat: query and add version to permitInfo --- .../src/modules/permit/types.ts | 1 + .../permit/utils/checkIsTokenPermittable.ts | 22 ++++++++++++++++--- .../permit/utils/generatePermitHook.ts | 2 ++ 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/apps/cowswap-frontend/src/modules/permit/types.ts b/apps/cowswap-frontend/src/modules/permit/types.ts index 92cdd414c6..312b5442a9 100644 --- a/apps/cowswap-frontend/src/modules/permit/types.ts +++ b/apps/cowswap-frontend/src/modules/permit/types.ts @@ -13,6 +13,7 @@ export type PermitType = 'dai-like' | 'eip-2612' export type SupportedPermitInfo = { type: PermitType + version: string | undefined // Some tokens have it different than `1`, and won't work without it } type UnsupportedPermitInfo = false export type PermitInfo = SupportedPermitInfo | UnsupportedPermitInfo diff --git a/apps/cowswap-frontend/src/modules/permit/utils/checkIsTokenPermittable.ts b/apps/cowswap-frontend/src/modules/permit/utils/checkIsTokenPermittable.ts index a0fca515ad..b0f420a5f6 100644 --- a/apps/cowswap-frontend/src/modules/permit/utils/checkIsTokenPermittable.ts +++ b/apps/cowswap-frontend/src/modules/permit/utils/checkIsTokenPermittable.ts @@ -74,6 +74,17 @@ async function actuallyCheckTokenIsPermittable(params: CheckIsTokenPermittablePa return { error: e.message || e.toString() } } + let version: string | undefined = undefined + + try { + // Required by USDC-mainnet as its version is `2`. + // There might be other tokens that need this as well. + version = await eip2612PermitUtils.getTokenVersion(tokenAddress) + } catch (e) { + // Not a problem, we can (try to) continue without it, and will default to `1` (part of the 1inch lib) + console.debug(`[checkTokenIsPermittable] Failed to get version for ${tokenAddress}`, e) + } + const baseParams: BaseParams = { chainId, eip2612PermitUtils, @@ -82,6 +93,7 @@ async function actuallyCheckTokenIsPermittable(params: CheckIsTokenPermittablePa tokenAddress, tokenName, walletAddress: owner, + version, } try { @@ -108,6 +120,7 @@ type BaseParams = { spender: string eip2612PermitUtils: Eip2612PermitUtils nonce: number + version: string | undefined } type EstimateParams = BaseParams & { @@ -116,7 +129,7 @@ type EstimateParams = BaseParams & { } async function estimateTokenPermit(params: EstimateParams): Promise { - const { provider, chainId, walletAddress, tokenAddress, type } = params + const { provider, chainId, walletAddress, tokenAddress, type, version } = params const getCallDataFn = type === 'eip-2612' ? getEip2612CallData : getDaiLikeCallData @@ -137,12 +150,13 @@ async function estimateTokenPermit(params: EstimateParams): Promise PERMIT_GAS_LIMIT_MIN[chainId] ? { type, + version, } : false } async function getEip2612CallData(params: BaseParams): Promise { - const { eip2612PermitUtils, walletAddress, spender, nonce, chainId, tokenName, tokenAddress } = params + const { eip2612PermitUtils, walletAddress, spender, nonce, chainId, tokenName, tokenAddress, version } = params return buildEip2162PermitCallData({ eip2162Utils: eip2612PermitUtils, callDataParams: [ @@ -155,12 +169,13 @@ async function getEip2612CallData(params: BaseParams): Promise { +chainId, tokenName, tokenAddress, + version, ], }) } async function getDaiLikeCallData(params: BaseParams): Promise { - const { eip2612PermitUtils, tokenAddress, walletAddress, spender, nonce, chainId, tokenName } = params + const { eip2612PermitUtils, tokenAddress, walletAddress, spender, nonce, chainId, tokenName, version } = params const permitTypeHash = await eip2612PermitUtils.getPermitTypeHash(tokenAddress) @@ -177,6 +192,7 @@ async function getDaiLikeCallData(params: BaseParams): Promise { chainId as number, tokenName, tokenAddress, + version, ], }) } diff --git a/apps/cowswap-frontend/src/modules/permit/utils/generatePermitHook.ts b/apps/cowswap-frontend/src/modules/permit/utils/generatePermitHook.ts index 7d781342aa..ea9db1f713 100644 --- a/apps/cowswap-frontend/src/modules/permit/utils/generatePermitHook.ts +++ b/apps/cowswap-frontend/src/modules/permit/utils/generatePermitHook.ts @@ -65,6 +65,7 @@ async function generatePermitHookRaw(params: PermitHookParams): Promise Date: Mon, 16 Oct 2023 18:00:32 +0100 Subject: [PATCH 3/8] feat: bump permittableTokensAtom storage key to `v1` --- .../src/modules/permit/state/permittableTokensAtom.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/cowswap-frontend/src/modules/permit/state/permittableTokensAtom.ts b/apps/cowswap-frontend/src/modules/permit/state/permittableTokensAtom.ts index daf8a9de07..aeebdf1716 100644 --- a/apps/cowswap-frontend/src/modules/permit/state/permittableTokensAtom.ts +++ b/apps/cowswap-frontend/src/modules/permit/state/permittableTokensAtom.ts @@ -12,7 +12,7 @@ import { AddPermitTokenParams, PermittableTokens } from '../types' * Contains either the permit info with `type` and `gasLimit` when supported or * `false` when not supported */ -export const permittableTokensAtom = atomWithStorage('permittableTokens:v0', { +export const permittableTokensAtom = atomWithStorage('permittableTokens:v1', { [SupportedChainId.MAINNET]: {}, [SupportedChainId.GOERLI]: {}, [SupportedChainId.GNOSIS_CHAIN]: {}, From eb81428decc3a77cda1072a6a0cae9bf14b43d7c Mon Sep 17 00:00:00 2001 From: Alfetopito Date: Tue, 17 Oct 2023 09:44:50 +0100 Subject: [PATCH 4/8] fix: usdc default tokens had the wrong name, causing the permit signature to fail --- libs/common-const/src/tokens.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/common-const/src/tokens.ts b/libs/common-const/src/tokens.ts index 473ddb5cad..474aa4e3ab 100644 --- a/libs/common-const/src/tokens.ts +++ b/libs/common-const/src/tokens.ts @@ -23,14 +23,14 @@ export const USDC_MAINNET = new Token( '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', 6, 'USDC', - 'USD//C' + 'USD Coin' ) export const USDC_GOERLI = new Token( SupportedChainId.GOERLI, '0x07865c6e87b9f70255377e024ace6630c1eaa37f', 6, 'USDC', - 'USD//C' + 'USD Coin' ) export const DAI = new Token( SupportedChainId.MAINNET, From e24f03af7949f4d9db7e3c4a5647aafffbba6af8 Mon Sep 17 00:00:00 2001 From: Alfetopito Date: Tue, 17 Oct 2023 09:49:38 +0100 Subject: [PATCH 5/8] chore: temporarily logging permit callData and params --- .../src/modules/permit/utils/buildPermitCallData.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/cowswap-frontend/src/modules/permit/utils/buildPermitCallData.ts b/apps/cowswap-frontend/src/modules/permit/utils/buildPermitCallData.ts index 67d5ddcca0..524847d413 100644 --- a/apps/cowswap-frontend/src/modules/permit/utils/buildPermitCallData.ts +++ b/apps/cowswap-frontend/src/modules/permit/utils/buildPermitCallData.ts @@ -7,7 +7,7 @@ export async function buildEip2162PermitCallData({ callDataParams, }: BuildEip2162PermitCallDataParams): Promise { const callData = await eip2162Utils.buildPermitCallData(...callDataParams) - + console.log(`[buildEip2162PermitCallData]`, callDataParams, callData) // For some reason, the method above removes the permit selector prefix // https://github.com/1inch/permit-signed-approvals-utils/blob/master/src/eip-2612-permit.utils.ts#L92 // Adding it back @@ -19,6 +19,7 @@ export async function buildDaiLikePermitCallData({ callDataParams, }: BuildDaiLikePermitCallDataParams): Promise { const callData = await eip2162Utils.buildDaiLikePermitCallData(...callDataParams) + console.log(`[buildDaiLikePermitCallData]`, callDataParams, callData) // Same as above, but for dai like // https://github.com/1inch/permit-signed-approvals-utils/blob/master/src/eip-2612-permit.utils.ts#L140 From 020e7e8aad39b5ff0b99d8029d33df78700859c3 Mon Sep 17 00:00:00 2001 From: Alfetopito Date: Tue, 17 Oct 2023 14:38:55 +0100 Subject: [PATCH 6/8] fix: hack to fix USDC token name when creating the permit callData --- .../src/modules/permit/utils/buildPermitCallData.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/apps/cowswap-frontend/src/modules/permit/utils/buildPermitCallData.ts b/apps/cowswap-frontend/src/modules/permit/utils/buildPermitCallData.ts index 524847d413..af4c56f534 100644 --- a/apps/cowswap-frontend/src/modules/permit/utils/buildPermitCallData.ts +++ b/apps/cowswap-frontend/src/modules/permit/utils/buildPermitCallData.ts @@ -6,7 +6,14 @@ export async function buildEip2162PermitCallData({ eip2162Utils, callDataParams, }: BuildEip2162PermitCallDataParams): Promise { - const callData = await eip2162Utils.buildPermitCallData(...callDataParams) + // TODO: this is ugly and I'm not happy with it either + // It'll probably go away when the tokens overhaul is implemented + // For now, this is a problem for favourite tokens cached locally with the hardcoded name for USDC token + // Using the wrong name breaks the signature. + const [permitParams, chainId, _tokenName, ...rest] = callDataParams + const tokenName = _tokenName === 'USD//C' ? 'USD Coin' : _tokenName + + const callData = await eip2162Utils.buildPermitCallData(permitParams, chainId, tokenName, ...rest) console.log(`[buildEip2162PermitCallData]`, callDataParams, callData) // For some reason, the method above removes the permit selector prefix // https://github.com/1inch/permit-signed-approvals-utils/blob/master/src/eip-2612-permit.utils.ts#L92 From 458d25904eb895f8ea18d4bdcf677bdddcc80c0d Mon Sep 17 00:00:00 2001 From: Alfetopito Date: Tue, 17 Oct 2023 15:36:46 +0100 Subject: [PATCH 7/8] feat: do not check for permit version if token cannot handle it --- .../src/modules/permit/const.ts | 8 +++++++ .../permit/utils/checkIsTokenPermittable.ts | 21 ++++++++++++------- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/apps/cowswap-frontend/src/modules/permit/const.ts b/apps/cowswap-frontend/src/modules/permit/const.ts index 516059f1f3..b6225c5134 100644 --- a/apps/cowswap-frontend/src/modules/permit/const.ts +++ b/apps/cowswap-frontend/src/modules/permit/const.ts @@ -1,3 +1,4 @@ +import { DAI } from '@cowprotocol/common-const' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { MaxUint256 } from '@ethersproject/constants' import { Wallet } from '@ethersproject/wallet' @@ -31,3 +32,10 @@ export const ORDER_TYPE_SUPPORTS_PERMIT: Record = { } export const PENDING_ORDER_PERMIT_CHECK_INTERVAL = ms`1min` + +// DAI's mainnet contract (https://etherscan.io/address/0x6b175474e89094c44da98b954eedeac495271d0f#readContract) returns +// `1` for the version, while when calling the contract method returns `2`. +// Also, if we use the version returned by the contract, it simply doesn't work +// Thus, do not call it for DAI. +// TODO: figure out whether more tokens behave the same way +export const TOKENS_TO_SKIP_VERSION = new Set([DAI.address.toLowerCase()]) diff --git a/apps/cowswap-frontend/src/modules/permit/utils/checkIsTokenPermittable.ts b/apps/cowswap-frontend/src/modules/permit/utils/checkIsTokenPermittable.ts index b0f420a5f6..3b4c5dd599 100644 --- a/apps/cowswap-frontend/src/modules/permit/utils/checkIsTokenPermittable.ts +++ b/apps/cowswap-frontend/src/modules/permit/utils/checkIsTokenPermittable.ts @@ -8,7 +8,7 @@ import { buildDaiLikePermitCallData, buildEip2162PermitCallData } from './buildP import { getPermitDeadline } from './getPermitDeadline' import { getPermitUtilsInstance } from './getPermitUtilsInstance' -import { DEFAULT_PERMIT_VALUE, PERMIT_GAS_LIMIT_MIN, PERMIT_SIGNER } from '../const' +import { DEFAULT_PERMIT_VALUE, PERMIT_GAS_LIMIT_MIN, PERMIT_SIGNER, TOKENS_TO_SKIP_VERSION } from '../const' import { CheckIsTokenPermittableParams, EstimatePermitResult, PermitType } from '../types' const EIP_2162_PERMIT_PARAMS = { @@ -76,13 +76,18 @@ async function actuallyCheckTokenIsPermittable(params: CheckIsTokenPermittablePa let version: string | undefined = undefined - try { - // Required by USDC-mainnet as its version is `2`. - // There might be other tokens that need this as well. - version = await eip2612PermitUtils.getTokenVersion(tokenAddress) - } catch (e) { - // Not a problem, we can (try to) continue without it, and will default to `1` (part of the 1inch lib) - console.debug(`[checkTokenIsPermittable] Failed to get version for ${tokenAddress}`, e) + if (!TOKENS_TO_SKIP_VERSION.has(tokenAddress)) { + // If the token does not outright fails when calling with the `version` value + // returned by the contract, fetch it. + + try { + // Required by USDC-mainnet as its version is `2`. + // There might be other tokens that need this as well. + version = await eip2612PermitUtils.getTokenVersion(tokenAddress) + } catch (e) { + // Not a problem, we can (try to) continue without it, and will default to `1` (part of the 1inch lib) + console.debug(`[checkTokenIsPermittable] Failed to get version for ${tokenAddress}`, e) + } } const baseParams: BaseParams = { From 86e48b3b2baab106d3624c423a3c48a5f6179074 Mon Sep 17 00:00:00 2001 From: Alfetopito Date: Wed, 18 Oct 2023 08:58:17 +0100 Subject: [PATCH 8/8] chore: remove console logs --- .../src/modules/permit/utils/buildPermitCallData.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/cowswap-frontend/src/modules/permit/utils/buildPermitCallData.ts b/apps/cowswap-frontend/src/modules/permit/utils/buildPermitCallData.ts index af4c56f534..aba6099b8f 100644 --- a/apps/cowswap-frontend/src/modules/permit/utils/buildPermitCallData.ts +++ b/apps/cowswap-frontend/src/modules/permit/utils/buildPermitCallData.ts @@ -14,7 +14,6 @@ export async function buildEip2162PermitCallData({ const tokenName = _tokenName === 'USD//C' ? 'USD Coin' : _tokenName const callData = await eip2162Utils.buildPermitCallData(permitParams, chainId, tokenName, ...rest) - console.log(`[buildEip2162PermitCallData]`, callDataParams, callData) // For some reason, the method above removes the permit selector prefix // https://github.com/1inch/permit-signed-approvals-utils/blob/master/src/eip-2612-permit.utils.ts#L92 // Adding it back @@ -26,7 +25,6 @@ export async function buildDaiLikePermitCallData({ callDataParams, }: BuildDaiLikePermitCallDataParams): Promise { const callData = await eip2162Utils.buildDaiLikePermitCallData(...callDataParams) - console.log(`[buildDaiLikePermitCallData]`, callDataParams, callData) // Same as above, but for dai like // https://github.com/1inch/permit-signed-approvals-utils/blob/master/src/eip-2612-permit.utils.ts#L140