月亮链 月亮链
Ctrl+D收藏月亮链

PAY:创建 ERC20 代币支付拆分智能合约_TOKEN

作者:

时间:1900/1/1 0:00:00

在加密货币的几乎每个领域,支付都是一个反复出现的话题,特别是向多个质押者提供支付。例如,DAO希望为多个计划提供资金,DEX希望合并向某些参与者分配交易费用,或者团队希望将代币作为月薪分发给团队成员。

智能合约使我们能够自动化这些类型的支付功能,这就限制了人工管理支付所导致的潜在错误,并允许我们将宝贵的时间花在其他生产性任务上。

今天,我们将学习如何创建自己的ERC20代币支付拆分器,它可以合并到任何项目中!

下面的内容要求你对Solidity有点熟悉,不过任何人都可以学习。

我们将创建两个合约。第一个将是ERC20代币支付拆分智能合约,第二个将是模拟池智能合约。ERC20代币支付拆分器智能合约将是抽象的,并持有用于管理收付方及其各自支付部分的逻辑和数据。模拟池将继承ERC20代币支付拆分器,以便我们可以自动将支付分发给多个质押者。在两个合约中拆分支付功能的原因有两个:

展示在真实世界的用例中代币支付拆分合约的使用

确保代币支付拆分合约足够灵活,任何人都可以选择并集成到自己的项目中

OpenZeppelin已有一个名为PaymentSplitter

SafeERC20

paymentToken是我们用于支付的ERC20代币的地址。

_totalShares提供来自所有收款人的份额相加。

_totalTokenReleased是已支付给所有收款人的支付代币总额。

_payees提供了当前所有收款人地址的数组。

_shares是收款人地址与分配给他们的份额数量的映射。

_tokenReleased是收款人地址到支付代币数量的映射。

现在放置一个接受三个参数的构造函数。第一个参数是我们希望在合约部署中初始化的收款人的数组。第二个参数是每个收款人的份额数组。第三个是将用于支付的ERC20代币的地址。

pragma solidity 0

构造函数包含一个require语句,以确保两个数组具有相同的长度,以便每个收款人都有分配给他们的份额。还有另一个require语句,以确保合约初始化与至少有一个收款人。

Alethea AI获得1600万美元以创建NFTMetaverse:8月24日消息,创建首个智能NFT的元宇宙AI基础设施服务商Alethea AI通过代币销售获得1600万美元资金,以构建一个由其机器人居住的元宇宙。此次代币销售的主要投资者包括NFT基金Metapurse、投资公司Crypto

function shares(address account) public view returns (uint256) { ? ?return _shares[account];}function payee(uint256 index) public view returns (address) { ? ?return _payees[index];}

现在我们将创建用于添加收款人的函数。

pragma solidity 0

_addPayee是我们在构造函数中调用的用于设置收款人数组的函数。这个函数有两个参数,收款人的帐户和与其相关的份额数量。然后它会检查账户是否为零地址,份额是否大于零,以及该账户是否已经注册为收款人。如果所有检查都通过,那么我们将数据添加到各自的变量中。

现在让我们添加一个函数来支持将代币分发给收款人。

pragma solidity 0

Release是一个任何人都可以调用的函数,它接受一个现有收款人帐户的参数。来分析一下这个函数中发生了什么。首先,它检查帐户是否有分配给它的份额。然后,它创建一个名为tokenTotalReceived的变量,该变量将合约的当前代币余额与之前释放的代币总数相加。创建另一个称为payment的变量,该变量确定收到的代币总额中有多少是欠账户的,然后减去多少已经释放到账户。然后,一个require语句检查当前支付金额是否大于零(即,当前是否欠下了更多代币)。如果该检查通过,则更新账户的tokenReleased,并更新totalTokenReleased。最后,支付给账户的代币金额被转账。

布林带指标创建者:目前比特币价格在43000美元左右符合逻辑:金色财经报道,布林带指标的创建者John Bollinger发推表示,目前比特币价格在43000美元左右是符合逻辑的水平,它是由1月份的峰值和3月份的低谷定义的。[2021/5/19 22:17:05]

现在函数已经就位了!但是这个合约还有一件事要做....事件!

我们将在合约中添加两个事件,将事件添加到合约顶部是一个良好的实践。

pragma solidity 0

function release(address account) public virtual { ? ?///existingFunctionCode ? ?emit PaymentReleased(account, payment);}

现在代币支付拆分合约已经建立!为了理解这在真实场景中是如何工作的,让我们创建一个模拟池合约,它将导入代币支付拆分器。

这个合约不会很复杂,因为我们只是想演示如何集成代币支付拆分器。这个合约定期收到我们想分发给收款人列表的特定ERC20代币。这个ERC20代币可以通过不同的场景到达,比如用户存款或来自另一个智能合约的重定向费用。在现实生活中,根据不同的项目,可能会有一个更复杂的合约,包含更多的功能来满足用户的用例。

在合约文件夹中,创建一个名为 MockPool.sol 的新文件。然后添加以下代码。

pragma solidity ^0.8.0;import " ? ?function drainTo(address _transferTo, address _token) public onlyOwner { ? ? ? ?require( ? ? ? ?_token != paymentToken, ? ? ? ?"MockPool: Token to drain is PaymentToken" ? ? ? ?); ? ? ? ?uint256 balance = IERC20(_token).balanceOf(address(this)); ? ? ? ?require(balance > 0, "MockPool: Token to drain balance is 0"); ? ? ? ?IERC20(_token).safeTransfer(_transferTo, balance); ? ?}}

在这份合约中,导入三样东西。首先是OpenZeppelin的Ownable实用程序,它在某些函数上使用唯一的onlyOwner 修饰符。第二个是SafeERC20,它允许安全的ERC20代币转账,正如将在合约中看到。第三个是我们的TokenPaymentSplitter合约。

动态 | EOS Canada 发起 “eosio.forum 创建与设置” 的提案:据IMEOS报道,EOS Canada 创建了一个多重签名提案供超级节点审核,希望将此合约部署到系统合约账户 eosio.forum,以便所有用户都能了解这是可信任的官方公投合约。目前改提案正在EOS Authority上进行BP投票。

该多重签名提案三个步骤如下:1. 创建 eosio.forum 帐户2. 购买 300 KB 的 RAM 用于存储合约和 ABI 文件3. 智能合约和 ABI 文件将部署到链上。[2018/11/30]

在MockPool构造函数中,我们需要TokenPaymentSplitter提供相同的三个参数,我们只是将它们传递给我们继承的合约。

在这个合约中添加了另一个函数,drainTo。它实际上与TokenPaymentSplitter合约没有任何关系。它只是在另一个没有设置为支付代币的ERC20代币被发送到池时的一种安全机制,然后有一种方法让合约所有者释放该代币。

测试智能合约与创建它们同样重要。这些合约处理的资产通常是属于其他人的,所以作为开发人员,我们有责任确保这些资产按照他们应该的方式工作,并且我们的测试可以覆盖几乎所有的边缘情况。

将在这里进行的测试是一些示例,以显示TokenPaymentSplitter智能合约按照我们的预期工作。在处理自己的项目时,可能希望创建专门适合自己的用例的测试。

为了支持我们的测试,我们希望包含一个ERC20代币,为此,我们将创建一个新的solididity文件,该文件导入OpenZepplin ERC20模板以供我们的测试使用。在合约文件夹中,创建一个名为Imports.sol 的新文件,并包括以下代码:

pragma solidity ^0.8.0;import "

现在,在test文件夹中创建一个名为test.js的文件。在这个文件的顶部,我们将导入支持我们的测试的包。

const { expect } = require('chai')const { ethers } = require('hardhat')

现在,为了设置测试,我们将首先创建必要的变量,创建beforeEach函数,该函数在每次测试之前调用,并创建一个空的 describe 函数,该函数将很快包含我们的测试。

describe('TokenPaymentSplitter Tests', () => {let deployerlet account1let account2let account3let account4let testPaymentTokenlet mockPoolbeforeEach(async () => { ? ?[deployer, account1, account2, account3, account4] = await ethers.getSigners() ? ?const TestPaymentToken = await ethers.getContractFactory('ERC20PresetMinterPauser') ? ?testPaymentToken = await TestPaymentToken.deploy('TestPaymentToken', 'TPT') ? ?await testPaymentToken.deployed(。)describe('Add payees with varying amounts and distribute payments', async () => {}}

在这些部分就位后,让我们进入这些测试的核心部分!

在我们的第一个测试中,我们想看看当我们部署一个包含平均分配份额的收款人列表的合约时会发生什么。下面是测试代码。

动态 | 嘉楠耘智前首席芯片工程师创建矿机制造企业:据coindesk报道,嘉楠耘智的前首席芯片工程师Chen Min建立了名为Linzhi的合资企业以制造加密货币挖矿设备。该公司的首个计划Lavasnow将处理以太坊和以太经典所使用的ethhash算法,预计明年将推出ASIC矿机系列。根据Chen Min本周在以太坊经典峰会发布的报告, Linzhi的新以太坊矿机使用的电量是比特大陆ethash矿机的1/8,预计每秒运行14亿哈希值。这意味着 Linzhi矿机每天能产出约20美元,相比之下比特大陆矿机预计产出为3美元。该公司希望客户在购买矿机后的四个月内就实现收支平衡。目前,该公司仍在努力开发该产品,预计客户会在2019年4月开始收到矿机。[2018/9/14]

it('payment token is distributed evenly to multiple payees', async () => { ? ?payeeAddressArray = [account1.address, account2.address, account3.address, account4.address] ? ?payeeShareArray = [10, 10, 10, 10] ? ?const MockPool = await ethers.getContractFactory('MockPool') ? ?mockPool = await MockPool.deploy( ? ? ? ?payeeAddressArray, ? ? ? ?payeeShareArray, ? ? ? ?testPaymentToken.address ? ?) ? ?await mockPool.deployed() ? ?await testPaymentToken.mint(mockPool.address, 100000) ? ?await mockPool ? ? ? ?.connect(account1) ? ? ? ?.release(account1.address) ? ?await mockPool ? ? ? ?.connect(account2) ? ? ? ?.release(account2.address) ? ?await mockPool ? ? ? ?.connect(account3) ? ? ? ?.release(account3.address) ? ?await mockPool ? ? ? ?.connect(account4) ? ? ? ?.release(account4.address) ? ?const account1TokenBalance = await testPaymentToken.balanceOf(account1.address) ? ?const account2TokenBalance = await testPaymentToken.balanceOf(account2.address) ? ?const account3TokenBalance = await testPaymentToken.balanceOf(account3.address) ? ?const account4TokenBalance = await testPaymentToken.balanceOf(account4.address) ? ?expect(account1TokenBalance).to.equal(25000) ? ?expect(account2TokenBalance).to.equal(25000) ? ?expect(account3TokenBalance).to.equal(25000) ? ?expect(account4TokenBalance).to.equal(25000。)

在这个测试中,我们将合约分配给4个收款人,每个人都有10个相同的份额。然后我们向合约发送100000单位的testPaymentToken,并向每个收款人发放付款。在测试中可以注意到,每个收款人都在调用函数来向自己释放代币。

在第二个测试中,我们希望确保即使每个收款人的份额分配不均,数学计算仍然有效。

it('payment token is distributed unevenly to multiple payees', async () => { ? ?payeeAddressArray = [account1.address, account2.address, account3.address, account4.address] ? ?payeeShareArray = [10, 5, 11, 7] ? ?const MockPool = await ethers.getContractFactory('MockPool') ? ?mockPool = await MockPool.deploy( ? ? ? ?payeeAddressArray, ? ? ? ?payeeShareArray, ? ? ? ?testPaymentToken.address ? ?) ? ?await mockPool.deployed() ? ?await testPaymentToken.mint(mockPool.address, 100000) ? ?await mockPool ? ? ? ?.connect(account1) ? ? ? ?.release(account1.address) ? ?await mockPool ? ? ? ?.connect(account2) ? ? ? ?.release(account2.address) ? ?await mockPool ? ? ? ?.connect(account3) ? ? ? ?.release(account3.address) ? ?await mockPool ? ? ? ?.connect(account4) ? ? ? ?.release(account4.address) ? ?const mockPoolTestPaymentTokenBalance = await testPaymentToken.balanceOf( ? ? ? ?mockPool.address ? ?) ? ?const account1TokenBalance = await testPaymentToken.balanceOf(account1.address) ? ?const account2TokenBalance = await testPaymentToken.balanceOf(account2.address) ? ?const account3TokenBalance = await testPaymentToken.balanceOf(account3.address) ? ?const account4TokenBalance = await testPaymentToken.balanceOf(account4.address) ? ?expect(mockPoolTestPaymentTokenBalance).to.equal(1) ? ?expect(account1TokenBalance).to.equal(30303) ? ?expect(account2TokenBalance).to.equal(15151) ? ?expect(account3TokenBalance).to.equal(33333) ? ?expect(account4TokenBalance).to.equal(21212。)

看起来收款人还能拿到钱,但注意到什么了吗?合约中还剩下一个单位的支付代币!由于Solidity没有小数,当它达到最低单位时,它通常会四舍五入,这可能会导致合约尘埃飞扬,就像我们在这里看到的。不过不用担心,因为我们预计未来会有支付代币流入合约,所以它将继续分发。

这与之前的测试类似,不过在资金被释放给收款人之间增加了更多支付代币发送到池中。这表明,随着支付代币不断流入模拟池合约,数学仍然可以确保收款人收到正确的金额。

it('payment token is distributed unevenly to multiple payees with additional payment token sent to pool', async () => { ? ?payeeAddressArray = [account1.address, account2.address, account3.address, account4.address] ? ?payeeShareArray = [10, 5, 11, 7] ? ?const MockPool = await ethers.getContractFactory('MockPool') ? ?mockPool = await MockPool.deploy( ? ? ? ?payeeAddressArray, ? ? ? ?payeeShareArray, ? ? ? ?testPaymentToken.address ? ?) ? ?await mockPool.deployed() ? ?await testPaymentToken.mint(mockPool.address, 100000) ? ?await mockPool ? ? ? ?.connect(account1) ? ? ? ?.release(account1.address) ? ?await mockPool ? ? ? ?.connect(account2) ? ? ? ?.release(account2.address) ? ?await testPaymentToken.mint(mockPool.address, 100000) ? ?await mockPool ? ? ? ?.connect(account3) ? ? ? ?.release(account3.address) ? ?await mockPool ? ? ? ?.connect(account4) ? ? ? ?.release(account4.address) ? ?await mockPool ? ? ? ?.connect(account1) ? ? ? ?.release(account1.address) ? ?await mockPool ? ? ? ?.connect(account2) ? ? ? ?.release(account2.address) ? ?const mockPoolTestPaymentTokenBalance = await testPaymentToken.balanceOf( ? ? ? ?mockPool.address ? ? ? ? ? ?) ? ?const account1TokenBalance = await testPaymentToken.balanceOf(account1.address) ? ?const account2TokenBalance = await testPaymentToken.balanceOf(account2.address) ? ?const account3TokenBalance = await testPaymentToken.balanceOf(account3.address) ? ?const account4TokenBalance = await testPaymentToken.balanceOf(account4.address) ? ?expect(mockPoolTestPaymentTokenBalance).to.equal(1) ? ?expect(account1TokenBalance).to.equal(60606) ? ?expect(account2TokenBalance).to.equal(30303) ? ?expect(account3TokenBalance).to.equal(66666) ? ?expect(account4TokenBalance).to.equal(42424。)

现在所有的测试都就绪了,是时候运行它们了,看看它们是否工作!在项目根文件夹中,使用npx hardhat test启动测试。如果一切都是正确的,那么你应该看到如下图所示的所有绿色格子。

如上所述,我们需要做更多的测试,以确保整个项目/协议按照预期工作,支付拆分器是它的集成部分。这将意味着更多的单元测试来覆盖所有可用的功能,以及更复杂的集成测试,这取决于具体用例。

支付是许多加密协议的一个常见方面,有几种方法可以解决它们。今天我们学习了一种管理支付的方法,尽管用户甚至可以在此合约的基础上构建以满足您的特定需求,如跨多个代币启用支付,添加额外的收款人或移除收款人,或在一个函数调用中同时分发所有支付。

Source:https://medium.com/coinmonks/create-an-erc20-token-payment-splitting-smart-contract-c79436470ccc

标签:PAYTOKTOKENKENGPAY3X Long TomoChain TokenX-TOKENOctane Protocol Token

POL币最新价格热门资讯
SOL:金色观察 | Solana网络故障近18小时 已重新启动_SOLA

截至北京时间9月15日10时,Solana主网 Beta 版间隙性不稳定已达 12 小时,Solana 链上应用至今无法正常运转.

1900/1/1 0:00:00
区块链:解读央行虚拟货币新规 炒币违法吗?_EOS

2021年9月24日,央行在其官网公布了《关于进一步防范和处置虚拟货币交易炒作风险的通知》(以下称《通知》),进一步明确虚拟货币及相关虚拟货币活动的属性.

1900/1/1 0:00:00
NFT:NFT渗入电影发行 区块链世界里岁月不老_区块链币是什么币

NFT在拍卖场上的火热依旧延续,这一次的主角是导演王家卫的代表作之一《花样年华》。近日,香港苏富比联手王家卫推出首个亚洲电影NFT《花样年华——一刹那》,将于下月9日登陆现代艺术晚拍.

1900/1/1 0:00:00
DEF:金色DeFi日报 | Vee.Finance官方确认超3500万美元资产被盗_DeFinition

DeFi数据1.DeFi总市值:1148.6亿美元 DeFi总市值数据来源:Coingecko2.过去24小时去中心化交易所的交易量:54.

1900/1/1 0:00:00
SOL:数读热门公链 Solana:总锁仓额超 116 亿美元 1583 个大户地址总持仓 4 亿枚_LANA

Solana 生态应用增长迅速,其生态已涵盖了 DeFi、NFT 等多个领域,目前 DeFi 是其最重要的组成部分.

1900/1/1 0:00:00
NFT:NFT社交属性更进一步:Twitter账户如何绑定并认证NFT头像_ITT

Twitter 上周宣布该公司正在进行 NFT 作品的认证功能,这意味着推特用户将可以在其账户下绑定所拥有的 NFT 并认证所有权。并且用户可以将通过认证的 NFT 作为其推特头像.

1900/1/1 0:00:00