28

I have the following simple smart contract...

contract SimpleStorage {
    uint storedData;
    function set(uint x) {
        storedData = x;
    }
    function get() constant returns (uint retVal) {
        return storedData;
    }
}

Which I deploy with the following code in the geth console...

var source = "contract SimpleStorage...[code here]"
var compiled = web3.eth.compile.solidity(source)
var contract = web3.eth.contract(compiled.Coin.info.abiDefinition)
var storage = contract.new({from:web3.eth.accounts[0], data: compiled.SimpleStorage.code, gas: 300000})

After the contract has been mined, I am able to access the contract functions via the storage object. I assumed that I could just call...

storage.set(10)

...to set the storedData variable. However every time I try this I get an "Invalid Address" error.

I'm sure that this is because I am attempting to perform a write operation on the internal state of the contract (read operations work fine).

I need to submit a transaction that mines the new state of the contract, however I can't figure out how to do this.

How can I perform write transactions in smart contracts?

1 Answer 1

28

Try setting

web3.eth.defaultAccount = eth.accounts[0]

It sounds like your transaction doesn't know what account to use to sign the call. Any call that changes the state of the contract (write operation) requires a signed transaction.

An alternative approach would be to pass a 'transaction object' as the last argument to contract method:

storage.set(10,{from: accounts[0]});

Edit 1:

When I chose the 'from' account, I got the following error: 'authentication needed: password or unlock'. So I needed to run personal.unlockAccount(eth.accounts[0],"password",15000). You can read about it at 'authentication needed: password or unlock' Error when trying to call smart contract method via web3 .

7
  • I knew it would be simple! How would I do this without setting the defaultAccount? For example if I was using multiple accounts on the same geth instance?
    – billett
    Commented Mar 16, 2016 at 8:04
  • You can call web3.accounts and store the results into an array. Then access the array for the specific account. When you call a method that executes a transaction and needs an account, pass an object that contains a from: storage.set(10,{from: accounts[1]});
    – dbryson
    Commented Mar 16, 2016 at 12:15
  • This is exactly what I was looking for. So simple! If the function has multiple parameters, is it just... storage.set(a,b,c,d,{from: eth.accounts[0]})?
    – billett
    Commented Mar 16, 2016 at 14:31
  • Yes. See the web3.js api docs: github.com/ethereum/wiki/wiki/… Note the transactionObject. This is what you can pass as the last argument to your contract call
    – dbryson
    Commented Mar 16, 2016 at 15:01
  • and how to obtain the txID of the result?
    – knocte
    Commented May 24, 2016 at 5:21

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.