How to write and test a KaliDAO extension

Ivelin Ivanov
Sporos DAO
Published in
7 min readJun 21, 2022

KaliDAO is the pioneer of legal DAO formation on-chain within less than 5 minutes and under $10 in fees on ETH L2.

Not only has the team spent a tremendous amount of time researching legal DAO wrappers and governance strategies, but they also have the legal and smart contract experience to back it up.

At SporosDAO we focus on streamlined legal DAO formation of For-Profit DevCos. Our community and users are bootstrapping development teams who aim to build sustainable web3 projects.

One of the key requirements for a legal and frictionless legal DAO entity is to minimize but not avoid the administrative burdens related to legal, tax and securities compliance. Gone are the days of cowboy style alegal DAO entities. For the foreseeable future, partnering with regulators is the practical way to bring serious liquidity into web3.

Two of the many optimizations we have spent a lot of time researching and implementing are:

  • Delay as much as practically and lawfully possible, triggering complex SEC securities registration rules and
  • Reduce personal income tax events.

To that extent, we decided to work with non-transferrable DAO governance ERC20 tokens with legally attached governance and warrants rights. This aims to reduce to some degree securities risks but at the same time introduces a challenge of minting sweat equity tokens to contributors as the team grows.

Most tools today rely on transferable tokens that are managed via multisigs, which are in turn managed by individuals as signatories.

It is not yet a well appreciated fact, that any time tokens go through an account that is personally owned (an individual has domain over it), that likely triggers a personal income tax event.

There are good reasons why in traditional finance, companies authorize employees and agents to make payments on behalf of the company from business bank accounts. It is messy to intermingle personal and company bank accounts. Not only it creates internal accounting complications but it also makes it hard to justify with the tax authorities which transactions are business related and which are personal.

Part of the technical and compliant solution we came up with was to build a ProjectManagement smart contract that allows contributors to propose scoped projects with a budget and a deadline. DAOs vote on projects like all other proposals. If a project is approved, the project manager has the discretion to organize tasks and contributors. When contributors deliver on their tasks, the project manager can directly authorize mint of DAO tokens (within the project budget) without going through a DAO proposal each time.

SporosDAO Project Management Flow

For a more detailed technical design document on the project management flow, take a look at our wiki.

Fortunately KaliDAO is not only a legal platform but also a brilliantly designed minimalistic technical platform as well. It provides battle tested APIs in Moloch v3 style plus extensibility.

If you deployed your KaliDAO, you can instantly begin working with legal protection, but you are not boxed in a rigid structure. You can change the legal documents of your DAO as the business evolves and you can also add new smart contract capabilities via extensions.

Extension API

There are a few minimal requirements for an extension to plug-into your KaliDAO. Your extension smart contract needs to implement one method: setExtension(). As a best practice (but optionally) it can implement callExtension() and also emit ExtensionSet and ExtensionCalled events.

setExtension() is called via DAO proposal. It is possible to have multiple proposals that call setExtension() in order to modify the parameters of a previous proposal. In our case we use this capability to allow project managers to request project deadline or budget extensions via proposals.

callExtension() is usually called directly by the end user. In our case that is the project manager. They use this method to request DAO mint of sweat token bounties to contributors for project deliverables. Notice that in the process tokens do not go through the project manager’s wallet. They are directly minted by the DAO smart contract to the contributor address.

There is a IKaliDAOextension.sol interface that you can import in your extension smart contract if the AGPL-3 license is not a concern.

One of the many benefits of having a solid DAO platform to build on top is that it allows for a continuous on-chain history of governance and business transactions that can plug into data analytics front ends. Traditionally corporate data is messy, siloed and heavily censored. It might be more productive to apply data science and learn from public blockchain data. Maybe we collectively learn and improve the 95–95% mortality rate for startups. Time will tell.

There is a great Kali subgraph project that provides indexed GraphQL data on TheGraph network for any KaliDAO contracts across ETH L1 and L2 chains. It is relatively straightforward to add your extension calls and events to the index. Just let the Kali team know that your extension is deployed.

A few more details about the KaliDAO extension interface.

Within setExtension() msg.sender is the address of the DAO, not an end user wallet address. This is because setExtension() is called from within the DAO processProposal() method when a DAO member interacts with a front end to process and approved proposal. The extentionData parameter in setExtension() is anything you can abi.encode() and then abi.decode(). In our case it’s a tuple of a project proposal:

function setExtension(bytes calldata extensionData) external payable {(  uint256 id,  address manager,  uint256 budget,  uint256 deadline,  string  memory goals) = abi.decode(  extensionData,  (uint256, address, uint256, uint256, string));...emit ExtensionSet(msg.sender, projectUpdate);}

Technically callExtension() can be freeform, because it is normally called from a user front end app. I appreciate Kali’s effort to standardize callExtension() because it makes it easier for third party front ends to interact with Kali smart contract extensions.

Testing

We use hardhat for our dev environment. It works nicely on a local machine and gitpod alike.

In order to test interactions between KaliDAO.sol and your extension, add Kali’s github repository to package.json.

"kalidao": "https://github.com/kalidao/kali-contracts.git"

You will also need to install as a dev dependency hardhat-dependency-compiler`

yarn add hardhat-dependency-compiler --save-dev

Import it in your hardhat.config.ts

import "hardhat-dependency-compiler";

And use it to help hardhat compile local Kali contracts within your test environment.

const config: HardhatUserConfig = {...
dependencyCompiler: {
// path to write temp compiled deps relative to contracts ./src path: "tmp", // paths relative to './src/hardhat-dependency-compiler/ paths: ["kalidao/contracts/KaliDAO.sol"],},...

namedAccounts is another convenient hardhat test extension that I learned about from the Kali testsuite.

namedAccounts: {  deployer: {    default: 0,  },  alice: {    default: 1,  },  bob: {    default: 2,  },  carol: {    default: 3,  },},

Feel free to look and borrow from our testsuite , project config and ci scripts. You are few steps away from a functional KaliDAO extension with 100% test coverage.

If you have any question or doubts, hop into our discord dev channel.

Deployment

You can deploy the new smart contract via an externally owned address (EOA) or via DAO proposal. The former is a little simpler, but it means that the person who owns the EOA may be directly responsible for any liabilities related to the contract. Keep this in mind in light of recent lawsuits against developers of smart contracts.

Deploying via DAO ProposalType.CALL takes an extra step to generate the deployment ABI, but the deployed contract is under the legal umbrella of the DAO.

Here is a test case that shows step by step how to generate the payload for deploying a smart contract via DAO proposal.

Activation

When your extension smart contract is deployed and ready for use, your DAO members can vote it in via an extension proposal. Here is a line of client side code from the testsuite that you can use in your front end to activate an extension:

await kali.propose(9, "New Project Proposal", [projectManagement.address], [1], [payload])

The first parameter is the type of KaliDAO proposal. 9 matches type EXTENSION in KaliDAO.sol ‘s ProposalType enum:

The second parameter is the description of the proposal, which will become part of the on-chain records and can be used in a future as a reference for company books and records.

The third parameter is an array of addresses of smart contracts that are proposed as extensions. In the example above, we are only interested in activating a deployed instance of the ProjectManagement contract.

The fourth parameter is an array of flags corresponding to each of the contracts from the third parameter. If the value of a flag in the array is greater than 0, it signifies whether to toggle between whitelist and unlist the extension in the DAO contract. If the value of the flag is 0, it has no effect on whitelisting. In the current version of KaliDAO.sol, a whitelisted extension has the following powers:

The final fifth parameter of the proposal is an array of payloads to be passed to the setExtension() method of a the corresponding extension contract from the third parameter when the DAO approves the proposal and processes it.

Once you battle test your extension and you think it can serve the bigger KaliDAO ecosystem, you can join the Kali discord and chat with the Kali team to add your extension as an option in their front end , so that users have an option to activate it alongside other default extensions when a new DAO is deployed.

Happy legal engineering!

--

--

Ivelin Ivanov
Sporos DAO

Open Source Software contributor and technology entrepreneur