Skip to content

Commit 3ee9a2f

Browse files
Fix handling of null amount value when fetching transactions from the mirror node (#715)
Fix handling of null amount value Signed-off-by: Maksim Dimitrov <[email protected]> Signed-off-by: Maksim Dimitrov <[email protected]>
1 parent edfb00c commit 3ee9a2f

File tree

2 files changed

+42
-12
lines changed

2 files changed

+42
-12
lines changed

packages/relay/src/lib/eth.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ export class EthImpl implements Eth {
7676
static blockLatest = 'latest';
7777
static blockEarliest = 'earliest';
7878
static blockPending = 'pending';
79-
79+
8080
/**
8181
* Configurable options used when initializing the cache.
8282
*
@@ -541,7 +541,7 @@ export class EthImpl implements Eth {
541541
blockNumberOrTag = EthImpl.blockLatest;
542542
}
543543
}
544-
544+
545545
// Cache is only set for `not found` balances
546546
const cachedLabel = `getBalance.${account}.${blockNumberOrTag}`;
547547
const cachedResponse: string | undefined = this.cache.get(cachedLabel);
@@ -961,7 +961,7 @@ export class EthImpl implements Eth {
961961
const sSig = contractResult.s === null ? null : contractResult.s.substring(0, 66);
962962

963963
if (process.env.DEV_MODE && process.env.DEV_MODE === 'true' && contractResult.result === 'CONTRACT_REVERT_EXECUTED') {
964-
let err = predefined.CONTRACT_REVERT(contractResult.error_message);
964+
const err = predefined.CONTRACT_REVERT(contractResult.error_message);
965965
throw err;
966966
}
967967

@@ -984,7 +984,7 @@ export class EthImpl implements Eth {
984984
transactionIndex: EthImpl.numberTo0x(contractResult.transaction_index),
985985
type: EthImpl.nullableNumberTo0x(contractResult.type),
986986
v: EthImpl.nullableNumberTo0x(contractResult.v),
987-
value: EthImpl.numberTo0x(contractResult.amount),
987+
value: EthImpl.nanOrNumberTo0x(contractResult.amount),
988988
});
989989
}
990990

@@ -1126,7 +1126,6 @@ export class EthImpl implements Eth {
11261126
* Then using the block timerange get all contract results to get transaction details.
11271127
* If showDetails is set to true subsequently call mirror node for additional transaction details
11281128
*
1129-
* TODO What do we return if we cannot find the block with that hash?
11301129
* @param blockHashOrNumber
11311130
* @param showDetails
11321131
*/
@@ -1137,7 +1136,7 @@ export class EthImpl implements Eth {
11371136

11381137
const timestampRange = blockResponse.timestamp;
11391138
const timestampRangeParams = [`gte:${timestampRange.from}`, `lte:${timestampRange.to}`];
1140-
const contractResults = await this.mirrorNodeClient.getContractResults({ timestamp: timestampRangeParams },undefined, requestId);
1139+
const contractResults = await this.mirrorNodeClient.getContractResults({ timestamp: timestampRangeParams }, undefined, requestId);
11411140
const maxGasLimit = constants.BLOCK_GAS_LIMIT;
11421141
const gasUsed = blockResponse.gas_used;
11431142

@@ -1268,7 +1267,7 @@ export class EthImpl implements Eth {
12681267
transactionIndex: EthImpl.numberTo0x(contractResultDetails.transaction_index),
12691268
type: EthImpl.nullableNumberTo0x(contractResultDetails.type),
12701269
v: EthImpl.nullableNumberTo0x(contractResultDetails.v),
1271-
value: EthImpl.numberTo0x(contractResultDetails.amount),
1270+
value: EthImpl.nanOrNumberTo0x(contractResultDetails.amount),
12721271
});
12731272
}
12741273
})
@@ -1359,7 +1358,7 @@ export class EthImpl implements Eth {
13591358
return [];
13601359
}
13611360

1362-
let unproccesedLogs = await this.mirrorNodeClient.pageAllResults(result, requestId);
1361+
const unproccesedLogs = await this.mirrorNodeClient.pageAllResults(result, requestId);
13631362

13641363
const logs: Log[] = [];
13651364
for(const log of unproccesedLogs) {

packages/relay/tests/lib/eth.spec.ts

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -965,6 +965,19 @@ describe('Eth calls using MirrorNode', async function () {
965965
expect(result.to).equal(contractAddress1);
966966
});
967967

968+
it('eth_getTransactionByBlockNumberAndIndex with null amount', async function () {
969+
// mirror node request mocks
970+
mock.onGet(`contracts/results?block.number=${defaultBlock.number}&transaction.index=${defaultBlock.count}&limit=100&order=asc`).reply(200, defaultContractResults);
971+
mock.onGet(`contracts/${contractAddress1}/results/${contractTimestamp1}`).reply(200, {...defaultDetailedContractResults, amount: null});
972+
973+
const result = await ethImpl.getTransactionByBlockNumberAndIndex(EthImpl.numberTo0x(defaultBlock.number), EthImpl.numberTo0x(defaultBlock.count));
974+
expect(result).to.exist;
975+
if (result == null) return;
976+
977+
// verify aggregated info
978+
expect(result.value).equal("0x0");
979+
});
980+
968981
it('eth_getTransactionByBlockNumberAndIndex with no contract result match', async function () {
969982
mock.onGet(`contracts/results?block.number=${defaultBlock.number}&transaction.index=${defaultBlock.count}&limit=100&order=asc`).reply(400, {
970983
'_status': {
@@ -1171,7 +1184,7 @@ describe('Eth calls using MirrorNode', async function () {
11711184
balance: defBalance
11721185
}
11731186
});
1174-
1187+
11751188
const resBalance = await ethImpl.getBalance(contractAddress1, blockNumber);
11761189
expect(resBalance).to.equal(defHexBalance);
11771190
});
@@ -1558,7 +1571,7 @@ describe('Eth calls using MirrorNode', async function () {
15581571
};
15591572

15601573
mock.onGet("blocks?limit=1&order=desc").reply(200, { blocks: [defaultBlock] });
1561-
1574+
15621575
mock.onGet(`contracts/results/logs?timestamp=gte:${defaultBlock.timestamp.from}&timestamp=lte:${defaultBlock.timestamp.to}&limit=2&order=asc`).replyOnce(200, filteredLogs)
15631576
.onGet('contracts/results/logs?limit=2&order=desc&timestamp=lte:1668432962.375200975&index=lt:0').replyOnce(200, filteredLogsNext);
15641577

@@ -2691,6 +2704,24 @@ describe('Eth', async function () {
26912704
expect(result.gas).to.eq('0x0');
26922705
});
26932706

2707+
it('handles transactions with null amount', async function () {
2708+
// mirror node request mocks
2709+
const detailedResultsWithNullNullableValues = {
2710+
...defaultDetailedContractResultByHash,
2711+
amount: null
2712+
};
2713+
2714+
mock.onGet(`contracts/results/${defaultTxHash}`).reply(200, detailedResultsWithNullNullableValues);
2715+
mock.onGet(`accounts/${defaultFromLongZeroAddress}`).reply(200, {
2716+
evm_address: `${defaultTransaction.from}`
2717+
});
2718+
const result = await ethImpl.getTransactionByHash(defaultTxHash);
2719+
if (result == null) return;
2720+
2721+
expect(result).to.exist;
2722+
expect(result.value).to.eq('0x0');
2723+
});
2724+
26942725
it('returns reverted transactions', async function () {
26952726
mock.onGet(`contracts/results/${defaultTxHash}`).reply(200, defaultDetailedContractResultByHashReverted);
26962727
mock.onGet(`accounts/${defaultFromLongZeroAddress}`).reply(200, {
@@ -2721,7 +2752,7 @@ describe('Eth', async function () {
27212752
expect(result.type).to.eq(EthImpl.numberTo0x(defaultTransaction.type));
27222753
expect(result.v).to.eq(EthImpl.numberTo0x(defaultTransaction.v));
27232754
expect(result.value).to.eq(defaultTransaction.value);
2724-
})
2755+
});
27252756

27262757
it('throws error for reverted transactions when DEV_MODE=true', async function () {
27272758
const initialDevModeValue = process.env.DEV_MODE;
@@ -2741,6 +2772,6 @@ describe('Eth', async function () {
27412772
}
27422773

27432774
process.env.DEV_MODE = initialDevModeValue;
2744-
})
2775+
});
27452776
});
27462777
});

0 commit comments

Comments
 (0)