UNPKG

hardhat

Version:

Hardhat is an extensible developer tool that helps smart contract developers increase productivity by reliably bringing together the tools they want.

161 lines 8.76 kB
import util from "node:util"; import { bytesToHexString } from "@nomicfoundation/hardhat-utils/bytes"; import { bytesToBigInt, bytesToNumber, } from "@nomicfoundation/hardhat-utils/number"; import { AddressTy, BoolTy, Bytes10Ty, Bytes11Ty, Bytes12Ty, Bytes13Ty, Bytes14Ty, Bytes15Ty, Bytes16Ty, Bytes17Ty, Bytes18Ty, Bytes19Ty, Bytes1Ty, Bytes20Ty, Bytes21Ty, Bytes22Ty, Bytes23Ty, Bytes24Ty, Bytes25Ty, Bytes26Ty, Bytes27Ty, Bytes28Ty, Bytes29Ty, Bytes2Ty, Bytes30Ty, Bytes31Ty, Bytes32Ty, Bytes3Ty, Bytes4Ty, Bytes5Ty, Bytes6Ty, Bytes7Ty, Bytes8Ty, Bytes9Ty, BytesTy, Int256Ty, StringTy, Uint256Ty, CONSOLE_LOG_SIGNATURES, } from "./console-log-signatures.js"; /** * Interprets a `Uint8Array` as a signed integer and returns a `BigInt`. Assumes 256-bit numbers. * @param {Uint8Array} num Signed integer value * @returns {bigint} */ const fromSigned = (num) => { return BigInt.asIntN(256, bytesToBigInt(num)); }; const REGISTER_SIZE = 32; export class ConsoleLogger { /** * Temporary code to print console.sol messages that come from EDR */ static getDecodedLogs(messages) { const logs = []; for (const message of messages) { const log = ConsoleLogger.#maybeConsoleLog(message); if (log !== undefined) { logs.push(ConsoleLogger.format(log)); } } return logs; } /** * Returns a formatted string using the first argument as a `printf`-like * format string which can contain zero or more format specifiers. * * If there are more arguments passed than the number of specifiers, the * extra arguments are concatenated to the returned string, separated by spaces. */ static format(args = []) { return util.format(...args); } /** Decodes a calldata buffer into string arguments for a console log. */ static #maybeConsoleLog(calldata) { const selector = bytesToNumber(calldata.subarray(0, 4)); const parameters = calldata.subarray(4); const argTypes = CONSOLE_LOG_SIGNATURES[selector]; if (argTypes === undefined) { return; } const decodedArgs = ConsoleLogger.#decode(parameters, argTypes); /** * The first argument is interpreted as the format string, which may need adjusting. * Replace the occurrences of %d and %i with %s. This is necessary because if the arguments passed are numbers, * they could be too large to be formatted as a Number or an Integer, so it is safer to use a String. * %d and %i are replaced only if there is an odd number of % before the d or i. * If there is an even number of % then it is assumed that the % is escaped and should not be replaced. * The regex matches a '%d' or an '%i' that has an even number of * '%' behind it (including 0). This group of pairs of '%' is captured * and preserved, while the '%[di]' is replaced with '%s'. * Naively doing (%%)* is not enough; we also have to use the * (?<!%) negative look-behind to make this work. * The (?:) is just to avoid capturing that inner group. */ if (decodedArgs.length > 0) { decodedArgs[0] = decodedArgs[0].replace(/((?<!%)(?:%%)*)(%[di])/g, "$1%s"); } return decodedArgs; } /** Decodes calldata parameters from `data` according to `types` into their string representation. */ static #decode(data, types) { return types.map((type, i) => { const position = i * 32; switch (types[i]) { case Uint256Ty: return bytesToBigInt(data.subarray(position, position + REGISTER_SIZE)).toString(10); case Int256Ty: return fromSigned(data.subarray(position, position + REGISTER_SIZE)).toString(); case BoolTy: if (data[position + 31] !== 0) { return "true"; } return "false"; case StringTy: const sStart = bytesToNumber(data.subarray(position, position + REGISTER_SIZE)); const sLen = bytesToNumber(data.subarray(sStart, sStart + REGISTER_SIZE)); return data .subarray(sStart + REGISTER_SIZE, sStart + REGISTER_SIZE + sLen) .toString(); case AddressTy: return bytesToHexString(data.subarray(position + 12, position + REGISTER_SIZE)); case BytesTy: const bStart = bytesToNumber(data.subarray(position, position + REGISTER_SIZE)); const bLen = bytesToNumber(data.subarray(bStart, bStart + REGISTER_SIZE)); return bytesToHexString(data.subarray(bStart + REGISTER_SIZE, bStart + REGISTER_SIZE + bLen)); case Bytes1Ty: return bytesToHexString(data.subarray(position, position + 1)); case Bytes2Ty: return bytesToHexString(data.subarray(position, position + 2)); case Bytes3Ty: return bytesToHexString(data.subarray(position, position + 3)); case Bytes4Ty: return bytesToHexString(data.subarray(position, position + 4)); case Bytes5Ty: return bytesToHexString(data.subarray(position, position + 5)); case Bytes6Ty: return bytesToHexString(data.subarray(position, position + 6)); case Bytes7Ty: return bytesToHexString(data.subarray(position, position + 7)); case Bytes8Ty: return bytesToHexString(data.subarray(position, position + 8)); case Bytes9Ty: return bytesToHexString(data.subarray(position, position + 9)); case Bytes10Ty: return bytesToHexString(data.subarray(position, position + 10)); case Bytes11Ty: return bytesToHexString(data.subarray(position, position + 11)); case Bytes12Ty: return bytesToHexString(data.subarray(position, position + 12)); case Bytes13Ty: return bytesToHexString(data.subarray(position, position + 13)); case Bytes14Ty: return bytesToHexString(data.subarray(position, position + 14)); case Bytes15Ty: return bytesToHexString(data.subarray(position, position + 15)); case Bytes16Ty: return bytesToHexString(data.subarray(position, position + 16)); case Bytes17Ty: return bytesToHexString(data.subarray(position, position + 17)); case Bytes18Ty: return bytesToHexString(data.subarray(position, position + 18)); case Bytes19Ty: return bytesToHexString(data.subarray(position, position + 19)); case Bytes20Ty: return bytesToHexString(data.subarray(position, position + 20)); case Bytes21Ty: return bytesToHexString(data.subarray(position, position + 21)); case Bytes22Ty: return bytesToHexString(data.subarray(position, position + 22)); case Bytes23Ty: return bytesToHexString(data.subarray(position, position + 23)); case Bytes24Ty: return bytesToHexString(data.subarray(position, position + 24)); case Bytes25Ty: return bytesToHexString(data.subarray(position, position + 25)); case Bytes26Ty: return bytesToHexString(data.subarray(position, position + 26)); case Bytes27Ty: return bytesToHexString(data.subarray(position, position + 27)); case Bytes28Ty: return bytesToHexString(data.subarray(position, position + 28)); case Bytes29Ty: return bytesToHexString(data.subarray(position, position + 29)); case Bytes30Ty: return bytesToHexString(data.subarray(position, position + 30)); case Bytes31Ty: return bytesToHexString(data.subarray(position, position + 31)); case Bytes32Ty: return bytesToHexString(data.subarray(position, position + 32)); default: return ""; } }); } } //# sourceMappingURL=console-logger.js.map