在下面的智能合约代码中,有一个函数正在构造函数内部执行。有人能解释一下构造函数中发生了什么吗
pragma solidity 0.8.7;
import "../interfaces/IAbstractRewards.sol";
import "@openzeppelin/contracts/utils/math/SafeCast.sol";
/**
* @dev Based on: https://github.com/indexed-finance/dividends/blob/master/contracts/base/AbstractDividends.sol
* Renamed dividends to rewards.
* @dev (OLD) Many functions in this contract were taken from this repository:
* https://github.com/atpar/funds-distribution-token/blob/master/contracts/FundsDistributionToken.sol
* which is an example implementation of ERC 2222, the draft for which can be found at
* https://github.com/atpar/funds-distribution-token/blob/master/EIP-DRAFT.md
*
* This contract has been substantially modified from the original and does not comply with ERC 2222.
* Many functions were renamed as "rewards" rather than "funds" and the core functionality was separated
* into this abstract contract which can be inherited by anything tracking ownership of reward shares.
*/
abstract contract AbstractRewards is IAbstractRewards {
using SafeCast for uint128;
using SafeCast for uint256;
using SafeCast for int256;
/* ======== Constants ======== */
uint128 public constant POINTS_MULTIPLIER = type(uint128).max;
/* ======== Internal Function References ======== */
function(address) view returns (uint256) private immutable getSharesOf;
function() view returns (uint256) private immutable getTotalShares;
/* ======== Storage ======== */
uint256 public pointsPerShare;
mapping(address => int256) public pointsCorrection;
mapping(address => uint256) public withdrawnRewards;
constructor(
function(address) view returns (uint256) getSharesOf_,
function() view returns (uint256) getTotalShares_
) {
getSharesOf = getSharesOf_;
getTotalShares = getTotalShares_;
}
/* ======== Public View Functions ======== */
/**
* @dev Returns the total amount of rewards a given address is able to withdraw.
* @param _account Address of a reward recipient
* @return A uint256 representing the rewards `account` can withdraw
*/
function withdrawableRewardsOf(address _account) public view override returns (uint256) {
return cumulativeRewardsOf(_account) - withdrawnRewards[_account];
}
/**
* @notice View the amount of rewards that an address has withdrawn.
* @param _account The address of a token holder.
* @return The amount of rewards that `account` has withdrawn.
*/
function withdrawnRewardsOf(address _account) public view override returns (uint256) {
return withdrawnRewards[_account];
}
/**
* @notice View the amount of rewards that an address has earned in total.
* @dev accumulativeFundsOf(account) = withdrawableRewardsOf(account) + withdrawnRewardsOf(account)
* = (pointsPerShare * balanceOf(account) + pointsCorrection[account]) / POINTS_MULTIPLIER
* @param _account The address of a token holder.
* @return The amount of rewards that `account` has earned in total.
*/
function cumulativeRewardsOf(address _account) public view override returns (uint256) {
return ((pointsPerShare * getSharesOf(_account)).toInt256() + pointsCorrection[_account]).toUint256() / POINTS_MULTIPLIER;
}
/* ======== Dividend Utility Functions ======== */
/**
* @notice Distributes rewards to token holders.
* @dev It reverts if the total shares is 0.
* It emits the `RewardsDistributed` event if the amount to distribute is greater than 0.
* About undistributed rewards:
* In each distribution, there is a small amount which does not get distributed,
* which is `(amount * POINTS_MULTIPLIER) % totalShares()`.
* With a well-chosen `POINTS_MULTIPLIER`, the amount of funds that are not getting
* distributed in a distribution can be less than 1 (base unit).
*/
function _distributeRewards(uint256 _amount) internal {
uint256 shares = getTotalShares();
require(shares > 0, "AbstractRewards._distributeRewards: total share supply is zero");
if (_amount > 0) {
pointsPerShare = pointsPerShare + (_amount * POINTS_MULTIPLIER / shares);
emit RewardsDistributed(msg.sender, _amount);
}
}
/**
* @notice Prepares collection of owed rewards
* @dev It emits a `RewardsWithdrawn` event if the amount of withdrawn rewards is
* greater than 0.
*/
function _prepareCollect(address _account) internal returns (uint256) {
uint256 _withdrawableDividend = withdrawableRewardsOf(_account);
if (_withdrawableDividend > 0) {
withdrawnRewards[_account] = withdrawnRewards[_account] + _withdrawableDividend;
emit RewardsWithdrawn(_account, _withdrawableDividend);
}
return _withdrawableDividend;
}
function _correctPointsForTransfer(address _from, address _to, uint256 _shares) internal {
int256 _magCorrection = (pointsPerShare * _shares).toInt256();
pointsCorrection[_from] = pointsCorrection[_from] + _magCorrection;
pointsCorrection[_to] = pointsCorrection[_to] - _magCorrection;
}
/**
* @dev Increases or decreases the points correction for `account` by
* `shares*pointsPerShare`.
*/
function _correctPoints(address _account, int256 _shares) internal {
pointsCorrection[_account] = pointsCorrection[_account] + (_shares * (int256(pointsPerShare)));
}
}
现在,在下面的智能合约(BasePool(中,它继承了上面的AbstractRewards智能合约。在BasePool合约的构造函数中,balanceOf
和totalSupply
是如何传递到AbstractRewards合约的
abstract contract BasePool is ERC20Votes, AbstractRewards, IBasePool, TokenSaver {
using SafeERC20 for IERC20;
using SafeCast for uint256;
using SafeCast for int256;
IERC20 public immutable depositToken;
IERC20 public immutable rewardToken;
ITimeLockPool public immutable escrowPool;
uint256 public immutable escrowPortion; // how much is escrowed 1e18 == 100%
uint256 public immutable escrowDuration; // escrow duration in seconds
event RewardsClaimed(address indexed _from, address indexed _receiver, uint256 _escrowedAmount, uint256 _nonEscrowedAmount);
constructor(
string memory _name,
string memory _symbol,
address _depositToken,
address _rewardToken,
address _escrowPool,
uint256 _escrowPortion,
uint256 _escrowDuration
) ERC20Permit(_name) ERC20(_name, _symbol) AbstractRewards(balanceOf, totalSupply) {
require(_escrowPortion <= 1e18, "BasePool.constructor: Cannot escrow more than 100%");
require(_depositToken != address(0), "BasePool.constructor: Deposit token must be set");
depositToken = IERC20(_depositToken);
rewardToken = IERC20(_rewardToken);
escrowPool = ITimeLockPool(_escrowPool);
escrowPortion = _escrowPortion;
escrowDuration = _escrowDuration;
if(_rewardToken != address(0) && _escrowPool != address(0)) {
IERC20(_rewardToken).safeApprove(_escrowPool, type(uint256).max);
}
}
function _mint(address _account, uint256 _amount) internal virtual override {
super._mint(_account, _amount);
_correctPoints(_account, -(_amount.toInt256()));
}
function _burn(address _account, uint256 _amount) internal virtual override {
super._burn(_account, _amount);
_correctPoints(_account, _amount.toInt256());
}
function _transfer(address _from, address _to, uint256 _value) internal virtual override {
super._transfer(_from, _to, _value);
_correctPointsForTransfer(_from, _to, _value);
}
function distributeRewards(uint256 _amount) external override {
rewardToken.safeTransferFrom(_msgSender(), address(this), _amount);
_distributeRewards(_amount);
}
function claimRewards(address _receiver) external {
uint256 rewardAmount = _prepareCollect(_msgSender());
uint256 escrowedRewardAmount = rewardAmount * escrowPortion / 1e18;
uint256 nonEscrowedRewardAmount = rewardAmount - escrowedRewardAmount;
if(escrowedRewardAmount != 0 && address(escrowPool) != address(0)) {
escrowPool.deposit(escrowedRewardAmount, escrowDuration, _receiver);
}
// ignore dust
if(nonEscrowedRewardAmount > 1) {
rewardToken.safeTransfer(_receiver, nonEscrowedRewardAmount);
}
emit RewardsClaimed(_msgSender(), _receiver, escrowedRewardAmount, nonEscrowedRewardAmount);
}
}
构造函数是在部署和调用智能合约时首先运行的函数。若构造函数有一个prameter,你们就必须设置它们。如果prameter包含其他智能合约的地址,则必须先部署它。