Deploy subDAOs With the subDAOs Factory
An entire SubDAO can be deployed using the subDAO Factory in a single transaction. You can use the subDAO Factory on the EthereansOS platform here (link coming soon).
The subDAO Factory, which is a custom Factory, allows you to clone (via the deploy function) your subDAO, choose which Components you want to link to it and initialize everything at once.
You can assemble the Root Layer with a selection of the following Components:
  • Treasury Manager
  • State Manager
  • SubDAO Manager
  • Delegations Manager
  • Treasury Splitter Manager
  • Investments Manager
The Proposal Manager is the only mandatory Component; it is automatically cloned and linked to your subDAO.

Deploy the subDAO

As input, the deploy method of the Factory takes the deployData parameter:
1
function deploy(bytes calldata deployData) external payable override(Factory, IFactory) virtual returns(address productAddress, bytes memory productInitResponse) {
Copied!
deployData is the encoded value of the OrganizationDeployData struct, which is composed as follows:
1
struct OrganizationDeployData {
2
string uri;
3
bytes[] mandatoryComponentsDeployData;
4
uint256[] additionalComponents;
5
bytes[] additionalComponentsDeployData;
6
bytes[] specialComponentsData;
7
bytes specificOrganizationData;
8
}
Copied!
  • string uri -> this uri parameter contains the subDAO's metadata. The subDAO contract implements the DynamicMetadataCapableElement, so that you can set a traditional or a dynamic uri (see here to learn more).
  • bytes[] mandatoryComponentsDeployData -> this init data is used to initialize the Proposal Manager, which is the only mandatory Component of the SubDAO.
  • uint256[] additionalComponents -> this is an index of the additional Components that you want to link to the SubDAO. Look below to find the Component indices.
  • bytes[] additionalComponentsDeployData -> this init data is used to initialize the additional chosen Components. Each position in the bytes array corresponds to the sequentially equivalent position in the additionalComponents array.
  • bytes[] specialComponentsData -> this data is used to link and initialize external Components to the deployed subDAO. See below to learn more.
  • bytes specificOrganizationData -> this data is used to initialize the subDAO. See below to learn more.
specificOrganizationData
The specificOrganizationData is used to initialize some parameters of the subDAO.
It must contain the following encoded parameters:
  • bool initToBeFinalized -> this represents if the subDAO has to be finalized later (true) or not (false).
  • address organizationHost -> this represents the subDAO Manager contract address, which is the subDAO host address. See here to learn more about initToBeFinalized and organizationHost.
  • proposalModels -> the model in the first position of this parameter is the poll model, and the others are a series of prefixed models that define the fixed executable Proposals that can be created and voted on using this specific subDAO. See here to learn more.
specialComponentsData
This parameter can be used to link and initialize external Components to the subDAO. The parameter must be the encoded valued of:
1
(bytes32 key, address modelOrLocation, bool active, bytes memory deployData) = abi.decode(specialComponentData, (bytes32, address, bool, bytes));
Copied!
for each element of the bytes[] specialComponentsData array.
  • bytes32 key -> it represents the user defined key of the Component.
  • address modelOrLocation -> it represents the Component address.
  • bool active -> it represents if the Component must be linked as active (true) or not (false)
  • bytes deployData -> if it's passed, it must contain encoded valued of:
    • clone -> it represents if the Component must be cloned (true) or not (false).
    • deployData -> it represents the initialization data of the Component.
So if you have a deployed and initialized Component you have to pass clone as false and deployData empty. If you have a deployed and not initialized Component you have to pass clone as false and deployData populated. If you have a not deployed and not initialized Component you have to pass clone as true and deployData populated.
Component Indices
  • Proposal Manager -> 0
  • Treasury Manager -> 1
  • State Manager -> 2
  • TreasurySplitter Manager -> 3
  • SubDAO Manager -> 4
  • Delegations Manager -> 5
  • Investments Manager -> 6

How to Pass the deployData

In this example, the Component indices are:
1
var values = ["proposalsManager", "treasuryManager", "stateManager", "treasurySplitterManager", "subDAOsManager", "delegationsManager"];
Copied!
The deployData to pass is composed as follows:
1
// Proposal Manager init data
2
mandatoryComponentsDeployData[0] = abi.encode(['tuple(address[],uint256[],uint256[],address,address,address[],address[])'], [
3
[
4
[], //address[] collections
5
[], //uint256[] objectIds
6
[], //uint256[] weights
7
utilities.voidEthereumAddress, //address creationRules
8
utilities.voidEthereumAddress, //triggeringRules
9
[], //address[] canTerminateAddresses
10
[] //address[] validatorsAddresses
11
]
12
]);
13
14
//in this example the Treasury, State Manager and TreasurySplitter Managers are linked as additional Components
15
var additionalComponentsDeployData = [
16
//Treasury Manager init data
17
"0x",
18
//State Manager init data
19
abi.encode(['tuple(string,bytes32,bytes)'], [
20
[
21
"test",
22
utilities.voidBytes32,
23
"0x"
24
]
25
]),
26
//TreasurySplitter init data
27
web3.eth.abi.encodeParameters(["uint256", "uint256", "bytes32[]", "uint256[]", "bytes32", "uint256", "uint256"], [0, 0, [],
28
[], utilities.voidBytes32, 2, 3
29
])
30
];
31
32
//Proposal Model init data
33
var subDAOProposalModelTypes = [
34
"address",
35
"string",
36
"bool",
37
"bytes[]",
38
"bytes32[]",
39
"address",
40
"address",
41
"uint256",
42
"address[][]",
43
"address[][]"
44
];
45
46
var subDAOProposalModels = [{
47
source : utilities.voidEthereumAddress, //address source
48
uri : "str", //string uri
49
perpetual : false, //bool isPreset
50
bytes : [], //bytes[] presetValues
51
bytes32 : [], //bytes32[] presetProposals
52
a : utilities.voidEthereumAddress, //address creationRules
53
b : utilities.voidEthereumAddress, //address triggeringRules
54
c : 0, //uint256 votingRulesIndex
55
d : [[utilities.voidEthereumAddress]], //address[][] canTerminateAddresses
56
e : [[utilities.voidEthereumAddress]] //address[][] validatorsAddresses
57
}];
58
59
60
61
var organizationDeployData = {
62
uri: "",
63
mandatoryComponentsDeployData,
64
additionalComponents: [1, 2, 3], //in this example the Treasury, State and Treasury Splitter are linked as additional Components
65
additionalComponentsDeployData,
66
specialComponentsData: '0x'
67
specificOrganizationData: abi.encode(["bool", "address", `tuple(${subDAOProposalModelTypes.join(',')})[]`, "bytes"], [false, utilities.voidEthereumAddress, subDAOProposalModels.map(it => Object.values(it)), "0x"])
68
}
69
70
data = abi.encode(["tuple(string,bytes,bytes[],uint256[],bytes[],bytes)"], [Object.values(organizationDeployData)]);
71
organizationFactory.methods.deploy(data).send({from : myAddress})
Copied!
Use this example pattern to create your own deployData.
Copy link