Адреса, булевы значения и байты
Адрес — это идентичность в Ethereum: 20 байт, по которым находят кошельки и контракты.
Половина логики контракта — это ответ на вопрос «кто меня вызвал?». А отвечает на него типaddressи переменнаяmsg.sender.
Тип address хранит 20-байтовый адрес — кошелька или контракта. У него есть свойства: balance (баланс в wei) и методы для отправки ETH. Особый подтип address payable — это адрес, которому разрешено отправлять эфир методами transfer, send, call. Обычный address деньги получать «напрямую» через эти методы не может — нужно явное приведение.
Булевы и байты
bool — стандартные true/false. bytes32 — фиксированный массив из 32 байт, часто используется для хэшей и коротких идентификаторов; он дешевле, чем динамический. bytes и string — динамические: длина не фиксирована, хранятся дороже. string — это по сути UTF-8 байты без удобной индексации.
address : 0x71C7...d8976F (20 байт) -> кошелёк/контракт bytes32 : 0xabcd...0000 (32 байта, фикс.) -> хэш, ключ bytes : 0x48656c6c6f (динамич.) -> произвольные данные string : "Привет" (UTF-8 байты) -> текст bool : true / false
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
contract Identity {
address public owner;
bool public active;
bytes32 public secretHash;
constructor() {
owner = msg.sender; // кто задеплоил — тот владелец
active = true;
}
function balanceOfOwner() public view returns (uint256) {
return owner.balance; // баланс адреса в wei
}
function setHash(string memory word) public {
secretHash = keccak256(abi.encodePacked(word)); // хэш в bytes32
}
}
Как работает под капотом (EVM/газ)
Адрес внутри EVM хранится в тех же 256-битных словах, просто старшие байты нулевые. bytes32 идеально ложится в один слот storage — отсюда его дешевизна. А string/bytes хранят длину и данные отдельно, для длинных значений это несколько слотов. Хэш keccak256 — основной криптографический примитив Ethereum: он детерминирован и помещается ровно в bytes32.
# Та же логика на Python: фикс. байты дешевле динамических
import hashlib
def keccak_like(word):
# имитация: 32-байтовый хэш как ключ фиксированного размера
return hashlib.sha256(word.encode("utf-8")).hexdigest()[:64]
owner = "0x71C7656EC7 ... d8976F" # 20 байт-адрес
active = True
secret_hash = keccak_like("Привет") # всегда 64 hex = 32 байта
print("owner:", owner)
print("active:", active)
print("hash(32 байта):", secret_hash)
print("длина строки фиксирована? ", len(secret_hash) == 64)
«Та же логика на Python ▶». Хэш всегда занимает фиксированный размер независимо от длины входа — поэтому в storage его держать предсказуемо дёшево.
Частые ошибки
- Пытаться отправить ETH на обычный
addressвместоaddress payable— компилятор не пропустит. - Сравнивать строки через
==— так нельзя; сравнивают хэши:keccak256(a) == keccak256(b). - Хранить длинные строки в storage без нужды — это дорого; часто достаточно хранить хэш или вынести текст в события/метаданные.
Best practices
- Для идентификаторов и хэшей используйте
bytes32вместоstring— один слот, дёшево и предсказуемо. - Проверяйте адреса на
address(0)перед важными операциями: нулевой адрес часто означает ошибку или сжигание. - Не доверяйте
tx.originдля авторизации — используйтеmsg.sender(подробнее в разделе безопасности).
Единицы эфира и глобальные переменные
Раз уж мы говорим про адреса и деньги, важно знать единицы. Самая мелкая единица эфира — wei; в одном ETH ровно 10^18 wei. Все суммы внутри EVM считаются в wei, потому что дробей нет: «полэфира» — это 5 * 10^17 wei. Solidity даёт удобные суффиксы wei, gwei и ether, так что можно написать 1 ether вместо длинного числа. Рядом с адресами почти всегда фигурируют глобальные переменные контекста: msg.sender (кто вызвал), msg.value (сколько wei прислано с вызовом), block.timestamp (время блока) и address(this) (адрес самого контракта). Эти величины — основной «вход» данных в контракт: именно из них логика узнаёт, кто и с какими деньгами к ней обратился, и на них же строятся все проверки доступа.
Итоги
address описывает идентичность, address payable умеет принимать ETH, bool — флаги, bytes32 — дешёвые фиксированные данные и хэши, а string/bytes — дорогие динамические. Дальше разберём область видимости и константы переменных состояния.