深度解析Solidity合約調(diào)用call,callcode,及delegatecall函數(shù)

三個方法都是用來進行合約交互的方法。由于沒有進行更進一步的封裝,不是最好的選擇,一般不會直接使用到它們;另外一個顯著的問題由于可以使用任意參數(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);
    }
    
}

下圖實際操作演示。


test

可以看到,由于沒有找到對應(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可以看看操作演示:


test1

函數(shù)的結(jié)果

call()的返回結(jié)果是一個bool,表示是否成功的調(diào)用,或者是失敗引起了EVM異常。該方法無法直接訪問函數(shù)返回結(jié)果(因為需要事前知道編碼和返回結(jié)果大小)。

call()的返回結(jié)果即使成功,并不能說操作成功了,只是沒有出現(xiàn)異常,比如我們第一個例子中,實際是調(diào)用到了fallback()函數(shù)。

delegatecall()

calldelegatecall的功能類似,區(qū)別僅在于后者僅使用給定地址的代碼,其它信息則使用當(dāng)前合約(如存儲,余額等等)。

函數(shù)的設(shè)計目的是為了使用存儲在另一個合約的庫代碼。

所以開發(fā)者在提供這樣的庫時,就要如何安排存儲來達到這樣的目的。

參考資料

關(guān)于作者

專注基于以太坊的相關(guān)區(qū)塊鏈技術(shù),了解以太坊,Solidity,Truffle。
博客:http://me.tryblockchain.org


  1. 關(guān)于這個的詳細說明,可以參考這里。http://ethereum.stackexchange.com/questions/8168/understanding-namereg-callregister-myname-style-call-between-contracts ?

  2. 類似構(gòu)造函數(shù)的定義方式。 ?

  3. 參數(shù)編碼格式與ABI的編碼格式一致,直接參考ABI。 ?

  4. 詳細了解ABI格式,可以參考:【文檔翻譯系列】ABI詳解 ?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 原文地址:C語言函數(shù)調(diào)用棧(一)C語言函數(shù)調(diào)用棧(二) 0 引言 程序的執(zhí)行過程可看作連續(xù)的函數(shù)調(diào)用。當(dāng)一個函數(shù)執(zhí)...
    小豬啊嗚閱讀 4,957評論 1 19
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,506評論 19 139
  • 本文翻譯自:https://github.com/ConsenSys/smart-contract-best-pr...
    tolak閱讀 5,251評論 4 21
  • 第5章 引用類型(返回首頁) 本章內(nèi)容 使用對象 創(chuàng)建并操作數(shù)組 理解基本的JavaScript類型 使用基本類型...
    大學(xué)一百閱讀 3,665評論 0 4
  • 今天被一個群里一個發(fā)R語言的生信小哥哥炸了回來。 自從考研,我就退出簡書一大段時間了,期間還有些原因是因為首頁那些...
    邱天閱讀 175評論 0 0

友情鏈接更多精彩內(nèi)容