Учимся читать смарт-контракт Ethereum на Solidity

Смарт-контракты? Они объединяют в себе и возможность написания условий контракта, и механизм строгого их выполнения. Если условия были заданы и была подписана соответствующая транзакция или запрос, то после принятия этого запроса или транзакции уже невозможно изменить условия или повлиять на их выполнение.

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

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

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

Пример кода смарт-контракта на Solidity

contract Bank {
address owner;
mapping(address => uint) balances;

function Bank() {
owner = msg.sender;
}

function deposit() public payable {
balances[msg.sender] += msg.value;
}

function withdraw(uint amount) public {
if (balances[msg.sender] >= amount) {
balances[msg.sender] -= amount;
msg.sender.transfer(amount);
}
}

function getMyBalance() public view returns(uint) {
return balances[msg.sender];
}

function kill() public {
if (msg.sender == owner)
selfdestruct(owner);
}
}

 

Выше приведен упрощенный исходный код, который может удерживать монеты пользователей и возвращать их по требованию.

Итак, есть смарт-контракт Bank, который выполняет следующие функции: он накапливает на своем балансе монеты, то есть при подтверждении транзакции и размещении такого смарт-контракта создается новый аккаунт, который может содержать на своем балансе монеты; он запоминает пользователей и распределение монет между ними; имеет несколько методов управления балансами, то есть имеется возможность пополнения, вывода и проверки баланса пользователя.

Давайте пройдемся по каждой строке исходного кода. В этом контракте есть константные поля. Одно из них, с типом address, называется owner. Здесь контракт запоминает адрес пользователя, создавшего этот смарт-контракт. Далее, есть динамическая структура, которая сохраняет в себе соответствия между адресами пользователей и балансами.

После этого следует метод Bank — он называется так же, как и контракт. Соответственно, это его конструктор. Здесь происходит присвоение переменной owner адреса того, кто разместил этот смарт-контракт в сети. Это единственное, что происходит в этом конструкторе. То есть msg в данном случае — это именно те данные, которые были переданы виртуальной машине вместе с транзакцией, содержащей весь код этого контракта. Соответственно, msg.sender — это автор данной транзакции, которая размещает этот код. Он и будет владельцем смарт-контракта.

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

Следующий метод называется withdraw и он принимает один параметр — ту сумму монет, которую кто-то хочет вывести из этого банка. Здесь идет проверка, достаточно ли монет на балансе пользователя, который вызывает этот метод, чтобы их отправить. Если их достаточно, тогда сам смарт-контракт возвращает вызывающему это количество монет.

Далее идет метод проверки текущего баланса пользователя. Тот, кто вызывает этот метод, будет использоваться для получения этого баланса в смарт-контракте. Стоит отметить, что модификатор этого метода — view. Это означает, что сам метод никак не меняет переменные своего класса и он фактически является только методом чтения. Отдельная транзакция не создается для вызова этого метода, комиссия не платится, а все вычисления выполняются локально, после чего пользователь получает результат.

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


Комментарии: