I’ve recently started a side project on Ethereum to work on an idea I’ve been mulling over since 2014. As part of the project I am trying to build, I will need to implement voting based on token ownership. Since this has been done with a few projects already, I figured there would be an easy way to implement it… and then I started to see how the sausage is made.

If you start with a standard ERC20 token, and would like to allow people to vote on items and have their vote weighted by how many tokens they own, you need to set up a vote counting contract. This contract will allow incoming votes, calculate vote tallies, and determine the outcome. To do this, the contract needs access to how many tokens each account has. You could simply ask the ERC20 token how many tokens each voter has when they make their vote, but then it leads you to a situation where a voter just moves their coins to a different address and then votes again.

Ok… so you could initialize the vote contract with the initial balance of the tokens. This would allow the voting contract to take a snapshot in time, and weight the votes based on the amounts of tokens held in a specific block. This would be ideal, but it is blocked by the fact that you can only send primitive data types between contracts.

// Example code showing a failure // The map of current token balances

mapping (string => address) tokenBalances; // This will not compile... Fail!

function GetBalances() returns ( mapping(address => uint) tokenBalances){

return tokenBalances;

}

To get around this, some token based voting protocols will freeze transfers of tokens during voting periods. This gets a little more complicated since in theory you would prevent anyone from transferring, buying, or selling that token during some predefined time window. This would reduce the functionality of the token, and perhaps even pressure the price of the token due to loss of usefulness. To get around this, some projects set up a scheme where the token is always transferable, unless you make a vote during some time window, then your account is locked until the voting period has completed.

Transfer of tokens is blocked once a vote is cast during a specified time window.

OK, so what if you didn’t want to block transfers at all and allow voting and transfers to continue simultaneously? Some other projects decided this was the ideal goal, and implemented functionality to track every transfer of tokens inside the contracts themselves. This would allow a contract to ask “What was my balance at X block when the voting started?”. The contract not only has to duplicate and store history of every transfer in the contract itself, which is odd since the blockchain itself already has this info, but it also would then have to search through the history of an address when the balance is queried. It essentially doubles the cost of gas for making transfers and querying balances. This is pretty cool, but seems very wasteful of the precious resources of a blockchain.

I’m sure there must be some other approaches, but I haven’t seen it. By all means, please send them my way. Whether it is Bitcoin or Ethereum, I always find myself having to re-set my expectations of where the current state is for the platforms. I do think the ability to send and retrieve more complex data structures between contracts is on the road map for Solidity/Ethereum, but until then people will have to make strange trade-offs and make things more complicated. The good thing is that it is just software, so it will evolve if enough people are aware of the issues facing the platforms.