Remix

為什麼solidity會拋出“注意:如果您發送值,則應支付建構子。”,而問題顯然出在其他地方?

  • January 14, 2021

我正在Remix上編寫一份能夠部署和跟踪子契約的契約。

以下是2份契約:

pragma solidity ^0.5.0;

契約工廠

contract ContractFactory{
   ChildContract[] public createdContracts;
   ChildContract public activeChild;

   function createChild() public{
       ChildContract newChild = new ChildContract();
       createdContracts.push(newChild);
       // if (address(activeChild) != address(0)){
           activeChild.activate(false);
       // }
       activeChild = newChild;
   }
}

兒童契約

contract ChildContract{
   bool isActive;

   constructor() public{
       isActive = true;
   }

   function activate(bool status) public{
       isActive = status;
   }
}

我部署了 ContractFactory,它是成功的。然後我嘗試呼叫該createChild函式。然後我收到以下錯誤:

transact to ContractFactory.createChild errored: VM error: revert.
revert  The transaction has been reverted to the initial state.
Note: The constructor should be payable if you send value.  Debug the transaction to get more information. 

從程式碼中可以明顯看出,如果我取消註釋函式if condition內部的註釋createChild,該函式將毫無問題地執行。我的問題是 - 為什麼solidity會拋出這個誤導性錯誤,因為問題在於未設置的變數?

Solidity throwing暗示這是一個編譯錯誤,這顯然不是這裡的情況。

送出事務的 web3 客戶端(在您的情況下為 Remix)在執行時引發異常。

它被拋出是因為您屏蔽了該if (address(activeChild) != address(0))語句,因此嘗試呼叫activeChild.activate(當activeChild指向地址 0 時)會恢復事務。

此資訊由 Remix 明確提供給您:

transact to ContractFactory.createChild errored: VM error: revert.
revert  The transaction has been reverted to the initial state.

關於建構子的註釋…好吧,它只是讓您了解所記錄的事實的註釋…

註釋掉檢查是失敗的原因。

activeChild直到後來才成為有效實例。

activeChild = newChild;

但這條線似乎是在試圖停用前任。如果沒有前任怎麼辦?

activeChild.activate(false)

在第一次執行時,不會有 previous activeChild,所以檢查很重要,否則肯定會遇到麻煩。

我可能會更明確地進行比較。

if(address(activeChild) != address(0)) { // carry on and deactivate it

正如其他評論員所提到的,執行時錯誤的可能原因只是一種猜測,而且常常具有誤導性。

希望能幫助到你。

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