ERC20-721Token的发行-冻结-多方签名功能

发行

ERC 代币的发行已经标准化,最好采用 openzeppelin 的模板,并搭配 solidity5.x 版本和 truffle 工具使用,效果更佳。

1
2
3
4
5
6
7
8
9
10
// ERC 721
pragma solidity ^0.5.0;

import 'openzeppelin-solidity/contracts/token/ERC721/ERC721Full.sol';
import 'openzeppelin-solidity/contracts/token/ERC721/ERC721Mintable.sol';

contract MyNFT is ERC721Full, ERC721Mintable {
constructor() ERC721Full("MyNFT", "MNFT") public {
}
}
1
2
3
4
5
6
7
8
9
10
11
12
// ERC 20
pragma solidity ^0.5.0;

import 'openzeppelin-solidity/contracts/token/ERC20/ERC20.sol';
import 'openzeppelin-solidity/contracts/token/ERC20/ERC20Detailed.sol';
import 'openzeppelin-solidity/contracts/ownership/Ownable.sol';

contract MyERC20 is ERC20, ERC20Detailed, Ownable {
constructor(uint256 initialSupply) ERC20Detailed("MyToken", "MT", 18) public {
_mint(msg.sender, initialSupply);
}
}

Freeze 功能 (openzeppelin-contracts v3.2.0之后)

也叫做 pause 或者 close,具体就是停止 Token 相关的 transfer(转账)功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// ERC 20
pragma solidity ^0.5.0;

import 'openzeppelin-solidity/contracts/token/ERC20/ERC20.sol';
import 'openzeppelin-solidity/contracts/token/ERC20/ERC20Detailed.sol';
import 'openzeppelin-solidity/contracts/ownership/Ownable.sol';

contract MyERC20 is ERC20, ERC20Detailed, Ownable {
bool public closed = false;

event Close();
event Open();

constructor(uint256 initialSupply) ERC20Detailed("MyToken", "MT", 18) public {
_mint(msg.sender, initialSupply);
}

// ------------------------------------------------------------------------
// Don't accept ETH
// ------------------------------------------------------------------------
function() external payable {
revert("Don't accept ETH");
}

function transfer(address _to, uint _value) whenOpen public returns (bool) {
return super.transfer(_to, _value);
}

function transferFrom(address _from, address _to, uint _value) whenOpen public returns (bool) {
return super.transferFrom(_from, _to, _value);
}

function close() onlyOwner whenOpen public {
closed = true;
emit Close();
}

function open() onlyOwner whenClosed public {
closed = false;
emit Open();
}

modifier whenOpen() {
require(!closed);
_;
}

modifier whenClosed() {
require(closed);
_;
}
}

openzeppelin-contracts v3.2.0版本中的实现代码如下 ERC721Pausable

1
2
3
contract ERC721PresetMinterPauserAutoId is Context, AccessControl, ERC721Burnable, ERC721Pausable {
......
}

MultiSigWallet 多方签名

gnosis 的 multisignature 功能最为完善。已经有多个生产项目采用此工具。目前此工具合约的 solidity 版本为0.4.15,项目语言版本交旧,但没有发生过安全问题。

首先 ERC20 合约的初始化总金额地址需要给到 MultiSigWallet 的合约地址,由 MultiSigWallet 合约完成多方签名确认后,ERC20 代币从 MultiSigWallet 合约的地址发送到接收人的账户地址。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// ERC 20
pragma solidity ^0.5.0;

import 'openzeppelin-solidity/contracts/token/ERC20/ERC20.sol';
import 'openzeppelin-solidity/contracts/token/ERC20/ERC20Detailed.sol';
import 'openzeppelin-solidity/contracts/ownership/Ownable.sol';

contract MyERC20 is ERC20, ERC20Detailed, Ownable {
bool public closed = false;

event Close();
event Open();

constructor(uint256 initialSupply) ERC20Detailed("MyToken", "MT", 18) public {
_mint(msg.sender, initialSupply);
}

// ------------------------------------------------------------------------
// Do accept ETH, deposit token in contract address
// ------------------------------------------------------------------------
function() external payable {}

function transfer(address _to, uint _value) whenOpen public returns (bool) {
return super.transfer(_to, _value);
}

function transferFrom(address _from, address _to, uint _value) whenOpen public returns (bool) {
return super.transferFrom(_from, _to, _value);
}

function close() onlyOwner whenOpen public {
closed = true;
emit Close();
}

function open() onlyOwner whenClosed public {
closed = false;
emit Open();
}

modifier whenOpen() {
require(!closed);
_;
}

modifier whenClosed() {
require(closed);
_;
}
}

Live website 地址在这里,以下操作均为https://wallet.gnosis.pm/上的截图。

1.增加钱包。如下图,完成钱包增加配置

2.点击 Wallets Name,即点击’Lcoin’,进入钱包的详细页面,如下图,进入后需要手动添加 Tokens Name,其后点击 Withdraw,最后经过 2 位 Required confirmations 后,Executed 状态变为 Yes

注意,此处,由 MultiSigWallet 合约完成多方签名确认后,ERC20 代币从 MultiSigWallet 合约的地址发送到接收人的账户地址(a825),MultiSigWallet 合约执行 transfer 给到接收人的账户地址(a825),所以 MultiSigWallet 合约的地址上需要有足够的 Eth 作为 gas

即使用 MultiSigWallet 转账时,花费的 gas 是 2 位 Required confirmations 和一次 transfer 的总和

3.如下图,虽然在 MultiSigWallet中可以选择到调用 ERC20 合约中的 close 函数,但是 close 函数并不受 MultiSigWallet 的控制,由onlyOwner,即 msg.sender 单独控制并操作

4.如下图,具体交易的内容在 MultiSigWallet,并配合etherscan 和 MyEtherWallet 中的结果

关联内容 ==> https://willzhuang.github.io/2020/09/07/ERC721%E5%AE%9E%E8%B7%B5/实践