Open vdamle opened 7 months ago
To verify that the approval is correctly done, I wrote a script to check the allowance:
import hre from 'hardhat';
import { JsonRpcProvider, MaxUint256, Wallet } from 'ethers';
const WETH_CONTRACT_ADDRESS = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2';
const WALLET_ADDRESS = '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266';
const SWAP_ROUTER_ADDRESS = '0xE592427A0AEce92De3Edee1F18E0157C05861564';
const SWAP_ROUTER_V2_ADDRESS = '0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45';
const ERC20_ABI = [
'function approve(address _spender,uint256 _value) returns (bool)',
'function allowance(address _owner,address _spender) view returns (uint256)',
'function balanceOf(address _owner) view returns (uint256)',
'function totalSupply() view returns (uint256)'
]
async function main() {
const rpc = new JsonRpcProvider( 'http://localhost:8545' ) ;
const wallet = new Wallet( '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80' , rpc);
const weth_contract = new hre.ethers.Contract(WETH_CONTRACT_ADDRESS, ERC20_ABI, wallet);
console.log(`checking allowance for ${SWAP_ROUTER_ADDRESS}`)
const allowance = await weth_contract.allowance(WALLET_ADDRESS, SWAP_ROUTER_ADDRESS);
console.log(`Allowance: ${allowance}`);
}
main()
.then(() => console.log('Execution complete'))
.catch((e) => console.error('unable to run hardhat script', e));
and I see that the swap router allowance is correctly resported:
➜ hardhat-scripts node scripts/allowance.js
checking allowance for 0xE592427A0AEce92De3Edee1F18E0157C05861564
Allowance: 2000000000000000000000
Execution complete
Same thing, I also got an error with eth_estimateGas
at first
But now the STF error
@vdamle did you solve the problem?
@vdamle @69popovvlad I have the same problem. Did you guys solve?
@vdamle @69popovvlad I have the same problem. Did you guys solve?
@animalconcerts Yes, I somehow solved it, but I don’t remember exactly how, because I solved several problems that kept popping up:
try increasing the gas limit GAS_LIMIT=2000000
then try checking through the allowance
method (you can use static call btw) to see how many tokens you have approved
and also approve
the required amount for the contract, if it is not enough
Also, if you plan to use uniswap permanently, you can approve the maximum number of tokens
Here is my code below as an example for you:
TransactionState.ts
export enum TransactionState {
Failed = 'Failed',
New = 'New',
Rejected = 'Rejected',
Sending = 'Sending',
Sent = 'Sent',
}
Some utils script
import { Wallet, ethers } from "ethers";
import { Token } from "@uniswap/sdk-core";
import ERC20 from '@eth-optimism/contracts-bedrock/forge-artifacts/ERC20.sol/ERC20.json' assert { type: 'json' };
/**
* @param tokenAdress Get ERC20 token contract
* @param wallet The wallet for which you need to find out the token balance
* @returns Signed contract of the ERC20 token
*/
export function getTokenContractERC20(tokenAdress: string, wallet: Wallet): Contract {
return new ethers.Contract(tokenAdress, ERC20.abi, wallet);
}
export function tokenAmountToWei(token: Token, amount: number) {
return ethers.parseUnits(amount.toString(), token.decimals);
}
WalletApi.ts
import { Contract, Wallet, ethers } from "ethers";
import { Token } from "@uniswap/sdk-core";
import { TransactionState } from "./TransactionState.js";
async approveForUniswap(token0: Token, token1: Token, wallet: Wallet, amount: number) {
const amountToken0 = amount < 0 ? ethers.MaxUint256 : tokenAmountToWei(token0, amount);
const amountToken1 = amount < 0 ? ethers.MaxUint256 : tokenAmountToWei(token1, amount);
const tx0 = await approve(SWAP_ROUTER_ADDRESS, token0, amountToken0, wallet);
const tx1 = await approve(SWAP_ROUTER_ADDRESS, token1, amountToken1, wallet);
const tx2 = await approve(NONFUNGIBLE_POSITION_ADDRESS, token0, amountToken0, wallet);
const tx3 = await approve(NONFUNGIBLE_POSITION_ADDRESS, token1, amountToken1, wallet);
return tx0 == tx1 && tx2 == tx3 && tx0 == tx3 && tx0 == TransactionState.Sent ? TransactionState.Sent : TransactionState.Failed;
}
async approve(spenderAddress: string, token: Token, amountWei: bigint, wallet: Wallet) {
try {
const tokenContract = getTokenContractERC20(token.address, wallet);
let allowancewei = await tokenContract.allowance.staticCall(
wallet.address,
spenderAddress,
);
if (amountWei <= allowancewei) {
return TransactionState.Sent;
}
const tx = await tokenContract.approve(
spenderAddress,
ethers.MaxUint256
);
await tx.wait();
allowancewei = await tokenContract.allowance.staticCall(
wallet.address,
spenderAddress,
);
if (amountWei > allowancewei) {
throw new Error(`Allowance amount of tokens ${allowancewei} is less than the required amount ${amountWei}`);
}
return TransactionState.Sent;
}
catch (error) {
console.error(`Approve error:: ${error}`);
return TransactionState.Failed;
}
}
My dependencies btw
"dependencies": {
"@eth-optimism/contracts-bedrock": "0.16.2",
"@uniswap/sdk-core": "4.0.9",
"@uniswap/v3-core": "1.0.1",
"@uniswap/v3-periphery": "1.4.4",
"@uniswap/v3-sdk": "3.10.0",
"ethers": "6.9.0",
"jsbi": "3.2.5"
},
I've been attempting to get the example trade to work using a mainnet fork setup with Anvil, as documented here
As far as I can tell, the example doesn't work with the latest version of the libraries:
The error is always:
Initially, I was seeing an error with
eth_estimateGas
:So I switched to using a pre-defined
gasLimit: 5_000_000
in the Tx.The steps for getting a quote and approving the swap router for token transfers work but the actual swap fails. As a minor detail, I'm not using the UI code but invoking the functions directly like below, so I can run the example from the command line:
I can see that the quote returns valid data:
I'd appreciate any input to troubleshoot this issue. I'd be happy to submit a PR to the docs/example code if there is any change required with the latest version of the v3 SDK.