ERC-777 和风险缓解

ERC777代币标准使用 防范风险

代币是其区块链原生的数字资产,为了提供交互性、可用性和统一性,引入了代币标准,创建代币的最广泛使用的标准ERC20、ERC-20 和 ERC-777中,它们都是以太坊区块链上存在的可替代代币的一些标准。智能合约开发有许多代币标准;然而,ERC 20是基本标准或默认标准,它是不可变的,在智能合约的开发中被广泛使用。

因此,在现有标准运行良好的情况下,为代币采用新标准通常不会被考虑。然而,随着DeFI的使用和采用的增加,以及几乎不存在监管的巨大流动性,不诚实的参与者利用生态系统的风险增加。

选择代币标准:ERC20 VS ERC777

ERC20 和 ERC777 是可替代代币开发的两个首选代币。代币的选择主要取决于使用、采用、特性和安全性。

ERC20具有广泛的使用范围、采用性和安全性,而ERC777具有改进的特性和向后兼容性。

ERC 777的目的

EIP(以太坊改进提案)ERC777引入了增强的特性,使与代币的交互更具有响应性。

HOOK等功能使智能合约在事件发生时能够作出反应或执行特定的操作,从而给予代币持有者更多的控制权。这样做的好处是可以避免代币被发送到错误的目的地地址从而丢失代币的情况。

此外,通过操作符,智能合约被授予执行任务的权限,并可以代表另一个合约或常规地址发送代币。

ERC777标准向后兼容ERC20,这允许与这些代币无缝交互,就像它们是ERC20一样,使用标准功能,仍然受益于增强的特性。

什么是智能合约?

智能合约是由开发人员编写的自动执行代码,用于执行买卖双方协议的条款。代码及其协议通过一个安全且不可变的区块链网络分布和去中心化。

智能合约不需要第三方、中心化机构或中介机构来执行该守则的条款,代码本身就是法律。它可以使未知方之间进行可信的交易和协议,并信任每个人的义务的安全履行。

为什么在漏洞利用中需要使用 ERC777 代币?

智能合约确实会遇到漏洞,这些漏洞大多是由代码中的漏洞造成的,无论是ERC20还是ERC777智能合约代码都是由人类用Solidity 的编程语言编写的,而且,每个人都容易犯错,有时不可预见的事件在某个时间点上可能会使现有的基础设施变得脆弱(如果没有预料到包含这些事件的话)。ERC777只是让它更容易瞄准设计糟糕的协议。

使用重入向量攻击利用了 imBTC 和 Dforce 的 Uniswap V1 池。重入攻击已经成为一个众所周知的漏洞,它在2016年著名的DAO(去中心化自治组织)黑客攻击中被曝光,当时ERC777标准还不存在。

将漏洞归咎于代币标准是非常方便的,因为开发人员和项目团队没有彻底地让智能合约接受审计和升级,而只是受利润驱动。

ERC777的用例

  • 它可用于将来自某些地址的代币列入黑名单或拒绝接收。
  • 使用操作符,它可以用来代表用户自动处理订阅或支付。
  • 发送功能允许添加用户交易数据和操作符交易数据,以更快的对账。
  • 它可以自动将特定代币重定向到另一个合约。

使用ERC777的tokensReceived Hook

// SPDX-License-Identifier: MIT
pragma solidity >=0.8.4;

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v4.1/contracts/token/ERC777/ERC777.sol";

contract my777Receiver is IERC777Recipient {

  mapping (address=>uint) public balances;
  ERC777 my_erc777;

  IERC1820Registry private registry1820= IERC1820Registry(0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24);

  constructor (address my_erc777_address){
      registry1820.setInterfaceImplementer(address(this),keccak256("ERC777TokensRecipient"),address(this));
      my_erc777 = ERC777(my_erc777_address);
  }

  //ERC777 Recipient Hook
  function tokensReceived(address operator, address from, address to,uint256 amount, bytes calldata data,
    bytes calldata operatorData) external {
  //revert or require
   }

  function () external payable {}

}

使用ERC777的操作符

// SPDX-License-Identifier: MIT
//Using https://remix.ethereum.org

pragma solidity >=0.8.4;

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v4.1/contracts/token/ERC777/ERC777.sol";

contract my777Receiver is IERC777Recipient {

  mapping (address=>uint) public balances;
  ERC777 my_erc777;

  IERC1820Registry private registry1820= IERC1820Registry(0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24);

  constructor (address my_erc777_address){
      registry1820.setInterfaceImplementer(address(this),keccak256("ERC777TokensRecipient"),address(this));
      my_erc777 = ERC777(my_erc777_address);
  }

//ERC 777 HOOK
  function tokensReceived(address operator,address from,address to,uint256 amount,
      bytes calldata userData,bytes calldata operatorData) override external{
    // revert();
  }

//Authorised Operator deposit
  function deposit(uint amount) public{
    my_erc777.operatorSend(address(msg.sender), address(this), amount, "", "");
    balances[msg.sender] += amount;
  }

//authorised Operator withdrawal
  function withdrawTokens() public{
    my_erc777.operatorSend(address(this), address(msg.sender), balances[msg.sender], "", "");
    balances[msg.sender] = 0;
  }
}

ERC777发送过程

// SPDX-License-Identifier: MIT
//Using https://remix.ethereum.org

pragma solidity >=0.8.4;

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v4.1/contracts/token/ERC777/ERC777.sol";

contract ERC777 is IERC777Recipient {
//calling the setInterfaceImplementer function on the ERC-1820 registry with the holder address as the address
  IERC1820Registry private registry1820= IERC1820Registry (0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24);
  registry1820.setInterfaceImplementer(address(this), keccak256("ERC777TokensSender"), address(this));
  mapping (address=>uint) public balances;

//ERC777 Sender Hook
function tokensToSend(address operator, address from,address to,uint256 amount,bytes calldata userData,
    bytes calldata operatorData) external{
}

function () external payable {}
}
  • 发送方作为代币的所有者,想要将代币转移到ERC777合约中,将调用ERC777的send函数。
  • 然后合约会从注册合约中找出已部署的ERC1820(已部署在区块链上的可信注册中心)收件人地址是否已向其注册以接收代币。
  • 如果注册表中有一条记录,那么将调用接收方合约中的tokensReceived函数来接收代币。
  • 接收方合约还可以决定拒绝tokensReceived函数中的代币。

防范智能合约风险

风险总是存在的,智能合约风险也不例外。因此,考虑到大量资金被转移到该领域,采用风险管理实践来保护使用DeFi的实体至关重要。以下几点值得考虑,但不是详尽无遗的,以减少风险。

审计

随着DeFi锁定价值的增加,对安全审计的需求也在增加。智能合约漏洞,拉地毯,和其他代码bug。智能合约审计可以手动或自动进行。智能合约审核员会检查智能合约代码,以检测漏洞和安全问题,从而在一定程度上保证项目代码可以安全部署。

Certik、Chainsulting、Openzeppellen、Perkshield是审计智能合约的知名区块链安全公司。

购买保险

DeFi保险是指为自己投保,或“购买保险”,以防范DeFi领域中发生的事件所带来的损失和风险。

DeFi保险是一种保护用户免受损失的保险,以换取费用。通过购买保险,可以将损失的影响降到最低。

Opium insurance、insurAce、nexus Mutual、Bridgemutual、Insure Defi 和 Unslashed 是一些去中心化的金融保险覆盖提供商。

使用有经验的开发人员:使用有经验的开发人员可以帮助减少智能合约所面临的一些风险。智能合约开发者更容易了解行业面临的一些风险,以及在智能合约部署中采用的最佳实践。

避免复制其他代码:从其他协议复制是一种快速的开发方法,但由于熟悉性和可能的不兼容性问题,容易被利用。

限制用户访问:可以使用硬件或软件设备离线存储私钥,用户访问应仅限于少数需要访问的用户,也可以使用多重签名合约来加强安全性。

总结

鼓励开发人员编写降低风险的软件代码,他们可以通过保护已知的漏洞、对智能合约代码进行审计、购买保险以及提供暂停、暂停和升级智能合约的功能来做到这一点。

Source:https://hackernoon.com/ethereum-tokens-a-dive-with-erc-777-and-risk-mitigations

关于

ChinaDeFi - ChinaDeFi.com 是一个研究驱动的DeFi创新组织,同时我们也是区块链开发团队。每天从全球超过500个优质信息源的近900篇内容中,寻找思考更具深度、梳理更为系统的内容,以最快的速度同步到中国市场提供决策辅助材料。

Layer 2道友 - 欢迎对Layer 2感兴趣的区块链技术爱好者、研究分析人与Gavin(微信: chinadefi)联系,共同探讨Layer 2带来的落地机遇。敬请关注我们的微信公众号 “去中心化金融社区”。

点赞 1
收藏 2
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

1 条评论

请先 登录 后评论
ChinaDeFi 去中心化金融社区
ChinaDeFi 去中心化金融社区
ChinaDeFi.com 是一个研究驱动的DeFi创新组织,同时我们也是区块链开发团队。每天从全球超过500个优质信息源的近900篇内容中,寻找思考更具深度、梳理更为系统的内容,以最快的速度同步到中国市场提供决策辅助材料。