Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement snapshot voting #16

Merged
merged 2 commits into from
Jan 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 35 additions & 30 deletions contracts/dao/extensions/aibtc-action-proposals.clar
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
(define-constant ERR_PROPOSAL_STILL_ACTIVE (err u1401))
(define-constant ERR_SAVING_PROPOSAL (err u1402))
(define-constant ERR_PROPOSAL_ALREADY_CONCLUDED (err u1403))
(define-constant ERR_RETRIEVING_START_BLOCK_HASH (err u1404))

;; error messages - voting
(define-constant ERR_VOTE_TOO_SOON (err u1500))
Expand Down Expand Up @@ -180,46 +181,44 @@
(define-public (vote-on-proposal (proposalId uint) (token <ft-trait>) (vote bool))
(let
(
(proposalRecord (unwrap! (map-get? Proposals proposalId) ERR_PROPOSAL_NOT_FOUND))
(proposalBlock (get startBlock proposalRecord))
(proposalBlockHash (unwrap! (get-block-hash proposalBlock) ERR_RETRIEVING_START_BLOCK_HASH))
(tokenContract (contract-of token))
(senderBalance (try! (contract-call? token get-balance tx-sender)))
(senderBalanceResponse (at-block proposalBlockHash (contract-call? .aibtc-token get-balance tx-sender)))
(senderBalance (unwrap-panic senderBalanceResponse))
)
;; required variables must be set
(asserts! (is-initialized) ERR_NOT_INITIALIZED)
;; token matches set voting token
(asserts! (is-eq tokenContract (var-get votingToken)) ERR_TOKEN_MISMATCH)
;; caller has the required balance
(asserts! (> senderBalance u0) ERR_INSUFFICIENT_BALANCE)
;; get proposal record
(let
(
(proposalRecord (unwrap! (map-get? Proposals proposalId) ERR_PROPOSAL_NOT_FOUND))
)
;; proposal is still active
(asserts! (>= burn-block-height (get startBlock proposalRecord)) ERR_VOTE_TOO_SOON)
(asserts! (< burn-block-height (get endBlock proposalRecord)) ERR_VOTE_TOO_LATE)
;; proposal not already concluded
(asserts! (not (get concluded proposalRecord)) ERR_PROPOSAL_ALREADY_CONCLUDED)
;; vote not already cast
(asserts! (is-none (map-get? VotingRecords {proposalId: proposalId, voter: tx-sender})) ERR_ALREADY_VOTED)
;; print vote event
(print {
notification: "vote-on-proposal",
payload: {
proposalId: proposalId,
voter: tx-sender,
amount: senderBalance
}
})
;; update the proposal record
(map-set Proposals proposalId
(if vote
(merge proposalRecord {votesFor: (+ (get votesFor proposalRecord) senderBalance)})
(merge proposalRecord {votesAgainst: (+ (get votesAgainst proposalRecord) senderBalance)})
)
;; proposal is still active
(asserts! (>= burn-block-height (get startBlock proposalRecord)) ERR_VOTE_TOO_SOON)
(asserts! (< burn-block-height (get endBlock proposalRecord)) ERR_VOTE_TOO_LATE)
;; proposal not already concluded
(asserts! (not (get concluded proposalRecord)) ERR_PROPOSAL_ALREADY_CONCLUDED)
;; vote not already cast
(asserts! (is-none (map-get? VotingRecords {proposalId: proposalId, voter: tx-sender})) ERR_ALREADY_VOTED)
;; print vote event
(print {
notification: "vote-on-proposal",
payload: {
proposalId: proposalId,
voter: tx-sender,
amount: senderBalance
}
})
;; update the proposal record
(map-set Proposals proposalId
(if vote
(merge proposalRecord {votesFor: (+ (get votesFor proposalRecord) senderBalance)})
(merge proposalRecord {votesAgainst: (+ (get votesAgainst proposalRecord) senderBalance)})
)
;; record the vote for the sender
(ok (map-set VotingRecords {proposalId: proposalId, voter: tx-sender} senderBalance))
)
;; record the vote for the sender
(ok (map-set VotingRecords {proposalId: proposalId, voter: tx-sender} senderBalance))
)
)

Expand All @@ -235,6 +234,8 @@
)
;; required variables must be set
(asserts! (is-initialized) ERR_NOT_INITIALIZED)
;; verify extension still active in dao
(try! (as-contract (is-dao-or-extension)))
;; verify treasury matches protocol treasury
(asserts! (is-eq treasuryContract (var-get protocolTreasury)) ERR_TREASURY_MISMATCH)
;; proposal past end block height
Expand Down Expand Up @@ -320,3 +321,7 @@
))
)

;; get block hash by height
(define-private (get-block-hash (blockHeight uint))
(get-block-info? id-header-hash blockHeight)
)
11 changes: 10 additions & 1 deletion contracts/dao/extensions/aibtc-core-proposals.clar
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
(define-constant ERR_PROPOSAL_STILL_ACTIVE (err u3402))
(define-constant ERR_SAVING_PROPOSAL (err u3403))
(define-constant ERR_PROPOSAL_ALREADY_CONCLUDED (err u3404))
(define-constant ERR_RETRIEVING_START_BLOCK_HASH (err u3405))

;; error messages - voting
(define-constant ERR_VOTE_TOO_SOON (err u3500))
Expand Down Expand Up @@ -172,8 +173,11 @@
(
(proposalContract (contract-of proposal))
(proposalRecord (unwrap! (map-get? Proposals proposalContract) ERR_PROPOSAL_NOT_FOUND))
(proposalBlock (get startBlock proposalRecord))
(proposalBlockHash (unwrap! (get-block-hash proposalBlock) ERR_RETRIEVING_START_BLOCK_HASH))
(tokenContract (contract-of token))
(senderBalance (try! (contract-call? token get-balance tx-sender)))
(senderBalanceResponse (at-block proposalBlockHash (contract-call? .aibtc-token get-balance tx-sender)))
(senderBalance (unwrap-panic senderBalanceResponse))
)
;; required variables must be set
(asserts! (is-initialized) ERR_NOT_INITIALIZED)
Expand Down Expand Up @@ -303,3 +307,8 @@
(contract-call? .aibtcdev-base-dao is-extension contract-caller)) ERR_NOT_DAO_OR_EXTENSION
))
)

;; get block hash by height
(define-private (get-block-hash (blockHeight uint))
(get-block-info? id-header-hash blockHeight)
)
Loading