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

Liquidator & disputer bot: Improve bot gas estimation #1801

Merged
merged 19 commits into from
Aug 7, 2020
Merged
Show file tree
Hide file tree
Changes from 17 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
15 changes: 11 additions & 4 deletions disputer/disputer.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ class Disputer {
this.toBN = this.web3.utils.toBN;
this.utf8ToHex = this.web3.utils.utf8ToHex;

// Multiplier to scale the amount of gas send with a transaction over and above the estimated gas from Truffle.
this.GAS_LIMIT_BUFFER = 1.25;

// Default config settings. Disputer deployer can override these settings by passing in new
// values via the `config` input object. The `isValid` property is a function that should be called
// before resetting any config settings. `isValid` must return a Boolean.
Expand Down Expand Up @@ -128,23 +131,26 @@ class Disputer {
const dispute = this.empContract.methods.dispute(disputeableLiquidation.id, disputeableLiquidation.sponsor);

// Simple version of inventory management: simulate the transaction and assume that if it fails, the caller didn't have enough collateral.
let gasLimit, totalPaid;
try {
await dispute.call({ from: this.account, gasPrice: this.gasEstimator.getCurrentFastPrice() });
totalPaid = await dispute.call({ from: this.account });
gasLimit = Math.floor((await dispute.estimateGas({ from: this.account })) * this.GAS_LIMIT_BUFFER);
} catch (error) {
this.logger.error({
at: "Disputer",
message: "Cannot dispute liquidation: not enough collateral (or large enough approval) to initiate dispute✋",
disputer: this.account,
sponsor: disputeableLiquidation.sponsor,
liquidation: disputeableLiquidation,
totalPaid,
error
});
continue;
}

const txnConfig = {
from: this.account,
gas: this.txnGasLimit,
gas: Math.min(gasLimit, this.txnGasLimit),
gasPrice: this.gasEstimator.getCurrentFastPrice()
};

Expand Down Expand Up @@ -223,9 +229,10 @@ class Disputer {
const withdraw = this.empContract.methods.withdrawLiquidation(liquidation.id, liquidation.sponsor);

// Confirm that dispute has eligible rewards to be withdrawn.
let withdrawAmount;
let withdrawAmount, gasLimit;
try {
withdrawAmount = revertWrapper(await withdraw.call({ from: this.account }));
gasLimit = Math.floor((await withdraw.estimateGas({ from: this.account })) * this.GAS_LIMIT_BUFFER);
if (withdrawAmount === null) {
throw new Error("Simulated reward withdrawal failed");
}
Expand All @@ -241,7 +248,7 @@ class Disputer {

const txnConfig = {
from: this.account,
gas: this.txnGasLimit,
gas: Math.min(gasLimit, this.txnGasLimit),
gasPrice: this.gasEstimator.getCurrentFastPrice()
};
this.logger.debug({
Expand Down
12 changes: 9 additions & 3 deletions liquidator/liquidator.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ class Liquidator {
this.fromWei = this.web3.utils.fromWei;
this.utf8ToHex = this.web3.utils.utf8ToHex;

// Multiplier to scale the amount of gas send with a transaction over and above the estimated gas from Truffle.
this.GAS_LIMIT_BUFFER = 1.25;

// Default config settings. Liquidator deployer can override these settings by passing in new
// values via the `config` input object. The `isValid` property is a function that should be called
// before resetting any config settings. `isValid` must return a Boolean.
Expand Down Expand Up @@ -248,8 +251,10 @@ class Liquidator {
);

// Simple version of inventory management: simulate the transaction and assume that if it fails, the caller didn't have enough collateral.
let gasLimit;
try {
await liquidation.call({ from: this.account });
gasLimit = Math.floor((await liquidation.estimateGas({ from: this.account })) * this.GAS_LIMIT_BUFFER);
} catch (error) {
this.logger.error({
at: "Liquidator",
Expand All @@ -268,7 +273,7 @@ class Liquidator {

const txnConfig = {
from: this.account,
gas: this.txnGasLimit,
gas: Math.min(gasLimit, this.txnGasLimit),
gasPrice: this.gasEstimator.getCurrentFastPrice()
};
this.logger.debug({
Expand Down Expand Up @@ -356,9 +361,10 @@ class Liquidator {
const withdraw = this.empContract.methods.withdrawLiquidation(liquidation.id, liquidation.sponsor);

// Confirm that liquidation has eligible rewards to be withdrawn.
let withdrawAmount;
let withdrawAmount, gasLimit;
try {
withdrawAmount = revertWrapper(await withdraw.call({ from: this.account }));
gasLimit = Math.floor((await withdraw.estimateGas({ from: this.account })) * this.GAS_LIMIT_BUFFER);
if (!withdrawAmount) {
throw new Error("Simulated reward withdrawal failed");
}
Expand All @@ -374,7 +380,7 @@ class Liquidator {

const txnConfig = {
from: this.account,
gas: this.txnGasLimit,
gas: Math.min(gasLimit, this.txnGasLimit),
gasPrice: this.gasEstimator.getCurrentFastPrice()
};
this.logger.debug({
Expand Down