Skip to content
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
5 changes: 4 additions & 1 deletion .circleci/config.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,12 +9,14 @@ references:
ipfs_image: &ipfs_image
image: requestnetwork/request-ipfs:v0.13.0
ganache_image: &ganache_image
image: trufflesuite/ganache-cli:v6.8.2
image: trufflesuite/ganache:v7.6.0
command:
- '-l'
- '90000000'
- '-m'
- 'candy maple cake sugar pudding cream honey rich smooth crumble sweet treat'
- '-k'
- 'london'
graph_image: &graph_image
image: graphprotocol/graph-node:v0.25.0
# wait for ganache, then start
Expand DownExpand Up@@ -288,6 +290,7 @@ jobs:
test-utils:
docker:
- *node_image
- *ganache_image
working_directory: *working_directory
steps:
- attach_workspace:
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -104,7 +104,7 @@ export function encodeRequestErc20ApprovalWithoutSwap(
options?: IRequestPaymentOptions,
): IPreparedTransaction | void {
const paymentNetwork = getPaymentNetworkExtension(request)?.id;
const overrides = options?.overrides ? options.overrides : undefined;
const overrides = options?.overrides;

switch (paymentNetwork) {
case ExtensionTypes.PAYMENT_NETWORK_ID.ERC20_PROXY_CONTRACT:
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -96,11 +96,14 @@ describe('any-to-eth-proxy', () => {
const fromNewBalance = await provider.getBalance(wallet.address);
const toNewBalance = await provider.getBalance(paymentAddress);
const feeNewBalance = await provider.getBalance(feeAddress);
const gasPrice = (await provider.getFeeData()).gasPrice || 0;
const gasPrice = confirmedTx.effectiveGasPrice;

// Check each balance
expect(
fromOldBalance.sub(fromNewBalance).sub(confirmedTx.gasUsed.mul(gasPrice)).toString(),
fromOldBalance
.sub(fromNewBalance)
.sub(confirmedTx.cumulativeGasUsed.mul(gasPrice))
.toString(),
// expectedAmount: 1.00
// feeAmount: + .02
// = 1.02
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -23,13 +23,13 @@ import {
erc20SwapToPayArtifact,
erc20SwapConversionArtifact,
} from '@requestnetwork/smart-contracts';
import { DAIX_ADDRESS } from './erc777-stream.test';

/* eslint-disable @typescript-eslint/no-unused-expressions */
/* eslint-disable @typescript-eslint/await-thenable */

const erc20ContractAddress = '0x9FBDa871d559710256a2502A2517b794B482Db40';
const feeAddress = '0xC5fdf4076b8F3A5357c5E395ab970B5B54098Fef';
const DAIX_ADDRESS = '0x7D782D2cc2755CA324De57D42e28Cc63278dFE12';

// Cf. ERC20Alpha in TestERC20.sol
const alphaContractAddress = '0x38cF23C52Bb4B13F051Aec09580a2dE845a7FA35';
Expand Down
3 changes: 1 addition & 2 deletions packages/payment-processor/test/payment/encoder.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -272,7 +272,7 @@ beforeAll(async () => {
await alphaContract.transfer(mainAddress, BigNumber.from('500000000000000000000'));
const erc20Contract = ERC20__factory.connect(erc20ContractAddress, wallet);
await erc20Contract.transfer(mainAddress, BigNumber.from('500000000000000000000'));
wallet.sendTransaction({
await wallet.sendTransaction({
to: mainAddress,
value: BigNumber.from('10000000000000000000'),
});
Expand DownExpand Up@@ -314,7 +314,6 @@ describe.each([
provider,
options,
);

let tx = await wallet.sendTransaction(encodedTransactions[0]);
let confirmedTx = await tx.wait(1);
expect(confirmedTx.status).toBe(1);
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -241,6 +241,8 @@ describe('erc777-stream', () => {

// wait 2 seconds of streaming to avoid failing
await new Promise((r) => setTimeout(r, 2000));
await provider.send('evm_mine', []);
await provider.send('evm_mine', []);

// Stopping fDAIX stream request
tx = await closeErc777StreamRequest(validRequest, wallet);
Expand All@@ -260,7 +262,7 @@ describe('erc777-stream', () => {
providerOrSigner: provider,
});
expect(paymentFlowRate).toBe('0');
});
}, 10000);
});

describe('makeErc777OneOffPayment', () => {
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -150,7 +150,7 @@ describe('payBatchProxyRequest', () => {
balanceEthAfter
.add(BigNumber.from(validRequest.expectedAmount).mul(2).toString())
.add('24')
.add(confirmedTx.gasUsed?.mul(tx?.gasPrice ?? 1))
.add(confirmedTx.cumulativeGasUsed.mul(confirmedTx.effectiveGasPrice))
.toString(),
);
expect(balanceFeeEthAfter.toString()).toBe(balanceFeeEthBefore.add('24').toString());
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -122,7 +122,7 @@ describe('payEthFeeProxyRequest', () => {
balanceEthAfter
.add(validRequest.expectedAmount)
.add('2')
.add(confirmedTx.gasUsed?.mul(tx?.gasPrice ?? 1))
.add(confirmedTx.cumulativeGasUsed.mul(confirmedTx.effectiveGasPrice))
.toString(),
);
expect(balanceFeeEthAfter.toString()).toBe(balanceFeeEthBefore.add('2').toString());
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,7 +18,6 @@ const mnemonic = 'candy maple cake sugar pudding cream honey rich smooth crumble
const paymentAddress = '0xf17f52151EbEF6C7334FAD080c5704D77216b732';
const provider = new providers.JsonRpcProvider('http://localhost:8545');
const wallet = Wallet.fromMnemonic(mnemonic).connect(provider);
const gasPrice = 2 * 10 ** 10; // await provider.getGasPrice()

const validRequest: ClientTypes.IRequestData = {
balance: {
Expand DownExpand Up@@ -124,10 +123,9 @@ describe('payEthInputDataRequest', () => {
expect(confirmedTx.status).toBe(1);
// new_balance = old_balance + amount + fees
expect(balanceAfter).toEqual(
balanceBefore.sub(validRequest.expectedAmount).sub(confirmedTx.gasUsed.mul(gasPrice) || 0),
);
expect(
balanceAfter.eq(balanceBefore.sub(validRequest.expectedAmount).sub(confirmedTx.gasUsed || 0)),
balanceBefore
.sub(validRequest.expectedAmount)
.sub(confirmedTx.cumulativeGasUsed.mul(confirmedTx.effectiveGasPrice) || 0),
);
});
});
Expand Down
2 changes: 1 addition & 1 deletion packages/payment-processor/test/payment/eth-proxy.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -134,7 +134,7 @@ describe('payEthProxyRequest', () => {
expect(balanceEthBefore.toString()).toBe(
balanceEthAfter
.add(validRequest.expectedAmount)
.add(confirmedTx.gasUsed?.mul(tx?.gasPrice ?? 1))
.add(confirmedTx.cumulativeGasUsed.mul(confirmedTx.effectiveGasPrice))
.toString(),
);
});
Expand Down
7 changes: 6 additions & 1 deletion packages/smart-contracts/hardhat.config.ts
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
import '@typechain/hardhat';
import '@nomiclabs/hardhat-waffle';
import '@nomiclabs/hardhat-ganache';
import '@nomiclabs/hardhat-etherscan';
import '@nomiclabs/hardhat-ethers';
import { subtask, task } from 'hardhat/config';
Expand DownExpand Up@@ -55,6 +54,12 @@ export default {
artifacts: 'build',
},
networks: {
hardhat: {
accounts: {
mnemonic: 'candy maple cake sugar pudding cream honey rich smooth crumble sweet treat',
},
hardfork: 'london',
},
private: {
url: 'http://127.0.0.1:8545',
accounts: undefined,
Expand Down
5 changes: 2 additions & 3 deletions packages/smart-contracts/package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -45,7 +45,7 @@
"lint:sol:check": "solhint \"src/contracts/**/*.sol\"",
"lint": "yarn run lint:lib && yarn run lint:sol",
"lint:check": "yarn run lint:lib:check && yarn run lint:sol:check",
"ganache": "ganache-cli -l 90000000 -p 8545 -m \"candy maple cake sugar pudding cream honey rich smooth crumble sweet treat\"",
"ganache": "yarn hardhat node",
"deploy": "yarn hardhat deploy-local-env --network private",
"test": "yarn hardhat test --network private",
"test:lib": "yarn jest test/lib"
Expand All@@ -56,7 +56,6 @@
"devDependencies": {
"@nomiclabs/hardhat-ethers": "2.0.2",
"@nomiclabs/hardhat-etherscan": "3.1.2",
"@nomiclabs/hardhat-ganache": "2.0.0",
"@nomiclabs/hardhat-waffle": "2.0.1",
"@nomiclabs/hardhat-web3": "2.0.0",
"@openzeppelin/contracts": "4.4.2",
Expand All@@ -75,7 +74,7 @@
"ethereum-waffle": "3.4.0",
"ethers": "5.5.1",
"ganache-cli": "6.12.0",
"hardhat": "2.4.1",
"hardhat": "2.12.0",
"shx": "0.3.2",
"solhint": "3.3.6",
"typechain": "5.1.1",
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -47,7 +47,6 @@ describe('contract: BatchConversionPayments', async () => {
const fiatDecimals = '00000000'; // 8 decimals
const thousandWith18Decimal = '1000000000000000000000'; // 21 decimals
const referenceExample = '0xaaaa';
const gasPrice = 2 * 10 ** 10; // await provider.getGasPrice()

// constants related to chainlink and conversion rate
const currencyManager = CurrencyManager.getDefault();
Expand DownExpand Up@@ -275,7 +274,7 @@ describe('contract: BatchConversionPayments', async () => {
forceExpectedFeeETHBalanceDiff?: BigNumber,
) => {
const receipt = await tx.wait();
const gasAmount = receipt.gasUsed.mul(gasPrice);
const gasAmount = receipt.gasUsed.mul(receipt.effectiveGasPrice);

const fromETHBalance = await provider.getBalance(await fromSigner.getAddress());
const toETHBalance = await provider.getBalance(to);
Expand DownExpand Up@@ -613,7 +612,7 @@ describe('contract: BatchConversionPayments', async () => {

// Check ETH balances //
const receipt = await tx.wait();
const gasAmount = receipt.gasUsed.mul(gasPrice);
const gasAmount = receipt.gasUsed.mul(receipt.effectiveGasPrice);

const fromETHBalance = await provider.getBalance(await fromSigner.getAddress());
const toETHBalance = await provider.getBalance(to);
Expand DownExpand Up@@ -760,7 +759,7 @@ describe('contract: BatchConversionPayments', async () => {
convRequest.path = [EUR_hash, ETH_hash, DAI_address];
await expect(
batchConversionProxy.batchMultiERC20ConversionPayments([convRequest], [], feeAddress),
).to.be.revertedWith('revert No aggregator found');
).to.be.revertedWith('No aggregator found');
});
it('cannot transfer if max to spend too low', async () => {
const convRequest = deepCopy(fauConvRequest);
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -124,7 +124,7 @@ describe('contract: ERC20SwapToConversion', () => {
referenceExample,
fiatDecimal.mul(1),
builder,
exchangeRateOrigin + 1000, // _uniswapDeadline. 100 -> 1000: Too low value may lead to error (network dependent)
exchangeRateOrigin + 10000, // _uniswapDeadline. 100 -> 1000: Too low value may lead to error (network dependent)
0, // _chainlinkMaxRateTimespan
),
)
Expand DownExpand Up@@ -187,7 +187,7 @@ describe('contract: ERC20SwapToConversion', () => {
referenceExample,
0,
builder,
exchangeRateOrigin + 1000, // _uniswapDeadline. 100 -> 1000: Too low value may lead to error (network dependent)
exchangeRateOrigin + 10000, // _uniswapDeadline. 100 -> 1000: Too low value may lead to error (network dependent)
0, // _chainlinkMaxRateTimespan
),
)
Expand DownExpand Up@@ -227,7 +227,7 @@ describe('contract: ERC20SwapToConversion', () => {
referenceExample,
fiatDecimal.mul(1),
builder,
exchangeRateOrigin + 1000, // _uniswapDeadline. 100 -> 1000: Too low value may lead to error (network dependent)
exchangeRateOrigin + 10000, // _uniswapDeadline. 100 -> 1000: Too low value may lead to error (network dependent)
0, // _chainlinkMaxRateTimespan
),
).to.be.revertedWith('UniswapV2Router: EXCESSIVE_INPUT_AMOUNT');
Expand DownExpand Up@@ -272,7 +272,7 @@ describe('contract: ERC20SwapToConversion', () => {
referenceExample,
fiatDecimal.mul(1),
builder,
exchangeRateOrigin + 1000, // _uniswapDeadline. 100 -> 1000: Too low value may lead to error (network dependent)
exchangeRateOrigin + 10000, // _uniswapDeadline. 100 -> 1000: Too low value may lead to error (network dependent)
0, // _chainlinkMaxRateTimespan
),
).to.be.revertedWith('UniswapV2Router: EXCESSIVE_INPUT_AMOUNT');
Expand DownExpand Up@@ -313,7 +313,7 @@ describe('contract: ERC20SwapToConversion', () => {
referenceExample,
fiatDecimal.mul(1),
builder,
exchangeRateOrigin + 1000, // _uniswapDeadline. 100 -> 1000: Too low value may lead to error (network dependent)
exchangeRateOrigin + 10000, // _uniswapDeadline. 100 -> 1000: Too low value may lead to error (network dependent)
0, // _chainlinkMaxRateTimespan
),
).to.be.revertedWith('Invalid payment proxy');
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -109,7 +109,7 @@ describe('contract: SwapToPay', () => {
referenceExample,
100,
builder,
exchangeRateOrigin + 1000, // _uniswapDeadline. 100 -> 1000: Too low value may lead to error (network dependent)
exchangeRateOrigin + 10000, // _uniswapDeadline. 100 -> 1000: Too low value may lead to error (network dependent)
),
)
.to.emit(erc20FeeProxy, 'TransferWithReferenceAndFee')
Expand DownExpand Up@@ -147,7 +147,7 @@ describe('contract: SwapToPay', () => {
referenceExample,
0,
builder,
exchangeRateOrigin + 1000, // -> 1000 Or it can reverts to UniswapV2Router: EXPIRED (network dependent)
exchangeRateOrigin + 10000, // -> 1000 Or it can reverts to UniswapV2Router: EXPIRED (network dependent)
),
)
.to.emit(erc20FeeProxy, 'TransferWithReferenceAndFee')
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -270,7 +270,7 @@ describe('contract: EthConversionProxy', () => {
value: mainEthAmount.result.add(ethFee.result).sub(1),
},
),
).to.be.revertedWith('revert paymentProxy transferExactEthWithReferenceAndFee failed');
).to.be.revertedWith('paymentProxy transferExactEthWithReferenceAndFee failed');
});
it('cannot transfer if rate is too old', async function () {
const path = [USD_hash, ETH_hash];
Expand DownExpand Up@@ -328,7 +328,7 @@ describe('contract: EthConversionProxy', () => {
value: ethFee.result.add(mainEthAmount.result),
},
),
).to.be.revertedWith('revert payment currency must be the native token');
).to.be.revertedWith('payment currency must be the native token');
});
});
});
Expand Down
2 changes: 1 addition & 1 deletion packages/utils/package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -40,9 +40,9 @@
"test:watch": "yarn test --watch"
},
"dependencies": {
"@rainbow-me/fee-suggestions": "2.1.0",
"@requestnetwork/types": "0.36.0",
"eccrypto": "1.1.6",
"eip1559-fee-suggestions-ethers": "1.3.3",
"ethers": "5.5.1",
"secp256k1": "4.0.2",
"tslib": "2.5.0"
Expand Down
2 changes: 1 addition & 1 deletion packages/utils/src/estimate-gas-fees.ts
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
import { BigNumber, constants, providers } from 'ethers';
import { suggestFees } from 'eip1559-fee-suggestions-ethers';
import { suggestFees } from '@rainbow-me/fee-suggestions';
import { maxBigNumber } from './index';

/**
Expand Down
56 changes: 56 additions & 0 deletions packages/utils/test/estimate-gas-fee.test.ts
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
import { estimateGasFees } from '@requestnetwork/utils/src';
import { BigNumber, providers, Wallet } from 'ethers';

jest.setTimeout(10000);

const mnemonic = 'candy maple cake sugar pudding cream honey rich smooth crumble sweet treat';
const dummyAddress = '0xf17f52151EbEF6C7334FAD080c5704D77216b732';
const provider = new providers.JsonRpcProvider('http://localhost:8545');
const wallet = Wallet.fromMnemonic(mnemonic).connect(provider);

const checkEstimation = (
baseEstimation: BigNumber,
currentEstimation: BigNumber,
ratioMax: number,
) => {
const absRatio =
Math.abs(baseEstimation.sub(currentEstimation).toNumber()) /
Math.max(baseEstimation.toNumber(), currentEstimation?.toNumber());
expect(absRatio).toBeLessThan(ratioMax);
};

describe('Gas fee estimation', () => {
it('Should not be undefined', async () => {
const estimation = await estimateGasFees({ provider });
expect(estimation.maxFeePerGas).toBeDefined();
expect(estimation.maxPriorityFeePerGas).toBeDefined();
});

it('Should return a lower estimation when the previous block is empty', async () => {
const firstEstimation = await estimateGasFees({ provider });
await provider.send('evm_mine', []);
const secondEstimation = await estimateGasFees({ provider });

expect(
firstEstimation.maxFeePerGas?.sub(secondEstimation.maxFeePerGas || 0).toNumber(),
).toBeGreaterThan(0);
});

it('Should return a consistent value compared to the default value', async () => {
// Run some transactions so there is data to perform the estimation
for (let i = 0; i < 20; i++) {
await wallet.sendTransaction({
to: dummyAddress,
value: BigNumber.from(1),
});
}

const estimation = await estimateGasFees({ provider });
const tx = await wallet.sendTransaction({
to: dummyAddress,
value: BigNumber.from(1),
});
checkEstimation(estimation.maxFeePerGas as BigNumber, tx.maxFeePerGas as BigNumber, 0.1);
checkEstimation(estimation.maxFeePerGas as BigNumber, tx.maxFeePerGas as BigNumber, 0.1);
});
});
Loading