合约实现以太坊子钱包

以太坊帐号只有一个地址,不能像比特币一样生成多个地址。通过合约其实可以实现以太坊的子钱包,但我今天开发的可能是一个失败的例子,因为创建合约的成本为355745gas,如果想要这个合约作为中心化应用中的子钱包,1.7CNY一个帐号的负担可能太大了。但是用于个人使用又不想备份太多私钥,却是一个比较好的方法。顺便可以积累一些Solidity的语法和功能

代码部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
pragma solidity ^0.4.19;

contract ERC20 {
function transfer(address _to, uint256 _value) public;
mapping (address => uint256) public balanceOf;
}

contract ChildAccount {
address public owner;
address public thisaddr=address(this);
function ChildAccount () public {
owner = msg.sender;
}
function () payable public {
owner.transfer(msg.value);
}
function withdrawERC20 (address contractAddress) public {
ERC20 token = ERC20(contractAddress);
token.transfer(owner,token.balanceOf(thisaddr));
}
}

代码分析

引用其他合约的函数

合约中是可以调用其他合约的方法的,前提是你提前申明,就比如我代码里的:

1
2
3
4
contract ERC20 {
function transfer(address _to, uint256 _value) public;
mapping (address => uint256) public balanceOf;
}

由于我在下面用到了ERC20的transfer方法合balanceOf方法,所以我定义了一个ERC20的合约,里面只是按照ERC20的标准申明了这两个函数,并不需要写实现。不写其他申明的原因也是为了解决创建合约的gas。其中transfer是转发ERC20token的方法,balanceOf是查看账户token余额的数组。我在合约ChildAccountwithdrawERC20这个函数中引用了这两个函数:

1
2
3
4
function withdrawERC20 (address contractAddress) public {
ERC20 token = ERC20(contractAddress);
token.transfer(owner,token.balanceOf(thisaddr));
}

withdrawERC20这个方法用来让主账户提取该合约中的token,用contractAddress合约地址来确定具体是哪个ERC20 token,先获取余额再按余额转账。因为ERC20合约无法直接感知token的进账,所以我们才需要这个函数让主张户主动提取token。当然这边也可以优化,比如可以一次性提取一大批固定的token,甚至可以用一个函数增加支持的token的地址,这里就不再细化了。

自动转账ether

上面转账token的方法还是主动调用的方法,但是转账ether可以是完全被动的。就比如payable函数

1
2
3
function () payable public {
owner.transfer(msg.value);
}

在构造函数中,已经把主张户设置成了owner : owner = msg.sender,也就是发起合约的账户为主账户。在payable函数中直接把发送来的ether全额打到owner的帐号中。payable在有人向这个合约打ether的时候会主动触发,因此转账过程就完全自动化了。