写点什么

分红派息合约的函数逻辑是怎么实现的?附分红合约代码及教程

作者:加密先生
  • 2023-02-08
    广东
  • 本文字数:2932 字

    阅读完需:约 10 分钟

分红派息型智能合约其实很好理解,就是给予持币用户或者 LP 用户一部分的分红。在区块链的世界里,可以将每个人分红的比例提前写入智能合约,然后由合约自动分配,这样就大大提高分红的公平性和便利性。


具体应该如何创建一个这样的分红合约呢?接下来给大家演示一下。


分红派息合约的函数逻辑是怎么实现的?附分红合约代码及教程


分红合约逻辑分红合约(PaymentSplit)具有以下几个特点:


在创建合约时定好分红受益人 payees 和每人的份额 shares。份额可以是相等,也可以是其他任意比例。在该合约收到的所有 ETH 中,每个受益人将能够提取与其分配的份额成比例的金额。分红合约遵循 Pull Payment 模式,付款不会自动转入账户,而是保存在此合约中。受益人通过调用 release()函数触发实际转账。// SPDX-License-Identifier: MITpragma solidity ^0.8.4;


/**


  • 分红合约

  • @dev 这个合约会把收到的 ETH 按事先定好的份额分给几个账户。收到 ETH 会存在分红合约中,需要每个受益人调用 release()函数来领取。*/contract PaymentSplit{分红合约事件分红合约中共有 3 个事件:


PayeeAdded:增加受益人事件。PaymentReleased:受益人提款事件。PaymentReceived:分红合约收款事件。// 事件 event PayeeAdded(address account, uint256 shares); // 增加受益人事件 event PaymentReleased(address to, uint256 amount); // 受益人提款事件 event PaymentReceived(address from, uint256 amount); // 合约收款事件分红合约状态变量分红合约中共有 5 个状态变量,用来记录受益地址、份额、支付出去的 ETH 等变量:


totalShares:总份额,为 shares 的和。totalReleased:从分红合约向受益人支付出去的 ETH,为 released 的和。payees:address 数组,记录受益人地址 shares:address 到 uint256 的映射,记录每个受益人的份额。released:address 到 uint256 的映射,记录分红合约支付给每个受益人的金额。uint256 public totalShares; // 总份额 uint256 public totalReleased; // 总支付


mapping(address => uint256) public shares; // 每个受益人的份额mapping(address => uint256) public released; // 支付给每个受益人的金额address[] public payees; // 受益人数组
复制代码


分红合约函数分红合约中共有 6 个函数:


构造函数:始化受益人数组_payees 和分红份额数组_shares,其中数组长度不能为 0,两个数组长度要相等。_shares 中元素要大于 0,_payees 中地址不能为 0 地址且不能有重复地址。receive():回调函数,在分红合约收到 ETH 时释放 PaymentReceived 事件。release():分红函数,为有效受益人地址_account 分配相应的 ETH。任何人都可以触发这个函数,但 ETH 会转给受益人地址 account。调用了 releasable()函数。releasable():计算一个受益人地址应领取的 ETH。调用了 pendingPayment()函数。pendingPayment():根据受益人地址_account, 分红合约总收入_totalReceived 和该地址已领取的钱_alreadyReleased,计算该受益人现在应分的 ETH。_addPayee():新增受益人函数及其份额函数。在合约初始化的时候被调用,之后不能修改。/*** @dev 初始化受益人数组_payees 和分红份额数组_shares* 数组长度不能为 0,两个数组长度要相等。_shares 中元素要大于 0,_payees 中地址不能为 0 地址且不能有重复地址*/constructor(address[] memory _payees, uint256[] memory _shares) payable {// 检查_payees 和_shares 数组长度相同,且不为 0require(_payees.length == _shares.length, "PaymentSplitter: payees and shares length mismatch");require(_payees.length > 0, "PaymentSplitter: no payees");// 调用_addPayee,更新受益人地址 payees、受益人份额 shares 和总份额 totalSharesfor (uint256 i = 0; i < _payees.length; i++) {_addPayee(_payees[i], _shares[i]);}}


/** * @dev 回调函数,收到ETH释放PaymentReceived事件 */receive() external payable virtual {    emit PaymentReceived(msg.sender, msg.value);}
/** * @dev 为有效受益人地址_account分帐,相应的ETH直接发送到受益人地址。任何人都可以触发这个函数,但钱会打给account地址。 * 调用了releasable()函数。 */function release(address payable _account) public virtual { // account必须是有效受益人 require(shares[_account] > 0, "PaymentSplitter: account has no shares"); // 计算account应得的eth uint256 payment = releasable(_account); // 应得的eth不能为0 require(payment != 0, "PaymentSplitter: account is not due payment"); // 更新总支付totalReleased和支付给每个受益人的金额released totalReleased += payment; released[_account] += payment; // 转账 _account.transfer(payment); emit PaymentReleased(_account, payment);}
/** * @dev 计算一个账户能够领取的eth。 * 调用了pendingPayment()函数。 */function releasable(address _account) public view returns (uint256) { // 计算分红合约总收入totalReceived uint256 totalReceived = address(this).balance + totalReleased; // 调用_pendingPayment计算account应得的ETH return pendingPayment(_account, totalReceived, released[_account]);}
/** * @dev 根据受益人地址`_account`, 分红合约总收入`_totalReceived`和该地址已领取的钱`_alreadyReleased`,计算该受益人现在应分的`ETH`。 */function pendingPayment( address _account, uint256 _totalReceived, uint256 _alreadyReleased) public view returns (uint256) { // account应得的ETH = 总应得ETH - 已领到的ETH return (_totalReceived * shares[_account]) / totalShares - _alreadyReleased;}
/** * @dev 新增受益人_account以及对应的份额_accountShares。只能在构造器中被调用,不能修改。 */function _addPayee(address _account, uint256 _accountShares) private { // 检查_account不为0地址 require(_account != address(0), "PaymentSplitter: account is the zero address"); // 检查_accountShares不为0 require(_accountShares > 0, "PaymentSplitter: shares are 0"); // 检查_account不重复 require(shares[_account] == 0, "PaymentSplitter: account already has shares"); // 更新payees,shares和totalShares payees.push(_account); shares[_account] = _accountShares; totalShares += _accountShares; // 释放增加受益人事件 emit PayeeAdded(_account, _accountShares);}
复制代码


分红合约 Remix 演示


  1. 部署 PaymentSplit 分红合约,并转入 1 ETH 在构造函数中,输入两个受益人地址,份额为 1 和 3。

  2. 查看受益人地址、份额、应分到的 ETH 查看第一位受益人

  3. 函数领取 ETH 调用 release

  4. 查看总支出、受益人余额、应分到的 ETH 的变化查看


总结以上是以太坊及兼容链的分红合约实战演练,相关的代码在文章中也已经给出。学会了以太坊的合约逻辑,那么再开发币安智能链、火币智能链等合约的时候就很方便了。大家对此有疑问,或者想要开发一个这类型的合约,可以联系:微信号:btc6540,或者是电报飞机号:@btc6540

用户头像

加密先生

关注

区块链dapp开发,v:btc6540 2023-02-07 加入

区块链工程师,专业开发

评论

发布
暂无评论
分红派息合约的函数逻辑是怎么实现的?附分红合约代码及教程_加密先生_InfoQ写作社区