Solidity中通过合约部署合约

在 Solidity 中,通过合约来部署合约只有一种方法(据我所知),就是使用new关键字(不使用 opcode)。

首先看一个例子。

contract Person {

    string public name;

    uint public age;

    function Person(string _name, uint _age) {
        name = _name;
        age = _age;
    }
}

contract Goddess {

    address[] people;

    function createPeople(string name, uint age) {
        people.push(new Person(name, age));
    }

}

上例中定义了两个合约。每次调用 Goddess 合约的createPeople方法时,就会通过new Person()在链上部署一个 Person 合约,并将合约的地址保存在people中。

由上例可以看出:
1. Goddess 可以部署无限个 Person 合约;
2. Goddess 只能部署 Person 合约。

其中,第2点意味着在编写 Goddess 合约时,Person 合约是已知的。实际上,如果查看编译后的二进制代码,会发现 Goddess 合约的代码中完整包含了 Person 合约的代码。也就是说,Person合约被“打包”到 Goddess 合约里了。

接下来,考虑先将 Goddess 部署到链上,然后再指定 Person 合约。这意味着,在没有指定之前,Goddess 并不知道自己要部署的是什么合约。

注意:虽然 Goddess 不需要知道待部署合约的内容,但必须知道待部署合约的构造函数的参数,否则无法进行部署。

实现的方法如下:

contract Person {

    string public name;

    uint public age;

    function Person(string _name, uint _age) {
        name = _name;
        age = _age;
    }

}

contract PersonCreator {

    function create(string name, uint age) returns (address) {
        return new Person(name, age);
    }

}

contract Goddess {

    PersonCreator creator;

    address[] people;

    function setCreator(PersonCreator _creator) {
        creator = _creator;
    }

    function createPeople(string name, uint age) {
        people.push(creator.create(name, age));
    }

}

在这里,添加了一个中间合约 PersonCreator,其中只有一个函数create用来部署 Person 合约,并返回合约地址。而 Goddess 通过 PersonCreator 来部署 Person 合约。

具体的步骤如下:
1. 部署 Goddess 合约到链上。此时creator尚未指定,Goddess 不知道待部署的合约是什么,只知道部署合约所需的参数是string name, uint age
2. 将 PersonCreator 部署到链上,得到其地址;
3. 调用 Goddess 合约的setCreator方法,将 PersonCreator 的地址传入;
4. 调用 Goddess 合约的createPeople方法,部署 Person 合约。

在上述实现方法中,主要包括两个合约。一个是 PersonCreator,一个是 Goddess。(Person 合约是不必要的,因为它的代码已经被“打包”在 PersonCreator 里了。)这两个合约在一定程度上实现了解耦合,唯一的耦合点就是如下的接口:

function create(string name, uint age) returns (address)

因此,可以在此基础上做一些更加灵活的事情:
1. 编写并部署 Alien 和 AlienCreator 合约,其中 AlienCreator 实现上述接口。则可以通过调用 Goddess 合约的setCreator方法,使 Goddess 合约可以部署 Alien 合约。以此类推,只要符合上述接口的合约,都可以通过 Goddess 合约来部署,
2. 只要知道 PersonCreator 的地址和上述接口,任何合约都可以部署 Person 合约。

在上述方法中,可以将接口的参数设置为bytes,使接口更通用,然而也会更复杂。

通过合约部署合约,如何获取部署的合约的地址,是一件相对来说比较麻烦的事情。目前我所使用的方法是将合约的地址通过事件写入到日志中,从而得知指定交易中建立了哪些合约。

发表评论

电子邮件地址不会被公开。 必填项已用*标注