Title: ERC_4824_Decentralized_Autonomous_Organizations
Category: ERCs

Author: thelastjosh
Date: 2022-02-18T20:09:00.537Z

Authors
Joshua Tan (@thelastjosh), Isaac Patka (@ipatka), Ido Gershtein (ido@daostack.io), Eyal Eithcowich (eyal@deepdao.io), Michael Zargham (@mzargham), Sam Furter (@nivida)




EIP Link
Github


Discussions
See  daostar.org, daostar.one, and original thread


Status
Draft


Type
Standards Track


Category
ERC


Created
2022-02-17



Abstract
A standard URI and JSON schema for decentralized autonomous organizations (DAOs), focusing on relating on-chain and off-chain representations of membership and proposals.
Motivation
DAOs, since being invoked in the Ethereum whitepaper, have been vaguely defined. This has led to a wide range of patterns but little standardization or interoperability between the frameworks and tools that have emerged. Standardization and interoperability are necessary to support a variety of use-cases. In particular, a standard daoURI, similar to tokenURI in ERC-721, will enhance DAO search, discoverability, legibility, and proposal simulation. More consistent data across the ecosystem is also a prerequisite for future DAO standards.
Specification
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119.
Every EIP-4824 compliant contract MUST implement the EIP4824 interface below:
pragma solidity ^0.4.20;

/// @title EIP-4824 DAOs
/// @dev See https://eips.ethereum.org/EIPS/eip-4824

interface EIP4824 {
    /// @notice A distinct Uniform Resource Identifier (URI) pointing to a JSON object following the "EIP-4824 DAO JSON-LD Schema". This JSON file splits into four URIs: membersURI, proposalsURI, activityLogURI, and governanceURI. The membersURI should point to a JSON file that conforms to the "EIP-4824 Members JSON-LD Schema". The proposalsURI should point to a JSON file that conforms to the "EIP-4824 Proposals JSON-LD Schema". The activityLogURI should point to a JSON file that conforms to the "EIP-4824 Activity Log JSON-LD Schema". The governanceURI should point to a flatfile, normatively a .md file. Each of the JSON files named above can be statically-hosted or dynamically-generated.
    function daoURI() external view returns (string _daoURI);
}

The EIP-4824 DAO JSON-LD Schema mentioned above.
{
	"@context": "http://www.daostar.org/schemas",
	"type": "DAO",
	"name": "<name of the DAO>",
	"description": "<description>",
	"membersURI": "<URI>",
	"proposalsURI": "<URI>",
	"activityLogURI": "<URI>",
	"governanceURI": "<URI>"
}

Members
Members JSON-LD Schema.
{
  "@context": "http://www.daostar.org/schemas",
  "type": "DAO",
  "name": "<name of the DAO>",
  "members": [
    {
      "type": "EthereumAddress",
      "address": "<address>"
    },
    {
      "type": "EthereumAddress",
      "address": "<address>"
    }
  ]
}

Proposals
Proposals JSON-LD Schema. Every EIP-4824 contract should implement a proposalsURI pointing to a JSON object satisfying this schema.
In particular, any on-chain proposal MUST be associated to an id of the form CAIP10_ADDRESS + “?proposalId=” + PROPOSAL_COUNTER, where CAIP10_ADDRESS is an address following the CAIP-10 standard and PROPOSAL_COUNTER is an arbitrary identifier such as a uint256 counter or a hash that is locally unique per CAIP-10 address. Off-chain proposals MAY use a similar id format where CAIP10_ADDRESS is replaced with an appropriate URI or URL.
{
  "@context": "http://www.daostar.org/schemas",
  "type": "DAO",
  "name": "<name of the DAO>",
  "proposals": [
    {
      "type": "proposal",
      "id": "<proposal ID>",
      "name": "<name or title of proposal>",
      "contentURI": "<URI to content or discussion>",
      "status": "<status of proposal>",
      "calls": [
        {
          "type": "CallDataEVM",
          "operation": "<call or delegate call>",
          "from": "<EthereumAddress>",
          "to": "<EthereumAddress>",
          "value": "<value>",
          "data": "<call data>"
        }
      ]
    }
  ]
}

Activity Log
Activity Log JSON-LD Schema.
{
  "@context": "http://www.daostar.org/schemas",
  "type": "DAO",
  "name": "<name of the DAO>",
  "activities": [
    {
      "id": "<activity ID>",
      "type": "activity",
      "proposal": {
        "id": "<proposal ID>",
        "type": "proposal"
      },
      "member": {
        "type": "EthereumAddress",
        "address": "<address>"
      }
    },
    {
      "id": "<activity ID>",
      "type": "activity",
      "proposal": {
        "id": "<proposal ID>",
        "type": "proposal"
      },
      "member": {
        "type": "EthereumAddress",
        "address": "<address>"
      }
    },
  ]
}

Rationale
In this standard, we assume that all DAOs possess at least two primitives: membership and behavior. Membership is defined by a set of addresses. Behavior is defined by a set of possible contract actions, including calls to external contracts and calls to internal functions. Proposals relate membership and behavior; they are objects that members can interact with and which, if and when executed, become behaviors of the DAO.
URIs and off-chain data
DAOs themselves have a number of existing and emerging use-cases. But almost all DAOs need to publish data off-chain for a number of reasons: communicating to and recruiting members, coordinating activities, powering user interfaces and governance applications such as Snapshot or Tally, or enabling search and discovery via platforms like DeepDAO or Messari. Having a standardized schema for this data, akin to an API specification, would strengthen existing use-cases for DAOs, help scale tooling and frameworks across the ecosystem, and build support for additional forms of interoperability.
While we considered standardizing on-chain aspects of DAOs in this standard, particularly on-chain proposal objects and proposal IDs, we felt that this level of standardization was premature given (1) the relative immaturity of use-cases, such as multi-DAO proposals or master-minion contracts, that would benefit from such standardization, (2) the close linkage between proposal systems and governance, which we did not want to standardize (see “governanceURI”, below), and (3) the prevalence of off-chain and L2 voting and proposal systems in DAOs (see “proposalsURI”, below). Further, a standard URI interface is relatively easy to adopt and has been actively demanded by frameworks (see “Community Consensus”, below).
membersURI
Approaches to membership vary widely in DAOs. Some DAOs and DAO frameworks (e.g. Gnosis Safe, Tribute), maintain an explicit, on-chain set of members, sometimes called owners or stewards. But many DAOs are structured so that membership status is based on the ownership of a token or tokens (e.g. Moloch, Compound, DAOstack, 1Hive Gardens). In these DAOs, computing the list of current members typically requires some form of off-chain indexing of events.
In choosing to ask only for an (off-chain) JSON schema of members, we are trading off some on-chain functionality for more flexibility and efficiency. We expect different DAOs to use membersURI in different ways: to serve a static copy of on-chain membership data, to contextualize the on-chain data (e.g. many Gnosis Safe stewards would not say that they are the only members of the DAO), to serve consistent membership for a DAO composed of multiple contracts, or to point at an external service that computes the list, among many other possibilities. We also expect many DAO frameworks to offer a standard endpoint that computes this JSON file, and we provide a few examples of such endpoints in the implementation section.
We encourage extensions of the Membership JSON-LD Schema, e.g. for DAOs that wish to create a state variable that captures active/inactive status or different membership levels.
proposalsURI
Proposals have become a standard way for the members of a DAO to trigger on-chain actions, e.g. sending out tokens as part of grant or executing arbitrary code in an external contract. In practice, however, many DAOs are governed by off-chain decision-making systems on platforms such as Discourse, Discord, or Snapshot, where off-chain proposals may function as signaling mechanisms for an administrator or as a prerequisite for a later on-chain vote. (To be clear, on-chain votes may also serve as non-binding signaling mechanisms or as “binding” signals leading to some sort of off-chain execution.) The schema we propose is intended to support both on-chain and off-chain proposals, though DAOs themselves may choose to report only on-chain, only off-chain, or some custom mix of proposal types.
Proposal ID. Every unique on-chain proposal MUST be associated to a proposal ID of the form CAIP10_ADDRESS + “?proposalId=” + PROPOSAL_COUNTER, where PROPOSAL_COUNTER is an arbitrary string which is unique per CAIP10_ADDRESS. Note that PROPOSAL_COUNTER may not be the same as the on-chain representation of the proposal; however, each PROPOSAL_COUNTER should be unique per CAIP10_ADDRESS, such that the proposal ID is a globally unique identifier. We endorse the CAIP-10 standard to support multi-chain / layer 2 proposals and the “?proposalId=” query syntax to suggest off-chain usage.
ContentURI. In many cases, a proposal will have some (off-chain) content such as a forum post or a description on a voting platform which predates or accompanies the actual proposal.
Status. Almost all proposals have a status or state, but the actual status is tied to the governance system, and there is no clear consensus between existing DAOs about what those statuses should be (see table below). Therefore, we have defined a “status” property with a generic, free text description field.




Project
Proposal Statuses




Aragon
Not specified


Colony
[‘Null’, ‘Staking’, ‘Submit’, ‘Reveal’, ‘Closed’, ‘Finalizable’, ‘Finalized’, ‘Failed’]


Compound
[‘Pending’, ‘Active’, ‘Canceled’, ‘Defeated’, ‘Succeeded’, ‘Queued’, ‘Expired’, ‘Executed’]


DAOstack/ Alchemy
[‘None’, ‘ExpiredInQueue’, ‘Executed’, ‘Queued’, ‘PreBoosted’, ‘Boosted’, ‘QuietEndingPeriod’]


Moloch v2
[sponsored, processed, didPass, cancelled, whitelist, guildkick]


Tribute
[‘EXISTS’, ‘SPONSORED’, ‘PROCESSED’]



ExecutionData. For on-chain proposals with non-empty execution, we include an array field to expose the call data. The main use-case for this data is execution simulation of proposals.
activityLogURI
The activity log JSON is intended to capture the interplay between a member of a DAO and a given proposal. Examples of activities include the creation/submission of a proposal, voting on a proposal, disputing a proposal, and so on.
Alternatives we considered: history, interactions
governanceURI
Membership, to be meaningful, usually implies rights and affordances of some sort, e.g. the right to vote on proposals, the right to ragequit, the right to veto proposals, and so on. But many rights and affordances of membership are realized off-chain (e.g. right to vote on a Snapshot, gated access to a Discord). Instead of trying to standardize these wide-ranging practices or forcing DAOs to locate descriptions of those rights on-chain, we believe that a flatfile represents the easiest and most widely-acceptable mechanism for communicating what membership means and how proposals work. These flatfiles can then be consumed by services such as Etherscan, supporting DAO discoverability and legibility.
We chose the word “governance” as an appropriate word that reflects (1) the widespread use of the word in the DAO ecosystem and (2) the common practice of emitting a governance.md file in open-source software projects.
Alternative names considered: description, readme, constitution
Why JSON-LD
We chose to use JSON-LD rather than the more widespread and simpler JSON standard because (1) we want to support use-cases where a DAO wants to include members using some other form of identification than their Ethereum address and (2) we want this standard to be compatible with future multi-chain standards. Either use-case would require us to implement a context and type for addresses, which is already implemented in JSON-LD.
Further, given the emergence of patterns such as subDAOs and DAOs of DAOs in large organizations such as Synthetix, as well as L2 and multi-chain use-cases, we expect some organizations will point multiple EIP-4824 DAOs to the same URI, which would then serve as a gateway to data from multiple contracts and services. The choice of JSON-LD allows for easier extension and management of that data.
Community Consensus
The initial draft standard was developed as part of the DAOstar One roundtable series, which included representatives from all major EVM-based DAO frameworks (Aragon, Compound, DAOstack, Gnosis, Moloch, OpenZeppelin, and Tribute), a wide selection of DAO tooling developers, as well as several major DAOs. Thank you to all the participants of the roundtable, the full list of which can be found here. We would especially like to thank Auryn Macmillan, Fabien of Snapshot, Selim Imoberdorf, Lucia Korpas, and Mehdi Salehi for their contributions.
In-person events will be held at Schelling Point 2022 and at ETHDenver 2022, where we hope to receive more comments from the community. We also plan to schedule a series of community calls through early 2022.
Security Considerations
This standard defines the interfaces for the DAO URIs but does not specify the rules under which the URIs are set, or how the data is prepared. Developers implementing this standard should consider how to update this data in a way aligned with the DAO’s governance model, and keep the data fresh in a way that minimizes reliance on centralized service providers.
Indexers that rely on the data returned by the URI should take caution if DAOs return executable code from the URIs. This executable code might be intended to get the freshest information on membership, proposals, and activity log, but it could also be used to run unrelated tasks.
Copyright
Copyright and related rights waived via CC0.

edited March 6, 2022: updated to reflect most recent changes to PR

Author: thelastjosh
Date: 2022-02-19T14:12:03.774Z

Additional references

Dilger, W. (1997). Decentralized autonomous organization of the intelligent home according to the principle of the immune system’. 1997 IEEE International Conference on Systems, Man, and Cybernetics. Computational Cybernetics and Simulation, 351–356. https://doi.org/10.1109/ICSMC.1997.625775

Buterin, V. (2013a). Ethereum whitepaper: A next-generation smart contract and decentralized application platform [White Paper]. https://blockchainlab.com/pdf/Ethereum_white_paper-a_next_generation_smart_contract_and_decentralized_application_platform-vitalik-buterin.pdf

JSON-LD Schema. https://json-ld.org/

CAIP-10. https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-10.md

Author: toledoroy
Date: 2022-03-16T14:19:53.869Z

Hi,
Great idea! we should definitely add some standards for metadata. Though I think we could generalize this idea a bit and perhaps come up with something that could work for other contracts as well.
First, I think it would probably make more sense to have different types/names for different JSON files, so we can tell them parts
E.g.
Members
 "type": "members",

and
Proposals
 "type": "proposals",

It might be more correct to name that parameter as role, not type, as the type usually represents what a thing is and this represents what it is for (purpose).
If you do that, you could just use the conventional contractURI() which would a JSON of “type”: “DAO” or “role”: “DAO”. Which makes more sense semantically, doesn’t require that you have prior knowledge regarding the contract type, and could be use as a general standard for all other types of contracts as well.

Author: thelastjosh
Date: 2022-03-20T12:24:56.691Z

Hi @toledoroy ! First off, thank you for the suggestions 
Re: associating types for the different JSON files being returned by membersURI and proposalsURI, we didn’t really dig into this during the working group discussions, so maybe now is a good opportunity. My thoughts are:

First, notice that each individual member does have a type or typeclass, member, and it might get confusing for member and members to be separate types (e.g. in the schema.org ontology, member supersedes members, so there’s no difference).
Perhaps most saliently, the membersURI and proposalsURI are pointing to different JSON objects because we expect some DAOs might want to compute those using different services, and it allows for more modularity. You could imagine them getting replaced by properties members and proposals, and daoURI returning a giant nested JSON with all the metadata, members, proposals, activities, etc. In that case, the type of the JSONs returned by membersURI, proposalsURI, and activityLogURI would just be DAO, since members and proposals are properties intended to be evaluated in the DAO type/context. And you can see this in current type signatures of the JSONs returned by proposalsURI, membersURI, and activityLogURI.
If I think about it from a data modeling standpoint, it feels like we should be able to just say that the type of the Members JSON should just be something like List(member) or [member].

Let me know if that makes sense; I’ve tagged some of the other team members to get their thoughts @mzargham @nivida.
Re: contractURI suggestion, I think you’re right, but I’m not familiar with uses of contractURI outside of the OpenSea context though for NFTs (essentially replacing/extending tokenURI). Do you see it getting more prominent usage elsewhere / has there been a standard emitted for it? I could see it being really useful to have a generic contractURI for every single contract that the daoURI schema could inherit from.

Author: julesl23
Date: 2022-03-21T15:41:16.913Z

Hi,
I am liking this but something did bother me…
That everything is shuffled off-chain to secondary storage.
I’m thinking that members can be a map of accounts on-chain (so can call member style functions). Proposals can each be an NFT, grounding the truth on-chain. Hence leveraging much more of the Ethereum eco system.
Sure, variables such as descriptions, history logs etc. can be off-chain JSON type files.
I’m all for pushing wider use of NFTs beyond digital art. I see this proposal as an opportunity to do this, forgive me.
What about gas fees might be a reaction? By the time if this goes to final stages, fees will be much lower anyway (hopefully).

Author: thelastjosh
Date: 2022-03-23T03:02:27.385Z

Thanks for the comments @julesl23 ! Re: proposals as NFTs—an idea like this did come up during the WG sessions, I think from @mzargham! We ended not going there because it’s not a pattern that we currently see in the ecosystem, and we didn’t want this first standard to push the envelope so much as organize and exemplify existing best-practices in observed DAOs and DAO frameworks.
DAOs in other L1s with much lower costs do end up hosting more of their ops and data on-chain (and we’re working to explore/cover those use-cases in a multi-chain working group), but for now that’s not standard in Ethereum use-cases. But even with lower fees, there will always be a use-case for the off-chain data for the legibility and discoverability use-cases we mention.

Author: toledoroy
Date: 2022-03-23T17:52:26.948Z

Loving this!
People are non-fungible too and there’s no reason for each DAO member to have to maintain and update their data on different locations.
image1275×984 69.3 KB

Author: Asgeir
Date: 2022-03-24T19:19:34.625Z

Great initiative! I love how open it is (even while making the data more easily consumable); it does not force DAOs into some rigid standardization scheme!
One thing that came to mind is that we could perhaps, instead of or in addition to the interface implementation requirement, have an event emitted with the daoURI.
The event could, for instance, be emitted by:

A common contract with a function that takes a daoURI and emits it in an event, or
It could be a standard event emitted by any contract, or
It could use ERC-3722 (Poster) with a standard tag.

The rationale for proposing this:

The daoURI is not something that is consumable on-chain, and therefore does not need to be part of the chain state.
It’s easy to propose a transaction that will emit the event to any DAO that can execute arbitrary transactions. It will also be easy for preexisting DAOs to “implement the standard”.
Implementing a Subgraph for continuously indexing all DAOs that emit the event is trivial.

Basically, this could make it cheaper to implement the standard, make it easier to implement the standard (and in the future update the daoURI), and make it more easily indexable.

Author: julesl23
Date: 2022-03-24T20:59:35.248Z

I second what @Asgeir says. I was going to say it but forgot as I wrote my other post.
The other thing I noticed was lack of timestamps in any of the JSON files…
Take an example where a DAO has thousands of members and the membership is tokenised with a secondary market so a lot of members joining and leaving. With current proposal it doesn’t define if memberships list has to be up to date. In this use case, a single member leaving/joining and the whole list has to be written out again.
I know there is the blurb on having endpoint to compute this real-time but unless I’m mistaken that requires server and defeats purpose of decentralisation. Is there a way to get this list computed by smart contract directly?
At least with a timestamp and a snapshot of members list, won’t have to keep uploading the most up to date.
On that point, wasn’t clear to me in activates log if member is the proposer of the contract, or members’ snapshot of voting and where would amounts/results go and so on?

Author: thelastjosh
Date: 2022-03-28T23:51:10.649Z

Just wanted to say that I really like this idea. It would make adoption much easier for existing DAOs. One question is which of these methods (contract, event, poster) we should recommend, and/or whether we should support all of them.
Small note, on some level no matter what method you use, daoURI has to be part of the chain state, it just doesn’t have to be defined in the contract.

Author: Asgeir
Date: 2022-03-29T10:26:52.793Z

I like the event method option since it’s the most flexible one. This will allow a more strict and backward-compatible standard to be developed using the contract method later (with additional checks and still emitting the event).
Can we assume that all DAOs can execute arbitrary function calls from the “avatar” address (or the address that represents the DAO)? If so, we could use the message sender as the DAO address (when indexing). Also, if there is a new emit of the event, we can treat it as an overwrite of the old daoURI.
Basically something like this:
emit ERC4824(string daoUIR); // implicitly the message sender is the DAO

Perhaps we should also add an indexed address to the event. That can be useful later if a new standard builds on this one using the contract method (where this address can probably be trusted, which is not the case in this version).

Author: thelastjosh
Date: 2022-03-29T13:42:55.243Z

In the standard we don’t actually assume that every standard has an avatar or canonical contract; in principle multiple contracts (on multiple chains / L2s!) associated to the same DAO can all pass to the same daoURI (~a company operating multiple storefronts or processes). But the event method still makes sense in that context.
How would attaching an indexed address to the event be useful? Are you assuming this would be “avatar” address?

Author: julesl23
Date: 2022-03-29T20:58:34.618Z

Okay, with so little use of the blockchain, what’s stopping a malicious actor pointing e.g. proposalsURI to their centralised storage and changing the proposal before its execution?
Will the community easily understand that this is not a trustless system? Given the context of its use, what are the checks and balances?

Author: julesl23
Date: 2022-03-30T07:27:39.565Z

Having the URI addresses (such as hashes) come from the blockchain would be more secure. Something like this:
emit ERC4824(
string context,
address indexed dao,
string name,
string description,
string membersURI,
string proposalsURI,
string activityLogURI,
string governanceURI
);

Author: Asgeir
Date: 2022-03-30T08:22:53.680Z

Aha, that makes sense.
My thinking was that in the initially proposed solution, using the EIP4824 interface, the daoURI would be associated with the address of the contract implementing it. If we were going to use an event instead, we need another way to associate an address with the daoURI (even if multiple addresses can point to the same daoURI). Also, we need to be able to trust that address (so that not anybody can register daoURIs for any address).
Therefore, looking at it again now, I can’t see how we can get an address that we can trust by only using an event (like I proposed above). I think we will need to use a contract that also emits the message sender (just like Poster does). Or could there be another solution here that I am not aware of?
I think it could make sense to create a new contract almost identical to the Poster contract and deployment process (via singleton). As Poster seems to be intended for social media: “A ridiculously simple general-purpose social media smart contract.”. Also, it will be less resource-intensive to process the events.

Author: julesl23
Date: 2022-03-30T23:50:01.525Z

Yeah, I’m liking it.
Three different versions:
v1
contract ERC4824v1 {
    event DAOUpdate(
        address indexed sender,
        address[] indexed daos,
        string name,
        string description,
        string membersURI,
        string proposalsURI,
        string activityLogURI,
        string governanceURI
    );

    function dao(
        address[] calldata daos,
        string calldata name,
        string calldata description,
        string calldata membersURI,
        string calldata proposalsURI,
        string calldata activityLogURI,
        string calldata governanceURI
    ) public {
        emit DAOUpdate(
            msg.sender,
            daos,
            name,
            description,
            membersURI,
            proposalsURI,
            activityLogURI,
            governanceURI
        );
    }
}

v2
contract ERC4824v2 {
    event DAOUpdate(address indexed sender, string uri);

    function dao(string calldata uri) public {
        emit DAOUpdate(msg.sender, uri);
    }
}

v3
contract ERC4824v3 {
    event DAOUpdate(address indexed sender, address[] indexed daos, string uri);

    function dao(address[] calldata daos, string calldata uri) public {
        emit DAOUpdate(msg.sender, daos, uri);
    }
}

The last one can search by dao(s) address, whilst the second one can’t. Both use less gas than the first. The first has the advantage of the last and the hashes of membersURI, proposalsURI and governanceURI come from the blockchain via events, more secure.

Author: julesl23
Date: 2022-03-31T19:05:00.611Z

I still feel there is a lack of timestamps though.
With events at least can get the block timestamp it was emitted from (to an accuracy between two blocks is probably good enough for most use cases). But anything in JSON-LD files cannot without timestamp fields in them, I feel is needed; considering that most data in these are conceptually snapshots.

Author: thelastjosh
Date: 2022-03-31T21:43:31.617Z

Just wanted to say that @mzargham and I are working on a response to the event/poster idea; we had a long conversation about it at today’s working group meeting and have some ideas!

Author: thelastjosh
Date: 2022-03-31T21:46:25.115Z

Re timestamps, I think this is more something that people could easily add to the data model / extend the standard with, rather than a truly necessary data field. We’re working to add tooling, e.g. a schema manager / explorer, to allow easier and relatively permisionless extensions of the data model for extended use-cases.

Author: julesl23
Date: 2022-04-01T00:34:14.100Z

That’s a shame @thelastjosh . So we are not able to search for any changes then?
For example, how to filter for new proposals?

Author: julesl23
Date: 2022-04-01T00:41:58.983Z

Also I’m not sure what fields are considered required and which optional?
For some use cases, the Members JSON-LD file is not possible as there is maybe no array list of members held by DAO contract, only total supply of governance tokens. This to save gas and storage, and maybe anonymity/security reasons too.
When proposals are voted for, at that stage can get list of accounts that voted with their governance tokens. So only then can these subset of accounts be recorded in proposals/activity files.

Author: zelbazk
Date: 2022-04-02T01:46:14.973Z

Hi all,
Forgive me for not contributing to the technical discussion around this proposal.
Re: mutli-DAO proposals and master-minion contracts, can someone link me to those discussion pages or (if they exist) proposals?

Author: julesl23
Date: 2022-04-05T20:15:10.646Z

Hi,
This works for my use cases for e-commerce and social media:
I was concerned on two things; lack of any timestamps and the JSON-LD files lack of security as they can be stored on centralised storages then changed at will.
I believe this helps bolster security by “grounding” the JSON-LD to the blockchain a lot more, by ensuring that any updates have emitted together the msg.sender and uri (hashed) link.
    event DAOUpdate(
        address indexed sender,
        address indexed dao,
        string name,
        string description,
        string governanceURI
    );

    event MemberUpdate(
        address indexed sender,
        address indexed dao,
        address indexed member,
        string memberURI
    );

    event ProposalUpdate(
        address indexed sender,
        address indexed dao,
        string indexed proposalId,
        string proposalURI
    );

    event ActivityLogUpdate(
        address indexed sender,
        address indexed dao,
        string indexed activityId,
        string activityLogURI
    );

This means breaking up the updates to their own JSON-LD files. So there is an individual Member JSON-LD Schema, Proposal JSON-LD Schema file, individual Activity Log JSON-LD Schema, rather than having them collected in bigger JSON-LD files.
Every update is posted out by calling their corresponding singleton contract function; dao, memberUpdate, proposalUpdate, or activityLogUpdate with the msg.sender address and uri link.
    function dao(
        address calldata dao,
        string calldata name,
        string calldata description,
        string calldata governanceURI
    ) public {
        emit DAOUpdate(msg.sender, daos, name, description, governanceURI);
    }

    function memberUpdate(
        address calldata dao,
        address member,
        string calldata memberURI
    ) public {
        emit MemberUpdate(msg.sender, daos, member, memberURI);
    }

    function proposalUpdate(
        address[] calldata daos,
        string calldata proposalId,
        string calldata proposalURI
    ) public {
        emit ProposalUpdate(msg.sender, daos, proposalId, proposalURI);
    }

    function activityLogUpdate(
        address calldata dao,
        string calldata activityId,
        string calldata activityLogURI
    ) public {
        emit ActivityLogUpdate(msg.sender, daos, activityId, activityLogURI);
    }

This solves my timestamp issue as every emitted event has a block number it came from. This can be retrieved and block numbers converted to timestamps using a web3 library.
Can validate off-line too that the posted uri hash matches the content that it points to (depending on recognised link formats like ipfs). As mentioned, each posted uri link is emitted with the msg.sender address, thus we know what account made the change. Off-line processing can validate if that account is a DAO member etc.
With the use of event filters from a web3 library, all proposals’ updates for a DAO can be retrieved and sorted by block number, hence just the latest changes can be returned etc. Similarly, all or individual proposals, members and activity logs can be retrieved using any or combination of their event’s indexed parameters.
So now I have a fourth version:
contract ERC4824v4 {
    event SchemaUpdate(
        address indexed sender,
        string indexed indexedSchemaURI,
        string name,
        string description,
        string schemaURI
    );

    event DAOUpdate(
        address indexed sender,
        address indexed dao,
        string name,
        string description,
        string governanceURI
    );

    event MemberUpdate(
        address indexed sender,
        address indexed dao,
        address indexed member,
        string memberURI
    );

    event ProposalUpdate(
        address indexed sender,
        address indexed dao,
        string indexed proposalId,
        string proposalURI
    );

    event ActivityLogUpdate(
        address indexed sender,
        address indexed dao,
        string indexed activityId,
        string activityLogURI
    );

    function schemaUpdate(
        string calldata name,
        string calldata description,
        string calldata schemaURI
    ) public {
        emit SchemaUpdate(msg.sender, schemaURI, name, description, schemaURI);
    }

    function daoUpdate(
        address dao,
        string calldata name,
        string calldata description,
        string calldata governanceURI
    ) public {
        emit DAOUpdate(msg.sender, dao, name, description, governanceURI);
    }

    function memberUpdate(
        address dao,
        address member,
        string calldata memberURI
    ) public {
        emit MemberUpdate(msg.sender, dao, member, memberURI);
    }

    function proposalUpdate(
        address dao,
        string calldata proposalId,
        string calldata proposalURI
    ) public {
        emit ProposalUpdate(msg.sender, dao, proposalId, proposalURI);
    }

    function activityLogUpdate(
        address dao,
        string calldata activityId,
        string calldata activityLogURI
    ) public {
        emit ActivityLogUpdate(msg.sender, dao, activityId, activityLogURI);
    }
}

Edit: Addtional event to handle schema updates
    event SchemaUpdate(
        address indexed sender,
        string indexed indexedSchemaURI,
        string name,
        string description,
        string schemaURI
    );

Author: julesl23
Date: 2022-04-05T21:59:34.034Z

Another point I wish to make about v4 is that the amount of JSON-LD files to write out will be a lot less, as won’t have to update a whole set of files ('cause they are linked) for one change. Only the JSON-LD file that has changed needs to be uploaded now.
This makes memberships that change a lot more possible to keep up to date as just need to call the memberUpdate method of the singleton contract when a member joins, to emit the MemberUpdate event. If a member leaves then can indicate this by simply calling memberUpdate with an empty memberURI string. All this means that DAOs that don’t explicitly keep a record of all members to save gas on storage or other reasons, don’t have to store an array of members in their contract.

Author: julesl23
Date: 2022-04-08T12:48:05.788Z

I have a little time over the weekend to implement this.
That way can examine any potential pitfalls. E.g. do endpoints to blockchain do throttling if there is a lot of event requests?

Author: julesl23
Date: 2022-04-11T21:18:40.043Z

Hi,
I tested out the concept and it met my requirements.
I set up some dummy DAO details called DAO Charity.
2022-04-11 20_09_59-localhost_3100_dao1561×492 11.4 KB
I then called the DAO Caster (provisional name I gave to the smart contract that emits the DAO updates).
Then I set up a dummy DAO discovery service that was able to retrieve the DAOUpdate event and its JSON-LD file. Noticed how the sender account address (msg.sender) is retrieved as it was sent out by the DAOUpdate. Additional information can be obtained from the event, such as the block number the event was emitted:
2022-04-11 20_35_37-localhost_3101_dao646×955 20.8 KB
Next, I set up a new proposal.
2022-04-11 20_36_52-localhost_3100_proposals_createProposal518×1005 22.6 KB
With DAO discovery service, was able to retrieve the proposal details from the proposal event emitted by DAO Caster.
2022-04-11 20_39_07-localhost_3101_proposals645×1132 25.8 KB
Noticed how the JSON-LD file got flagged with “Warning Sender was not a member”. This was achieved by using the sender account address sent out by the DAO Caster ProposalUpdate event to look for MemberUpdate events that had that sender account address. None were found for the block number the proposal was submitted in.
I also added extra details, as seen in the ActivityLog JSON-LD file:
2022-04-11 20_40_03-localhost_3101_activityLogs559×1022 20.7 KB
One extra property is the DAO address that is required for the security checks. Now that the JSON-LD files have sender details and the URI hashed links sent from the emitted events, the JSON-LD files can be checked and verified. I believe this makes the JSON-LD files in this web3 world much more secure and practical to use. Thus increases the security of other JSON-LD files that link to them.
Code for DAO Caster and test apps here: https://github.com/julesl23/DAO-Caster

Author: julesl23
Date: 2022-04-11T21:39:47.850Z

A note, JSON-LD schemas in the web3 world, should be secured on immutable storage and hashed, just like the DAO updates. Hence, DAO Caster has an additional function called schemaUpdate that can be called for when a new or amended schema is uploaded for use.

Author: thelastjosh
Date: 2022-04-15T13:34:30.367Z

Hey @Asgeir and @julesl23 , sorry for the delay in responding!
Some of the other co-authors (Zargham and Isaac) and I recently had a chance to work on this in-person during a conference last week. TL;DR: instead of asking DAOs to interact with the existing Poster contract in order to emit an event describing their daoURI, we will encourage DAOs to deploy a new, thin contract that contains functions to display and manage daoURI. This is similar to one of @Asgeir’s recommendations to deploy a new Poster-like contract. The spec for that contract is written below.
We will also deploy a factory contract to make it easier to deploy these contracts (so in practice the DAO just needs to emit a contract interaction, just as with Poster) and to take care of other “convenience” things like detecting the DAO contract form & deploying an fully-functioning endpoint, but the factory contract will not be part of the specification.
ALSO, in response to comments from one of the EIP editors, we are planning to rename the standard to “EIP-4824 DAO API” (this might help explain the repeated references to “API” in the rationale below).

Rationale
Migrating or upgrading contracts is a nontrivial task, and asking DAOs to migrate contracts just in order to implement the daoURI interface presents a significant barrier to adoption. On the other hand, it is relatively straightforward to ask DAOs to (1) deploy a new “API manager” contract and then (2) verify ownership via a contract interaction with the manager contract. In cases where the new contract is deployed via a contract interaction with a factory contract, the two steps above can be condensed into a single contract interaction.
We also considered allowing DAOs to “post” their daoURI by interacting with an existing contract, e.g. one based on EIP-3772 Poster, in order to emit an event containing the daoURI address. The issue with this option is that daoURI is a key part of a DAO and we believe it should live in DAO’s own contract space and be “self-hosted” rather than be tied to an external contract. Not having control over the daoURI contract also makes it harder to transfer ownership of the DAO’s API due to contract migrations or other events. [side note: Zargham referred to this manager contract as a kind “mutable NFT”]

DAO API Manager Contract Specification
Here’s a complete specification of that contract; we will refine this spec into an actual contract specification that will go into the standard.

Goals

provide DAOs a means of “owning” the URI pointing to their metadata
increase discoverability of the URI from a DAO’s existing contract(s)
allow DAOs the ability to update their metadata (in this case, just daoURI)
provide on-chain transparency for updates to their data


Data Structure

Owner: 
Offer: {ToBeOwner: , Deadline: }
daoURI: 


Restricted Methods (msg sender restriction)
Offer Ownership (OwnerOnly)

assert msg sender is Owner
input message has 1 argument 
optionally we generate block height a “Deadline” after which the offer is timed out
posterior state: ToBeOwner is changed to the argument 
emit a proposed change of ownership event

Claim Ownership (unique state depended address)

assert msg sender is ToBeOwner
++ assert the blockheight is before the deadline (probably using Get Offer Status method below)
input message has no argument
posterior state: Owner is changed to ToBeOwner
emit a change of Owner event

Update URI (OwnerOnly)

assert msg sender is Owner
input message has 1 argument 
posterior state: daoURI is changed to the argument 
emit a change of URI event


Public methods
Get Owner

no restrictions on who can call this method
no arguments required
returns Owner field
intended to run off chain (since it doesn’t mutate the contract state)

Get Offer Status

no restrictions on who can call this method
no arguments required
returns True if the deadline is not past, and false if it has
intended to run off chain (since it doesn’t mutate the contract state)

Get Candidate Owner

no restrictions on who can call this method
no arguments required
returns the 0x000 address (or the current Owner) if get offer status is False
returns the ToBeOwner address if offer status is True
intended to run off chain (since it doesn’t mutate the contract state)

Get daoURI

no restrictions on who can call this method
no arguments required
returns daoURI field
intended to run off chain (since it doesn’t mutate the contract state)

Author: brickpop
Date: 2022-06-16T13:55:29.569Z

Hi there,
This is my first contribution, apologies if I is is slightly out of scope.
I was recently onboarded to the DAOStar initiative in the scope of the Aragon project (@nivida and Michael Heuer) and I found a couple of topics that I would like to gather your feedback from, as they may affect other DAO tooling as well.

Standardised Multi endpoint URL’s
Talking about a DAO API, it seems unavoidable to deal with centralized services. But at the same time, DAO’s are also likely to pin static metadata through IPFS or similar. Centralized + decentralized.
If the value behind daoURI() or any JSON URI field is interpreted at the will of the implementer, there’s a risk that some DAO details can be browsed on one platform but not on another one. What’s the common intuition about endpoints?


https://service.net/file.json (no integrity check)
ipfs://ipns/<ipns-name>/meta.json
ipfs://ipfs/<cid>/meta.json

I Vocdoni we went a bit further back in 2018 and drafted a simple solution that could inspire some standardisation on the DAO API side. Example of an on-chain URL:
ipfs://ipns/<ipns-name>/meta.json,ipfs://ipfs/<cid>,https://server-fallback.net/meta.json!<expected-hash>

Split the URL by commas ,

Try to resolve from left to right
If the https endpoint is fetched, hash the data and compare it to the value after the ! bang symbol (optional)

I would be glad to get your feedback.

Multiple types of membership
Another topic where I’d like your feedback is about the fact that some DAO’s may have more than one membership model in parallel.
Example:

A group of wallets on a multisig can approve Action 1 at any time
A massive group of ERC20 (weighted) holders can approve Action 2 after a two-week vote
People with a valid ZK proof based on off-chain data can vote to approve Action 3

There may be cases in which a flat list of members doesn’t accurately represent de definition of the membership. In some cases it may not even be possible to generate a deterministic list of wallets.
Does this scenario echo with someone else?
Thank you!

Author: thelastjosh
Date: 2022-06-20T01:14:22.773Z

I Vocdoni we went a bit further back in 2018 and drafted a simple solution  that could inspire some standardisation on the DAO API side. Example of an on-chain URL:
ipfs://ipns/<ipns-name>/meta.json,ipfs://ipfs/<cid>,https://server-fallback.net/meta.json!<expected-hash>

This seems very sensible to me, and could be used to designate fallbacks even if we assume DAOs don’t use IPFS. That said, I think this could be a separate standard from EIP-4824. We can, however, start playing around with something like this in our own internal implementations.

There may be cases in which a flat list of members doesn’t accurately represent de definition of the membership. In some cases it may not even be possible to generate a deterministic list of wallets.

Agreed; however, EIP-4824 doesn’t define how DAOs define membership internally, just a mechanism for publishing a list of records. They are free to define multiple membership categories, and then record them via some sort of “category” field in each member record.

Author: brickpop
Date: 2022-06-22T16:21:54.031Z

Thank you for the response Josh,



 thelastjosh:

This seems very sensible to me, and could be used to designate fallbacks even if we assume DAOs don’t use IPFS. That said, I think this could be a separate standard from EIP-4824. We can, however, start playing around with something like this in our own internal implementations.



What would we need for an interim recommendation to eventually be part of the current draft?
What’s the procedure to start a separate EIP? A new post on the Ethereum Magicians forum?




 thelastjosh:

They are free to define multiple membership categories, and then record them via some sort of “category” field in each member record



Then, may it be useful to propose a JSON schema for it and some recommended values? There is already a recommendation about proposal status enum’s, where each DAO framework has its own values. Maybe there can be a similar thing with categories?
Regarding endpoints tied to a backend (members, activity), would it make sense to suggest a pagination mechanism? The list of all USDC token holders may be quite large.


I’d also like to ask about another topic regarding metadata contents, like a DAO’s description. Is there consensus about how description texts should be interpreted?

Plain text, wrapped.
Plain text, transforming line breaks
Plain text, converting line breaks into paragraphs
Markdown (restricted subset)
Markdown
HTML

Thank you!

Author: crazyrabbitLTC
Date: 2022-10-20T20:30:06.918Z

Hey folks! Wanting to check back in on this.
As a comment, I think we probably shouldn’t include offerOwnership or claimOwnership in the standard. This is a rather opinionated legacy way of defining ownership and not very future proof.
It would be better if rather these kinds of update were instead guarded by roles such as OpenZeppelin Access Control.
This way DAO’s can create ownership sets rather than relying upon a singular master address.

Author: thelastjosh
Date: 2022-10-24T12:11:46.215Z

Just checking, but by offerOwnership or claimOwnership you mean aspects of the on-chain registration contract for managing ownership of daoURI?

Author: parseb
Date: 2022-10-31T09:27:44.303Z

Wrote a lot more; but I don’t want to waste your time. In short: Please keep it assumption free.
Source of worry: this seems to assume that DAOs necessarily have a proposal system and can only affect themselves and the world through it. While it is true that most DAO frameworks do so, one cannot dismiss the possibility that this common feature is nothing more than a skewmorphic and facile default.

Author: thelastjosh
Date: 2022-10-31T15:56:39.876Z

Source of worry: this seems to assume that DAOs necessarily have a proposal system and can only affect themselves and the world through it. While it is true that most DAO frameworks do so, one cannot dismiss the possibility that this common feature is nothing more than a skewmorphic and facile default.

I very much agree with this @parseb ; in practice there are plenty of ways for a DAO to affect the real world / blockchain state without going through a formal proposal system (as we typically imagine it), e.g. depending on the contract, a behind-the-scenes administrator or multisig might execute actions without putting it to any kind of vote or approval process. In general, we expect DAOs adopting the standard to publish daoURI and deploy a registration contract. Those who don’t have conventional proposals will certainly not maintain a proposalsURI endpoint, which is fine.
It would be nice to standardize what it means to have a proposal system, so we can always and easily verify that when a contract action executes, it DID go through a formal proposal system rather than through some other execution authority.

Author: thelastjosh
Date: 2022-10-31T15:56:51.682Z

ALSO, @crazyrabbitLTC in response to your question @izkp and @mzargham are going to write a blog post answering the access control / roles question in more detail. Will post here once that’s written.

Author: izkp
Date: 2022-11-15T14:45:20.760Z

Just opened a PR on the EIP repo suggesting that we add a contract registry field. This would allow DAOs to tag other relevant contracts besides their main executor


GitHub



Comparing ethereum:master...ipatka:patch-1 · ethereum/EIPs
The Ethereum Improvement Proposal repository. Contribute to ethereum/EIPs development by creating an account on GitHub.





For example, a Nouns style DAO consists of the following contracts which should all be tagged:

ERC721 governance token
Treasury
Logic contract
Upgradeable proxies
Core team
Veto committee

I am recommending we add this as another URI, contractsRegistryURI
{
    "@context": "<http://www.daostar.org/schemas>",
    "type": "DAO",
    "name": "<name of the DAO>",
    "contracts": [
        {
            "type": "EthereumAddress",
            "id": "<address or other identifier>",
						"label": "Treasury"
        },
        {
            "type": "EthereumAddress",
            "id": "<address or other identifier>",
						"label": "Governance Token"
        }
    ]
}

Author: izkp
Date: 2022-11-15T16:28:48.975Z

I updated it to use OZ access control. Thanks for the recommendation

github.com


metagov/daostar/blob/23e8fa6722217154ffb38a5ff0631f6342b30f2a/contracts/src/Registration.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

import {AccessControl} from "openzeppelin/access/AccessControl.sol";
import {Clones} from "openzeppelin/proxy/Clones.sol";

/// @title EIP-4824 DAOs
/// @dev See <https://eips.ethereum.org/EIPS/eip-4824>
interface EIP4824 {
    /// @notice A distinct Uniform Resource Identifier (URI) pointing to a JSON object following the "EIP-4824 DAO JSON-LD Schema". This JSON file splits into four URIs: membersURI, proposalsURI, activityLogURI, and governanceURI. The membersURI should point to a JSON file that conforms to the "EIP-4824 Members JSON-LD Schema". The proposalsURI should point to a JSON file that conforms to the "EIP-4824 Proposals JSON-LD Schema". The activityLogURI should point to a JSON file that conforms to the "EIP-4824 Activity Log JSON-LD Schema". The governanceURI should point to a flatfile, normatively a .md file. Each of the JSON files named above can be statically-hosted or dynamically-generated.
    function daoURI() external view returns (string memory _daoURI);
}

error NotDaoOrManager();
error NotDao();
error NotCandidate();
error AlreadyInitialized();
error OfferExpired();

/// @title EIP-4824: DAO Registration




  This file has been truncated. show original

Author: izkp
Date: 2023-04-27T02:23:23.786Z

The current spec does not enable easy indexing across different DAO factories. DAO factories which implement 4824 interfaces may emit their own events to create and update DAO URIs but the original spec does not specify the event format in the interface.
One potential solution is to:

Update the spec interface to specify a standard event
Add a ‘minimal registration’ contract which simply allows other factories to emit an event


Event update
pragma solidity ^0.8.1;

/// @title EIP-4824 Common Interfaces for DAOs
/// @dev See https://eips.ethereum.org/EIPS/eip-4824

interface EIP4824 {

	event DAOURIUpdated(address daoAddress, string daoURI);

    /// @notice A distinct Uniform Resource Identifier (URI) pointing to a JSON object following the "EIP-4824 DAO JSON-LD Schema". This JSON file splits into four URIs: membersURI, proposalsURI, activityLogURI, and governanceURI. The membersURI should point to a JSON file that conforms to the "EIP-4824 Members JSON-LD Schema". The proposalsURI should point to a JSON file that conforms to the "EIP-4824 Proposals JSON-LD Schema". The activityLogURI should point to a JSON file that conforms to the "EIP-4824 Activity Log JSON-LD Schema". The governanceURI should point to a flatfile, normatively a .md file. Each of the JSON files named above can be statically-hosted or dynamically-generated.
    function daoURI() external view returns (string _daoURI);
}


Minimal registration contract
Other factories can call ‘logRegistration’ during their deployment. The function would have to be called from the new DAO. In Safes and Moloch v3 there are initialization actions which are called on setup. Other DAO frameworks probably do too.
contract EIP4824MinimalRegistrationLog {
    event DAOURIUpdate(address daoAddress, string daoURI);

    mapping(address => string) public daoURIs;

    constructor() {}

    function logRegistration(string calldata daoURI_) external {
        daoURIs[msg.sender] = daoURI_;
        emit DAOURIUpdate(msg.sender, daoURI_); // Require to be called by DAO itself. Can be called as many times as desired
    }
}



Open Questions/ thoughts (to be addressed on next DAOstar working group call)
How does this minimal registration contract compare with the existing registration contract factory? The registration contract factory includes additional features for allowing managers/ subDAOs to update the URI. Is this redundant.
Why not just have the other DAO factories call the original summoner?
Perhaps a better solution would be to use this registration log as a top level indexer which would inform a subgraph, or other indexer which other contracts to monitor for future URI updates. That way the DAO does not need to manage the URI in multiple places.

Author: thelastjosh
Date: 2023-04-27T16:11:15.360Z

izkp:

    I am recommending we add this as another URI, contractsRegistryURI



What do you think about having this as a separate DAOIP rather than as part of 4824? Or is to germane enough that we think all DAOs will need this? I think it could go either way. There are probably some complexities to reporting contract architectures, plus we may want to even track this as attestations of some sort by the DAO.

Author: thelastjosh
Date: 2023-04-27T16:35:17.978Z

After today’s working group session, Isaac and I came up with the following approach, featuring two approaches to registration:

for pre-4824 DAOs, the standard registration contract approach that is already in the standard
for 4824-native DAOs (deployed with the daoURI interface), a minimal registrationLog indexer

In addition to a slightly modified version of Isaac’s code above, here’s the expected addition to the standard:

When a 4824-native DAO factory deploys a 4824-native DAO, the DAO factory SHOULD incorporate a call to logRegistration as part of the DAO’s initialization. If the DAO is ERC-165 compliant, the factory can do this without additional permissions. If it is not, the factory SHOULD first obtain access control rights to the logRegistration contract and then call logRegistration directly with the address of the new DAO and the daoURI of the new DAO.
Any user, including the DAO itself, MAY call logRegistration and submit a registration for a DAO which is both 4824-native and ERC-165 compliant.

Note that we have revised the registration factory for pre-4824 DAOs to also call the minimal indexer contract.
See architecture diagram below.
The plans for DAOstar One - Overview of Architecture1688×1297 171 KB
Some remaining unresolved issues:

If we need to implement a blacklist / deletions, should we implement that at the indexer level on-chain or at the subgraph level?
What governance, if any, needs to be attached to the indexer? We probably do not need to specify that in the standard itself.

Author: thelastjosh
Date: 2023-04-27T17:17:28.199Z

Just noting that, in the new draft PR, we have added a SHOULD recommendation for access control in the registration contract, without requiring OZ access control. We also added a slightly obvious condition, that a DAO inheriting the EIP4824 interface SHOULD implement a method for updating it.

Author: peersky
Date: 2023-05-12T08:27:18.297Z

Hi @thelastjosh ! Tim from OpenZeppelin here.
Few thoughts from my side:

Perhaps there is just a need for standard of SC URIs
daoURI is just being one of them:

There are tokenURI in ERC721
OpenSea uses contractURI for ERC1155 contract URI
OpenZeppelin ERC1155Metadata specifies token URI’s in uri function.

Besides that, there are also EIPs in different stages, including Last Call also specifying URIs:


*EIP-5169 with scriptURI*
Wallet connect  discusses ERC-1328 with URI for WC, which also could be stored in SCs

*EIP-1046 proposes to add tokenURI to ERC20/1155/721 tokens as a requirement*

Perhaps it would make sense to come up with standard for one and only one Smart Contract URI.
Such could potentially be written in a such way that it can point to on-chain data as well as off-chain
I believe that it is still very important to define schemas in a standard. ERC seems like way to go today however I’m wondering if there could be any way that we could define a maintainable registry of Ethereum schemas AND offload EIP registry from need to review these schemas (that would allow ecosystem to develop more quickly)

Few concerns regarding schema

Risks of centralization
Introducing single endpoint for proposalsURI brings in centralization risks. Right now in OpenZeppelin Governor, proposer can set his own proposal URI with IPFS link describing the proposal.
If there is single proposalsURI it brings in concerns of who controls that endpoint.

URI objects proposed should have block numbers
Objects such as membersURI proposed by this EIP can be out-of sync with blockchain state.
I can see in the discussion that this might be out of scope to keep as much DAO specific as possible.
However I would argue that Members object in my understanding can be only relevant to a particular time, as a constantly changing value.
As a potential use-case is ERC20Voting which implements snapshots, if there would be a block number appended to the membersURI it would allow DAO frontends to render voting power purely from URI object, without querying blockchain at all.

Author: thelastjosh
Date: 2023-05-14T00:07:41.491Z

Thanks for the comment Tim! Just checking, but I believe we already share some Telegram channels, right? Would love to follow-up with your suggestions in the next engineering chat for 4824.

Perhaps it would make sense to come up with standard for one and only one Smart Contract URI.

I agree that it would be nice to have just a standard smart contract URI for any metadata that a smart contract needs to report. The question is what would you standardize exactly; just that the interfaces all have the same naming format, e.g. tokenURI, contractURI, scriptURI, etc.? Or that they should all share some common namespace so there isn’t conflict?
Note that EAS actually has a system set up to publish Ethereum schemas, at least for attestations (which are pretty generic).

Introducing single endpoint for proposalsURI brings in centralization risks. Right now in OpenZeppelin Governor, proposer can set his own proposal URI with IPFS link describing the proposal.

Interesting idea! I’m not sure this hits the mark though, because proposalsURI is really just an index of the existing proposals in the DAO; each of those proposals can publish an additional URI field that is controlled by the proposer (but this would require some sort of on-chain logic to verify, and proposalsURI is not on-chain). Yes, there is centralization, but that centralization is ultimately inherited from the DAO that controls daoURI.

However I would argue that Members object in my understanding can be only relevant to a particular time, as a constantly changing value.

Agreed.

As a potential use-case is ERC20Voting  which implements snapshots, if there would be a block number appended to the membersURI it would allow DAO frontends to render voting power purely from URI object, without querying blockchain at all.

How does this work? Right now, we’re agreed that membersURI does not allow you calculate a member’s voting power without querying the blockchain. What would appending a single block number do to make this different?

Author: peersky
Date: 2024-09-10T18:20:18.007Z

thelastjosh:

I agree that it would be nice to have just a standard smart contract URI for any metadata that a smart contract needs to report. The question is what would you standardize exactly; just that the interfaces all have the same naming format, e.g. tokenURI, contractURI, scriptURI, etc.? Or that they should all share some common namespace so there isn’t conflict?


@thelastjosh for my delayed respponse, I missed that conversation thread.
Please see my suggestions to ERC7572 and related PR
TLDR: I suggest them to drop out schema requirement, leaving in only contractURI method that could be reused by 4824 as dependency and incorporate your idea of having contract address return field.
Regarding schema itself I find it much less important at the moment than the interface standartisation what is nearly impossible to change in the future.

Author: thelastjosh
Date: 2024-09-18T21:32:24.029Z

Thanks @peersky I hadn’t seen the new 7572 PR.
Agreed, schemas can change faster than the interfaces, ref. DAOIPs.

Author: MJmk2
Date: 2024-10-25T01:18:25.700Z

A great read, thanks for the informative information.

Author: thelastjosh
Date: 2024-11-25T00:37:50.943Z

Hi @Trarda54 I don’t think this is something we can resolve completely in this standard, just as the authors of EIP-721 did not resolve it for tokenURI. We do identify an indexing priority based on different levels of “authenticity” in DAOIP-6.
Would suspect that resolving it would require some incentive via a registry with an enforcement/slashing function for false reports.
If you are interested in digging farther into this problem, consider contributing to a future DAOIP!

Author: galaparm
Date: 2024-12-03T11:41:40.595Z

Could you clarify how the snapshot of membership would work in practice? Specifically, how would it handle updates to the membership list in a decentralized way without requiring constant re-uploading of the entire list? Would it be possible to implement this through a smart contract, or would off-chain solutions still be necessary for real-time updates?

Author: thelastjosh
Date: 2025-02-02T03:34:18.290Z

Could you clarify how the snapshot of membership would work in practice? Specifically, how would it handle updates to the membership list in a decentralized way without requiring constant re-uploading of the entire list?

This EIP does not specify how the contents of membersURI would be updated; it only specifies the method of publishing such a membersURI.

Would it be possible to implement this through a smart contract, or would off-chain solutions still be necessary for real-time updates?

It’s definitely possible to implement a dedicated subgraph for membersURI, which is in fact what we do for certain memberURIs.