Proposal Samples

In this section, you can find useful Proposals to use in your Organization.

This section is constantly updated.

Root Proposals

contract SetComponentProposal {

    string public uri;
    IOrganization.Component public component;
    
    function lazyInit(bytes memory lazyInitData) external returns(bytes memory lazyInitResponseData) {
        require(keccak256(bytes(uri)) == keccak256(""));
        (uri, lazyInitResponseData) = abi.decode(lazyInitData, (string, bytes));
        require(keccak256(bytes(uri)) != keccak256(""));

        (component) = abi.decode(lazyInitResponseData, (IOrganization.Component));

        lazyInitResponseData = "";
}

    function execute(bytes32) external {
        IOrganization(ILazyInitCapableElement(msg.sender).host()).set(component);
    }
}

This Proposal can be used to link / un-link / replace a Component (at both the Root Layer and the Governance Layer).

The lazyInit function initializes the Proposal uri and the Component struct. As explained here, the Component struct is composed as follows:

  • address location -> this represents the address of the Component smart contract.

  • bytes32 key -> this represents the user-defined bytes32 key that represents the Component inside*** the Organization.

  • bool isActive -> represents if the Component must have an active key or not.

*** To link a new Component, the key parameter must be a new one that does not correspond to any other Component already present in the Organization, and the location must be passed as the contract address of the new Component.

To un-link a Component the key parameter must be the one corresponding to the Component that you want to unlink and the location address must be passed as address(0).

To replace a Component the key parameter must be the one corresponding to the Component that you want to replace and the location must be passed as the smart contract address of the new Component.

contract AttachSubDAOProposal {
    using ExternalGetters for IOrganization;

    string public uri;
    ISubDAOsManager.SubDAOEntry public entry;

    function lazyInit(bytes memory lazyInitData) external returns(bytes memory lazyInitResponseData) {
        require(keccak256(bytes(uri)) == keccak256(""));
        (uri, lazyInitResponseData) = abi.decode(lazyInitData, (string, bytes));
        require(keccak256(bytes(uri)) != keccak256(""));

        (entry) = abi.decode(lazyInitResponseData, (ISubDAOsManager.SubDAOEntry));

        lazyInitResponseData = "";
    }

    function execute(bytes32) external {
        IOrganization(ILazyInitCapableElement(msg.sender).host()).subDAOsManager().set(entry.key, entry.location, entry.newHost);
    }
}

This Proposal can be used to link / un-link / replace a subDAO from the subDAO Manager.

The lazyInit function initializes the Proposal uri and the SubDAOEntry struct. As explained here, the SubDAOEntry struct is composed as follows:

  • address location -> represents the address of the Component smart contract

  • bytes32 key -> represents the user-defined bytes32 key that represents the subDAO inside the subDAOManager.

  • address newHost -> Parameter used only when replacing a subDAO. It represents the new host address of the replaced subDAO.

To link a new subDAO the key parameter must be a new one that does not correspond to any other subDAO already registered in the subDAO Manager and the location must be passed as the smart contract address of the new subDAO.

To unlink a subDAO the key parameter must be the one corresponding to the subDAO that you want to unlink and the location address must be passed as address(0).

To replace a subDAO the key parameter must be the one corresponding to the subDAO that you want to replace and the location must be passed as the smart contract address of the new subDAO and newHost must be passed as the new host address of the replaced subDAO.

contract DelegationsManagerAttacherProposal {
    using AddressUtilities for address;

    string public uri;
    address public delegationsManagerAddress;
    address public involvedDelegation;
    bool public attach;

    function lazyInit(bytes memory lazyInitData) external returns(bytes memory lazyInitResponseData) {
        require(keccak256(bytes(uri)) == keccak256(""));
        (uri, lazyInitResponseData) = abi.decode(lazyInitData, (string, bytes));
        require(keccak256(bytes(uri)) != keccak256(""));

        (delegationsManagerAddress, involvedDelegation, attach) = abi.decode(lazyInitResponseData, (address, address, bool));
        require(delegationsManagerAddress != address(0), "zero");
        require(involvedDelegation != address(0), "zero");

        lazyInitResponseData = "";
    }

    function execute(bytes32) external {
        IDelegationsManager delegationsManager = IDelegationsManager(delegationsManagerAddress);
        if(attach) {
            delegationsManager.set(involvedDelegation.asSingletonArray());
        } else {
            delegationsManager.remove(involvedDelegation.asSingletonArray());
        }
    }
}

This Proposal can be used by the Organization to link / un-link a Delegation from its Delegations Manager.

While the Proposal with which a Delegation can link / un-link itself from the Delegations Manager can be found here.

The contract lazyInit initializes the Proposal uri and also:

  • delegationsManagerAddress -> represents the address of the Delegations Manager linked to the Organization.

  • involvedDelegation -> represents the address of the Delegation to link / un-link.

  • attach -> represents if the Delegation must be linked to the Delegations Manager (true) or un-linked (false).

Transfer Funds From the Treasury Manager

contract TransferManagerProposal {
    string public uri;
    address public treasuryManagerAddress;
    ITreasuryManager.TransferEntry[] public entries;

    function lazyInit(bytes memory lazyInitData) external returns(bytes memory lazyInitResponseData) {
        require(keccak256(bytes(uri)) == keccak256(""));
        (uri, lazyInitResponseData) = abi.decode(lazyInitData, (string, bytes));
        require(keccak256(bytes(uri)) != keccak256(""));

        ITreasuryManager.TransferEntry[] memory _entries;
        (treasuryManagerAddress, _entries) = abi.decode(lazyInitResponseData, (address, ITreasuryManager.TransferEntry[]));
        for(uint256 i = 0; i < _entries.length; i++) {
            entries.push(_entries[i]);
        }

        lazyInitResponseData = "";
    }

    function execute(bytes32) external {
        ITreasuryManager(treasuryManagerAddress).batchTransfer(entries);
    }
}

This Proposal can be used to transfer funds from the Treasury Manager of an Organization.

As explained here, the Treasury Manager supports ETH, ERC20, ERC721, ERC1155, and Items (both their Interoperable Interfaces and the Main Interface). Moreover, the Treasury Manager can be extended to support even more standards (see here to learn more).

The lazyInit function initializes: the Proposal uri; the Treasury contract address to interact with; and the TransferEntry struct.

Here is described how the TransferEntry struct is composed, and how to pass it to perform a transfer operation with one standard rather than another.

Change Organization uri

contract ChangeOrganizationUriProposal {

    string public constant LABEL = 'changeOrganizationUri';

    string public uri;

    string public value;

    function lazyInit(bytes memory lazyInitData) external returns(bytes memory lazyInitResponseData) {
        require(keccak256(bytes(uri)) == keccak256(""));
        (uri, lazyInitResponseData) = abi.decode(lazyInitData, (string, bytes));
        require(keccak256(bytes(uri)) != keccak256(""));

        (value) = abi.decode(lazyInitResponseData, (string));

        lazyInitResponseData = "";
    }

    function execute(bytes32) external {
        IOrganization(ILazyInitCapableElement(msg.sender).host()).setUri(value);
    }
}

This Proposal can be used to change the Organization uri. Implementing the DynamicMetadataCapableElement, the Organization has a general uri.

The lazyInit initializes:

  • string uri -> Proposal uri

  • string value -> new Organization uri.

When the Proposal execute function is called, the setUri function of the Organization is called changing the Organization uri.

Change a value saved in the State Manager

contract SetUint256Proposal {
    using Getters for IOrganization;
    using State for IStateManager;

    string public constant LABEL = 'setUint256';

    string public uri;
    string public name;
    uint256 public value;

    function lazyInit(bytes memory lazyInitData) external returns(bytes memory lazyInitResponseData) {
        require(keccak256(bytes(uri)) == keccak256(""));
        (uri, lazyInitResponseData) = abi.decode(lazyInitData, (string, bytes));
        require(keccak256(bytes(uri)) != keccak256(""));

        (name, value) = abi.decode(lazyInitResponseData, (string, uint256));

        lazyInitResponseData = "";
    }

    function execute(bytes32) external {
        IOrganization(ILazyInitCapableElement(msg.sender).host()).stateManager().setUint256(name, value);
    }
}

This Proposal can be used to change a uint256 value saved in the State Manager such as a fee. For example, the Organization has a Factory with a fee-based business model deployed through the Factory-Of-Factories. The Factory fee, both a creation fee and a usage fee is saved in the State Manager. In this way, the fee can be voted and changed by a subDAO.

The subDAO model to be used for this purpose can contain a preset or an ordinary Proposal. In the first case, through the Proposal, it's possible to change the value choosing from one of the preset values. In the second case, the user can propose a new value to be voted.

The lazyInit function of the SetUint256 Proposal initialize the Proposal uri containing Proposal Metadata and also:

  • string name -> represents the name of the variable to save.

  • uint256 value -> represents the value of the variable to save.

To replace an existing variable value the name must be the name of the variable to replace.

Change the Investments Manager tokens to buy with ETH

contract ChangeInvestmentsManagerFourTokensFromETHList {
    using ExtGetters for IOrganization;

    string public uri;
    address[] public tokens;
    string public additionalUri;

    function lazyInit(bytes memory lazyInitData) external returns(bytes memory lazyInitResponseData) {
        require(keccak256(bytes(uri)) == keccak256(""));
        (uri, lazyInitResponseData) = abi.decode(lazyInitData, (string, bytes));
        require(keccak256(bytes(uri)) != keccak256(""));

        address[] memory _tokens;
        (additionalUri, _tokens) = abi.decode(lazyInitResponseData, (string, address[]));

        require(_tokens.length == 4, "length");
        for(uint256 i = 0; i < _tokens.length; i++) {
            require(_tokens[i] != address(0), "zero");
        }

        tokens = _tokens;

        lazyInitResponseData = "";
    }

    function execute(bytes32) external {
        IOrganization(ILazyInitCapableElement(msg.sender).host()).investmentsManager().setTokensFromETH(tokens);
    }
}

This Proposal can be used to change the tokens that the Investments Manager must buy using ETH.

This Proposal is used by the Ethereans OS subDAO. The Ethereans OS Investments Manager buys five tokens and one of these is $OS that cannot be changed. For this reason, the Proposal can change only four tokens. You can modify this Proposal according to your Investments Manager's needs.

The lazyInit function of the ChangeInvestmentsManagerFourTokensFromETHList Proposal initialize the Proposal uri containing Proposal Metadata and also:

  • string additionalUri -> this can contain Proposal description, risks, benefits, and other information to describe the proposal behavior.

  • address[] _tokens -> represents the addresses of the tokens to buy from ETH. (As said above, this Proposal is customized so that you can only choose four tokens).

SubDAO Proposals

Change the Investments Manager tokens and percentages to sell in return for ETH

contract ChangeInvestmentsManagerFiveTokensToETHList {
    using ExtGetters for IOrganization;

    uint256 public constant MAX_PERCENTAGE_PER_TOKEN = 50000000000000000;

    string public uri;
    address[] public tokens;
    uint256[] public percentages;
    string public additionalUri;


    function lazyInit(bytes memory lazyInitData) external returns(bytes memory lazyInitResponseData) {
        require(keccak256(bytes(uri)) == keccak256(""));
        (uri, lazyInitResponseData) = abi.decode(lazyInitData, (string, bytes));
        require(keccak256(bytes(uri)) != keccak256(""));

        address[] memory _tokens;
        uint256[] memory _percentages;
        (additionalUri,_tokens, _percentages) = abi.decode(lazyInitResponseData, (uri, address[], uint256[]));

        require(_tokens.length == 5 && _tokens.length == _percentages.length, "length");

        for(uint256 i = 0; i < _tokens.length - 1; i++) {
            require(_tokens[i] != address(0), "zero");
            require(_percentages[i] > 0 && _percentages[i] <= MAX_PERCENTAGE_PER_TOKEN, "oob");
        }

        tokens = _tokens;
        percentages = _percentages;

        lazyInitResponseData = "";
    }

    function execute(bytes32) external {
        IOrganization(ILazyInitCapableElement(msg.sender).host()).investmentsManager().setTokensToETH(tokens, percentages);
    }
}

This Proposal can be used to change the tokens and the percentages for each token that the Investments Manager must sell to ETH.

This Proposal is used by the Ethereans OS subDAO. The Ethereans OS Investments Manager sells five tokens and of each token can be sold a maximum of 5% of the token amount present in the Investments Manager.

You can modify this Proposal according to your Investments Manager's needs selling more than five tokens and more than 5% of each token.

The lazyInit function of the ChangeInvestmentsManagerFourTokensFromETHList Proposal initialize the Proposal uri containing Proposal Metadata and also:

  • string additionalUri -> this can contain Proposal description, risks, benefits, and other information to describe the proposal behavior.

  • address[] _tokens -> represents the addresses of the tokens to sell to ETH. (As said above, this Proposal is customized so that you can choose five tokens).

  • uint256[] _percentages -> represents the percentages values to sell of each token. (As said above, this Proposal is customized so that you can sell a maximum of 5% of each token).

Last updated