Solidity Call函數(shù)

call(0.5.3版本)

https://solidity.readthedocs.io/en/develop/types.html#address
合約之間的調(diào)用有2種方式: 底層的call方式和 new 合約的方式

  • call:通過合約ContractAddres.call(編碼后的方法名和參數(shù))亿卤,返回調(diào)用是否成功扛点,以及返回值data

  • delegatecall :設(shè)計(jì)是為了調(diào)用其它合約的API用的,類似于 Copy了API合約的API函數(shù)到本地合約執(zhí)行益缠,會修改調(diào)用者合約的狀態(tài)變量越平。

  • staticcall: Since byzantium staticcall can be used as well. This is basically the same as call, but will revert if the called function modifies the state in any way

All three functions call, delegatecall and staticcall are very low-level functions and should only be used as a last resort as they break the type-safety of Solidity.

The .gas() option is available on all three methods, while the .value() option is not supported for delegatecall.
可以設(shè)置這次合約調(diào)用的 gas最大值、轉(zhuǎn)賬的Ether值

address(nameReg).call.gas(1000000)(abi.encodeWithSignature("register(string)", "MyName"));
address(nameReg).call.value(1 ether)(abi.encodeWithSignature("register(string)", "MyName"));
address(nameReg).call.gas(1000000).value(1 ether)(abi.encodeWithSignature("register(string)", "MyName"));

合約之間的調(diào)用建議的方式是:通過new 合約亩歹,通過合約的方式去調(diào)用书幕,而不是通過call的方式去調(diào)用新荤,因?yàn)檫@樣會失去控制權(quán)。(重入風(fēng)險)

使用方式:

  1. 通過abi的函數(shù)進(jìn)行編碼按咒,然后通過合約地址進(jìn)行調(diào)用
  2. 返回是否調(diào)用成功迟隅,以及返回?cái)?shù)據(jù)但骨。
  3. 返回?cái)?shù)據(jù)解碼之后,可以獲取調(diào)用返回值智袭。
bytes memory payload = abi.encodeWithSignature("register(string)", "MyName");

(bool success, bytes memory returnData) = address(nameReg).call(payload);

require(success);

http://me.tryblockchain.org/Solidity-call-callcode-delegatecall.html

  • 三個方法都是用來進(jìn)行合約交互的方法奔缠。
  • 由于沒有進(jìn)行更進(jìn)一步的封裝,不是最好的選擇吼野,一般不會直接使用到它們校哎;另外一個顯著的問題由于可以使用任意參數(shù)類型,在語言層面不能保證類型安全瞳步,所以不推薦使用闷哆。
<address>.call(...) returns (bool)
<address>.delegatecall(...) returns (bool)

代碼層面上面的區(qū)別

  1. call: 調(diào)用后內(nèi)置變量 msg 的值會修改為調(diào)用者,執(zhí)行環(huán)境為被調(diào)用者的運(yùn)行環(huán)境(合約的 storage)单起。
  2. delegatecall: 調(diào)用后內(nèi)置變量 msg 的值不會修改為調(diào)用者抱怔,但執(zhí)行環(huán)境為調(diào)用者的運(yùn)行環(huán)境(修改的成員變量的值體現(xiàn)在 調(diào)用者)。

第一種情況call調(diào)用嘀倒,B.temp1的值 Account(A).address屈留,成了A的合約地址了,因?yàn)槭茿合約調(diào)用了B合約,而不是 A.msg.sender
但是A合約調(diào)用自己的test()方法测蘑, A合約的 temp1 =A.msg.sender灌危,而B合約的temp1= Account(A).address

第二種情況delegatecall:假借B的手,調(diào)用了B合約的方法碳胳,但是修改了的卻是A合約的變量勇蝙,這個有點(diǎn)厲害。

pragma solidity >=0.4.22 <0.6.0;
contract A {
    address public temp1;
    uint256 public temp2;

    function three_call(address addr) public {
        bytes memory payload = abi.encodeWithSignature("test()");
        (bool success, bytes memory returnData) = address(addr).call(payload);
        //(bool success, bytes memory returnData) = address(addr).delegatecall(payload);
    }
    
    function test() public  {
        temp1 = msg.sender;
        temp2 = 200;
    }
}

contract B {
    address public temp1;
    uint256 public temp2;

    function test() public  {
        temp1 = msg.sender;
        temp2 = 100;
    }
}

delegatecall的安全漏洞

因?yàn)閐elegatecall的執(zhí)行環(huán)境是調(diào)用者的環(huán)境挨约,假如A合約 里面提供了delegatecall 函數(shù)調(diào)用了B合約里面的方法味混,那么用戶張三調(diào)用A合約的該方法,如果B合約里面修改了某個環(huán)境變量的值烫罩,且該值A(chǔ)合約中也有惜傲,那么A合約中的成員變量

例如A合約 開放了callFunc方法,該方法可以讓用戶調(diào)用 某個合約地址的某個方法(因?yàn)槎紱]寫死)

contract A {
    address owner;

    function callFunc(address addr, bytes data) public {
        addr.delegatecall(data);
        //address(Attack).delegatecall(bytes4(keccak256("foo()")));  //利用代碼示意
    }
}

現(xiàn)在有個黑客發(fā)現(xiàn)了這個Bug贝攒,于是黑客寫了一個Attack合約,用 Attack合約的地址时甚,和 foo函數(shù)去調(diào)用 A合約中的callFunc方法隘弊,通過在Attack合約中修改owner的地址,因?yàn)閳?zhí)行環(huán)境為調(diào)用者的環(huán)境荒适,所以直接修改了A合約的owner梨熙,并且可以發(fā)起轉(zhuǎn)賬,因?yàn)閳?zhí)行環(huán)境是調(diào)用者

contract Attack {
    address owner;
    address benifit;

    function foo() public {
        // any codes
        benifit.send(100);
        owner="黑客地址";
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末刀诬,一起剝皮案震驚了整個濱河市咽扇,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖质欲,帶你破解...
    沈念sama閱讀 212,080評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件树埠,死亡現(xiàn)場離奇詭異,居然都是意外死亡嘶伟,警方通過查閱死者的電腦和手機(jī)怎憋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,422評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來九昧,“玉大人绊袋,你說我怎么就攤上這事≈ィ” “怎么了癌别?”我有些...
    開封第一講書人閱讀 157,630評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蹋笼。 經(jīng)常有香客問我规个,道長,這世上最難降的妖魔是什么姓建? 我笑而不...
    開封第一講書人閱讀 56,554評論 1 284
  • 正文 為了忘掉前任诞仓,我火速辦了婚禮,結(jié)果婚禮上速兔,老公的妹妹穿的比我還像新娘墅拭。我一直安慰自己,他們只是感情好涣狗,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,662評論 6 386
  • 文/花漫 我一把揭開白布谍婉。 她就那樣靜靜地躺著,像睡著了一般镀钓。 火紅的嫁衣襯著肌膚如雪穗熬。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,856評論 1 290
  • 那天丁溅,我揣著相機(jī)與錄音唤蔗,去河邊找鬼。 笑死窟赏,一個胖子當(dāng)著我的面吹牛妓柜,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播涯穷,決...
    沈念sama閱讀 39,014評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼棍掐,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了拷况?” 一聲冷哼從身側(cè)響起作煌,我...
    開封第一講書人閱讀 37,752評論 0 268
  • 序言:老撾萬榮一對情侶失蹤掘殴,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后粟誓,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體奏寨,經(jīng)...
    沈念sama閱讀 44,212評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,541評論 2 327
  • 正文 我和宋清朗相戀三年努酸,在試婚紗的時候發(fā)現(xiàn)自己被綠了服爷。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,687評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡获诈,死狀恐怖仍源,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情舔涎,我是刑警寧澤笼踩,帶...
    沈念sama閱讀 34,347評論 4 331
  • 正文 年R本政府宣布,位于F島的核電站亡嫌,受9級特大地震影響嚎于,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜挟冠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,973評論 3 315
  • 文/蒙蒙 一于购、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧知染,春花似錦肋僧、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,777評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至掺炭,卻和暖如春辫诅,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背涧狮。 一陣腳步聲響...
    開封第一講書人閱讀 32,006評論 1 266
  • 我被黑心中介騙來泰國打工炕矮, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人勋篓。 一個月前我還...
    沈念sama閱讀 46,406評論 2 360
  • 正文 我出身青樓吧享,卻偏偏與公主長得像,于是被迫代替她去往敵國和親譬嚣。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,576評論 2 349

推薦閱讀更多精彩內(nèi)容