Solidity

從地址到合約類型的顯式轉換實際上在 Solidity 中做了什麼?

  • December 19, 2021

我開始進行solidity開發,我看到它在契約中被使用,我不太明白它的含義。

contract A {
   address bAddress;
   constructor(address b){
      bAddress = b;
   }

   function callHello() external view returns(string memory){
      B b = B(bAddress); // explicit conversion from address to contract type
      return b.sayHello();
   }
}
contract B {
    string greeting = "hello world";
    function sayHello() external view returns(string memory){
        return greeting;
    }
}

在這個例子中,我們有B b = B(bAddress);. 這段程式碼是我有疑問的部分,我試圖搜尋任何可以幫助我的問題,但我沒有找到一個能夠準確解釋為什麼將bAddress它傳遞給B契約的問題。它是建構子的隱藏參數嗎?就像,它在那裡的東西,你總是可以把它傳遞進去?我們放在那裡的地址會變成類型B的合約地址嗎?

抱歉,如果這是一個反復出現的問題,我只是找不到可以幫助我理解這一點的答案。在上面的範例中,他們確實有一條註釋說關於該行從地址到契約類型的顯式轉換,但我無法理解。

提前致謝。

在 Solidity 中,合約變數實際上只是一個底層地址。

您實際上可以與部署在特定地址的程式碼進行互動,而無需合約變數。address具有成員函式,例如.call()。這些函式是進行外部呼叫的低級 EVM 方式。在這個級別上,函式並不真正存在。您指定一些呼叫數據發送到該程式碼並接收回一段返回數據。

Solidity 的合約類型是一種抽象,使外部程式碼看起來更像您可能從其他語言中熟悉的類。類可以有方法,在 Solidity 中,編譯器通過讓字節碼在呼叫數據的前 4 個字節中期望函式 ID(選擇器)來模擬這一點,並根據發送的 ID 執行不同的操作。具體來說,ID 決定瞭如何解釋它後面的數據(即參數)。

無需在地址上使用低級.call()並手動建構正確的呼叫數據,您只需在合約上呼叫外部函式,編譯器就會為您將其轉換為它生成的字節碼中的低級呼叫。但是,要做到這一點,它需要知道該合約的地址。您可以通過將地址轉換為合約類型來提供此資訊。為方便起見,您可以將此類轉換的結果儲存在契約變數中,而不必每次都進行轉換。

除了外部功能外,合約也有內部功能,它們的工作方式非常不同。您可能注意到您不能在合約變數上呼叫內部函式。您只能從您自己的合約或從您繼承的合約中呼叫內部函式。這是因為對這些的呼叫不會轉到不同的地址,也不需要模擬外部函式的整個機制。它們是駐留在合約自己的字節碼中的實際函式。呼叫它們只是正常跳轉到字節碼中的不同位置。

因此,總而言之,合約包含您在合約本身中使用的內部函式和您自己不呼叫但希望從其他合約呼叫的外部函式的混合。當您只使用後者時,這可能會令人困惑,因為您不需要所有其他東西。您甚至不需要知道呼叫它的函式體,只需知道名稱和參數即可。這就是為什麼存在另一種契約 - interface. 介面只定義外部函式的名稱和參數。這就是執行外部呼叫所需要知道的全部內容。在您的範例中顯示的情況下,使用介面而不是實際契約更為常見,我認為它的目的更清晰。

契約建設是另一回事。鑄造時根本不涉及建構子。只有在部署合約時才會呼叫建構子,這通常發生在完全獨立的事務中。在這種情況下,建構子參數包含在事務數據中。

只能通過以下兩種方式之一從合約中呼叫建構子:

  1. 將參數傳遞給基本建構子。這不會被誤認為是強制轉換,因為它永遠不會發生在函式體內。
  2. 部署另一個合約的合約。這使用了不同的語法:new B(...)因此它也可以明顯地與演員表區分開來。請注意,您不能將其與介面一起使用,因為它們只攜帶足夠的資訊來呼叫它們所代表的合約,而不是重新創建它。

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