Skip to content

Commit 6f76303

Browse files
Merge pull request #498 from multiversx/return-data-8
Recover return data of smart contract (new implementation)
2 parents 22f0fe6 + 0ac07f1 commit 6f76303

10 files changed

+12039
-70
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@multiversx/sdk-core",
3-
"version": "13.7.0",
3+
"version": "13.8.0",
44
"description": "MultiversX SDK for JavaScript and TypeScript",
55
"author": "MultiversX",
66
"homepage": "https://multiversx.com",

src/interfaceOfNetwork.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ export interface IContractResultItem {
5353
data: string;
5454
returnMessage: string;
5555
logs: ITransactionLogs;
56+
previousHash?: string;
5657
}
5758

5859
export interface IContractQueryResponse {

src/smartcontracts/resultsParser.spec.ts

Lines changed: 6 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,17 @@
1+
import BigNumber from "bignumber.js";
2+
import { assert } from "chai";
3+
import { Address } from "../address";
4+
import { IAddress } from "../interface";
15
import {
26
ContractQueryResponse,
37
ContractResultItem,
48
ContractResults,
9+
TransactionEventData,
510
TransactionEventOnNetwork,
611
TransactionEventTopic,
712
TransactionLogsOnNetwork,
813
TransactionOnNetwork,
9-
TransactionEventData,
1014
} from "../networkProviders";
11-
import BigNumber from "bignumber.js";
12-
import { assert } from "chai";
13-
import * as fs from "fs";
14-
import path from "path";
15-
import { Address } from "../address";
16-
import { IAddress } from "../interface";
17-
import { ITransactionOnNetwork } from "../interfaceOfNetwork";
18-
import { LogLevel, Logger } from "../logger";
1915
import { loadAbiRegistry } from "../testutils";
2016
import { ArgSerializer } from "./argSerializer";
2117
import { ResultsParser } from "./resultsParser";
@@ -258,10 +254,7 @@ describe("test smart contract results parser", () => {
258254

259255
let bundle = parser.parseUntypedOutcome(transaction);
260256
assert.deepEqual(bundle.returnCode, ReturnCode.Ok);
261-
assert.equal(
262-
bundle.returnMessage,
263-
"@too much gas provided for processing: gas provided = 596384500, gas used = 733010",
264-
);
257+
assert.equal(bundle.returnMessage, "ok");
265258
assert.deepEqual(bundle.values, []);
266259
});
267260

@@ -383,47 +376,4 @@ describe("test smart contract results parser", () => {
383376
assert.deepEqual(bundle.b, new BigNumber(43));
384377
assert.deepEqual(bundle.c, new BigNumber(44));
385378
});
386-
387-
// This test should be enabled manually and run against a set of sample transactions.
388-
// 2022-04-03: test ran against ~1800 transactions sampled from devnet.
389-
it.skip("should parse real-world contract outcomes", async () => {
390-
let oldLogLevel = Logger.logLevel;
391-
Logger.setLevel(LogLevel.Trace);
392-
393-
let folder = path.resolve(process.env["SAMPLES"] || "SAMPLES");
394-
let samples = loadRealWorldSamples(folder);
395-
396-
for (const [transaction, _] of samples) {
397-
console.log("Transaction:", transaction.hash.toString());
398-
399-
let bundle = parser.parseUntypedOutcome(transaction);
400-
401-
console.log("Return code:", bundle.returnCode.toString());
402-
console.log("Return message:", bundle.returnMessage);
403-
console.log("Num values:", bundle.values.length);
404-
console.log("=".repeat(80));
405-
406-
assert.include(KnownReturnCodes, bundle.returnCode.valueOf());
407-
}
408-
409-
Logger.setLevel(oldLogLevel);
410-
});
411-
412-
function loadRealWorldSamples(folder: string): [ITransactionOnNetwork, string][] {
413-
let transactionFiles = fs.readdirSync(folder);
414-
let samples: [ITransactionOnNetwork, string][] = [];
415-
416-
for (const file of transactionFiles) {
417-
let txHash = path.basename(file, ".json");
418-
let filePath = path.resolve(folder, file);
419-
let jsonContent: string = fs.readFileSync(filePath, { encoding: "utf8" });
420-
let json = JSON.parse(jsonContent);
421-
let payload = json["data"]["transaction"];
422-
let transaction = TransactionOnNetwork.fromProxyHttpResponse(txHash, payload);
423-
424-
samples.push([transaction, jsonContent]);
425-
}
426-
427-
return samples;
428-
}
429379
});

src/smartcontracts/resultsParser.ts

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -284,12 +284,10 @@ export class ResultsParser {
284284
}
285285

286286
let { returnCode, returnDataParts } = this.sliceDataFieldInParts(eventTooMuchGas.data);
287-
let lastTopic = eventTooMuchGas.getLastTopic();
288-
let returnMessage = lastTopic?.toString() || returnCode.toString();
289287

290288
return {
291289
returnCode: returnCode,
292-
returnMessage: returnMessage,
290+
returnMessage: returnCode.toString(),
293291
values: returnDataParts,
294292
};
295293
}
@@ -355,6 +353,25 @@ export class ResultsParser {
355353
}
356354
}
357355

356+
// Additional fallback heuristics (alter search constraints):
357+
for (const resultItem of transaction.contractResults.items) {
358+
let writeLogWithReturnData = resultItem.logs.findSingleOrNoneEvent(WellKnownEvents.OnWriteLog, (event) => {
359+
const addressIsContract = event.address.bech32() == contractAddress.toBech32();
360+
return addressIsContract;
361+
});
362+
363+
if (writeLogWithReturnData) {
364+
const { returnCode, returnDataParts } = this.sliceDataFieldInParts(writeLogWithReturnData.data);
365+
const returnMessage = returnCode.toString();
366+
367+
return {
368+
returnCode: returnCode,
369+
returnMessage: returnMessage,
370+
values: returnDataParts,
371+
};
372+
}
373+
}
374+
358375
return null;
359376
}
360377

src/testdata/README.md

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
# Testdata
2+
3+
## Files `transactions.mainnet.json`
4+
5+
Transactions were sampled from the mainnet BigQuery dataset:
6+
7+
```sql
8+
DECLARE
9+
TIMESTAMP_START DATE DEFAULT '2024-09-01';
10+
DECLARE
11+
TIMESTAMP_END DATE DEFAULT '2024-09-03';
12+
-- Contract execute, with success
13+
(
14+
SELECT
15+
`_id`,
16+
'execute_success' `kind`
17+
FROM
18+
`multiversx-blockchain-etl.crypto_multiversx_mainnet_eu.transactions`
19+
WHERE
20+
DATE(`timestamp`) >= TIMESTAMP_START
21+
AND DATE(`timestamp`) <= TIMESTAMP_END
22+
AND `isScCall` = TRUE
23+
AND ARRAY_LENGTH(`esdtValues`) = 0
24+
AND `status` = 'success'
25+
AND RAND() < 0.25
26+
LIMIT
27+
250 )
28+
UNION ALL
29+
-- Contract execute, with error
30+
(
31+
SELECT
32+
`_id`,
33+
'execute_error' `kind`
34+
FROM
35+
`multiversx-blockchain-etl.crypto_multiversx_mainnet_eu.transactions`
36+
WHERE
37+
DATE(`timestamp`) >= TIMESTAMP_START
38+
AND DATE(`timestamp`) <= TIMESTAMP_END
39+
AND `isScCall` = TRUE
40+
AND ARRAY_LENGTH(`esdtValues`) = 0
41+
AND `status` = 'fail'
42+
AND RAND() < 0.25
43+
LIMIT
44+
250 )
45+
UNION ALL
46+
-- Contract transfer & execute, with success
47+
(
48+
SELECT
49+
`_id`,
50+
'transfer_execute_success' `kind`
51+
FROM
52+
`multiversx-blockchain-etl.crypto_multiversx_mainnet_eu.transactions`
53+
WHERE
54+
DATE(`timestamp`) >= TIMESTAMP_START
55+
AND DATE(`timestamp`) <= TIMESTAMP_END
56+
AND `isScCall` = TRUE
57+
AND ARRAY_LENGTH(`esdtValues`) > 0
58+
AND `status` = 'success'
59+
AND RAND() < 0.25
60+
LIMIT
61+
250 )
62+
UNION ALL
63+
-- Contract transfer & execute, with error
64+
(
65+
SELECT
66+
`_id`,
67+
'transfer_execute_error' `kind`
68+
FROM
69+
`multiversx-blockchain-etl.crypto_multiversx_mainnet_eu.transactions`
70+
WHERE
71+
DATE(`timestamp`) >= TIMESTAMP_START
72+
AND DATE(`timestamp`) <= TIMESTAMP_END
73+
AND `isScCall` = TRUE
74+
AND ARRAY_LENGTH(`esdtValues`) > 0
75+
AND `status` = 'fail'
76+
AND RAND() < 0.25
77+
LIMIT
78+
250)
79+
UNION ALL
80+
-- Relayed, with success
81+
(
82+
SELECT
83+
`_id`,
84+
'relayed_success' `kind`
85+
FROM
86+
`multiversx-blockchain-etl.crypto_multiversx_mainnet_eu.transactions`
87+
WHERE
88+
DATE(`timestamp`) >= TIMESTAMP_START
89+
AND DATE(`timestamp`) <= TIMESTAMP_END
90+
AND `isRelayed` = TRUE
91+
AND `status` = 'success'
92+
AND RAND() < 0.25
93+
LIMIT
94+
50)
95+
UNION ALL
96+
-- Relayed, with failure
97+
(
98+
SELECT
99+
`_id`,
100+
'relayed_error' `kind`
101+
FROM
102+
`multiversx-blockchain-etl.crypto_multiversx_mainnet_eu.transactions`
103+
WHERE
104+
DATE(`timestamp`) >= TIMESTAMP_START
105+
AND DATE(`timestamp`) <= TIMESTAMP_END
106+
AND `isRelayed` = TRUE
107+
AND `status` = 'fail'
108+
AND RAND() < 0.25
109+
LIMIT
110+
50)
111+
```

0 commit comments

Comments
 (0)