0

I have setup testrpc with two accounts using this syntax basically:

testrpc -h 0.0.0.0 --account=0x93e707aa1e3ada62,10000000000000000000 --account=0x47e7625a68200ea9,1000000000000000000

I can transfer eth between the two accounts using MetaMask.

I then used the Crowdfuding example as described here:

https://dappsforbeginners.wordpress.com/tutorials/contracts-that-send-transactions/

This defines two functions, newCampaign:

function newCampaign(address beneficiary, uint goal, uint deadline) returns (uint campaignID) {
    campaignID = numCampaigns++; // campaignID is return variable
    Campaign c = campaigns[campaignID]; // assigns reference
    c.beneficiary = beneficiary;
    c.fundingGoal = goal;
    c.deadline = block.number + deadline;
}

And, contribute:

//function to contributes to the campaign
function contribute(uint campaignID) {
    Campaign c = campaigns[campaignID];
    Funder f = c.funders[c.numFunders++];
    f.addr = msg.sender;
    f.amount = msg.value;
    c.amount += f.amount;

}

I can compile the contract successfully, and deploy seems to work.

I then jump into truffle console. I'm trying to create a new campaign with the first user, and then contribute to it with the second user.

From within truffle, I run this code:

CrowdFunding.deployed()
.then( function(inst) { 
  return inst.newCampaign( "0x30924cD9D8e3644B1c186e3381694403A77f87b6", 50, 50 ); } )
.then( function(id) { 
  console.log( "ID:", id ); });

This does not print out the expected campaign ID, as I expected. Instead it prints out:

ID: { tx: '0x3afb822beb6dae9d73db0505ba0ee1056902e5c968bd8a6888fe0024f633f8e4',
  receipt: 
   { transactionHash: '0x3afb822beb6dae9d73db0505ba0ee1056902e5c968bd8a6888fe0024f633f8e4',
     transactionIndex: 0,
     blockHash: '0xccd15e9cb18c9b0d8d9c4298bb886c427f155318755c241515796cb0483ff66d',
     blockNumber: 9,
     gasUsed: 88745,
     cumulativeGasUsed: 88745,
     contractAddress: null,
     logs: [] },
  logs: [] }
undefined

Q1: So, that's my first problem, how do I get the campaignId supposedly returned from the newCampaign call?

Q2 Obviously I will then want to call the contribute function. But, I'm confused as to how I masequerade as the second user? I can get their address from MetaMask, but do I do something like this:

CrowdFunding.deployed()
.doTheThingsToGetCampaignId(). // fix the above code...
.then( function(inst) { 
  tx = { from: 0x132123 # The second account's address?
  return inst.contribute( campaignId, 50 ).call( tx ); // What should be here?
} );

Q3: I see various examples like inst.contribute.call(...). What's the right way to call contribute from truffle?

1 Answer 1

1

Q0 ;-)

You can probably get away with

$ testrpc

Q1

To get you started. Later, check out the web3 API and the async technique. In Truffle:

> var accounts = web3.eth.accounts;
undefined
> accounts
[ '0x123...']
> var account1 = accounts[0]
undefined
> account
'0x123...'
> var account2 = accounts[1]

Great.

Q2

You can add from: This is where value: and gas: go optionally.

return inst.newCampaign( "0x30924cD9D8e3644B1c186e3381694403A77f87b6", 50, 50, {from: account1} ); 

Q3

There are two modes of invoking a function. In the case of a state-change, you sendTransaction(). Truffle gives you better readability by wrapping Web3. That's what's going on here. Deep down, it's a sendTransaction():

inst.newCampaign( ... )

Since you sent a transaction it needs to be verified by the network. The first callback gives you the transaction hash, hence the unexpected big string. You might say:

then( function(txn) { 
  console.log( "TransactionHash", txn ); ...

You can also invoke functions read-only with .call(). That would be:

inst.newCampaign.call( ... )

Again, read only (and fast, and returns the expected value) but it doesn't change the state. So, not appropriate for newCampaign because that's supposed to update the chain. .call() is sometimes used for "dry run" and often used for query operations.

Hope it helps.

5
  • So, for Q3, I think I am still confused. "Deep down it's a sendTransaction()." The next thing you show is "inst.newCampaign(...)" Do you mean to provide some syntax with "sendTransaction" chained into it, or are you just saying truffle provides syntactic sugar to make a call to sendTransaction unnecessary? And, I think I am getting the gist between call() which does not change state (no updates to the chain), and sendTransaction() (which does update the chain). But, I'm still unclear on the syntax to make a call to a function which updates the chain.
    – xrd
    Commented Jun 29, 2017 at 3:06
  • And, for Q2, do you mean to use "inst.contribute( campaignId, { from: account[0] })". I'm still confused as to how to get the campaignId from the initial call to newCampaign. I don't see it anywhere in the tx.
    – xrd
    Commented Jun 29, 2017 at 3:10
  • Truffle adds sugar, and your code is doing sendTransaction() correctly. Gist of call/read-only/local execution/local blockchain copy sounds correct. You would only add .call() in Tuffle's sugar-coated syntax to switch to read-only. Yes, I meant { from: account[n] } (better than hard coding it). Commented Jun 29, 2017 at 4:38
  • 1
    Now ... hmmm ... bad news. You can't get a return value from a send transaction. One of several issues I spotted in the contract ... obviously, you want that child contract ID. That's a can of worms when starting out in this environment. A solution to that issue is to set up an event listener, and have the contract emit an event. So two tasks ... in Solidity, emit events ("event log") and then in JavaScript, listen for them. Maybe start here. ethereum.stackexchange.com/questions/2854/… Commented Jun 29, 2017 at 4:44
  • BTW .. the return value is visible to other contracts that invoke functions but it isn't (easily) visible from "outside" whereas events are easily monitored from outside. You set up a listener with something to do in a callback and then it waits for something to appear in the log ... like, say ... LogNewContract, address: 0x123 Commented Jun 29, 2017 at 4:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.