W3Cschool
恭喜您成為首批注冊用戶
獲得88經驗值獎勵
當前合約的函數可以直接(“內部”)調用,也可以遞歸調用,如以下無意義的示例所示:
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.22 <0.9.0; // This will report a warning contract C { function g(uint a) public pure returns (uint ret) { return a + f(); } function f() internal pure returns (uint ret) { return g(7) + f(); } }
這些函數調用被轉換為 EVM 內的簡單跳轉。這具有不清除當前內存的效果,即將內存引用傳遞給內部調用的函數非常有效。只能在內部調用同一合約實例的函數。
您仍然應該避免過度遞歸,因為每個內部函數調用至少使用一個堆棧槽并且只有 1024 個可用槽。
也可以使用this.g(8);
andc.g(2);
表示法調用函數,其中 c
是合約實例,g
是屬于 的函數c
。通過任何一種方式調用函數g
都會導致它被“外部”調用,使用消息調用而不是直接通過跳轉。請注意,函數調用this
不能在構造函數中使用,因為實際的合約尚未創(chuàng)建。
其他合約的函數必須在外部調用。對于外部調用,所有函數參數都必須復制到內存中。
筆記
從一個合約到另一個合約的函數調用不會創(chuàng)建自己的交易,它是作為整個交易的一部分的消息調用。
在調用其他合約的函數時,您可以通過特殊選項指定調用時發(fā)送的 Wei 或 Gas 數量。請注意,不鼓勵明確指定 gas 值,因為操作碼的 gas 成本可能會在未來發(fā)生變化。您發(fā)送給合約的任何 Wei 都會添加到該合約的總余額中:{value: 10, gas: 10000}
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.6.2 <0.9.0; contract InfoFeed { function info() public payable returns (uint ret) { return 42; } } contract Consumer { InfoFeed feed; function setFeed(InfoFeed addr) public { feed = addr; } function callFeed() public { feed.info{value: 10, gas: 800}(); } }
您需要將修飾符payable
與info
函數一起使用,否則該value
選項將不可用。
警告
請注意,僅在本地設置 函數調用的發(fā)送量和發(fā)送量,最后的括號執(zhí)行實際調用。so 不調用函數并且和設置丟失,只 執(zhí)行函數調用。feed.info{value: 10, gas: 800}
value
gas
feed.info{value: 10, gas: 800}
value
gas
feed.info{value: 10, gas: 800}()
由于 EVM 認為對不存在的合約的調用總是成功的,Solidity 使用extcodesize
操作碼檢查即將被調用的合約是否確實存在(它包含代碼),如果不存在則引發(fā)異常. 如果返回數據將在調用后被解碼,則跳過此檢查,因此 ABI 解碼器將捕獲不存在合約的情況。
請注意,在對地址而不是合約實例進行操作的低級調用的情況下,不會執(zhí)行此檢查。
筆記
對預編譯合約使用高級調用時要小心 ,因為即使它們執(zhí)行代碼并且可以返回數據,編譯器也會根據上述邏輯認為它們不存在。
如果被調用的合約本身拋出異常或耗盡gas,函數調用也會導致異常。
警告
與另一個合約的任何交互都會帶來潛在的危險,特別是如果事先不知道合約的源代碼。當前的合約將控制權移交給被調用的合約,這可能會做任何事情。即使被調用的合約繼承自已知的父合約,也只需要繼承的合約有正確的接口即可。然而,合同的執(zhí)行可能是完全任意的,因此會造成危險。此外,請做好準備,以防它在第一次調用返回之前調用系統(tǒng)的其他合約,甚至返回調用合約。這意味著被調用合約可以通過其函數改變調用合約的狀態(tài)變量。以某種方式編寫函數,例如,
筆記
在 Solidity 0.6.2 之前,指定值和氣體的推薦方法是使用f.value(x).gas(g)()
. 這在 Solidity 0.6.2 中已被棄用,并且自 Solidity 0.7.0 起不再可行。
函數調用參數可以按任何順序按名稱給出,如果它們被包含在下面的示例中。參數列表的名稱必須與函數聲明中的參數列表一致,但可以是任意順序。{ }
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.0 <0.9.0; contract C { mapping(uint => uint) data; function f() public { set({value: 2, key: 3}); } function set(uint key, uint value) public { data[key] = value; } }
未使用的參數(尤其是返回參數)的名稱可以省略。這些參數仍將存在于堆棧中,但無法訪問。
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.22 <0.9.0; contract C { // omitted name for parameter function func(uint k, uint) public pure returns(uint) { return k; } }
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: