前幾天聽一個好友說起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