內部合約到合約呼叫
我對 Solidity 文件中的以下句子感到困惑:
在執行回退功能期間,合約只能依靠它傳遞的“gas 津貼”(2300 gas)當時可用。
我的文章是這個文章的延續。這篇文章有一個答案說
“津貼”適用於從一個智能合約到另一個智能合約的內部發送。因為 send 無法指定 gas 數量(而 call 可以),Solidity 規定了一個最大 gas 數量(即 2300)。
因為 OP 的交易不是內部契約到契約發送,所以 2300 津貼不適用並且交易通過了。
那麼,“內部”是什麼意思?假設我(作為 EOA)簽署交易 TX1 並廣播它。這個 TX1
foo
在合約 A 中執行一個函式,將乙太幣轉移到另一個合約 B。contract contractA { //... function foo() external { //... contractB.transfer(1 ether); } //... }
是
contractB.transfer(1 ether);
內部呼叫嗎?我猜這是外部呼叫,因為它呼叫另一個契約。如果交易總是有發件人設置的氣體限制,那麼津貼的含義是什麼?什麼時候,在什麼情況下,這個該死的“津貼”適用?
有人可以提供一段程式碼或描述一個場景,當 2300 津貼不夠時,當我們設置 gasLimit 足以執行
transfer
功能時?
如果交易總是有發件人設置的氣體限制,那麼津貼的含義是什麼?
並不真地。當 EOA 呼叫合約 A 時,交易中設置了 gas 限制,這是真的。但是,當合約 A 呼叫合約 B 時,合約 A 可能會限制合約 B 可以花費多少 gas。這個限制可能低於目前剩餘的天然氣合約 A。在這種情況下,即使呼叫合約 B 會耗盡 gas 並因此失敗,合約 A 仍然有一些 gas 來處理這種情況。
什麼時候,在什麼情況下,這個該死的“津貼”適用?
一個合約呼叫另一個合約的方式有多種,這些方式的行為不同:
- 一個人可能只是將其他合約的方法稱為函式。在這種情況下,呼叫合約將被允許花費交易中剩餘的所有氣體。
- 可以使用函式
call
,delegatecall
或staticall
允許明確指定呼叫合約允許花費多少 gas(儘管預設情況下這些函式允許花費所有剩餘的 gas)。- 可以使用允許被呼叫合約最多花費 2300 gas 的函式
transfer
,send
並且這個硬編碼的值不能更改。當 2300 津貼不夠時,有人可以提供一段程式碼或描述一個場景嗎?
當然。讓我們假設合約 B 的以下實現:
contractB { uint private etherReceived = 0; function () external payable { etherReceived += msg.value; } }
合約試圖通過備份功能計算它曾經收到多少乙太幣。這個實現有一個問題,因為它更新了回退函式中的儲存變數,並且這樣的更新花費了 5000 或更多的氣體。因此,
transfer
從另一個契約到這樣的契約將失敗。有人可以提供一段程式碼或描述一個場景……我們設置了足以執行傳輸功能的gasLimit嗎?
函式
transfer
具有不可更改的硬編碼氣體限制 2300。然而,這裡有一個合約的例子,它的備份功能符合這個嚴格的限制,但做了一些有用的事情:contractB { event Deposit (address from, uint value); function () external payable { emit Deposit (msg.sender, msg.value); } }
津貼是2300,不是23000。
這種津貼不夠的情況:
將狀態變數從零更改為非零。