Конструктор смарт контрактов на эфириуме

Обновлено: 11.05.2024

If you are new to blockchain development and don’t know where to start, or if you just want to understand how to deploy and interact with smart contracts, this guide is for you. We will walk through creating and deploying a simple smart contract on the Ropsten test network using a virtual wallet (MetaMask), Solidity, Hardhat, and Alchemy (don’t worry if you don’t understand what any of this means yet, we will explain it).

In part 2 of this tutorial we’ll go through how we can interact with our smart contract once it’s deployed, and in part 3 we’ll cover how to publish it on Etherscan.

If you have questions at any point feel free to reach out in the Alchemy Discord!

Step 1: Connect to the Ethereum network

There are many ways to make requests to the Ethereum chain. For simplicity, we’ll use a free account on Alchemy, a blockchain developer platform and API that allows us to communicate with the Ethereum chain without having to run our own nodes. The platform also has developer tools for monitoring and analytics that we’ll take advantage of in this tutorial to understand what’s going on under the hood in our smart contract deployment. If you don’t already have an Alchemy account, you can sign up for free here.

Step 2: Create your app (and API key)

Once you’ve created an Alchemy account, you can generate an API key by creating an app. This will allow us to make requests to the Ropsten test network. If you’re not familiar with testnets, check out this page.

  1. Navigate to the “Create App” page in your Alchemy Dashboard by hovering over “Apps” in the nav bar and clicking “Create App”

Hello world create app

  1. Name your app “Hello World”, offer a short description, select “Staging” for the Environment (used for your app bookkeeping), and choose “Ropsten” for your network.

create app view hello world

  1. Click “Create app” and that’s it! Your app should appear in the table below.

Step 3: Create an Ethereum account (address)

We need an Ethereum account to send and receive transactions. For this tutorial, we’ll use MetaMask, a virtual wallet in the browser used to manage your Ethereum account address. More on transactions.

You can download and create a MetaMask account for free here. When you are creating an account, or if you already have an account, make sure to switch over to the “Ropsten Test Network” in the upper right (so that we’re not dealing with real money).

metamask ropsten example

Step 4: Add ether from a Faucet

In order to deploy our smart contract to the test network, we’ll need some fake ETH. To get ETH you can go to the Ropsten faucet and enter your Ropsten account address, then click “Send Ropsten ETH.” It may take some time to receive your fake ETH due to network traffic. You should see ETH in your MetaMask account soon after!

Step 5: Check your Balance

To double check our balance is there, let’s make an eth_getBalance request using Alchemy’s composer tool. This will return the amount of ETH in our wallet. After you input your MetaMask account address and click “Send Request”, you should see a response like this:

NOTE: This result is in wei not ETH. Wei is used as the smallest denomination of ether. The conversion from wei to ETH is: 1 eth = 10 18 wei. So if we convert 0x2B5E3AF16B1880000 to decimal we get 5 * 10¹⁸ which equals 5 ETH.

Phew! Our fake money is all there .

Step 6: Initialize our project

First, we’ll need to create a folder for our project. Navigate to your command line and type:

Now that we’re inside our project folder, we’ll use npm init to initialize the project. If you don’t already have npm installed, follow these instructions (we’ll also need Node.js so download that too!).

It doesn’t really matter how you answer the installation questions, here is how we did it for reference:

Approve the package.json and we’re good to go!

Hardhat is a development environment to compile, deploy, test, and debug your Ethereum software. It helps developers when building smart contracts and dApps locally before deploying to the live chain.

Inside our hello-world project run:

Check out this page for more details on installation instructions.

Step 8: Create Hardhat project

Inside our project folder run:

You should then see a welcome message and option to select what you want to do. Select “create an empty hardhat.config.js”:

This will generate a hardhat.config.js file for us which is where we’ll specify all of the set up for our project (on step 13).

Step 9: Add project folders

To keep our project organized we’ll create two new folders. Navigate to the root directory of your project in your command line and type:

  • contracts/ is where we’ll keep our hello world smart contract code file
  • scripts/ is where we’ll keep scripts to deploy and interact with our contract

Step 10: Write our contract

You might be asking yourself, when the heck are we going to write code?? Well, here we are, on step 10.

Open up the hello-world project in your favorite editor (we like VSCode). Smart contracts are written in a language called Solidity which is what we will use to write our HelloWorld.sol smart contract.‌

  1. Navigate to the “contracts” folder and create a new file called HelloWorld.sol
  2. Below is a sample Hello World smart contract from the Ethereum Foundation that we will be using for this tutorial. Copy and paste in the contents below into your HelloWorld.sol file, and be sure to read the comments to understand what this contract does:

This is a super simple smart contract that stores a message upon creation and can be updated by calling the update function.

Step 11: Connect MetaMask & Alchemy to your project

We’ve created a MetaMask wallet, Alchemy account, and written our smart contract, now it’s time to connect the three.

Every transaction sent from your virtual wallet requires a signature using your unique private key. To provide our program with this permission, we can safely store our private key (and Alchemy API key) in an environment file.

To learn more about sending transactions, check out this tutorial on sending transactions using web3.

First, install the dotenv package in your project directory:

Copy Alchemy API URL

Your .env should look like this:

To actually connect these to our code, we’ll reference these variables in our hardhat.config.js file on step 13.

Don't commit .env ! Please make sure never to share or expose your .env file with anyone, as you are compromising your secrets in doing so. If you are using version control, add your .env to a gitignore file.

Step 12: Install Ethers.js

Ethers.js is a library that makes it easier to interact and make requests to Ethereum by wrapping standard JSON-RPC methods with more user friendly methods.

Hardhat makes it super easy to integrate Plugins for additional tooling and extended functionality. We’ll be taking advantage of the Ethers plugin for contract deployment (Ethers.js has some super clean contract deployment methods).

In your project directory type:

We’ll also require ethers in our hardhat.config.js in the next step.

Step 13: Update hardhat.config.js

We’ve added several dependencies and plugins so far, now we need to update hardhat.config.js so that our project knows about all of them.

Update your hardhat.config.js to look like this:

Step 14: Compile our contract

To make sure everything is working so far, let’s compile our contract. The compile task is one of the built-in hardhat tasks.

From the command line run:

You might get a warning about SPDX license identifier not provided in source file , but no need to worry about that — hopefully everything else looks good! If not, you can always message in the Alchemy discord.

Step 15: Write our deploy script

Now that our contract is written and our configuration file is good to go, it’s time to write our contract deploy script.

Navigate to the scripts/ folder and create a new file called deploy.js , adding the following contents to it:

Hardhat does an amazing job of explaining what each of these lines of code does in their Contracts tutorial, we’ve adopted their explanations here.

A ContractFactory in ethers.js is an abstraction used to deploy new smart contracts, so HelloWorld here is a factory for instances of our hello world contract. When using the hardhat-ethers plugin ContractFactory and Contract instances are connected to the first signer by default.

Calling deploy() on a ContractFactory will start the deployment, and return a Promise that resolves to a Contract . This is the object that has a method for each of our smart contract functions.

Step 16: Deploy our contract

We’re finally ready to deploy our smart contract! Navigate to the command line and run:

You should then see something like:

If we go to the Ropsten etherscan and search for our contract address we should able to see that it has been deployed successfully. The transaction will look something like this:

etherscan contract

The From address should match your MetaMask account address and the To address will say “Contract Creation” but if we click into the transaction we’ll see our contract address in the To field:

etherscan transaction

Congrats! You just deployed a smart contract to the Ethereum chain 🎉

hello world explorer

To understand what’s going on under the hood, let’s navigate to the Explorer tab in our Alchemy dashboard. If you have multiple Alchemy apps make sure to filter by app and select “Hello World”.

Here you’ll see a handful of JSON-RPC calls that Hardhat/Ethers made under the hood for us when we called the .deploy() function. Two important ones to call out here are eth_sendRawTransaction , which is the request to actually write our contract onto the Ropsten chain, and eth_getTransactionByHash which is a request to read information about our transaction given the hash (a typical pattern when transactions). To learn more about sending transactions, check out this tutorial on sending transactions using Web3

That’s all for part 1 of this tutorial, in part 2 we’ll actually interact with our smart contract by updated our initial message, and in part 3 we’ll publish our smart contract to Etherscan so everyone will know how to interact with it.

Want to learn more about Alchemy? Check out our website. Never want to miss an update? Subscribe to our newsletter here! Be sure to also follow our Twitter and join our Discord.

В последнее время ко мне поступает огромное количество запросов за помощью в разработке смартконтракта для проведения ICO, при этом у меня не хватает времени, чтобы помочь каждому. Поэтому я решил написать этот небольшой пост (ссылка на видео в конце поста), в котором описываю очень простой смартконтракт для проведения crowdsale, который вы можете использовать в своих проектах.




Для экономии времени я написал контракт заранее. Давайте разберем его по шагам.

Смартконтракт является программой написанной на языке программирования. В нашем случае на языке Solidity. Для разработки простых контрактов я использую онлайн редактор и компилятор Remix.

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


Сразу после идет строка, которая указывает, какую версию компиллятора следует использовать. Если этой строки не будет, то смартконтракт не скомпилируется.


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

Прежде всего следует понимать, что после загрузки смартконтракта в виртуальную машину Ethereum вы будете взаимодействовать с ним на общих основаниях, как и все остальные пользователи. Логично, что мы, как команда проекта, хотели бы находиться в привилегированных условиях, которые должны как минимум выражаться в том, что контракт должен сформировать именно на командные токены и конечно же отдал именно нам собранный эфир. Для этого контракт должен знать своего владельца и именно за это отвечает контракт «owned».


Контракт «owned» содержит лишь одно публичное поле «owner», значение которого инициализируется в конструкторе значением поля «sender» глобальной структуры «msg», таким образом, изначально владельцем контракта становится тот, кто осуществил его деплой.

Логично предусмотреть возможность смены владельца на случай, если наш private key будет скомпрометирован, для этого предусмотрена функция «changeOwner», которая получает в качестве параметра адрес нового владельца. Следует обратить на модификатор «onlyOwner», который определен внутри этого же смартконтракта. Модификаторы представляют собой очень удобную конструкцию, позволяющую сгруппировать и присвоить название условиям вызова функций смартконтракта. Модификатор «onlyOwner» проверяет, что вызов функции осуществляется с адреса, который сохранен в поле «owner».

Следующий в иерархии контракт – «Crowdsale», отвечает непосредственно за сбор средств и выдачу токенов и наследует рассмотренный ранее контракт «owned».


Особое внимание следует обратить на следующие элементы контракта:

  • Публичное поле «totalSupply», которое должно содержать общее количество токенов, выпущенных смартконтрактом;
  • Публичная карта «balanceOf», которое содержит информацию о балансах всех держателей токенов;
  • Событие Transfer, которое должно испускаться смартконтрактом при каждой операции перемещения токенов между держателями токенов.

Конструктор смартконтракта «Crowdsale» предельно прост. Прежде всего инициализируется значение поля «totalSupply». Наш контракт выпускает 21 миллион токенов, из которых 20 миллионов сразу будут перемещены на баланс смартконтракта. Будем считать, что токены с адреса смартконтракта как раз и доступны для продажи. Оставшиеся токены, в нашем случае 1 миллион, будут записаны на адрес владельца контракта. Ну и в конце конструктора испускается событие «Transfer», которое помещается в блокчейн и информирует пользователей контракта о том, что с баланса контракта на баланс владельца контракта переведено соответствующее количество токенов. Именно испускание этого события позволит etherscan.io корректно отобразить держателей токенов и их балансы.

Затем осуществляется проверка того, что на балансе смартконтракта есть достаточное количество токенов для продажи. Если запрошено больше токенов, чем есть у смартконтракта, то будем переводить все оставшиеся токены. Определяем стоимость в «wei» оставшихся токенов и возвращаем отправителю излишне переведенный эфир. Убеждаемся, что количество покупаемых токенов ненулевое, после чего записываем это количество токенов на баланс покупателя и списываем их с баланса смартконтракта. В конце не забываем испустить событие Transfer.

На этом собственно реализация функциональности сбора средств закончена, но теперь нужно сделать наш токен операбельным и реализовать еще некоторые функции стандарта ERC20. Это сделано в контракте «EasyToken», который наследуется от рассмотренного ранее контракта «Crowdsale».


Прежде всего определим 4 публичных поля, которые сейчас практически не используются никакими кошельками, но для порядка все же определим их. Здесь укажем полное и сокращенное наименование токена, а также количество дробных знаков. В нашем случае токен является неделимым, т.к. значение поля «decimals» установлено равным 0.

И наконец, единственной функцией смартконтракта «EasyToken», ради которой мы создавали этот контракт, является «transfer», которая также является частью стандарта ERC20 и позволит кошелькам пользователей осуществлять передачу токенов друг другу, переводить их на биржу и выводить их с нее. Реализация функции крайне проста, проверяется достаточность количества токенов на балансе отправителя, после чего баланс отправителя уменьшается, а баланс получателя увеличивается на запрошенное количество токенов. В конце испускается событие «Transfer». Теперь наш токен является операбельным и осталось сделать самое главное – предоставить владельцу контракта возможность вывести собранные эфиры. Это мы сделаем в контракте «EasyCrowdsale».


Функция «withdraw» имеет модификатор «onlyOwner», т.е. может быть вызвана только владельцем смартконтракта. Единственное, что она делает – переводит весь баланс смартконтракта на адрес владельца смартконтракта.

Несмотря на то, что рассмотренный нами смартконтракт является полностью функционально законченным и работоспособным, использовать его в реальном проекте я бы не рекомендовал. Чрезмерное упрощение логики контракта привело к тому, что такой контракт не обеспечивает защиту интересов инвесторов в должной мере, а именно, не устанавливает срок проведения crowdsale, не устанавливает минимальной границы сбора, не возвращает средства инвесторам в случае недостижения минимальной границы, а также содержит ряд известных уязвимостей на уровне компилятора языка Solidity, например, подвержен так называемой short address attack.

Многие из этих недостатков устранены в смартконтракте нашего проекта PROVER. Контракт PROOF загружен в Ethereum по этому адресу вместе с исходным кодом, с которым можно познакомиться. Можно даже проверить, как работает контракт, отправив на него реальный эфир, у нас как раз сейчас идет Pre-ICO:). На самом деле, мы будем рады, если вы присоединитесь к presale нашего проекта PROVER, который продлится до конца сентября. PROVER – это уникальная технология подтверждения подлинности видеоматериалов на базе блокчейн и видеоаналитики.

Создаем первый смарт-контракт на Ethereum менее, чем за 60 минут

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

Для этого создается особый программный объект – смарт-контракт. Такие программы записываются в блокчейн и запоминаются навсегда. У всех участников сети есть ее копия. При этом работу контракта можно совместить с управлением денежными операциями: созданием аукциона, пари, лотереи, игры с денежным вознаграждением и т. д.

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

Рассмотрим реализацию смарт-контракта при помощи блокчейна Ethereum. Смарт-контракты Bitcoin ограничены в возможностях, в то время как Ethereum был спроектирован с учетом этих потребностей, и активно применяется для распределенной работы программ на основе блокчейн технологии, в частности, виртуальной машины Turing Complete.

В этом туториале мы создадим смарт-контракт программы простого счетчика. Программный код контракта будет написан на специальном языке для создания смарт-контрактов Solidity, во многом похожем на JavaScript.

Первым делом необходимо установить Ganache — инструмент для создания приватного блокчейна, работающего на вашем компьютере. Советуем загрузить версию 1.0.2, так как последняя версия по нашему опыту пока некорректно обрабатывает запросы смарт-контрактов. Также вам понадобится локальная копия MyEtherWallet (url-сайт на в рассматриваемом случае не подойдет). По последней ссылке вам нужно загрузить пакет с названием вида etherwallet-v3.xx.x.x.zip.

Онлайн-редактор Remix содержит компилятор для языка Solidity. При первом посещении страницы редактор для наглядности загружается с некоторым кодом. Этот код можно безболезненно стереть и заменить программой контракта Counter:

Он содержит одну переменную count и три функции. Переменная представляет собой целое число и является локальной – доступна только в пределах контракта Counter. Первая и вторая функции incrementCounter() и decrementCounter() изменяют значение count : повышают или понижают на единицу. Третья функция getCount() возвращает текущее значение переменной count .

При переносе кода в Remix он будет автоматически скомпилирован (по умолчанию на сайте стоит галочка Auto compile).

Оставим вкладку с редактором открытой, чтобы впоследствии к ней вернуться.

Запустите предварительно установленное приложение Ganache. Обратите внимание на ссылку на RPC SERVER. Она также нам вскоре понадобится.

Разархивируйте сохраненную ранее zip-папку MyEtherWallet и откройте index.html в веб-браузере. В правом верхнем углу находится кнопка с надписью Network ETH. По умолчанию в качестве сети выбирается основная сеть Ethereum (mainnet). Для изменения этого параметра, в выпадающем списке выбираем Add Custom Network / Node.

При этом откроется окно, в котором вы можете вставить информацию о RPC Server, предоставленную Ganache. Имя узла (Node Name) можно выбрать произвольное.

С этого момента локальная копия MyEtherWallet подключится к вашему блокчейн серверу на Ganache.

Воспользуемся MyEtherWallet, чтобы загрузить смарт-контракт Counter. Для этого в верхней навигационной панели нажимаем на Contracts и на открывшейся странице контрактов выбираем Deploy Contract.

Видим, что MyEtherWallet запрашивает байт-код контракта. Возвращаемся в Remix IDE и нажимаем кнопку “Details”.

При этом появится окно со множеством деталей о контракте Counter. Для того, чтобы скомпилировать байт-код, скопируйте его из параметра object раздела BYTECODE (удобнее всего скопировать весь блок при помощи соответствующей иконки, а потом удалить все лишнее).

Переносим байт-код в MyEtherWallet. Параметр Gas Limit определится автоматически.

Чуть ниже на этой же странице импортируем аккаунт для загрузки контракта. Ganache выдает десять адресов, которые мы можем использовать для взаимодействия с нашим приватным блокчейном. Для того, чтобы воспользоваться одним из них и загрузить контракт, переходим в Ganache и кликаем на иконку любого из адресов.

Копируем ключ, выбираем Private Key и вставляем значение

Теперь, если нажать Unlock, MyEtherWallet попросит нас подтвердить транзакцию.

При нажатии Sign Transaction под кнопкой добавятся Raw Transaction и Signed Transaction. Нажимаем на Deploy Contract.

Соглашаемся с предупреждением.

В результате транзакции в Ganache в разделе текущих обрабатываемых блоков (Current Blocks) число изменится с 0 на 1. Также на 1 возрастет счетчик для выбранного ключа.

Теперь смарт-контракт загружен в локальный блокчейн.

Для того, чтобы провзаимодействовать со счетчиком контракта, возвращаемся в MyEtherWallet и выбираем раздел Interact With Contract.

При выборе соответствующего раздела откроется лог всех проведенных транзакций.

При нажатии на запись о транзакции будет выведена вся информация о ней, среди которой необходимый адрес контракта – Created Contact Address.

Копируем адрес и вставляем в соответствующее поле MyEhtherWallet.

Все, что осталось – это найти ABI – то, что сообщает MyEtherWallet как взаимодействовать с нашим контрактом. Для этого возвращаемя к тому месту, где мы остановились в Remix (Details), в разделе ABI копируем информацию в буфер обмена, переносим в MyEtherWallet и нажимаем Access. При этом появится раздел Read / Write Contract, у которого при помощи выпадающего списка станет доступен выбор функций из тех, что мы записали в нашей программе.

Проверим работу смарт-контракта. В нашем коде мы инициализировали значение переменной count нулем. Для того, чтобы подтвердить корректность работы, вызовем функцию getCount() .

То есть функция работает корректно. Функция инкремента предполагает активное действие с нашей стороны – осуществление транзакции. При выборе функции нажимаем Write и соглашаемся с запросом транзакции.

В результате при новом запросе функции getCount видим 1 вместо 0 (и выросшее число транзакций в Ganache).

Аналогичным образом вы можете протестировать поведение функции decrementCount() .

Итак, мы запустили блокчейн на нашем компьютере, развернули на нем смарт-контракт и провзаимодействовали с ним. Это очень близко к тому, как на начальном этапе происходит процесс профессиональной разработки смарт-контрактов на Ethereum. Когда вы становитесь готовы к тому, чтобы другие пользователи могли взаимодействовать с вашим смарт-контрактом без использования реальных денег (как в сети mainnet), вы можете загрузить смарт-контракт в Ethereum test network, (testnet).


Solidity

Это название главного языка, который разработала команда кефира для запуска смарт-контрактов. Если вы программист, то просто пробегитесь глазами по документации языка — он неприлично простой. К слову, сделали его простым, чтобы было сложнее ошибиться в написании смарт-контракта. Так что абсолютно любой программист хотя бы уровня джуниора сможет разобраться в нем. Абсолютно нет смысла платить огромные деньги разработчикам, которые знают солидити — обучить уже существующего разработчика будет на порядок дешевле.

Смарт-контракты

… и все, что вам нужно о них знать. Пропустите эту секцию, если вы не программист. Смарт-контракт — это кусок кода. В принципе, это класс в солидити (ООП, да), у которого есть два типа функций: изменяющие состояние и не изменяющие. Ну и чтобы запускать функции в смарт-контракте просто отправив на него кефир, нужно эту функции пометить payable .

Состояние — это хранилище данных, блокчейн, епта. Контракты могут изменять блокчейн (состояние, хранилище) — но чтобы изменить блокчейн нужно заплатить кефира майнерам. Как они будут делить кефир разбирать не будем в рамках этой статьи. Оплата майнерам за запуск кода, изменяющий состояние, называется Газом (Gas). Если кто-то извне закинет кефира на адрес смарт-контракта с вызовом функции, помеченной payable , но не помеченной Constant , View или Pure , то из отправленной суммы будет вычтено нужное количество кефира для оплаты майнерам. Обычно в ERC20 токенах это функции, которые либо выдают отправителю токенов за кефир, либо переводят токены от одного держателя токенов другому.

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

А еще есть две важные штуки в солидити: множественное наследование и модификаторы функций. Про них тоже нужно знать.

Первое — просто контракты могут наследоваться одновременно с нескольких классов типа TimedCrowdsale , CappedCrowdsale , MintedCrowdsale , Ownable — при этом функции конструкторов тоже запускаются друг за другом — но это я объясню на примере уже дальше.

Второе — это возможности создавать функции, которые потом будут вставлены в другие функции. Это как простая инкапсуляция, только чуть более гибкая — это буквально шаблон функции. Когда вы создаете модификатор, вы пишете специальный символ _ там, где подразумеваете код функции, использующей этот модификатор. То есть модификаторы — это не просто инкапсулированный функционал, который возвращает значение; это — шаблон функции, когда код из модификатора буквально вставляется в функцию, использующую этот модификатор.

Перейдем к практике.

Готовим окружение

Если вы не знаете, что такое Терминал — почитайте вот эту статью. Если вы на окнах, ставьте себе Терминал через WLS. Если вы уже знакомы с Терминалом, продолжим. Алсо, сразу поставьте себе Node.js — он будет необходим для следующих шагов. Лучше ставить LTS, но, на самом деле, абсолютно без разницы, какую из современных версий ноды ставить.

Первое, что мы сразу поставим и запустим процесс синхронизации блоков — это geth . Короче, это утилита, написанная на Go, которая позволит нам запускать ноду эфира на локальном компе и коннектиться к тестовой и реальной сети. Установить можно через инсталяторы, но я крайне советую фигачить geth сразу в Терминал, как описано вот тут. Проверить, установился ли у вас норм geth , можно, запустив команду в Терминале:


Если вам выплюнуло версию geth — все в ажуре, продолжаем туториал. Если нет — хреново, исправляйте; придется, похоже, заняться любовными ласками с Терминалом и своей операционной системой — но вам не впервой, разберетесь. Как установите geth, запускайте в Терминале команду:


Это запустит процесс синхронизации вашей ноды с тестовым сервером, блоки которого можно глянуть вот тут. Проверить, синхронизировались ли вы с сетью в консоли geth можно, прописав:


Процесс синхронизации у меня занимал от 1 до 4 часов — когда как. Алсо, помимо синхронизации блоков, придется ждать еще и синхронизации состояний — это чаще дольше, чем синхронизация блоков. Также можно использовать команды geth с флагом --light — тогда синхронизация длится от нескольких секунд до минуты и вы все еще можете деплоить контракты.

Ладно, первую утилиту мы поставили — ставим следующую. Нам нужно поставить аналог geth , только совсем уж локальную симуляцию блокчейна — testrpc . Да-да, у нас 3 блокчейна:

  • testrpc — локальная симуляция блокчейна; быстрая, но ненастоящяя и хранится только у вас на машине
  • geth --testnet — уже реальный блокчейн, но тестовая сеть, где можно бесплатно получать кефир и тестить всякие непотребства, денег не потеряете
  • geth — мейннет, главный, реальный блокчейн, настоящий кефир; все по-взрослому, ошибки тут — потери реального кефира

Ставим testrpc , запустив следующую команду:


Ну или встанет сразу с трюфелем, так как теперь testrpc под крылом трюфеля и зовется ganache-cli . Хотя черт его знает, у меня все и с ванильным testrpc сработало. А если работает — не трогай, как учили меня в межгалактической академии. Можно еще его и запустить, чтобы проверить установку, прописав truffle в консоли, но у нас уже синхронизируется тестовый блокчейн — не будем ему мешать.

Ну что, разобрались с блокчейнами? Ноды теперь есть и тестовая даже синхронизируется? Ставим удобную утилиту для работы со смарт-контрактами на кефире — truffle , следующей командой:


Трюфель — это тулза, которая позволяет держать смарт-контракты в разных файлах, импортировать другие файлы, а так же компилирует ваш код смарт-контрактов в один большой байт-код (нечитаемый человеком), автоматически находит у вас локально запущенный geth (тестовый и реальный) или testrpc , деплоит ваш смарт-контракт в эту сеть. Алсо, проверяет ваш код смарт-контракта на ошибки и с недавних пор еще и дебажить помогает завершенные транзакции. Мастхев, короче.

На этом этапе у вас должны быть установлены: testrpc , geth , truffle — если чего-то из этого нет или версия не выплевывается в консоль по запросу, то поправьте это; иначе не получится у вас ничего.

Алсо, я накидал простенький баш-скриптик, который установит все за вас. Вызывается вот так:


— но я его ни разу не тестил еще, так что не уверен в его работоспособности. Однако пулл-реквестам буду только рад.

Фигачим контракт

За вас все уже придумано и написано — это хорошо. Немного головняка будет все равно — но я постараюсь вам его минимизировать. Использовать мы будем уже готовые ERC20 контракты от OpenZeppelin — это сейчас стандарт индустрии, они прошли аудит, да и вообще все их код используют. Спасибо им огромное за вклад в опенсоус.

Сделайте cd в какую-нибудь безопасную папку и после пропишите:


В этой папке и будем работать. Создадим здесь заглушку для нашего смарт-контракта:


Зашибись, четко. У нас теперь есть две очень важные папки, в которые мы и будем лезть: contracts и migrations . Первая — код наших контрактов, вторая — код для truffle, чтобы знать, что делать при деплое контрактов в блокчейн.

Дальше нам нужно забрать текущий код смарт-контрактов из npm и, собственно говоря, начать сам проект:


Отлично, код смарт-контрактов от OpenZeppelin у нас в кармане в папке node_modules/openzeppelin-solidity/contracts . Теперь заходим в главную папку contracts , удаляем там все файлы и добавляем файлы MyToken.sol и MyCrowdsale.sol — естественно, свои контракты вы назовете иначе. Первый будет контрактом на наш ERC20 Токен, а второй — контрактом нашего ICO, который будет принимать кефир и раздавать людям MyToken . Эта статья может устареть, но вы всегда можете глянуть, как OpenZeppelin предлагают вам создавать контракты у них в репозитории. Вот так у нас будет выглядеть MyToken.sol :


Найс — у вас есть смарт-контракт собственного токена (только смените названия в константах)! Можете глянуть, что там за наследование от MintableToken — но там все максимально просто. Это токен, который можно выпускать (от англ. «Mint» — чеканить), и выпускать его имеет право только владелец, так как MintableToken еще и наследуется от Ownable . Алсо, MintableToken еще и наследуется от классов ERC20 токенов, написанных OpenZeppelin, в которых и реализован интерфейс ERC20:


Ага, вот вам и весь ERC20 интерфейс. Сложно? Не думаю. Дает возможность глянуть, сколько было выпущено токенов, проверить баланс адреса и перевести токенов на другой адрес, выплюнув в сеть событие перевода для легких клиентов кефира. И все это вы получаете фор фри в вашем MyToken.sol благодаря работе OpenZeppelin — они молодцы.

А теперь перейдем к главной части нашего ICO — нам же нужно принимать кефиры и раздавать MyToken ! Вот так будет выглядеть ваш MyCrowdsale.sol :


Так-так-так, что тут у нас? Что, пацаны, смарт-контракты? Наша публичная продажа токенов наследует три самых популярных свойства: у нее есть хард-кап, больше которого собрать не получится; софт-кап, не собрав который эфиры возвращаются; время начало и конца продажи токенов. Собственно говоря, а что еще для счастья нужно?

Программисты, обратите внимание, как конструкторы классов множественного наследования выстроены в ряд и получают аргументы из главного конструктора MyCrowdsale . Алсо, мы проверяем, что хардкеп у нас выше софткепа — алес гут! Алсо, не пугайтесь туче параметров в конструкторе MyCrowdsale — мы передадим их на этапе деплоя контракта в трюфеле.

Вот и все — у вас есть готовые контракты вашего собственного ERC20 токена и даже смарт-контракт ICO, который настраивается по вашему желанию и раздает ваши токены за кефир. Алсо, его поддерживают все ERC20 кошельки — ляпота! Перейдем к ручным тестам и деплою.

Миграции

Как я уже говорил ранее, тестировать мы будем последовательно на трех блокчейн-сетях, но процесс тестирования ручками всегда будет один и тот же. Начнем с testrpc , потом перейдем к geth --testnet и дальше в geth . Соу фар мы только писали код, давайте его попробуем скомпилировать. В папке проекта пропишите:


Если все скомпилировалось без проблем — то у вас появится папочка build , в которой будет содержаться кракозябра для трюфеля, чтобы он смог задеплоить в блокчейн байт-код ваших смарт-контрактов. Перед тем, как деплоить смарт-контракты, нам нужно рассказать трюфелю, что вообще нужно делать. Деплой смарт-контрактов в трюфеле называется миграцией — ну, что же, будем придерживаться этой терминологии. Зайдите в migrations/1_initial_migration.js и измените его следующим способом:


Это тот самый файл, который будет использоваться трюфелем для деплоя контрактов. Что же мы тут такого наворотили? Во-первых, мы запросили скомпилированные MyToken и MyCrowdsale . После, мы установили константы со всеми аргументами нашего ICO — установили время начала и конца; сколько токенов будут получать люди за 1 вей кефира (0.000000000000000001 eth = 1 wei; установка decimals указывает, сколько нужно порядков wei, чтобы получить 1 ваш новоиспеченный токен); кошелек, куда придут полученные на продаже кефиры; хард-кеп и софт-кеп. Учтите, что openingTime всегда должен быть после времени текущего блока в блокчейне — иначе ваш смарт-контракт не задеплоится из-за проверки условия в TimedCrowdsale . Я на эти грабли наступал, а провалившиеся транзакции вообще никак не получается дебажить. Меняйте эти константы по своему усмотрению.

Следующий шаг — это именно деплой смарт-контрактов. Тут ничего интересного: у нас есть объект deployer , который деплоит артефакты смарт-контрактов и передает туда аргументы. Заметьте, что сначала деплоится MyToken , и только потом MyCrowdsale — и во второй передается аргументом адрес первого.

Дальше самое интересное — то, о чем не пишут ни в документации, ни в книжках. Когда вы создаете с кошелька MyToken , этот кошелек становится владельцем MyToken по суперклассу Ownable — то же самое происходит и с MyCrowdsale . Если глубоко копнуть в MintableToken , то можно увидеть, что чеканить монеты-то может только Owner ! А кто владелец MyToken ? Правильно: адрес, который его и задеплоил. А кто будет отправлять запросы на чеканку монет? Правильно: смарт-контракт MyCrowdsale . Напомню, что адрес, создавший MyToken и адрес MyCrowdsale — это два разных адреса.

Поэтому у нас добавляется неправославный третий шаг деплоя, где адрес, задеплоивший контракты ( web3.eth.accounts[0] ) вызывает функцию transferOwnership на контракте MyToken , чтобы MyCrowdsale владел MyToken и мог чеканить монеты. А MyCrowdsale все еще под владением web3.eth.accounts[0] — так что все пучком.

Заметка про web3.eth.accounts[0] : когда деплоите смарт-контракт, убедитесь, что geth или testrpc имеют правильный кошелек в web3.eth.accounts[0] — не теряйте приватный ключ к нему, хоть это никак вам не навредит, но вдруг владельцу что-нибудь потом нужно будет сделать, а ключа уже нет?

В testrpc , как правило, аккаунты создаются сразу при запуске и они сразу же разлочиваются; однако на тестовом и реальном блокчейне эфира стоит создать аккаунт через personal.newAccount() — дальше пополнить этот адрес через Faucet на тестовом блокчейне или реальным кефиром на реальном блокчейне. Не теряйте пароль и приватные ключи.

Алсо, вы можете в аккаунты добавить уже существующий кошелек, вызвав web3.personal.importRawKey('pvt_key', 'password') , но для этого нужно вызывать geth с дополнительным параметром --rpcapi="db,eth,net,web3,personal,web3" . Думаю, разберетесь.

Тестирование и деплой

Йес, контракты готовы, миграции написаны, осталось только задеплоить и проверить. Как geth (тестовый и реальный), так и testrpc управляются одинаково через truffle console — так что опишу способ проверки для testrpc и просто расскажу, как включить geth после. И так, запускаем тестовый локальный блокчейн кефира:


Эм… вот и все. У вас локально работает симуляция блокчейна кефира.

А чтобы задеплоить в тестовый блокчейн эфира, вы вместо этой команды сделаете geth --testnet --rpc . А чтобы задеплоить в реальный блокчейн эфира, вы пропишите просто geth --rpc . Флаг --rpc нужен, чтобы трюфель смог подключиться. Следующие шаги деплоя и теста более-менее одинаковы для всех трех типов блокчейна. Единственное что — после того, как вы запустите тестовый или реальный блокчейн через geth , он начнет синхронизировать блоки — а это может занять до 4-5 часов на хорошем Интернет-соединении. Ремарка про эта была в самом начале статьи. Перед деплоем смарт-контрактов рекомендую дождаться полной синхронизации. Алсо, блокчейн весит в районе 60-100 гигабайт, так что подготовьте для этого место на диске.

Алсо-алсо, убедитесь, что web3.eth.accounts[0] разлочен. Обычно можно прописать в консоли testrpc , которая открывается сразу, либо в отдельном окошке Терминала в консоли, которая открывается через geth console : eth.unlockAccount(eth.accounts[0], "Пароль, полученный при создании учетки", 24*3600) — это разлочит ваш аккаунт, который должен создать смарт-контракт

Теперь открываем новое окошко Терминала ( testrpc не закрываем — он должен работать) и прописываем в папке проекта:


Эта магическая команда скомпилирует смарт-контракт (то есть не нужно каждый раз писать truffle compile ) и задеплоит его на микро-сервер блокчейна, найденный открытым локально. Стоит отметить, что если testrpc сделает это мгновенно, то тестовый и реальный блокчейны будут гораздо дольше включать транзакцию в следующие блоки. После этого у вас должно выплюнуться нечто подобное в консольку:


Думаю, вы уже поняли, что консолька вам выдала адреса смарт-контрактов MyToken и MyCrowdsale . Все! Смарт-контракт задеплоен в тот блокчейн, микро-сервер которого у вас открыт. Осталось лишь проверить, что токены и вправду раздаются юзерам, которые присылают кефир на смарт-контракт MyCrowdsale . Прописываем в Терминале следующее, чтобы зайти в консоль трюфеля:


Прописываем следующее в теперь уже трюфеле (без комментариев только):


В случае с testrpc можно сразу же проверять снова баланс нашего кошелька, но в случае с тестовым и реальным блокчейном нужно подождать, пока транзакция наша будет включена в блок — обычно, когда это происходит, трюфель выдает вам номер транзакции. Подождали? Проверяем снова наш баланс в MyToken :


Вот и все! Сначала тестите свой контракт на testrpc , потом на geth --testnet , потом деплойте на geth . Вот и запустили вы свое собственное ICO! И не пришлось вам тратить десятки килобаксов на аудит и запуск. Накосячить с тем, что нам предоставили ребята из OpenZeppelin, на самом деле, очень сложно. А когда вы используете truffle — так разработка на солидити вообще в сказку превращается. Ну, кроме случаев, когда транзакции ревертятся еще во время выполнения на смарт-контракте — дебажить их сущий ад. Но дебаггинг смарт-контрактов, воистину, достоин отдельной статьи.

Заключение

Огромное спасибо, что дочитали до конца этой статьи! Если мне удалось сэкономить вам время или деньги, либо если вы узнали что-то новое из этой статьи, то я этому буду очень рад. Буду так же очень признателен, если поделитесь этой статьей со своими друзьями или знакомыми, которые хотят провести ICO — сэкономьте им $75,000 на недо-программистов, которые высасывают деньги из крипто-рынка, как паразиты, копи-пастя одни и те же 25 строк кода.

Удачи в разработке смарт-контрактов! Остались вопросы? Милости прошу в комментарии — с удовольствием на все отвечу и постараюсь помочь с проблемами.

Бонус

А что, если вы хотите изменить логику, по которой считается цена покупки токенов? Конечно, можно изменить правильно rate или использовать один из классов контрактов от OpenZeppelin, но вдруг вы хотите чего-нибудь еще более извращенного? В смарт-контракте можно оверрайтнуть функцию getTokenAmount следующим образом:


В общем, так можно сделать цену токена зависящей от времени покупки — чем дальше в лес, тем дороже токены. Не бойтесь экспериментировать и переписывать некоторые функции смарт-контрактов — это весело!


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

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

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

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

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

    • Фиксированные по длине типы данных (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 .

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






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

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

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

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

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

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


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

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

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


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


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

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

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

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


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

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

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

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

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


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


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


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

      Теперь следует проверить, корректно ли создался смарт-контракт. Для этого можно использовать метод 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. Разобрались, как создавать счёт, как создавать корректный смарт-контракт, получать по нему информацию и изменять его состояние, а также выяснили, как с этим смарт-контрактом взаимодействовать.

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

      Читайте также: