初识 Solidity 编程语言

一. 简介

Solidity 是一种面向智能合约的高级编程语言,主要用于在以太坊(Ethereum)区块链平台上开发和部署智能合约。Solidity 由以太坊创始团队开发,旨在简化智能合约的创建和管理,Solidit 语言有以下这些主要的特点。

  • 面向合约编程:Solidity 专为编写智能合约设计,这些合约运行在以太坊虚拟机(EVM)上,自动执行和管理区块链上的交易和协议。
  • 静态类型:Solidity 是一种静态类型语言,变量类型在编译时确定,提供了更严格的类型检查和更高的代码安全性。
  • 合约继承:Solidity 支持合约继承,允许开发者创建可重用的合约组件,从而简化代码结构和提高代码的可维护性。
  • 库和接口:Solidity 提供了库和接口功能,帮助开发者模块化代码,提高代码的重用性和可维护性。
  • 事件和日志:Solidity 支持事件和日志功能,可以在合约执行过程中生成日志记录,方便在区块链上进行事件追踪和调试。
  • 访问控制和权限管理:Solidity 提供了灵活的访问控制机制,可以定义不同的访问权限和角色,确保合约的安全性。

二. 合约文件结构

这里我们直接看一个真实项目的标准的合约合约文件,L2RewardManager 是这个合约的名称,该合约继承了 L2Base, L2RewardManagerStorage, L2RewardManager 合约的常量,事件和错误类型都定义到了 L2RewardManagerStorage 文件里面了。

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.24;


import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {L2RewardManagerStorage} from "@/contracts/l2/core/L2RewardManagerStorage.sol";
import {L2Base} from "@/contracts/l2/core/L2Base.sol";

contract L2RewardManager is L2Base, L2RewardManagerStorage {
    using SafeERC20 for IERC20;
    uint256 public stakerPercent = 92;

    constructor(){
        _disableInitializers();
    }

    function initialize(
        address initialOwner
    ) external initializer {
        __L2Base_init(initialOwner);
    }

    function calculateFee(address strategy, address operator, uint256 baseFee) external {
        uint256 totalShares = getStrategy(strategy).totalShares();
        uint256 operatorShares = getDelegationManager().operatorShares(operator, strategy);
        uint256 operatorTotalFee = baseFee / (operatorShares / totalShares);

        uint256 stakerFee = operatorTotalFee * (stakerPercent / 100);
        stakerRewards[strategy] = stakerFee;

        uint256 operatorFee = operatorTotalFee * ((100 - stakerPercent) / 100);
        operatorRewards[operator] = operatorFee;

        emit OperatorStakerReward(
            strategy,
            operator,
            stakerFee,
            operatorFee
        );
    }

    function depositDappLinkToken(uint256 amount) external returns (bool){
        getDapplinkToken().safeTransferFrom(msg.sender, address(this), amount);
        emit DepositDappLinkToken(msg.sender, amount);
        return true;
    }

    function operatorClaimReward() external returns (bool){
        uint256 claimAmount = operatorRewards[msg.sender];
        getDapplinkToken().safeTransferFrom(address(this), msg.sender, claimAmount);
        emit OperatorClaimReward(
            msg.sender,
            claimAmount
        );
        return true;
    }

    function stakerClaimReward(address strategy) external returns (bool){
       uint256 stakerAmount = stakerRewardsAmount(strategy);
        getDapplinkToken().safeTransferFrom(address(this), msg.sender, stakerAmount);
        emit StakerClaimReward(
            msg.sender,
            stakerAmount
        );
        return true;
    }

    function stakerRewardsAmount(address strategy) public view returns (uint256){
        uint256 stakerShare = getStrategyManager().getStakerStrategyShares(msg.sender, strategy);
        uint256 strategyShares = getStrategy(strategy).totalShares();
        if (stakerShare == 0 ||strategyShares == 0) {
            return 0;
        }
        return stakerRewards[strategy] * (stakerShare /  strategyShares);
    }

    function updateOperatorAndStakerShareFee(uint256 _stakerPercent) external {
         stakerPercent = _stakerPercent;
    }
}

合约文件详细解释

  • 版本声明:这是合约的版本声明,指定合约使用的 Solidity 编译器版本。
pragma solidity ^0.8.24;
  • 导入声明:如果合约依赖于其他文件或库,可以使用 import 语句导入。
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {L2RewardManagerStorage} from "@/contracts/l2/core/L2RewardManagerStorage.sol";
import {L2Base} from "@/contracts/l2/core/L2Base.sol";
  • 合约声明: 使用 contract 关键字声明一个新合约,合约的主体内容放在大括号内。
  • 合约继承:使用 is 后面跟其他合约名称表示继承
contract L2RewardManager is L2Base, L2RewardManagerStorage {
}
  • 状态变量:状态变量是存储在区块链上的变量,合约中可以访问和修改这些变量。 public 关键字表示这些变量可以从外部读取。
uint256 public stakerPercent = 92;
  • 常量:
bytes32 public constant STAKING_MANAGER_ROLE = keccak256("STAKING_MANAGER_ROLE");
  • 事件:事件是 EVM 日志的一种便捷接口,前端应用可以监听这些事件。
event OperatorStakerReward(
    address strategy,
    address operator,
    uint256 stakerFee,
    uint256 operatorFee
);
  • 修饰符:修饰符用于修改函数的行为,这里 onlyStrategyManager 修饰符确保只有合约的拥有者才能调用某些函数。
modifier onlyStrategyManager() {
    require(msg.sender == address(strategyManager), "StrategyBase.onlyStrategyManager");
    _;
}
  • 构造函数:构造函数在合约部署时执行,用于初始化状态变量。
constructor(){
    _disableInitializers();
}
  • 初始化函数: 参数初始化,函数职能执行一次
function initialize(
    address initialOwner
) external initializer {
    __L2Base_init(initialOwner);
}
  • 函数:一个计算 operator cliam 奖励的函数
function operatorClaimReward() external returns (bool){
    uint256 claimAmount = operatorRewards[msg.sender];
    getDapplinkToken().safeTransferFrom(address(this), msg.sender, claimAmount);
    emit OperatorClaimReward(
        msg.sender,
        claimAmount
    );
    return true;
}
  • 错误定义:0 地址是抛出这个错误
error ZeroAddress();

上面解释加了一个我们 L2RewardManager 合约里面没有用到的东西。

三. 合约定义

在 Solidity 中,定义合约包括声明合约的名称、设置合约的状态变量、编写函数和事件等。 L2RewardManager 是一个详细的合约定义示例,我们上面也简单解释了这个合约。

留言
全部评论(0)