Solidity
Solidity 多重契約和繼承問題
我的智能合約已經超過了
24K
允許的大小Ethereum
,所以我不得不把它分解成更小的合約。然後,我不得不促進這些合約之間的各種繼承和導入,以使一切再次正常工作,但最後,我仍然無法成功部署——而且似乎是相同的“合約大小也是如此” -大”的原因。這是松露告訴我的:Error: *** Deployment Failed *** "DBTCFull" ran out of gas (using a value you set in your network config or deployment parameters.) * Block limit: 6721975 (0x6691b7) * Gas sent: 6721975 (0x6691b7)
我很確定我收到了這個錯誤,因為契約仍然太大。
由於我只完成了這個項目的 2/3 並且還有更多程式碼要編寫,因此大小將是一個問題。所以我在這裡真正想了解的是我應該採取什麼方法。我應該使用:
- 繼承- 契約在哪裡導入其他契約?或者
- 參考- 契約在哪裡單獨部署,然後相互參考?
這是一個大致說明我的合約應該如何相互互動的場景:
契約#1
contract MakePizza { // 1. This contract defines a “Pizza” Struct and… // 2. Has functions to make various Types of Pizza Struct Pizza { … } // etc. }
契約#2
contract DeliverPizza is MakePizza { // This contract only handles the Deliveries of Pizzas. So it: // 1. Defines a “Customer” Struct (customer’s name, phone number, etc.) // 2. Defines a “CustomerAddress” Struct (street address, city, zip-code, etc.) // 3. Has “delivery” type functions }
契約#3
Contract HandleTheMoney is MakePizza, DeliverPizza { // Defines all things having to do with funds: // 1. Acceptable Payment methods // 2. Defines various Fees // 3. Declares the Permissions re who’s allowed to withdraw funds from the contract, etc. }
// 最後,契約#4:
contract JoesPizzaShop is MakePizza, DeliverPizza, HandleTheMoney { // The “master” contract, bringing everything together }
所以我很確定這是繼承方法。(因為我在
is MakePizza
這裡使用該語法。)現在事情是這樣的:這一切都成功編譯- 但無法部署,給了我上面列出的錯誤。似乎將所有文件相互導入並沒有做任何事情來減少整體大小。
另一種方法是分別部署每個合約,然後在“主”合約中獲取它們的實例——被呼叫的合約——
JoesPizzaShop
並以這種方式工作。我認為後一種方法會“更乾淨”——而且希望更小。但我擔心它也可能會產生自己獨特的噩夢。甚至可能需要重大的架構更改。
所以基本上,我不知道如何進行。
鑑於契約的規模似乎是主要問題,我應該採取哪種方法?
我只是以錯誤的方式執行繼承方法 - 還是一開始就是錯誤的方法?
在編譯時,所有合約都組合在一起以產生一個字節碼,因此繼承對於減小合約大小沒有多大幫助。
從錯誤消息來看,問題似乎是氣體不足,您似乎使用的是預設氣體 6.7M 氣體。作為參考,目前主網的區塊氣體限制超過 12M 氣體。
一個臨時的解決方案是增加塊氣體限制。
- 對於松露,編輯網路配置並添加氣體參數。
networks: { development: { host: "127.0.0.1", port: 8545, network_id: "*", websockets: true, gas: 12000000 // <--- Increased block gas limit },
- 對於 ganache-cli 將請求的氣體傳遞給
-l
參數:ganache-cli -l 12000000
擁有單獨合約的另一種方法是使用庫來分離功能。它需要更多的計劃來分離庫並調整遷移腳本以將庫部署和連結到主合約中。
pragma solidity >=0.4.0 <0.8.0; pragma experimental ABIEncoderV2; library PizzaLib { struct Pizza { uint256 ingredients; } function mix(Pizza calldata pizza, uint256 ingredients) external pure returns (Pizza memory) { Pizza memory p = pizza; p.ingredients = ingredients; return p; } } contract PizzaShop { using PizzaLib for PizzaLib.Pizza; function foo() public pure returns (PizzaLib.Pizza memory) { PizzaLib.Pizza memory pizza; pizza = pizza.mix(23); return pizza; } }
例如遷移看起來像
module.exports = async function(deployer, network, accounts) { await deployer.deploy(PizzaLib); await deployer.link(PizzaLib, PizzaShop); await deployer.deploy(PizzaShop); }