1. 什么情况下需要使用合约销毁?
销毁合约只是让你的智能合约无法再继续工作,但是在区块链上的数据还是保留的。什么情况下需要使用到销毁合约?
- 你的智能合约在不使用的情况下,你可以把它给销毁。
- 强迫你的用户放弃旧的智能合约,使用新的智能合约,所以必须把旧的给销毁。但是由于目前智能合约是能够升级的,所以不赞成使用这方法。
- 你的合约受攻击到了不可挽回的地步,就必须被迫强行销毁。记得,在销毁之前你必须把旧合约内的代币给迁移出来,不然你旧合约的代币也是找不回来的。
2. 如何进行合约销毁?
2.1 合约销毁的原理
比如一个自动售货机,当一件产品不再供货销售时,就可以将该产品对应的调取函数作废掉。
2.2 合约销毁用到的基本命令
SelfDestruct
2.3 合约销毁的步骤
1
2
3
3. 合约销毁的案例
3.1 案例1:销毁不再使用的合约(合约中无Token)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;
contract xiaohui{
uint money = 0;
address owner;
constructor () {
owner = msg.sender;
}
function increcement() public {
money += 10;
}
modifier ownercontrol() {
require (msg.sender == owner);
_;
}
function kill() public ownercontrol{
selfdestruct(owner);
}
}
3.2 案例2:销毁合约(合约中有Token)
发布一个代币,然后进行approve 允许第三方挪动
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract Coin is ERC20{
constructor() ERC20("TestCoin", "TEC") {
//初始发行1000个币去到作者的户口内,并且是6个小数点
_mint(msg.sender, 1000 * 10 ** decimals());
}
function decimals()public pure override returns(uint8){
return 6;
}
}
- 把一定的代币打入合约内,使用第三方挪动资金的话也就是transferFrom就必须进行approve先,也能够直接调用token内的transfer,把代币直接打入合约中。
执行destroyContact也就是自毁合约,自毁前将会把合约内剩下的代币余额全都转回给作者。
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
contract CoinContract{
IERC20 MyToken;
address public immutable ownerAddress;
constructor(address TokenAddress){
MyToken = IERC20(TokenAddress);
ownerAddress = msg.sender;
}
function transferCoinToContract(uint amount)public{
//必须调用token当中的approve先,授权给本合约总共允许挪动多少资金,否则直接调用transferFrom的话肯定会报错的。
//委任第三方转账的话,必须使用transferFrom
//以下是把自己的户口当中资金打入合约内
MyToken.transferFrom(msg.sender,address(this),amount);
}
function checkBalance(address _addr)public view returns(uint){
//查看本合约内有多少的代币
return MyToken.balanceOf(_addr);
}
function checkRemainingApproveBalance() public view returns(uint){
//查看本身的户口,允许第三方挪动的自己还剩下多少
return MyToken.allowance(msg.sender,address(this));
}
modifier isOwner(){
require(msg.sender==ownerAddress,"you are not owner");
_;
}
function destroyContact() public isOwner{
//检查是否是合约的作者,不是就报错了
//在自毁合约前,必须把代币给转出去,否则合约内的代币就永远无法取出来了,但是连锁上的数据还是保存的,只要查看balanceOf就能查到余额
//以下的代码是把合约内的代币转回给作者
MyToken.transfer(ownerAddress,MyToken.balanceOf(address(this)));
selfdestruct(payable(ownerAddress));
}
}
参考文献
[1] 【Solidity】SelfDestruct 销毁合约,https://www.pangzai.win/%E3%80%90solidity%E3%80%91selfdestruct-%E9%94%80%E6%AF%81%E5%90%88%E7%BA%A6/
[2] 智能合约安全审计入门篇 —— 自毁函数,https://learnblockchain.cn/article/3331
版权声明:本文为runrundream原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。