Community reserve

A decentralized autonomous organization (DAO) may wish to source funds from its members to save for use at a later date. A treasury therefore serves as a form of 'community wallet', where members can contribute funds, knowing that they may only be released at the behest of the community.

Treasuries are not, by default, limited to the reserve of a single token and are indeed able to hold any supported Cardano tokens.

A treasury, as a community's reserves, will naturally need to interact with governance proposals. Indeed, the primary mechanism by which funds are able to be released by the treasury, will be the passing of an appropriate proposal.

Multisigs vs Script-locking

In DAOs which are implemented as strictly a multisig which is then managed by a set of members, the treasury is just the contents of that multisig wallet. Funds can be sent to and from that wallet and votes can mean spending from the wallet is agreed upon, and then executed by the various multisig’s key holders.

In a more advanced governance system where the voting is performed on-chain, we need something a little different. The treasury cannot be a simple multisig, because then, if the key holders disagree with the proposal’s consensus, they are able to veto it. Additionally, they may all unanimously agree on something which hasn’t been agreed by a proposal at all. In order to resolve this, we need to use the DAO’s key authorization mechanism in order to control this treasury.

Treasury Script

Let’s store all of the DAO’s funds at a script. This script cannot be spent by anyone, but anyone can send funds to it. Using Effects, we can encode the action of withdrawing UTXOs at this script: Our effect validator checks simply that a GAT is burned, and that it correctly spends exactly the amount specified, returns the change, and sends it to one or more addresses. From the perspective of the effect, that’s all it needs to do.

Now, however, we must also encode in the treasury script that the treasury can allow this to happen. We do this using “yielding validation” to the authority token. How to perform this is specified in Authority Tokens (and by extension Reusable Authority Tokens). But essentially, this allows the treasury to “give up” all of it’s validation logic when presented with proof that an authority token is correctly being used in the transaction, which should only happen as a result of a proposal passing.

Hopefully it’s clear now that essentially all the treasury must be is the simplest possible script which yields validation to authority tokens:

$$ \text{treasuryValidator}_{gatCS}\ \_redeemer\ \datum\ ctx =\\ \forall s \in \text{findGATScriptHashes}{gatCS}(\text{ctx.txInfo}) ,\ \text{scriptUsed}(s) $$

Of course, additional logic may be built on top for whatever reason. But this is the core logic for how to encode a treasury as part of Agora.