Model Governance Rules

Contract Name

GitHub

Deployed Contract Address

Contract Implemented

Initialization data

SubDAOProposalManager

coming soon

coming soon

ProposalManager

ProposalManager init data.

SubDAO Proposals are different than Root ones. A subDAO Proposal is always created from Proposal Model. Root Proposals, on the other hand, can be freely written, without any template basis.

SubDAO Proposal Manager

A SubDAO implements a Proposal Manager equal to that of a Root. Of course, the Root will have its own Proposal Manager and a SubDAO will have its own.

The only difference is in the _hostIProposalCommand passed as true. As explained here, this parameter represents if the host of the Proposal Manager (the subDAO contract in this case) should have overriding methods to have custom logic. In the case of a subDAO, in fact, the Proposal Manager has to manager Surveyless and Survey Proposals different from Root Proposals. This logic is already present in the subDAO contract code.

SubDAO Proposal Manager Initialization

As explained in the Root Proposal Manager page, the ProposalManager contract is a lazyInitCapableElement. This means it is a Factory-Capable Component, and must be initialized as follows:

function _lazyInit(bytes memory lazyInitData) internal override returns(bytes memory) {
    (_hostIsProposalCommand, lazyInitData) = abi.decode(lazyInitData, (bool, bytes));
    if(lazyInitData.length > 0) {
        ProposalsManagerLibrary.setConfiguration(_configuration, abi.decode(lazyInitData, (ProposalConfiguration)));
    }
    return "";
}

struct ProposalConfiguration {
    address[] collections;
    uint256[] objectIds;
    uint256[] weights;
    address creationRules;
    address triggeringRules;
    address[] canTerminateAddresses;
    address[] validatorsAddresses;
}
  • _hostIsProposalCommand -> It must be passed as true. it defines if the Proposal Manager is hosted (host parameter at LazyInitCapableElement) by a smart contract overriding some Proposal Manager functions (true) or not (false). In the case of a subDAO, the subDAO itself is the Proposal Manager host address. This configuration allows the subDAO having the custom Proposals logic for Surveyless and Survey Proposals.

  • collections address[] -> these are the ERC1155 / Item Collection addresses supported to vote on a proposal. For ERC20 tokens, this parameter should be passed as empty.

  • objectIds uint256[] -> these represent, for each collection, the object id of the supported ERC1155 / Item tokens. For an ERC20, the address must be converted in uint parameter and passed in this object id parameter, while the related collection address must be passed as empty. collections and objectIds define the supported tokens of a subDAO.

  • weights uint256[] -> this array contains, for each objectid, its weight when voting for a Proposal. The weighted vote is equal to number of votes * weight, where weight is specific to the token used.

  • creationRules -> this is the creationRules contract address.

  • triggeringRules -> this is the triggeringRules contract address.

  • canTerminateAddresses address[] -> this array contains the canTerminate contract addresses.

  • validators[] -> this array contains all validators contract addresses.

As you can see, the canTerminateAddresses, validatorsAddresses , creationRules and triggeringRules are set to the Proposal Manager level even if each SubDAOProposalModel already has those parameters. But why?

If a model--whether a Surveyless or Survey Proposal--is created without passing canTerminateAddresses, validatorsAddresses, creationRules or triggeringRules in the SubDAOProposalModel struct, the subDAO will automatically take as default, for each of these parameters, those passed in the Proposal Manager as ProposalConfiguration known as the "local configuration". Consequently, they are default Proposal Manager governance rules that are only used if a SubDAOProposalModel does not have specific ones.

So if a Model has not canTerminateAddresses, validatorsAddresses, creationRules or triggeringRules , it means that a Vertical Permission Layer for the Model is not specified. In this case it's used the one defined at Proposal Manager level, i.e. local configuration.

Create a SubDAO Proposal

As explained here, a Proposal can be created using the batchCreate function of the Proposal Manager.

function batchCreate(ProposalCodes[] calldata codeSequences) external returns(bytes32[] memory createdProposalIds);

The ProposalCodes[] input parameter is composed as follows:

  • ProposalCode[] codes -> containing the ProposalCode struct, look below.

  • bool alstoTerminate -> it indicates whether the Proposal should be created and terminated in the same transaction (true) or not (false).

    alsoTerminate as true can be used only if the Proposal Manager has set canTerminateAddresses and validatorsAddresses host only or if canTerminateAddresses is not present (and therefore the proposal can always terminate) and validatorsAddresses is not present (the proposal is always valid). In all other cases alsoTerminate has to be passed as false.

For a subDAO Proposal, the ProposalCode struct must be passed as follows:

  • address location -> must contain the modelIdex, i.e. the index of the Proposal Model to use.

  • bytes bytecode -> if you're creating a Surveyless Proposal, it must contain the presetIndex, i.e. the index of the presetValue of the Proposal Model. If is a Survey Proposal, it must contain the init data of the Proposal.

These data are validated by the createProposalCodeSequence function of the subDAO contract which takes the governance rules and the Proposal code from the chosen Proposal Model.

Take, for example, the Surveyless Proposal Model to change the inflation rate percentage of the Root's governance token, with the presetsValues 2%, 6% and 10%. Let's say you want to create a Proposal to vote for 6% inflation. In this case, the location must contains the index of the Proposal Model and the bytecode must contain the index that identifies the 6% position in the array of presetsValues.

Take, for example, the Survey Proposal Model to change the inflation rate percentage of the Root's governance token. In this case, there are no presets values. Let's say you want to create a Proposal to vote for 0.5% inflation. In this case, the location must contains the index of the Proposal Model and the bytecode must contain the init data to define 0.5% according to the Proposal code.

The following is the only data that a user can decide when creating a Proposal for a subDAO:

  • Which of the preset models to use, and therefore which Proposal to propose.

  • Which presetValue to use to create the Proposal in the case of a Surveyless.

  • Which data to use to create the Proposal in the case of a Survey.

The user cannot write the code of the Proposal, unlike in a Root.

Technical note:

The _createCodeSequence function of the subDAO Proposal Manager uses the bytecode parameter to initialize a Proposal, unlike the standard Proposal Manager of the Root Layer. In fact, the standard Proposal Manager uses the bytecode passed to deploy the Proposal Smart contract corresponding to the bytecode.

Voting, voting management (i.e withdrawing votes), Proposal termination and Proposal code execution all follow the same functioning (explained here) as the Root Proposal Manager.

Last updated