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

 

 

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