Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix/resend-transaction #130

Merged
merged 3 commits into from
Oct 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@rsksmart/rif-relay-server",
"version": "2.2.1",
"version": "2.2.2",
"private": false,
"description": "This project contains all the server code for the rif relay system.",
"license": "MIT",
Expand Down
2 changes: 1 addition & 1 deletion src/Conversions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export const toNativeWeiFrom = ({
const bigxRate = BigNumberJs(xRate ?? '0');

if (bigAmount.isZero() || bigxRate.isZero()) {
return BigNumberJs(constants.Zero.toString());
return BigNumberJs(0);
}

const amountAsFraction = toPrecision({
Expand Down
16 changes: 12 additions & 4 deletions src/RegistrationManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import {
import type { ManagerEvent, PastEventOptions } from './definitions/event.type';
import { getServerConfig } from './ServerConfigParams';
import { getPastEventsForHub } from './getPastEventsForHub';
import type { RelayManagerData } from '@rsksmart/rif-relay-client';
franciscotobar marked this conversation as resolved.
Show resolved Hide resolved

export type RelayServerRegistryInfo = {
url: string;
Expand Down Expand Up @@ -68,7 +69,7 @@ export class RegistrationManager {

private readonly _txStoreManager: TxStoreManager;

private _relayData: IRelayHub.RelayManagerDataStruct | undefined;
private _relayData: RelayManagerData | undefined;

private _lastWorkerAddedTransaction: TypedEvent | undefined;

Expand Down Expand Up @@ -186,7 +187,14 @@ export class RegistrationManager {
}
}

this._relayData = await this.getRelayData();
const relayData = await this.getRelayData();

this._relayData = {
currentlyStaked: await relayData.currentlyStaked,
manager: await relayData.manager,
registered: await relayData.registered,
url: await relayData.url,
};

for (const eventData of hubEventsSinceLastScan) {
switch (eventData.event) {
Expand Down Expand Up @@ -423,7 +431,7 @@ export class RegistrationManager {
const provider = getProvider();

const gasPrice = await provider.getGasPrice();
const gasLimit = BigNumber.from(minTxGasCost ? minTxGasCost : 21000);
const gasLimit = BigNumber.from(minTxGasCost ?? 21000);
const txCost = gasLimit.mul(gasPrice);

const managerBalance = await provider.getBalance(this._managerAddress);
Expand Down Expand Up @@ -470,7 +478,7 @@ export class RegistrationManager {

const provider = getProvider();
const gasPrice = await provider.getGasPrice();
const gasLimit = BigNumber.from(minTxGasCost ? minTxGasCost : 21000);
const gasLimit = BigNumber.from(minTxGasCost ?? 21000);
const txCost = gasPrice.mul(gasLimit);

const workerBalance = await provider.getBalance(this._workerAddress);
Expand Down
44 changes: 22 additions & 22 deletions src/RelayServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -266,29 +266,26 @@ export class RelayServer extends EventEmitter {
contracts: { relayHubAddress },
} = this.config;

const relayHubAddressValue = await metadata.relayHubAddress;

// Check that the relayHub is the correct one
if (
metadata.relayHubAddress.toString().toLowerCase() !==
relayHubAddress.toLowerCase()
) {
if (relayHubAddressValue.toLowerCase() !== relayHubAddress.toLowerCase()) {
throw new Error(
`Wrong hub address.\nRelay server's hub address: ${
this.config.contracts.relayHubAddress
}, request's hub address: ${metadata.relayHubAddress.toString()}\n`
`Wrong hub address.\nRelay server's hub address: ${this.config.contracts.relayHubAddress}, request's hub address: ${relayHubAddressValue}\n`
);
}

const feesReceiver = relayRequest.relayData.feesReceiver.toString();
const feesReceiver = await relayRequest.relayData.feesReceiver;
// Check the relayWorker (todo: once migrated to multiple relays, check if exists)
if (feesReceiver.toLowerCase() !== this.feesReceiver.toLowerCase()) {
throw new Error(`Wrong fees receiver address: ${feesReceiver}\n`);
}

const gasPrice = relayRequest.relayData.gasPrice.toString();
const gasPrice = await relayRequest.relayData.gasPrice;
// Check that the gasPrice is initialized & acceptable
if (this.gasPrice.gt(gasPrice)) {
throw new Error(
`Unacceptable gasPrice: relayServer's gasPrice:${this.gasPrice.toString()} request's gasPrice: ${gasPrice}`
`Unacceptable gasPrice: relayServer's gasPrice:${this.gasPrice.toString()} request's gasPrice: ${gasPrice.toString()}`
);
}

Expand All @@ -299,9 +296,11 @@ export class RelayServer extends EventEmitter {
);
}

validateVerifier(envelopingRequest: EnvelopingTxRequest): void {
const callVerifier =
envelopingRequest.relayRequest.relayData.callVerifier.toString();
async validateVerifier(
envelopingRequest: EnvelopingTxRequest
): Promise<void> {
const callVerifier = await envelopingRequest.relayRequest.relayData
.callVerifier;
if (!this.isTrustedVerifier(callVerifier)) {
throw new Error(`Invalid verifier: ${callVerifier}`);
}
Expand All @@ -320,8 +319,8 @@ export class RelayServer extends EventEmitter {
async validateRequestWithVerifier(
envelopingTransaction: EnvelopingTxRequest
): Promise<void> {
const verifier =
envelopingTransaction.relayRequest.relayData.callVerifier.toString();
const verifier = await envelopingTransaction.relayRequest.relayData
.callVerifier;

if (!this.isTrustedVerifier(verifier)) {
throw new Error('Invalid verifier');
Expand Down Expand Up @@ -410,9 +409,7 @@ export class RelayServer extends EventEmitter {

return {
maxPossibleGas: initialGasEstimation,
maxPossibleGasWithFee: initialGasEstimation.add(
fee.toFixed(0).toString()
),
maxPossibleGasWithFee: initialGasEstimation.add(fee.toFixed(0)),
};
}

Expand Down Expand Up @@ -557,17 +554,20 @@ export class RelayServer extends EventEmitter {

const provider = getProvider();

const relayHubAddress = await envelopingTransaction.metadata
.relayHubAddress;
const gasPrice = await envelopingTransaction.relayRequest.relayData
.gasPrice;

const currentBlock = await provider.getBlockNumber();
const details: SendTransactionDetails = {
signer: this.workerAddress,
serverAction: ServerAction.RELAY_CALL,
method,
destination: envelopingTransaction.metadata.relayHubAddress.toString(),
destination: relayHubAddress,
gasLimit: maxPossibleGasWithViewCall,
creationBlockNumber: currentBlock,
gasPrice: BigNumber.from(
envelopingTransaction.relayRequest.relayData.gasPrice
),
gasPrice: BigNumber.from(gasPrice.toString()),
};
const txDetails = await this.transactionManager.sendTransaction(details);
// after sending a transaction is a good time to check the worker's balance, and replenish it.
Expand Down
11 changes: 7 additions & 4 deletions src/TransactionManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -238,8 +238,11 @@ data | 0x${transaction.data ?? ''}
): Promise<SignedTransactionDetails> {
// Resend transaction with exactly the same values except for gas price
const txToSign: PopulatedTransaction = {
...tx,
to: tx.to,
gasLimit: tx.gasLimit,
gasPrice: newGasPrice,
data: tx.data,
nonce: tx.nonce,
};

const keyManager = this.managerKeyManager.isSigner(tx.from)
Expand Down Expand Up @@ -288,10 +291,10 @@ data | 0x${transaction.data ?? ''}
const bigRetryGasPriceFactor = BigNumberJs(
this.config.blockchain.retryGasPriceFactor
);
const oldPrice = BigNumber.from(oldGasPrice);
const bigOldGasPrice = BigNumberJs(oldPrice.toString());

const bigNewGasPrice = bigRetryGasPriceFactor.multipliedBy(bigOldGasPrice);
const bigNewGasPrice = bigRetryGasPriceFactor.multipliedBy(
oldGasPrice ? oldGasPrice.toString() : 0
);

let newGasPrice = BigNumber.from(bigNewGasPrice.toFixed(0));

Expand Down
8 changes: 4 additions & 4 deletions src/Utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { getDefaultProvider, providers, utils } from 'ethers';
import { getAddress } from 'ethers/lib/utils';
import ow from 'ow';
import { getServerConfig } from './ServerConfigParams';
import type { RelayManagerData } from '@rsksmart/rif-relay-client';

const CONFIG_CONTRACTS = 'contracts';
const CONFIG_BLOCKCHAIN = 'blockchain';
Expand Down Expand Up @@ -87,18 +88,17 @@ export function isSecondEventLater(a: TypedEvent, b: TypedEvent): boolean {
}

export function isRegistrationValid(
relayData: IRelayHub.RelayManagerDataStruct | undefined,
relayData: RelayManagerData | undefined,
managerAddress: string
): boolean {
if (relayData) {
const manager = relayData.manager.toString();
const {
app: { url: serverUrl },
} = getServerConfig();

return (
isSameAddress(manager, managerAddress) &&
relayData.url.toString() === serverUrl
isSameAddress(relayData.manager, managerAddress) &&
relayData.url === serverUrl
);
}

Expand Down
61 changes: 32 additions & 29 deletions src/relayServerUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,11 @@ async function calculateFee(
}

const { transferFeePercentage } = appConfig;

const data = await relayRequest.request.data;
//Even if transferFeePercentage = 0, it has priority over gas fee
if (
transferFeePercentage >= 0 &&
isTransferOrTransferFrom(relayRequest.request.data.toString())
) {
if (transferFeePercentage >= 0 && isTransferOrTransferFrom(data.toString())) {
const transferFee = await calculateFeeFromTransfer(
relayRequest.request.data.toString(),
data.toString(),
transferFeePercentage,
relayRequest
);
Expand Down Expand Up @@ -97,12 +94,12 @@ async function calculateFixedUsdFee(
envelopingRequest: EnvelopingRequest,
fixedUsdFee: number
) {
const tokenAddress = envelopingRequest.request.tokenContract.toString();
const gasPrice = envelopingRequest.relayData.gasPrice.toString();
const tokenContractAddress = await envelopingRequest.request.tokenContract;
const gasPrice = await envelopingRequest.relayData.gasPrice;

const provider = getProvider();

const tokenInstance = ERC20__factory.connect(tokenAddress, provider);
const tokenInstance = ERC20__factory.connect(tokenContractAddress, provider);
const tokenSymbol = await tokenInstance.symbol();

const exchangeRate = await getExchangeRate(US_DOLLAR_SYMBOL, tokenSymbol);
Expand All @@ -112,8 +109,8 @@ async function calculateFixedUsdFee(

return await convertTokenToGas(
fixedFeeInToken.toString(),
tokenAddress,
gasPrice
tokenContractAddress,
gasPrice.toString()
);
}

Expand All @@ -125,7 +122,7 @@ async function calculateFixedUsdFee(
async function calculateFeeFromTransfer(
data: string,
transferFeePercentage: number,
relayRequest: EnvelopingRequest
envelopingRequest: EnvelopingRequest
): Promise<BigNumberJs> {
if (!isTransferOrTransferFrom(data)) {
return BigNumberJs(0);
Expand All @@ -140,11 +137,13 @@ async function calculateFeeFromTransfer(
const valueInDecimal = BigNumberJs('0x' + valueHex);

const feeInToken = valueInDecimal.multipliedBy(transferFeePercentage);
const tokenContractAddress = await envelopingRequest.request.tokenContract;
const gasPrice = await envelopingRequest.relayData.gasPrice;

return await convertTokenToGas(
feeInToken.toString(),
relayRequest.request.tokenContract.toString(),
relayRequest.relayData.gasPrice.toString()
tokenContractAddress,
gasPrice.toString()
);
}

Expand Down Expand Up @@ -196,8 +195,8 @@ async function validateIfGasAmountIsAcceptable(
const relayRequest = envelopingTransaction.relayRequest;

const estimatedDestinationGasCost = await estimateInternalCallGas({
from: relayRequest.relayData.callForwarder.toString(),
to: relayRequest.request.to.toString(),
from: relayRequest.relayData.callForwarder,
Fixed Show fixed Hide fixed
to: relayRequest.request.to,
Fixed Show fixed Hide fixed
gasPrice: relayRequest.relayData.gasPrice,
data: relayRequest.request.data,
});
Expand All @@ -207,8 +206,9 @@ async function validateIfGasAmountIsAcceptable(
);

const { gas } = relayRequest.request as RelayRequestBody;
const gasValue = await gas;
const bigGasFromRequestMaxAgreed = bigMaxEstimatedGasDeviation.multipliedBy(
gas.toString()
gasValue.toString()
);

if (estimatedDestinationGasCost.gt(bigGasFromRequestMaxAgreed.toFixed(0))) {
Expand All @@ -227,14 +227,19 @@ async function validateIfTokenAmountIsAcceptable(
return;
}

const { tokenAmount, tokenContract } =
envelopingTransaction.relayRequest.request;
const { gasPrice } = envelopingTransaction.relayRequest.relayData;
const {
request: { tokenAmount, tokenContract },
relayData: { gasPrice },
} = envelopingTransaction.relayRequest;

const tokenContractAddress = await tokenContract;
const tokenAmountValue = await tokenAmount;
const gasPriceValue = await gasPrice;

const tokenAmountInGas = await convertTokenToGas(
tokenAmount.toString(),
tokenContract.toString(),
gasPrice.toString()
tokenAmountValue.toString(),
tokenContractAddress,
gasPriceValue.toString()
);

const isTokenAmountAcceptable = tokenAmountInGas.isGreaterThanOrEqualTo(
Expand Down Expand Up @@ -294,14 +299,12 @@ async function convertGasToTokenAndNative(
relayRequest: EnvelopingRequest,
initialEstimation: BigNumber
) {
const gasPrice = relayRequest.relayData.gasPrice.toString();
const gasPrice = await relayRequest.relayData.gasPrice;
const tokenContractAddress = await relayRequest.request.tokenContract;

const provider = getProvider();

const tokenInstance = ERC20__factory.connect(
relayRequest.request.tokenContract.toString(),
provider
);
const tokenInstance = ERC20__factory.connect(tokenContractAddress, provider);

const token: ExchangeToken = {
instance: tokenInstance,
Expand All @@ -328,7 +331,7 @@ async function convertGasToTokenAndNative(
valueInToken: initialEstimationInToken.toString(),
valueInNative: initialEstimationInNative.toString(),
exchangeRate: xRate,
gasPrice,
gasPrice: gasPrice.toString(),
};
}

Expand Down
Loading