openzeppelin-solidity/contracts的代码学习——payment
payment - A collection of smart contracts that can be used to manage payments through escrow arrangements, withdrawals, and claims. Includes support for both single payees and multiple payees.(这个是不是就是token中withdrawl的来源,要好好看看,在博客的the security of smart有写)
临时账户:其实就是一个映射,在下面例子即deposits_,存储某address应该从合约中取出的钱数
下面这里的代码是openzepplin中写的有关实现临时账户的标准,值得学习,我们学习类似cryptopunks的代码的时候就发现他们是这么写的
https://github.com/OpenZeppelin/openzeppelin-solidity/tree/master/contracts/payment
Escrow.sol
- pragma solidity ^0.4.23;
- import "../math/SafeMath.sol";
- import "../ownership/Ownable.sol";
- /**
- * @title Escrow
- * @dev Base escrow contract, holds funds destinated to a payee until they
- * withdraw them. The contract that uses the escrow as its payment method
- * should be its owner, and provide public methods redirecting to the escrow's
- * deposit and withdraw.
- */
- contract Escrow is Ownable {
- using SafeMath for uint256;
- event Deposited(address indexed payee, uint256 weiAmount);
- event Withdrawn(address indexed payee, uint256 weiAmount);
- mapping(address => uint256) private deposits_;
- //得到临时账户中的余额
- function depositsOf(address _payee) public view returns (uint256) {
- return deposits_[_payee];
- }
- /**
- * @dev Stores the sent amount as credit to be withdrawn.
- * @param _payee The destination address of the funds.
- */
//往临时账户中存钱,因为声明为payable,所以调用该函数的address通过将msg.value数量的金额传给了合约地址,并同时将数额写到临时账户deposits_上- function deposit(address _payee) public onlyOwner payable {
- uint256 amount = msg.value;//为什么不直接用msg.value进行add运算,是这样更安全吗??????
- deposits_[_payee] = deposits_[_payee].add(amount);//为了安全,不使用+来直接运算,而是使用SafeMath.sol中的函数
- emit Deposited(_payee, amount);
- }
- /**
- * @dev Withdraw accumulated balance for a payee.
- * @param _payee The address whose funds will be withdrawn and transferred to.
- */
- //从合约地址中取出临时账户上的所有钱,并将临时账户上的数额清零
- function withdraw(address _payee) public onlyOwner {
- uint256 payment = deposits_[_payee];
- assert(address(this).balance >= payment);//原本是this.balance来得到当前账户地址上的余额??????,address(this)就是是显示转换成合约地址为address类型
- deposits_[_payee] = 0;
- _payee.transfer(payment);
- emit Withdrawn(_payee, payment);
- }
- }
疑惑address(this).balance的解决,(这里的this代表的是合约的地址):
- pragma solidity ^0.4.24;
contract Get{
//查询当前的余额- function getBalance() public view returns(uint){
- return this.balance;
- }
event SendEvent(address to, uint value, bool result);
//使用send()发送ether,观察会触发fallback函数
function sendEther() public{
bool result = this.send(1);
emit SendEvent(this, 1, result);
}
当想要使用this.balance这么写得到账户的余额时,remix编译中会报警告:
- Warning:Using contract member "balance" inherited from the address type is deprecated.Convert the contract to "address" type to access the member,for example use "address(contract).balance" instead.
除此之外,使用this.send也是会报相似的警告:
- Warning:Using contract member "send" inherited from the address type is deprecated.Convert the contract to "address" type to access the member,for example use "address(contract).send" instead.
这就是this.balance为什么改为address(this).balance的原因,在这里this.send也要改为address(this).send
PullPayment.sol
- pragma solidity ^0.4.;
- import "./Escrow.sol";
- /**
- * @title PullPayment
- * @dev Base contract supporting async send for pull payments. Inherit from this
- * contract and use asyncTransfer instead of send or transfer.
- */
- contract PullPayment {
- Escrow private escrow;
- constructor() public {
- escrow = new Escrow();
- }
- /**
- * @dev Withdraw accumulated balance, called by payee.
- */
- //取钱
- function withdrawPayments() public {
- address payee = msg.sender;
- escrow.withdraw(payee);
- }
- /**
- * @dev Returns the credit owed to an address.
- * @param _dest The creditor's address.
- */
- //查余额
- function payments(address _dest) public view returns (uint256) {
- return escrow.depositsOf(_dest);
- }
- /**
- * @dev Called by the payer to store the sent amount as credit to be pulled.
- * @param _dest The destination address of the funds.
- * @param _amount The amount to transfer.
- */
- //向临时账户中存钱
- function asyncTransfer(address _dest, uint256 _amount) internal {
- escrow.deposit.value(_amount)(_dest);//形如someAddress.call.value()() ,因为deposit是payable的,value(_amount)相当于{value:_amount}
- }
- }
contracts/payment/ConditionalEscrow.sol
就是当某条件允许时才能够将临时账户中的钱取出
该函数为abstract函数
- pragma solidity ^0.4.;
- import "./Escrow.sol";
- /**
- * @title ConditionalEscrow
- * @dev Base abstract escrow to only allow withdrawal if a condition is met.
- */
- contract ConditionalEscrow is Escrow {
- /**
- * @dev Returns whether an address is allowed to withdraw their funds. To be
- * implemented by derived contracts.
- * @param _payee The destination address of the funds.
- */
- function withdrawalAllowed(address _payee) public view returns (bool);
- function withdraw(address _payee) public {
- require(withdrawalAllowed(_payee));//只有满足情况了才能withdraw,下面即实现例子RefundEscrow.sol
- super.withdraw(_payee);
- }
- }
contracts/payment/RefundEscrow.sol
当账户状态为Refunding时,存钱的人能把存的钱取回
当账户状态为Closed时,受益人才能把账户中的钱取出
- pragma solidity ^0.4.;
- import "./ConditionalEscrow.sol";
- import "../ownership/Ownable.sol";
- /**
- * @title RefundEscrow
- * @dev Escrow that holds funds for a beneficiary(收益人), deposited from multiple parties.
- * The contract owner may close the deposit period, and allow for either withdrawal
- * by the beneficiary, or refunds to the depositors.
- */
- contract RefundEscrow is Ownable, ConditionalEscrow {
- enum State { Active, Refunding, Closed }
- event Closed();
- event RefundsEnabled();
- State public state;
- address public beneficiary;
- /**
- * @dev Constructor.
- * @param _beneficiary The beneficiary of the deposits.
- */
- constructor(address _beneficiary) public {//声明受益人,此时账户状态为Active
- require(_beneficiary != address());
- beneficiary = _beneficiary;
- state = State.Active;
- }
- /**
- * @dev Stores funds that may later be refunded.
- * @param _refundee The address funds will be sent to if a refund occurs.
- */
- function deposit(address _refundee) public payable {//往账户存钱
- require(state == State.Active);
- super.deposit(_refundee);//使用的是super,即父合约而不是this本合约
- }
- /**
- * @dev Allows for the beneficiary to withdraw their funds, rejecting
- * further deposits.
- */
- function close() public onlyOwner {//当账户状态为Closed,就不能再往里面存钱了,只能受益人取钱
- require(state == State.Active);
- state = State.Closed;
- emit Closed();
- }
- /**
- * @dev Allows for refunds to take place, rejecting further deposits.
- */
- function enableRefunds() public onlyOwner {
- require(state == State.Active);
- state = State.Refunding;
- emit RefundsEnabled();
- }
- /**
- * @dev Withdraws the beneficiary's funds.
- */
- function beneficiaryWithdraw() public {//受益人取钱
- require(state == State.Closed);
- beneficiary.transfer(address(this).balance);
- }
- /**
- * @dev Returns whether refundees can withdraw their deposits (be refunded).
- */
- function withdrawalAllowed(address _payee) public view returns (bool) {//当账户状态为Refunding时,存钱的人能把存的钱取回
- return state == State.Refunding;
- }
- }
contracts/payment/SplitPayment.sol
付款人能够根据自己在该合约生成时付的钱生成的股份shares[payee]占总股份的比例来要求合约返还自己的钱
- pragma solidity ^0.4.;
- import "../math/SafeMath.sol";
- /**
- * @title SplitPayment
- * @dev Base contract that supports multiple payees claiming funds sent to this contract
- * according to the proportion they own.
- */
- contract SplitPayment {
- using SafeMath for uint256;
- uint256 public totalShares = ;
- uint256 public totalReleased = ;
- mapping(address => uint256) public shares;//payee所拥有的股份
- mapping(address => uint256) public released;//合约已经还给payee的钱
- address[] public payees;
- /**
- * @dev Constructor
- */
- constructor(address[] _payees, uint256[] _shares) public payable {
- require(_payees.length == _shares.length);
- require(_payees.length > );
- for (uint256 i = ; i < _payees.length; i++) {//在该合约创建的时候_payee就都加到该合约中了,比例也是早就算好的
- _addPayee(_payees[i], _shares[i]);
- }
- }
- /**
- * @dev payable fallback
- */
- function () external payable {}
- /**
- * @dev Claim your share of the balance.
- */
- function claim() public {
- address payee = msg.sender;
- require(shares[payee] > );
- uint256 totalReceived = address(this).balance.add(totalReleased);//就是合约还回去的钱totalReleased+现在合约中有的钱 = 合约总共收到的钱
- uint256 payment = totalReceived.mul( //等价于((totalReceived*(shares[payee]/totalShares))-released[payee]),就是通过比例算出本payee发给该合约的钱-之前还的钱released[payee] = 还需要还的钱payment
- shares[payee]).div(
- totalShares).sub(
- released[payee]
- );
- require(payment != );
- assert(address(this).balance >= payment);//合约中现在还有的钱要大于payment才能把钱给payee
- released[payee] = released[payee].add(payment);
- totalReleased = totalReleased.add(payment);
- payee.transfer(payment);
- }
- /**
- * @dev Add a new payee to the contract.
- * @param _payee The address of the payee to add.
- * @param _shares The number of shares owned by the payee.
- */
- function _addPayee(address _payee, uint256 _shares) internal {
- require(_payee != address());
- require(_shares > );
- require(shares[_payee] == );
- payees.push(_payee);
- shares[_payee] = _shares;
- totalShares = totalShares.add(_shares);
- }
- }
⚠️:Add a leading underscore to internal and private functions,要在internal and private函数的名字前加下划线
openzeppelin-solidity/contracts的代码学习——payment的更多相关文章
- openzeppelin-solidity/contracts的代码学习——access
https://github.com/OpenZeppelin/openzeppelin-solidity/tree/master/contracts/access access - Smart co ...
- u-boot代码学习内容
前言 u-boot代码庞大,不可能全部细读,只能有选择的读部分代码.在读代码之前,根据韦东山教材,关于代码学习内容和深度做以下预先划定. 一.Makefile.mkconfig.config.mk等 ...
- Objective-C代码学习大纲(3)
Objective-C代码学习大纲(3) 2011-05-11 14:06 佚名 otierney 字号:T | T 本文为台湾出版的<Objective-C学习大纲>的翻译文档,系统介绍 ...
- ORB-SLAM2 论文&代码学习 ——Tracking 线程
本文要点: ORB-SLAM2 Tracking 线程 论文内容介绍 ORB-SLAM2 Tracking 线程 代码结构介绍 写在前面 上一篇文章中我们已经对 ORB-SLAM2 系统有了一个概览性 ...
- ORB-SLAM2 论文&代码学习 —— 单目初始化
转载请注明出处,谢谢 原创作者:Mingrui 原创链接:https://www.cnblogs.com/MingruiYu/p/12358458.html 本文要点: ORB-SLAM2 单目初始化 ...
- ORB-SLAM2 论文&代码学习 —— LocalMapping 线程
转载请注明出处,谢谢 原创作者:Mingrui 原创链接:https://www.cnblogs.com/MingruiYu/p/12360913.html 本文要点: ORB-SLAM2 Local ...
- Learning Memory-guided Normality代码学习笔记
Learning Memory-guided Normality代码学习笔记 记忆模块核心 Memory部分的核心在于以下定义Memory类的部分. class Memory(nn.Module): ...
- 3.1.5 LTP(Linux Test Project)学习(五)-LTP代码学习
3.1.5 LTP(Linux Test Project)学习(五)-LTP代码学习 Hello小崔 华为技术有限公司 Linux内核开发 2 人赞同了该文章 LTP代码学习方法主要介绍两个步骤, ...
- Apollo代码学习(七)—MPC与LQR比较
前言 Apollo中用到了PID.MPC和LQR三种控制器,其中,MPC和LQR控制器在状态方程的形式.状态变量的形式.目标函数的形式等有诸多相似之处,因此结合自己目前了解到的信息,将两者进行一定的比 ...
随机推荐
- MQTT再学习 -- MQTT 客户端源码分析
MQTT 源码分析,搜索了一下发现网络上讲的很少,多是逍遥子的那几篇. 参看:逍遥子_mosquitto源码分析系列 参看:MQTT libmosquitto源码分析 参看:Mosquitto学习笔记 ...
- Dynamics CRM 2016/365 窗体中添加按钮
一.工具下载,及界面介绍 1.下载XrmToolBox工具(XrmToolBox for Microsoft Dynamics CRM/365 CE) 链接:https://www.xrmtoolbo ...
- 【Spring】详解spring事务属性
Spring声明式事务让我们从复杂的事务处理中得到解脱.使得我们再也无需要去处理获得连接.关闭连接.事务提交和回滚等这些操作.再也无需要我们在与事务相关的方法中处理大量的try…catch…final ...
- One Person Game(zoj3593+扩展欧几里德)
One Person Game Time Limit:2000MS Memory Limit:65536KB 64bit IO Format:%lld & %llu Submit Status ...
- 封装方法公共文件common.js
/** * Created by Administrator on 2017/3/24. */ /** * 格式化日期 * @param dt 日期对象 * @returns {string} 返回值 ...
- sql server: quering roles, schemas, users,logins
--https://docs.microsoft.com/en-us/sql/relational-databases/security/authentication-access/managing- ...
- encodeURIComponent编码时为什么要编码两次
Why 要对url进行编码? 当使用地址栏提交查询参数时,如果不编码,非英文字符会按照操作系统的字符集进行编码提交到服务器,服务器会按照配置的字符集进行解码,所以如果两者不一致就会导致乱码. Wh ...
- JS中使用document.defaultView.getComputedStyle()、currentStyle()方法获取CSS属性值
在对网页进行调试的过程中,经常会用到js来获取元素的CSS样式,方法有很多很多,现在仅把我经常用的方法总结如: 1. obj.style:这个方法只能JS只能获取写在html标签中的写在style属性 ...
- 本地存储之sessionStorage
源码可以到GitHub上下载! sessionStorage: 关闭浏览器再打开将不保存数据 复制标签页会连同sessionStorage数据一同复制 复制链接地址打开网页不会复制seession ...
- http请求之get和post的区别
前言:大家现在度娘一下,查得最多的区别,可能就是: “Get把参数写在URL中,Post通过请求体来传参的” “GET没有POST安全,因为Get参数直接显示在URL上” “Get请求在URL中传送的 ...