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:

function deploy(bytes calldata deployData) external payable override(Factory, IFactory) virtual returns(address productAddress, bytes memory productInitResponse) {

deployData is the encoded value of the OrganizationDeployData struct, which is composed as follows:

struct OrganizationDeployData {
    string uri;
    bytes[] mandatoryComponentsDeployData;
    uint256[] additionalComponents;
    bytes[] additionalComponentsDeployData;
    bytes[] specialComponentsData;
    bytes specificOrganizationData;
}
  • 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:

(bytes32 key, address modelOrLocation, bool active, bytes memory deployData) = abi.decode(specialComponentData, (bytes32, address, bool, bytes));

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:

var values = ["proposalsManager", "treasuryManager", "stateManager", "treasurySplitterManager", "subDAOsManager", "delegationsManager"];

The deployData to pass is composed as follows:

// Proposal Manager init data
mandatoryComponentsDeployData[0] = abi.encode(['tuple(address[],uint256[],uint256[],address,address,address[],address[])'], [
    [
        [], //address[] collections           
        [], //uint256[] objectIds
        [], //uint256[] weights
        utilities.voidEthereumAddress, //address creationRules
        utilities.voidEthereumAddress, //triggeringRules
        [], //address[] canTerminateAddresses
        [] //address[] validatorsAddresses
    ]
]);

//in this example the Treasury, State Manager and TreasurySplitter Managers are linked as additional Components
var additionalComponentsDeployData = [
    //Treasury Manager init data
    "0x",
    //State Manager init data
    abi.encode(['tuple(string,bytes32,bytes)'], [
        [
            "test",
            utilities.voidBytes32,
            "0x"
        ]
    ]),
    //TreasurySplitter init data
    web3.eth.abi.encodeParameters(["uint256", "uint256", "bytes32[]", "uint256[]", "bytes32", "uint256", "uint256"], [0, 0, [],
        [], utilities.voidBytes32, 2, 3
    ])
];

//Proposal Model init data 
var subDAOProposalModelTypes = [
    "address", 
    "string",
    "bool",
    "bytes[]",
    "bytes32[]",
    "address",
    "address",
    "uint256",
    "address[][]",
    "address[][]"
];

var subDAOProposalModels = [{
    source : utilities.voidEthereumAddress, //address source
    uri : "str", //string uri
    perpetual : false, //bool isPreset
    bytes : [], //bytes[] presetValues
    bytes32 : [], //bytes32[] presetProposals
    a : utilities.voidEthereumAddress, //address creationRules
    b : utilities.voidEthereumAddress, //address triggeringRules
    c : 0, //uint256 votingRulesIndex
    d : [[utilities.voidEthereumAddress]], //address[][] canTerminateAddresses
    e : [[utilities.voidEthereumAddress]] //address[][] validatorsAddresses
}];            
                       
                                  
                                                        
var organizationDeployData = {
    uri: "",
    mandatoryComponentsDeployData,
    additionalComponents: [1, 2, 3], //in this example the Treasury, State and Treasury Splitter are linked as additional Components
    additionalComponentsDeployData,
    specialComponentsData: '0x'
    specificOrganizationData: abi.encode(["bool", "address", `tuple(${subDAOProposalModelTypes.join(',')})[]`, "bytes"], [false, utilities.voidEthereumAddress, subDAOProposalModels.map(it => Object.values(it)), "0x"])
}

data = abi.encode(["tuple(string,bytes,bytes[],uint256[],bytes[],bytes)"], [Object.values(organizationDeployData)]);
organizationFactory.methods.deploy(data).send({from : myAddress})

Use this example pattern to create your own deployData.

Last updated