Skip to content

Commit

Permalink
fix: nonce from worker signer
Browse files Browse the repository at this point in the history
  • Loading branch information
franciscotobar committed Sep 6, 2024
1 parent 63b84fe commit facacd7
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 18 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@rsksmart/rif-relay-client",
"version": "2.2.5",
"version": "2.2.6",
"private": false,
"description": "This project contains all the client code for the rif relay system.",
"license": "MIT",
Expand Down Expand Up @@ -90,7 +90,7 @@
"typescript": "4.8.2"
},
"peerDependencies": {
"@rsksmart/rif-relay-contracts": "2.1.1-beta.1",
"@rsksmart/rif-relay-contracts": "2.1.1-beta.2",
"ethers": "^5.7.0"
},
"publishConfig": {
Expand Down
39 changes: 30 additions & 9 deletions src/gasEstimator/gasEstimator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,21 @@ import type { EnvelopingTxRequest } from '../common/relayTransaction.types';
import {
POST_RELAY_DEPLOY_GAS_COST,
PRE_RELAY_GAS_COST,
POST_DEPLOY_EXECUTION_FACTOR,
resolveSmartWalletAddress,
standardMaxPossibleGasEstimation,
STORAGE_REFUND,
POST_DEPLOY_EXECUTION,
POST_DEPLOY_NO_EXECUTION,
} from './utils';
import {
getProvider,
type EnvelopingRequest,
type RelayTxOptions,
} from '../common';
import { RelayHub__factory } from '@rsksmart/rif-relay-contracts';
import {
BaseSmartWalletFactory__factory,
RelayHub__factory,
} from '@rsksmart/rif-relay-contracts';
import { signEnvelopingRequest } from '../signer';

const estimateRelayMaxPossibleGas = async (
Expand Down Expand Up @@ -63,10 +68,15 @@ const estimateRelayMaxPossibleGas = async (
* - preEnvelopedTxEstimation: the gas required without the payment and the internal call
* - paymentEstimation: the gas required for the payment
* - internalEstimation: the gas required for the internal call
* - POST_DEPLOY_NO_EXECUTION: when there is no execution in deployment, an additional 4_000 are needed. In the default
* we need to subtract 3500 to avoid over estimating the tx
* - POST_RELAY_DEPLOY_GAS_COST: transfer back cost is always included since we cannot know if the smart wallet is going
* to have some balance after the execution
* - POST_DEPLOY_NO_EXECUTION: when there is no execution in deployment, an additional 4_000 are needed
* - POST_DEPLOY_EXECUTION: when there is execution in deployment, an additional 1_500 are needed
* - STORAGE_REFUND: After the nonces were already touched by a smart wallet deployment or smart wallet execution, we need to subtract 15_000
* - Manually subtract:
* - Without signature, we cannot analyze if there some of the gas costs should be included or not, to avoid underestimating the relay transaction
* the costs are included in all of them. These costs can be subtract by using the following constants:
* - POST_RELAY_DEPLOY_GAS_COST: transfer back cost is always included since we cannot know if the smart wallet is going
* to have some balance after the execution
* - OWNER_ALREADY_TOUCHED: Owner already touched, while we are doing the transfer back the owner may or not be a new account
* @param relayRequest
* @param signer
* @param options
Expand Down Expand Up @@ -96,18 +106,24 @@ const estimateRelayMaxPossibleGasNoSignature = async (
const isDeploy = isDeployRequest(relayRequest);
if (isDeploy) {
const from = signer.address;
const provider = getProvider();
const factory = BaseSmartWalletFactory__factory.connect(
await relayRequest.relayData.callForwarder,
provider
);
const nonce = await factory.nonce(from);
const updatedRelayRequest = {
request: {
...relayRequest.request,
from,
to: constants.AddressZero,
nonce,
},
relayData: {
...relayRequest.relayData,
},
};
const signature = signEnvelopingRequest(updatedRelayRequest, from, signer);
const provider = getProvider();
const relayHub = RelayHub__factory.connect(
await request.relayHub,
provider
Expand Down Expand Up @@ -150,12 +166,17 @@ const estimateRelayMaxPossibleGasNoSignature = async (
let missingGas = 0;
if (isDeploy) {
if (to == constants.AddressZero) {
missingGas = POST_DEPLOY_EXECUTION_FACTOR * 8;
missingGas = POST_DEPLOY_NO_EXECUTION;
} else {
missingGas = POST_DEPLOY_EXECUTION_FACTOR * 3;
missingGas = POST_DEPLOY_EXECUTION;
}
}

const nonce = BigNumber.from(await request.nonce);
if (!nonce.isZero()) {
missingGas -= STORAGE_REFUND;
}

return preEnvelopedTxEstimation
.add(paymentEstimation)
.add(internalEstimation)
Expand Down
1 change: 1 addition & 0 deletions src/gasEstimator/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ export {
standardMaxPossibleGasEstimation,
PRE_RELAY_GAS_COST,
POST_RELAY_DEPLOY_GAS_COST,
OWNER_ALREADY_TOUCHED,
} from './utils';
10 changes: 8 additions & 2 deletions src/gasEstimator/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ import type { RelayTxOptions } from '../common';

const PRE_RELAY_GAS_COST = 74_000;
const POST_RELAY_DEPLOY_GAS_COST = 33_500;
const POST_DEPLOY_EXECUTION_FACTOR = 500;
const POST_DEPLOY_EXECUTION = 1_500;
const POST_DEPLOY_NO_EXECUTION = 4_000;
const STORAGE_REFUND = 15_000;
const OWNER_ALREADY_TOUCHED = 25_000;

const standardMaxPossibleGasEstimation = async (
{ relayRequest, metadata: { signature } }: EnvelopingTxRequest,
Expand Down Expand Up @@ -81,5 +84,8 @@ export {
resolveSmartWalletAddress,
PRE_RELAY_GAS_COST,
POST_RELAY_DEPLOY_GAS_COST,
POST_DEPLOY_EXECUTION_FACTOR,
POST_DEPLOY_EXECUTION,
POST_DEPLOY_NO_EXECUTION,
STORAGE_REFUND,
OWNER_ALREADY_TOUCHED,
};
24 changes: 19 additions & 5 deletions test/gasEstimator/gasEstimator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@ import chaiAsPromised from 'chai-as-promised';
import sinonChai from 'sinon-chai';
import { createSandbox, SinonStubbedInstance } from 'sinon';
import { BigNumber, constants, providers, Wallet } from 'ethers';
import { RelayHub, RelayHub__factory } from '@rsksmart/rif-relay-contracts';
import {
BaseSmartWalletFactory__factory,
RelayHub,
RelayHub__factory,
SmartWalletFactory,
} from '@rsksmart/rif-relay-contracts';

import {
FAKE_DEPLOY_REQUEST,
Expand Down Expand Up @@ -47,6 +52,7 @@ describe('GasEstimator', function () {
request: {
...FAKE_RELAY_TRANSACTION_REQUEST.relayRequest.request,
tokenAmount: 0,
nonce: constants.Zero,
},
},
};
Expand All @@ -57,6 +63,7 @@ describe('GasEstimator', function () {
request: {
...FAKE_DEPLOY_TRANSACTION_REQUEST.relayRequest.request,
tokenAmount: 0,
nonce: constants.Zero,
},
},
};
Expand Down Expand Up @@ -300,7 +307,14 @@ describe('GasEstimator', function () {
},
} as unknown as RelayHub;

const factoryStub = {
nonce: () => Promise.resolve(constants.One),
} as unknown as SmartWalletFactory;

sandbox.stub(RelayHub__factory, 'connect').returns(relayHubStub);
sandbox
.stub(BaseSmartWalletFactory__factory, 'connect')
.returns(factoryStub);
});

describe('with contract execution', function () {
Expand All @@ -314,7 +328,7 @@ describe('GasEstimator', function () {
.add(fakeTokenGas)
.add(fakeInternalGas)
.add(gasEstimatorUtils.POST_RELAY_DEPLOY_GAS_COST)
.add(gasEstimatorUtils.POST_DEPLOY_EXECUTION_FACTOR * 3);
.add(gasEstimatorUtils.POST_DEPLOY_EXECUTION);

expect(estimation).eqls(
expectedEstimation,
Expand All @@ -338,7 +352,7 @@ describe('GasEstimator', function () {
.add(fakeTokenGas)
.add(fakeInternalGas)
.add(gasEstimatorUtils.POST_RELAY_DEPLOY_GAS_COST)
.add(gasEstimatorUtils.POST_DEPLOY_EXECUTION_FACTOR * 3);
.add(gasEstimatorUtils.POST_DEPLOY_EXECUTION);

expect(estimation).eqls(
expectedEstimation,
Expand Down Expand Up @@ -370,7 +384,7 @@ describe('GasEstimator', function () {
const expectedEstimation = deployEstimation
.add(fakeTokenGas)
.add(gasEstimatorUtils.POST_RELAY_DEPLOY_GAS_COST)
.add(gasEstimatorUtils.POST_DEPLOY_EXECUTION_FACTOR * 8);
.add(gasEstimatorUtils.POST_DEPLOY_NO_EXECUTION);

expect(estimation).eqls(
expectedEstimation,
Expand All @@ -393,7 +407,7 @@ describe('GasEstimator', function () {
const expectedEstimation = deployEstimation
.add(fakeTokenGas)
.add(gasEstimatorUtils.POST_RELAY_DEPLOY_GAS_COST)
.add(gasEstimatorUtils.POST_DEPLOY_EXECUTION_FACTOR * 8);
.add(gasEstimatorUtils.POST_DEPLOY_NO_EXECUTION);

expect(estimation).eqls(
expectedEstimation,
Expand Down

0 comments on commit facacd7

Please sign in to comment.