truffle
Version:
Truffle - Simple development framework for Ethereum
1,548 lines (1,341 loc) • 54.6 kB
JavaScript
#!/usr/bin/env node
/******/ (() => { // webpackBootstrap
/******/ var __webpack_modules__ = ({
/***/ 92936:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ getAddress: () => (/* binding */ getAddress),
/* harmony export */ getContractAddress: () => (/* binding */ getContractAddress),
/* harmony export */ getCreate2Address: () => (/* binding */ getCreate2Address),
/* harmony export */ getIcapAddress: () => (/* binding */ getIcapAddress),
/* harmony export */ isAddress: () => (/* binding */ isAddress)
/* harmony export */ });
/* harmony import */ var _ethersproject_bytes__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(46366);
/* harmony import */ var _ethersproject_bignumber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(2593);
/* harmony import */ var _ethersproject_keccak256__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(38197);
/* harmony import */ var _ethersproject_rlp__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(50284);
/* harmony import */ var _ethersproject_logger__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(66167);
/* harmony import */ var _version__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6915);
const logger = new _ethersproject_logger__WEBPACK_IMPORTED_MODULE_0__/* .Logger */ .Yd(_version__WEBPACK_IMPORTED_MODULE_1__/* .version */ .i);
function getChecksumAddress(address) {
if (!(0,_ethersproject_bytes__WEBPACK_IMPORTED_MODULE_2__/* .isHexString */ .A7)(address, 20)) {
logger.throwArgumentError("invalid address", "address", address);
}
address = address.toLowerCase();
const chars = address.substring(2).split("");
const expanded = new Uint8Array(40);
for (let i = 0; i < 40; i++) {
expanded[i] = chars[i].charCodeAt(0);
}
const hashed = (0,_ethersproject_bytes__WEBPACK_IMPORTED_MODULE_2__/* .arrayify */ .lE)((0,_ethersproject_keccak256__WEBPACK_IMPORTED_MODULE_3__/* .keccak256 */ .w)(expanded));
for (let i = 0; i < 40; i += 2) {
if ((hashed[i >> 1] >> 4) >= 8) {
chars[i] = chars[i].toUpperCase();
}
if ((hashed[i >> 1] & 0x0f) >= 8) {
chars[i + 1] = chars[i + 1].toUpperCase();
}
}
return "0x" + chars.join("");
}
// Shims for environments that are missing some required constants and functions
const MAX_SAFE_INTEGER = 0x1fffffffffffff;
function log10(x) {
if (Math.log10) {
return Math.log10(x);
}
return Math.log(x) / Math.LN10;
}
// See: https://en.wikipedia.org/wiki/International_Bank_Account_Number
// Create lookup table
const ibanLookup = {};
for (let i = 0; i < 10; i++) {
ibanLookup[String(i)] = String(i);
}
for (let i = 0; i < 26; i++) {
ibanLookup[String.fromCharCode(65 + i)] = String(10 + i);
}
// How many decimal digits can we process? (for 64-bit float, this is 15)
const safeDigits = Math.floor(log10(MAX_SAFE_INTEGER));
function ibanChecksum(address) {
address = address.toUpperCase();
address = address.substring(4) + address.substring(0, 2) + "00";
let expanded = address.split("").map((c) => { return ibanLookup[c]; }).join("");
// Javascript can handle integers safely up to 15 (decimal) digits
while (expanded.length >= safeDigits) {
let block = expanded.substring(0, safeDigits);
expanded = parseInt(block, 10) % 97 + expanded.substring(block.length);
}
let checksum = String(98 - (parseInt(expanded, 10) % 97));
while (checksum.length < 2) {
checksum = "0" + checksum;
}
return checksum;
}
;
function getAddress(address) {
let result = null;
if (typeof (address) !== "string") {
logger.throwArgumentError("invalid address", "address", address);
}
if (address.match(/^(0x)?[0-9a-fA-F]{40}$/)) {
// Missing the 0x prefix
if (address.substring(0, 2) !== "0x") {
address = "0x" + address;
}
result = getChecksumAddress(address);
// It is a checksummed address with a bad checksum
if (address.match(/([A-F].*[a-f])|([a-f].*[A-F])/) && result !== address) {
logger.throwArgumentError("bad address checksum", "address", address);
}
// Maybe ICAP? (we only support direct mode)
}
else if (address.match(/^XE[0-9]{2}[0-9A-Za-z]{30,31}$/)) {
// It is an ICAP address with a bad checksum
if (address.substring(2, 4) !== ibanChecksum(address)) {
logger.throwArgumentError("bad icap checksum", "address", address);
}
result = (0,_ethersproject_bignumber__WEBPACK_IMPORTED_MODULE_4__/* ._base36To16 */ .g$)(address.substring(4));
while (result.length < 40) {
result = "0" + result;
}
result = getChecksumAddress("0x" + result);
}
else {
logger.throwArgumentError("invalid address", "address", address);
}
return result;
}
function isAddress(address) {
try {
getAddress(address);
return true;
}
catch (error) { }
return false;
}
function getIcapAddress(address) {
let base36 = (0,_ethersproject_bignumber__WEBPACK_IMPORTED_MODULE_4__/* ._base16To36 */ .t2)(getAddress(address).substring(2)).toUpperCase();
while (base36.length < 30) {
base36 = "0" + base36;
}
return "XE" + ibanChecksum("XE00" + base36) + base36;
}
// http://ethereum.stackexchange.com/questions/760/how-is-the-address-of-an-ethereum-contract-computed
function getContractAddress(transaction) {
let from = null;
try {
from = getAddress(transaction.from);
}
catch (error) {
logger.throwArgumentError("missing from address", "transaction", transaction);
}
const nonce = (0,_ethersproject_bytes__WEBPACK_IMPORTED_MODULE_2__/* .stripZeros */ .G1)((0,_ethersproject_bytes__WEBPACK_IMPORTED_MODULE_2__/* .arrayify */ .lE)(_ethersproject_bignumber__WEBPACK_IMPORTED_MODULE_4__/* .BigNumber */ .O$.from(transaction.nonce).toHexString()));
return getAddress((0,_ethersproject_bytes__WEBPACK_IMPORTED_MODULE_2__/* .hexDataSlice */ .p3)((0,_ethersproject_keccak256__WEBPACK_IMPORTED_MODULE_3__/* .keccak256 */ .w)((0,_ethersproject_rlp__WEBPACK_IMPORTED_MODULE_5__.encode)([from, nonce])), 12));
}
function getCreate2Address(from, salt, initCodeHash) {
if ((0,_ethersproject_bytes__WEBPACK_IMPORTED_MODULE_2__/* .hexDataLength */ .E1)(salt) !== 32) {
logger.throwArgumentError("salt must be 32 bytes", "salt", salt);
}
if ((0,_ethersproject_bytes__WEBPACK_IMPORTED_MODULE_2__/* .hexDataLength */ .E1)(initCodeHash) !== 32) {
logger.throwArgumentError("initCodeHash must be 32 bytes", "initCodeHash", initCodeHash);
}
return getAddress((0,_ethersproject_bytes__WEBPACK_IMPORTED_MODULE_2__/* .hexDataSlice */ .p3)((0,_ethersproject_keccak256__WEBPACK_IMPORTED_MODULE_3__/* .keccak256 */ .w)((0,_ethersproject_bytes__WEBPACK_IMPORTED_MODULE_2__/* .concat */ .zo)(["0xff", getAddress(from), salt, initCodeHash])), 12));
}
//# sourceMappingURL=index.js.map
/***/ }),
/***/ 20335:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ Ox: () => (/* binding */ parseFixed),
/* harmony export */ S5: () => (/* binding */ formatFixed),
/* harmony export */ xs: () => (/* binding */ FixedNumber)
/* harmony export */ });
/* unused harmony export FixedFormat */
/* harmony import */ var _ethersproject_bytes__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(46366);
/* harmony import */ var _ethersproject_logger__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(66167);
/* harmony import */ var _version__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(48794);
/* harmony import */ var _bignumber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(2593);
const logger = new _ethersproject_logger__WEBPACK_IMPORTED_MODULE_0__/* .Logger */ .Yd(_version__WEBPACK_IMPORTED_MODULE_1__/* .version */ .i);
const _constructorGuard = {};
const Zero = _bignumber__WEBPACK_IMPORTED_MODULE_2__/* .BigNumber */ .O$.from(0);
const NegativeOne = _bignumber__WEBPACK_IMPORTED_MODULE_2__/* .BigNumber */ .O$.from(-1);
function throwFault(message, fault, operation, value) {
const params = { fault: fault, operation: operation };
if (value !== undefined) {
params.value = value;
}
return logger.throwError(message, _ethersproject_logger__WEBPACK_IMPORTED_MODULE_0__/* .Logger */ .Yd.errors.NUMERIC_FAULT, params);
}
// Constant to pull zeros from for multipliers
let zeros = "0";
while (zeros.length < 256) {
zeros += zeros;
}
// Returns a string "1" followed by decimal "0"s
function getMultiplier(decimals) {
if (typeof (decimals) !== "number") {
try {
decimals = _bignumber__WEBPACK_IMPORTED_MODULE_2__/* .BigNumber */ .O$.from(decimals).toNumber();
}
catch (e) { }
}
if (typeof (decimals) === "number" && decimals >= 0 && decimals <= 256 && !(decimals % 1)) {
return ("1" + zeros.substring(0, decimals));
}
return logger.throwArgumentError("invalid decimal size", "decimals", decimals);
}
function formatFixed(value, decimals) {
if (decimals == null) {
decimals = 0;
}
const multiplier = getMultiplier(decimals);
// Make sure wei is a big number (convert as necessary)
value = _bignumber__WEBPACK_IMPORTED_MODULE_2__/* .BigNumber */ .O$.from(value);
const negative = value.lt(Zero);
if (negative) {
value = value.mul(NegativeOne);
}
let fraction = value.mod(multiplier).toString();
while (fraction.length < multiplier.length - 1) {
fraction = "0" + fraction;
}
// Strip training 0
fraction = fraction.match(/^([0-9]*[1-9]|0)(0*)/)[1];
const whole = value.div(multiplier).toString();
if (multiplier.length === 1) {
value = whole;
}
else {
value = whole + "." + fraction;
}
if (negative) {
value = "-" + value;
}
return value;
}
function parseFixed(value, decimals) {
if (decimals == null) {
decimals = 0;
}
const multiplier = getMultiplier(decimals);
if (typeof (value) !== "string" || !value.match(/^-?[0-9.]+$/)) {
logger.throwArgumentError("invalid decimal value", "value", value);
}
// Is it negative?
const negative = (value.substring(0, 1) === "-");
if (negative) {
value = value.substring(1);
}
if (value === ".") {
logger.throwArgumentError("missing value", "value", value);
}
// Split it into a whole and fractional part
const comps = value.split(".");
if (comps.length > 2) {
logger.throwArgumentError("too many decimal points", "value", value);
}
let whole = comps[0], fraction = comps[1];
if (!whole) {
whole = "0";
}
if (!fraction) {
fraction = "0";
}
// Trim trailing zeros
while (fraction[fraction.length - 1] === "0") {
fraction = fraction.substring(0, fraction.length - 1);
}
// Check the fraction doesn't exceed our decimals size
if (fraction.length > multiplier.length - 1) {
throwFault("fractional component exceeds decimals", "underflow", "parseFixed");
}
// If decimals is 0, we have an empty string for fraction
if (fraction === "") {
fraction = "0";
}
// Fully pad the string with zeros to get to wei
while (fraction.length < multiplier.length - 1) {
fraction += "0";
}
const wholeValue = _bignumber__WEBPACK_IMPORTED_MODULE_2__/* .BigNumber */ .O$.from(whole);
const fractionValue = _bignumber__WEBPACK_IMPORTED_MODULE_2__/* .BigNumber */ .O$.from(fraction);
let wei = (wholeValue.mul(multiplier)).add(fractionValue);
if (negative) {
wei = wei.mul(NegativeOne);
}
return wei;
}
class FixedFormat {
constructor(constructorGuard, signed, width, decimals) {
if (constructorGuard !== _constructorGuard) {
logger.throwError("cannot use FixedFormat constructor; use FixedFormat.from", _ethersproject_logger__WEBPACK_IMPORTED_MODULE_0__/* .Logger */ .Yd.errors.UNSUPPORTED_OPERATION, {
operation: "new FixedFormat"
});
}
this.signed = signed;
this.width = width;
this.decimals = decimals;
this.name = (signed ? "" : "u") + "fixed" + String(width) + "x" + String(decimals);
this._multiplier = getMultiplier(decimals);
Object.freeze(this);
}
static from(value) {
if (value instanceof FixedFormat) {
return value;
}
if (typeof (value) === "number") {
value = `fixed128x${value}`;
}
let signed = true;
let width = 128;
let decimals = 18;
if (typeof (value) === "string") {
if (value === "fixed") {
// defaults...
}
else if (value === "ufixed") {
signed = false;
}
else {
const match = value.match(/^(u?)fixed([0-9]+)x([0-9]+)$/);
if (!match) {
logger.throwArgumentError("invalid fixed format", "format", value);
}
signed = (match[1] !== "u");
width = parseInt(match[2]);
decimals = parseInt(match[3]);
}
}
else if (value) {
const check = (key, type, defaultValue) => {
if (value[key] == null) {
return defaultValue;
}
if (typeof (value[key]) !== type) {
logger.throwArgumentError("invalid fixed format (" + key + " not " + type + ")", "format." + key, value[key]);
}
return value[key];
};
signed = check("signed", "boolean", signed);
width = check("width", "number", width);
decimals = check("decimals", "number", decimals);
}
if (width % 8) {
logger.throwArgumentError("invalid fixed format width (not byte aligned)", "format.width", width);
}
if (decimals > 80) {
logger.throwArgumentError("invalid fixed format (decimals too large)", "format.decimals", decimals);
}
return new FixedFormat(_constructorGuard, signed, width, decimals);
}
}
class FixedNumber {
constructor(constructorGuard, hex, value, format) {
if (constructorGuard !== _constructorGuard) {
logger.throwError("cannot use FixedNumber constructor; use FixedNumber.from", _ethersproject_logger__WEBPACK_IMPORTED_MODULE_0__/* .Logger */ .Yd.errors.UNSUPPORTED_OPERATION, {
operation: "new FixedFormat"
});
}
this.format = format;
this._hex = hex;
this._value = value;
this._isFixedNumber = true;
Object.freeze(this);
}
_checkFormat(other) {
if (this.format.name !== other.format.name) {
logger.throwArgumentError("incompatible format; use fixedNumber.toFormat", "other", other);
}
}
addUnsafe(other) {
this._checkFormat(other);
const a = parseFixed(this._value, this.format.decimals);
const b = parseFixed(other._value, other.format.decimals);
return FixedNumber.fromValue(a.add(b), this.format.decimals, this.format);
}
subUnsafe(other) {
this._checkFormat(other);
const a = parseFixed(this._value, this.format.decimals);
const b = parseFixed(other._value, other.format.decimals);
return FixedNumber.fromValue(a.sub(b), this.format.decimals, this.format);
}
mulUnsafe(other) {
this._checkFormat(other);
const a = parseFixed(this._value, this.format.decimals);
const b = parseFixed(other._value, other.format.decimals);
return FixedNumber.fromValue(a.mul(b).div(this.format._multiplier), this.format.decimals, this.format);
}
divUnsafe(other) {
this._checkFormat(other);
const a = parseFixed(this._value, this.format.decimals);
const b = parseFixed(other._value, other.format.decimals);
return FixedNumber.fromValue(a.mul(this.format._multiplier).div(b), this.format.decimals, this.format);
}
floor() {
const comps = this.toString().split(".");
if (comps.length === 1) {
comps.push("0");
}
let result = FixedNumber.from(comps[0], this.format);
const hasFraction = !comps[1].match(/^(0*)$/);
if (this.isNegative() && hasFraction) {
result = result.subUnsafe(ONE.toFormat(result.format));
}
return result;
}
ceiling() {
const comps = this.toString().split(".");
if (comps.length === 1) {
comps.push("0");
}
let result = FixedNumber.from(comps[0], this.format);
const hasFraction = !comps[1].match(/^(0*)$/);
if (!this.isNegative() && hasFraction) {
result = result.addUnsafe(ONE.toFormat(result.format));
}
return result;
}
// @TODO: Support other rounding algorithms
round(decimals) {
if (decimals == null) {
decimals = 0;
}
// If we are already in range, we're done
const comps = this.toString().split(".");
if (comps.length === 1) {
comps.push("0");
}
if (decimals < 0 || decimals > 80 || (decimals % 1)) {
logger.throwArgumentError("invalid decimal count", "decimals", decimals);
}
if (comps[1].length <= decimals) {
return this;
}
const factor = FixedNumber.from("1" + zeros.substring(0, decimals), this.format);
const bump = BUMP.toFormat(this.format);
return this.mulUnsafe(factor).addUnsafe(bump).floor().divUnsafe(factor);
}
isZero() {
return (this._value === "0.0" || this._value === "0");
}
isNegative() {
return (this._value[0] === "-");
}
toString() { return this._value; }
toHexString(width) {
if (width == null) {
return this._hex;
}
if (width % 8) {
logger.throwArgumentError("invalid byte width", "width", width);
}
const hex = _bignumber__WEBPACK_IMPORTED_MODULE_2__/* .BigNumber */ .O$.from(this._hex).fromTwos(this.format.width).toTwos(width).toHexString();
return (0,_ethersproject_bytes__WEBPACK_IMPORTED_MODULE_3__/* .hexZeroPad */ .$m)(hex, width / 8);
}
toUnsafeFloat() { return parseFloat(this.toString()); }
toFormat(format) {
return FixedNumber.fromString(this._value, format);
}
static fromValue(value, decimals, format) {
// If decimals looks more like a format, and there is no format, shift the parameters
if (format == null && decimals != null && !(0,_bignumber__WEBPACK_IMPORTED_MODULE_2__/* .isBigNumberish */ .Zm)(decimals)) {
format = decimals;
decimals = null;
}
if (decimals == null) {
decimals = 0;
}
if (format == null) {
format = "fixed";
}
return FixedNumber.fromString(formatFixed(value, decimals), FixedFormat.from(format));
}
static fromString(value, format) {
if (format == null) {
format = "fixed";
}
const fixedFormat = FixedFormat.from(format);
const numeric = parseFixed(value, fixedFormat.decimals);
if (!fixedFormat.signed && numeric.lt(Zero)) {
throwFault("unsigned value cannot be negative", "overflow", "value", value);
}
let hex = null;
if (fixedFormat.signed) {
hex = numeric.toTwos(fixedFormat.width).toHexString();
}
else {
hex = numeric.toHexString();
hex = (0,_ethersproject_bytes__WEBPACK_IMPORTED_MODULE_3__/* .hexZeroPad */ .$m)(hex, fixedFormat.width / 8);
}
const decimal = formatFixed(numeric, fixedFormat.decimals);
return new FixedNumber(_constructorGuard, hex, decimal, fixedFormat);
}
static fromBytes(value, format) {
if (format == null) {
format = "fixed";
}
const fixedFormat = FixedFormat.from(format);
if ((0,_ethersproject_bytes__WEBPACK_IMPORTED_MODULE_3__/* .arrayify */ .lE)(value).length > fixedFormat.width / 8) {
throw new Error("overflow");
}
let numeric = _bignumber__WEBPACK_IMPORTED_MODULE_2__/* .BigNumber */ .O$.from(value);
if (fixedFormat.signed) {
numeric = numeric.fromTwos(fixedFormat.width);
}
const hex = numeric.toTwos((fixedFormat.signed ? 0 : 1) + fixedFormat.width).toHexString();
const decimal = formatFixed(numeric, fixedFormat.decimals);
return new FixedNumber(_constructorGuard, hex, decimal, fixedFormat);
}
static from(value, format) {
if (typeof (value) === "string") {
return FixedNumber.fromString(value, format);
}
if ((0,_ethersproject_bytes__WEBPACK_IMPORTED_MODULE_3__/* .isBytes */ ._t)(value)) {
return FixedNumber.fromBytes(value, format);
}
try {
return FixedNumber.fromValue(value, 0, format);
}
catch (error) {
// Allow NUMERIC_FAULT to bubble up
if (error.code !== _ethersproject_logger__WEBPACK_IMPORTED_MODULE_0__/* .Logger */ .Yd.errors.INVALID_ARGUMENT) {
throw error;
}
}
return logger.throwArgumentError("invalid FixedNumber value", "value", value);
}
static isFixedNumber(value) {
return !!(value && value._isFixedNumber);
}
}
const ONE = FixedNumber.from(1);
const BUMP = FixedNumber.from("0.5");
//# sourceMappingURL=fixednumber.js.map
/***/ }),
/***/ 89923:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
module.exports = {
run: __webpack_require__(69909),
meta: __webpack_require__(21288)
};
/***/ }),
/***/ 69909:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
module.exports = async function (options) {
const OS = __webpack_require__(22037);
const { Console } = __webpack_require__(68303);
const { Environment } = __webpack_require__(76765);
const TruffleError = __webpack_require__(73321);
const loadConfig = __webpack_require__(932);
if (options.url && options.network) {
const message =
"" +
"Mutually exclusive options, --url and --network detected!" +
OS.EOL +
"Please use either --url or --network and try again." +
OS.EOL +
"See: https://trufflesuite.com/docs/truffle/reference/truffle-commands/#console" +
OS.EOL;
throw new TruffleError(message);
}
let config = loadConfig(options);
await Environment.detect(config);
const c = new Console(config.with({ noAliases: true }));
return await c.start();
};
/***/ }),
/***/ 68303:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
const repl = __webpack_require__(38102);
const provision = __webpack_require__(7702);
const {
Web3Shim,
createInterfaceAdapter
} = __webpack_require__(36339);
const contract = __webpack_require__(78883);
const os = __webpack_require__(22037);
const vm = __webpack_require__(26144);
const expect = __webpack_require__(14096);
const TruffleError = __webpack_require__(73321);
const fse = __webpack_require__(55674);
const path = __webpack_require__(71017);
const EventEmitter = __webpack_require__(82361);
const { spawn } = __webpack_require__(32081);
const Require = __webpack_require__(35422);
const debug = __webpack_require__(15158)("console");
const { parseQuotesAndEscapes } = __webpack_require__(34763);
const {
excludedTruffleConsoleCommands,
validTruffleConsoleCommands
} = __webpack_require__(91874);
// Create an expression that returns a string when evaluated
// by the REPL
const makeIIFE = str => `(() => "${str}")()`;
const processInput = input => {
const words = input.trim().split(/\s+/);
// empty input
if (words.length === 0) return input;
// maybe truffle command
if (words[0].toLowerCase() === "truffle") {
const cmd = words[1];
if (cmd === undefined) {
return makeIIFE(
`ℹ️ : 'Missing truffle command. Please include a valid truffle command.`
);
}
const normalizedCommand = cmd.toLowerCase();
const isExcludedInREPL =
excludedTruffleConsoleCommands.includes(normalizedCommand);
if (isExcludedInREPL) {
return makeIIFE(
`ℹ️ : '${words[0]} ${cmd}' is not allowed in Console environment.`
);
}
if (!validTruffleConsoleCommands.includes(normalizedCommand)) {
return makeIIFE(
`ℹ️ : '${words[0]} ${cmd}' is not a valid truffle command.`
);
}
return words.slice(1).join(" ");
}
// an expression
return input.trim();
};
class Console extends EventEmitter {
constructor(options) {
super();
EventEmitter.call(this);
expect.options(options, [
"working_directory",
"contracts_directory",
"contracts_build_directory",
"migrations_directory",
"networks",
"network",
"network_id",
"provider",
"resolver",
"build_directory"
]);
this.options = options;
this.repl = null;
// we need to keep track of name conflicts that occur between contracts and
// repl context objects so as not to overwrite them - this is to prevent
// overwriting Node native objects like Buffer, number, etc.
this.replGlobals = new Set();
this.knownReplNameConflicts = new Set();
this.newReplNameConflicts = new Set();
this.interfaceAdapter = createInterfaceAdapter({
provider: options.provider,
networkType: options.networks[options.network].type
});
this.web3 = new Web3Shim({
provider: options.provider,
networkType: options.networks[options.network].type
});
}
recordNameConflicts(abstractions) {
for (const abstraction of abstractions) {
const name = abstraction.contract_name;
if (
!this.knownReplNameConflicts.has(name) &&
this.replGlobals.has(name)
) {
this.newReplNameConflicts.add(name);
this.knownReplNameConflicts.add(name);
}
}
}
async start() {
try {
// start the repl with an empty prompt and show a proper one when
// the repl has set up its context and is ready to accept input
this.repl = repl.start({
prompt: "",
eval: this.interpret.bind(this)
});
// Get and set Truffle and User Globals
const truffleAndUserGlobals = await this.calculateTruffleAndUserGlobals();
Object.entries(truffleAndUserGlobals).forEach(([key, value]) => {
this.repl.context[key] = value;
});
// record name conflicts to avoid clobbering globals with contracts
this.replGlobals = new Set(
Object.getOwnPropertyNames(this.repl.context.global)
);
// repl is ready - set and display prompt
this.repl.setPrompt("truffle(" + this.options.network + ")> ");
// hydrate the environment with the user's contracts
this.provision();
// provision first before displaying prompt so that if
// there is a warning the user will end up at the prompt
this.repl.displayPrompt();
this.repl.on("exit", () => {
process.exit();
});
// ensure that `await`-ing this method never resolves. (we want to keep
// the console open until it exits on its own)
return new Promise(() => {});
} catch (error) {
this.options.logger.log(
"Unexpected error setting up the environment or provisioning " +
"contracts while instantiating the console."
);
this.options.logger.log(error.stack || error.message || error);
}
}
getUserDefinedGlobals({ accounts, interfaceAdapter, web3 }) {
// exit if feature should be disabled
if (this.options["require-none"]) return;
// exit if no hydrate options are set
if (
(!this.options.console || !this.options.console.require) &&
!this.options.require &&
!this.options.r
)
return;
const addToContext = (context, userData, namespace) => {
for (const key in userData) {
if (namespace) {
if (typeof context[namespace] === "undefined") {
context[namespace] = {};
}
context[namespace][key] = userData[key];
} else {
context[key] = userData[key];
}
}
};
const errorMessage =
"You must specify the console.require property as " +
"either a string or an array. If you specify an array, its members " +
"must be paths or objects containing at least a `path` property.";
const requireValue =
this.options.r || this.options.require || this.options.console.require;
// Require allows us to inject Truffle variables into the script's scope
const requireOptions = {
context: {
accounts,
interfaceAdapter,
web3
}
};
const userGlobals = {};
if (typeof requireValue === "string") {
requireOptions.file = requireValue;
addToContext(userGlobals, Require.file(requireOptions));
} else if (Array.isArray(requireValue)) {
this.options.console.require.forEach(item => {
if (typeof item === "string") {
requireOptions.file = item;
addToContext(userGlobals, Require.file(requireOptions));
} else if (typeof item === "object" && item.path) {
requireOptions.file = item.path;
addToContext(userGlobals, Require.file(requireOptions), item.as);
} else {
throw new Error(errorMessage);
}
});
} else {
throw new Error(errorMessage);
}
return userGlobals;
}
async calculateTruffleAndUserGlobals() {
let accounts;
try {
accounts = await this.interfaceAdapter.getAccounts();
} catch {
// don't prevent Truffle from working if user doesn't provide some way
// to sign transactions (e.g. no reason to disallow debugging)
accounts = [];
}
const userGlobals = this.getUserDefinedGlobals({
web3: this.web3,
interfaceAdapter: this.interfaceAdapter,
accounts
});
const truffleGlobals = {
web3: this.web3,
interfaceAdapter: this.interfaceAdapter,
accounts,
artifacts: this.options.resolver
};
// we insert user variables first so as to not clobber Truffle's
return {
...userGlobals,
...truffleGlobals
};
}
provision() {
let files = [];
let jsonBlobs = [];
try {
files = fse.readdirSync(this.options.contracts_build_directory);
} catch (error) {
// Error reading the build directory? Must mean it doesn't exist or we don't have access to it.
// Couldn't provision the contracts if we wanted. It's possible we're hiding very rare FS
// errors, but that's better than showing the user error messages that will be "build folder
// doesn't exist" 99.9% of the time.
}
files.forEach(file => {
// filter out non artifacts
if (!file.endsWith(".json")) return;
try {
const body = fse.readFileSync(
path.join(this.options.contracts_build_directory, file),
"utf8"
);
const json = JSON.parse(body);
// Artifacts may not contain metadata. For example, early Solidity versions as well as
// Vyper contracts do not include metadata. Just push them to json blobs.
if (json.metadata === undefined) {
jsonBlobs.push(json);
} else {
// filter out Truffle's console.log. We don't want users to interact with in the REPL.
// user contracts named console.log will be imported, and a warning will be issued.
const metadata = JSON.parse(json.metadata);
const sources = Object.keys(metadata.sources);
if (
sources.length > 1 ||
(sources.length === 1 &&
!sources.some(source => {
return (
source === "truffle/console.sol" ||
source === "truffle/Console.sol"
);
}))
) {
jsonBlobs.push(json);
}
}
} catch (error) {
throw new Error(`Error parsing or reading ${file}: ${error.message}`);
}
});
const abstractions = jsonBlobs.map(json => {
const abstraction = contract(json);
provision(abstraction, this.options);
return abstraction;
});
this.recordNameConflicts(abstractions);
this.resetContractsInConsoleContext(abstractions);
return abstractions;
}
resetContractsInConsoleContext(abstractions) {
abstractions = abstractions || [];
const contextVars = {};
abstractions.forEach(abstraction => {
const name = abstraction.contract_name;
// don't overwrite Node's native objects - only load contracts
// into the repl context when no conflict exists
if (!this.knownReplNameConflicts.has(name)) {
contextVars[name] = abstraction;
}
});
if (this.newReplNameConflicts.size > 0) {
const contractNames = [...this.newReplNameConflicts.keys()];
this.newReplNameConflicts.clear();
console.log(
`\n > Warning: One or more of your contract(s) has a name conflict ` +
`with something in the current repl context and was not loaded by ` +
`default. \n > You can use 'artifacts.require("<artifactName>")' ` +
`to obtain a reference to your contract(s). \n > Truffle recommends ` +
`that you rename your contract to avoid problems. \n > The following ` +
`name conflicts exist: ${contractNames.join(", ")}.\n`
);
}
// make sure the repl gets the new contracts in its context
Object.keys(contextVars || {}).forEach(key => {
this.repl.context[key] = contextVars[key];
});
}
async runSpawn(inputStrings, options) {
let childPath;
/* eslint-disable no-undef */
if (true) {
childPath = path.join(__dirname, "consoleChild.bundled.js");
} else {}
const spawnOptions = { stdio: "pipe" };
const settings = ["config", "network", "url"]
.filter(setting => options[setting])
.map(setting => `--${setting} ${options[setting]}`)
.join(" ");
const spawnInput = `${settings} -- ${inputStrings}`;
const spawnedProcess = spawn(
"node",
["--no-deprecation", childPath, spawnInput],
spawnOptions
);
// Theoretically stderr can contain multiple errors.
// So let's just print it instead of throwing through
// the error handling mechanism. Bad call? Who knows...
// better be safe and buffer stderr so that it doesn't
// interrupt stdout, and present it as a complete
// string at the end of the spawned process.
let bufferedError = "";
spawnedProcess.stderr.on("data", data => {
bufferedError += data.toString();
});
spawnedProcess.stdout.on("data", data => {
// convert buffer to string
data = data.toString();
// workaround: remove extra newline in `truffle develop` console
// truffle test, for some reason, appends a newline to the data
// it emits here.
if (data.endsWith(os.EOL)) data = data.slice(0, -os.EOL.length);
console.log(data);
});
return new Promise((resolve, reject) => {
spawnedProcess.on("close", code => {
// dump bufferedError
debug(bufferedError);
if (!code) {
// re-provision to ensure any changes are available in the repl
this.provision();
//display prompt when child repl process is finished
this.repl.displayPrompt();
return void resolve();
}
reject(code);
});
});
}
async interpret(input, context, filename, callback) {
const processedInput = processInput(input);
if (validTruffleConsoleCommands.includes(processedInput.split(/\s+/)[0])) {
try {
parseQuotesAndEscapes(processedInput); //we're just doing this to see
//if it errors. unfortunately we need to throw out the result and recompute
//it afterward (but the input string is probably short so it's OK).
await this.runSpawn(processedInput, this.options);
} catch (error) {
// Perform error handling ourselves.
if (error instanceof TruffleError) {
console.log(error.message);
} else {
// Bubble up all other unexpected errors.
console.log(error.stack || error.toString());
}
return callback();
}
// Reprovision after each command as it may change contracts.
try {
this.provision();
return callback();
} catch (error) {
// Don't pass abstractions to the callback if they're there or else
// they'll get printed in the repl.
return callback(error);
}
}
// Much of the following code is from here, though spruced up:
// https://github.com/nfcampos/await-outside
/*
- allow whitespace before everything else
- optionally capture `var| let |const <varname> = `
- varname only matches if it starts with a-Z or _ or $
and if contains only those chars or numbers
- this is overly restrictive but is easier to maintain
- capture `await <anything that follows it>`
*/
let includesAwait =
/^\s*((?:(?:var|const|let)\s+)?[a-zA-Z_$][0-9a-zA-Z_$]*\s*=\s*)?(\(?\s*await[\s\S]*)/;
const match = processedInput.match(includesAwait);
let source = processedInput;
let assignment = null;
// If our code includes an await, add special processing to ensure it's evaluated properly.
if (match) {
let assign = match[1];
const expression =
match[2] && match[2].endsWith(";")
? // strip off trailing ";" to prevent the expression below from erroring
match[2].slice(0, -1)
: match[2];
const RESULT = "__await_outside_result";
// Wrap the await inside an async function.
// Strange indentation keeps column offset correct in stack traces
source = `(async function() { try {${
assign ? `global.${RESULT} =` : "return"
} (
${expression.trim()}
); } catch(e) {global.ERROR = e; throw e; } }())`;
assignment = assign
? `${assign.trim()} global.${RESULT}; void delete global.${RESULT};`
: null;
//finally, if the assignment did not use var, const, or let, make sure to
//return the result afterward
if (assign) {
const bareAssignmentMatch = assign.match(
/^\s*([a-zA-Z_$][0-9a-zA-Z_$]*)\s*=\s*/
);
if (bareAssignmentMatch) {
const varName = bareAssignmentMatch[1];
assignment += varName;
}
}
}
const runScript = script => {
const options = {
displayErrors: false,
breakOnSigint: true,
filename: filename
};
vm.createContext(context);
return script.runInContext(context, options);
};
let script;
try {
const options = { lineOffset: -1 };
script = vm.createScript(source, options);
} catch (error) {
// If syntax error, or similar, bail.
return callback(error);
}
// Ensure our script returns a promise whether we're using an
// async function or not. If our script is an async function,
// this will ensure the console waits until that await is finished.
Promise.resolve(runScript(script))
.then(value => {
// If there's an assignment to run, run that.
if (assignment) return runScript(vm.createScript(assignment));
return value;
})
.then(value => {
// All good? Return the value (e.g., eval'd script or assignment)
callback(null, value);
})
.catch(callback);
}
}
module.exports = {
Console
};
/***/ }),
/***/ 932:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
module.exports = function (options) {
const Config = __webpack_require__(20553);
const TruffleError = __webpack_require__(73321);
const mergeConfigNetwork = __webpack_require__(22173);
let config;
try {
config = Config.detect(options);
config = mergeConfigNetwork(config, options);
} catch (error) {
if (error instanceof TruffleError && options.url) {
config = Config.default();
config = mergeConfigNetwork(config, options);
// in case config file is not detected (exception thrown) AND url is provided in the options,
// We use default config and set compileNone to true. Since there are is no config files and url is provided,
// It is assumed that truffle debug/console is being used for analysis and debugging and that there is nothing to compile.
// E.g. analysing/debugging a single transaction of an external project
config.compileNone = true;
config.configFileSkipped = true;
} else {
throw error;
}
}
return config;
};
/***/ }),
/***/ 22173:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
const { URL } = __webpack_require__(57310);
module.exports = function (config, options) {
if (options.url) {
const url = new URL(options.url);
config.networks[url.host] = {
url: options.url,
network_id: "*"
};
config.network = url.host;
}
config.merge(options);
return config;
};
/***/ }),
/***/ 70972:
/***/ ((module) => {
"use strict";
module.exports = require("@truffle/db-loader");
/***/ }),
/***/ 11651:
/***/ ((module) => {
"use strict";
module.exports = require("ganache");
/***/ }),
/***/ 44516:
/***/ ((module) => {
"use strict";
module.exports = require("original-require");
/***/ }),
/***/ 39491:
/***/ ((module) => {
"use strict";
module.exports = require("assert");
/***/ }),
/***/ 50852:
/***/ ((module) => {
"use strict";
module.exports = require("async_hooks");
/***/ }),
/***/ 14300:
/***/ ((module) => {
"use strict";
module.exports = require("buffer");
/***/ }),
/***/ 32081:
/***/ ((module) => {
"use strict";
module.exports = require("child_process");
/***/ }),
/***/ 22057:
/***/ ((module) => {
"use strict";
module.exports = require("constants");
/***/ }),
/***/ 6113:
/***/ ((module) => {
"use strict";
module.exports = require("crypto");
/***/ }),
/***/ 71891:
/***/ ((module) => {
"use strict";
module.exports = require("dgram");
/***/ }),
/***/ 82361:
/***/ ((module) => {
"use strict";
module.exports = require("events");
/***/ }),
/***/ 57147:
/***/ ((module) => {
"use strict";
module.exports = require("fs");
/***/ }),
/***/ 73292:
/***/ ((module) => {
"use strict";
module.exports = require("fs/promises");
/***/ }),
/***/ 13685:
/***/ ((module) => {
"use strict";
module.exports = require("http");
/***/ }),
/***/ 95687:
/***/ ((module) => {
"use strict";
module.exports = require("https");
/***/ }),
/***/ 98188:
/***/ ((module) => {
"use strict";
module.exports = require("module");
/***/ }),
/***/ 41808:
/***/ ((module) => {
"use strict";
module.exports = require("net");
/***/ }),
/***/ 22037:
/***/ ((module) => {
"use strict";
module.exports = require("os");
/***/ }),
/***/ 71017:
/***/ ((module) => {
"use strict";
module.exports = require("path");
/***/ }),
/***/ 85477:
/***/ ((module) => {
"use strict";
module.exports = require("punycode");
/***/ }),
/***/ 63477:
/***/ ((module) => {
"use strict";
module.exports = require("querystring");
/***/ }),
/***/ 14521:
/***/ ((module) => {
"use strict";
module.exports = require("readline");
/***/ }),
/***/ 38102:
/***/ ((module) => {
"use strict";
module.exports = require("repl");
/***/ }),
/***/ 12781:
/***/ ((module) => {
"use strict";
module.exports = require("stream");
/***/ }),
/***/ 71576:
/***/ ((module) => {
"use strict";
module.exports = require("string_decoder");
/***/ }),
/***/ 24404:
/***/ ((module) => {
"use strict";
module.exports = require("tls");
/***/ }),
/***/ 76224:
/***/ ((module) => {
"use strict";
module.exports = require("tty");
/***/ }),
/***/ 57310:
/***/ ((module) => {
"use strict";
module.exports = require("url");
/***/ }),
/***/ 73837:
/***/ ((module) => {
"use strict";
module.exports = require("util");
/***/ }),
/***/ 26144:
/***/ ((module) => {
"use strict";
module.exports = require("vm");
/***/ }),
/***/ 59796:
/***/ ((module) => {
"use strict";
module.exports = require("zlib");
/***/ })
/******/ });
/************************************************************************/
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ var cachedModule = __webpack_module_cache__[moduleId];
/******/ if (cachedModule !== undefined) {
/******/ return cachedModule.exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = __webpack_module_cache__[moduleId] = {
/******/ id: moduleId,
/******/ loaded: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.loaded = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = __webpack_modules__;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = __webpack_module_cache__;
/******/
/******/ // the startup function
/******/ __webpack_require__.x = () => {
/******/ // Load entry module and return exports
/******/ var __webpack_exports__ = __webpack_require__.O(undefined, [5158,9129,6127,5674,6674,439,406,7657,6434,1503,1698,1833,1071,9612,3613,8834,8100,4914,2895,794,9813,6062,6276,1327,4968,553,4273,102,3077,7017,2478,4986], () => (__webpack_require__(89923)))
/******/ __webpack_exports__ = __webpack_require__.O(__webpack_exports__);
/******/ return __webpack_exports__;
/******/ };
/******/
/************************************************************************/
/******/ /* webpack/runtime/amd options */
/******/ (() => {
/******/ __webpack_require__.amdO = {};
/******/ })();
/******/
/******/ /* webpack/runtime/chunk loaded */
/******/ (() => {
/******/ var deferred = [];
/******/ __webpack_require__.O = (result, chunkIds, fn, priority) => {
/******/ if(chunkIds) {
/******/ priority = priority || 0;
/******/ for(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];
/******/ deferred[i] = [chunkIds, fn, priority];
/******/ return;
/******/ }
/******/ var notFulfilled = Infinity;
/******/ for (var i = 0; i < deferred.length; i++) {
/******/ var [chunkIds, fn, priority] = deferred[i];
/******/ var fulfilled = true;
/******/ for (var j = 0; j < chunkIds.length; j++) {
/******/ if ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {
/******/ chunkIds.splice(j--, 1);
/******/ } else {
/******/ fulfilled = false;
/******/ if(priority < notFulfilled) notFulfilled = priority;
/******/ }
/******/ }
/******/ if(fulfilled) {
/******/ deferred.splice(i--, 1)
/******/ var r = fn();
/******/ if (r !== undefined) result = r;
/******/ }
/******/ }
/******/ return result;
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/compat get default export */
/******/ (() => {
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = (module) => {
/******/ var getter = module && module.__esModule ?
/******/ () => (module['default']) :
/******/ () => (module);
/******/ __webpack_require__.d(getter, { a: getter });
/******/ return getter;
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/define property getters */
/******/ (() => {
/******/ // define getter functions for harmony exports
/******/ __webpack_require__.d = (exports, definition) => {
/******/ for(var key in definition) {
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ }
/******/ }
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/ensure chunk */
/******/ (() => {
/******/ __webpack_require__.f = {};
/******/ // This file contains only the entry chunk.
/******/ // The chunk loading function for additional chunks
/******/ __webpack_require__.e = (chunkId) => {
/******/ return Promise.all(Object.keys(__webpack_require__.f).reduce((promises, key) => {
/******/ __webpack_require__.f[key](chunkId, promises);
/******/ return promises;
/******/ }, []));
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/get javascript chunk filename */
/******/ (() => {
/******/ // This function allow to reference async chunks and sibling chunks for the entrypoint
/******/ __webpack_require__.u = (chunkId) => {
/******/ // return url for filenames based on template
/******/ return "" + chunkId + ".bundled.js";
/******/ };
/***