Poll Lifecycle

This is the first of a 3-part article which presents the Solidity-based implementation of the Token weighted voting protocol. I am presenting the end-to-end implementation overview of this at DevCon2 and these 3 articles aim to go into the detail of this.

Here, we examine the lifecycle of a poll and its data structure.

High-level contract design

Before we go into the implementation details, it’s necessary to understand the Colony contract design at a high level.

The Colony contract itself serves as the interface to the user.

The library layer encapsulates the business logic for different domains, e.g. TokenLibrary contains the logic for managing Colony tokens, Voting library contains the poll and votes management logic etc. The Security and Task library in the diagram below are greyed out as they’re not directly relevant in the context of this article but they form an integral part of the Colony network.

While we use libraries to encapsulate business logic, we use a generic storage contract to persist Colony data, e.g. storing information about the token balances, polls and votes etc.

This contracts design is established following our chosen approach for writing upgradable contracts.

Colony high level contract design

In this first article on poll management, all functionality is encapsulated into the Voting Library implementation.

Poll data structure

Similar to the traditional sense of what makes up a poll, we have implemented the following properties:

  • description — contains the poll question itself, e.g. “Should Scotland be an independent country?”
  • poll options — there should be a minimum of 2 options for each poll, e.g. “Yes”, “No”
  • start time — the point in time when the poll opens for voting
  • close time — the point in time when the poll closes for voting
  • poll status — a poll goes through the stages of being created, active (open for votes or revealing votes) and resolved

These are implemented as bytes32 key mappings to their respective EterenalStorage-supported types.

bytes32 Key                                  Mapped value type
sha3("Poll", pollId, "description")         => string
sha3("Poll", pollId, "option", idx)         => string
sha3("Poll", pollId, "startTime")           => uint256
sha3("Poll", pollId, "closeTime")           => uint256
sha3("Poll", pollId, "status")              => uint256

In addition, there are two global properties we maintain for the purpose of enumerating through polls and poll options. We keep a count of polls and poll options and never delete them. Thus we maintain a “poll count” global property which helps us keep track of this and used to generate the ID of the next item when it’s created.

bytes32 Key                                  Mapped value type
sha3("PollCount")                           => uint256
sha3("Poll", pollId, "OptionsCount")        => uint256

Poll Lifecycle

Polls can be managed by admins only and their lifecycle is a one-way staged process as follows:

Poll Lifecycle

To ensure the stages are sequential, we make use of a modifier to ensure the poll is currently with the correct status.

modifier ensurePollStatus(uint256 pollId, uint256 pollStatus)
   var currentStatus = getUIntValue(sha3(“Poll”, pollId, “status”));
   if (pollStatus != currentStatus) { throw; }

The following poll management functions have been implemented in our Voting library, which set the required properties outlined above, i.e. description, poll option, open and close times and status:

function createPoll(string description) {...}
function addPollOption(uint256 pollId, string pollOptionDescription)
  ensurePollStatus(pollId, 0)
  returns (bool) {...}
function openPoll(uint256 pollId, uint256 pollDuration)
  ensurePollStatus(pollId, 0)
  returns (bool) {...}
function resolvePoll(address _storageContract, uint256 pollId)
  ensurePollStatus(pollId, 1)
  returns (bool) {...}

Let’s run through a sample call sequence for this:

colony.createPoll("Should the United Kingdom remain a member of the EU?");
colony.addPollOption(1, "Yes");
colony.addPollOption(1, "No");
colony.openPoll(1, 24);
// forward time past the poll close time

Poll close time

There is an additional status of poll closed which gets determined by the poll closeTime property, i.e.

if (closeTime > now) => Poll is closed

This is set in the openPoll function as:

now + pollDuration * 1 hours

Poll duration is set in hours as the lowest denominator for poll duration time, however you can easily adjust that to minutes, seconds, days etc.

Poll Voting

In the second article we will examine the Secret Voting implementation and the double linked lists data structures we use to manage these.

If you have any feedback or stories to share, reach out to us on Twitter.

Colony is a platform for open organizations.

Join the discussion on Discourse, follow us on Twitter, sign up for (occasional) email updates, or if you’re feeling old-skool, drop us an email.