Деплой и тест ICO и ERC20 смарт-контракта Moonbeam используя hardhat
Данный документ является продолжением документации работы с мунбимом, ознакомьтесь с первой статьей для установки локальной ноды Moonbeam Development Node и комапонентов hardhat. В этой статье мы расскажем как задеплоить и протестировать ICO и ERC20 смарт-контракты Moonbeam используя локальную ноду, с помощью hardhat
1. Переходим в папку contacts (которая должна находится по пути hardhat-dev/contracts) и проверям что там находится:
cd contracts
Проверяем что лежит в папке | ll Если там находятся лишние файлы, удалите их чтоб они не мешали вам. В нашем случае там находится файл "Greeter.sol", давайте удалим его | rm -rf Greeter.sol И еще раз проверим что находится в папке contract: | ll
2. Создаем ERC20 смарт-контракт, здесь для примера используется импорт одной из стандартной библиотек ERC20.
npm install @openzeppelin/contracts
Создаем скрипт контракта ERC20
nano contracts/MyTokenERC20.sol
Пример скрипта, который мы использовали :
pragma solidity ^0.8.1;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract MyTokenERC20 is ERC20 {
/**
* @dev Constructor that gives msg.sender all of exis>
*/
constructor(
string memory name,
string memory symbol,
uint256 initialSupply
) ERC20(name, symbol) {
_mint(msg.sender, initialSupply);
}
}!help Проверяем чтоб версия солидити, которая используется в контракте совпадала с версией используемой в файле конфига:
nano hardhat.config.js
require("@nomiclabs/hardhat-waffle");
// This is a sample Hardhat task. To learn how to creat>
// https://hardhat.org/guides/create-task.html
task("accounts", "Prints the list of accounts", async (>
const accounts = await hre.ethers.getSigners();
for (const account of accounts) {
console.log(account.address);
}
});
// You need to export an object to set up your config
// Go to https://hardhat.org/config/ to learn more
/**
* @type import('hardhat/config').HardhatUserConfig
*/
const { privateKey } = require('./secrets.json');
module.exports = {
solidity: "0.8.1",
networks: {
dev: {
url: "http://127.0.0.1:9933",
chainId: 1281,
accounts: [privateKey]
}
}
};nano contracts/ICO.sol
Пример скрипта, который мы использовали :
pragma solidity ^0.8.1;
import "./MyTokenERC20.sol";
contract ICO {
uint public buyPrice;
MyTokenERC20 public token;
constructor(MyTokenERC20 _token, uint _buyPrice) {
token = _token;
buyPrice = _buyPrice;
}
function buy() external payable returns (uint) {
uint tokens = _buy(msg.sender , msg.value);
return tokens;
}
function _buy(address _sender , uint256 _amount) inte>
uint tokens = _amount / buyPrice;
token.transfer(_sender , tokens);
return tokens;
}
}!help У этого контракта есть функция бай - функцию бай мы будем использовать для покупки токенов. Также у ICO смарт-контракта есть конструктор который принимает адресс ERC20 токена и цену токена, функция бай отправляет токены тому кто прислал эфир в соответсвии с указанной ценой.
4. Теперь нам нужно изменить деплой скрипт, который мы использовали в предидущей доке :
nano scripts/deploy.js
Вот так выглядит наш скрипт деплоя для текущего проекта :
async function main() {
// Weget the contract to deploy
const MyTokenERC20 = await ethers.getContractFactory('MyTokenERC20');
console.log('Deploying MyTokenERC20...');
const totalSupply = '1000000';
// Instantiating a new ERC20 smart contract
const myTokenERC20 = await MyTokenERC20.deploy('DoubleTop', 'DoubleTop', totalSupply + '0000000000000000000');
// Waiting for the deployent to resolve
await myTokenERC20.deployed();
console.log('MyTokenERC20 deployed to:', myTokenERC20.address);
// We get the contract to deploy
const ICO = await ethers.getContractFactory('ICO');
console.log('Deploying ICO...');
// Instantiating a new ICO smart contract
const ico = await ICO.deploy(myTokenERC20.address, 1000);
// Waiting for the deployment to resolve
await ico.deployed();
console.log('ICO deployed to:', ico.address);
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});!Замените название "DoubleTop" в строке 8 на название вашего токена!
!help Обозначения скрипта. Для вашего удобства разберем что означает каждый абзац в скрипте (цифра это номер абзаца) :
1) Инициализация ERC20 контракта
3) Ожидания пока ERC20 контракт задеплоится
cd test
Проверяем что лежит в папке | ll Если там находятся лишние файлы, удалите их чтоб они не мешали вам. В нашем случае там находится файл "sample-test.js", давайте удалим его | rm -rf sample-test.js И еще раз проверим что находится в папке contract: | ll
создаем новый тестовый файл ICO.js
nano ICO.js
Вот так выглядит наш скрипт для теста :
const { expect } = require('chai');
describe('ICO contract', () => {
let TokenContract, tokenContract, ICO, ico, owner, addr1, addr2, addr3
const totalSupply = '1000000';
const price = '10';
beforeEach(async () => {
TokenContract = await ethers.getContractFactory('MyTokenERC20');
tokenContract = await TokenContract.deploy('MyTokenERC20', 'MTE', totalSupply + '00000000000000000');
await tokenContract.deployed();
ICO = await ethers.getContractFactory('ICO');
ico = await ICO.deploy(tokenContract.address, price);
await ico.deployed();
[owner, addr1, addr2, addr3] = await ethers.getSigners();
await tokenContract.transfer(ico.address, '2000000' + '00000000000000000');
});
describe('Transfer token', () => {
it('Owner balance', async () => {
const ownerBalance = await tokenContract.balanceOf(owner.address);
expect(ownerBalance.toString()).to.equal('800000' + '000000000000000000');
});
it('Buy token', async () => {
await ico.connect(addr1).buy({ value: ethers.utills.parseEther('1') });
const adde1Balance = await tokenContract.balanceOf(addr1.address);
expect(addr1Balance.toString()).to.equal(ethers.utils.parseEther('0.1').toString());
});
});
});!help В первом тесте (строка 24-26) - мы берем адрес владельца и проверяем что баланс корректный. Во втором тесте (строка 30-34) - мы вызываем функцию покупки токенов и проверяем что функция покупки отработала корректно.
npx hardhat compile
npx hardhat test
npx hardhat run scripts/deploy.js --network dev
8. Теперь давайте подключимся к метамаску и протестируем и проверим работоспособность наших контрактов. Для этого нам понадобится расширение метамаска, аккаунт разработчика который мы использовали
(можете ознакомится с аккаунтами разработчиков здесь).
Мы для наших проектов использовали аккаунт Геральда :
Public Address: 0x6Be02d1d3665660d22FF9624b7BE0551ee1Ac91b Private Key: 0x99b3c12287537e38c90a9219d4cb074a89a16e9cdb20bf85728ebd97c343e342
Импортируем закрытый ключ, подключаемся к сети Moonbeam Dev (как подключить метамаск к сетям moonbeam) и убеждаемся что у нас на балансе токены Dev и которые вы создали в смарт-контракте. В нашем случае "DoubleTop".
9. Сделаем пару тестовых переводов между кошельками метамаска для того чтоб убедится что все корректно работает :
Отправим токены Dev и созданные нами токены на второй кошелек
Проверяем со второго кошелька что токены пришли :
Отправляем оставшиеся созданные токены на адрес смарт-контракта
10. Напоследок проверяем функцию покупки токенов в ICO смарт-контракте. Для этого мы используем среду разработки Remix :
Переходим во вкладку Workspace и создаем новую рабочую среду :
Создаем 2 файла "ICO.sol" и "MyTokenERC20.sol". Копируем в созданные файлы наши контракты соответсвенно :
Переходим к компиляции файлов ICO.sol и MyTokenERC20.sol которые мы создали :
Теперь пробуем купить наши токены с помощь смарт-контракта ICO развернутого в среде разработки remix :
https://razumv.tech/smart-contract_Moonbeam
https://docs.moonbeam.network/builders/get-started/moonbeam-dev/
https://docs.moonbeam.network/tokens/connect/metamask/#connect-metamask-to-moonbeam
https://docs.moonbeam.network/ru/integrations/wallets/metamask/