solidity的高阶语法4

1.提款模式

提款模式确保不会造成安全威胁的直接转接呼叫。 以下合约显示了使用转账调用发送以太币的不安全方式。

复制代码
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);
   }
}
 

2.限制访问

限制访问合同是一种常见做法。 默认情况下,合约状态是只读的,除非将其指定为公共状态。

我们可以限制谁可以修改合约的状态或使用修饰符调用合约的函数。 我们将创建并使用多个修饰符,如下所述 −

  • onlyBy − 一旦用于函数,则只有提到的调用者可以调用该函数。

  • onlyAfter − 一旦用于函数,则可以在一定时间段后调用该函数。

  • costs − 一旦用于函数,则仅当提供特定值时调用者才能调用该函数。

示例

复制代码
pragma solidity ^0.5.0;

contract Test {
   address public owner = msg.sender;
   uint public creationTime = now;

   modifier onlyBy(address _account) {
      require(
         msg.sender == _account,
         "Sender not authorized."
      );
      _;
   }
   function changeOwner(address _newOwner) public onlyBy(owner) {
      owner = _newOwner;
   }
   modifier onlyAfter(uint _time) {
      require(
         now >= _time,
         "Function called too early."
      );
      _;
   }
   function disown() public onlyBy(owner) onlyAfter(creationTime + 6 weeks) {
      delete owner;
   }
   modifier costs(uint _amount) {
      require(
         msg.value >= _amount,
         "Not enough Ether provided."
      );
      _;
      if (msg.value > _amount)
         msg.sender.transfer(msg.value - _amount);
   }
   function forceOwnerChange(address _newOwner) public payable costs(200 ether) {
      owner = _newOwner;
      if (uint(owner) & 0 == 1) return;        
   }
}
 
相关推荐
电报号dapp1191 小时前
DApp定制开发与源码交付:打造专属区块链应用的核心战略
web3·去中心化·区块链·智能合约
电报号dapp1194 小时前
交易所定制化开发:拒绝模板化与源码交付的战略价值
金融·web3·去中心化·区块链·智能合约
TechubNews4 小时前
《每周策略通》1.15
区块链
MQLYES6 小时前
07-BTC-挖矿难度
区块链
电报号dapp1197 小时前
质押挖矿DAPP与Swap交易所开发:构建DeFi新基建的全景指南
web3·去中心化·区块链·智能合约
区块链小八歌7 小时前
从流动性枢纽到衍生品引擎:2026 新年伊始,Kodiak 的进化之路
区块链
草原猫17 小时前
DAPP开发应用场景解析:DAPP开发可以用在哪些业务中?
区块链·dapp开发
商业讯网119 小时前
国家电投海外项目运营经验丰富
大数据·人工智能·区块链
老蒋每日coding20 小时前
Solidity入门(2):Foundry框架开发指南
区块链
DICOM医学影像1 天前
8. go语言从零实现以太坊响应端 - 查询区块链账户余额
golang·区块链·以太坊·web3.0·响应端·从零实现