Как извлечь деньги из смарт контракта эфириум
Перейти к содержимому

Как извлечь деньги из смарт контракта эфириум

  • автор:

Withdraw Ether From Smart Contract¶

So far we have sent Ether to our Smart Contract. But there is currently no way to get Ether back out again! So, what’s next? Yes! A function to withdraw Ether would be good, ey?!

Add a Withdraw Function¶

Let’s add the following function to the Smart Contract:

This function will send all funds stored in the Smart Contract to the person who calls the «withdrawMoney()» function.

Deploy the new Smart Contract¶

  1. Deploy the new version and send again 1 Ether to the Smart Contract.
  2. To avoid confusion I recommend you close the previous Instance, we won’t need it anymore

At the end you should end up with one active Instance of your Smart Contract.

The same procedure as before:

  1. Put in «1 Ether» into the value input box
  2. hit «receiveMoney» in your new contract Instance

Your balance should be 1 Ether again:

If your balance is 0, then double check the value field

If your balance is 2 Ether, then double check the contract Instance you are interacting with!

Withdraw Funds from the Smart Contract¶

Now it’s time we use our new function! But to make things more exciting, we’re going to withdraw to a different Account.

Select the second Account from the Accounts dropdown:

Then hit the «withdrawMoney» button:

Observe the amount of Ether you have now in your Account:

It’s more than the previous 100 Ether! We got our 1 Ether through our Smart Contract into another Account! AWESOME!

Why not 101 Ether?

Are you wondering why you don’t have 101 Ether in your Account? After all, you had 100 Ether before, and now you added 1 Ether, so, why is it not 101 Ether? Is the Math you learned in school worthless?

No, the Math you learned in School comes in handy actually.

What you can observe here is the concept of «Gas» on the Ethereum Blockchain. Every transaction on Ethereum costs a little bit. And it’s not different here on a simulated chain. Same principles apply. How much is the Gas you paid, you’re wondering? Well, you can open the transaction details and see for yourself. We’re covering this — in depth — later on in the course. I also made a dedicated video and blog post about this if you want to deep dive right now.

While we can withdraw our funds now, the whole function itself is pretty useless, isn’t it?! Anyone can withdraw funds to his Account. There are no fractions of the Amount — all in all, pretty insecure.

I still hope the concept is a bit clearer now!

Let’s to another function, which allows us the send the full amount to a specific Address! It will still be insecure, but at least teaches a new concept — one at a time!

How to withdraw Ether from a contract?

How can I transfer Ether from the contract to my personal purse (non programmatically using such a program as Ethereum Wallet)?

Can I send Ether from the contract like as I can do with regular wallet?

In the «possible duplicate» question it is not said how to withdraw from the contract non-programmatically. It is should be easy for a user to withdraw, without him writing a code.

4 Answers 4

Basically it all depends on your contract.

Let’s have an example contract:

You can save Ether in this contract by calling the payme function. Also you can query how much Ether the contract has. But the Ether can’t be transferred away, so it’s stuck in the contract forever.

@Victory’s answer has a good idea about how to enable withdrawals without any coding. But that of course requires the contract to support such functionality.

Работа со смарт-контрактами через Ethereum RPC API

Всем привет. В этой статье мы рассмотрим основные приемы по публикации смарт-контрактов и взаимодействию с ними с использованием Ethereum RPC API. Обсуждаемые методы API позволяют решать такие задачи:

  1. Создание счёта.
  2. Создание корректного смарт-контракта.
  3. Получение информации со смарт-контракта.
  4. Изменение состояния смарт-контракта.
  • Некоторые общие замечания
  • Упаковка параметров и возвращаемых данных
  • Создание счёта и работа с ним
  • Создание смарт-контракта
    • Компиляция исходного кода смарт-контракта
    • Извлечение кода из транзакции
    • Рассчёт стоимости опубликования контракта
    • Выполнение транзакции на публикацию контракта
    • Создание контракта с параметрами
    • Идентификация методов контракта
    • Вызов методов запроса информации
    • Вызов методов, изменяющих состояние контракта

    Некоторые общие замечания

    1. Все предлагаемые действия иллюстрируются реальными данными из тестовой сети Rinkeby (на момент написания статьи).
    2. Состояние транзакций, счетов и смарт-контрактов в Rinkeby можно отслеживать по сайту https://rinkeby.etherscan.io/ (для подсети Ropsten будет, соответственно, https://ropsten.etherscan.io/).

    Упаковка параметров и возвращаемых данных

    Эта часть также носит общий характер и поэтому вынесена в отдельную главку, но её изучение можно отложить до момента, когда непосредственно понадобится использовать параметры или разобрать ответ смарт-контракта.

    Входящий (параметры) или исходящий пакет данных для контракта формируется по следующему принципу:

    • Фиксированные по длине типы данных (address, uint32, bytes32) передаются с выравниванием до 32-байтного слова (64 hex-цифры).
    • Переменные по длине типы данных (строковые, массивы) передаются по следующей схеме:
      • В позиции объекта в списке передается смещение блока с его данными относительно начала пакета (с выравниванием до 32-байтного слова).
      • В первом 32-байтном слове блока передается число единиц данных.
      • В последующих 32-байтных словах передаются сами данные.

      В строке 000 передается адрес 0х570f5d143ee469d12dc29bf8b3345fa5536476d9 .
      В строке 020 передается ссылка на блок, описывающий переменную типа string — 0x80 байт от начала блока.
      В строке 040 передается целое число 0х1234 .
      В строке 060 передается ссылка на блок, описывающий массив address[] — 0xc0 байт от начала блока.
      В строке 080 передается счетчик символов переменной типа string — 3 .
      В строке 0a0 передаются сами символы переменной типа string — слово New .
      В строке 0c0 передается счетчик элементов массива address[] — 2 .
      В строке 0e0 передается первый элемент массива address[] — 0хaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa .
      В строке 100 передается второй элемент массива address[] — 0хbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb .

      Внимание! Весь блок передается одним слитным массивом:

      Создание счёта и работа с ним

      Для создания нового счёта используется метод personal_newAccount , в качестве параметра которому передаётся пароль, который в дальнейшем будет использоваться для разблокировки счёта:

      В ответ приходит идентификатор счёта, в данном случае — 0xfbeda9914b78b58a0f0e810298f9d545f8379f8d .

      Все дальнейшие манипуляции мы будем производить с этого счета — 0xfbeda9914b78b58a0f0e810298f9d545f8379f8d .

      Теперь нам необходимо положить на него некоторую сумму для оплаты исполнения транзакций. Так как в тестовой сети Rinkeby поучаствовать в майнинге человеку со стороны невозможно, то для пополнения счетов предусмотрен специальный «кран», процедура использования которого описана здесь — https://faucet.rinkeby.io/.

      Для пополнения счета необходимо:

        Зарегистрироваться на github.com и создать новый gist:

      Создание смарт-контракта

      Технически смарт-контракт создаётся транзакцией, содержащей в поле данных байт-код контракта и блок параметров инициализации, если такие предусмотрены смарт-контрактом.

      Байт-код контракта для формирования транзакции создания может быть получен следующими способами:

      • Компиляцией из исходного текста смарт-контракта.
      • Извлечением из другой транзакции создания такого же смарт-контракта.

      Технически можно извлечь код транзакции непосредственно по идентификатору уже существующего смарт-контракта (метод eth_getCode), но этого делать НЕЛЬЗЯ, так как он выдаёт байт-код, подвергшийся специальной обработке при создании смарт-контракта (в частности, из него удаляются блоки инициализации).

      Компиляция исходного кода смарт-контракта

      Для компиляции исходного кода на Solidity я использую Remix — https://remix.ethereum.org/.

      Вводим текст контракта, если ошибок нет — в поле Bytecode будет находиться собственно байткод, в нашем случае:

      Извлечение кода из транзакции

      Для извлечения кода из транзакции используется метод eth_getTransactionByHash . В нашем примере «клонируемый» смарт-контракт был создан транзакцией 0xc4d20bb8f9eede45968fc6bc850397e92b9f263eeb11200615cc08562d46c2e7 .

      В тэге input ответа содержится байткод контракта.

      Обратите внимание, что если конструктор смарт-контракта предусматривает использование параметров, то кроме байт-кода в тэге input будут указаны значения параметров, следующих сразу следом за байт-кодом. При создании шаблона смарт-контракта для последующего клонирования можно использовать нулевые значения параметров.

      Расчет стоимости опубликования контракта

      Для расчета стоимости опубликования контракта используется метод eth_estimateGas , в параметрах которого следует указать номер счета (тэг from ), с которого будет создан контракт, а также байт-код контракта (тэг data ). В ответе будет указано необходимое количество Gas.

      Если конструктор смарт-контракта предполагает использование параметров, то они должны быть включены в запрос в тэге data сразу после байт-кода. В противном случае расчет Gas будет некорректным.

      Обратите внимание, что в некоторых случаях смарт-контракты содержат семантические (не синтаксические) ошибки, которые пропускаются компилятором, но приводят к неработоспособности контракта. Одним из признаков появления такой ошибки будет резкое — в разы, возрастание стоимости создания контракта.

      Выполнение транзакции на публикацию контракта

      Для публикации контракта используется метод eth_sendTransaction . В качестве параметров методу передаются:

      • номер счета, с которого создаётся контракт (тэг from );
      • стоимость публикации в Gas (тэг gas , берется из предыдущего пункта);
      • байт-код контракта с пристыкованным блоком параметров конструктора (тэг data , должен полностью совпадать с использованным в предыдущем пункте).

      В ответ мы получим номер транзакции:

      или сообщение об ошибке:

      Теперь необходимо дождаться завершения транзакции и получить результат её исполнения — создан контракт или нет. Для этого используется метод eth_getTransactionReceipt :

      Пока транзакция находится в «листе ожидания» (Pending Txn), будет выдаваться следующий ответ:

      После исполнения транзакции мы получим полную «квитанцию», в теге contractAddress которой будет содержаться адрес созданного смарт-контракта:

      Если в течении 5 минут квитанция не получена, то либо в сети проблемы, либо ваш узел не разослал проводку по сети. Чтобы понять истинную причину, следует просмотреть очередь Pending Txn на etherscan.io (https://rinkeby.etherscan.io/txsPending). Если транзакции там нет — значит, надо перезапустить клиент Ethereum и повторить публикацию заново.

      Теперь следует проверить, корректно ли создался смарт-контракт. Для этого можно использовать метод eth_getCode — получение кода контракта по его адресу:

      Если контракт создался некорректно, то будет получен ответ:

      Если в тэге result выдаются некоторые данные, отличные от 0x , то контракт создан успешно.

      Взаимодействие со смарт-контрактом

      Для демонстрации взаимодействия со смарт-контрактом будем использовать следующий образцовый смарт-контракт:

      При создании контракта (конструктор — функция Test ) ему передаются адрес Продавца ( seller_ ) и адрес Банка ( bank_ ). Метод GetStatus возвращает адресa Продавца, Банка и текущий статус контракта. Метод SetBankCert предназначен для сохранения в контракте некоторого цифрового идентификатора с переводом в статус «Confirmed».

      Создание контракта с параметрами

      Если конструктор смарт-контракта использует параметры (как в нашем демонстрационном примере), то они должны быть «упакованы» в соответствии с описанием «Упаковка параметров и возвращаемых данных» и присоединены в хвост к байт-коду контракта.

      В нашем случае, передача адреса Продавца 0x794ce6de39fa2d274438cc1692db04dfb5bea836 и адреса Банка 0xfbeda9914 b78b58a0f0e810298f9d545f8379f8d при создании смарт-контракта будет выглядеть следующим образом (байт-код контракта кончается на 0029 ):

      Еще раз обращаю внимание, что расчет Gas должен выполняться для всего блока Байт-код + Параметры, иначе контракт или не будет создан, или будет неработоспособен.

      Наш тестовый демо-контракт был создан по адресу 0x3d20e579f5befdc7d3f589adb6155f684d9a751c .

      Идентификация методов контракта

      Для идентификации метода смарт-контракта, к которому мы обращаемся, используются первые 4 байта (8 шестнадцатеричных цифр) от хэша описания метода.

      Например, для метода GetStatus демо-контракта описанием будет GetStatus() , а для метода SetBankCert — SetBankCert(address) . Особое внимание следует обратить на отсутствие пробелов в описании — были печальные прецеденты :(.

      Для определения хэша используется метод web3_sha3 , при этом строчное значение следует давать в шестнадцатеричном представлении (для GetStatus() это будет 0x4765745374617475732829 ):

      Соответственно, идентификатором метода GetStatus будет 0xabd95b95 , для метода SetBankCert идентификатор — 0x1bb71149 .

      Вызов методов запроса информации

      Для вызова методов, не связанных с изменением состояния контракта (например, для получения информации о его текущем статусе), может быть использован метод API eth_call .

      Запрос метода имеет такую структуру:

      Блок <Данные запроса> формируется следующим образом:

      <Идентификатор метода><Данные параметров>

      где <Данные параметров> формируются, как указано в пункте «Упаковка параметров и возвращаемых данных».

      Если метод не предполагает наличия параметров, то блок <Данные запроса> состоит только из идентификатора метода.

      Например, для вызова метода GetStatus демо-контракта Test используется запрос:

      на который будет дан ответ:

      Разберем полученный ответ в соответствии с правилами пункта «Упаковка параметров и возвращаемых данных» и с учетом описания метода GetStatus — function GetStatus() constant returns (address, address, string retVal).

      Для удобства анализа разложим ответ на 32-байтные слова:

      Исходя из описания мы ожидаем получение следующего набора переменных: address, string. Таким образом:

      • в строке 000 находится адрес Продавца (тип address ) — 0x794ce6de39fa2d274438cc1692db04dfb5bea836
      • в строке 020 находится адрес Продавца (тип address ) — 0xfbeda9914b78b58a0f0e810298f9d545f8379f8d
      • в строке 040 находится ссылка на блок описания статуса контракта (тип string ) — блок начинается с адреса 060
      • в строке 060 находится счетчик символов в строке статуса контракта — 3 символа
      • в строке 080 находятся собственно символы статуса контракта в шестнадцатеричной кодировке — New

      Вызов методов, изменяющих состояние контракта

      Для вызова методов, изменяющих состояние контракта, должен быть использован метод API eth_sendTransaction .

      Запрос метода имеет такую структуру:

      <Адрес инициатора> должен иметь баланс, достаточный для выплаты <Стоимости исполнения> . Кроме того, следуют учитывать, что контракт может содержать внутренние условия по контролю <Адреса инициатора> , как, например, в методе SetBankCert нашего демо-контракта.
      Блок <Данные запроса> формируется следующим образом:

      <Идентификатор метода><Данные параметров>

      где <Данные параметров> формируются, как указано в параграфе «Упаковка параметров и возвращаемых данных».

      Если метод не предполагает наличия параметров, то блок <Данные запроса> состоит только из идентификатора метода.

      Например, для вызова метода SetBankCert(«0хf7b0f8870a5596a7b57dd3e035550aeb5af16607») демо-контракта, <Данные запроса> будут иметь следующий вид:

      Для определения стоимости исполнения, как и при создании смарт-контракта, используется метод eth_estimateGas , в который передаются всё те же параметры, которые затем будут переданы в методе eth_sendTransaction .

      Как показывает опыт, если в вызываемом методе содержится транзакционный вызов других смарт-контрактов, то сумма Gas может быть рассчитана неверно и транзакция не исполнится. Поэтому рекомендую указывать заведомо большее количество Gas, так как, по идее, излишек использован не будет. В таких случаях я указываю количество Gas, близкое к максимальному — 0х200000 .

      Далее вызываем метод eth_sendTransaction :

      и получаем в ответ идентификатор транзакции:

      Как и в случае с созданием смарт-контракта, ожидаем исполнения транзакции, запрашивая квитанцию (метод eth_getTran sactionReceipt):

      Как только квитанция пришла — транзакция исполнилась:

      Однако, само по себе исполнение транзакции вовсе не означает, что смарт-контракт переключился в нужное состояние, кроме того, могут не исполниться внутренние транзакционные вызовы других смарт-контрактов.

      На мой взгляд, самый надежный способ проверить, что всё отработало — снова запросить состояние смарт-контракта и убедиться, что всё изменилось «как надо».

      Разобрав ответ, мы увидим, что статус изменился на «Confirmed».

      Резюме

      В этом руководстве мы рассмотрели выполнение ряда задач, связанных с публикацией смарт-контрактов и взаимодействием с ними с помощью RPC API блокчейн-платформы Ethereum. Разобрались, как создавать счёт, как создавать корректный смарт-контракт, получать по нему информацию и изменять его состояние, а также выяснили, как с этим смарт-контрактом взаимодействовать.

      Если у вас возникнут дополнительные вопросы, рад буду ответить/подсказать.

      Пишем смарт-контракт Ethereum — это просто: Часть 11 — ICO, refund — возврат средств по softcap

      В предыдущей статье мы познакомились с видами эмиссий и научились верифицировать контракт в etherscan. Теперь наша задача создать механизм возврата средств, тем самым повысив доверие инвесторов.

      В некоторых ICO для реализации проекта необходима какая-то минимальная сумма. Так называемый softcap. Если основатели ее не собирают, то проект выполнить невозможно.

      Зачем нужен механизм возврата средств по softcap?

      1. Если во время ICO softcap не был достигнут, то получается что и деньги у вас и проект не будет выполнен. В этом случае, если вы не вернете средства, то инвесторы могут посчитать вас обманщиком.
      2. Наличие возврата денег повышает доверие инвесторов.

      Когда возврат по softcap не нужен?

      1. Если ваш проект не имеет минимальной суммы для реализации. Например, если у вас проект по инвестициям в валюты, то тут минимальная сумма не нужна. В любом случае можно инвестировать любую сумму.
      2. Когда вы четко прописываете в WhitePaper, что при недостижении softcap инвестиции не возвращаются (это может быть оправдано как покрытие расходов на запуск ICO).
      3. Если вы достаточно уверены в том, что соберете softcap. Такая уверенность может основываться на результатах сбора во время presale например.

      Как сделать механизм возврата средств?

      Возврат средств может быть реализован как на пресейле так и на ICO. Работает он достаточно просто. Во время ICO средства инвесторов перечисляются не специальный счет-контракт. С этого счета основатели не могут вывести деньги до окончания ICO. По окончанию можно проверить — достигнут ли softcap. Если не достигнут, то средства остаются на специальном счете и инвесторы могут вернуть себе средства путем вызова специальной функции возврата. Обычно ее называют refund. Если же softcap был достигнут, то средства со спец-счета переводятся на счет основателей.

      Давайте приступим к нашей реализации. За основу мы возьмем код 9-го урока.

      Для простоты средства инвесторов у нас будут собираются на счету контракта распродажи.

      Нижняя граница сборов softcap у нас будет хранится в переменной sotfcap.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *