A tool to manage the Treasury of a DAO through Discord. The Treasury is managed using Enzyme Finance's vaults. The infrastructure is fully serverless and based on AWS Lambda.
This tool's capabilities are the following:
- Attribute a specific Discord role to users who have invested in the DAO's fund. This verification is done using Ethereum Authentication through Discord which I've built for a previous hackathon, but here with the added twist that the users only get authenticated if their address owns shares from the Enzyme vault in which the DAO's Treasury is stored.
- Once a user is assigned the investor role, they become able to call slash commands which give them information about the current state of the Treasury, such as the shares balances of all the other authenticated users.
- Upon authentication, if the address corresponds to that of the owner of the vault (the Treasury manager), the user also gets assigned the manager role on Discord, which enables them to call slash commands to start polls to decide what the DAO's Treasury funds should be allocated to. Only the authenticated investors can vote on these polls and the more shares an investor owns, the more weight their vote has.
- Upon poll expiration, case the result of the poll was to go through with a certain trade, the execution of the trade through the Enzyme vault is triggered.
If you find this repository useful, any ETH, NFT, or other tokens are greatly appreciated.
ETH Address: 0xa8624937a437F53382d4B48f1AE13E0CF5C9F8cB
- An Enzyme Finance vault
- A Discord account and a server where you're an administrator
- AWS Account with console and programmatic access
- A domain name registered with AWS
- Local AWS credentials profile
- Node version 14
- SAM CLI
- Create a vault on Enzyme (on Kovan Network).
- Create a Discord server if you don't have one already. Create the roles you want to give the users after they've authenticated with Ethereum. I named my roles manager and investor. manager will be assigned to the address of the owner of the vault and investor will be assigned to any address that owns shares from the vault.
- Set up an application for your bot
- Select the following boxes in the OAuth2 tab. Open the link marked in red and choose your server to add the bot.
- Create an access key pair for your AWS user as explained here (this user must have administrator access).
- Create file
.aws/credentials
with the same structure as.aws/credentials.example
(including the "[scaffold-eth]" part), and fill in the parametersaws_access_key_id
andaws_secret_access_key
with the values you obtained from the previous step.
- Create a certificate in Certificate Manager for the API endpoint you'll later deploy to be linked to. For instance, mine is at dev.api.vorder.io. Don't forget to add the DNS record to your domain as mentioned in the verification prompt that shows up once you create the certificate. You won't be able to deploy the Ethereum Authentication Infrastructure correctly without the certificate Status showing up as Issued, so wait for it to complete before doing that part.
All the secrets necessary for the bot to run are retrieved from an AWS Secrets Manager secret named /dev/discord_dao_treasury_bot/discord
you have to create that secret manually before deploying the stack. When creating the secret choose the option Other type of secrets.
The secret must contain the following key/value pairs:
app_id
, from the application you've created in the Discord Setup.public_key
, from the application you've created in the Discord Setup.bot_token
, from the application you've created in the Discord Setup.server_id
- Right-click your server on Discord and select Copy ID to get this.channel_id
. Right-click your channel on Discord and select Copy ID to get this.owner_role_id
. Right-click the manager role you've created in the Discord setup and select Copy ID to get this. You can see your server's roles by right-clicking your server > Server Settings > Roles.investor_role_id
. Same as forowner_role_id
but now for the investor role.jwt_secret
. This is the secret which will be used to encode/decode the authentication JWTs. Anything works here, but choose something strong enough.vault_address
. The address of the Enzyme vault you've created above.ethereum_node_endpoint
. The URL for an Alchemy/Infura node endpoint.vault_owner_eth_private_key
. The private key of the address that owns the Enzyme vault.
We'll now go through the deployment of the infrastructure responsible for interacting with Discord. This includes creating the slash-command and handling the role assignment when a user is successfuly authenticated.
-
cd
into packages/discord-interaction/src/commands_layer/nodejs and install the layer dependencies usingnpm install
. -
cd
back into packages/discord-interaction/ and dosam build
. Once the build is complete dosam deploy --guided
and choose the following parameters:Stack Name [dev-discord-interaction]: dev-discord-interaction
AWS Region [us-east-2]: us-east-2
#Shows you resources changes to be deployed and require a 'Y' to initiate deploy
Confirm changes before deploy [y/N]: n
#SAM needs permission to be able to create roles to connect to the resources in your template
Allow SAM CLI IAM role creation [Y/n]: y
DiscordHandlerFunction may not have authorization defined, Is this okay? [y/N]: y
Save arguments to configuration file [Y/n]: y
SAM configuration file [samconfig.toml]: samconfig.toml
SAM configuration environment [default]: default
-
Once the deployment is complete copy the API Gateway endpoint URL stack output and paste it in the Discord Developer Portal as Interactions Endpoint URL. If Discord was able to successfuly ping our Lambda you'll get a message saying "All your edits have been carefully recorded" at the top of the screen.
-
Check that you now have a stack called dev-discord-interaction in Cloudformation. Cross your fingers 🤞 and call the command
/eth-auth
in your Discord channel. If everything went right with the deploy, the bot should respond with a URL.
This deployment is quite similar to the one for the Discord Interaction Infrastructure:
-
cd
into packages/enzyme-interaction/src/dependencies_layer/nodejs and install the layer dependencies usingnpm install
. -
cd
back into packages/enzyme-interaction/ and dosam build
. Once the build is complete dosam deploy --guided
and choose the following parameters:Stack Name [dev-enzyme-interaction]: dev-enzyme-interaction
AWS Region [us-east-2]: us-east-2
#Shows you resources changes to be deployed and require a 'Y' to initiate deploy
Confirm changes before deploy [y/N]: n
#SAM needs permission to be able to create roles to connect to the resources in your template
Allow SAM CLI IAM role creation [Y/n]: y
DiscordHandlerFunction may not have authorization defined, Is this okay? [y/N]: y
Save arguments to configuration file [Y/n]: y
SAM configuration file [samconfig.toml]: samconfig.toml
SAM configuration environment [default]: default
Now let's deploy the API that will talk to the front-end and handle the Ethereum authentication flow.
- In the root folder run
yarn install
. You'll get quite a lot of warnings regarding workspace dependencies, but those are harmless. Note: All the packages for this infrastructure (and also for the front-end and the chain) are installed throughyarn
workspaces. The api package dependencies will later be installed usingnpm
.
cd
into packages/db-infrastructure and runnpm run deploy
. After this runs, you should now have a stack called dev-scaffold-eth-infra-dynamodb in Cloudformation.
cd
into packages/api and install the dependencies usingnpm install
.- Change the URL that will be linked to your API in the following files - this is the same URL that you've created the Certificate above for, e.g. for me it's dev.api.vorder.io:
- In the file packages/api/serverless.yml, change the variable domainName so that it matches your URL. ${self:custom.stage} is set to dev by default already.
- In the file packages/react-app/src/util change baseUrl to that same URL so that the front-end knows where the API is located.
- Link your API to the URL by running
npx serverless create_domain
. - Finally, deploy the infrastucture using
npm run deploy
.
- Integrate on-chain voting using https://docs.openzeppelin.com/contracts/4.x/governance
- Push notifications every time an investor buys or sells shares