Могу ли я отправить эфириум на контракт вне его конструктора?

Как финансировать контракты Solidity с помощью эфира? Пример в часто задаваемых вопросах по Solidity, http://solidity.readthedocs.io/en/develop/frequently-asked-questions.html#store-ether-in-a-contract , финансирует контракт через конструктор контракта. Можно ли сделать то же самое вне конструктора?

Некоторый фон; Я хочу, чтобы контракт мог отправлять эфир на чей-то адрес через что-то вродеrecipient.send(169000000000000000000);

Во всяком случае, вот вывод из моей gethконсоли:

>eth.getBalance(eth.coinbase)
169531250000000000000

Итак, у меня есть ~169 Эфира для игры. Большой! Итак, я попробовал это:

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

Который я затем хотел профинансировать с помощью следующего вызова .js:

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")})

К сожалению, похоже, это не работает; При загрузке консоли получаю следующее:

>eth.getBalance('0x0d2bbe5af1fa1eaebc5ad6e27aa27a7328dc58bc')
0

Итак, задаваясь вопросом, был ли мой .js неисправен, я попробовал то же самое в консоли:

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

Бу :( Вот тогда я и задумался, а можно ли вообще отправить Эфир! Но:

>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

Так что, похоже, я все-таки могу отправить эфир на неконтрактный адрес. Фу!

Как мне сделать то же самое с контрактными адресами?

Ответы (1)

Да , эфир можно отправить на контракт вне его конструктора.

Рекомендуемый способ — вызвать функцию в контракте (функция получения эфира / резервная функция) , и эта функция может делать больше, чем просто регистрировать событие .

Начиная с Solidity 0.4 , payableмодификатор должен быть прикреплен к функции или резервной функции.

Можно было бы сделать резервную функцию payable, но это означает, что другие люди могут случайно отправить эфир на контракт. Этот вид устраняет преимущество payable, которое Solidity добавила, чтобы контракты не должны были реализовывать свой собственный модификатор для отклонения эфира и присоединения его к большинству своих функций.

Функции, которые хотят получить эфир, должны указать новый модификатор payable (иначе они выбрасывают).

Контракты, которые хотят получить эфир с простой «отправкой», должны реализовать резервную функцию с модификатором payable. Контракты теперь выбрасываются, если не определена оплачиваемая резервная функция и ни одна функция не соответствует подписи.

Ура! хороший! Итак, это работает: function() payable { Funded(msg.sender, msg.value); } А затем вызывая это следующим образом: web3.eth.sendTransaction({from: adminAccount, to: contractAddress, value: web3.toWei(100,"ether")}) ... финансирует контракт 100 Ether :) Спасибо!
Относительно: «Функция отката может быть сделана платной, но это означает, что другие люди могут случайно отправить эфир на контракт». Можно ли этого избежать, добавив onlyOwnerмодификатор в резервную функцию (как описано здесь: solidity.readthedocs.io/en/develop/contracts.html )?
Да, добавление другого модификатора, например, onlyOwnerможет предотвратить отправку эфира с других адресов.