Skip to content

Commit

Permalink
Fix error handling (#72)
Browse files Browse the repository at this point in the history
* fix error handling

* fix parseAndSetUnrecognizedErrorMessage

* bump version
  • Loading branch information
defi-dev authored Dec 12, 2023
1 parent 181de25 commit 1227aa1
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 58 deletions.
2 changes: 2 additions & 0 deletions app/Network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -336,13 +336,15 @@ export class Network {
blockNumber = BigInt(blockNumber.toString());
const before = this.nowMs();

const oldLatestBlockNumber = this.latestBlockNumber;
if (this.latestBlockNumber && blockNumber <= this.latestBlockNumber) {
return null;
}
this.latestBlockNumber = blockNumber;

const block = await this.queryBlock(blockNumber);
if (!block) {
this.latestBlockNumber = oldLatestBlockNumber;
setTimeout(() => {
this._onNewBlockCallback(blockNumber);
}, 1000);
Expand Down
47 changes: 47 additions & 0 deletions app/Utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
} from './Constants.js';
import { ParsedJobConfig, ParsedRawJob, UnsignedTransaction } from './Types.js';
import { ethers } from 'ethers';
import { Result } from 'ethers/lib/utils';

export function sleep(ms: number) {
return new Promise(resolve => setTimeout(resolve, ms, []));
Expand Down Expand Up @@ -194,3 +195,49 @@ export function chunkArray(array, chunkSize) {
export function flattenArray(array) {
return [].concat(...array);
}

export function filterFunctionResultObject(res: Result, numberToString = false): { [key: string]: any } {
if (!Array.isArray(res)) {
if (typeof res === 'object' && numberToString) {
const clone = { ...res };
Object.keys(clone).map(key => {
if (clone[key] && clone[key].hex) {
clone[key] = BigInt(clone[key].hex).toString(10);
}
});
return clone;
}
return res;
}

const filteredResult = {};

if (res.length === 0) {
return {};
}
if (res.length === 1) {
return [filterFunctionResultObject(res['0'])];
} else if (res.length > 1) {
// For a fake array the object keys length is twice bigger than its length
const isRealArray = Array.isArray(res) && Object.keys(res).length === res.length;
// if is a real array, it's items could be an unfiltered object
if (isRealArray) {
return res.map(v => filterFunctionResultObject(v));
} else {
// else it is a fake object
let i = 0;
for (const field in res) {
if (i++ < res.length) {
continue;
}
if (Array.isArray(res[field])) {
filteredResult[field] = filterFunctionResultObject(res[field]);
} else {
filteredResult[field] = res[field];
}
}
}
}

return filteredResult;
}
11 changes: 7 additions & 4 deletions app/agents/AbstractAgent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
import { BigNumber, ethers, Wallet } from 'ethers';
import { getEncryptedJson } from '../services/KeyService.js';
import { AVERAGE_BLOCK_TIME_SECONDS, BN_ZERO, DEFAULT_SYNC_FROM_CHAINS } from '../Constants.js';
import { numberToBigInt, toChecksummedAddress, weiValueToEth } from '../Utils.js';
import { filterFunctionResultObject, numberToBigInt, toChecksummedAddress, weiValueToEth } from '../Utils.js';
import { FlashbotsExecutor } from '../executors/FlashbotsExecutor.js';
import { PGAExecutor } from '../executors/PGAExecutor.js';
import { getAgentDefaultSyncFromSafe, getDefaultExecutorConfig, setConfigDefaultValues } from '../ConfigGetters.js';
Expand Down Expand Up @@ -623,9 +623,12 @@ export abstract class AbstractAgent implements IAgent {
.replace('"{', '{');
decodedError = this.contract.decodeError(JSON.parse(responseJson).response.error.data);
}
err.message =
`Error: VM Exception while processing transaction: reverted with ${decodedError.name} ` +
`decoded error and ${JSON.stringify(decodedError.args)} args`;
if (decodedError) {
const filteredArgs = filterFunctionResultObject(decodedError.args, true);
err.message =
`Error: VM Exception while processing transaction: reverted with ${decodedError.name} ` +
`decoded error and ${JSON.stringify(filteredArgs)} args`;
}
} catch (_) {
console.error('decode error', _);
}
Expand Down
53 changes: 2 additions & 51 deletions app/clients/EthersContract.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ethers } from 'ethers';
import { sleep } from '../Utils.js';
import { sleep, filterFunctionResultObject } from '../Utils.js';
import { ContractWrapper, ErrorWrapper, EventWrapper, TxDataWrapper, WrapperListener } from '../Types.js';
import { Result, Fragment, ErrorFragment, FunctionFragment, EventFragment } from 'ethers/lib/utils.js';
import { Fragment, ErrorFragment, FunctionFragment, EventFragment } from 'ethers/lib/utils.js';
import logger from '../services/Logger.js';
import QueueEmitter from '../services/QueueEmitter.js';

Expand Down Expand Up @@ -257,52 +257,3 @@ export class EthersContract implements ContractWrapper {
return this.abiEventByTopic;
}
}

function filterFunctionResultObject(res: Result, numberToString = false): { [key: string]: any } {
if (!Array.isArray(res)) {
if (typeof res === 'object' && numberToString) {
const clone = { ...res };
console.log('clone', clone);
Object.keys(clone).map(key => {
if (clone[key] && clone[key].hex) {
console.log('clone[key]', clone[key]);
console.log('BigInt(clone[key].hex)', BigInt(clone[key].hex));
clone[key] = BigInt(clone[key].hex).toString(10);
}
});
return clone;
}
return res;
}

const filteredResult = {};

if (res.length === 0) {
return {};
}
if (res.length === 1) {
return [filterFunctionResultObject(res['0'])];
} else if (res.length > 1) {
// For a fake array the object keys length is twice bigger than its length
const isRealArray = Array.isArray(res) && Object.keys(res).length === res.length;
// if is a real array, it's items could be an unfiltered object
if (isRealArray) {
return res.map(v => filterFunctionResultObject(v));
} else {
// else it is a fake object
let i = 0;
for (const field in res) {
if (i++ < res.length) {
continue;
}
if (Array.isArray(res[field])) {
filteredResult[field] = filterFunctionResultObject(res[field]);
} else {
filteredResult[field] = res[field];
}
}
}
}

return filteredResult;
}
2 changes: 2 additions & 0 deletions app/executors/PGAExecutor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ export class PGAExecutor extends AbstractExecutor implements Executor {
} catch (_e) {
e = _e;
}
envelope.executorCallbacks.txEstimationFailed(e, tx.data as string);
return callback(this.err(`gasLimitEstimation failed with error: ${e.message}`));
}
printSolidityCustomError(
this.clog.bind(this),
Expand Down
9 changes: 7 additions & 2 deletions app/jobs/RandaoJob.ts
Original file line number Diff line number Diff line change
Expand Up @@ -312,15 +312,20 @@ export class RandaoJob extends AbstractJob {
return;
}

if (this.isResolverJob() && !this.isNotSuitableForBlacklistError(err)) {
this.incrementFailedExecutesInARow(err);

this.watch();
}

protected incrementFailedExecutesInARow(err) {
if (!this.isNotSuitableForBlacklistError(err)) {
// Assume that a failed execution behaviour is equal to a failed estimation
this.failedExecuteEstimationsInARow += 1;
if (this.failedExecuteEstimationsInARow > this.BLACKLIST_ESTIMATIONS_LIMIT) {
this.agent.addJobToBlacklist(this.key, err.message);
this.failedExecuteEstimationsInARow = 0;
}
}
this.watch();
}

protected _executeTxEstimationFailed(error, _txData: string): any {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "powerpool-agent-v2-node",
"version": "0.3.2",
"version": "0.5.1",
"description": "PowerPool Agent V2 Keeper Node",
"main": "app/Run.ts",
"scripts": {
Expand Down

0 comments on commit 1227aa1

Please sign in to comment.