Skip to content

Type 2 transactions for miner / mtx broadcaster #1174

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

Merged
merged 10 commits into from
Nov 2, 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
8 changes: 4 additions & 4 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 packages/metatransaction-broadcaster/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ COPY ./packages ./packages
COPY ./package.json ./
COPY ./package-lock.json ./
COPY ./build ./build
RUN npm i
RUN npm ci
RUN cd ./packages/metatransaction-broadcaster/ && npm i
RUN cd ./packages/package-utils/ && npm i
EXPOSE 3000
Expand Down
16 changes: 10 additions & 6 deletions packages/metatransaction-broadcaster/MetatransactionBroadcaster.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const sqlite = require("sqlite");
const sqlite3 = require("sqlite3");
const queue = require("express-queue");
const NonceManager = require("./ExtendedNonceManager");
const { colonyIOCors, ConsoleAdapter, updateGasEstimate } = require("../package-utils");
const { colonyIOCors, ConsoleAdapter, getFeeData } = require("../package-utils");

const ETHEREUM_BRIDGE_ADDRESS = "0x75Df5AF045d91108662D8080fD1FEFAd6aA0bb59";
const BINANCE_BRIDGE_ADDRESS = "0x162E898bD0aacB578C8D5F8d6ca588c13d2A383F";
Expand Down Expand Up @@ -81,7 +81,7 @@ class MetatransactionBroadcaster {
const colonyNetworkDef = await this.loader.load({ contractName: "IColonyNetwork" }, { abi: true, address: false });
this.colonyNetwork = new ethers.Contract(colonyNetworkAddress, colonyNetworkDef.abi, this.wallet);

this.gasPrice = await updateGasEstimate("safeLow", this.chainId, this.adapter);
this.feeData = await getFeeData("safeLow", this.chainId, this.adapter, this.provider);
this.tokenLockingAddress = await this.colonyNetwork.getTokenLocking();

this.metaTxDef = await this.loader.load({ contractName: "IBasicMetaTransaction" }, { abi: true, address: false });
Expand Down Expand Up @@ -336,6 +336,10 @@ class MetatransactionBroadcaster {

try {
gasEstimate = await estimateGas(...args);
if (ethers.BigNumber.from(args[args.length - 1].gasLimit).gt(gasEstimate.mul(11).div(10))) {
// eslint-disable-next-line
args[args.length - 1].gasLimit = gasEstimate.mul(11).div(10);
}
} catch (err) {
let reason;
try {
Expand Down Expand Up @@ -441,14 +445,14 @@ class MetatransactionBroadcaster {
try {
const { target, userAddress, payload, r, s, v } = req.body;
const contract = new ethers.Contract(target, this.metaTxDef.abi, this.nonceManager);
this.gasPrice = await updateGasEstimate("safeLow", this.chainId, this.adapter);
this.feeData = await getFeeData("safeLow", this.chainId, this.adapter, this.provider);
return this.processTransactionLogic(req, res, contract.estimateGas.executeMetaTransaction, contract.executeMetaTransaction, [
userAddress,
payload,
r,
s,
v,
{ gasPrice: this.gasPrice, gasLimit: this.gasLimit },
{ ...this.feeData, gasLimit: this.gasLimit },
]);
} catch (err) {
return res.status(500).send({
Expand All @@ -462,7 +466,7 @@ class MetatransactionBroadcaster {
try {
const { target, owner, spender, value, deadline, r, s, v } = req.body;
const contract = new ethers.Contract(target, this.metaTxTokenDef.abi, this.nonceManager);
this.gasPrice = await updateGasEstimate("safeLow", this.chainId, this.adapter);
this.feeData = await getFeeData("safeLow", this.chainId, this.adapter, this.provider);
return this.processTransactionLogic(req, res, contract.estimateGas.permit, contract.permit, [
owner,
spender,
Expand All @@ -471,7 +475,7 @@ class MetatransactionBroadcaster {
v,
r,
s,
{ gasPrice: this.gasPrice, gasLimit: this.gasLimit },
{ ...this.feeData, gasLimit: this.gasLimit },
]);
} catch (err) {
return res.status(500).send({
Expand Down
90 changes: 90 additions & 0 deletions packages/package-utils/getFeeData.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
const ethers = require("ethers");
const axios = require("axios");

/**
* Update the gas estimate
* @param {string} Transaction speed (fastest, fast, safeLow)
* @param {number} Chain ID
* @param {object} Adapter
* @param {object} Provider
* @return {Promise}
*/
const getFeeData = async function (_type, chainId, adapter, provider) {
let defaultGasPrice;
let factor;
let feeData;

let type = _type;
const options = {
headers: {
"User-Agent": "Request-Promise",
},
json: true, // Automatically parses the JSON string in the response
};

if (chainId === 100) {
options.url = "https://blockscout.com/xdai/mainnet/api/v1/gas-price-oracle";
defaultGasPrice = ethers.BigNumber.from(10000000000);
factor = 1;
// This oracle presents the information slightly differently from ethgasstation.
if (_type === "safeLow") {
type = "slow";
}
} else if (chainId === 1) {
options.url = "https://ethgasstation.info/json/ethgasAPI.json";
defaultGasPrice = ethers.BigNumber.from(10000000000);
factor = 10;
} else {
// We don't have an oracle, so just use the provided fee data
adapter.log(`During gas estimation: unknown chainid ${chainId}`);
feeData = await provider.getFeeData();
delete feeData.lastBaseFeePerGas;
if (feeData.maxFeePerGas) {
delete feeData.gasPrice;
}
return feeData;
}

try {
feeData = await provider.getFeeData();
delete feeData.lastBaseFeePerGas;
if (feeData.maxFeePerGas) {
delete feeData.gasPrice;
}
// Update gas prices from whichever oracle
try {
const request = await axios.request(options);
const gasEstimates = request.data;

if (feeData.maxFeePerGas) {
// Update the EIP1559 fee data based on the type
const ratio = gasEstimates[type] / gasEstimates.average;
// Increase the priority fee by this ratio
const newMaxPriorityFeePerGas = ethers.BigNumber.from(Math.floor(feeData.maxPriorityFeePerGas * 1000))
.mul(Math.floor(ratio * 1000))
.div(1000 * 1000);
// Increase the max fee per gas by the same amount (not the same ratio)
feeData.maxFeePerGas = feeData.maxFeePerGas.add(newMaxPriorityFeePerGas).sub(feeData.maxPriorityFeePerGas);
feeData.maxPriorityFeePerGas = newMaxPriorityFeePerGas;
return feeData;
}

// If we get here, chain is not EIP1559, so just update gasPrice
if (gasEstimates[type]) {
feeData.gasPrice = ethers.BigNumber.from(gasEstimates[type] * 1e9).div(factor);
} else {
feeData.gasPrice = defaultGasPrice;
}
} catch (err) {
adapter.error(`Error during gas estimation: ${err}`);
adapter.error(`Using default fee data from node`);
}
} catch (err) {
adapter.error(`Error getting fee data from provider: ${err}`);
adapter.error(`Using default static gas fee. Hopefully it's not too low...`);
feeData = { gasPrice: defaultGasPrice };
}
return feeData;
};

module.exports = getFeeData;
2 changes: 1 addition & 1 deletion packages/package-utils/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
exports.colonyIOCors = require("./colonyIOCors");
exports.updateGasEstimate = require("./updateGasEstimate");
exports.getFeeData = require("./getFeeData");
exports.DiscordAdapter = require("./adapters/discord");
exports.SlackAdapter = require("./adapters/slack");
exports.ConsoleAdapter = require("./adapters/console");
Expand Down
55 changes: 0 additions & 55 deletions packages/package-utils/updateGasEstimate.js

This file was deleted.

Loading