Forkchoice Ethereum Mainnet

Address Contract Partially Verified

Address 0x55656b8a58dF94C1e8B5142F8da973301452eA65
Balance 0 ETH
Nonce 1
Code Size 7705 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

7705 bytes
0x6080604052600436106101925763ffffffff60e060020a600035041663053e71a681146101975780632173a10f146101c15780632c052031146101d657806332ed3d60146101fd5780633b9302941461021b5780633ec36b991461023c57806340f41c1914610282578063427fa1d2146102b3578063441c77c0146102d457806349403183146103005780636148fed5146103185780636afa97a81461035b5780636b2d95d4146103825780636cbf9c5e146103a35780637f97e836146103c45780638090f92e146103e8578063819b02931461042057806388d21ff31461044a57806397508f36146104625780639760356014610477578063a1103f371461048f578063a25236fe146104b3578063a4439dc5146104cb578063aa7ca464146104e3578063b11d8bb814610507578063b43bd06914610525578063bb11ed7e1461054c578063d1382092146105a1578063d901402b146105c5578063d9548e53146105e9578063e7b1d43c14610601578063e8cfa3f014610619578063ee68483014610631578063fc0c546a14610649575b600080fd5b3480156101a357600080fd5b506101af60043561065e565b60408051918252519081900360200190f35b3480156101cd57600080fd5b506101af6106b3565b3480156101e257600080fd5b506101af600160a060020a03600435166024356044356106b8565b34801561020957600080fd5b506101af600435602435604435610881565b34801561022757600080fd5b506101af600160a060020a036004351661095d565b34801561024857600080fd5b50610280602460048035828101929082013591813580830192908201359160443580830192908201359160643591820191013561096f565b005b34801561028e57600080fd5b50610297610a0f565b60408051600160a060020a039092168252519081900360200190f35b3480156102bf57600080fd5b506101af600160a060020a0360043516610a1e565b3480156102e057600080fd5b506102ec600435610ad8565b604080519115158252519081900360200190f35b34801561030c57600080fd5b506102ec600435610b23565b34801561032457600080fd5b50610330600435610ba0565b6040805195865260208601949094528484019290925260608401526080830152519081900360a00190f35b34801561036757600080fd5b506101af600160a060020a0360043516602435604435610bce565b34801561038e57600080fd5b506101af600160a060020a0360043516610c85565b3480156103af57600080fd5b50610280600435602435604435606435610c99565b3480156103d057600080fd5b506102ec600160a060020a036004351660243561120b565b3480156103f457600080fd5b506102806024600480358281019290820135918135808301929082013591604435918201910135611250565b34801561042c57600080fd5b506102ec600435602435600160a060020a03604435166064356112cc565b34801561045657600080fd5b506102ec60043561130a565b34801561046e57600080fd5b506101af61131f565b34801561048357600080fd5b50610280600435611325565b34801561049b57600080fd5b506101af600160a060020a03600435166024356114c9565b3480156104bf57600080fd5b50610280600435611500565b3480156104d757600080fd5b506102ec60043561159a565b3480156104ef57600080fd5b506102ec600160a060020a03600435166024356115c8565b34801561051357600080fd5b5061028060043560243560443561160d565b34801561053157600080fd5b506101af600160a060020a0360043516602435604435611810565b34801561055857600080fd5b50604080516020600480358082013583810280860185019096528085526102809536959394602494938501929182918501908490808284375094975061189c9650505050505050565b3480156105ad57600080fd5b506101af600160a060020a03600435166024356118d4565b3480156105d157600080fd5b506101af600160a060020a03600435166024356119a6565b3480156105f557600080fd5b506102ec600435611a45565b34801561060d57600080fd5b50610280600435611a4a565b34801561062557600080fd5b506101af600435611b76565b34801561063d57600080fd5b506102ec600435611bca565b34801561065557600080fd5b50610297611bfc565b600061066982611bca565b151561067457600080fd5b61067d82610b23565b1561069a57506000818152600160205260409020600301546106ae565b506000818152600160205260409020600401545b919050565b600081565b60008060006106c686610a1e565b91506106d286836118d4565b90505b8115610874576106e586836118d4565b90508481116107b757838214156107af57600160a060020a03861660009081526003602090815260409182902082517f30fe0a0a000000000000000000000000000000000000000000000000000000008152600481019190915260248101859052915173739f1745e415782861373c5ff1a6dc56d2d41451926330fe0a0a926044808301939192829003018186803b15801561078057600080fd5b505af4158015610794573d6000803e3d6000fd5b505050506040513d60208110156107aa57600080fd5b505191505b819250610878565b600160a060020a03861660009081526003602090815260409182902082517f30fe0a0a000000000000000000000000000000000000000000000000000000008152600481019190915260248101859052915173739f1745e415782861373c5ff1a6dc56d2d41451926330fe0a0a926044808301939192829003018186803b15801561084157600080fd5b505af4158015610855573d6000803e3d6000fd5b505050506040513d602081101561086b57600080fd5b505191506106d5565b8192505b50509392505050565b600080546001018155808061089c428663ffffffff611c0b16565b91506108ae828563ffffffff611c0b16565b6040805160a08101825284815260208082018481528284018b8152600060608086018281526080870183815283548452600180885289852098518955955195880195909555925160028701559151600386015591516004909401939093555483518b8152918201879052818401859052925193945033937f404f1f1c229d9eb2a949e7584da6ffde9d059ef2169f487ca815434cce0640d0929181900390910190a35050600054949350505050565b60026020526000908152604090205481565b600087861461097d57600080fd5b87841461098957600080fd5b87821461099557600080fd5b5060005b87811015610a04576109fc8989838181106109b057fe5b9050602002013588888481811015156109c557fe5b602002919091013590508787858181106109db57fe5b9050602002013586868681811015156109f057fe5b90506020020135610c99565b600101610999565b505050505050505050565b600654600160a060020a031681565b600160a060020a038116600090815260036020908152604080832081517f30fe0a0a000000000000000000000000000000000000000000000000000000008152600481019190915260248101849052905173739f1745e415782861373c5ff1a6dc56d2d41451926330fe0a0a9260448082019391829003018186803b158015610aa657600080fd5b505af4158015610aba573d6000803e3d6000fd5b505050506040513d6020811015610ad057600080fd5b505192915050565b6000610ae38261130a565b1515610aee57600080fd5b60008281526001602081905260409091200154610b0a90611a45565b158015610b1d5750610b1b8261159a565b155b92915050565b6000610b2d611dbd565b610b3683611bca565b1515610b4157600080fd5b5050600090815260016020818152604092839020835160a0810185528154815292810154918301919091526002810154928201839052600381015460608301819052600490910154608090920182905290810190910260649091021190565b6001602081905260009182526040909120805491810154600282015460038301546004909301549192909185565b600080600080610bdd86611bca565b1515610be857600080fd5b6000868152600160209081526040808320600160a060020a038b16845260060190915290205460ff161515610c1c57600080fd5b610c2586610b23565b610c30576001610c33565b60005b60ff1692508285604051808381526020018281526020019250505060405180910390209150610c6287876119a6565b9050818114610c7057600080fd5b610c7a87876118d4565b979650505050505050565b6000610b1d82610c9484610a1e565b6118d4565b6000806000610ca78761159a565b1515610cb257600080fd5b33600090815260026020526040902054851115610cf55733600090815260026020526040902054610cea90869063ffffffff611c1816565b9250610cf583611500565b33600090815260026020526040902054851115610d1157600080fd5b861515610d1d57600080fd5b851515610d2957600080fd5b831580610ddf57503360009081526003602090815260409182902082517f366a5ba2000000000000000000000000000000000000000000000000000000008152600481019190915260248101879052915173739f1745e415782861373c5ff1a6dc56d2d414519263366a5ba2926044808301939192829003018186803b158015610db257600080fd5b505af4158015610dc6573d6000803e3d6000fd5b505050506040513d6020811015610ddc57600080fd5b50515b1515610dea57600080fd5b3360009081526003602090815260409182902082517f07d29ac9000000000000000000000000000000000000000000000000000000008152600481019190915260248101879052915173739f1745e415782861373c5ff1a6dc56d2d41451926307d29ac9926044808301939192829003018186803b158015610e6b57600080fd5b505af4158015610e7f573d6000803e3d6000fd5b505050506040513d6020811015610e9557600080fd5b5051915086821415610f51573360009081526003602090815260409182902082517f07d29ac90000000000000000000000000000000000000000000000000000000081526004810191909152602481018a9052915173739f1745e415782861373c5ff1a6dc56d2d41451926307d29ac9926044808301939192829003018186803b158015610f2257600080fd5b505af4158015610f36573d6000803e3d6000fd5b505050506040513d6020811015610f4c57600080fd5b505191505b610f5d848333886112cc565b1515610f6857600080fd5b3360009081526003602052604080822081517f9735c51b000000000000000000000000000000000000000000000000000000008152600481019190915260248101879052604481018a905260648101859052905173739f1745e415782861373c5ff1a6dc56d2d4145192639735c51b9260848082019391829003018186803b158015610ff357600080fd5b505af4158015611007573d6000803e3d6000fd5b5050505061101533886114c9565b604080517f977aa031000000000000000000000000000000000000000000000000000000008152600481810152602481018390526064810188905260806044820152600960848201527f6e756d546f6b656e73000000000000000000000000000000000000000000000060a4820152905191925073393e69e7ae7addcfd744b71d209b1f04800d89e59163977aa0319160c480820192600092909190829003018186803b1580156110c557600080fd5b505af41580156110d9573d6000803e3d6000fd5b5050604080517f977aa03100000000000000000000000000000000000000000000000000000000815260048181015260248101859052606481018a905260806044820152600a60848201527f636f6d6d6974486173680000000000000000000000000000000000000000000060a4820152905173393e69e7ae7addcfd744b71d209b1f04800d89e5935063977aa031925060c4808301926000929190829003018186803b15801561118957600080fd5b505af415801561119d573d6000803e3d6000fd5b5050506000888152600160208181526040808420338086526005909101835293819020805460ff1916909317909255815189815291519293508a927fea7979e4280d7e6bffc1c7d83a1ac99f16d02ecc14465ce41016226783b663d79281900390910190a350505050505050565b60006112168261130a565b151561122157600080fd5b506000908152600160209081526040808320600160a060020a0394909416835260059093019052205460ff1690565b600085841461125e57600080fd5b85821461126a57600080fd5b5060005b858110156112c3576112bb87878381811061128557fe5b90506020020135868684818110151561129a57fe5b9050602002013585858581811015156112af57fe5b9050602002013561160d565b60010161126e565b50505050505050565b60008060006112db85886118d4565b84101591506112ea85876118d4565b841115806112f6575085155b9050818015610c7a57509695505050505050565b60008115801590610b1d575050600054101590565b60005481565b6000818152600160208190526040909120015461134190611a45565b151561134c57600080fd5b3360009081526003602090815260409182902082517f366a5ba2000000000000000000000000000000000000000000000000000000008152600481019190915260248101849052915173739f1745e415782861373c5ff1a6dc56d2d414519263366a5ba2926044808301939192829003018186803b1580156113cd57600080fd5b505af41580156113e1573d6000803e3d6000fd5b505050506040513d60208110156113f757600080fd5b5051151561140457600080fd5b3360009081526003602052604080822081517f6d900ed0000000000000000000000000000000000000000000000000000000008152600481019190915260248101849052905173739f1745e415782861373c5ff1a6dc56d2d4145192636d900ed09260448082019391829003018186803b15801561148157600080fd5b505af4158015611495573d6000803e3d6000fd5b50506040513392508391507f402507661c8c8cb90e0a796450b8bdd28b6c516f05279c0cd29e84c344e1699a90600090a350565b604080516c01000000000000000000000000600160a060020a03851602815260148101839052905190819003603401902092915050565b61150981611c2a565b600654336000818152600260205260408082205481517f725248730000000000000000000000000000000000000000000000000000000081526004810194909452602484015251600160a060020a0390931692637252487392604480820193929182900301818387803b15801561157f57600080fd5b505af1158015611593573d6000803e3d6000fd5b5050505050565b60006115a58261130a565b15156115b057600080fd5b600082815260016020526040902054610b1b90611a45565b60006115d38261130a565b15156115de57600080fd5b506000908152600160209081526040808320600160a060020a0394909416835260069093019052205460ff1690565b600061161884610ad8565b151561162357600080fd5b600084815260016020908152604080832033845260050190915290205460ff16151561164e57600080fd5b600084815260016020908152604080832033845260060190915290205460ff161561167857600080fd5b61168233856119a6565b60408051858152602081018590528151908190039091019020146116a557600080fd5b6116af33856118d4565b905082600114156116d65760008481526001602052604090206003018054820190556116ee565b60008481526001602052604090206004018054820190555b3360009081526003602052604080822081517f6d900ed0000000000000000000000000000000000000000000000000000000008152600481019190915260248101879052905173739f1745e415782861373c5ff1a6dc56d2d4145192636d900ed09260448082019391829003018186803b15801561176b57600080fd5b505af415801561177f573d6000803e3d6000fd5b505050600085815260016020818152604080842033808652600682018452828620805460ff191686179055948a9052928252600383015460049093015481518781529283019390935281810192909252606081018690529051919250859187917f9b19aaec524fad29c0ced9b9973a15e3045d7c3be156d71394ab40f0d5f119ff919081900360800190a450505050565b60008060008061181f86611bca565b151561182a57600080fd5b6000868152600160209081526040808320600160a060020a038b16845260060190915290205460ff16151561185e57600080fd5b61186786610b23565b611872576000610c33565b6040805160018082526020820188905282519182900390920190209093509150610c6287876119a6565b60005b81518110156118d0576118c882828151811015156118b957fe5b90602001906020020151611325565b60010161189f565b5050565b600073393e69e7ae7addcfd744b71d209b1f04800d89e56350389f5c60046118fc86866114c9565b6040805160e060020a63ffffffff86160281526004810193909352602483019190915260606044830152600960648301527f6e756d546f6b656e73000000000000000000000000000000000000000000000060848301525160a4808301926020929190829003018186803b15801561197357600080fd5b505af4158015611987573d6000803e3d6000fd5b505050506040513d602081101561199d57600080fd5b50519392505050565b600073393e69e7ae7addcfd744b71d209b1f04800d89e56350389f5c60046119ce86866114c9565b6040805160e060020a63ffffffff86160281526004810193909352602483019190915260606044830152600a60648301527f636f6d6d6974486173680000000000000000000000000000000000000000000060848301525160a4808301926020929190829003018186803b15801561197357600080fd5b421190565b6000611a74611a5833610c85565b336000908152600260205260409020549063ffffffff611c1816565b905081811015611a8357600080fd5b3360008181526002602090815260408083208054879003905560055481517fa9059cbb0000000000000000000000000000000000000000000000000000000081526004810195909552602485018790529051600160a060020a039091169363a9059cbb9360448083019493928390030190829087803b158015611b0557600080fd5b505af1158015611b19573d6000803e3d6000fd5b505050506040513d6020811015611b2f57600080fd5b50511515611b3c57600080fd5b60408051838152905133917ffaeb7dbb9992397d26ea1944efd40c80b40f702faf69b46c67ad10aba68ccb79919081900360200190a25050565b6000611b8182611bca565b1515611b8c57600080fd5b611b9582610b23565b15611bb257506000818152600160205260409020600401546106ae565b506000818152600160205260409020600301546106ae565b6000611bd58261130a565b1515611be057600080fd5b60008281526001602081905260409091200154610b1d90611a45565b600554600160a060020a031681565b81810182811015610b1d57fe5b600082821115611c2457fe5b50900390565b600554604080517f70a0823100000000000000000000000000000000000000000000000000000000815233600482015290518392600160a060020a0316916370a082319160248083019260209291908290030181600087803b158015611c8f57600080fd5b505af1158015611ca3573d6000803e3d6000fd5b505050506040513d6020811015611cb957600080fd5b50511015611cc657600080fd5b33600081815260026020908152604080832080548601905560055481517f23b872dd0000000000000000000000000000000000000000000000000000000081526004810195909552306024860152604485018690529051600160a060020a03909116936323b872dd9360648083019493928390030190829087803b158015611d4d57600080fd5b505af1158015611d61573d6000803e3d6000fd5b505050506040513d6020811015611d7757600080fd5b50511515611d8457600080fd5b60408051828152905133917ff7aaf024511d9982df8cd0d437c71c30106e6848cd1ba3d288d7a9c0e276aeda919081900360200190a250565b60a060405190810160405280600081526020016000815260200160008152602001600081526020016000815250905600a165627a7a72305820dfb0bd5ea70ad6f1df929d57bad9a8a3a61facd419e162e3168c26c446d299260029

Verified Source Code Partial Match

Compiler: v0.4.24+commit.e67f0147 EVM: byzantium Optimization: Yes (200 runs)
CivilPLCRVoting.sol 757 lines
// File: contracts/installed_contracts/DLL.sol

pragma solidity^0.4.11;

library DLL {

  uint constant NULL_NODE_ID = 0;

  struct Node {
    uint next;
    uint prev;
  }

  struct Data {
    mapping(uint => Node) dll;
  }

  function isEmpty(Data storage self) public view returns (bool) {
    return getStart(self) == NULL_NODE_ID;
  }

  function contains(Data storage self, uint _curr) public view returns (bool) {
    if (isEmpty(self) || _curr == NULL_NODE_ID) {
      return false;
    }

    bool isSingleNode = (getStart(self) == _curr) && (getEnd(self) == _curr);
    bool isNullNode = (getNext(self, _curr) == NULL_NODE_ID) && (getPrev(self, _curr) == NULL_NODE_ID);
    return isSingleNode || !isNullNode;
  }

  function getNext(Data storage self, uint _curr) public view returns (uint) {
    return self.dll[_curr].next;
  }

  function getPrev(Data storage self, uint _curr) public view returns (uint) {
    return self.dll[_curr].prev;
  }

  function getStart(Data storage self) public view returns (uint) {
    return getNext(self, NULL_NODE_ID);
  }

  function getEnd(Data storage self) public view returns (uint) {
    return getPrev(self, NULL_NODE_ID);
  }

  /**
  @dev Inserts a new node between _prev and _next. When inserting a node already existing in
  the list it will be automatically removed from the old position.
  @param _prev the node which _new will be inserted after
  @param _curr the id of the new node being inserted
  @param _next the node which _new will be inserted before
  */
  function insert(Data storage self, uint _prev, uint _curr, uint _next) public {
    require(_curr != NULL_NODE_ID);

    remove(self, _curr);

    require(_prev == NULL_NODE_ID || contains(self, _prev));
    require(_next == NULL_NODE_ID || contains(self, _next));

    require(getNext(self, _prev) == _next);
    require(getPrev(self, _next) == _prev);

    self.dll[_curr].prev = _prev;
    self.dll[_curr].next = _next;

    self.dll[_prev].next = _curr;
    self.dll[_next].prev = _curr;
  }

  function remove(Data storage self, uint _curr) public {
    if (!contains(self, _curr)) {
      return;
    }

    uint next = getNext(self, _curr);
    uint prev = getPrev(self, _curr);

    self.dll[next].prev = prev;
    self.dll[prev].next = next;

    delete self.dll[_curr];
  }
}

// File: contracts/installed_contracts/AttributeStore.sol

/* solium-disable */
pragma solidity^0.4.11;

library AttributeStore {
    struct Data {
        mapping(bytes32 => uint) store;
    }

    function getAttribute(Data storage self, bytes32 _UUID, string _attrName)
    public view returns (uint) {
        bytes32 key = keccak256(_UUID, _attrName);
        return self.store[key];
    }

    function setAttribute(Data storage self, bytes32 _UUID, string _attrName, uint _attrVal)
    public {
        bytes32 key = keccak256(_UUID, _attrName);
        self.store[key] = _attrVal;
    }
}

// File: contracts/zeppelin-solidity/token/ERC20/IERC20.sol

pragma solidity ^0.4.24;

/**
 * @title ERC20 interface
 * @dev see https://github.com/ethereum/EIPs/issues/20
 */
interface IERC20 {
    function totalSupply() external view returns (uint256);

    function balanceOf(address who) external view returns (uint256);

    function allowance(address owner, address spender) external view returns (uint256);

    function transfer(address to, uint256 value) external returns (bool);

    function approve(address spender, uint256 value) external returns (bool);

    function transferFrom(address from, address to, uint256 value) external returns (bool);

    event Transfer(address indexed from, address indexed to, uint256 value);

    event Approval(address indexed owner, address indexed spender, uint256 value);
}

// File: contracts/zeppelin-solidity/math/SafeMath.sol

pragma solidity ^0.4.24;


/**
 * @title SafeMath
 * @dev Math operations with safety checks that throw on error
 */
library SafeMath {

  /**
  * @dev Multiplies two numbers, throws on overflow.
  */
  function mul(uint256 _a, uint256 _b) internal pure returns (uint256 c) {
    // Gas optimization: this is cheaper than asserting 'a' not being zero, but the
    // benefit is lost if 'b' is also tested.
    // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
    if (_a == 0) {
      return 0;
    }

    c = _a * _b;
    assert(c / _a == _b);
    return c;
  }

  /**
  * @dev Integer division of two numbers, truncating the quotient.
  */
  function div(uint256 _a, uint256 _b) internal pure returns (uint256) {
    // assert(_b > 0); // Solidity automatically throws when dividing by 0
    // uint256 c = _a / _b;
    // assert(_a == _b * c + _a % _b); // There is no case in which this doesn't hold
    return _a / _b;
  }

  /**
  * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
  */
  function sub(uint256 _a, uint256 _b) internal pure returns (uint256) {
    assert(_b <= _a);
    return _a - _b;
  }

  /**
  * @dev Adds two numbers, throws on overflow.
  */
  function add(uint256 _a, uint256 _b) internal pure returns (uint256 c) {
    c = _a + _b;
    assert(c >= _a);
    return c;
  }
}

// File: contracts/installed_contracts/PLCRVoting.sol

pragma solidity ^0.4.8;





/**
@title Partial-Lock-Commit-Reveal Voting scheme with ERC20 tokens
@author Team: Aspyn Palatnick, Cem Ozer, Yorke Rhodes
*/
contract PLCRVoting {

    // ============
    // EVENTS:
    // ============

    event _VoteCommitted(uint indexed pollID, uint numTokens, address indexed voter);
    event _VoteRevealed(uint indexed pollID, uint numTokens, uint votesFor, uint votesAgainst, uint indexed choice, address indexed voter, uint salt);
    event _PollCreated(uint voteQuorum, uint commitEndDate, uint revealEndDate, uint indexed pollID, address indexed creator);
    event _VotingRightsGranted(uint numTokens, address indexed voter);
    event _VotingRightsWithdrawn(uint numTokens, address indexed voter);
    event _TokensRescued(uint indexed pollID, address indexed voter);

    // ============
    // DATA STRUCTURES:
    // ============

    using AttributeStore for AttributeStore.Data;
    using DLL for DLL.Data;
    using SafeMath for uint;

    struct Poll {
        uint commitEndDate;     /// expiration date of commit period for poll
        uint revealEndDate;     /// expiration date of reveal period for poll
        uint voteQuorum;	    /// number of votes required for a proposal to pass
        uint votesFor;		    /// tally of votes supporting proposal
        uint votesAgainst;      /// tally of votes countering proposal
        mapping(address => bool) didCommit;  /// indicates whether an address committed a vote for this poll
        mapping(address => bool) didReveal;   /// indicates whether an address revealed a vote for this poll
    }

    // ============
    // STATE VARIABLES:
    // ============

    uint constant public INITIAL_POLL_NONCE = 0;
    uint public pollNonce;

    mapping(uint => Poll) public pollMap; // maps pollID to Poll struct
    mapping(address => uint) public voteTokenBalance; // maps user's address to voteToken balance

    mapping(address => DLL.Data) dllMap;
    AttributeStore.Data store;

    IERC20 public token;

    /**
    @param _token The address where the ERC20 token contract is deployed
    */
    constructor(address _token) public {
        require(_token != 0);

        token = IERC20(_token);
        pollNonce = INITIAL_POLL_NONCE;
    }

    // ================
    // TOKEN INTERFACE:
    // ================

    /**
    @notice Loads _numTokens ERC20 tokens into the voting contract for one-to-one voting rights
    @dev Assumes that msg.sender has approved voting contract to spend on their behalf
    @param _numTokens The number of votingTokens desired in exchange for ERC20 tokens
    */
    function requestVotingRights(uint _numTokens) public {
        require(token.balanceOf(msg.sender) >= _numTokens);
        voteTokenBalance[msg.sender] += _numTokens;
        require(token.transferFrom(msg.sender, this, _numTokens));
        emit _VotingRightsGranted(_numTokens, msg.sender);
    }

    /**
    @notice Withdraw _numTokens ERC20 tokens from the voting contract, revoking these voting rights
    @param _numTokens The number of ERC20 tokens desired in exchange for voting rights
    */
    function withdrawVotingRights(uint _numTokens) external {
        uint availableTokens = voteTokenBalance[msg.sender].sub(getLockedTokens(msg.sender));
        require(availableTokens >= _numTokens);
        voteTokenBalance[msg.sender] -= _numTokens;
        require(token.transfer(msg.sender, _numTokens));
        emit _VotingRightsWithdrawn(_numTokens, msg.sender);
    }

    /**
    @dev Unlocks tokens locked in unrevealed vote where poll has ended
    @param _pollID Integer identifier associated with the target poll
    */
    function rescueTokens(uint _pollID) public {
        require(isExpired(pollMap[_pollID].revealEndDate));
        require(dllMap[msg.sender].contains(_pollID));

        dllMap[msg.sender].remove(_pollID);
        emit _TokensRescued(_pollID, msg.sender);
    }

    /**
    @dev Unlocks tokens locked in unrevealed votes where polls have ended
    @param _pollIDs Array of integer identifiers associated with the target polls
    */
    function rescueTokensInMultiplePolls(uint[] _pollIDs) public {
        // loop through arrays, rescuing tokens from all
        for (uint i = 0; i < _pollIDs.length; i++) {
            rescueTokens(_pollIDs[i]);
        }
    }

    // =================
    // VOTING INTERFACE:
    // =================

    /**
    @notice Commits vote using hash of choice and secret salt to conceal vote until reveal
    @param _pollID Integer identifier associated with target poll
    @param _secretHash Commit keccak256 hash of voter's choice and salt (tightly packed in this order)
    @param _numTokens The number of tokens to be committed towards the target poll
    @param _prevPollID The ID of the poll that the user has voted the maximum number of tokens in which is still less than or equal to numTokens
    */
    function commitVote(uint _pollID, bytes32 _secretHash, uint _numTokens, uint _prevPollID) public {
        require(commitPeriodActive(_pollID));

        // if msg.sender doesn't have enough voting rights,
        // request for enough voting rights
        if (voteTokenBalance[msg.sender] < _numTokens) {
            uint remainder = _numTokens.sub(voteTokenBalance[msg.sender]);
            requestVotingRights(remainder);
        }

        // make sure msg.sender has enough voting rights
        require(voteTokenBalance[msg.sender] >= _numTokens);
        // prevent user from committing to zero node placeholder
        require(_pollID != 0);
        // prevent user from committing a secretHash of 0
        require(_secretHash != 0);

        // Check if _prevPollID exists in the user's DLL or if _prevPollID is 0
        require(_prevPollID == 0 || dllMap[msg.sender].contains(_prevPollID));

        uint nextPollID = dllMap[msg.sender].getNext(_prevPollID);

        // edge case: in-place update
        if (nextPollID == _pollID) {
            nextPollID = dllMap[msg.sender].getNext(_pollID);
        }

        require(validPosition(_prevPollID, nextPollID, msg.sender, _numTokens));
        dllMap[msg.sender].insert(_prevPollID, _pollID, nextPollID);

        bytes32 UUID = attrUUID(msg.sender, _pollID);

        store.setAttribute(UUID, "numTokens", _numTokens);
        store.setAttribute(UUID, "commitHash", uint(_secretHash));

        pollMap[_pollID].didCommit[msg.sender] = true;
        emit _VoteCommitted(_pollID, _numTokens, msg.sender);
    }

    /**
    @notice                 Commits votes using hashes of choices and secret salts to conceal votes until reveal
    @param _pollIDs         Array of integer identifiers associated with target polls
    @param _secretHashes    Array of commit keccak256 hashes of voter's choices and salts (tightly packed in this order)
    @param _numsTokens      Array of numbers of tokens to be committed towards the target polls
    @param _prevPollIDs     Array of IDs of the polls that the user has voted the maximum number of tokens in which is still less than or equal to numTokens
    */
    function commitVotes(uint[] _pollIDs, bytes32[] _secretHashes, uint[] _numsTokens, uint[] _prevPollIDs) external {
        // make sure the array lengths are all the same
        require(_pollIDs.length == _secretHashes.length);
        require(_pollIDs.length == _numsTokens.length);
        require(_pollIDs.length == _prevPollIDs.length);

        // loop through arrays, committing each individual vote values
        for (uint i = 0; i < _pollIDs.length; i++) {
            commitVote(_pollIDs[i], _secretHashes[i], _numsTokens[i], _prevPollIDs[i]);
        }
    }

    /**
    @dev Compares previous and next poll's committed tokens for sorting purposes
    @param _prevID Integer identifier associated with previous poll in sorted order
    @param _nextID Integer identifier associated with next poll in sorted order
    @param _voter Address of user to check DLL position for
    @param _numTokens The number of tokens to be committed towards the poll (used for sorting)
    @return valid Boolean indication of if the specified position maintains the sort
    */
    function validPosition(uint _prevID, uint _nextID, address _voter, uint _numTokens) public constant returns (bool valid) {
        bool prevValid = (_numTokens >= getNumTokens(_voter, _prevID));
        // if next is zero node, _numTokens does not need to be greater
        bool nextValid = (_numTokens <= getNumTokens(_voter, _nextID) || _nextID == 0);
        return prevValid && nextValid;
    }

    /**
    @notice Reveals vote with choice and secret salt used in generating commitHash to attribute committed tokens
    @param _pollID Integer identifier associated with target poll
    @param _voteOption Vote choice used to generate commitHash for associated poll
    @param _salt Secret number used to generate commitHash for associated poll
    */
    function revealVote(uint _pollID, uint _voteOption, uint _salt) public {
        // Make sure the reveal period is active
        require(revealPeriodActive(_pollID));
        require(pollMap[_pollID].didCommit[msg.sender]);                         // make sure user has committed a vote for this poll
        require(!pollMap[_pollID].didReveal[msg.sender]);                        // prevent user from revealing multiple times
        require(keccak256(_voteOption, _salt) == getCommitHash(msg.sender, _pollID)); // compare resultant hash from inputs to original commitHash

        uint numTokens = getNumTokens(msg.sender, _pollID);

        if (_voteOption == 1) {// apply numTokens to appropriate poll choice
            pollMap[_pollID].votesFor += numTokens;
        } else {
            pollMap[_pollID].votesAgainst += numTokens;
        }

        dllMap[msg.sender].remove(_pollID); // remove the node referring to this vote upon reveal
        pollMap[_pollID].didReveal[msg.sender] = true;

        emit _VoteRevealed(_pollID, numTokens, pollMap[_pollID].votesFor, pollMap[_pollID].votesAgainst, _voteOption, msg.sender, _salt);
    }

    /**
    @notice             Reveals multiple votes with choices and secret salts used in generating commitHashes to attribute committed tokens
    @param _pollIDs     Array of integer identifiers associated with target polls
    @param _voteOptions Array of vote choices used to generate commitHashes for associated polls
    @param _salts       Array of secret numbers used to generate commitHashes for associated polls
    */
    function revealVotes(uint[] _pollIDs, uint[] _voteOptions, uint[] _salts) external {
        // make sure the array lengths are all the same
        require(_pollIDs.length == _voteOptions.length);
        require(_pollIDs.length == _salts.length);

        // loop through arrays, revealing each individual vote values
        for (uint i = 0; i < _pollIDs.length; i++) {
            revealVote(_pollIDs[i], _voteOptions[i], _salts[i]);
        }
    }

    /**
    @param _pollID Integer identifier associated with target poll
    @param _salt Arbitrarily chosen integer used to generate secretHash
    @return correctVotes Number of tokens voted for winning option
    */
    function getNumPassingTokens(address _voter, uint _pollID, uint _salt) public constant returns (uint correctVotes) {
        require(pollEnded(_pollID));
        require(pollMap[_pollID].didReveal[_voter]);

        uint winningChoice = isPassed(_pollID) ? 1 : 0;
        bytes32 winnerHash = keccak256(winningChoice, _salt);
        bytes32 commitHash = getCommitHash(_voter, _pollID);

        require(winnerHash == commitHash);

        return getNumTokens(_voter, _pollID);
    }

    // ==================
    // POLLING INTERFACE:
    // ==================

    /**
    @dev Initiates a poll with canonical configured parameters at pollID emitted by PollCreated event
    @param _voteQuorum Type of majority (out of 100) that is necessary for poll to be successful
    @param _commitDuration Length of desired commit period in seconds
    @param _revealDuration Length of desired reveal period in seconds
    */
    function startPoll(uint _voteQuorum, uint _commitDuration, uint _revealDuration) public returns (uint pollID) {
        pollNonce = pollNonce + 1;

        uint commitEndDate = block.timestamp.add(_commitDuration);
        uint revealEndDate = commitEndDate.add(_revealDuration);

        pollMap[pollNonce] = Poll({
            voteQuorum: _voteQuorum,
            commitEndDate: commitEndDate,
            revealEndDate: revealEndDate,
            votesFor: 0,
            votesAgainst: 0
        });

        emit _PollCreated(_voteQuorum, commitEndDate, revealEndDate, pollNonce, msg.sender);
        return pollNonce;
    }

    /**
    @notice Determines if proposal has passed
    @dev Check if votesFor out of totalVotes exceeds votesQuorum (requires pollEnded)
    @param _pollID Integer identifier associated with target poll
    */
    function isPassed(uint _pollID) constant public returns (bool passed) {
        require(pollEnded(_pollID));

        Poll memory poll = pollMap[_pollID];
        return (100 * poll.votesFor) > (poll.voteQuorum * (poll.votesFor + poll.votesAgainst));
    }

    // ----------------
    // POLLING HELPERS:
    // ----------------

    /**
    @dev Gets the total winning votes for reward distribution purposes
    @param _pollID Integer identifier associated with target poll
    @return Total number of votes committed to the winning option for specified poll
    */
    function getTotalNumberOfTokensForWinningOption(uint _pollID) constant public returns (uint numTokens) {
        require(pollEnded(_pollID));

        if (isPassed(_pollID))
            return pollMap[_pollID].votesFor;
        else
            return pollMap[_pollID].votesAgainst;
    }

    /**
    @notice Determines if poll is over
    @dev Checks isExpired for specified poll's revealEndDate
    @return Boolean indication of whether polling period is over
    */
    function pollEnded(uint _pollID) constant public returns (bool ended) {
        require(pollExists(_pollID));

        return isExpired(pollMap[_pollID].revealEndDate);
    }

    /**
    @notice Checks if the commit period is still active for the specified poll
    @dev Checks isExpired for the specified poll's commitEndDate
    @param _pollID Integer identifier associated with target poll
    @return Boolean indication of isCommitPeriodActive for target poll
    */
    function commitPeriodActive(uint _pollID) constant public returns (bool active) {
        require(pollExists(_pollID));

        return !isExpired(pollMap[_pollID].commitEndDate);
    }

    /**
    @notice Checks if the reveal period is still active for the specified poll
    @dev Checks isExpired for the specified poll's revealEndDate
    @param _pollID Integer identifier associated with target poll
    */
    function revealPeriodActive(uint _pollID) constant public returns (bool active) {
        require(pollExists(_pollID));

        return !isExpired(pollMap[_pollID].revealEndDate) && !commitPeriodActive(_pollID);
    }

    /**
    @dev Checks if user has committed for specified poll
    @param _voter Address of user to check against
    @param _pollID Integer identifier associated with target poll
    @return Boolean indication of whether user has committed
    */
    function didCommit(address _voter, uint _pollID) constant public returns (bool committed) {
        require(pollExists(_pollID));

        return pollMap[_pollID].didCommit[_voter];
    }

    /**
    @dev Checks if user has revealed for specified poll
    @param _voter Address of user to check against
    @param _pollID Integer identifier associated with target poll
    @return Boolean indication of whether user has revealed
    */
    function didReveal(address _voter, uint _pollID) constant public returns (bool revealed) {
        require(pollExists(_pollID));

        return pollMap[_pollID].didReveal[_voter];
    }

    /**
    @dev Checks if a poll exists
    @param _pollID The pollID whose existance is to be evaluated.
    @return Boolean Indicates whether a poll exists for the provided pollID
    */
    function pollExists(uint _pollID) constant public returns (bool exists) {
        return (_pollID != 0 && _pollID <= pollNonce);
    }

    // ---------------------------
    // DOUBLE-LINKED-LIST HELPERS:
    // ---------------------------

    /**
    @dev Gets the bytes32 commitHash property of target poll
    @param _voter Address of user to check against
    @param _pollID Integer identifier associated with target poll
    @return Bytes32 hash property attached to target poll
    */
    function getCommitHash(address _voter, uint _pollID) constant public returns (bytes32 commitHash) {
        return bytes32(store.getAttribute(attrUUID(_voter, _pollID), "commitHash"));
    }

    /**
    @dev Wrapper for getAttribute with attrName="numTokens"
    @param _voter Address of user to check against
    @param _pollID Integer identifier associated with target poll
    @return Number of tokens committed to poll in sorted poll-linked-list
    */
    function getNumTokens(address _voter, uint _pollID) constant public returns (uint numTokens) {
        return store.getAttribute(attrUUID(_voter, _pollID), "numTokens");
    }

    /**
    @dev Gets top element of sorted poll-linked-list
    @param _voter Address of user to check against
    @return Integer identifier to poll with maximum number of tokens committed to it
    */
    function getLastNode(address _voter) constant public returns (uint pollID) {
        return dllMap[_voter].getPrev(0);
    }

    /**
    @dev Gets the numTokens property of getLastNode
    @param _voter Address of user to check against
    @return Maximum number of tokens committed in poll specified
    */
    function getLockedTokens(address _voter) constant public returns (uint numTokens) {
        return getNumTokens(_voter, getLastNode(_voter));
    }

    /*
    @dev Takes the last node in the user's DLL and iterates backwards through the list searching
    for a node with a value less than or equal to the provided _numTokens value. When such a node
    is found, if the provided _pollID matches the found nodeID, this operation is an in-place
    update. In that case, return the previous node of the node being updated. Otherwise return the
    first node that was found with a value less than or equal to the provided _numTokens.
    @param _voter The voter whose DLL will be searched
    @param _numTokens The value for the numTokens attribute in the node to be inserted
    @return the node which the propoded node should be inserted after
    */
    function getInsertPointForNumTokens(address _voter, uint _numTokens, uint _pollID)
    constant public returns (uint prevNode) {
      // Get the last node in the list and the number of tokens in that node
      uint nodeID = getLastNode(_voter);
      uint tokensInNode = getNumTokens(_voter, nodeID);

      // Iterate backwards through the list until reaching the root node
      while(nodeID != 0) {
        // Get the number of tokens in the current node
        tokensInNode = getNumTokens(_voter, nodeID);
        if(tokensInNode <= _numTokens) { // We found the insert point!
          if(nodeID == _pollID) {
            // This is an in-place update. Return the prev node of the node being updated
            nodeID = dllMap[_voter].getPrev(nodeID);
          }
          // Return the insert point
          return nodeID;
        }
        // We did not find the insert point. Continue iterating backwards through the list
        nodeID = dllMap[_voter].getPrev(nodeID);
      }

      // The list is empty, or a smaller value than anything else in the list is being inserted
      return nodeID;
    }

    // ----------------
    // GENERAL HELPERS:
    // ----------------

    /**
    @dev Checks if an expiration date has been reached
    @param _terminationDate Integer timestamp of date to compare current timestamp with
    @return expired Boolean indication of whether the terminationDate has passed
    */
    function isExpired(uint _terminationDate) constant public returns (bool expired) {
        return (block.timestamp > _terminationDate);
    }

    /**
    @dev Generates an identifier which associates a user and a poll together
    @param _pollID Integer identifier associated with target poll
    @return UUID Hash which is deterministic from _user and _pollID
    */
    function attrUUID(address _user, uint _pollID) public pure returns (bytes32 UUID) {
        return keccak256(_user, _pollID);
    }
}

// File: contracts/proof-of-use/telemetry/TokenTelemetryI.sol

pragma solidity ^0.4.23;

interface TokenTelemetryI {
  function onRequestVotingRights(address user, uint tokenAmount) external;
}

// File: contracts/tcr/CivilPLCRVoting.sol

pragma solidity ^0.4.23;



/**
@title Partial-Lock-Commit-Reveal Voting scheme with ERC20 tokens
*/
contract CivilPLCRVoting is PLCRVoting {

  TokenTelemetryI public telemetry;

  /**
  @dev Initializer. Can only be called once.
  @param tokenAddr The address where the ERC20 token contract is deployed
  @param telemetryAddr The address where the TokenTelemetry contract is deployed
  */
  constructor(address tokenAddr, address telemetryAddr) public PLCRVoting(tokenAddr) {
    require(telemetryAddr != 0);
    telemetry = TokenTelemetryI(telemetryAddr);
  }

  /**
    @notice Loads _numTokens ERC20 tokens into the voting contract for one-to-one voting rights
    @dev Assumes that msg.sender has approved voting contract to spend on their behalf
    @param _numTokens The number of votingTokens desired in exchange for ERC20 tokens
    @dev Differs from base implementation in that it records use of token in mapping for "proof of use"
  */
  function requestVotingRights(uint _numTokens) public {
    super.requestVotingRights(_numTokens);
    telemetry.onRequestVotingRights(msg.sender, voteTokenBalance[msg.sender]);
  }

  /**
  @param _pollID Integer identifier associated with target poll
  @param _salt Arbitrarily chosen integer used to generate secretHash
  @return correctVotes Number of tokens voted for losing option
  */
  function getNumLosingTokens(address _voter, uint _pollID, uint _salt) public view returns (uint correctVotes) {
    require(pollEnded(_pollID));
    require(pollMap[_pollID].didReveal[_voter]);

    uint losingChoice = isPassed(_pollID) ? 0 : 1;
    bytes32 loserHash = keccak256(losingChoice, _salt);
    bytes32 commitHash = getCommitHash(_voter, _pollID);

    require(loserHash == commitHash);

    return getNumTokens(_voter, _pollID);
  }

  /**
  @dev Gets the total losing votes for reward distribution purposes
  @param _pollID Integer identifier associated with target poll
  @return Total number of votes committed to the losing option for specified poll
  */
  function getTotalNumberOfTokensForLosingOption(uint _pollID) public view returns (uint numTokens) {
    require(pollEnded(_pollID));

    if (isPassed(_pollID))
      return pollMap[_pollID].votesAgainst;
    else
      return pollMap[_pollID].votesFor;
  }

}

Read Contract

INITIAL_POLL_NONCE 0x2173a10f → uint256
attrUUID 0xa1103f37 → bytes32
commitPeriodActive 0xa4439dc5 → bool
didCommit 0x7f97e836 → bool
didReveal 0xaa7ca464 → bool
getCommitHash 0xd901402b → bytes32
getInsertPointForNumTokens 0x2c052031 → uint256
getLastNode 0x427fa1d2 → uint256
getLockedTokens 0x6b2d95d4 → uint256
getNumLosingTokens 0x6afa97a8 → uint256
getNumPassingTokens 0xb43bd069 → uint256
getNumTokens 0xd1382092 → uint256
getTotalNumberOfTokensForLosingOption 0xe8cfa3f0 → uint256
getTotalNumberOfTokensForWinningOption 0x053e71a6 → uint256
isExpired 0xd9548e53 → bool
isPassed 0x49403183 → bool
pollEnded 0xee684830 → bool
pollExists 0x88d21ff3 → bool
pollMap 0x6148fed5 → uint256, uint256, uint256, uint256, uint256
pollNonce 0x97508f36 → uint256
revealPeriodActive 0x441c77c0 → bool
telemetry 0x40f41c19 → address
token 0xfc0c546a → address
validPosition 0x819b0293 → bool
voteTokenBalance 0x3b930294 → uint256

Write Contract 9 functions

These functions modify contract state and require a wallet transaction to execute.

commitVote 0x6cbf9c5e
uint256 _pollID
bytes32 _secretHash
uint256 _numTokens
uint256 _prevPollID
commitVotes 0x3ec36b99
uint256[] _pollIDs
bytes32[] _secretHashes
uint256[] _numsTokens
uint256[] _prevPollIDs
requestVotingRights 0xa25236fe
uint256 _numTokens
rescueTokens 0x97603560
uint256 _pollID
rescueTokensInMultiplePolls 0xbb11ed7e
uint256[] _pollIDs
revealVote 0xb11d8bb8
uint256 _pollID
uint256 _voteOption
uint256 _salt
revealVotes 0x8090f92e
uint256[] _pollIDs
uint256[] _voteOptions
uint256[] _salts
startPoll 0x32ed3d60
uint256 _voteQuorum
uint256 _commitDuration
uint256 _revealDuration
returns: uint256
withdrawVotingRights 0xe7b1d43c
uint256 _numTokens

Recent Transactions

No transactions found for this address