tradingstrategy-ai/frontend

Deposit payment contract authorization fails in some wallets

Closed this issue · 1 comments

Issue

When attempting to make a deposit into a strategy, the contract call submit payment fails with the error below on some wallets. So far, this appears to occur on: Keystone hardware wallet, Uniswap mobile wallet, sometime on Rabby injected wallet.

Example error message

ContractFunctionExecutionError: The contract function "buySharesOnBehalfUsingTransferWithAuthorizationAndTermsOfService" reverted with the following reason:
GasAbstraction: invalid signature

Contract Call:
  address:   0xb71F8d2cd7E6aC4d0C6810a293a1Ea0fCaE9d6a4
  function:  buySharesOnBehalfUsingTransferWithAuthorizationAndTermsOfService(address from, address to, uint256 value, uint256 validAfter, uint256 validBefore, bytes32 nonce, uint8 v, bytes32 r, bytes32 s, uint256 minSharesQuantity, bytes32 termsOfServiceHash, bytes termsOfServiceSignature)
  args:                                                                      (0x23de77c515aa58A0234B9b4f43dB4FCdB336708E, 0xb71F8d2cd7E6aC4d0C6810a293a1Ea0fCaE9d6a4, 100000, 0, 1712165533, 0x48752137490dd68e41d92e47967daf8e3903c52162ded89f9f2d27bad25f9ef1, 27, 0x099ef0bf8a6e29fe619635cd65e927cf463aa88cc43d1c398a055e7554553d0b, 0x1a8a3086fe35f8172fe7b657c62f84450f8f3d9382ec32656170c6e9703b9313, 1, 0x65cb3999902d514e798a845c52be591f102789e315d58e16940f82fa0df6727b, 0x8ae991159a342312181a187f080ea7b7c6e48783ff19ed979f42c782598736615065aa5cb4de51f793d0c499032e844684ee426c85a1dca4551b38bc35ecaa251c)
  sender:    0x23de77c515aa58A0234B9b4f43dB4FCdB336708E

Docs: https://viem.sh/docs/contract/simulateContract
Version: viem@2.5.0
    at nh (getContractError.js:26:12)
    at A (simulateContract.js:73:15)
    at async F (simulateContract.js:23:33)
    at async p (+page.svelte:55:11)

This was fixed for Uniswap wallet with #714.

The issue had to do with the non-standard implementation of EIP-3009 on the Polygon bridged USDC token. That token requires a different EIP-712 domain that what is defined in the standard.

The issue for Uniswap wallet had to do with the domain properties that are included with the signature request:

function getTypes(chainId: number, tokenVersion: string, transferMethod: TransferMethod) {
const types: TypedData = {
EIP712Domain: getEIP712Domain(chainId, tokenVersion)
};
types[transferMethod] = [
{ name: 'from', type: 'address' },
{ name: 'to', type: 'address' },
{ name: 'value', type: 'uint256' },
{ name: 'validAfter', type: 'uint256' },
{ name: 'validBefore', type: 'uint256' },
{ name: 'nonce', type: 'bytes32' }
];
return types;
}

The EIP-712 spec allows for any combination of the following fields to be included: name, version, chainId, verifyingContract, salt:
https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator

The fields used by EIP-3009 (transfer with authorization) are the above fields minus salt:
https://eips.ethereum.org/EIPS/eip-3009#use-with-web3-providers

But Polygon bridged USDC doesn't follow the standard – it includes salt but excludes chainId. We have special-case code for this here:

function getEIP712Domain(chainId: number, tokenVersion: string) {
if (chainId === 137 && tokenVersion === '1') {
return [
{ name: 'name', type: 'string' },
{ name: 'version', type: 'string' },
{ name: 'verifyingContract', type: 'address' },
{ name: 'salt', type: 'bytes32' }
];
} else {
return [
{ name: 'name', type: 'string' },
{ name: 'version', type: 'string' },
{ name: 'chainId', type: 'uint256' },
{ name: 'verifyingContract', type: 'address' }
];
}
}

However… we still passed along all of the fields in the domain object. In theory, the wallet implementation of eth_signTypedData should ignore any fields that aren't included in the specified EIP712Domain. But apparently some wallet's don't … so they reject a signature request where the domain fields don't match the specified EIP712Domain.

The fix in #714 was to only pass the domain fields required by the EIP712Domain. This fixed the issue for Uniswap wallet. Unfortunately, the signature still fails in Keystone hardware wallet.