truffle
Version:
Truffle - Simple development framework for Ethereum
1,448 lines (1,291 loc) • 830 kB
JavaScript
#!/usr/bin/env node
exports.id = 2478;
exports.ids = [2478];
exports.modules = {
/***/ 71861:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
const debug = __webpack_require__(15158)("deployer:ens");
const { getEnsAddress, default: ENSJS } = __webpack_require__(26143);
const contract = __webpack_require__(78883);
const { sha3 } = __webpack_require__(18269);
const { hash } = __webpack_require__(59873);
class ENS {
constructor({ provider, networkId, ens }) {
this.networkId = networkId;
this.provider = provider;
this.devRegistry = null;
// we need a reference to the ens field to update it for @truffle/contract
this.ens = ens;
}
determineENSRegistryAddress() {
if (this.ens.registryAddress) {
return this.ens.registryAddress;
} else if (this.ensjs) {
return this.ensjs.ens.address;
} else {
const message =
`Truffle could not locate the address of the ENS ` +
`registry for the network you are using. You must either be on a` +
`known network or a development blockchain.`;
throw new Error(message);
}
}
async deployNewDevENSRegistry(from) {
const ENSRegistryArtifact = __webpack_require__(56442);
const ENSRegistry = contract(ENSRegistryArtifact);
ENSRegistry.setProvider(this.provider);
const ensRegistry = await ENSRegistry.new({ from });
this.ens.registryAddress = ensRegistry.address;
this.devRegistry = ensRegistry;
this.setENSJS();
await this.deployNewDevReverseRegistrar(from);
return ensRegistry;
}
//this method should only be called when using a dev registry!
//do not call it otherwise!
async deployNewDevReverseRegistrar(from) {
const registryAddress = this.determineENSRegistryAddress();
debug("from: %s", from);
debug("registryAddress: %s", registryAddress);
const ReverseRegistrarArtifact = __webpack_require__(85574);
const ReverseRegistrar = contract(ReverseRegistrarArtifact);
ReverseRegistrar.setProvider(this.provider);
//note: the resolver address we're supposed to pass in to the constructor
//is supposed to be the "default resolver"; I'm not sure what that means,
//but I figure using the resolver for "addr.reverse" ought to suffice,
//right? So let's set up a resolver for it.
//but in order to set its resolver, we first have to set its owner.
await this.setNameOwner({ from, name: "addr.reverse" });
//now we can actually set the resolver
const { resolverAddress } = await this.ensureResolverExists({
from,
name: "addr.reverse"
});
debug("resolver set: %s", resolverAddress);
//...but wait! we need it to be owned by the registry (or 0), not by us.
//(otherwise the deployment will revert.) so, let's hand over ownership to
//the registry.
await this.updateNameOwner({
from,
newOwner: registryAddress,
name: "addr.reverse"
});
//now we can do the deployment!
const reverseRegistrar = await ReverseRegistrar.new(
registryAddress,
resolverAddress,
{
from
}
);
//except, we're not done... we need to transfer ownership from the registry
//to the reverse registrar.
//(if there were a previous reverse registrar, this would happen automatically,
//but there wasn't, so it doesn't.)
await this.updateNameOwner({
from,
newOwner: reverseRegistrar.address,
name: "addr.reverse"
});
//and we're done!
}
async ensureResolverExists({ from, name }) {
// See if the resolver is set, if not then set it
const resolverAddress = await this.ensjs.name(name).getResolver();
// names with no set resolver have 0x0 returned
if (resolverAddress !== "0x0000000000000000000000000000000000000000") {
const resolvedAddress = await this.ensjs.name(name).getAddress("ETH");
return { resolvedAddress, resolverAddress };
}
// deploy a resolver if one isn't set
const PublicResolverArtifact = __webpack_require__(32927);
const PublicResolver = contract(PublicResolverArtifact);
PublicResolver.setProvider(this.provider);
let registryAddress = this.determineENSRegistryAddress();
const publicResolver = await PublicResolver.new(registryAddress, { from });
await this.ensjs.name(name).setResolver(publicResolver.address, { from });
return { resolvedAddress: null, resolverAddress: publicResolver.address };
}
async setAddress(name, addressOrContract, { from }) {
this.validateSetAddressInputs({ addressOrContract, name, from });
const address = this.parseAddress(addressOrContract);
try {
this.setENSJS();
} catch (error) {
if (error.message.includes("error instantiating the ENS")) {
await this.deployNewDevENSRegistry(from);
this.setENSJS();
}
}
// In the case where there is a registry deployed by the user,
// set permissions so that the resolver can be set by the user
if (this.devRegistry) await this.setNameOwner({ from, name });
// Find the owner of the name and compare it to the "from" field
const nameOwner = await this.ensjs.name(name).getOwner();
if (nameOwner !== from) {
const message =
`The default address or address provided in the "from" ` +
`field for registering does not own the specified ENS name. The ` +
`"from" field address must match the owner of the name.` +
`\n> Failed to register ENS name ${name}` +
`\n> Address in "from" field - ${from}` +
`\n> Current owner of '${name}' - ${nameOwner}`;
throw new Error(message);
}
const { resolvedAddress } = await this.ensureResolverExists({ from, name });
// If the resolver points to a different address or is not set,
// then set it to the specified address
if (resolvedAddress !== address) {
await this.ensjs.name(name).setAddress("ETH", address);
}
}
async setNameOwner({ name, from }) {
const nameLabels = name.split(".").reverse();
// Set top-level name
let builtName = nameLabels[0];
await this.devRegistry.setSubnodeOwner("0x0", sha3(builtName), from, {
from
});
// If name is only one label, stop here
if (nameLabels.length === 1) return;
for (const label of nameLabels.slice(1)) {
await this.devRegistry.setSubnodeOwner(
hash(builtName),
sha3(label),
from,
{ from }
);
builtName = label.concat(`.${builtName}`);
}
}
//this method assumes that from owns the parent!
//it won't work otherwise!
async updateNameOwner({ name, from, newOwner }) {
//this method does *not* walk the tree.
//it only updates this individual entry.
let label, suffix;
const dotIndex = name.indexOf("."); //find the first dot
if (dotIndex !== -1) {
label = name.slice(0, dotIndex); //everything before the dot
suffix = name.slice(dotIndex + 1); //everything after the dot
} else {
label = name;
suffix = "";
}
await this.devRegistry.setSubnodeOwner(
suffix !== "" ? hash(suffix) : "0x0",
sha3(label),
newOwner,
{ from }
);
}
parseAddress(addressOrContract) {
if (typeof addressOrContract === "string") return addressOrContract;
try {
return addressOrContract.address;
} catch (error) {
const message =
`You have not entered a valid address or contract ` +
`object with an address property. Please ensure that you enter a ` +
`valid address or pass in a valid artifact.`;
throw new Error(message);
}
}
validateSetAddressInputs({ addressOrContract, name, from }) {
if (
!addressOrContract ||
!name ||
!from ||
(typeof addressOrContract !== "string" &&
typeof addressOrContract !== "object") ||
typeof name !== "string" ||
typeof from !== "string"
) {
const message =
`The 'address', 'name', or 'from' parameter is invalid for ` +
`the call to the setAddress function. Please ensure that you are ` +
`passing valid values. The received input values were the ` +
`following:\n - address: ${addressOrContract}\n - name: ${name}\n - from: ` +
`${from}\n`;
throw new Error(message);
}
}
setENSJS() {
let ensAddress;
try {
ensAddress = this.ens.registryAddress || getEnsAddress(this.networkId);
this.ensjs = new ENSJS({
provider: this.provider,
ensAddress
});
} catch (error) {
const message =
`There was an error instantiating the ENS library. ` +
`Please ensure you have the correct ENS registry address. Truffle` +
`is currently using ${ensAddress}.`;
throw new Error(`${message} - ${error.message}`);
}
}
}
module.exports = ENS;
/***/ }),
/***/ 669:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
const expect = __webpack_require__(14096);
const DeferredChain = __webpack_require__(17162);
const Deployment = __webpack_require__(91432);
const link = __webpack_require__(13690);
const create = __webpack_require__(63218);
const ENS = __webpack_require__(71861);
class Deployer extends Deployment {
constructor(options) {
expect.options(options, ["provider", "networks", "network", "network_id"]);
super(options);
this.options = options;
this.chain = new DeferredChain();
this.network = options.network;
this.networks = options.networks;
this.network_id = options.network_id;
this.provider = options.provider;
this.known_contracts = {};
if (options.ens && options.ens.enabled) {
//HACK: use getter to get what we want and put it where we want
options.ens.registryAddress = options.ensRegistry.address;
this.ens = new ENS({
provider: options.provider,
networkId: options.network_id,
ens: options.ens
});
}
(options.contracts || []).forEach(
contract => (this.known_contracts[contract.contract_name] = contract)
);
}
// Note: In all code below we overwrite this.chain every time .then() is used
// in order to ensure proper error processing.
start() {
return this.chain.start();
}
link(library, destinations) {
return this.queueOrExec(link(library, destinations, this));
}
deploy() {
const args = Array.prototype.slice.call(arguments);
const contract = args.shift();
return this.queueOrExec(this.executeDeployment(contract, args, this));
}
new() {
const args = Array.prototype.slice.call(arguments);
const contract = args.shift();
return this.queueOrExec(create(contract, args, this));
}
then(fn) {
return this.queueOrExec(function () {
return fn(this);
});
}
queueOrExec(fn) {
return this.chain.started == true
? new Promise(accept => accept()).then(fn)
: this.chain.then(fn);
}
finish() {
this.close();
}
}
module.exports = Deployer;
/***/ }),
/***/ 13690:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
var Linker = __webpack_require__(6227);
module.exports = function(library, destinations, deployer) {
return async function() {
await Linker.link(library, destinations, deployer);
};
};
/***/ }),
/***/ 63218:
/***/ ((module) => {
module.exports = function (contract, args, deployer) {
return async function () {
if (deployer.options.events) {
await deployer.options.events.emit("deployment:newContract", {
contract
});
}
return contract.new.apply(contract, args);
};
};
/***/ }),
/***/ 17162:
/***/ ((module) => {
function DeferredChain() {
var self = this;
this.chain = new Promise(function (accept, reject) {
self._accept = accept;
self._reject = reject;
});
this.await = new Promise(function () {
self._done = arguments[0];
self._error = arguments[1];
});
this.started = false;
}
DeferredChain.prototype.then = function (fn) {
var self = this;
this.chain = this.chain.then(function () {
var args = Array.prototype.slice.call(arguments);
return fn.apply(null, args);
});
this.chain = this.chain.catch(function (e) {
self._error(e);
throw e;
});
return this;
};
DeferredChain.prototype.catch = function (fn) {
this.chain = this.chain.catch(function () {
var args = Array.prototype.slice.call(arguments);
return fn.apply(null, args);
});
return this;
};
DeferredChain.prototype.start = function () {
this.started = true;
this.chain = this.chain.then(this._done);
this._accept();
return this.await;
};
module.exports = DeferredChain;
/***/ }),
/***/ 91432:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
const debug = __webpack_require__(15158)("deployer:deployment"); // eslint-disable-line no-unused-vars
const sanitizeMessage = __webpack_require__(84331);
/**
* @class Deployment
*/
class Deployment {
/**
* constructor
* @param {Number} confirmations confirmations needed to resolve an instance
*/
constructor(options) {
const networkConfig = options.networks[options.network] || {};
this.confirmations = options.confirmations || 0;
this.timeoutBlocks = options.timeoutBlocks || 0;
this.pollingInterval = networkConfig.deploymentPollingInterval || 4000;
this.promiEventEmitters = [];
this.confirmationsMap = {};
this.blockPoll;
this.options = options;
}
async emit(name, data) {
if (this.options && this.options.events) {
return await this.options.events.emit(name, data);
}
}
/**
* Helper to parse a deploy statement's overwrite option
* @private
* @param {Array} args arguments passed to deploy
* @param {Boolean} isDeployed is contract deployed?
* @return {Boolean} true if overwrite is ok
*/
_canOverwrite(args, isDeployed) {
const lastArg = args[args.length - 1];
const isObject = typeof lastArg === "object";
const overwrite = isObject && isDeployed && lastArg.overwrite === false;
return !overwrite;
}
/**
* Gets arbitrary values from constructor params, if they exist.
* @private
* @param {Array} args constructor params
* @return {Any|Undefined} gas value
*/
_extractFromArgs(args, key) {
let value;
args.forEach(arg => {
const hasKey =
!Array.isArray(arg) &&
typeof arg === "object" &&
Object.keys(arg).includes(key);
if (hasKey) value = arg[key];
});
return value;
}
/**
* Emits a `block` event on each new block heard. This polling is
* meant to be cancelled immediately on resolution of the
* contract instance or on error. (See stopBlockPolling)
* @private
* @param {Object} interfaceAdapter
*/
async _startBlockPolling(interfaceAdapter) {
const self = this;
const startTime = new Date().getTime();
let secondsWaited = 0;
let blocksWaited = 0;
let currentBlock = await interfaceAdapter.getBlockNumber();
self.blockPoll = setInterval(async () => {
const newBlock = await interfaceAdapter.getBlockNumber();
blocksWaited = newBlock - currentBlock + blocksWaited;
currentBlock = newBlock;
secondsWaited = Math.floor((new Date().getTime() - startTime) / 1000);
const data = {
blockNumber: newBlock,
blocksWaited: blocksWaited,
secondsWaited: secondsWaited
};
await self.emit("deployment:block", data);
}, self.pollingInterval);
}
/**
* Clears the interval timer initiated by `startBlockPolling
* @private
*/
_stopBlockPolling() {
clearInterval(this.blockPoll);
}
/**
* Waits `n` blocks after a tx is mined, firing a pseudo
* 'confirmation' event for each one.
* @private
* @param {Number} blocksToWait
* @param {Object} receipt
* @param {Object} interfaceAdapter
* @return {Promise} Resolves after `blockToWait` blocks
*/
async _waitBlocks(blocksToWait, state, interfaceAdapter) {
const self = this;
let currentBlock = await interfaceAdapter.getBlockNumber();
return new Promise(accept => {
let blocksHeard = 0;
const poll = setInterval(async () => {
const newBlock = await interfaceAdapter.getBlockNumber();
if (newBlock > currentBlock) {
blocksHeard = newBlock - currentBlock + blocksHeard;
currentBlock = newBlock;
const data = {
contractName: state.contractName,
receipt: state.receipt,
num: blocksHeard,
block: currentBlock
};
await self.emit("deployment:confirmation", data);
}
if (blocksHeard >= blocksToWait) {
clearInterval(poll);
accept();
}
}, self.pollingInterval);
});
}
/**
* Sanity checks catch-all:
* Are we connected?
* Is contract deployable?
* @private
* @param {Object} contract TruffleContract
* @return {Promise} throws on error
*/
async _preFlightCheck(contract) {
// Check that contract is not array
if (Array.isArray(contract)) {
const data = {
type: "noBatches",
contract
};
const message = await this.emit("deployment:error", data);
throw new Error(sanitizeMessage(message));
}
// Check bytecode
if (contract.bytecode === "0x") {
const data = {
type: "noBytecode",
contract
};
const message = await this.emit("deployment:error", data);
throw new Error(sanitizeMessage(message));
}
// Check network
await contract.detectNetwork();
}
// ----------------- Confirmations Handling (temporarily disabled) -------------------------------
/**
* There are outstanding issues at both geth (with websockets) & web3 (with confirmation handling
@@ -247,27 +221,6 @@ class Deployment {
});
}
/**
* Handler for contract's `confirmation` event. Rebroadcasts as a deployer event
* and maintains a table of txHashes & their current confirmation number. This
* table gets polled if the user needs to wait a few blocks before getting
* an instance back.
* @private
* @param {Object} parent Deployment instance. Local `this` belongs to promievent
* @param {Number} num Confirmation number
* @param {Object} receipt transaction receipt
*/
async _confirmationCb(parent, state, num, receipt) {
const eventArgs = {
contractName: state.contractName,
num: num,
receipt: receipt
};
parent.confirmationsMap[receipt.transactionHash] = num;
await parent.emitter.emit("confirmation", eventArgs);
}
// ----------------- Confirmations Handling (temporarily disabled) -------------------------------
/**
* There are outstanding issues at both geth (with websockets) & web3 (with confirmation handling
* over RPC) that impair the confirmations handlers' reliability. In the interim we're using
* simple block polling instead. (See also _confirmationCb )
*
* Queries the confirmations mapping periodically to see if we have
* heard enough confirmations for a given tx to allow `deploy` to complete.
* Resolves when this is true.
*
* @private
* @param {String} hash contract creation tx hash
* @return {Promise}
*/
async _waitForConfirmations(hash) {
let interval;
const self = this;
return new Promise(accept => {
interval = setInterval(() => {
if (self.confirmationsMap[hash] >= self.confirmations) {
clearInterval(interval);
accept();
}
}, self.pollingInterval);
});
}
// ------------------------------------ Methods --------------------------------------------------
/**
*
* @param {Object} contract Contract abstraction
* @param {Array} args Constructor arguments
* @return {Promise} Resolves an instance
*/
executeDeployment(contract, args) {
const self = this;
return async function () {
await self._preFlightCheck(contract);
let instance;
let eventArgs;
let shouldDeploy = true;
let state = {
contractName: contract.contractName
};
const isDeployed = contract.isDeployed();
const newArgs = await Promise.all(args);
const currentBlock = await contract.interfaceAdapter.getBlock("latest");
// Last arg can be an object that tells us not to overwrite.
if (newArgs.length > 0) {
shouldDeploy = self._canOverwrite(newArgs, isDeployed);
}
// Case: deploy:
if (shouldDeploy) {
/*
Set timeout override. If this value is zero,
@truffle/contract will defer to web3's defaults:
- 50 blocks (websockets) OR 50 * 15sec (http)
*/
contract.timeoutBlocks = self.timeoutBlocks;
eventArgs = {
state: state,
contract: contract,
deployed: isDeployed,
blockLimit: currentBlock.gasLimit,
gas: self._extractFromArgs(newArgs, "gas") || contract.defaults().gas,
gasPrice:
self._extractFromArgs(newArgs, "gasPrice") ||
contract.defaults().gasPrice,
from:
self._extractFromArgs(newArgs, "from") || contract.defaults().from
};
// Get an estimate for previews / detect constructor revert
// NB: web3 does not strip the revert msg here like it does for `deploy`
try {
eventArgs.estimate = await contract.new.estimateGas.apply(
contract,
newArgs
);
} catch (err) {
eventArgs.estimateError = err;
}
// Emit `deployment:start` & send transaction
await self.emit("deployment:start", eventArgs);
const promiEvent = contract.new.apply(contract, newArgs);
// Track emitters for cleanup on exit
self.promiEventEmitters.push(promiEvent);
// Subscribe to contract events / rebroadcast them to any reporters
promiEvent
.on("transactionHash", async hash => {
const data = {
contractName: state.contractName,
transactionHash: hash
};
await self.emit("deployment:txHash", data);
})
.on("receipt", receipt => {
// We want this receipt available for the post-deploy event
// so gas reporting is at hand there.
state.receipt = receipt;
});
await self._startBlockPolling(contract.interfaceAdapter);
// Get instance (or error)
try {
instance = await promiEvent;
self._stopBlockPolling();
} catch (err) {
self._stopBlockPolling();
eventArgs.error = err.error || err;
const message = await self.emit("deployment:failed", eventArgs);
self.close();
throw new Error(sanitizeMessage(message));
}
// Case: already deployed
} else {
instance = await contract.deployed();
}
// Emit `postDeploy`
eventArgs = {
contract: contract,
instance: instance,
deployed: shouldDeploy,
receipt: state.receipt
};
await self.emit("deployment:succeed", eventArgs);
// Wait for `n` blocks
if (self.confirmations !== 0 && shouldDeploy) {
await self._waitBlocks(
self.confirmations,
state,
contract.interfaceAdapter
);
}
// Finish: Ensure the address and tx-hash are set on the contract.
contract.address = instance.address;
contract.transactionHash = instance.transactionHash;
return instance;
};
}
/**
* Cleans up promiEvents' emitter listeners
*/
close() {
this.promiEventEmitters.forEach(item => {
item.removeAllListeners();
});
}
}
module.exports = Deployment;
/***/ }),
/***/ 6227:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
const sanitizeMessage = __webpack_require__(84331);
module.exports = {
link: async function (library, destinations, deployer) {
let eventArgs;
let libraryName = library.contractName;
if (libraryName == null && library.constructor) {
//allow for the possibility that library is an instance rather
//than a class
libraryName = library.constructor.contractName;
}
// Validate name (it might still be undefined)
if (libraryName == null) {
eventArgs = {
type: "noLibName"
};
let message;
if (deployer.options && deployer.options.events) {
message = await deployer.options.events.emit(
"deployment:error",
eventArgs
);
}
throw new Error(sanitizeMessage(message));
}
// Validate address: don't want to use .address directly because it will throw.
let hasAddress;
typeof library.isDeployed === "function"
? (hasAddress = library.isDeployed())
: (hasAddress = library.address != null);
if (!hasAddress) {
eventArgs = {
type: "noLibAddress",
contract: library
};
let message;
if (deployer.options && deployer.options.events) {
message = await deployer.options.events.emit(
"deployment:error",
eventArgs
);
}
throw new Error(sanitizeMessage(message));
}
// Link all destinations
if (!Array.isArray(destinations)) {
destinations = [destinations];
}
for (let destination of destinations) {
// Don't link if result will have no effect.
const alreadyLinked = destination.links[libraryName] === library.address;
const noLinkage = !destination.unlinked_binary.includes(libraryName);
if (alreadyLinked || noLinkage) continue;
eventArgs = {
libraryName,
libraryAddress: library.address,
contractName: destination.contractName,
contractAddress: destination.contractAddress
};
if (deployer.options && deployer.options.events) {
await deployer.options.events.emit("deployment:linking", eventArgs);
}
destination.link(library);
}
}
};
/***/ }),
/***/ 84331:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
const debug = __webpack_require__(15158)("deployer:sanitizeMessage");
module.exports = message => {
if (Array.isArray(message)) {
// for some reason, message is returned as an array padded with many
// empty arrays - should investigate this further later
debug("processing the following message - %o", message);
return message[0];
}
return message;
};
/***/ }),
/***/ 83474:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.Migration = void 0;
const path = __importStar(__webpack_require__(71017));
const deployer_1 = __importDefault(__webpack_require__(669));
const Require = __importStar(__webpack_require__(35422));
const interface_adapter_1 = __webpack_require__(36339);
const ResolverIntercept_1 = __webpack_require__(40960);
const db_loader_1 = __webpack_require__(70972);
const emitEvent_1 = __webpack_require__(92931);
class Migration {
constructor(file, config) {
this.file = path.resolve(file);
this.number = parseInt(path.basename(file));
this.isFirst = false;
this.isLast = false;
this.dryRun = config.dryRun;
this.interactive = config.interactive;
this.config = config;
}
// ------------------------------------- Private -------------------------------------------------
/**
* Loads & validates migration, then runs it.
* @param {Object} options config and command-line
* @param {Object} context web3 & interfaceAdapter
* @param {Object} deployer truffle module
* @param {Object} resolver truffle module
*/
_load(options, context, deployer, resolver) {
return __awaiter(this, void 0, void 0, function* () {
// Load assets and run `execute`
const accounts = yield context.interfaceAdapter.getAccounts();
const requireOptions = {
file: this.file,
context: context,
resolver: resolver,
args: [deployer]
};
// in the above options, resolver is actually an instance of
// ResolverIntercept - adding that type to @truffle/require causes a
// circular dependency - for now we'll just do a ts-ignore
// @ts-ignore
const fn = Require.file(requireOptions);
const unRunnable = !fn || !fn.length || fn.length == 0;
if (unRunnable) {
const msg = `Migration ${this.file} invalid or does not take any parameters`;
throw new Error(msg);
}
// `migrateFn` might be sync or async. We negotiate that difference in
// `execute` through the deployer API.
const migrateFn = fn(deployer, options.network, accounts);
yield this._deploy(options, context, deployer, resolver, migrateFn);
});
}
/**
* Initiates deployer sequence, then manages migrations info
* publication to chain / artifact saving.
* @param {Object} options config and command-line
* @param {Object} context web3 & interfaceAdapter
* @param {Object} deployer truffle module
* @param {Object} resolver truffle module
* @param {[type]} migrateFn module.exports of a migrations.js
*/
_deploy(options, context, deployer, resolver, migrateFn) {
return __awaiter(this, void 0, void 0, function* () {
try {
yield deployer.start();
// Allow migrations method to be async and
// deploy to use await
if (migrateFn && migrateFn.then !== undefined) {
// @ts-ignore
yield deployer.then(() => migrateFn);
}
// Migrate without saving
if (options.save === false)
return;
let Migrations;
// Attempt to write migrations record to chain
try {
Migrations = resolver.require("Migrations");
}
catch (error) {
// do nothing, Migrations contract optional
}
if (Migrations && Migrations.isDeployed()) {
const message = `Saving migration to chain.`;
if (!this.dryRun) {
const data = { message: message };
yield (0, emitEvent_1.emitEvent)(options, "migrate:settingCompletedMigrations:start", data);
}
const migrations = yield Migrations.deployed();
const receipt = yield migrations.setCompleted(this.number);
if (!this.dryRun) {
const data = { receipt: receipt, message: message };
yield (0, emitEvent_1.emitEvent)(options, "migrate:settingCompletedMigrations:succeed", data);
}
}
const eventArgs = {
isLast: this.isLast,
interfaceAdapter: context.interfaceAdapter
};
yield (0, emitEvent_1.emitEvent)(options, "migrate:migration:succeed", eventArgs);
let artifacts = resolver
.contracts()
.map((abstraction) => abstraction._json);
if (this.config.db && this.config.db.enabled && artifacts.length > 0) {
// currently if Truffle Db fails to load, getTruffleDb returns `null`
const Db = (0, db_loader_1.getTruffleDb)();
if (Db) {
const db = Db.connect(this.config.db);
const project = yield Db.Project.initialize({
db,
project: {
directory: this.config.working_directory
}
});
const result = yield project
.connect({ provider: this.config.provider })
.loadMigrate({
network: {
name: this.config.network
},
artifacts
});
({ artifacts } = result);
yield project.assignNames({
assignments: {
networks: [result.network]
}
});
}
}
// Save artifacts to local filesystem
yield options.artifactor.saveAll(artifacts);
deployer.finish();
// Cleanup
if (this.isLast) {
// Exiting w provider-engine appears to be hopeless. This hack on
// our fork just swallows errors from eth-block-tracking
// as we unwind the handlers downstream from here.
if (this.config.provider && this.config.provider.engine) {
this.config.provider.engine.silent = true;
}
}
}
catch (error) {
const errorData = {
type: "migrateErr",
error: error
};
yield (0, emitEvent_1.emitEvent)(options, "migrate:migration:error", errorData);
deployer.finish();
throw error;
}
});
}
// ------------------------------------- Public -------------------------------------------------
/**
* Instantiates a deployer, connects this migration and its deployer to the reporter
* and launches a migration file's deployment sequence
* @param {Object} options config and command-line
*/
run(options) {
return __awaiter(this, void 0, void 0, function* () {
const { interfaceAdapter, resolver, context, deployer } = this.prepareForMigrations(options);
// Get file path and emit pre-migration event
const file = path.relative(options.migrations_directory, this.file);
const block = yield interfaceAdapter.getBlock("latest");
const preMigrationsData = {
file: file,
number: this.number,
isFirst: this.isFirst,
network: options.network,
networkId: options.network_id,
blockLimit: block.gasLimit
};
yield (0, emitEvent_1.emitEvent)(options, "migrate:migration:start", preMigrationsData);
yield this._load(options, context, deployer, resolver);
});
}
prepareForMigrations(options) {
const interfaceAdapter = (0, interface_adapter_1.createInterfaceAdapter)({
provider: options.provider,
networkType: options.networks[options.network].type
});
const web3 = new interface_adapter_1.Web3Shim({
provider: options.provider,
networkType: options.networks[options.network].type
});
const resolver = new ResolverIntercept_1.ResolverIntercept(options.resolver);
// Initial context.
const context = { web3, interfaceAdapter, config: this.config };
const deployer = new deployer_1.default(options);
return { interfaceAdapter, resolver, context, deployer };
}
serializeable() {
return {
file: this.file,
number: this.number,
isFirst: this.isFirst,
isLast: this.isLast,
dryRun: this.dryRun,
interactive: this.interactive
};
}
}
exports.Migration = Migration;
//# sourceMappingURL=Migration.js.map
/***/ }),
/***/ 40960:
/***/ ((__unused_webpack_module, exports) => {
"use strict";
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.ResolverIntercept = void 0;
class ResolverIntercept {
constructor(resolver) {
this.resolver = resolver;
this.cache = [];
}
require(contractName) {
// remove file extension if present on name
const sanitizedContractName = contractName
.replace(/^\.\//, "")
.replace(/\.sol$/i, "");
// there may be more than one contract of the same name which will be
// problematic - only return the first one found in the cache for now
for (const contract of this.cache) {
// @ts-ignore
if (contract.contract_name === sanitizedContractName) {
return contract;
}
}
// Note, will error if nothing is found.
const resolved = this.resolver.require(sanitizedContractName);
this.cache.push(resolved);
return resolved;
}
contracts() {
return this.cache;
}
}
exports.ResolverIntercept = ResolverIntercept;
//# sourceMappingURL=ResolverIntercept.js.map
/***/ }),
/***/ 92931:
/***/ (function(__unused_webpack_module, exports) {
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.emitEvent = void 0;
const emitEvent = (options, name, data) => __awaiter(void 0, void 0, void 0, function* () {
if (options.events) {
return yield options.events.emit(name, data);
}
});
exports.emitEvent = emitEvent;
//# sourceMappingURL=emitEvent.js.map
/***/ }),
/***/ 22478:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.ResolverIntercept = void 0;
const fs_1 = __importDefault(__webpack_require__(57147));
const path = __importStar(__webpack_require__(71017));
const glob_1 = __importDefault(__webpack_require__(12884));
const expect = __importStar(__webpack_require__(14096));
const config_1 = __importDefault(__webpack_require__(20553));
const Migration_1 = __webpack_require__(83474);
const emitEvent_1 = __webpack_require__(92931);
const inquirer_1 = __importDefault(__webpack_require__(96062));
var ResolverIntercept_1 = __webpack_require__(40960);
Object.defineProperty(exports, "ResolverIntercept", ({ enumerable: true, get: function () { return ResolverIntercept_1.ResolverIntercept; } }));
/**
* This API is consumed by `@truffle/core` at the `migrate` and `test` commands via
* the `.runMigrations` method.
*/
exports["default"] = {
Migration: Migration_1.Migration,
logger: null,
promptToAcceptDryRun: function (options) {
return __awaiter(this, void 0, void 0, function* () {
const prompt = [
{
type: "confirm",
name: "proceed",
message: `Dry-run successful. Do you want to proceed with real deployment? >> (y/n): `,
default: false
}
];
const answer = yield inquirer_1.default.prompt(prompt);
if (answer.proceed) {
return true;
}
if (options) {
yield (0, emitEvent_1.emitEvent)(options, "migrate:dryRun:notAccepted");
}
return false;
});
},
assemble: function (options) {
const config = config_1.default.detect(options);
if (!fs_1.default.existsSync(config.migrations_directory) ||
!(fs_1.default.readdirSync(config.migrations_directory).length > 0)) {
return [];
}
const migrationsDir = config.migrations_directory;
const directoryContents = glob_1.default.sync(`${migrationsDir}${path.sep}*`);
const files = directoryContents.filter(item => fs_1.default.statSync(item).isFile());
if (files.length === 0)
return [];
let migrations = files
.filter(file => isNaN(parseInt(path.basename(file))) === false)
.filter(file => path.extname(file).match(config.migrations_file_extension_regexp) !=
null)
.map(file => new Migration_1.Migration(file, config));
// Make sure to sort the prefixes as numbers and not strings.
migrations = migrations.sort((a, b) => {
if (a.number > b.number)
return 1;
if (a.number < b.number)
return -1;
return 0;
});
return migrations;
},
run: function (options) {
return __awaiter(this, void 0, void 0, function* () {
expect.options(options, [
"working_directory",
"migrations_directory",
"contracts_build_directory",
"provider",
"artifactor",
"resolver",
"network",
"network_id",
"logger",
"from" // address doing deployment
]);
if (options.reset === true) {
yield this.runAll(options);
return;
}
const lastMigration = yield this.lastCompletedMigration(options);
// Don't rerun the last completed migration.
yield this.runFrom(lastMigration + 1, options);
});
},
runFrom: function (number, options) {
return __awaiter(this, void 0, void 0, function* () {
let migrations = this.assemble(options);
while (migrations.length > 0) {
if (migrations[0].number >= number)
break;
migrations.shift();
}
if (options.to) {
migrations = migrations.filter(migration => migration.number <= options.to);
}
return yield this.runMigrations(migrations, options);
});
},
runAll: function (options) {
return __awaiter(this, void 0, void 0, function* () {
return yield this.runFrom(0, options);
});
},
runMigrations: function (migrations, options) {
return __awaiter(this, void 0, void 0, function* () {
// Perform a shallow clone of the options object
// so that we can override the provider option without
// changing the original options object passed in.
const clone = {};
Object.keys(options).forEach(key => (clone[key] = options[key]));
if (options.quiet)
clone.logger = { log: function () { } };
clone.resolver = this.wrapResolver(options.resolver, clone.provider);
// Make migrations aware of their position in sequence
const total = migrations.length;
if (total) {
migrations[0].isFirst = true;
migrations[total - 1].isLast = true;
}
yield (0, emitEvent_1.emitEvent)(options, "migrate:runMigrations:start", {
migrations,
dryRun: options.dryRun
});
try {
// @ts-ignore
global.artifacts = clone.resolver;
// @ts-ignore
global.config = clone;
for (const migration of migrations) {
yield migration.run(clone);
}
yield (0, emitEvent_1.emitEvent)(options, "migrate:runMigrations:finish", {
dryRun: options.dryRun,
error: null
});
return;
}
catch (error) {
yield (0, emitEvent_1.emitEvent)(options, "migrate:runMigrations:finish", {
dryRun: options.dryRun,
error: error.toString()
});
throw error;
}
finally {
// @ts-ignore
delete global.artifacts;
// @ts-ignore
delete global.config;
}
});
},
wrapResolver: function (resolver, provider) {
return {
require: function (import_path, search_path) {
const abstraction = resolver.require(import_path, search_path);
abstraction.setProvider(provider);
return abstraction;
},
resolve: resolver.resolve
};
},
lastCompletedMigration: function (options) {
return __awaiter(this, void 0, void 0, function* () {
let Migrations; // I don't think we have a good type for this yet
try {
Migrations = options.resolver.require("Migrations");
}
catch (error) {
// don't throw, Migrations contract optional
return 0;
}
if (Migrations.isDeployed() === false)
return 0;
const migrationsOnChain = (migrationsAddress) => __awaiter(this, void 0, void 0, function* () {
return ((yield Migrations.interfaceAdapter.getCode(migrationsAddress)) !== "0x");
});
// Two possible Migrations.sol's (lintable/unlintable)