4

How do I fund Solidity contracts with Ether? The example in the Solidity FAQ, http://solidity.readthedocs.io/en/develop/frequently-asked-questions.html#store-ether-in-a-contract, funds a contract via the contract's constructor. Can you do the same outside of the constructor?

Some background; I want a contract to be able to send Ether to someone's address via something like recipient.send(169000000000000000000);

Anyway, here's the output from my geth console:

>eth.getBalance(eth.coinbase)
169531250000000000000

So I have ~169 Ether to play with. Great! So I tried this:

contract A {
    function fund() public {
        Funded(msg.sender,msg.value);
    }    
}

Which I then wanted to fund with the following .js call:

const exchangerContract = web3.eth.contract(exchangerAbi)
const contractAddress = '0x0d2bbe5af1fa1eaebc5ad6e27aa27a7328dc58bc'
const contract = exchangerContract.at(contractAddress)
contract.fund({from: web3.eth.accounts[0], value: web3.toWei(100,"ether")})

Unfortunately, that doesn't seem to work; I get the following when I load up the console:

>eth.getBalance('0x0d2bbe5af1fa1eaebc5ad6e27aa27a7328dc58bc')
0

So, wondering if my .js was faulty, I tried the same in the console:

>eth.sendTransaction({from: eth.coinbase, to: '0x0d2bbe5af1fa1eaebc5ad6e27aa27a7328dc58bc', value: web3.toWei(100, "ether")})
"0x136ae6919bd2640425b03633b6709c3863d96600da6ca0c61956f694bbe62384"
>eth.getBalance('0x0d2bbe5af1fa1eaebc5ad6e27aa27a7328dc58bc')
0

Boo :( So then I wondered if it was possible to send Ether at all! But:

>personal.newAccount()
Passphrase: 
Repeat passphrase: 
"0x5e610b6696683e1c4173bd949279fd6127d8b808"
> eth.getBalance(eth.coinbase)
169531250000000000000
> eth.getBalance(eth.accounts[1])
0
> eth.sendTransaction({from: eth.coinbase, to: eth.accounts[1], value: web3.toWei(169, "ether")})
"0x136ae6919bd2640425b03633b6709c3863d96600da6ca0c61956f694bbe62384"
> eth.getBalance(eth.accounts[1])
169000000000000000000

So it seems I can send Ether to a non-contract address, after all. Phew!

How do I do the same to contract addresses?

6

Yes, ether can be sent to a contract outside of its constructor.

The recommended way is to invoke a function in the contract (Receiving Ether / the fallback function), and the function can do more instead of just log an event.

Since Solidity 0.4, the payable modifier needs to be attached to the function or fallback function.

The fallback function could be made payable, but that means other people can accidentally send ether to the contract. This kind of removes the benefit of payable, which Solidity added so that contracts didn't have to implement their own modifier to reject ether and attach it to most of their functions.

Functions that want to receive Ether have to specify the new payable modifier (otherwise they throw).

Contracts that want to receive Ether with a plain "send" have to implement a fallback function with the payable modifier. Contracts now throw if no payable fallback function is defined and no function matches the signature.

  • 1
    Yay! nice one! So this works: function() payable { Funded(msg.sender, msg.value); } And then calling it this way: web3.eth.sendTransaction({from: adminAccount, to: contractAddress, value: web3.toWei(100,"ether")}) ...funds the contract with 100 Ether :) Thanks! – glowkeeper Oct 24 '16 at 21:32
  • Regarding: "The fallback function could be made payable, but that means other people can accidentally send ether to the contract." Could that be prevented by adding the onlyOwner modifier to the fallback function (as described here: solidity.readthedocs.io/en/develop/contracts.html)? – glowkeeper Oct 24 '16 at 21:48
  • Yes, adding another modifier like onlyOwner can prevent other addresses sending ether. – eth Oct 24 '16 at 23:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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