Closed anilhelvaci closed 2 years ago
These are notes that I'm leaving to myself as I'm exploring the
governace
package.
getParamMgrRetriever
, what does this return?ElectionType.offer_filter
needs further explanation- When governing an API invocation, how do we see the arguments that will be passed to the API to be invoked?
- a property called
methodArgs
is present insideissue
object.- When opening a question on whether or not mark an asset as collateral, does it make sense to open this question with the ElectionType as an api_invocation or a param_change?
- Who holds the
contractGovernor
'screatorFacet
?- How can a simple voter get to vote on a question?
- Logic behind
electrateTools/getPoserInvitation
?- Structure of
offerConfig
formakeVoteInvitation
?- How do voters get the
questionHandle
? Is there another way other than usinggetOpenQuestions
?- How does the
poserInvitation
get updated? Related MethodsgetUpdatedPoserFacet
- What happens if I use
paramChangeSpec
that does not have a[CONTRACT_ELECTORATE]
property?
Below is the initial design I've come to after going over Agoric's existing governance package and Compound Finance's governance method.
I'll refer to the governance token as GOV. This name is arbitrary, might change later.
The general rules around the initial governance design is;
The way I'm planning to implement above behaviors in agoric-sdk governance package is;
Users should lock their GOV tokens inside a ZCFSeat so that we're sure they actually have those tokens.
The existing implementation of the an Electorate is the committee.js contract which stores all posed questions in a map that has structure like this;
const allQuestions = MapStore<QuestionHandle, VoteCounterFacets>
Since users will lock their GOV tokens into our contract we're gonna have to use a ZCFSeat
to escrow those tokens. The way I imagine how to integrate a ZCFSeat
into the existing structure above is;
/**
@type {{
voteCounterFacet: VoteCounterFacet,
tokenSeat: ZCFSeat
}} QuestionFacet
*/
const allQuestions = MapStore<QuestionHandle, QuestionFacet>
To achieve desired behavior a collection of methods like below should be implemented;
const verifyCanPoseQuestion = () => {
// Checks if the user has enough GOV tokens to pose a question. This method will be added to the existing `addQuestion` implementation in the committee contract.
};
const vote = (questionHandle) => {
// Enables users to vote on a particular question at a the weight they posses GOV tokens.
};
const redeem = (questionHandle) => {
// Lets users redeem the GOV tokens they locked for a particular question.
};
const electorateFacet = {
addQuestion,
vote,
redeem,
};
const creatorFacet = {
.
.
.
getElectorateFacetInvitation: () => getElectorateFacetInvitation(zcf, electorateFacet), // See ElectorateTools
};
This module is gonna be like the existing ElectorateTools but we'll store this in our package and will implement required utility methods for our Electorate here. One obvious method is;
/**
* @param {ZCF} zcf
* @param {ElectorateFacet} electorateFacet
*/
const getElectorateFacetInvitation = (zcf, electorateFacet) => {
const electorateFacetHandler = () => Far(`questionPoser`, electorateFacet);
return zcf.makeInvitation(electorateFacetHandler, `electorateFacet`);
};
Work_In_Progress
Below is a very high level overview of the design that aims to show which methods will be added to which component.
getParamMgrRetriever, what does this return?
See README.md
ElectionType.offer_filter needs further explanation
Zoe now has filters that allow a contract or its governance to limit which offers can be exercised. The purpose of this is to allow governance to disable access to the contract in emergencies. My apologies that this hasn't been added to the documentation yet.
https://github.com/Agoric/agoric-sdk/commit/732e229ca5d3f3bb196b8bcaa442be3f03f99a62
Who holds the contractGovernor's creatorFacet?
Our bootstrap environment holds those. I suspect this is insufficiently documented. You might ask about it in office hours.
How can a simple voter get to vote on a question?
Their voterFacet can be used to cast ballots on questions they know about. The harder question is how they come to know about votes in progress. The committee's publicFacet has a questionSubscriber
that notifies about new questions, and a getOpenQuestions()
method that allows one to ask directly. Our voting UI makes use of these.
Logic behind electrateTools/getPoserInvitation?
The creatorFacet in committee.js has a method getPoserInvitation()
that allows its caller to get an invitation that can be used to create a new question that the electorate can vote on. When the committee is controlled by an electionManager (e.g. psmCharter.js) that method is tightly held and only a limited set of people can invoke it.
Users should lock their GOV tokens inside a ZCFSeat so that we're sure they actually have those tokens.
I recommend following the attestation model. This allows holders of some tokens to get attestations that they can use to vote and doesn't require locking up the tokens.
Thanks @Chris-Hibbert !!!
How does the attestation module know that the user actually has the assets they're trying to make an attestation for?
attMaker
object lives inside lib-wallet
module. So I believe it's safe to assume wallet does some kind of checking before creating the attestation. But I haven't been able to find the related code for this. Keep digging. lienBridge
seems like it's connected to the cosmos layer. This is my understanding after reading the README for the stakeFactory
package. This might not be the actual case but still struggling to understand what lienBridge
is actually good for.
Looks like lienBridge
is the actual mechanism that checks if the user actually has the assets they want to create attestation
for. I can see from the code that it connects to a lower level layer and queries the state of a particular asset, implicated by its brand, and from that state attMaker
decides it can create an attestation
for that asset or not. lienBridge
depends on a brand
object and a bridgeManager
object and that bridgeManager
depends on a bridgeDevice
object in order to connect to lower level layer I mentioned earlier. This whole mechanism is mostly used for stakeFactory
so the brand
here is BLD. The process of creating the lienBridge
of the correct brand
, BLD, and accessing the bridgeManager
is handled during bootstrap. This makes sense because stakeFactory
is part of the inter-protocol. But in our case we need a attMaker
and therefore a lienBridge
for our own GOV brand, this makes me skeptical about below topics;
bridgeManager
or bridgeDevice
from a deploy script?attMaker
and therefore lienBridge
objects for my own governance token like here?Where should we create the attestationFacets
: Electorate, ElectionManager or the governedContract(LendingPool)?
Related Code my-lien.js attestation.js bridge.js attestation/test-userFlow.js
I'd be glad if you could answer above questions 🙏 @Chris-Hibbert @dckc
- how can I create the
attMaker
and thereforelienBridge
objects for my own governance token?
The lienBridge
makes sense only for tokens where an ERTP brand (such as BLD) represents a cosmos denom (such as ubld
). Does the GOV token necessarily have a cosmos denom?
If so, then it would make sense to expand makeStakeReporter
to work not just for BLD but for all brands registered with E(bankManager).addAsset(). Then the home.attMaker
would work for GOV as well as BLD, provided GOV is registered.
- As a dApp developer do I have access to a
bridgeManager
orbridgeDevice
from a deploy script?
No; that would allow dApp developers to interfere with chain-wide services.
- Where should we create the
attestationFacets
: Electorate, ElectionManager or the governedContract(LendingPool)?
Probably LendingPool. @Chris-Hibbert , does that make sense to you?
Another possibility is a separate contract. BLD Boost was originally a separate contract from the attestation maker, but we folded them together to simplify some things. I can probably dig up the separate contract and you might want to use that.
Where should we create the attestationFacets: Electorate, ElectionManager or the governedContract(LendingPool)? Probably LendingPool. @Chris-Hibbert , does that make sense to you?
certainly not the electorate or electionManager. Whatever can validate ownership of the underlying token, which makes some sense for the lendingPool.
Another possibility is a separate contract. BLD Boost was originally a separate contract from the attestation maker, but we folded them together to simplify some things. I can probably dig up the separate contract and you might want to use that.
Yes, that would be helpful. I recall the original version (or at least an earlier version) having tests that started with assets created in the JS layer.
Anil Helvaci => Found it: https://github.com/Agoric/agoric-sdk/pull/3475
The lienBridge makes sense only for tokens where an ERTP brand (such as BLD) represents a cosmos denom (such as ubld). Does the GOV token necessarily have a cosmos denom?
I don't know what it means for an ERTP brand to represent a cosmos denom @dckc. What I had in mind is a simple ERTP fungible token created with zcf.makeZCFMint()
. If having a cosmos denom just means that it should have 6 decimal places like BLD then I can definitely do that. But according to:
If so, then it would make sense to expand makeStakeReporter to work not just for BLD but for all brands registered with E(bankManager).addAsset(). Then the home.attMaker would work for GOV as well as BLD, provided GOV is registered.
Requires some changes to the agoric-sdk
as well and waiting for this change to come alive probably going to block me for some time.
Another possibility is a separate contract. BLD Boost was originally a separate contract from the attestation maker, but we folded them together to simplify some things. I can probably dig up the separate contract and you might want to use that.
Yes, that would be helpful. I recall the original version (or at least an earlier version) having tests that started with assets created in the JS layer.
This seems like a quicker approach. I would be so glad if you could provide me the separate contract and the tests you mention here.
I want to sum up what I understand just to make sure we're on the same page;
There's no way I can use the attestation
module as it is right now to mint attestations for fungible assets created with zcf.makeZCFMint
or makeIssuerKit
. To make it work the brand has to have a cosmos denom and makeStakeReporter
should be expanded to work with ERTP assets that have cosmos denom so that home.attMaker
can create attestations
for those assets.
Another possible way is to use a separate contract. The samples shall be provided.
Am I correct? @Chris-Hibbert @dckc ?
I'm still not sure how this separate contract will make sure users actually have the GOV tokens without making them lock their GOV tokens?
The lienBridge makes sense only for tokens where an ERTP brand (such as BLD) represents a cosmos denom (such as ubld). Does the GOV token necessarily have a cosmos denom?
I don't know what it means for an ERTP brand to represent a cosmos denom @dckc. What I had in mind is a simple ERTP fungible token created with
zcf.makeZCFMint()
.
Oops. I'm afraid the whole discussion of attestations has been a red herring. You did say that you plan for users to put their tokens in escrow with Zoe in order to prove ownership. Attestations are a way to avoid that, since BLD boost is designed to let people participate without transferring their BLD tokens to Zoe.
You did say that you plan for users to put their tokens in escrow with Zoe in order to prove ownership. Attestations are a way to avoid that, since BLD boost is designed to let people participate without transferring their BLD tokens to Zoe.
I need to make sure users have the governance token of my protocol before I let them do any governance action. One possible solution I had in mind was to escrow the tokens in Zoe. But this is not mandatory I just need to make sure they have the tokens. You and Chris suggested attestations saying that it is more flexible and users might need their tokens for something else. This makes sense to me. But from what I can understand; attestations, as they are right now, only work for BLD brand and no other ERTP brand. If there's a solution for this, I want to use attestations for governance tokens distributed from lending protocol.
The attestations used in BLD boost attest that some cosmos-level tokens have a lien against them.
In order to get further in this discussion, I suppose we need to clear this up...
I don't know what it means for an ERTP brand to represent a cosmos denom @dckc.
I'm not sure how to do that briefly. Perhaps in office hours tomorrow?
I'm not sure how to do that briefly. Perhaps in office hours tomorrow?
That'd be great, looking forward to it!
Electorate
need to be a contract or can it be just a js module? @Chris-Hibbert @Chris-Hibbert says it has to be a contract
ref: coreArchitecture.png (office hours recording to appear)
In this session of the office hours it has been clarified that there's no easy way for an ordinary ERTP token can be attested. So moving forward with the escrowing strategy.
feature/governance-voting
As a result of the conversation above and my own work, I've made the below design
src/lendingPoolElectorate.js
Mostly similar to the committee.js
but lets users do weighted voting. Has two additional methods to the poserFacet
;
electorateFacet
(replaces poserFacet) to the ElectionManager
, to let users vote by escrowing their GOV tokens. The value
in the escrowed amount is the share(weight) argument in the submitVote
method of the binaryCounter.js
.binaryCounter.js
needs to know the total number of votes in order to calculate a quorum
threshold. In our case the total number of votes is interpreted as total number of shares
. We use this method to let the electorate know about the total governance token supply so that it can ask the question with the correct quorum threshold.src/lendingPoolElectionManager.js
Contains the escrowing logic. Has its own ERTP NFT called POP(Proof of Participation). So that users can redeem their escrowed tokens. Exposes addQuestion
and voteOnQuestion
methods in its public facet and makes decisions according to the amount of assets escrowed.
vote
flag in the offerArgs
and if it is true
we vote with their escrowed weight to the positive
position. We assume if one asks a question they wouldn't want to vote Against
their own question.test/governanceAssertions.js and test/governanceScenarioHelpers.js Contain helper methods for unit tests to avoid code reuse and maintain cleaner tests.
Requirements
The parameters to be controlled by governance are listed in the bounty specification. Seems like they all can be controlled by one
ParamManager
controlled by acontractHelper
.Current Structure
There's a
ParamManager
for every pool in the protocol. TheseParamManager
s are stored in theLendingPool
contract. Ideally I want to use the contractHelper.js but not sure how I can make that happen in a scenario where we are required to update the parameters that are directly related to pools.Steps