visual-identity/contracts/polls/PollManager.sol

254 lines
6.0 KiB
Solidity
Raw Normal View History

pragma solidity ^0.4.23;
2018-06-26 10:19:04 -04:00
import "../common/Controlled.sol";
import "../token/MiniMeToken.sol";
2018-06-26 15:41:28 -04:00
2018-06-26 10:19:04 -04:00
contract PollManager is Controlled {
2018-06-26 10:19:04 -04:00
struct Poll {
uint startBlock;
uint endBlock;
address token;
bool canceled;
uint voters;
string description;
mapping(address => uint) votes;
uint results;
uint qvResults;
2018-06-26 10:19:04 -04:00
}
Poll[] _polls;
MiniMeTokenFactory public tokenFactory;
MiniMeToken public token;
2018-06-26 14:44:45 -04:00
constructor(address _tokenFactory, address _token)
2018-06-26 10:19:04 -04:00
public {
tokenFactory = MiniMeTokenFactory(_tokenFactory);
token = MiniMeToken(_token);
}
modifier onlySNTHolder {
// TODO: require min number of tokens?
require(token.balanceOf(msg.sender) > 0);
_;
}
function addPoll(
uint _endBlock,
string _description)
2018-06-26 14:44:45 -04:00
public
2018-06-26 10:19:04 -04:00
onlySNTHolder
returns (uint _idPoll)
{
2018-06-26 17:02:04 -04:00
require(_endBlock > block.number);
2018-06-26 14:44:45 -04:00
2018-06-26 10:19:04 -04:00
_idPoll = _polls.length;
_polls.length ++;
2018-06-26 14:44:45 -04:00
Poll storage p = _polls[ _idPoll ];
2018-06-26 17:02:04 -04:00
p.startBlock = block.number;
2018-06-26 10:19:04 -04:00
p.endBlock = _endBlock;
p.voters = 0;
p.description = _description;
2018-06-26 10:19:04 -04:00
p.token = tokenFactory.createCloneToken(
address(token),
2018-06-26 17:02:04 -04:00
block.number - 1,
"SNT Voting Token",
2018-06-26 10:19:04 -04:00
token.decimals(),
"SVT",
2018-06-26 10:19:04 -04:00
true);
emit PollCreated(_idPoll);
2018-06-26 10:19:04 -04:00
}
2018-06-26 14:44:45 -04:00
function cancelPoll(uint _idPoll)
onlyController
public
{
require(_idPoll < _polls.length);
Poll storage p = _polls[_idPoll];
require(p.endBlock < block.number);
2018-06-26 10:19:04 -04:00
p.canceled = true;
2018-06-26 14:44:45 -04:00
emit PollCanceled(_idPoll);
2018-06-26 10:19:04 -04:00
}
2018-06-26 14:44:45 -04:00
function canVote(uint _idPoll)
public
view
returns(bool)
{
if(_idPoll >= _polls.length) return false;
Poll storage p = _polls[_idPoll];
uint balance = MiniMeToken(p.token).balanceOfAt(msg.sender, p.startBlock - 1);
return block.number >= p.startBlock &&
block.number <= p.endBlock &&
!p.canceled &&
balance != 0;
}
function sqrt(uint256 x) public pure returns (uint256 y) {
uint256 z = (x + 1) / 2;
y = x;
while (z < y) {
y = z;
z = (x / z + z) / 2;
}
}
function vote(uint _idPoll) public {
2018-06-26 14:44:45 -04:00
require(_idPoll < _polls.length);
2018-06-26 10:19:04 -04:00
2018-06-26 14:44:45 -04:00
Poll storage p = _polls[_idPoll];
2018-06-26 10:19:04 -04:00
2018-06-26 14:44:45 -04:00
require(block.number >= p.startBlock && block.number < p.endBlock && !p.canceled);
2018-06-26 10:19:04 -04:00
2018-06-26 14:44:45 -04:00
unvote(_idPoll);
2018-06-26 10:19:04 -04:00
2018-06-26 14:44:45 -04:00
uint amount = MiniMeToken(p.token).balanceOf(msg.sender);
2018-06-26 10:19:04 -04:00
2018-06-26 14:44:45 -04:00
require(amount != 0);
require(MiniMeToken(p.token).transferFrom(msg.sender, address(this), amount));
2018-06-26 10:19:04 -04:00
p.votes[msg.sender] = amount;
p.voters++;
p.results += amount;
p.qvResults += sqrt(amount);
emit Vote(_idPoll, msg.sender, amount);
2018-06-26 10:19:04 -04:00
}
function customVote(uint _idPoll, uint _amount) public {
2018-06-27 13:27:01 -04:00
require(_idPoll < _polls.length);
Poll storage p = _polls[_idPoll];
require(block.number >= p.startBlock && block.number < p.endBlock && !p.canceled);
unvote(_idPoll);
uint balance = MiniMeToken(p.token).balanceOf(msg.sender);
2018-06-27 21:42:17 -04:00
require(balance != 0 && balance >= _amount && _amount != 0);
2018-06-27 13:27:01 -04:00
require(MiniMeToken(p.token).transferFrom(msg.sender, address(this), _amount));
p.votes[msg.sender] = _amount;
2018-06-27 13:27:01 -04:00
p.voters++;
p.results += _amount;
p.qvResults += sqrt(_amount);
2018-06-27 13:27:01 -04:00
emit Vote(_idPoll, msg.sender, _amount);
2018-06-27 13:27:01 -04:00
}
2018-06-26 14:44:45 -04:00
function unvote(uint _idPoll) public {
require(_idPoll < _polls.length);
Poll storage p = _polls[_idPoll];
require(block.number >= p.startBlock && block.number < p.endBlock && !p.canceled);
2018-06-26 10:19:04 -04:00
uint amount = p.votes[msg.sender];
2018-06-26 10:19:04 -04:00
if (amount == 0) return;
p.votes[msg.sender] = 0;
p.voters--;
p.results -= amount;
p.qvResults -= sqrt(amount);
2018-06-26 10:19:04 -04:00
2018-06-26 14:44:45 -04:00
require(MiniMeToken(p.token).transferFrom(address(this), msg.sender, amount));
2018-06-26 10:19:04 -04:00
emit Unvote(_idPoll, msg.sender, amount);
2018-06-26 10:19:04 -04:00
}
// Constant Helper Function
2018-06-26 14:44:45 -04:00
function nPolls()
public
view
returns(uint)
{
2018-06-26 10:19:04 -04:00
return _polls.length;
}
2018-06-26 14:44:45 -04:00
function poll(uint _idPoll)
public
view
returns(
2018-06-26 10:19:04 -04:00
uint _startBlock,
uint _endBlock,
2018-06-27 20:45:31 -04:00
bool _canVote,
2018-06-26 10:19:04 -04:00
address _token,
bool _canceled,
string _description,
2018-06-26 10:19:04 -04:00
bool _finalized,
uint _totalCensus,
uint _voters,
uint _results,
uint _qvResults
2018-06-26 14:44:45 -04:00
)
{
require(_idPoll < _polls.length);
Poll storage p = _polls[_idPoll];
2018-06-26 10:19:04 -04:00
_startBlock = p.startBlock;
_endBlock = p.endBlock;
_token = p.token;
_canceled = p.canceled;
2018-06-27 20:45:31 -04:00
_canVote = canVote(_idPoll);
_description = p.description;
2018-06-26 14:44:45 -04:00
_finalized = (!p.canceled) && (block.number >= _endBlock);
2018-06-26 10:19:04 -04:00
_totalCensus = MiniMeToken(p.token).totalSupply();
_voters = p.voters;
_results = p.results;
_qvResults = p.qvResults;
2018-06-26 10:19:04 -04:00
}
2018-06-26 14:44:45 -04:00
function getVote(uint _idPoll, address _voter)
public
view
returns (uint)
2018-06-26 14:44:45 -04:00
{
require(_idPoll < _polls.length);
Poll storage p = _polls[_idPoll];
return p.votes[_voter];
}
2018-06-26 14:44:45 -04:00
function proxyPayment(address )
payable
returns(bool) {
2018-06-26 10:19:04 -04:00
return false;
}
2018-06-26 14:44:45 -04:00
function onTransfer(address , address , uint )
public
pure
returns(bool)
{
2018-06-26 10:19:04 -04:00
return true;
}
2018-06-26 14:44:45 -04:00
function onApprove(address , address , uint )
public
pure
returns(bool) {
2018-06-26 10:19:04 -04:00
return true;
}
event Vote(uint indexed idPoll, address indexed _voter, uint amount);
event Unvote(uint indexed idPoll, address indexed _voter, uint amount);
2018-06-26 10:19:04 -04:00
event PollCanceled(uint indexed idPoll);
event PollCreated(uint indexed idPoll);
2018-06-26 10:19:04 -04:00
}