ETH多签测试

in #cn-dev5 years ago

前言

ETH的多签是依靠智能合约实现的,也就是说持币的是智能合约,通过在智能合约里设置条件,来使转账之类的权限通过多人签名来集体控制。

从网上找到了一段简单的多签智能合约,代码如下:

pragma solidity ^0.4.21;

contract MultiSigWallet{
    address private owner;
    mapping (address => uint8) private managers;
    
    modifier isOwner{
        require(owner == msg.sender);
        _;
    }
    
    modifier isManager{
        require(
            msg.sender == owner || managers[msg.sender] == 1);
        _;
    }
    
    uint constant MIN_SIGNATURES = 3;
    uint private transactionIdx;
    
    struct Transaction {
        address from;
        address to;
        uint amount;
        uint8 signatureCount;
        mapping (address => uint8) signatures;
    }
    
    mapping (uint => Transaction) private transactions;
    uint[] private pendingTransactions;
    
    function MultiSigWallet() public{
        owner = msg.sender;
    }
    
    event DepositFunds(address from, uint amount);
    event TransferFunds(address to, uint amount);
    event TransactionCreated(
        address from,
        address to,
        uint amount,
        uint transactionId
        );
    
    function addManager(address manager) public isOwner{
        managers[manager] = 1;
    }
    
    function removeManager(address manager) public isOwner{
        managers[manager] = 0;
    }
    
    function () public payable{
        emit DepositFunds(msg.sender, msg.value);
    }
    
    function withdraw(uint amount) isManager public{
        transferTo(msg.sender, amount);
    }
    function transferTo(address to,  uint amount) isManager public{
        require(address(this).balance >= amount);
        uint transactionId = transactionIdx++;
        
        Transaction memory transaction;
        transaction.from = msg.sender;
        transaction.to = to;
        transaction.amount = amount;
        transaction.signatureCount = 0;
        transactions[transactionId] = transaction;
        pendingTransactions.push(transactionId);
        emit TransactionCreated(msg.sender, to, amount, transactionId);
    }
    
    function getPendingTransactions() public isManager view returns(uint[]){
        return pendingTransactions;
    }
    
    function signTransaction(uint transactionId) public isManager{
        Transaction storage transaction = transactions[transactionId];
        require(0x0 != transaction.from);
        require(msg.sender != transaction.from);
        require(transaction.signatures[msg.sender]!=1);
        transaction.signatures[msg.sender] = 1;
        transaction.signatureCount++;
        
        if(transaction.signatureCount >= MIN_SIGNATURES){
            require(address(this).balance >= transaction.amount);
            transaction.to.transfer(transaction.amount);
            emit TransferFunds(transaction.to, transaction.amount);
            deleteTransactions(transactionId);
        }
    }
    
    function deleteTransactions(uint transacionId) public isManager{
        uint8 replace = 0;
        for(uint i = 0; i< pendingTransactions.length; i++){
            if(1==replace){
                pendingTransactions[i-1] = pendingTransactions[i];
            }else if(transacionId == pendingTransactions[i]){
                replace = 1;
            }
        } 
        delete pendingTransactions[pendingTransactions.length - 1];
        pendingTransactions.length--;
        delete transactions[transacionId];
    }
    
    function walletBalance() public isManager view returns(uint){
        return address(this).balance;
    }
}

部署合约

我本地的测试网络是使用 Ganache 搭建的,如下图

我修改了我的 Ganache 的端口为 8545

然后打开 Remix,在右边栏选择 Run,在 Environment 中选择 Web3 Provider,如下图

在弹出的层中,输入本地地址和刚才配置的8545端口,就可以连接到 Ganache 的环境了,如下图

连接成功后,会看到在 Environment 下面的 Account 栏中会列出所有 Ganache 中的测试账号。

我们选择第一个账号作为部署合约的主账号,即合约的 owner

在编辑器中创建一个新的合约文件,把上面的合约代码复制进编辑器,右边栏选择 Compile
Select new compiler version 中选择 0.4.21 版本的编译器,等待编译完成。
完成后,最下面出现绿色的提示信息,如下图

再切换回 Run 标签,点击 Deploy 就可以部署了。
部署成功后,在 Deployed Contracts 中就能看到新部署的合约了,下拉打开可以看到合约的各个接口,如图

增加合约管理员

在右边栏找到合约的 addManager 接口,下拉打开输入一个以太钱包地址,然后点击 transact 即完成添加。
这里我把 Ganache 的第 2 到 4 的地址加入进管理员中。

给合约内转账

切换回 Ganache,在 Transactions 中找到我们刚才部署的合约地址,0x08ea5409922D4204C0E03d17243E77c3810C0CCe

使用任意的其他账号转账任意个 ETH 进合约里。
我用的是 MyEtherWallet进行的转账,只需要把节点设置成本地网络,
然后用私钥模式登陆转账即可,这里就略过不说了。

转完账后,在 RemixRun 标签下,找到合约的 walletBalance 接口,
点击调用即可显示当前合约的余额,注意单位!

多签从合约内转出金额

回到 Remix,在右边栏的 Run 标签下,先确认 Account 选择的是合约的 owner
这个例子里就是第一个测试地址了。

在合约中找到 transferTo,下拉打开,输入一个本地测试网络中的以太钱包地址,输入待转账的金额,点击 transact。这里注意单位,下图为转 5 ETH,

成功执行后,就会有一个等待多签的 transactionpendingTransactions 这个数组里。
点击 getPendingTransactions 可以得到当前等待多签的 transaction 在数组中的索引值。
下图则代表当前等待多签的 transaction 的索引值是 0 。

这时,在 Run 标签页的顶部,把 Account 依次切换为其他几个管理员,分别执行合约的 signTransaction 接口即可完成多签,其中 transactionId 就是上一步中的索引值,如下图

目前这个合约代码中,是当签名管理员的数量大于等于3个,就正式完成多签并发送交易。
所以当第三个管理执行完 signTransaction 后,查一下合约的余额就发现已经转出去 5ETH了。

总结

目前这个例子中的合约代码还是比较简单的,没有各个用户的权重关系。这个就可以根据自己的需要来写合约了。

Over!


欢迎使用 SteemEditor 来编写文章,获取 @steemeditor.bot 的大力点赞!


欢迎使用 SteemTools,微信扫一扫开始使用


感谢你的阅读,我是中文区见证人之一,欢迎通过 SteemConnect 来给我投票,或者打开 https://steemit.com/~witnesses/ 页面,输入 ety001 进行投票。

2.gif

中文区的见证人目前有:
支持一下他们(按字母顺序),一人可以有30票


Thank you for reading. I'm a witness. I would really appreciate your witness vote! You can vote by SteemConnect. Or open https://steemit.com/~witnesses page, input ety001 to vote.

2.gif

Sort:  

恭喜你!您的这篇文章入选 @justyy 今日 (2018-12-23) 榜单 【优秀的文章】, 回复本条评论24小时内领赏,点赞本评论将支持 @dailychina 并增加将来您的奖赏。

Congratulations! This post has been selected by @justyy as today's (2018-12-23) 【Good Posts】, Steem On! Reply to this message in 24 hours to get rewards. Upvote this comment to support the @dailychina and increase your future rewards! ^_^

不明觉厉

Coin Marketplace

STEEM 0.26
TRX 0.11
JST 0.033
BTC 64107.21
ETH 3073.84
USDT 1.00
SBD 3.88