Выходные прошли и пора возвращаться к рабочим ритмам.
С прошлым постом я забыл дать прикрепить ссылку к оригинальной статье, поэтому исправляюсь и выделяю ее отдельно:
https://www.rareskills.io/post/solidity-metadata
Вообще у RareSkills очень хороший всегда материал и, при изучении каакой-либо темы, рекомендую искать подборки там.
А сейчас мы продолжаем разговор о metadata.
Расшифровка metadata
Давайте посмотрим на гекс в синей рамке скрина из предыдущего поста:
>>> bytes.fromhex("69706673").decode("ASCII")
'ipfs'Далее рассмотрим код в красном поле:
>>> bytes.fromhex("736f6c63").decode("ASCII")
'solc'Это дает нам подсказку о том, что содержат эти данные: хэш IPFS и версию компилятора solidity.
Хэш IPFS
Раздел, подчеркнутый желтым, вместе с бирюзовой рамкой можно поместить в следующий python-скрипт (обратите внимание, что мы используем версию кода с комментарием // nothing):
import base58
hex_ipfs_hash = "12206a68b6b8bcc01ba559ec3adf7a387b6c4210a5dc69a05d038e9d17cae3fa373b"
bytes_str = bytes.fromhex(hex_ipfs_hash)
print(base58.b58encode(bytes_str).decode("utf-8"))
# QmVW2XyafSxDtiSqirJRauuT5SaQtGnQYsxxyYHrFmRTEa
Qm...RTEa - это IPFS-хэш файла метаданных, созданного компилятором. Этот участок кода (бирюзовый и желтый) кодируется иначе, чем поля выше. В частности, IPFS-хэш (бирюзовый и желтый) представляет собой закодированную в base58 версию шестнадцатеричных данных «1220...RTEa».
Это хэш IPFS, который вы получите, если поместите JSON-файл из компилятора Solidity на IPFS. На скрине этого поста файл JSON, о котором идет речь.
Мы можем сохранить JSON-файл как реальный файл, а затем проверить, что хэш совпадает с тем, который мы создали в python выше. Вам понадобится установленный инструмент командной строки ipfs (как установить).
mkdir out
solc --optimize-runs 1000 --bin --metadata C.sol --output-dir out
# Compiler run successful. Artifact(s) can be found in directory "out".
ipfs add -qr --only-hash out/Empty_meta.json
# QmVW2XyafSxDtiSqirJRauuT5SaQtGnQYsxxyYHrFmRTEa
Это совпадает с хэшем, полученным ранее.
Не приведет ли это к коллизиям хэшей?
Если два контракта с идентичным исходным кодом и конфигурацией компилятора хранят свой проверенный исходный код на IPFS, хэши IPFS будут сталкиваться (clash), но это желательно, потому что это экономит место storage. Смарт-контракты однозначно идентифицируются по комбинации идентификатора цепочки и их адреса, а не по содержимому IPFS.
Получение версии solidity
Наконец, если мы преобразуем секцию в оранжевой рамке, то получим версию solidity.
>>> 0x00 # solidity is version 0
0
>>> 0x08 # major version
8
>>> 0x14 # minor version
20
# correct, we used solidity 0.8.20
Зачем нужны метаданные смарт-контракта?
Эти метаданные добавляют дополнительные 53 байта к стоимости развертывания, что означает дополнительные 10 600 газа (200 на байткод) + стоимость calldata (16 газа на ненулевой байт, 4 газа на нулевой байт). Это означает до 848 дополнительных газа к стоимости calldata.
Так зачем это включать?
Это позволяет строго проверять код смарт-контракта. В метаданные JSON, которые выводит компилятор, входит хэш исходного кода. Поэтому если исходный код немного изменится, то изменится и JSON-файл метаданных, и его IPFS-хэш изменится.
Один странный трюк для снижения расхода газа через хэш IPFS
Один из очевидных способов оптимизировать затраты на газ во время развертывания - использовать опцию --no-cbor-metadata. Но если вам это нужно для проверки контракта, то вы все равно можете снизить стоимость газа, добывая хэши IPFS, в которых много нулевых байтов.
Когда контракт будет развернут, нулевые байты уменьшат стоимость calldata. Поскольку исходный код хэшируется, включая комментарии, это означает, что можно добывать комментарии, которые приводят к газоэффективным хэшам IPFS, которые будут добавлены к контракту. Обратите внимание, это означает, что мы хотим, чтобы в шестнадцатеричном представлении хэша были нули, а не в кодировке base58.
#metadata
