argent钱包软件转账免手续费之谜——钱包创建

前几天听一个好友说起argent这个数字货币钱包软件,说它有个特色——转账免手续费。我问他转的是什么币,他说是ETH。这让我大吃一惊。因为很久以前我研究过以太坊转账免手续费的问题,总的来说,就是很复杂。

用中心化的方式:先让用户转账,然后中心化系统给用户把手续费补给用户。
去中心化的方式:好像没找到合理的方式,时间太久忘了。

听到好友说有这么个钱包软件做到了免手续费转ETH,我非常兴奋,好奇心爆棚,一定要一探究竟。下面就是我探究argent转账免手续费的经历。

下载argent钱包软件

这个钱包软件目前在国内还不能下载,只能翻墙去下载。

安装注册钱包

这个没什么好说的,跟普通钱包差不多,都是备份密钥种子那一套。

开始体验软件

打开软件,会给你的钱包提前分配一个以太坊账户地址,要你网这个地址里转入ETH,激活它。你还能自定义一个专属你钱包的ENS。

我激活之后就这样子:

经过查询etherscan,我发现事情并不简单。

注意看上面显示我是16天之前转的ETH,但是这个合约账户是13天前创建的

也就是说当我看到我钱包里的这个账号的时候,这个账号地址是个智能合约地址,此时这个智能合约还没有被创建。我转账之后第三天这个智能合约地址被创建了。

也就是说,智能合约与地址是能够提前被预订的!!!能够提前预订!!!能够提前预订!!!

原谅我以前不学无术,孤陋寡闻,我真不知道还有这种事情,我以前真的以为那串像乱码一样的字符串可能像区块哈希一样,是不能被提前预测到的。

后来我就研究了一下以太坊智能合约地址生成规则,于是就有了前面几篇博客的内容:

以太坊智能合约地址生成之CREATE指令 https://blog.csdn.net/console/editor/html/106541978

以太坊智能合约地址生成之CREATE2指令 https://blog.csdn.net/maxdaic/article/details/106542548

钱包合约创建流程

通过etherscan查到,我的钱包智能合约是由0x40C84310Ef15B0c0E5c69d25138e0E16e8000fE9(合约名:WalletFactory)创建的,而这个地址也是一个智能合约地址。当然通过智能合约创建另一个智能合约这已经是很常规的操作了。

问题来了,WalletFactory是通过哪个接口给我创建的钱包合约?

通过查看我的钱包智能合约事件日志也许可以看出一些端倪。如下图:

可以看到,这里事件是创建合约的时候记录下来的。并且这里有个有用的信息,那就是箭头上的method id。

method id是什么?就是调用智能合约接口的时候,对智能合约接口做keccak256运算,取其前四个字节。如baz(uint32,bool)的method id为0xcdcd77c0

用golang实现method id代码如下:

func MustGenerateMethodID(method string) string {
	buf := Keccak256Hash([]byte(method))
	return "0x"+hex.EncodeToString(buf[:4])
}

测试代码:

func TestMustGenerateMethodID(t *testing.T) {
	var testcases = []struct{
		method string
		want string
	} {
		{
			"baz(uint32,bool)",
			"0xcdcd77c0",
		},
		{
			"bar(bytes3[2])",
			"0xfce353f6",
		},
		//{
		//	"createCounterfactualWallet(address,address[],string,bytes32)",
		//	"0xc3606c88",
		//},
		{
			"createCounterfactualWalletWithGuardian(address,address[],string,address,bytes32)",
			"0xc3606c88",
		},
	}

	for _,oneCase := range testcases {
		got := MustGenerateMethodID(oneCase.method)
		if got != oneCase.want {
			t.Error("generate method id error")
			t.Error("want:", oneCase.want)
			t.Error("got: ", got)
			return
		}
	}
}

通过测试,我发现这个method id是 函数createCounterfactualWalletWithGuardian(address,address[],string,address,bytes32)的。于是可以顺藤摸瓜,摸清楚整个流程。

对了,argent智能合约已经开源,地址是:https://github.com/argentlabs/argent-contracts

创建钱包智能合约的关键代码如下:

function _createCounterfactualWallet(
        address _owner,
        address[] memory _modules,
        string memory _label,
        address _guardian,
        bytes32 _salt
    )
        internal
    {
        _validateInputs(_owner, _modules, _label);
        bytes32 newsalt = _newSalt(_salt, _owner, _modules, _guardian);
        bytes memory code = abi.encodePacked(type(Proxy).creationCode, uint256(walletImplementation));
        address payable wallet;
        // solium-disable-next-line security/no-inline-assembly
        assembly {
            wallet := create2(0, add(code, 0x20), mload(code), newsalt)
            if iszero(extcodesize(wallet)) { revert(0, returndatasize) }
        }
        _configureWallet(BaseWallet(wallet), _owner, _modules, _label, _guardian);
    }

可以看到,这里创建智能合约是使用以太坊虚拟机的create2指令。而newsalt是使用官方指定的_salt, _owner, _modules, _guardian这几个参数生成的。所以argent官方通过这几个参数就可以提前生成钱包智能合约的地址。

到此,梳理一下整个钱包创建的业务流程:

(1)先通过一些列参数提前生成一批智能合约地址;

(2)当用户注册argent钱包的时候,提取一个地址并把它分配给用户;

(3)用户往这个地址转账ETH;

(4)检测到用户转了ETH到其钱包智能合约地址上,通过WalletFactory智能合约创建用户钱包智能合约。

更多精彩,下回分析

(全文完)

参考资料:

https://solidity.readthedocs.io/en/develop/abi-spec.html

https://etherscan.io/address/0x8b55c928602896a1e078e23a3fee33393821eec7#events

https://github.com/argentlabs/argent-contracts

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章