When migrating more than one contract the following works:
deployer.deploy(contractA);
deployer.deploy(contractB);
but if the second contract needs information from the first contract to be deployed, then this:
await deployer.deploy(contractA);
const instanceA = await contractA.deployed();
const value = await instanceA.getValue();
deployer.deploy(contractB, value);
does not work. Only contractA is deployed to the network and truffle migrate ends after showing contractB's address and does not say "Saving successful migration to network..."
This is true even in the simplified example of:
await deployer.deploy(contractA);
deployer.deploy(contractB);
The use of .then() or deployer.then() results in the same behavior - only the first contract is saved to the network.
deployer.deploy(contractA).then( ()=>{ deployer.deploy(contractB); });
deployer.deploy(contractA);
deployer.then( ()=> deployer.deploy(contractB); );
In all cases, truffle migrate says Deploying contractB and provides contractB: <contractB address> but it does not say Saving successful migration to network...
Running truffle 3.4.11, node 7.10.1, and TestRPC 4.1.3 and simple contractA in contracts/contractA.sol and contractB in contracts/contractB.sol with migrations/2_deploy_contracts.js containing:
````
var contractA = artifacts.require("../contracts/contractA.sol");
var contractB = artifacts.require("../contracts/contractB.sol");
module.exports = async function(deployer, network, accounts) {
await deployer.deploy(contractA);
deployer.deploy(contractB);
}
contractA will be deployed on the network while contractB will not. (Obviously, this is not the use case, this is the simplest replication. The use case would be something closer to:
var contractA = artifacts.require("../contracts/contractA.sol");
var contractB = artifacts.require("../contracts/contractB.sol");
module.exports = async function(deployer, network, accounts) {
const addr = accounts[0];
await deployer.deploy(contractA, addr);
const instance = await contractA.deployed();
const value = await instance.getValue();
console.log('DEBUG:', value); // provides an expected value
deployer.deploy(contractB, value);
}
````
Both contracts should be on the network.
truffle network shows only the first contract. Using truffle console and trying to access contractB.deployed() results in a message that the contract is not deployed on the network.
You need to return deployer.deploy(...) from inside .then(() => {...})
For me it works with
deployer.deploy(contractA).then( ()=> deployer.deploy(contractB) );
or
deployer.then( ()=> {
...
return deployer.deploy(contractB);
);
async...await and any Promise.* don't work as per #501
I will give it a try and report back (probably in a couple days when I can return to my project).
This is still an issue in 4.0.1 only .then and Promise chaining seems to work
Tried every possible combination, async + await, then() and async+await+then(), it doesn't work. In fact it always save Artifacts before deploying second contract, that's why you do not see address of the second contract. In my case I see address of the second contract after saving artifacts:
Running step...
Deploying SampleCampaign...
... 0x68e6e16d86617689f9522e6dc9b56e0e9f66c7400e7c101fd3e0afaf5ffe8ca4
Saving artifacts...
... 0xdc7a4c7cdc7634c1b68fa254f863b2d54edbb475100f52fe87f084c63dcbd95d
SampleCampaign: 0xad89528ffe22aa057cfbec6c9ccf2367a638eb79
So if I run truffle console and then in console:
SampleCampaign.deployed()
I get:
SampleCampaign has not been deployed to detected network (network/artifact mismatch)
at /usr/lib/node_modules/truffle/build/cli.bundled.js:318327:17
at
at process._tickDomainCallback (internal/process/next_tick.js:228:7)
But if I check address "0xad89528ffe22aa057cfbec6c9ccf2367a638eb79" I see that contract is there:
SampleCampaign.at("0xad89528ffe22aa057cfbec6c9ccf2367a638eb79")
This issue seems to be a duplicate of https://github.com/trufflesuite/truffle/issues/501.
@ismaelbej Thank you for noting this, closing here in favor of #501..
@dzentota @mhchu
The deployer stages deployments rather than running them at the execution time of the migration function. It's possible to use async/await within its context but ultimately you also have to follow the deployer's interface by returning a promise to its .then property. More guidance on this at the other issue here
I saw #501 before and some similar. But approach mentioned in #501 doesn't work, output is the same
@dzentota Could you share the code from your migrations that's not working?
Hi, unfortunately I don't have all the variants I've tried. Here is an example with then()
var Crowdsale = artifacts.require("./Crowdsale.sol");
var SampleCampaign = artifacts.require('./SampleCampaign.sol');
module.exports = function (deployer) {
Crowdsale.deployed().then(function (_) {
console.log(Crowdsale.address);
return _.token.call();
}).then(function(tokenAddress) {
let crowdsaleAddress = Crowdsale.address;
let minContribution = 1000000000000000000;
let maxContribution = 10000000000000000000;
let softCap = 5000000000000000000;
let hardCap = 100000000000000000000;
let startTime = Math.floor(Date.now() / 1000);
let endTime = Math.floor(Date.now() / 1000) + 100000;
let fee = 1;
let bountyFee = 1;
deployer.deploy(
SampleCampaign,
crowdsaleAddress,
tokenAddress,
minContribution,
maxContribution,
softCap,
hardCap,
startTime,
endTime,
fee,
bountyFee
);
})
}
Output:
migrate -f 4
Using network 'develop'.
Running migration: 4_deploy_campaign.js
Saving successful migration to network...
Replacing SampleCampaign...
... 0x87e580340a0fdff84559a1bb014f08f281476024af9f32a8036e4743f19f9f2d
Saving artifacts...
truffle(develop)> ... 0x2606dfbc10b81afaa9d780e64c1612cea03e27dea943b48b2f3c40b4d03b3856
SampleCampaign: 0xbaaa2a3237035a2c7fa2a33c76b44a8c6fe18e87
undefined
Actually, I see all this text except undefined. Undefined appears after I hit enter (otherwise it hangs)
@dzentota The example @Velenir gives in this issue above is the model you should follow. If you want to run async logic in the migrations you must return it as a promise to the deployer method. In your case,
module.exports = function (deployer) {
deployer.then( function() {
return Crowdsale.deployed() .... etc ...
);
Additionally make sure you return everything async in the promise chain. For example the deployer.deploy in your final clause should also be prefaced with a return.
Thanks @cgewecke now it works!!!
Additionally make sure you return everything async in the promise chain
@dzentota @cgewecke yes, this part is key in a way I can't quite understand yet. Is this because the main deployment function "knows to wait" for the promise chain to finish executing when it depends on its return value?
Is the value returned from the deployment function actually used by truffle in any way...?
Most helpful comment
You need to return
deployer.deploy(...)from inside.then(() => {...})For me it works with
or
async...awaitand anyPromise.*don't work as per #501