Еще на пятой неделе @Web3bridge мы написали смарт-контракт, который реализует механизм ставок для указанного токена ERC20, позволяя пользователям ставить и снимать токены, получая при этом вознаграждения в зависимости от продолжительности их ставок и указанного процента вознаграждения.

Он также включает в себя функции вывода эфира и получения вознаграждений. Контракт наследуется от контракта ERC20 и соответствует стандартному интерфейсу ERC20 для взаимодействия токенов. Я объясню каждую часть кода шаг за шагом:

Идентификатор лицензии SPDX и директива Pragma:

// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

В этом разделе указывается идентификатор лицензии (MIT) и используемая версия компилятора Solidity (0.8.20).

Импорт ERC20 из контрактов OpenZeppelin:

import {ERC20} from "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol";

Контракт импортирует контракт ERC20 из библиотеки контрактов OpenZeppelin. Этот импортированный контракт используется в качестве основы для создания собственного токена ERC20.

Объявление интерфейса:

interface IStandardToken {
    function balanceOf(address account) external view returns (uint256);
    function totalSupply() external view returns (uint256);
    function transfer(address to, uint256 amount) external returns (bool);
    function transferFrom(address from, address to, uint256 amount) external returns (bool);
    function withdrawEther() external;
}

Интерфейс IStandardToken объявлен с функциями, определяющими стандартный интерфейс токена ERC20, включая balanceOf, totalSupply, transfer, transferFrom и withdrawEther.

Заявление о договоре доли:

contract Stake is ERC20 {
    // ...
}

Контракт Stake объявлен и наследуется от контракта ERC20. Это означает, что контракт Stake представляет собой токен ERC20 с дополнительными функциями ставок.

Переменные состояния:

IStandardToken standardToken;
struct stakeStruct {
    uint amountStaked;
    uint timeStaked; // keep track of when stake happened
}
uint public rewardPercent = 1;
mapping(address => stakeStruct) public userStakeMap;
  • standardToken: Экземпляр интерфейса IStandardToken, представляющий токен, который пользователи будут стейкать.
  • stakeStruct: пользовательская структура данных, используемая для хранения информации о ставке пользователя, включая сумму ставки и время ее размещения.
  • rewardPercent: общедоступная переменная, представляющая процент вознаграждений, полученных участниками. Изначально он установлен на уровне 1%.
  • userStakeMap: сопоставление, которое связывает адреса Ethereum с записями stakeStruct, позволяя контракту отслеживать долю каждого пользователя.

Конструктор:

constructor(address _standardToken) ERC20("RewardToken", "RWT") {
    standardToken = IStandardToken(_standardToken);
}

Конструктор контракта принимает адрес стандартного токена ERC20 в качестве аргумента и инициализирует переменную standardToken. Он также инициализирует токен ERC20 с именем «RewardToken» и символом «RWT».

События:

event Staked(uint amountstake, uint totalAmountStaked, uint time);
event unStaked(uint amountstake, uint totalAmountStaked, uint time, uint rewards);
event claimReward(uint time, uint rewards);

Объявлено, что эти события регистрируют важные действия по контракту, такие как ставка, отмена ставки и получение вознаграждения. Они полезны для мониторинга активности контрактов.

Функция ставок:

function stake(uint _amount) external {
    // ...
}

Эта функция позволяет пользователям ставить определенное количество токенов. Он проверяет баланс токенов пользователя, переносит токены в контракт и записывает детали ставки в userStakeMap.

Функция снятия ставок:

function unStake(uint _amount) external {
    // ...
}

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

Функция вывода эфира:

function withdrawEther() external {
    standardToken.withdrawEther();
    payable(msg.sender).transfer(address(this).balance);
}

Эта функция вычисляет вознаграждения, на которые имеет право стейкер, на основе продолжительности ставки и процента вознаграждения.

Функция расчета вознаграждения:

function calculateRewards(address _staker) public view returns (uint) {
    // ...
}

Эта функция вычисляет вознаграждения, на которые имеет право стейкер, на основе продолжительности ставки и процента вознаграждения.

Функция получения вознаграждений:

function claimRewards() public {
    // ...
}

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

Функции возврата и получения:

fallback() external payable {}
receive() external payable {}

Эти функции позволяют контракту получать эфир. Функция fallback вызывается, когда контракт получает эфир без специального вызова функции, а функция receive вызывается, когда контракт получает эфир посредством прямого платежа.