Search Apps Documentation Source Content File Folder Download Copy

Gno.land Moderation DAO Module

Gno.land Moderation DAO Module

This blog post is written by the Teritori team, whose focus is to allow organizations to communicate and interact in a resilient and transparent way. Teritori is a partner and grantee of Gno.land.

When it comes to the complex subject of discussion forums and decentralized social networks, numerous technical and philosophical questions arise. Imagining a 24/7 online communication system whose administration cannot be compromised or censored by any entity or individual is one of the most intriguing challenges of the decade. Approximately 10 months ago, the Teritori core team decided to explore the new possibilities offered by Gno.land on the theme of decentralized moderation and to build the foundation for future generations of developers to create resilient, robust, and autonomous applications.

The vision

About Teritori

Teritori is a decentralized Operating System for individuals & communities that allows organizations to communicate and interact in a resilient and transparent way. Its core components include the creation of a decentralized User Profile for individuals & organizations as well as a dApp Store allowing users to pick their favorite services for daily usage and developers to list their product in order to grow their user base. Finally, Teritori backbone, its P2P messenger application that will enable users to create resilient token-gated groups in a click will even allow non-crypto-native users to get onboard as this feature doesn't even require a wallet connection to get started.

Teritori <> Gno.land

Convinced of the benefits of offering a contribution-based consensus model and taking advantage of an interpreted version of Golang, the Teritori core team aims to become one of the most prolific contributors to Gno.land. Our plan is to focus on features that enable the coordination of organizations and individuals via governance, communications, and collaboration. Eventually, all the features listed on Teritori will be accessible in the Gno.land network, contributing to the growth of the ecosystem.

PoC and iterations

Another important point to emphasize is that the Teritori core team intends to improve the features it deploys on Gno.land by taking advantage of the user test phases to collect feedback that will enable iteration and improvement of the service. As a result, the “Proof-of-Concept” (“PoC”) presented in this article will be subject to updates and evolutions, which will be communicated in due course, as will the associated test phases.

What is the Gno Moderation Module?

The Gno Moderation Module is a smart contract (“realm”) that enables a decentralized, autonomous organization (DAO) to manage the moderation of a forum or social thread through a transparent on-chain vote.

Let’s take an example:

Imagine a simple social network similar to Instagram, in which all content is decentralized (using IPFS for images, videos, music etc.). For each post, users sign in via their wallet to post content, and no centralized administrator can delete this content. The freedom offered by this type of decentralized application is immense since even as developers of the application, it is impossible to delete the content. Therefore, we can consider this “space of freedom” as a “common space” unlike any application owned by a private company and hosted on centralized infrastructure. With this radical freedom for the user comes a great responsibility— to collectively ensure the security of this space rather than delegating the responsibility to moderators employed by a commercial enterprise. This is why we’ve created the “Gno Moderation Module.”

How does it work?

moderation_flow v0.1

The Gno Moderation Module allows users to notify the moderation DAO community that they wish to report content. Through this action (permitted by the smart contract), they inform the DAO community that the content is inappropriate.

content flag

Once the content has been reported a certain number of times (10 times in this PoC) by users (who may or may not be members of the Moderation DAO), an on-chain proposal is automatically created.

moderation dao feed

This on-chain proposal is then listed in the Moderation DAO tab on the Social Feed as well as on the Moderation DAO profile proposals feed so all Moderation DAO members can vote on it. A debate can take place to discuss the best choice for the content.

moderation dao vote

Moderation DAO members have three voting options:

  • Ban the content in question
  • Abstain
  • Do not ban the content in question

Once the required vote quota has been reached, the contract automatically executes the voted decision.

The Current Status:

The Teritori core team received a grant from the Gno.land core team to build the necessary tools for decentralized moderation.

To accomplish this task, we divided our work into five main stages:

  1. Build “DAO” standards to establish the fundamental building blocks and ensure a modular approach in the long term for various tools.
  2. Build a “DAO” deployer that allows non-tech users to easily utilize the different standards.
  3. Build a customizable Moderation Module that can cater to a wide range of use cases. For example, if we replace the social feed with a service marketplace, the Moderation Module can transform into a “Justice Module” that resolves conflicts between sellers and buyers on a decentralized platform and serves as an escrow system.
  4. Develop the user experience that allows for large-scale experimentation with the Moderation Module within a dedicated context of an active social feed. Here, we created a social feed realm and enabled non-developer Gno.land users to participate in the full-scale experience.
  5. Establish interactions between smart contracts (r/boards, r/socialfeed, /r/users), conduct experiments to enhance their security, and identify emerging needs for these innovative use cases.

What does a DAO realm look like?

  • We decided to build two different DAO standards, using two different approaches of modularity:
  • Aragon DAO Standard, based on the amazing work of the Aragon team (using Solidity)
  • DAODAO smart contract, using CosmWasm, that allows more modularity.

Here is an example, with the DAODAO contract ported into Gnolang: Source

  1package dao_realm
  2
  3import (
  4	"encoding/base64"
  5	"std"
  6	"strings"
  7	"time"
  8
  9	dao_core "gno.land/p/demo/daodao/core_v16"
 10	dao_interfaces "gno.land/p/demo/daodao/interfaces_v16"
 11	proposal_single "gno.land/p/demo/daodao/proposal_single_v16"
 12	voting_group "gno.land/p/demo/daodao/voting_group_v17"
 13	"gno.land/p/demo/ujson_v5"
 14	"gno.land/r/demo/groups_v22"
 15	modboards "gno.land/r/demo/modboards_v9"
 16)
 17
 18var (
 19	daoCore       dao_interfaces.IDAOCore
 20	mainBoardName = "dao_realm"
 21	groupName     = mainBoardName + "_voting_group"
 22	groupID       groups.GroupID
 23)
 24
 25func init() {
 26	modboards.CreateBoard(mainBoardName)
 27
 28	votingModuleFactory := func(core dao_interfaces.IDAOCore) dao_interfaces.IVotingModule {
 29		groupID = groups.CreateGroup(groupName)
 30		groups.AddMember(groupID, "g1747t5m2f08plqjlrjk2q0qld7465hxz8gkx59c", 1, "")
 31		groups.AddMember(groupID, "g108cszmcvs4r3k67k7h5zuhm4el3qhlrxzhshtv", 1, "")
 32		groups.AddMember(groupID, "g14u5eaheavy0ux4dmpykg2gvxpvqvexm9cyg58a", 1, "")
 33		groups.AddMember(groupID, "g1ckn395mpttp0vupgtratyufdaakgh8jgkmr3ym", 1, "")
 34		groups.AddMember(groupID, std.GetOrigCaller().String(), 1, "")
 35		return voting_group.NewVotingGroup(groupID)
 36	}
 37
 38	proposalModulesFactories := []dao_interfaces.ProposalModuleFactory{
 39		func(core dao_interfaces.IDAOCore) dao_interfaces.IProposalModule {
 40			tt := proposal_single.Percent(100) // 1%
 41			tq := proposal_single.Percent(100) // 1%
 42			return proposal_single.NewDAOProposalSingle(core, &proposal_single.DAOProposalSingleOpts{
 43				MaxVotingPeriod: time.Hour * 24 * 42,
 44				Threshold: proposal_single.Threshold{ThresholdQuorum: &proposal_single.ThresholdQuorum{
 45					Threshold: proposal_single.PercentageThreshold{Percent: &tt},
 46					Quorum:    proposal_single.PercentageThreshold{Percent: &tq},
 47				}},
 48			})
 49		},
 50	}
 51
 52	messageHandlersFactories := []dao_interfaces.MessageHandlerFactory{
 53		func(core dao_interfaces.IDAOCore) dao_interfaces.MessageHandler {
 54			return groups.NewAddMemberHandler()
 55		},
 56		func(core dao_interfaces.IDAOCore) dao_interfaces.MessageHandler {
 57			return groups.NewDeleteMemberHandler()
 58		},
 59		func(core dao_interfaces.IDAOCore) dao_interfaces.MessageHandler {
 60			// TODO: add a router to support multiple proposal modules
 61			propMod := core.ProposalModules()[0]
 62			return proposal_single.NewUpdateSettingsHandler(propMod.Module.(*proposal_single.DAOProposalSingle))
 63		},
 64		func(core dao_interfaces.IDAOCore) dao_interfaces.MessageHandler {
 65			return modboards.NewCreateBoardHandler()
 66		},
 67		func(core dao_interfaces.IDAOCore) dao_interfaces.MessageHandler {
 68			return modboards.NewDeletePostHandler()
 69		},
 70	}
 71
 72	daoCore = dao_core.NewDAOCore(votingModuleFactory, proposalModulesFactories, messageHandlersFactories)
 73}
 74
 75func Render(path string) string {
 76	return "[[board](/r/demo/modboards:" + mainBoardName + ")]\n\n" + daoCore.Render(path)
 77}
 78
 79func VoteJSON(moduleIndex int, proposalID int, voteJSON string) {
 80	module := dao_core.GetProposalModule(daoCore, moduleIndex)
 81	if !module.Enabled {
 82		panic("proposal module is not enabled")
 83	}
 84	module.Module.VoteJSON(proposalID, voteJSON)
 85}
 86
 87func Execute(moduleIndex int, proposalID int) {
 88	module := dao_core.GetProposalModule(daoCore, moduleIndex)
 89	if !module.Enabled {
 90		panic("proposal module is not enabled")
 91	}
 92	module.Module.Execute(proposalID)
 93}
 94
 95func ProposeJSON(moduleIndex int, proposalJSON string) {
 96	module := dao_core.GetProposalModule(daoCore, moduleIndex)
 97	if !module.Enabled {
 98		panic("proposal module is not enabled")
 99	}
100	module.Module.ProposeJSON(proposalJSON)
101}
102
103func getProposalsJSON(moduleIndex int, limit int, startAfter string, reverse bool) string {
104	module := dao_core.GetProposalModule(daoCore, moduleIndex)
105	return module.Module.ProposalsJSON(limit, startAfter, reverse)
106}

Public Grant Report:

You can find the full report of Teritori Core’s journey here.

Resources:

Documentation:

Packages:

Tutorial:


Tags: #gnoland #dao #moderation #teritori

Written by ferrymangmi, zxxma, michelleellen on 19 Oct 2023

Published by g125em6arxsnj49vx35f0n0z34putv5ty3376fg5 to gno.land's blog