diff --git a/packages/common/src/LightTruffleContract.ts b/packages/common/src/LightTruffleContract.ts index aa2d64225..01c4b788a 100644 --- a/packages/common/src/LightTruffleContract.ts +++ b/packages/common/src/LightTruffleContract.ts @@ -55,7 +55,6 @@ function retype (outputs?: readonly JsonFragment[], ret?: any): any { export class Contract { provider!: JsonRpcProvider - signer!: JsonRpcSigner constructor (readonly contractName: string, readonly abi: JsonFragment[]) { } @@ -74,7 +73,8 @@ export class Contract { // the 'getAddress' may throw if the underlying provider does not return addresses. let signer: JsonRpcSigner | undefined try { - const signerFromAddress = await this.signer.getAddress() + const noAddressSetSigner: JsonRpcSigner = this.provider.getSigner() + const signerFromAddress = await noAddressSetSigner.getAddress() signer = this.provider.getSigner(signerFromAddress) } catch (e: any) { // nothing to do here - signer does not have accounts and can only work with ephemeral keys @@ -129,7 +129,6 @@ export class Contract { setProvider (provider: JsonRpcProvider, _: unknown): void { this.provider = provider - this.signer = provider.getSigner() } } diff --git a/packages/paymasters/src/TokenPaymasterInteractor.ts b/packages/paymasters/src/TokenPaymasterInteractor.ts index 07e92bf2d..a24ddded3 100644 --- a/packages/paymasters/src/TokenPaymasterInteractor.ts +++ b/packages/paymasters/src/TokenPaymasterInteractor.ts @@ -2,7 +2,15 @@ import BN from 'bn.js' import { JsonRpcProvider, ExternalProvider } from '@ethersproject/providers' -import { Address, Contract, TruffleContract, wrapWeb3JsProvider } from '@opengsn/common' +import { + Address, + Contract, + LoggerInterface, + TruffleContract, + constants, + toBN, + wrapWeb3JsProvider +} from '@opengsn/common' import { IERC20Instance } from '@opengsn/contracts' import { IChainlinkOracleInstance, PermitERC20UniswapV3PaymasterInstance } from '../types/truffle-contracts' @@ -26,6 +34,7 @@ export class TokenPaymasterInteractor { private readonly PermitERC20UniswapV3Paymaster: Contract private readonly ChainlinkOracle: Contract private readonly paymasterAddress: Address + private readonly logger: LoggerInterface tokenAddress?: Address tokenSwapData?: TokenSwapData @@ -35,9 +44,11 @@ export class TokenPaymasterInteractor { constructor ( provider: JsonRpcProvider | ExternalProvider, - paymasterAddress: Address + paymasterAddress: Address, + logger: LoggerInterface ) { this.paymasterAddress = paymasterAddress + this.logger = logger this.provider = wrapWeb3JsProvider(provider) this.ERC20Instance = TruffleContract({ contractName: 'ERC20Instance', @@ -108,8 +119,28 @@ export class TokenPaymasterInteractor { const tokenSwapData = await this.paymaster.getTokenSwapData(tokenAddress) const chainlinkInstance = await this._createChainlinkOracleInstance(tokenSwapData.priceFeed) const quote = await chainlinkInstance.latestAnswer() - const actualQuote = await this.paymaster.toActualQuote(quote.toString(), tokenSwapData.priceDivisor.toString()) - const amountInWei = await this.paymaster.tokenToWei(tokenAmount.toString(), actualQuote.toString(), tokenSwapData.reverseQuote) - return { actualQuote, amountInWei } + const description = `(tokenAddress=${tokenAddress} tokenAmount=${tokenAmount.toString()} priceFeed=${tokenSwapData.priceFeed} quote=${quote.toString()} priceDivisor=${tokenSwapData.priceDivisor.toString()} reverseQuote=${tokenSwapData.reverseQuote})` + this.logger.debug(`Converting token balance to Ether quote ${description}`) + try { + const actualQuote = await this.paymaster.toActualQuote(quote.toString(), tokenSwapData.priceDivisor.toString()) + this.logger.debug(`actualQuote=${actualQuote.toString()}`) + if (tokenAmount.gt(toBN(10).pow(toBN(30)))) { + this.logger.debug(`Amount to convert is > 1e30 which is infinity in most cases (tokenAddress=${tokenAddress})`) + return { + actualQuote: toBN(0), + amountInWei: constants.MAX_UINT256 + } + } + const amountInWei = await this.paymaster.tokenToWei(tokenAmount.toString(), actualQuote.toString(), tokenSwapData.reverseQuote) + this.logger.debug(`amountInWei=${amountInWei.toString()}`) + return { actualQuote, amountInWei } + } catch (error: any) { + this.logger.error(`Failed to convert token balance to Ether quote ${description}`) + this.logger.error(error) + return { + actualQuote: toBN(0), + amountInWei: toBN(0) + } + } } } diff --git a/packages/paymasters/src/TokenPaymasterProvider.ts b/packages/paymasters/src/TokenPaymasterProvider.ts index c64a8b143..215906107 100644 --- a/packages/paymasters/src/TokenPaymasterProvider.ts +++ b/packages/paymasters/src/TokenPaymasterProvider.ts @@ -59,7 +59,7 @@ export class TokenPaymasterProvider extends RelayProvider { const chainId = this.origProvider.network.chainId const paymasterAddress = getPaymasterAddressByTypeAndChain(this.config?.paymasterAddress, chainId, this.logger) - this.tokenPaymasterInteractor = new TokenPaymasterInteractor(this.origProvider, paymasterAddress as any) + this.tokenPaymasterInteractor = new TokenPaymasterInteractor(this.origProvider, paymasterAddress as any, this.logger) await this.tokenPaymasterInteractor.init() this.relayClient.dependencies.asyncPaymasterData = this._buildPaymasterData.bind(this) if (permitERC20TokenForGas == null) {