Описание контрактов ERC721 и NFT. Часть 3
Далее пройдем по более сложным функциям контракта, оставив самые сложные на отдельный пост.
Итак, функция approve(), в которой мы принимаем адрес (кому мы одобряем использование нашего NFT) и сам id токена. В функции нам нужно получить адрес владельца данного токена, проверить, что msg.sender является либо владельцем, либо имеет разрешение на токен, и уже после добавить в mapping разрешение на данный токен данному адресу.
В функции setApprovalForAll() мы принимаем оператора (или адрес магазина) и булево значение, и сперва проверяем, что msg.sender не равен адресу магазина, так как нельзя выписывать права самому себе. Далее мы говорим, что даем разрешение данному оператору на управление нашими токенами.
Далее идут сразу две служебные функции _safeMint(), с разным количеством принимаемых аргументов. В первой мы получаем только адрес, куда следует отправить созданные токены, id токена, и перенаправляем ее во второй _safeMint() вместе с новым аргументом bytes.
Во втором _safeMint() принимаем уже три агрумента: адрес, id и bytes. Внутри вызываем функцию _mint() и делаем проверку на получающего данный NFT с помощью служебной функции _checkOnERC721Received(), о которой поговорим позже.
В _mint() принимаем адрес и id токена, проверяем, чтобы данный адрес не был нулевым, а затем устанавливаем владельца токена в mapping и увеличиваем баланс владельца.
Если честно, я сам не понял, зачем создаются две функции _safeMint. Полагаю, что это было сделано на случай, если потребуются передать дополнительные аргументы (bytes). Если же нет - функция передает пустое значение.
У меня не так много опыта в выпуске NFT, но уверен, что когда в практике столкнусь с данной проблемой, то опишу ее подробнее на канале.
Также сейчас стоит упомянуть функцию supportsInterface(), которую мы получаем из наследуемого интерфейса IERC165. В ней мы просто говорим, что наш контракт работает с интерфейсом IERC721.
#erc721 #nft
Далее пройдем по более сложным функциям контракта, оставив самые сложные на отдельный пост.
Итак, функция approve(), в которой мы принимаем адрес (кому мы одобряем использование нашего NFT) и сам id токена. В функции нам нужно получить адрес владельца данного токена, проверить, что msg.sender является либо владельцем, либо имеет разрешение на токен, и уже после добавить в mapping разрешение на данный токен данному адресу.
В функции setApprovalForAll() мы принимаем оператора (или адрес магазина) и булево значение, и сперва проверяем, что msg.sender не равен адресу магазина, так как нельзя выписывать права самому себе. Далее мы говорим, что даем разрешение данному оператору на управление нашими токенами.
Далее идут сразу две служебные функции _safeMint(), с разным количеством принимаемых аргументов. В первой мы получаем только адрес, куда следует отправить созданные токены, id токена, и перенаправляем ее во второй _safeMint() вместе с новым аргументом bytes.
Во втором _safeMint() принимаем уже три агрумента: адрес, id и bytes. Внутри вызываем функцию _mint() и делаем проверку на получающего данный NFT с помощью служебной функции _checkOnERC721Received(), о которой поговорим позже.
В _mint() принимаем адрес и id токена, проверяем, чтобы данный адрес не был нулевым, а затем устанавливаем владельца токена в mapping и увеличиваем баланс владельца.
Если честно, я сам не понял, зачем создаются две функции _safeMint. Полагаю, что это было сделано на случай, если потребуются передать дополнительные аргументы (bytes). Если же нет - функция передает пустое значение.
У меня не так много опыта в выпуске NFT, но уверен, что когда в практике столкнусь с данной проблемой, то опишу ее подробнее на канале.
Также сейчас стоит упомянуть функцию supportsInterface(), которую мы получаем из наследуемого интерфейса IERC165. В ней мы просто говорим, что наш контракт работает с интерфейсом IERC721.
#erc721 #nft
Описание контрактов ERC721 и NFT. Часть 4
Особый интерес в этом контракте представляет функция _checkOnERC721Received().
Она принимает такие аргументы, как адрес отправителя, адрес получателя, id токена и некоторые данные в формате bytes, и нужна для того, чтобы проверить, куда мы отправляем наш NFT. В случае, если отправка идет на обычный адрес пользователя, то все ок, однако с адресами контрактов несколько сложнее.
С помощью условия "to.code.length > 0" мы проверяем, что "to" является все таки адресом контракта.
Далее, с помощью ранее подключенного интерфейса IERC721Receiver, на адрес получателя мы вызываем функцию onERC721Received() и передаем аргументы отправителя, получателя, id токена и данные.
В случае, если приходит правильный ответ, то это говорит о том, что контракт может принимать токен, в противном случае мы получаем ошибку, вариантов коей может быть два.
В первом случае контракт получателя совсем не работает с NFT и нам возвращаются пустые данные. А во втором, контракт работает с NFT, но по каким-то причинам не может принять наш токен.
И вот в первом случае мы просто выводим ошибку и откатываем транзакцию, а во втором - принимаем ошибку с помощью assembly и также возвращаем NFT.
#erc721 #nft
Особый интерес в этом контракте представляет функция _checkOnERC721Received().
Она принимает такие аргументы, как адрес отправителя, адрес получателя, id токена и некоторые данные в формате bytes, и нужна для того, чтобы проверить, куда мы отправляем наш NFT. В случае, если отправка идет на обычный адрес пользователя, то все ок, однако с адресами контрактов несколько сложнее.
С помощью условия "to.code.length > 0" мы проверяем, что "to" является все таки адресом контракта.
Далее, с помощью ранее подключенного интерфейса IERC721Receiver, на адрес получателя мы вызываем функцию onERC721Received() и передаем аргументы отправителя, получателя, id токена и данные.
В случае, если приходит правильный ответ, то это говорит о том, что контракт может принимать токен, в противном случае мы получаем ошибку, вариантов коей может быть два.
В первом случае контракт получателя совсем не работает с NFT и нам возвращаются пустые данные. А во втором, контракт работает с NFT, но по каким-то причинам не может принять наш токен.
И вот в первом случае мы просто выводим ошибку и откатываем транзакцию, а во втором - принимаем ошибку с помощью assembly и также возвращаем NFT.
#erc721 #nft
Описание контрактов ERC721 и NFT. Часть 5
Также в нашем контракте есть служебные функции _safeTransfer() и _transfer().
В первой принимаются аргументы отправителя, получателя, номер токена и другие данные. Тут вызывается другая функция _transfer() и используется _checkOnERC721Received, чтобы проверить, можно ли отправлять токен.
А во второй проверяется владелец токена и адрес отправителя. В mapping добавляются и отнимаются балансы, а также присваивается токен новому владельцу. Все просто, как и в ERC20.
Ну и последние две функции это _baseURI() и tokenURI(), которые возвращают url нашего токена.
_baseURI() - просто возвращает адрес хранилища, если он есть, к которому после нужно добавить идентификатор токена в tokenURI().
Более того, в уроке приводится дополнительный контракт ERC721URIStorage.sol, который расширяет работу с url токена.
В нем создается отдельный mapping, где хранятся id токена и сами url.
Функция tokenURI() переопределяется, но по сути ничего не меняется в выдаче результатов.
Добавляется функция _setTokenURI(), которая устанавливает в mapping новый url токена, и функция _burn(), которая удаляет его оттуда. Надо заметить, что _burn() еще вызывает аналогичную функцию в родительском контракте.
#erc721 #nft
Также в нашем контракте есть служебные функции _safeTransfer() и _transfer().
В первой принимаются аргументы отправителя, получателя, номер токена и другие данные. Тут вызывается другая функция _transfer() и используется _checkOnERC721Received, чтобы проверить, можно ли отправлять токен.
А во второй проверяется владелец токена и адрес отправителя. В mapping добавляются и отнимаются балансы, а также присваивается токен новому владельцу. Все просто, как и в ERC20.
Ну и последние две функции это _baseURI() и tokenURI(), которые возвращают url нашего токена.
_baseURI() - просто возвращает адрес хранилища, если он есть, к которому после нужно добавить идентификатор токена в tokenURI().
Более того, в уроке приводится дополнительный контракт ERC721URIStorage.sol, который расширяет работу с url токена.
В нем создается отдельный mapping, где хранятся id токена и сами url.
Функция tokenURI() переопределяется, но по сути ничего не меняется в выдаче результатов.
Добавляется функция _setTokenURI(), которая устанавливает в mapping новый url токена, и функция _burn(), которая удаляет его оттуда. Надо заметить, что _burn() еще вызывает аналогичную функцию в родительском контракте.
#erc721 #nft
Описание контрактов ERC721 и NFT. Часть 6
Ну, и в завершении нашего сегодняшнего изучения ERC721 стоить сказать пару слов о Enumerable контракте, о котором лектора спрашивают в уроке.
Enumerable, как и URIStorage, расширяют функционал основного контракта. В частности этот добавляет работу с токенами по индексу.
Здесь создаются mapping, которые хранят индексы всех токенов, индексы токенов на разных адресах и владельцы токенов по индексу.
Также добавляются функции, которые возвращают общее количество всех токенов, которые были созданы, поиск токена по индексу и поиск владельца по индексу токена.
Переопределяется функция _beforeTokenTransfer(), и добавляются несколько служебных фукнций для управления mapping.
Добавление Enumerable контракта является более сложной организацией работы с NFT, которую используют крупные компании на мировом рынке. Для выпуска своего NFT будет достаточно базовых функций, которые мы сегодня прошли.
#erc721 #nft
Ну, и в завершении нашего сегодняшнего изучения ERC721 стоить сказать пару слов о Enumerable контракте, о котором лектора спрашивают в уроке.
Enumerable, как и URIStorage, расширяют функционал основного контракта. В частности этот добавляет работу с токенами по индексу.
Здесь создаются mapping, которые хранят индексы всех токенов, индексы токенов на разных адресах и владельцы токенов по индексу.
Также добавляются функции, которые возвращают общее количество всех токенов, которые были созданы, поиск токена по индексу и поиск владельца по индексу токена.
Переопределяется функция _beforeTokenTransfer(), и добавляются несколько служебных фукнций для управления mapping.
Добавление Enumerable контракта является более сложной организацией работы с NFT, которую используют крупные компании на мировом рынке. Для выпуска своего NFT будет достаточно базовых функций, которые мы сегодня прошли.
#erc721 #nft
Описание контрактов ERC721 и NFT. Часть 7
Забыл написать, про контракт, где реализуется ERC721.
В файлах он идет под названием MyToken.sol.
Итак, в нем мы подключаем три других контракта для наследования функций:
import "./ERC721.sol";
import "./ERC721Enumerable.sol";
import "./ERC721URIStorage.sol";
Далее создаем переменные для сохранения владельца и id токена.
В конструкторе вызываем контракт ERC721 и передаем туда имя токена и его символ, а внутри устанавливаем владельца.
Дальше, через функцию safeMint(), в которой принимаем адрес получателя и другие данные, создаем NFT через служебные функции _safeMint() и _setTokenURI(). В конце, увеличиваем id токена для последующего минта.
Также, с помощью supportsInterface() говорим, что поддерживаем интерфейсы ERC721 и ERC721Enumerable.
Устанавливаем url адрес в _baseURI() и tokenURI().
И в конце, добавляем функцию для уничтожения нашего токена _burn().
Если вы все же решили использовать Enumerable контракты, то нужно переопределить функцию _beforeTokenTransfer(), вызывая в нем эту же функцию из контракта выше (используя super).
Вот и все!
ERC721 достаточно сложный контракт для тех, кто впервые столкнулся с ним. Однако, посидев с ним несколько часов, вы сможете лучше ориентироваться в коде и уже самостоятельно использовать новые контракты, которые смогут улучшиться ваш NFT.
#erc721 #nft
Забыл написать, про контракт, где реализуется ERC721.
В файлах он идет под названием MyToken.sol.
Итак, в нем мы подключаем три других контракта для наследования функций:
import "./ERC721.sol";
import "./ERC721Enumerable.sol";
import "./ERC721URIStorage.sol";
Далее создаем переменные для сохранения владельца и id токена.
В конструкторе вызываем контракт ERC721 и передаем туда имя токена и его символ, а внутри устанавливаем владельца.
Дальше, через функцию safeMint(), в которой принимаем адрес получателя и другие данные, создаем NFT через служебные функции _safeMint() и _setTokenURI(). В конце, увеличиваем id токена для последующего минта.
Также, с помощью supportsInterface() говорим, что поддерживаем интерфейсы ERC721 и ERC721Enumerable.
Устанавливаем url адрес в _baseURI() и tokenURI().
И в конце, добавляем функцию для уничтожения нашего токена _burn().
Если вы все же решили использовать Enumerable контракты, то нужно переопределить функцию _beforeTokenTransfer(), вызывая в нем эту же функцию из контракта выше (используя super).
Вот и все!
ERC721 достаточно сложный контракт для тех, кто впервые столкнулся с ним. Однако, посидев с ним несколько часов, вы сможете лучше ориентироваться в коде и уже самостоятельно использовать новые контракты, которые смогут улучшиться ваш NFT.
#erc721 #nft
Урок 25 - Rinkeby, Etherscan, Alchemy
Всем привет!
И сразу к хорошим новостям! Еще не улеглись полученные знания после вчерашнего разбора ERC721, как лектор будет радовать нас новым крутым стримом по ERC1155, который призван заменить 721, и позволяет создавать уникальные и не уникальные токены!
Стрим будет 08 сентября в 19:00 по московскому времени на канале Ильи. Там вы сможете задать вопросы напрямую! Всем советую подключиться!
Ну, а мы сегодня продолжаем наше обучение и поговорим о деплое контрактов в тестовые сети, типа Rinkeby. Также рассмотрим один из популярных сервисов Alchemy.
Новый видео урок!
В зарубежных вакансиях часто проскальзывает пункт, что разработчику нужно уметь загружать свои контракты в тестовые сети и работать с одним из сервисов, который позволяет делать это.
Именно поэтому данное видео будет интересно еще и со стороны поиска работы!
Всем приятного дня и легкого обучения!
#урок #rinkeby #etherscan #alchemy
Всем привет!
И сразу к хорошим новостям! Еще не улеглись полученные знания после вчерашнего разбора ERC721, как лектор будет радовать нас новым крутым стримом по ERC1155, который призван заменить 721, и позволяет создавать уникальные и не уникальные токены!
Стрим будет 08 сентября в 19:00 по московскому времени на канале Ильи. Там вы сможете задать вопросы напрямую! Всем советую подключиться!
Ну, а мы сегодня продолжаем наше обучение и поговорим о деплое контрактов в тестовые сети, типа Rinkeby. Также рассмотрим один из популярных сервисов Alchemy.
Новый видео урок!
В зарубежных вакансиях часто проскальзывает пункт, что разработчику нужно уметь загружать свои контракты в тестовые сети и работать с одним из сервисов, который позволяет делать это.
Именно поэтому данное видео будет интересно еще и со стороны поиска работы!
Всем приятного дня и легкого обучения!
#урок #rinkeby #etherscan #alchemy
YouTube
Hardhat, Ethers.js, Rinkeby, Alchemy, Etherscan
ХОТИТЕ СТАТЬ РАЗРАБОТЧИКОМ Solidity, узнать об Ethereum, блокчейне и многом другом ещё больше?!
Мои друзья из GUIDE DAO (бывшая школа MCS) предлагают скидку 0,1 ETH на ВСЕ СВОИ БУТКЕМЫ ПО КРИПТЕ! Материалы этих буткемов подготовлены мной и другими специалистами:…
Мои друзья из GUIDE DAO (бывшая школа MCS) предлагают скидку 0,1 ETH на ВСЕ СВОИ БУТКЕМЫ ПО КРИПТЕ! Материалы этих буткемов подготовлены мной и другими специалистами:…
Деплой контракта в сеть Hardhat
Вообще, как я понял из уроков, есть два типа деплоя контрактов:
1. Деплой в hardhat для проведения тестов с функциями контрактов;
2. Общий деплой в блокчейн;
Разница лишь в том, что для тестов мы разворачиваем контракт каждый раз для каждого теста, а в общем деплое - один раз. При этом за пределами hardhat, в тестовых сетях типа Rinkeby, контракт загружается по примеру mainnet - один раз и его нельзя уже редактировать или удалять.
Для деплоя контракта используется уже знакомый нам код:
async function main() {
const [signer] = await hre.ethers.getSigners();
const Lock = await hre.ethers.getContractFactory("Lock", signer);
const lock = await Lock.deploy();
await lock.deployed();
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
Нужно сказать, что чаще всего код для деплоя в сеть пишут в файле с таким же названием - deploy.js.
После этого, вам нужно скомпилировать ваш контракт с помощью команды npx hardhat compile, и далее развернуть его в сеть с помощью:
npx harhat run noscripts\deploy.js --network localhost
Все! Теперь можно создать другой файл, подключить в него ethers.js и проводить какие-либо работы с развернутым контрактом уже в сети hardhat.
#deploy #hardhat
Вообще, как я понял из уроков, есть два типа деплоя контрактов:
1. Деплой в hardhat для проведения тестов с функциями контрактов;
2. Общий деплой в блокчейн;
Разница лишь в том, что для тестов мы разворачиваем контракт каждый раз для каждого теста, а в общем деплое - один раз. При этом за пределами hardhat, в тестовых сетях типа Rinkeby, контракт загружается по примеру mainnet - один раз и его нельзя уже редактировать или удалять.
Для деплоя контракта используется уже знакомый нам код:
async function main() {
const [signer] = await hre.ethers.getSigners();
const Lock = await hre.ethers.getContractFactory("Lock", signer);
const lock = await Lock.deploy();
await lock.deployed();
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
Нужно сказать, что чаще всего код для деплоя в сеть пишут в файле с таким же названием - deploy.js.
После этого, вам нужно скомпилировать ваш контракт с помощью команды npx hardhat compile, и далее развернуть его в сеть с помощью:
npx harhat run noscripts\deploy.js --network localhost
Все! Теперь можно создать другой файл, подключить в него ethers.js и проводить какие-либо работы с развернутым контрактом уже в сети hardhat.
#deploy #hardhat
Немного о сетях и сервисах
Самое главное, что нужно знать о тестовых сетях Эфира то, что на данный момент информация во многих роликах о деплое контрактов уже устарела.
Ранее существовали популярные тестовые сети:
1. Rinkeby
2. Ropsten
3. Kiln
4. Kovan
Так вот, они будут удалены из-за слияния сетей Эфира в середине сентября 2022 года. Другими словами, их не нужно использовать вообще!
На их смену придут две новые сети:
1. Gorly
2. Sepolia
Они, вероятнее всего, станут основными тестовыми сетями для Эфира и всех токенов на его основе.
Поэтому в видео уроке необходимо взять общий принцип разворачивания СК, а не пример с Rinkeby.
Также существует несколько сервисов, которые помогают разворачивать контракты в тестовых сетях и взаимодействовать с ними. Самыми популярными являются
1. Alchemy
2. Infura
Оба бесплатные, но с ограничениями. Для обучения подходят оба. Да и в вакансиях чаще всего встречаются только эти два.
В принципе, ничего сложного с регистрацией и использованием этих сервисов я не нашел. Если вам потребуется, я поищу дополнительный материал по этим темам.
Далее перейдем к деплою контракта и env.
#infura #rinkeby #ropsten #alchemy #gorly #sepolia
Самое главное, что нужно знать о тестовых сетях Эфира то, что на данный момент информация во многих роликах о деплое контрактов уже устарела.
Ранее существовали популярные тестовые сети:
1. Rinkeby
2. Ropsten
3. Kiln
4. Kovan
Так вот, они будут удалены из-за слияния сетей Эфира в середине сентября 2022 года. Другими словами, их не нужно использовать вообще!
На их смену придут две новые сети:
1. Gorly
2. Sepolia
Они, вероятнее всего, станут основными тестовыми сетями для Эфира и всех токенов на его основе.
Поэтому в видео уроке необходимо взять общий принцип разворачивания СК, а не пример с Rinkeby.
Также существует несколько сервисов, которые помогают разворачивать контракты в тестовых сетях и взаимодействовать с ними. Самыми популярными являются
1. Alchemy
2. Infura
Оба бесплатные, но с ограничениями. Для обучения подходят оба. Да и в вакансиях чаще всего встречаются только эти два.
В принципе, ничего сложного с регистрацией и использованием этих сервисов я не нашел. Если вам потребуется, я поищу дополнительный материал по этим темам.
Далее перейдем к деплою контракта и env.
#infura #rinkeby #ropsten #alchemy #gorly #sepolia
Настройка и использование .env
ENV (environment variables) - это особые переменные рабочей среды. Другими словами, это некие глобальные значения, расположенные на уровне операционной системы, доступные программам, например настройки системы.
В нашем примере, их используют для того, чтобы скрыть некоторые, особо важные участки кода, как например приватный ключ в Метамаск.
Устанавливается он при помощи команды в консоли:
npm install dotenv --save
Или как было показано в видео: через файл hardhat.config.json и команды в консоли после - npm install.
Затем в тот же файл hardhat.config добавляете строку подключения:
require('dotenv').config()
Далее вы заходите или создаете папку .env в корневом каталоге проекта и записываете переменные (в нашем случае ключи и доступы), например так:
S3_BUCKET="YOURS3BUCKET"
SECRET_KEY="YOURSECRETKEYGOESHERE"
Также проверьте, что в файле gitingnore есть запись ".env", чтобы случайно ваши пароли и ключи не попали в открытый доступ.
После всех этих действий, вы можете использовать созданные переменные в других файлах. Для этого, в месте, где хотите использовать env переменную, ставите фигурные скобки и записываете по примеру:
{process.env.API_KEY} - где API_KEY - имя вашей переменной.
Так легко и просто вы можете защищать свои данные на видео, в репозиториях, на слайдах и т.д.
#env
ENV (environment variables) - это особые переменные рабочей среды. Другими словами, это некие глобальные значения, расположенные на уровне операционной системы, доступные программам, например настройки системы.
В нашем примере, их используют для того, чтобы скрыть некоторые, особо важные участки кода, как например приватный ключ в Метамаск.
Устанавливается он при помощи команды в консоли:
npm install dotenv --save
Или как было показано в видео: через файл hardhat.config.json и команды в консоли после - npm install.
Затем в тот же файл hardhat.config добавляете строку подключения:
require('dotenv').config()
Далее вы заходите или создаете папку .env в корневом каталоге проекта и записываете переменные (в нашем случае ключи и доступы), например так:
S3_BUCKET="YOURS3BUCKET"
SECRET_KEY="YOURSECRETKEYGOESHERE"
Также проверьте, что в файле gitingnore есть запись ".env", чтобы случайно ваши пароли и ключи не попали в открытый доступ.
После всех этих действий, вы можете использовать созданные переменные в других файлах. Для этого, в месте, где хотите использовать env переменную, ставите фигурные скобки и записываете по примеру:
{process.env.API_KEY} - где API_KEY - имя вашей переменной.
Так легко и просто вы можете защищать свои данные на видео, в репозиториях, на слайдах и т.д.
#env
Пример деплоя контракта в сеть Goerli
И наконец, давайте попробуем загрузить наш контракт в тестовую сеть goerli.
Хочу уточнить, что после тестов мне больше понравился Alchemy, поэтому я буду использовать в примере его сервис.
Итак, на данный момент, вы должны были уже зарегистрироваться в Alchemy на официальном сайте и создать env файл.
Заходим в Alchemy и кликаем на кнопку Create App. Появляется окошко с полями. Там мы вводим название проекта, его описание, а также в поле Chain должен значиться Ethereum и в Network - Goerly.
С помощью Alchemy можно загружать контракты и в другие блокчейн сети, как Solana или Polygon, но мы работаем именно с Эфиром.
После этого создастся ваш проект. В рамках поля проекта ищите кнопку View key и нажимаете на нее. Копируете API key в свой env файл в новую переменную, например API_KEY.
Теперь заходим на сайт Метамаск и скачиваем приложение для Chrome.
Запишите, сохраните, сфотографируйте секретную фразу восстановления МетаМаск!!! Это очень важно! Если вдруг вы забудете пароль, это будет единственный способ восстановить доступ!
После установки и регистрации, открываете приложение и в самом верху выбираете "Тестовая сеть Goerly".
Рядом с названием вашего аккаунта будет меню (три точки), нажимаете их, выбираете реквизиты счета, экспорт закрытого ключа, вводите еще раз свой пароль, копируете свой закрытый ключ и вставляете его в новую переменную в env файле, например META_KEY.
Теперь идем в папку нашего проекта и открываем файл hardhat.config.json.
В раздел module.exports добавляем код networks, как в примере лектора в уроке или как представлено ниже, чтобы в итоге он выглядел так:
module.exports = {
solidity: "0.8.9",
networks: {
goerli: {
url:
accounts: [process.env.META_KEY]
}
}
};
И вот после всех этих действий, мы можем загрузить свой проект в goerly, выполнив команду в консоли:
npx harhat run noscripts\deploy.js --network goerly
В вашем проекте на Alchemy должен появиться новый контракт, если все прошло как надо.
#goerly #metamask #alchemy
И наконец, давайте попробуем загрузить наш контракт в тестовую сеть goerli.
Хочу уточнить, что после тестов мне больше понравился Alchemy, поэтому я буду использовать в примере его сервис.
Итак, на данный момент, вы должны были уже зарегистрироваться в Alchemy на официальном сайте и создать env файл.
Заходим в Alchemy и кликаем на кнопку Create App. Появляется окошко с полями. Там мы вводим название проекта, его описание, а также в поле Chain должен значиться Ethereum и в Network - Goerly.
С помощью Alchemy можно загружать контракты и в другие блокчейн сети, как Solana или Polygon, но мы работаем именно с Эфиром.
После этого создастся ваш проект. В рамках поля проекта ищите кнопку View key и нажимаете на нее. Копируете API key в свой env файл в новую переменную, например API_KEY.
Теперь заходим на сайт Метамаск и скачиваем приложение для Chrome.
Запишите, сохраните, сфотографируйте секретную фразу восстановления МетаМаск!!! Это очень важно! Если вдруг вы забудете пароль, это будет единственный способ восстановить доступ!
После установки и регистрации, открываете приложение и в самом верху выбираете "Тестовая сеть Goerly".
Рядом с названием вашего аккаунта будет меню (три точки), нажимаете их, выбираете реквизиты счета, экспорт закрытого ключа, вводите еще раз свой пароль, копируете свой закрытый ключ и вставляете его в новую переменную в env файле, например META_KEY.
Теперь идем в папку нашего проекта и открываем файл hardhat.config.json.
В раздел module.exports добавляем код networks, как в примере лектора в уроке или как представлено ниже, чтобы в итоге он выглядел так:
module.exports = {
solidity: "0.8.9",
networks: {
goerli: {
url:
https://eth-goerli.alchemyapi.io/v2/${process.env.API_KEY},accounts: [process.env.META_KEY]
}
}
};
И вот после всех этих действий, мы можем загрузить свой проект в goerly, выполнив команду в консоли:
npx harhat run noscripts\deploy.js --network goerly
В вашем проекте на Alchemy должен появиться новый контракт, если все прошло как надо.
#goerly #metamask #alchemy
Alchemy
Alchemy Dashboard
Whether you're a beginner developer, startup, web3 market leader, or a large enterprise, Alchemy makes multichain web3 development easy with reliable and scalable node infrastructure, enhanced APIs, and developer tools. Get started for free!
Как получить эфир для сети Goerli
Кстати, для все операций теперь в тестовой сети вам может потребоваться Эфир. Для этого в google вводите в строку поиска goerli faucet.
Например, у меня в поиске в первой ссылке был этот сайт. Можете зарегистрироваться там или поискать другие сайты, которые позволят получать эфир без регистрации.
Теперь нам нужно скопировать адрес нашего кошелька из МетаМаск. Заходим в браузере туда и нажимаем на название аккаунта, чтобы получить наш адрес.
Возвращаемся на сайт faucet (все они работают по одному и тому же принципу), и в поле вставляем наш адрес кошелька. Через пару минут проверяем его и убеждаемся, что теперь там доступно немного ETH.
Так можно делать на других сайтах и собрать чуть больше эфира на кошельке для тестов с контрактом.
Нужно отметить, что этот ETH не имеет никакой ценности и торговать им на бирже не получится. Он создан специально для работы в тестовых сетях.
#goerly #metamask #faucet
Кстати, для все операций теперь в тестовой сети вам может потребоваться Эфир. Для этого в google вводите в строку поиска goerli faucet.
Например, у меня в поиске в первой ссылке был этот сайт. Можете зарегистрироваться там или поискать другие сайты, которые позволят получать эфир без регистрации.
Теперь нам нужно скопировать адрес нашего кошелька из МетаМаск. Заходим в браузере туда и нажимаем на название аккаунта, чтобы получить наш адрес.
Возвращаемся на сайт faucet (все они работают по одному и тому же принципу), и в поле вставляем наш адрес кошелька. Через пару минут проверяем его и убеждаемся, что теперь там доступно немного ETH.
Так можно делать на других сайтах и собрать чуть больше эфира на кошельке для тестов с контрактом.
Нужно отметить, что этот ETH не имеет никакой ценности и торговать им на бирже не получится. Он создан специально для работы в тестовых сетях.
#goerly #metamask #faucet
Кратко о работе с Etherscan
Etherscan - это самый популярный сайт, где можно просматривать контракты, их код, abi и транзакции по ним.
И чтобы легче находить его и верифицировать свой контракт, можно использовать hardhat.
Для этого после регистрации на Etherscan в правом верхнем углу кликаем на аватар своего профиля и выбираем Api keys. Создаем свой ключ и копируем его в новую переменную в файле env, например ETH_KEY.
Затем снова открываем файл hardhat.config.json и в раздел module.exports добавляем:
etherscan: {
apiKey:
}
К слову сказать, у вас уже должен быть подключен новый пакет hardhat-etherscan (в toolbox он уже есть). Если нет, то сделать это можно командой в консоли:
npm install --save-dev @nomiclabs/hardhat-etherscan
и добавлением записи в hardhat.config.json:
require("@nomiclabs/hardhat-etherscan");
После этого в консоли вам станет доступна команда:
npx hardhat verify --network netName contractAddress
где netName - имя тестовой сети, куда вы загрузили свой контракт, а contractAddress - адрес вашего контракта.
Данная команда выдаст вам ссылку на etherscan, где вы можете получить всю информацию по вашему контракту в блокчейне.
#etherscan
Etherscan - это самый популярный сайт, где можно просматривать контракты, их код, abi и транзакции по ним.
И чтобы легче находить его и верифицировать свой контракт, можно использовать hardhat.
Для этого после регистрации на Etherscan в правом верхнем углу кликаем на аватар своего профиля и выбираем Api keys. Создаем свой ключ и копируем его в новую переменную в файле env, например ETH_KEY.
Затем снова открываем файл hardhat.config.json и в раздел module.exports добавляем:
etherscan: {
apiKey:
${process.env.ETH_KEY}}
К слову сказать, у вас уже должен быть подключен новый пакет hardhat-etherscan (в toolbox он уже есть). Если нет, то сделать это можно командой в консоли:
npm install --save-dev @nomiclabs/hardhat-etherscan
и добавлением записи в hardhat.config.json:
require("@nomiclabs/hardhat-etherscan");
После этого в консоли вам станет доступна команда:
npx hardhat verify --network netName contractAddress
где netName - имя тестовой сети, куда вы загрузили свой контракт, а contractAddress - адрес вашего контракта.
Данная команда выдаст вам ссылку на etherscan, где вы можете получить всю информацию по вашему контракту в блокчейне.
#etherscan
Урок 26 - Honeypot
Надеюсь у всех вчера получилось разобраться с деплоем контрактов в различные сети, а также с новым пакетом для скрытия важной информации в коде.
Сегодня же у нас достаточно легкий урок. В нем нужно не столько учиться каким-то фишкам или настройкам пакетов и конфигов, сколько понять общий принцип ловушки: как ее разглядеть в коде и как научиться переигрывать мошенников.
Также это будет полезно, если вы на досуге "играетесь" с криптовалютой, биржами и следите за выходом новых токенов.
Новый видео урок.
Также напоминаю, что завтра у нас будет стрим от Ильи в 19:00 по московскому времени на его канале. Можно будет узнать новую тему, которую мы будем разбирать в пятницу, и задать вопросы по Solidity.
Вероятнее всего, я завтра сделаю несколько простых постов по нюансам языка, дам несколько полезных ссылок и рекомендаций.
На этой неделе мы закончим продвинутое обучение и со следующей я расскажу вам о новых планах.
Всем легкого дня и быстрого обучения!
#урок #honeypot
Надеюсь у всех вчера получилось разобраться с деплоем контрактов в различные сети, а также с новым пакетом для скрытия важной информации в коде.
Сегодня же у нас достаточно легкий урок. В нем нужно не столько учиться каким-то фишкам или настройкам пакетов и конфигов, сколько понять общий принцип ловушки: как ее разглядеть в коде и как научиться переигрывать мошенников.
Также это будет полезно, если вы на досуге "играетесь" с криптовалютой, биржами и следите за выходом новых токенов.
Новый видео урок.
Также напоминаю, что завтра у нас будет стрим от Ильи в 19:00 по московскому времени на его канале. Можно будет узнать новую тему, которую мы будем разбирать в пятницу, и задать вопросы по Solidity.
Вероятнее всего, я завтра сделаю несколько простых постов по нюансам языка, дам несколько полезных ссылок и рекомендаций.
На этой неделе мы закончим продвинутое обучение и со следующей я расскажу вам о новых планах.
Всем легкого дня и быстрого обучения!
#урок #honeypot
YouTube
Solidity и смарт-контракты Ethereum, урок #30 | Безопасность: ловушка "honeypot", ловим хакеров
ХОТИТЕ СТАТЬ РАЗРАБОТЧИКОМ Solidity, узнать об Ethereum, блокчейне и многом другом ещё больше?!
Мои друзья из GUIDE DAO (бывшая школа MCS) предлагают скидку 0,1 ETH на ВСЕ СВОИ БУТКЕМЫ ПО КРИПТЕ! Материалы этих буткемов подготовлены мной и другими специалистами:…
Мои друзья из GUIDE DAO (бывшая школа MCS) предлагают скидку 0,1 ETH на ВСЕ СВОИ БУТКЕМЫ ПО КРИПТЕ! Материалы этих буткемов подготовлены мной и другими специалистами:…
Что такое Honeypot
И по традиции, давайте разберемся, что же такое этот Honeypot.
Honeypot (горшок с медом) - это некая ловушка для пользователей, которая основана на не самых очевидных моментах в коде. Чаще всего им пользуются мошенники, чтобы обманом продать токены, которые нельзя будет потом перепродать.
Допустим, по всем каналам в Телеграм и на популярных ресурсах кто-то делает посты о том, что он запускает крутые токены в оборот, что у него большие планы, и уже несколько крупных компаний поддерживают его инициативу. Конечно же, он предлагает всем пользователям купить его токены по бросовой цене в 0.1 $ и обещает, что через полгода их стоимость будет около 1 $ или даже 5 $. Доверчивые люди бросаются покупать токены в надежде заработать. Но через указанный промежуток времени, никакого роста токена нет, и пользователи решают продать его.
А не тут-то было! Токены продать больше нельзя, и мошенник уходит с деньгами создавать новый скам.
В этом уроке и обращают наше внимание на подобные нюансы в коде, как избежать обмана, и как перехитрить мошенника, если он захочет использовать уязвимость нашего контракта на reentrancy.
#honeypot
И по традиции, давайте разберемся, что же такое этот Honeypot.
Honeypot (горшок с медом) - это некая ловушка для пользователей, которая основана на не самых очевидных моментах в коде. Чаще всего им пользуются мошенники, чтобы обманом продать токены, которые нельзя будет потом перепродать.
Допустим, по всем каналам в Телеграм и на популярных ресурсах кто-то делает посты о том, что он запускает крутые токены в оборот, что у него большие планы, и уже несколько крупных компаний поддерживают его инициативу. Конечно же, он предлагает всем пользователям купить его токены по бросовой цене в 0.1 $ и обещает, что через полгода их стоимость будет около 1 $ или даже 5 $. Доверчивые люди бросаются покупать токены в надежде заработать. Но через указанный промежуток времени, никакого роста токена нет, и пользователи решают продать его.
А не тут-то было! Токены продать больше нельзя, и мошенник уходит с деньгами создавать новый скам.
В этом уроке и обращают наше внимание на подобные нюансы в коде, как избежать обмана, и как перехитрить мошенника, если он захочет использовать уязвимость нашего контракта на reentrancy.
#honeypot
👍1
Разбор Honeypot
Для того, чтобы вы понимали лучше разбор данного урока, я скидываю ссылку на комит урока от лектора. Лучше всего будет, если вы прочитаете пост, а затем еще раз сами просмотрите код контрактов.
Как я понял из урока, honeypot основан на подмене контракта для логирования событий в контракте банка. Вроде как, всем пользователям показывается первый обычный контракт Logger, который просто порождает событие для log, а на самом деле, наследование идет от другого контракта, который был как бы спрятан от глаз пользователей.
И если не разобраться, от кого идет наследование в ILogger public logger в контракте банка, то можно попасть на деньги.
Также в данном примере была использована уязвимость reentrancy (по сути, повторный возов функций кода) в контракте банка, чтобы заманить в ловушку потенциального хакера.
Хакер думает, что раз "balances[_initiator] = 0" вызывается после отправки средств на счет пользователя, то можно создать новый контракт для атаки, который будет вызывать функцию _withdraw каждый раз по новому пока на счету банка не останется средств.
И вот для того, чтобы обмануть хакера, который хочет обмануть нас, в контракте банка мы создаем новую переменную "bool resuming", чтобы запутать хакера, и в функции _withdraw принимаем дополнительный аргумент "uint _statusCode".
После этого, уже как бы мы сами создаем контракт honeypot и обновляем withdraw с новой bool переменной.
Т.е. изначально лектор показывал, что honeypot создал мошенник, чтобы обманывать пользователей, а позже honeypot создаем мы, чтобы обмануть мошенника.
Уже в нашем honeypot мы используем "_actionCode", чтобы определить, кто пытается вызвать withdraw.
Если обычный пользователь снимает свои деньги, то все проходит ок.
Если же мошенник пытается использовать уязвимость reentrancy и вызывать повторно withdraw, то через нее мы вызываем служебную _widthdraw с новым передаваемым аргументом "_statusCode", который на втором вызове меняет значение на "2". Теперь сам мошенник попадает в нашу ловушку honeypot, транзакция откачивается и он не может получить даже свои деньги.
Вот как-то так.
В 4 контрактах и 1 интерфейсе из урока легко запутаться, полагаю как и в данном посте при первом прочтении.
Тут главное понять, что в рамках урока мы действуем и как мошенник и как тот, кто хочет обмануть мошенника, поэтому один код работает сразу для двух примеров.
#honeypot
Для того, чтобы вы понимали лучше разбор данного урока, я скидываю ссылку на комит урока от лектора. Лучше всего будет, если вы прочитаете пост, а затем еще раз сами просмотрите код контрактов.
Как я понял из урока, honeypot основан на подмене контракта для логирования событий в контракте банка. Вроде как, всем пользователям показывается первый обычный контракт Logger, который просто порождает событие для log, а на самом деле, наследование идет от другого контракта, который был как бы спрятан от глаз пользователей.
И если не разобраться, от кого идет наследование в ILogger public logger в контракте банка, то можно попасть на деньги.
Также в данном примере была использована уязвимость reentrancy (по сути, повторный возов функций кода) в контракте банка, чтобы заманить в ловушку потенциального хакера.
Хакер думает, что раз "balances[_initiator] = 0" вызывается после отправки средств на счет пользователя, то можно создать новый контракт для атаки, который будет вызывать функцию _withdraw каждый раз по новому пока на счету банка не останется средств.
И вот для того, чтобы обмануть хакера, который хочет обмануть нас, в контракте банка мы создаем новую переменную "bool resuming", чтобы запутать хакера, и в функции _withdraw принимаем дополнительный аргумент "uint _statusCode".
После этого, уже как бы мы сами создаем контракт honeypot и обновляем withdraw с новой bool переменной.
Т.е. изначально лектор показывал, что honeypot создал мошенник, чтобы обманывать пользователей, а позже honeypot создаем мы, чтобы обмануть мошенника.
Уже в нашем honeypot мы используем "_actionCode", чтобы определить, кто пытается вызвать withdraw.
Если обычный пользователь снимает свои деньги, то все проходит ок.
Если же мошенник пытается использовать уязвимость reentrancy и вызывать повторно withdraw, то через нее мы вызываем служебную _widthdraw с новым передаваемым аргументом "_statusCode", который на втором вызове меняет значение на "2". Теперь сам мошенник попадает в нашу ловушку honeypot, транзакция откачивается и он не может получить даже свои деньги.
Вот как-то так.
В 4 контрактах и 1 интерфейсе из урока легко запутаться, полагаю как и в данном посте при первом прочтении.
Тут главное понять, что в рамках урока мы действуем и как мошенник и как тот, кто хочет обмануть мошенника, поэтому один код работает сразу для двух примеров.
#honeypot
Тесты с урока про Honeypot
Также хочу обратить ваше внимание, что лектор в уроке для проведения тестов с контрактами использует деплой с учетом последних обновлений hardhat, который я описывал ранее.
Однако напомню для повторения.
В начале он импортирует loadFixture, expect и ethers для проведения тестов, а также type для использования typechain.
import { loadFixture } from "@nomicfoundation/hardhat-network-helpers";
import { expect } from "chai";
import { ethers } from "hardhat";
import type { Bank, Attack, Logger, Honeypot } from "../typechain-types";
Затем в деплое, вместо beforeEach, пишет функцию dep(), которая возвращает объекты для тестирования ниже.
И в тестах начинает работы с получения этих объектов через await loadFixture(dep).
На данный момент это стандарт работы с тестами в hardhat и их нужно знать.
#honeypot #deploy
Также хочу обратить ваше внимание, что лектор в уроке для проведения тестов с контрактами использует деплой с учетом последних обновлений hardhat, который я описывал ранее.
Однако напомню для повторения.
В начале он импортирует loadFixture, expect и ethers для проведения тестов, а также type для использования typechain.
import { loadFixture } from "@nomicfoundation/hardhat-network-helpers";
import { expect } from "chai";
import { ethers } from "hardhat";
import type { Bank, Attack, Logger, Honeypot } from "../typechain-types";
Затем в деплое, вместо beforeEach, пишет функцию dep(), которая возвращает объекты для тестирования ниже.
И в тестах начинает работы с получения этих объектов через await loadFixture(dep).
На данный момент это стандарт работы с тестами в hardhat и их нужно знать.
#honeypot #deploy
Solidity by Example
Сегодня, в ожидании стрима, на канале не будет уроков. Вместо этого я сделаю несколько полезных постов по работе с Solidity.
Я нашел один интересный сайт, где приводятся примеры кода Solidity, как шпаргалки.
Очень удобно, например, когда вы забыли какой-то урок или функцию, и хотите быстро по коду понять написание или использование.
Да, он на английском, но тем не менее очень понятен интуитивно.
Solidity by Example.
#links #hint
Сегодня, в ожидании стрима, на канале не будет уроков. Вместо этого я сделаю несколько полезных постов по работе с Solidity.
Я нашел один интересный сайт, где приводятся примеры кода Solidity, как шпаргалки.
Очень удобно, например, когда вы забыли какой-то урок или функцию, и хотите быстро по коду понять написание или использование.
Да, он на английском, но тем не менее очень понятен интуитивно.
Solidity by Example.
#links #hint
Статья с рекомендациями
Также нашел еще одну интересную статью с рекомендациями по написанию хорошего кода. Она на английском языке, поэтому в течение дня я сделаю несколько постов с переводом основных пунктов.
Советы достаточно интересные, и ничего подобного раньше в уроках или других видео я не встречал.
#link #hint
Также нашел еще одну интересную статью с рекомендациями по написанию хорошего кода. Она на английском языке, поэтому в течение дня я сделаю несколько постов с переводом основных пунктов.
Советы достаточно интересные, и ничего подобного раньше в уроках или других видео я не встречал.
#link #hint
Используйте модификаторы правильно
Интересное замечание, которое я не встречал еще в практике.
Не рекомендуется использовать модификаторы, в которых изменяются переменные состояния или реализуются внешние вызовы, например при наследовании, так как сами модификаторы исполняются до кода в функции.
contract Registry {
address owner;
function isVoter(address _addr) external returns(bool) {
// Code
}
}
contract Election {
Registry registry;
modifier isEligible(address _addr) {
require(registry.isVoter(_addr));
_;
}
function vote() isEligible(msg.sender) public {
// Code
}
}
Например, выше вы можете видеть НЕ правильное использование модификатора, так как контракт Registry может делать reentrancy атаку в другом контракте, вызывая Election.vote() внутри isVoter().
Модификаторы чаще всего используются, чтобы заменить дублирующийся код в функциях, по примеру проверки владельца isOwner().
#modifier #hint
Интересное замечание, которое я не встречал еще в практике.
Не рекомендуется использовать модификаторы, в которых изменяются переменные состояния или реализуются внешние вызовы, например при наследовании, так как сами модификаторы исполняются до кода в функции.
contract Registry {
address owner;
function isVoter(address _addr) external returns(bool) {
// Code
}
}
contract Election {
Registry registry;
modifier isEligible(address _addr) {
require(registry.isVoter(_addr));
_;
}
function vote() isEligible(msg.sender) public {
// Code
}
}
Например, выше вы можете видеть НЕ правильное использование модификатора, так как контракт Registry может делать reentrancy атаку в другом контракте, вызывая Election.vote() внутри isVoter().
Модификаторы чаще всего используются, чтобы заменить дублирующийся код в функциях, по примеру проверки владельца isOwner().
#modifier #hint
👍1
Аккуратнее с делением чисел
Solidity, на данный момент сентября 2022 года, не поддерживает числа с точкой, и при делении 5/2 будет показан результат "2". Т.е. вместе с откидыванием цифр после точки, он еще и округляет результат до меньшего числа.
Это действительно проблема для большинства разработчиков. И многие пытаются преодолеть ее через дополнительные библиотеки на openzeppelin или пишут свои "костыли".
В документации по Solidity пишут, что нужно использовать мультипликатор, как в примере:
uint multiplier = 10;
uint x = (5 * multiplier) / 2;
Из других статей я понял, что можно также выполнять все математические операции на фронтенде, чтобы все было точнее, а уже результат сохранять в Solidity.
Некоторые предлагают использовать decimals эфира, но я не видел хороших примеров.
#division #integer #hint
Solidity, на данный момент сентября 2022 года, не поддерживает числа с точкой, и при делении 5/2 будет показан результат "2". Т.е. вместе с откидыванием цифр после точки, он еще и округляет результат до меньшего числа.
Это действительно проблема для большинства разработчиков. И многие пытаются преодолеть ее через дополнительные библиотеки на openzeppelin или пишут свои "костыли".
В документации по Solidity пишут, что нужно использовать мультипликатор, как в примере:
uint multiplier = 10;
uint x = (5 * multiplier) / 2;
Из других статей я понял, что можно также выполнять все математические операции на фронтенде, чтобы все было точнее, а уже результат сохранять в Solidity.
Некоторые предлагают использовать decimals эфира, но я не видел хороших примеров.
#division #integer #hint
👍1