三個方法都是用來進行合約交互的方法。由于沒有進行更進一步的封裝,不是最好的選擇,一般不會直接使用到它們;另外一個顯著的問題由于可以使用任意參數(shù)類型,在語言層面不能保證類型安全,所以不推薦使用。
call() 方法
call()是一個底層的接口,用來向一個合約發(fā)送消息[1],也就是說如果你想實現(xiàn)自己的消息傳遞,可以使用這個函數(shù)。函數(shù)支持傳入任意類型的任意參數(shù),并將參數(shù)打包成32字節(jié),相互拼接后向合約發(fā)送這段數(shù)據(jù)。
函數(shù)的傳輸?shù)臄?shù)據(jù)
由于向另一個合約發(fā)送數(shù)據(jù)時,找不到對應(yīng)的方法簽名,會默認(rèn)調(diào)用fallback()函數(shù)[2],所以我們可以通過這個來看看call()傳的具體數(shù)據(jù)。
pragma solidity ^0.4.0;
contract Person{
bytes fail;
function(){
fail = msg.data;
}
function getFail() returns (bytes){
return fail;
}
}
contract CallTest{
function callData(address addr) returns (bool){
return addr.call("abc", 256);
}
}
下圖實際操作演示。
可以看到,由于沒有找到對應(yīng)的函數(shù)調(diào)用,最終調(diào)用的是fallback()函數(shù),通過fail字段,我們看到了收到msg.data:
0x61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100
前32字節(jié)為abc對應(yīng)的acii編碼值,后32位為256的對應(yīng)編碼值[3]。
call指定函數(shù)
如果第一個參數(shù)剛好是四個字節(jié),會認(rèn)為這四個字節(jié)指定的是函數(shù)簽名的序號值,生成方式參見ABI協(xié)議的函數(shù)選擇器[4]。由如果你只是想傳個參數(shù)值,而不是想指定一個函數(shù)序號,應(yīng)避免第一個參數(shù)剛好是四個字節(jié)。
pragma solidity ^0.4.0;
contract Person{
uint age = 10;
function increaseAge(string name, uint num) returns (uint){
return ++age;
}
function getAge() returns (uint){
return age;
}
}
contract CallTest{
function callByFun(address addr)returns (bool){
bytes4 methodId = bytes4(keccak256("increaseAge(string,uint256)"));
return addr.call(methodId,"jack", 1);
}
}
通過下圖的gif可以看看操作演示:
函數(shù)的結(jié)果
call()的返回結(jié)果是一個bool,表示是否成功的調(diào)用,或者是失敗引起了EVM異常。該方法無法直接訪問函數(shù)返回結(jié)果(因為需要事前知道編碼和返回結(jié)果大小)。
call()的返回結(jié)果即使成功,并不能說操作成功了,只是沒有出現(xiàn)異常,比如我們第一個例子中,實際是調(diào)用到了fallback()函數(shù)。
delegatecall()
call與delegatecall的功能類似,區(qū)別僅在于后者僅使用給定地址的代碼,其它信息則使用當(dāng)前合約(如存儲,余額等等)。
函數(shù)的設(shè)計目的是為了使用存儲在另一個合約的庫代碼。
所以開發(fā)者在提供這樣的庫時,就要如何安排存儲來達到這樣的目的。
參考資料
關(guān)于作者
專注基于以太坊的相關(guān)區(qū)塊鏈技術(shù),了解以太坊,Solidity,Truffle。
博客:http://me.tryblockchain.org
-
關(guān)于這個的詳細說明,可以參考這里。http://ethereum.stackexchange.com/questions/8168/understanding-namereg-callregister-myname-style-call-between-contracts ?
-
類似構(gòu)造函數(shù)的定義方式。 ?
-
參數(shù)編碼格式與ABI的編碼格式一致,直接參考ABI。 ?
-
詳細了解ABI格式,可以參考:【文檔翻譯系列】ABI詳解 ?