我注意到,当一个合同工厂用' new‘关键字创建一个新合同时,交易成本就像它第一次部署合同一样,花费了大量的天然气。我不明白为什么这么高的天然气成本,如果合同已经部署过,而且代码已经“在区块链中”,那么为什么它需要重新部署整个代码。
下面是一个例子:
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契约的‘TokenCreator’函数,创建OwnedToken契约的一个对象。但是,如果代码总是相同的话,为什么调用函数的成本与部署OwnedToken契约的成本一样高呢?
谢谢。
发布于 2020-07-04 02:02:09
正如@Good颤振所言,您总是创建不同的实例。因此,byteCode是复制的,因此成本总是相同的气体。
为了避免这种情况,您可以使用一个克隆工厂:https://github.com/optionality/clone-factory。它创建一个新的契约,它将所有调用委托给给定的库契约。库只部署了一次,所以克隆工厂部署要便宜得多。
更新:如果有人感兴趣的话,写一篇关于克隆工厂的博客文章:https://soliditydeveloper.com/clonefactory。
发布于 2020-07-04 01:42:02
如果契约以前已经部署过,并且代码已经“在块链中”,那么为什么它需要再次部署整个代码?
因为相同的契约可能有不同的实例部署在不同的地址和持有不同值的状态变量。
https://ethereum.stackexchange.com/questions/84764
复制相似问题