-
Notifications
You must be signed in to change notification settings - Fork 212
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat!: add a claimsRegistrar based on attestations (#3622)
* feat!: use contractGovernor to govern Treasury using ParamManager extract params to a separate file integrate contract governance into treasury swingset test for treasury governance closes #3189 closes #3473 * chore: minor cleanups: drop extra logs, standardize asserts, tsc fix * chore: improve typescript declarations * feat: add noAction electorate for assurance of no governance changes * chore: validate() in test checks the installations * fix: import types.js into params so bundle is usable in tests * feat!: add a claimsRegistrar based on attestations Agents who can deposit an attestation payment will get the ability to vote that amount. refactor common registrat code to a library tests that BinaryBallotCounter can count these votes. * chore: review sugestions: types, cleanups, comments * chore: better type decls, capitalize handles more handles have capitalized names than not. Suggestions from #3932 * fix: remove spurious distinction in naming of Liquidity keyword * fix: handle<'attestation'> ==> Handle<'Attestation'> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
- Loading branch information
1 parent
c19f141
commit 3acf78d
Showing
19 changed files
with
636 additions
and
102 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
// @ts-check | ||
|
||
import { E } from '@agoric/eventual-send'; | ||
import { Far } from '@agoric/marshal'; | ||
import { makeSubscriptionKit } from '@agoric/notifier'; | ||
import { makeStore } from '@agoric/store'; | ||
import { AmountMath, AssetKind } from '@agoric/ertp'; | ||
import { | ||
startCounter, | ||
getOpenQuestions, | ||
getQuestion, | ||
getPoserInvitation, | ||
} from './electorateTools'; | ||
|
||
const { details: X } = assert; | ||
|
||
// shareHolders is an Electorate that relies on an attestation contract to | ||
// validate ownership of voting shares. The electorate provides voting facets | ||
// corresponding to the attestations to ensure that only valid holders of shares | ||
// have the ability to vote. | ||
|
||
// The attestation contract is responsible for ensuring that each votable share | ||
// has a persistent handle that survives through extending the duration of the | ||
// lien and augmenting the number of shares it represents. This contract makes | ||
// that persistent handle visible to ballotCounters. | ||
|
||
/** @type {ContractStartFn} */ | ||
const start = zcf => { | ||
const { | ||
brands: { Attestation: attestationBrand }, | ||
} = zcf.getTerms(); | ||
const empty = AmountMath.makeEmpty(attestationBrand, AssetKind.SET); | ||
|
||
/** @type {Store<Handle<'Question'>, QuestionRecord>} */ | ||
const allQuestions = makeStore('Question'); | ||
const { subscription, publication } = makeSubscriptionKit(); | ||
|
||
/** @param { SetValue } attestations */ | ||
const makeVoterInvitation = attestations => { | ||
// TODO: The UI will probably want something better, but I don't know what. | ||
const voterDescription = attestations.reduce((desc, amount) => { | ||
const { address, amountLiened } = amount; | ||
return `${desc} ${address}/${amountLiened}`; | ||
}, 'Address/Amount:'); | ||
|
||
// The electorate doesn't know the clock, but it believes the times are | ||
// comparable between the clock for voting deadlines and lien expirations. | ||
|
||
return Far(`a voter ${voterDescription}`, { | ||
/** | ||
* @param {Handle<'Question'>} questionHandle | ||
* @param {Position[]} positions | ||
*/ | ||
castBallotFor: (questionHandle, positions) => { | ||
const { voteCap, deadline } = allQuestions.get(questionHandle); | ||
return attestations | ||
.filter(({ expiration }) => expiration > deadline) | ||
.forEach(({ amountLiened, handle }) => { | ||
return E(voteCap).submitVote(handle, positions, amountLiened); | ||
}); | ||
}, | ||
}); | ||
}; | ||
|
||
/** @type {OfferHandler} */ | ||
const vote = seat => { | ||
/** @type {Amount} */ | ||
const attestation = seat.getAmountAllocated('Attestation'); | ||
assert( | ||
AmountMath.isGTE(attestation, empty, attestationBrand), | ||
X`There was no attestation escrowed`, | ||
); | ||
// Give the user their attestation payment back | ||
seat.exit(); | ||
|
||
assert.typeof(attestation.value, 'object'); // entailed by isGTE on empty SET | ||
return makeVoterInvitation(attestation.value); | ||
}; | ||
|
||
/** @type {AddQuestion} */ | ||
const addQuestion = async (voteCounter, questionSpec) => { | ||
return startCounter( | ||
zcf, | ||
questionSpec, | ||
0n, | ||
voteCounter, | ||
allQuestions, | ||
publication, | ||
); | ||
}; | ||
|
||
/** @type {ClaimsElectoratePublic} */ | ||
const publicFacet = Far('publicFacet', { | ||
getQuestionSubscription: () => subscription, | ||
getOpenQuestions: () => getOpenQuestions(allQuestions), | ||
getInstance: zcf.getInstance, | ||
getQuestion: handle => getQuestion(handle, allQuestions), | ||
makeVoterInvitation: () => zcf.makeInvitation(vote, 'attestation vote'), | ||
}); | ||
|
||
/** @type {ShareholdersCreatorFacet} */ | ||
const creatorFacet = Far('creatorFacet', { | ||
getPoserInvitation: () => getPoserInvitation(zcf, addQuestion), | ||
addQuestion, | ||
getQuestionSubscription: () => subscription, | ||
getPublicFacet: () => publicFacet, | ||
}); | ||
|
||
return { publicFacet, creatorFacet }; | ||
}; | ||
|
||
harden(start); | ||
export { start }; |
Oops, something went wrong.