我有一个契约,我希望能够创建一个相同合同的副本,然后让子项目能够从父协议中检索数据。当我试图编译以下内容时,这是我要做的内容的简化版本:
contract Example {
uint256 num;
address parent;
function Example(uint256 _num, address _parent) {
num = _num;
parent = _parent;
}
function createChild() {
uint256 childNum = num + 1;
Example child = new Example(childNum, this);
}
function getNumber() constant returns (uint256) {
return num;
}
function getParentNumber() constant returns (uint256) {
Example e = Example(parent);
return e.getNumber();
}
}可以理解的是,...the solidity编译器抱怨:
example.sol:15:25: Error: Circular reference for contract creation (cannot create instance of derived or same contract).
Example child = new Example(childNum, this);这与文档所说的发生的情况相匹配:http://solidity.readthedocs.io/en/develop/contracts.html#multiple-inheritance-and-linearization
所以我不能那样做是有道理的。但是,是否有一种(最好是干净的)方法来完成一项合同,用与其本身相同的代码创建一个契约,然后调用该契约上的方法并获取数据?
发布于 2016-10-04 21:39:51
刀 (有5,000万美元的缺陷)是一个很好的例子,说明合同能够使用工厂创建自己的副本。
这是工厂的合同:
contract DAO_Creator {
function createDAO(
address _curator,
uint _proposalDeposit,
uint _minTokensToCreate,
uint _closingTime
) returns (DAO _newDAO) {
return new DAO(
_curator,
DAO_Creator(this),
_proposalDeposit,
_minTokensToCreate,
_closingTime,
msg.sender
);
}
}下面是创建新的子DAOs的代码:
contract DAO is DAOInterface, Token, TokenCreation {
...
function splitDAO(
uint _proposalID,
address _newCurator
) noEther onlyTokenholders returns (bool _success) {
...
p.splitData[0].newDAO = createNewDAO(_newCurator);
...
}
...
function createNewDAO(address _newCurator) internal returns (DAO _newDAO) {
NewCurator(_newCurator);
return daoCreator.createDAO(_newCurator, 0, 0, now + splitExecutionPeriod);
}
...
}有一种方法可以通过父契约的splitDAO(...)方法将以太和令牌从父契约转移到子契约(这是DAO黑客利用的)。
您应该能够设计您的合同,以便在引用父合同的子合同中执行方法。
发布于 2018-05-16 03:00:47
我写了一篇关于如何在媒体上解决这个问题的文章。
https://medium.com/@kylebryant_28277/subverting-the-circular-reference-error-in-solidity-f7167bf9fdb
基本上,您需要创建两个新契约,一个创建您想要的类型的新契约,另一个创建该契约的抽象契约。我把这叫做制造商和供应商的合同。读一读:)!
pragma solidity ^0.4.17;
contract VotethComment {
string public comment;
string public nickname;
address public author;
address[] public votethComments;
address votethCommentMaker;
constructor(string _comment, string _nickname, address _author, address _votethCommentMaker) public {
comment = _comment;
nickname = _nickname;
author = _author;
votethCommentMaker = _votethCommentMaker;
}
function addComment(string _comment, string _nickname) public {
VotethCommentSupplier votethCommentSupplier = VotethCommentSupplier(votethCommentMaker);
votethComments.push(votethCommentSupplier.makeComment(_comment, _nickname, msg.sender));
}
}
contract VotethCommentSupplier {
function makeComment(string _comment, string _nickname, address _author) public returns(address);
}
contract VotethCommentMaker {
function makeComment(string _comment, string _nickname, address _author) public returns(address) {
return new VotethComment(_comment, _nickname, _author, this);
}
}发布于 2018-08-28 12:50:36
你可以做这样的事。
contract ObjectFactory{
function createObject() returns(address){
Object subObject = new Object();
return subObject;
}
}
contract Object{
function createSubObject(ObjectFactory factory) returns(address) {
address objectAddress = factory.createObject();
return ObjectAddress;
}
}此代码将使对象契约创建类型为Object的子合同,ObjectAddress将返回新创建对象的地址。
请注意,可以将ObjectFactory factory视为正常地址。
https://ethereum.stackexchange.com/questions/9000
复制相似问题