I am able to reproduce issue that you were facing. I did following to solve this issue.
Created two separate contract files inside contracts folder for SimpleStore and ContrctFactory as following :-
SimpleStore.sol file -
pragma solidity ^0.4.16;
contract SimpleStore {
uint public value;
function SimpleStore (uint num) public {
value = num;
}
function setValue (uint num) public {
value = num;
}
}
ContractFactory.sol file -
pragma solidity ^0.4.16;
contract SimpleStore {
uint public value;
function SimpleStore (uint num) public {
value = num;
}
function setValue (uint num) public {
value = num;
}
}
contract ContractFactory {
address public store;
function ContractFactory () public {
}
function createStore () public {
store = new SimpleStore(12);
}
}
2_deploy_contracts.js file -
var SimpleStore = artifacts.require("./SimpleStore.sol");
var ContractFactory = artifacts.require("./ContractFactory.sol");
module.exports = function(deployer) {
deployer.deploy(SimpleStore,10, {gas: 6700000});
deployer.deploy(ContractFactory,{gas: 6700000});
};
app.js file -
import { default as Web3} from 'web3';
import { default as contract } from 'truffle-contract'
import SimpleStore_artifacts from '../../build/contracts/SimpleStore.json'
import ContractFactory_artifacts from '../../build/contracts/ContractFactory.json'
var SimpleStore = contract(SimpleStore_artifacts);
var ContractFactory = contract(ContractFactory_artifacts);
$( document ).ready(function() {
if (typeof web3 !== 'undefined') {
console.warn("Using web3 detected from external source like Metamask")
// Use Mist/MetaMask's provider
window.web3 = new Web3(web3.currentProvider);
} else {
console.warn("No web3 detected. Falling back to http://localhost:8545. You should remove this fallback when you deploy live, as it's inherently insecure. Consider switching to Metamask for development. More info here: http://truffleframework.com/tutorials/truffle-and-metamask");
// fallback - use your fallback strategy (local node / hosted node + in-dapp id mgmt / fail)
window.web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
}
SimpleStore.setProvider(web3.currentProvider);
ContractFactory.setProvider(web3.currentProvider);
ContractFactory.deployed().then(function(instance) {
return instance.createStore({from: web3.eth.accounts[0],gas: 6700000});
console.log("******");
});
});
Adding gas cost as an argument has resolved problem of VM exception.
instance.createStore({from: web3.eth.accounts[0],gas: 6700000});
I am also able to execute transaction from truffle console -
truffle(development)> ContractFactory.deployed().then(function (instance) { return instance.createStore({from: web3.eth.accounts[0],gas: 6700000});})
{ tx: '0x4d34e45cddbfa6f087f5dcb02bb5e7dc0fa18a0f7d24e87f8fff8702dd3e53bc',
receipt:
{ transactionHash: '0x4d34e45cddbfa6f087f5dcb02bb5e7dc0fa18a0f7d24e87f8fff8702dd3e53bc',
transactionIndex: 0,
blockHash: '0xf77b2baa3cacc941a8376376425c642c6db580e4a26918a0905ed589a618bfe7',
blockNumber: 26,
gasUsed: 123078,
cumulativeGasUsed: 123078,
contractAddress: null,
In web3py you can use the method buildTransaction:
myContract.functions.myMethod(*args, **kwargs).buildTransaction(transaction)
In your example you can do as follows:
tx = greeter.functions.greet("newGreet").buildTransaction({'nonce': web3.eth.getTransactionCount('your accountaddress')}}
Then you can sign the transaction using:
signed_tx = web3.eth.account.signTransaction(tx, private_key='your privateKey')
and finally you can send the transaction signed using:
web3.eth.sendRawTransaction(signed_tx.rawTransaction)
Hope this helps.
Best Answer
Because your
greet()
function is markedconstant
, web3 by default simulates the call and returns the value, but no transaction is sent, and thus no state changes are retained. This behavior can be forced in non-constant methods usingcontract.method.call()
.To call the function in a way that does send a transaction and update the chain, use
greeter.greet.sendTransaction({from:eth.coinbase, gas:100000})
.Unfortunately, while other contracts will recieve the proper return value, web3 will return a transaction hash, as opposed to a return value. In this case, it makes sense to use Events.
For example, the solidity would look something like:
And to get a return value: