Skip to content

Commit

Permalink
Merge pull request #42 from portto/dao-new
Browse files Browse the repository at this point in the history
Update DAO contract and add admin transactions
  • Loading branch information
boczeratul authored Jan 5, 2022
2 parents 0dc1ddd + 756cda4 commit e1e0f1d
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 15 deletions.
57 changes: 42 additions & 15 deletions contracts/flow/dao/BloctoDAO.cdc
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,13 @@ import BloctoToken from "../token/BloctoToken.cdc"

pub contract BloctoDAO {
access(contract) var topics: [Topic]
access(contract) var votedRecords: [{ Address: Int }]
access(contract) var totalTopics: Int

pub let AdminStoragePath: StoragePath;
pub let VoterStoragePath: StoragePath;
pub let VoterPublicPath: PublicPath;
pub let VoterPath: PrivatePath;

pub enum CountStatus: UInt8 {
pub case invalid
Expand All @@ -34,7 +39,10 @@ pub contract BloctoDAO {
endAt: endAt,
minVoteStakingAmount: minVoteStakingAmount
))
BloctoDAO.votedRecords.append({})
BloctoDAO.totalTopics = BloctoDAO.totalTopics + 1
}

pub fun updateTopic(id: Int, title: String?, description: String?, startAt: UFix64?, endAt: UFix64?, voided: Bool?) {
pre {
BloctoDAO.topics[id].proposer == self.owner!.address: "Only original proposer can update"
Expand All @@ -50,11 +58,16 @@ pub contract BloctoDAO {
}
}

// Voter resource holder can vote on topics
pub resource Voter {
pub resource interface VoterPublic {
// voted topic id <-> options index mapping
pub fun getVotedOption(topicId: UInt64): Int?
pub fun getVotedOptions(): { UInt64: Int }
}

// Voter resource holder can vote on topics
pub resource Voter: VoterPublic {
access(self) var records: { UInt64: Int }

pub fun vote(topicId: UInt64, optionIndex: Int) {
pre {
self.records[topicId] == nil: "Already voted"
Expand All @@ -66,7 +79,11 @@ pub contract BloctoDAO {

pub fun getVotedOption(topicId: UInt64): Int? {
return self.records[topicId]
}
}

pub fun getVotedOptions(): { UInt64: Int } {
return self.records
}

init() {
self.records = {}
Expand All @@ -86,14 +103,13 @@ pub contract BloctoDAO {
}

pub struct Topic {
pub let id: Int;
pub let proposer: Address
pub var title: String
pub var description: String
pub let minVoteStakingAmount: UFix64

pub var options: [String]
// address <-> address selected options index mapping
access(self) var voted: { Address: Int }
// options index <-> result mapping
pub var votesCountActual: [UFix64]

Expand All @@ -120,10 +136,12 @@ pub contract BloctoDAO {
self.description = description
self.minVoteStakingAmount = minVoteStakingAmount != nil ? minVoteStakingAmount! : 0.0
self.votesCountActual = []

for option in options {
self.votesCountActual.append(0.0)
}
self.voted = {}

self.id = BloctoDAO.totalTopics

self.sealed = false
self.countIndex = 0
Expand Down Expand Up @@ -157,14 +175,14 @@ pub contract BloctoDAO {
pre {
self.isStarted(): "Vote not started"
!self.isEnded(): "Vote ended"
self.voted[voterAddr] == nil: "Already voted"
BloctoDAO.votedRecords[self.id][voterAddr] == nil: "Already voted"
}

let voterStaked = BloctoDAO.getStakedBLT(address: voterAddr)

assert(voterStaked >= self.minVoteStakingAmount, message: "Not eligible")

self.voted[voterAddr] = optionIndex
BloctoDAO.votedRecords[self.id][voterAddr] = optionIndex
}

// return if count ended
Expand All @@ -176,15 +194,17 @@ pub contract BloctoDAO {
return CountStatus.finished
}

let votedList = self.voted.keys
let votedList = BloctoDAO.votedRecords[self.id].keys
var batchEnd = self.countIndex + size

if batchEnd > votedList.length {
batchEnd = votedList.length
}

while self.countIndex != batchEnd {
let address = votedList[self.countIndex]
let voterStaked = BloctoDAO.getStakedBLT(address: address)
let votedOptionIndex = self.voted[address]!
let votedOptionIndex = BloctoDAO.votedRecords[self.id][address]!
self.votesCountActual[votedOptionIndex] = self.votesCountActual[votedOptionIndex] + voterStaked

self.countIndex = self.countIndex + 1
Expand All @@ -193,7 +213,6 @@ pub contract BloctoDAO {
self.sealed = self.countIndex == votedList.length

return CountStatus.success

}

pub fun isEnded(): Bool {
Expand All @@ -207,24 +226,27 @@ pub contract BloctoDAO {
pub fun getVotes(page: Int, pageSize: Int?): [VoteRecord] {
var records: [VoteRecord] = []
let size = pageSize != nil ? pageSize! : 100
let addresses = self.voted.keys
let addresses = BloctoDAO.votedRecords[self.id].keys
var pageStart = (page - 1) * size
var pageEnd = pageStart + size

if pageEnd > addresses.length {
pageEnd = addresses.length
}

while pageStart < pageEnd {
let address = addresses[pageStart]
let optionIndex = self.voted[address]!
let optionIndex = BloctoDAO.votedRecords[self.id][address]!
let amount = BloctoDAO.getStakedBLT(address: address)
records.append(VoteRecord(address: address, optionIndex: optionIndex, amount: amount))
pageStart = pageStart + 1
}

return records
}

pub fun getTotalVoted(): Int {
return self.voted.keys.length
return BloctoDAO.votedRecords[self.id].keys.length
}
}

Expand Down Expand Up @@ -266,8 +288,13 @@ pub contract BloctoDAO {

init () {
self.topics = []
self.votedRecords = []
self.totalTopics = 0

self.AdminStoragePath = /storage/bloctoDAOAdmin
self.VoterStoragePath = /storage/bloctoDAOVoter
self.VoterPublicPath = /public/bloctoDAOVoter
self.VoterPath = /private/bloctoDAOVoter
self.account.save(<-create Admin(), to: self.AdminStoragePath)
}
}
9 changes: 9 additions & 0 deletions flow.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@
}
},
"contracts": {
"BloctoDAO": {
"source": "./contracts/flow/dao/BloctoDAO.cdc",
"aliases": {
"mainnet": "0xe0f601b5afd47581"
}
},
"BloctoPass": {
"source": "./contracts/flow/token/BloctoPass.cdc",
"aliases": {
Expand Down Expand Up @@ -261,6 +267,9 @@
"blt-admin-mainnet": {
"fromFile": "./flow.mainnet.json"
},
"blt-dao-admin-mainnet": {
"fromFile": "./flow.mainnet.json"
},
"blt-staking-admin-mainnet": {
"fromFile": "./flow.mainnet.json"
},
Expand Down
14 changes: 14 additions & 0 deletions transactions/dao/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# DAO - Examples
### Setup Proposer
```
flow transactions send ./transactions/dao/createProposer.cdc \
--signer blt-dao-admin-mainnet \
--network mainnet
```

### Propose New Topic
```
flow transactions send ./transactions/dao/proposeNewTopic.cdc \
--signer blt-dao-admin-mainnet \
--network mainnet
```
18 changes: 18 additions & 0 deletions transactions/dao/createProposer.cdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import BloctoDAO from "../../contracts/flow/dao/BloctoDAO.cdc"

transaction {

prepare(signer: AuthAccount) {
let admin = signer
.borrow<&BloctoDAO.Admin>(from: BloctoDAO.AdminStoragePath)
?? panic("Signer is not the admin")

let proposer <- admin.createProposer()

signer.save(<-proposer, to: /storage/bloctoDAOProposer)
signer.link<&BloctoDAO.Proposer>(
/private/bloctoDAOProposer,
target: /storage/bloctoDAOProposer
)
}
}
21 changes: 21 additions & 0 deletions transactions/dao/proposeNewTopic.cdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import BloctoDAO from "../../contracts/flow/dao/BloctoDAO.cdc"

transaction {
let proposer: &BloctoDAO.Proposer

prepare(signer: AuthAccount) {
self.proposer = signer.getCapability(/private/bloctoDAOProposer).borrow<&BloctoDAO.Proposer>()
?? panic("Could not borrow reference")
}

execute {
self.proposer.addTopic(
title: "How much $BLT token grant should the Blocto ecosystem fund allocate for the IDO platform from portto, the infrastructure supplier?",
description: "Portto is the infrastructure supplier of Blocto's upcoming IDO platform. In this poll, we wish to decide how much $BLT token should be granted to portto for developing the Blocto IDO platform via BloctoDAO. The grant will be granted from the ecosystem fund.",
options: ["100K $BLT", "300K $BLT", "500K $BLT"],
startAt: 1641373200.0,
endAt: 1641546000.0,
minVoteStakingAmount: 0.00000001
)
}
}

0 comments on commit e1e0f1d

Please sign in to comment.