Solidity
工廠契約的高gas成本!
我注意到,當合約工廠使用“new”關鍵字創建新合約時,交易會花費大量的 gas,就好像它是第一次部署合約一樣。我不明白為什麼這麼高的 gas 成本,如果之前已經部署了合約並且程式碼已經在“區塊鏈中”,那麼為什麼需要再次部署整個程式碼。
這是一個例子:
pragma solidity >=0.4.22 <0.6.0; contract OwnedToken { // `TokenCreator` is a contract type that is defined below. // It is fine to reference it as long as it is not used // to create a new contract. TokenCreator creator; address owner; bytes32 name; // This is the constructor which registers the // creator and the assigned name. constructor(bytes32 _name) public { // State variables are accessed via their name // and not via e.g. `this.owner`. Functions can // be accessed directly or through `this.f`, // but the latter provides an external view // to the function. Especially in the constructor, // you should not access functions externally, // because the function does not exist yet. // See the next section for details. owner = msg.sender; // We do an explicit type conversion from `address` // to `TokenCreator` and assume that the type of // the calling contract is `TokenCreator`, there is // no real way to check that. creator = TokenCreator(msg.sender); name = _name; } function changeName(bytes32 newName) public { // Only the creator can alter the name -- // the comparison is possible since contracts // are explicitly convertible to addresses. if (msg.sender == address(creator)) name = newName; } function transfer(address newOwner) public { // Only the current owner can transfer the token. if (msg.sender != owner) return; // We ask the creator contract if the transfer // should proceed by using a function of the // `TokenCreator` contract defined below. If // the call fails (e.g. due to out-of-gas), // the execution also fails here. if (creator.isTokenTransferOK(owner, newOwner)) owner = newOwner; } } contract TokenCreator { function createToken(bytes32 name) public returns (OwnedToken tokenAddress) { // Create a new `Token` contract and return its address. // From the JavaScript side, the return type is // `address`, as this is the closest type available in // the ABI. return new OwnedToken(name); } function changeName(OwnedToken tokenAddress, bytes32 name) public { // Again, the external type of `tokenAddress` is // simply `address`. tokenAddress.changeName(name); } // Perform checks to determine if transferring a token to the // `OwnedToken` contract should proceed function isTokenTransferOK(address currentOwner, address newOwner) public pure returns (bool ok) { // Check an arbitrary condition to see if transfer should proceed return keccak256(abi.encodePacked(currentOwner, newOwner))[0] == 0x7f; } }
TokenCreator 合約的’createToken’ 函式創建一個 OwnedToken 合約的對象。但是,如果程式碼始終相同,為什麼呼叫該函式的成本與部署 OwnedToken 合約的成本一樣高呢?
謝謝你。
正如@goodvibration 所說,您總是創建不同的實例。因此 byteCode 是重複的,因此總是消耗相同數量的 gas。
為避免這種情況,您可以使用複製工廠:https ://github.com/optionality/clone-factory 。它創建了一個新合約,將所有呼叫委託給給定的庫合約。該庫僅部署一次,因此複製工廠部署要便宜得多。
更新:如果有人感興趣,寫一篇關於複製工廠的部落格文章:https ://soliditydeveloper.com/clonefactory 。