- Solidity 教程
- Solidity - 主页
- Solidity - 概述
- Solidity - 环境设置
- Solidity - 基本语法
- Solidity - 首次应用
- Solidity - 评论
- 坚固性 - 类型
- Solidity - 变量
- Solidity - 可变范围
- Solidity - 运算符
- 坚固性 - 循环
- Solidity - 决策
- 坚固性 - 弦乐
- Solidity - 数组
- Solidity - 枚举
- Solidity - 结构
- Solidity - 映射
- 坚固性 - 转换
- Solidity - 以太币单位
- Solidity - 特殊变量
- Solidity - 风格指南
- 实体函数
- Solidity - 函数
- Solidity - 函数修饰符
- Solidity - 查看函数
- Solidity - 纯函数
- Solidity - 后备函数
- 函数重载
- 数学函数
- 加密函数
- Solidity 常见模式
- Solidity - 提款模式
- Solidity - 限制访问
- 坚固进阶
- Solidity - 合约
- 坚固性——继承
- Solidity - 构造函数
- Solidity - 抽象合约
- Solidity - 接口
- Solidity - 库
- 坚固性 - 装配
- Solidity - 活动
- Solidity - 错误处理
- Solidity 有用资源
- Solidity - 快速指南
- Solidity - 有用的资源
- 坚固性 - 讨论
Solidity - 提款模式
提款模式确保不会造成安全威胁的直接转接呼叫。以下合约显示了使用转账调用发送以太币的不安全方式。
pragma solidity ^0.5.0;
contract Test {
address payable public richest;
uint public mostSent;
constructor() public payable {
richest = msg.sender;
mostSent = msg.value;
}
function becomeRichest() public payable returns (bool) {
if (msg.value > mostSent) {
// Insecure practice
richest.transfer(msg.value);
richest = msg.sender;
mostSent = msg.value;
return true;
} else {
return false;
}
}
}
通过使最富有的合约成为后备功能失败的合约,可以使上述合约处于不可用状态。当后备函数失败时,becomeRichest()函数也会失败,合约将永远卡住。为了缓解这个问题,我们可以使用 Withdrawal Pattern。
在提款模式中,我们将在每次转账前重置待处理金额。它将确保只有调用者合约失败。
pragma solidity ^0.5.0;
contract Test {
address public richest;
uint public mostSent;
mapping (address => uint) pendingWithdrawals;
constructor() public payable {
richest = msg.sender;
mostSent = msg.value;
}
function becomeRichest() public payable returns (bool) {
if (msg.value > mostSent) {
pendingWithdrawals[richest] += msg.value;
richest = msg.sender;
mostSent = msg.value;
return true;
} else {
return false;
}
}
function withdraw() public {
uint amount = pendingWithdrawals[msg.sender];
pendingWithdrawals[msg.sender] = 0;
msg.sender.transfer(amount);
}
}