Solidity

內部合約到合約呼叫

  • November 15, 2019

我對 Solidity 文件中的以下句子感到困惑:

在執行回退功能期間,合約只能依靠它傳遞的“gas 津貼”(2300 gas)當時可用。

我的文章是這個文章的延續。這篇文章有一個答案說

“津貼”適用於從一個智能合約到另一個智能合約的內部發送。因為 send 無法指定 gas 數量(而 call 可以),Solidity 規定了一個最大 gas 數量(即 2300)。

因為 OP 的交易不是內部契約到契約發送,所以 2300 津貼不適用並且交易通過了。

那麼,“內部”是什麼意思?假設我(作為 EOA)簽署交易 TX1 並廣播它。這個 TX1foo在合約 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 來處理這種情況。

什麼時候,在什麼情況下,這個該死的“津貼”適用?

一個合約呼叫另一個合約的方式有多種,這些方式的行為不同:

  1. 一個人可能只是將其他合約的方法稱為函式。在這種情況下,呼叫合約將被允許花費交易中剩餘的所有氣體。
  2. 可以使用函式call,delegatecallstaticall允許明確指定呼叫合約允許花費多少 gas(儘管預設情況下這些函式允許花費所有剩餘的 gas)。
  3. 可以使用允許被呼叫合約最多花費 2300 gas 的函式transfersend並且這個硬編碼的值不能更改。

當 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。

這種津貼不夠的情況:

將狀態變數從零更改為非零。

引用自:https://ethereum.stackexchange.com/questions/77521