Make state public

Make state public

//SPDX-License-Identifier: MIT
pragma solidity >=0.8.4;

import "@openzeppelin/contracts/access/Ownable.sol";

import "@chainlink/contracts/src/v0.8/VRFConsumerBase.sol";

interface IKetherHomepage {
  function ads(uint _idx) external view returns (address,uint,uint,uint,uint,string memory,string memory,string memory,bool,bool);
  function getAdsLength() view external returns (uint);
}

interface IERC721 {
  function ownerOf(uint256) external view returns (address);
  function balanceOf(address) external view returns (uint256);
  function tokenOfOwnerByIndex(address, uint256) external view returns (uint256);
}

interface IERC20 {
  function balanceOf(address account) external view returns (uint256);
  function transfer(address recipient, uint256 amount) external returns (bool);
}

library Errors {
  string constant MustOwnToken = "must own token";
  string constant OnlyMagistrate = "only active magistrate can do this";
  string constant MustHaveEntropy = "waiting for entropy";
  string constant MustHaveNominations = "must have nominations";
  string constant AlreadyStarted = "election already started";
  string constant NotExecuted = "election not executed";
  string constant TermNotExpired = "term not expired";
  string constant NotEnoughLink = "not enough LINK";
  string constant NotNominated = "token is not nominated";
}

contract KetherSortition is Ownable, VRFConsumerBase {
  event Nominated(
      uint256 indexed termNumber,
      address nominator,
      uint256 pixels
  );

  event ElectionExecuting(
    uint256 indexed termNumber
  );

  event ElectionCompleted(
    uint256 indexed termNumber,
    uint256 magistrateToken,
    address currentTokenOwner
  );

  event StepDown(
    uint256 indexed termNumber,
    uint256 magistrateToken,
    address currentTokenOwner
  );

  event ReceivedPayment(
    uint256 indexed termNumber,
    uint256 value
  );

  struct Nomination{
    uint256 termNumber;
    uint256 nominatedToken;
  }
  uint256 constant PIXELS_PER_CELL = 100;

  /// @notice tokenId of an NFT whose owner controls the royalties purse for this term.
  uint256 public magistrateToken;
  /// @notice length of magistrate term
  uint256 public termDuration;
  /// @notice minimum time period for new nominations (e.g. if a magistrate steps down)
  uint256 public minElectionDuration;
  /// @notice timestamp of start of current term
  uint256 public termStarted;
  /// @notice timestamp of end of current term
  uint256 public termExpires;
  /// @notice current term
  uint256 public termNumber = 0;

  IERC721 ketherNFTContract;
  IKetherHomepage ketherContract;

  /// @dev tokenIDs nominated in the current term
  uint256[] public nominatedTokens;
  /// @dev count of pixels nominated in the current term
  uint256 public nominatedPixels = 0;
  mapping(uint256 => Nomination) nominations; // mapping of tokenId => {termNumber, nominatedToken}

  /// @dev provided by Chainlink
  uint256 public electionEntropy;

  // nominating -[term expired & startElection() calls]> waitingForEntropy -[Chainlink calls into fulfillrandomness()]> gotEntropy -[completeElection()] -> nominating
  enum StateMachine { NOMINATING, WAITING_FOR_ENTROPY, GOT_ENTROPY }
  StateMachine public state = StateMachine.NOMINATING;

  // Chainlink values
  bytes32 private s_keyHash;
  uint256 private s_fee;

  constructor(address _ketherNFTContract, address _ketherContract, address vrfCoordinator, address link, bytes32 keyHash, uint256 fee, uint256 _termDuration, uint256 _minElectionDuration ) VRFConsumerBase(vrfCoordinator, link) {
    s_keyHash = keyHash;
    s_fee = fee;

    ketherNFTContract = IERC721(_ketherNFTContract);
    ketherContract = IKetherHomepage(_ketherContract);

    termDuration = _termDuration;
    minElectionDuration = _minElectionDuration;
    termExpires = block.timestamp + _termDuration;
  }

  receive() external payable {
    emit ReceivedPayment(termNumber, msg.value);
  }

  // Internal helpers:

  /**
   * @notice Only callable by Chainlink VRF, async triggered via startElection().
   */
  function fulfillRandomness(bytes32 requestId, uint256 randomness) internal override {
    require(state == StateMachine.WAITING_FOR_ENTROPY, Errors.NotExecuted);
    electionEntropy = randomness;
    state = StateMachine.GOT_ENTROPY;
  }

  /// @dev _nominate does not check token ownership, must already be checked.
  /// @param _ownedTokenId Token to nominate from
  /// @param _nominateTokenId Token to nominate to.
  function _nominate(uint256 _ownedTokenId, uint256 _nominateTokenId) internal returns (uint256 pixels) {
    // Only push the ad and update pixel count if it's not been nominated before
    if (!isNominated(_ownedTokenId)) {
      pixels += getAdPixels(_ownedTokenId);
      nominatedTokens.push(_ownedTokenId);
    }

    nominations[_ownedTokenId] = Nomination(termNumber + 1, _nominateTokenId);

    return pixels;
  }

  /// @dev _nominate does not check token ownership, must already be checked.
  /// @param _nominateSelf if true each token nominates itself
  /// @param _nominateTokenId if nominateSelf is false, token to nominate to. Must be a NFT-wrapped token
  function _nominateAll(bool _nominateSelf, uint256 _nominateTokenId) internal returns (uint256) {
    require(state == StateMachine.NOMINATING, Errors.AlreadyStarted);
    address sender = _msgSender();
    require(ketherNFTContract.balanceOf(sender) > 0, Errors.MustOwnToken);
    // This checks that the _nominateTokenId is minted, will revert otherwise
    require(_nominateSelf || ketherNFTContract.ownerOf(_nominateTokenId) != address(0));

    uint256 pixels = 0;
    for (uint256 i = 0; i < ketherNFTContract.balanceOf(sender); i++) {
      uint256 idx = ketherNFTContract.tokenOfOwnerByIndex(sender, i);
      if (_nominateSelf) {
        pixels += _nominate(idx, idx);
      } else {
        pixels += _nominate(idx, _nominateTokenId);
      }
    }

    nominatedPixels += pixels;

    // Note this is emitted in the helper while `nominate` emits the event in the public function
    emit Nominated(termNumber+1, sender, pixels);
    return pixels;
  }

  // Views:

  function getMagistrate() public view returns (address) {
    return getAdOwner(magistrateToken);
  }

  function getAdOwner(uint256 _idx) public view returns (address) {
    return ketherNFTContract.ownerOf(_idx);
  }

  function getAdPixels(uint256 _idx) public view returns (uint256) {
    (,,,uint width,uint height,,,,,) = ketherContract.ads(_idx);
    return width * height * PIXELS_PER_CELL;
  }

  function isNominated(uint256 _idx) public view returns (bool) {
    return nominations[_idx].termNumber > termNumber;
  }

  function getNominatedToken(uint256 _idx) public view returns (uint256) {
    require(isNominated(_idx), Errors.NotNominated);

    return nominations[_idx].nominatedToken;
  }

  function getNextMagistrateToken() public view returns (uint256) {
    require(state == StateMachine.GOT_ENTROPY, Errors.MustHaveEntropy);
    require(nominatedTokens.length > 0, Errors.MustHaveNominations);

    uint256 pixelChosen = electionEntropy % nominatedPixels;
    uint256 curPixel = 0;

    for(uint256 i = 0; i < nominatedTokens.length; i++) {
      uint256 idx = nominatedTokens[i];
      curPixel += getAdPixels(idx);
      if (curPixel > pixelChosen) {
        return getNominatedToken(idx);
      }
    }
    return 0;
  }

  // External interface:

  /**
   * @notice Nominate tokens held by the sender as candidates for magistrate in the next term.
   *      Nominations of tokens are independent of their owner.
   * @param _ownedTokenId Token to nominate from
   * @param _nominateTokenId tokenId to count nominations towards. Must be an NFT-wrapped token.
   * @return Number of nominated pixels.
   *
   * Emits {Nominated} event.
   */
  function nominate(uint256 _ownedTokenId, uint256 _nominateTokenId) external returns (uint256) {
    require(state == StateMachine.NOMINATING, Errors.AlreadyStarted);
    address sender = _msgSender();
    require(ketherNFTContract.ownerOf(_ownedTokenId) == sender, Errors.MustOwnToken);
    // This checks that the _nominateTokenId is minted, will revert otherwise
    require(ketherNFTContract.ownerOf(_nominateTokenId) != address(0));
    uint256 pixels = _nominate(_ownedTokenId, _nominateTokenId);

    // Note this is emitted in the public function while `_nominateAll` emits the event in the helper
    emit Nominated(termNumber+1, sender, pixels);

    return pixels;
  }

  /**
   * @notice Nominate tokens held by the sender as candidates towards a specific `_nominateTokenId` as magistrate in the next term
   * @param _nominateTokenId tokenId to count nominations towards. Must be an NFT-wrapped token.
   * @return Number of nominated pixels.
   *
   * Emits {Nominated} event.
   */
  function nominateAll(uint256 _nominateTokenId) public returns (uint256) {
    return _nominateAll(false, _nominateTokenId);
  }

  /**
   * @notice Nominate tokens held by the sender as candidates towards a specific `_nominateTokenId` as magistrate in the next term
   * @return Number of nominated pixels.
   *
   * Emits {Nominated} event.
   */
  function nominateSelf() public returns (uint256) {
    return _nominateAll(true, 0);
  }

  /**
   * @notice Stop accepting nominations, start election.
   *
   * Emits {ElectionExecuting} event.
   */
  function startElection() external {
    require(state == StateMachine.NOMINATING, Errors.AlreadyStarted);
    require(nominatedTokens.length > 0, Errors.MustHaveNominations);
    require(termExpires <= block.timestamp, Errors.TermNotExpired);
    require(LINK.balanceOf(address(this)) >= s_fee, Errors.NotEnoughLink);

    state = StateMachine.WAITING_FOR_ENTROPY;
    requestRandomness(s_keyHash, s_fee);

    emit ElectionExecuting(termNumber);
  }

  /**
   * @notice Assign new magistrate and open up for nominations for next election.
   *
   * Emits {ElectionCompleted} event.
   */
  function completeElection() external {
    require(state == StateMachine.GOT_ENTROPY, Errors.MustHaveEntropy);
    magistrateToken = getNextMagistrateToken();

    termNumber += 1;
    termStarted = block.timestamp;
    termExpires = termStarted + termDuration;

    delete nominatedTokens;
    nominatedPixels = 0;
    state = StateMachine.NOMINATING;

    emit ElectionCompleted(termNumber, magistrateToken, getMagistrate());
  }

  // Only magistrate:

  /// @notice Transfer balance controlled by magistrate.
  /// @notice Magistrate has exclusive rights to withdraw until the end of term.
  /// @notice Remaining balance after the next election is rolled over to the next magistrate.
  function withdraw(address payable to) public {
    require(_msgSender() == getMagistrate(), Errors.OnlyMagistrate);
    // TODO: Someday, would it be fun if this required having a >2 LINK balance to
    // withdraw? If we wanna be super cute, could automagically buy LINK from
    // the proceeds before transferring the remaining balance.

    to.transfer(address(this).balance);
  }

  /// @notice Cut the term short, leaving enough time for new nominations.
  /// Emits {StepDown} event.
  function stepDown() public {
    require(_msgSender() == getMagistrate(), Errors.OnlyMagistrate);

    uint256 timeRemaining = termExpires - block.timestamp;
    if (timeRemaining > minElectionDuration) {
      termExpires = block.timestamp + minElectionDuration;
    }

    emit StepDown(termNumber, magistrateToken, _msgSender());
  }

  // Only owner (admin helpers):

  /**
   * @notice Withdraw ERC20 tokens, primarily for rescuing remaining LINK once the experiment is over.
   */
  function adminWithdrawToken(IERC20 token, address to) external onlyOwner {
    token.transfer(to, token.balanceOf(address(this)));
  }
}

//SPDX-License-Identifier: MIT
pragma solidity >=0.8.4;

import "@openzeppelin/contracts/access/Ownable.sol";

import "@chainlink/contracts/src/v0.8/VRFConsumerBase.sol";

interface IKetherHomepage {
  function ads(uint _idx) external view returns (address,uint,uint,uint,uint,string memory,string memory,string memory,bool,bool);
  function getAdsLength() view external returns (uint);
}

interface IERC721 {
  function ownerOf(uint256) external view returns (address);
  function balanceOf(address) external view returns (uint256);
  function tokenOfOwnerByIndex(address, uint256) external view returns (uint256);
}

interface IERC20 {
  function balanceOf(address account) external view returns (uint256);
  function transfer(address recipient, uint256 amount) external returns (bool);
}

library Errors {
  string constant MustOwnToken = "must own token";
  string constant OnlyMagistrate = "only active magistrate can do this";
  string constant MustHaveEntropy = "waiting for entropy";
  string constant MustHaveNominations = "must have nominations";
  string constant AlreadyStarted = "election already started";
  string constant NotExecuted = "election not executed";
  string constant TermNotExpired = "term not expired";
  string constant NotEnoughLink = "not enough LINK";
  string constant NotNominated = "token is not nominated";
}

contract KetherSortition is Ownable, VRFConsumerBase {
  event Nominated(
      uint256 indexed termNumber,
      address nominator,
      uint256 pixels
  );

  event ElectionExecuting(
    uint256 indexed termNumber
  );

  event ElectionCompleted(
    uint256 indexed termNumber,
    uint256 magistrateToken,
    address currentTokenOwner
  );

  event StepDown(
    uint256 indexed termNumber,
    uint256 magistrateToken,
    address currentTokenOwner
  );

  event ReceivedPayment(
    uint256 indexed termNumber,
    uint256 value
  );

  struct Nomination{
    uint256 termNumber;
    uint256 nominatedToken;
  }
  uint256 constant PIXELS_PER_CELL = 100;

  /// @notice tokenId of an NFT whose owner controls the royalties purse for this term.
  uint256 public magistrateToken;
  /// @notice length of magistrate term
  uint256 public termDuration;
  /// @notice minimum time period for new nominations (e.g. if a magistrate steps down)
  uint256 public minElectionDuration;
  /// @notice timestamp of start of current term
  uint256 public termStarted;
  /// @notice timestamp of end of current term
  uint256 public termExpires;
  /// @notice current term
  uint256 public termNumber = 0;

  IERC721 ketherNFTContract;
  IKetherHomepage ketherContract;

  /// @dev tokenIDs nominated in the current term
  uint256[] public nominatedTokens;
  /// @dev count of pixels nominated in the current term
  uint256 public nominatedPixels = 0;
  mapping(uint256 => Nomination) nominations; // mapping of tokenId => {termNumber, nominatedToken}

  /// @dev provided by Chainlink
  uint256 public electionEntropy;

  // nominating -[term expired & startElection() calls]> waitingForEntropy -[Chainlink calls into fulfillrandomness()]> gotEntropy -[completeElection()] -> nominating
  enum StateMachine { NOMINATING, WAITING_FOR_ENTROPY, GOT_ENTROPY }
  StateMachine state = StateMachine.NOMINATING;

  // Chainlink values
  bytes32 private s_keyHash;
  uint256 private s_fee;

  constructor(address _ketherNFTContract, address _ketherContract, address vrfCoordinator, address link, bytes32 keyHash, uint256 fee, uint256 _termDuration, uint256 _minElectionDuration ) VRFConsumerBase(vrfCoordinator, link) {
    s_keyHash = keyHash;
    s_fee = fee;

    ketherNFTContract = IERC721(_ketherNFTContract);
    ketherContract = IKetherHomepage(_ketherContract);

    termDuration = _termDuration;
    minElectionDuration = _minElectionDuration;
    termExpires = block.timestamp + _termDuration;
  }

  receive() external payable {
    emit ReceivedPayment(termNumber, msg.value);
  }

  // Internal helpers:

  /**
   * @notice Only callable by Chainlink VRF, async triggered via startElection().
   */
  function fulfillRandomness(bytes32 requestId, uint256 randomness) internal override {
    require(state == StateMachine.WAITING_FOR_ENTROPY, Errors.NotExecuted);
    electionEntropy = randomness;
    state = StateMachine.GOT_ENTROPY;
  }

  /// @dev _nominate does not check token ownership, must already be checked.
  /// @param _ownedTokenId Token to nominate from
  /// @param _nominateTokenId Token to nominate to.
  function _nominate(uint256 _ownedTokenId, uint256 _nominateTokenId) internal returns (uint256 pixels) {
    // Only push the ad and update pixel count if it's not been nominated before
    if (!isNominated(_ownedTokenId)) {
      pixels += getAdPixels(_ownedTokenId);
      nominatedTokens.push(_ownedTokenId);
    }

    nominations[_ownedTokenId] = Nomination(termNumber + 1, _nominateTokenId);

    return pixels;
  }

  /// @dev _nominate does not check token ownership, must already be checked.
  /// @param _nominateSelf if true each token nominates itself
  /// @param _nominateTokenId if nominateSelf is false, token to nominate to. Must be a NFT-wrapped token
  function _nominateAll(bool _nominateSelf, uint256 _nominateTokenId) internal returns (uint256) {
    require(state == StateMachine.NOMINATING, Errors.AlreadyStarted);
    address sender = _msgSender();
    require(ketherNFTContract.balanceOf(sender) > 0, Errors.MustOwnToken);
    // This checks that the _nominateTokenId is minted, will revert otherwise
    require(_nominateSelf || ketherNFTContract.ownerOf(_nominateTokenId) != address(0));

    uint256 pixels = 0;
    for (uint256 i = 0; i < ketherNFTContract.balanceOf(sender); i++) {
      uint256 idx = ketherNFTContract.tokenOfOwnerByIndex(sender, i);
      if (_nominateSelf) {
        pixels += _nominate(idx, idx);
      } else {
        pixels += _nominate(idx, _nominateTokenId);
      }
    }

    nominatedPixels += pixels;

    // Note this is emitted in the helper while `nominate` emits the event in the public function
    emit Nominated(termNumber+1, sender, pixels);
    return pixels;
  }

  // Views:

  function getMagistrate() public view returns (address) {
    return getAdOwner(magistrateToken);
  }

  function getAdOwner(uint256 _idx) public view returns (address) {
    return ketherNFTContract.ownerOf(_idx);
  }

  function getAdPixels(uint256 _idx) public view returns (uint256) {
    (,,,uint width,uint height,,,,,) = ketherContract.ads(_idx);
    return width * height * PIXELS_PER_CELL;
  }

  function isNominated(uint256 _idx) public view returns (bool) {
    return nominations[_idx].termNumber > termNumber;
  }

  function getNominatedToken(uint256 _idx) public view returns (uint256) {
    require(isNominated(_idx), Errors.NotNominated);

    return nominations[_idx].nominatedToken;
  }

  function getNextMagistrateToken() public view returns (uint256) {
    require(state == StateMachine.GOT_ENTROPY, Errors.MustHaveEntropy);
    require(nominatedTokens.length > 0, Errors.MustHaveNominations);

    uint256 pixelChosen = electionEntropy % nominatedPixels;
    uint256 curPixel = 0;

    for(uint256 i = 0; i < nominatedTokens.length; i++) {
      uint256 idx = nominatedTokens[i];
      curPixel += getAdPixels(idx);
      if (curPixel > pixelChosen) {
        return getNominatedToken(idx);
      }
    }
    return 0;
  }

  // External interface:

  /**
   * @notice Nominate tokens held by the sender as candidates for magistrate in the next term.
   *      Nominations of tokens are independent of their owner.
   * @param _ownedTokenId Token to nominate from
   * @param _nominateTokenId tokenId to count nominations towards. Must be an NFT-wrapped token.
   * @return Number of nominated pixels.
   *
   * Emits {Nominated} event.
   */
  function nominate(uint256 _ownedTokenId, uint256 _nominateTokenId) external returns (uint256) {
    require(state == StateMachine.NOMINATING, Errors.AlreadyStarted);
    address sender = _msgSender();
    require(ketherNFTContract.ownerOf(_ownedTokenId) == sender, Errors.MustOwnToken);
    // This checks that the _nominateTokenId is minted, will revert otherwise
    require(ketherNFTContract.ownerOf(_nominateTokenId) != address(0));
    uint256 pixels = _nominate(_ownedTokenId, _nominateTokenId);

    // Note this is emitted in the public function while `_nominateAll` emits the event in the helper
    emit Nominated(termNumber+1, sender, pixels);

    return pixels;
  }

  /**
   * @notice Nominate tokens held by the sender as candidates towards a specific `_nominateTokenId` as magistrate in the next term
   * @param _nominateTokenId tokenId to count nominations towards. Must be an NFT-wrapped token.
   * @return Number of nominated pixels.
   *
   * Emits {Nominated} event.
   */
  function nominateAll(uint256 _nominateTokenId) public returns (uint256) {
    return _nominateAll(false, _nominateTokenId);
  }

  /**
   * @notice Nominate tokens held by the sender as candidates towards a specific `_nominateTokenId` as magistrate in the next term
   * @return Number of nominated pixels.
   *
   * Emits {Nominated} event.
   */
  function nominateSelf() public returns (uint256) {
    return _nominateAll(true, 0);
  }

  /**
   * @notice Stop accepting nominations, start election.
   *
   * Emits {ElectionExecuting} event.
   */
  function startElection() external {
    require(state == StateMachine.NOMINATING, Errors.AlreadyStarted);
    require(nominatedTokens.length > 0, Errors.MustHaveNominations);
    require(termExpires <= block.timestamp, Errors.TermNotExpired);
    require(LINK.balanceOf(address(this)) >= s_fee, Errors.NotEnoughLink);

    state = StateMachine.WAITING_FOR_ENTROPY;
    requestRandomness(s_keyHash, s_fee);

    emit ElectionExecuting(termNumber);
  }

  /**
   * @notice Assign new magistrate and open up for nominations for next election.
   *
   * Emits {ElectionCompleted} event.
   */
  function completeElection() external {
    require(state == StateMachine.GOT_ENTROPY, Errors.MustHaveEntropy);
    magistrateToken = getNextMagistrateToken();

    termNumber += 1;
    termStarted = block.timestamp;
    termExpires = termStarted + termDuration;

    delete nominatedTokens;
    nominatedPixels = 0;
    state = StateMachine.NOMINATING;

    emit ElectionCompleted(termNumber, magistrateToken, getMagistrate());
  }

  // Only magistrate:

  /// @notice Transfer balance controlled by magistrate.
  /// @notice Magistrate has exclusive rights to withdraw until the end of term.
  /// @notice Remaining balance after the next election is rolled over to the next magistrate.
  function withdraw(address payable to) public {
    require(_msgSender() == getMagistrate(), Errors.OnlyMagistrate);
    // TODO: Someday, would it be fun if this required having a >2 LINK balance to
    // withdraw? If we wanna be super cute, could automagically buy LINK from
    // the proceeds before transferring the remaining balance.

    to.transfer(address(this).balance);
  }

  /// @notice Cut the term short, leaving enough time for new nominations.
  /// Emits {StepDown} event.
  function stepDown() public {
    require(_msgSender() == getMagistrate(), Errors.OnlyMagistrate);

    uint256 timeRemaining = termExpires - block.timestamp;
    if (timeRemaining > minElectionDuration) {
      termExpires = block.timestamp + minElectionDuration;
    }

    emit StepDown(termNumber, magistrateToken, _msgSender());
  }

  // Only owner (admin helpers):

  /**
   * @notice Withdraw ERC20 tokens, primarily for rescuing remaining LINK once the experiment is over.
   */
  function adminWithdrawToken(IERC20 token, address to) external onlyOwner {
    token.transfer(to, token.balanceOf(address(this)));
  }
}


Ambix appendSource dynamic conversion setup safety check

pragma solidity ^0.4.24;

import 'openzeppelin-solidity/contracts/token/ERC20/StandardBurnableToken.sol';
import 'openzeppelin-solidity/contracts/ownership/Ownable.sol';

/**
  @dev Ambix contract is used for morph Token set to another
  Token's by rule (recipe). In distillation process given
  Token's are burned and result generated by emission.

  The recipe presented as equation in form:
  (N1 * A1 & N'1 * A'1 & N''1 * A''1 ...)
  | (N2 * A2 & N'2 * A'2 & N''2 * A''2 ...) ...
  | (Nn * An & N'n * A'n & N''n * A''n ...)
  = M1 * B1 & M2 * B2 ... & Mm * Bm
    where A, B - input and output tokens
          N, M - token value coeficients
          n, m - input / output dimetion size
          | - is alternative operator (logical OR)
          & - is associative operator (logical AND)
  This says that `Ambix` should receive (approve) left
  part of equation and send (transfer) right part.
*/
contract Ambix is Ownable {
    address[][] public A;
    uint256[][] public N;
    address[] public B;
    uint256[] public M;

    /**
     * @dev Append token recipe source alternative
     * @param _a Token recipe source token addresses
     * @param _n Token recipe source token counts
     **/
    function appendSource(
        address[] _a,
        uint256[] _n
    ) external onlyOwner {
        uint256 i;

        require(_a.length == _n.length && _a.length > 0);

        for (i = 0; i < _a.length; ++i)
            require(_a[i] != 0);

        if (_n.length == 1 && _n[0] == 0) {
            require(B.length == 1);
        } else {
            for (i = 0; i < _n.length; ++i)
                require(_n[i] > 0);
        }

        A.push(_a);
        N.push(_n);
    }

    /**
     * @dev Set sink of token recipe
     * @param _b Token recipe sink token list
     * @param _m Token recipe sink token counts
     */
    function setSink(
        address[] _b,
        uint256[] _m
    ) external onlyOwner{
        require(_b.length == _m.length);

        for (uint256 i = 0; i < _b.length; ++i)
            require(_b[i] != 0);

        B = _b;
        M = _m;
    }

    /**
     * @dev Run distillation process
     * @param _ix Source alternative index
     */
    function run(uint256 _ix) public {
        require(_ix < A.length);
        uint256 i;

        if (N[_ix][0] > 0) {
            // Static conversion

            StandardBurnableToken token = StandardBurnableToken(A[_ix][0]);
            // Token count multiplier
            uint256 mux = token.allowance(msg.sender, this) / N[_ix][0];
            require(mux > 0);

            // Burning run
            for (i = 0; i < A[_ix].length; ++i) {
                token = StandardBurnableToken(A[_ix][i]);
                require(token.transferFrom(msg.sender, this, mux * N[_ix][i]));
                token.burn(mux * N[_ix][i]);
            }

            // Transfer up
            for (i = 0; i < B.length; ++i) {
                token = StandardBurnableToken(B[i]);
                require(token.transfer(msg.sender, M[i] * mux));
            }

        } else {
            // Dynamic conversion
            //   Let source token total supply is finite and decrease on each conversion,
            //   just convert finite supply of source to tokens on balance of ambix.
            //         dynamicRate = balance(sink) / total(source)

            // Is available for single source and single sink only
            require(A[_ix].length == 1 && B.length == 1);

            StandardBurnableToken source = StandardBurnableToken(A[_ix][0]);
            StandardBurnableToken sink = StandardBurnableToken(B[0]);

            uint256 scale = 10 ** 18 * sink.balanceOf(this) / source.totalSupply();

            uint256 allowance = source.allowance(msg.sender, this);
            require(allowance > 0);
            require(source.transferFrom(msg.sender, this, allowance));
            source.burn(allowance);

            uint256 reward = scale * allowance / 10 ** 18;
            require(reward > 0);
            require(sink.transfer(msg.sender, reward));
        }
    }
}

pragma solidity ^0.4.24;

import 'openzeppelin-solidity/contracts/token/ERC20/StandardBurnableToken.sol';
import 'openzeppelin-solidity/contracts/ownership/Ownable.sol';

/**
  @dev Ambix contract is used for morph Token set to another
  Token's by rule (recipe). In distillation process given
  Token's are burned and result generated by emission.

  The recipe presented as equation in form:
  (N1 * A1 & N'1 * A'1 & N''1 * A''1 ...)
  | (N2 * A2 & N'2 * A'2 & N''2 * A''2 ...) ...
  | (Nn * An & N'n * A'n & N''n * A''n ...)
  = M1 * B1 & M2 * B2 ... & Mm * Bm
    where A, B - input and output tokens
          N, M - token value coeficients
          n, m - input / output dimetion size
          | - is alternative operator (logical OR)
          & - is associative operator (logical AND)
  This says that `Ambix` should receive (approve) left
  part of equation and send (transfer) right part.
*/
contract Ambix is Ownable {
    address[][] public A;
    uint256[][] public N;
    address[] public B;
    uint256[] public M;

    /**
     * @dev Append token recipe source alternative
     * @param _a Token recipe source token addresses
     * @param _n Token recipe source token counts
     **/
    function appendSource(
        address[] _a,
        uint256[] _n
    ) external onlyOwner {
        require(_a.length == _n.length);
        for (uint256 i = 0; i < _a.length; ++i)
            require(_a[i] != 0);

        A.push(_a);
        N.push(_n);
    }

    /**
     * @dev Set sink of token recipe
     * @param _b Token recipe sink token list
     * @param _m Token recipe sink token counts
     */
    function setSink(
        address[] _b,
        uint256[] _m
    ) external onlyOwner{
        require(_b.length == _m.length);
        for (uint256 i = 0; i < _b.length; ++i)
            require(_b[i] != 0);

        B = _b;
        M = _m;
    }

    /**
     * @dev Run distillation process
     * @param _ix Source alternative index
     */
    function run(uint256 _ix) public {
        require(_ix < A.length);
        uint256 i;

        if (N[_ix][0] > 0) {
            // Static conversion

            StandardBurnableToken token = StandardBurnableToken(A[_ix][0]);
            // Token count multiplier
            uint256 mux = token.allowance(msg.sender, this) / N[_ix][0];
            require(mux > 0);

            // Burning run
            for (i = 0; i < A[_ix].length; ++i) {
                token = StandardBurnableToken(A[_ix][i]);
                require(token.transferFrom(msg.sender, this, mux * N[_ix][i]));
                token.burn(mux * N[_ix][i]);
            }

            // Transfer up
            for (i = 0; i < B.length; ++i) {
                token = StandardBurnableToken(B[i]);
                require(token.transfer(msg.sender, M[i] * mux));
            }

        } else {
            // Dynamic conversion
            //   Let source token total supply is finite and decrease on each conversion,
            //   just convert finite supply of source to tokens on balance of ambix.
            //         dynamicRate = balance(sink) / total(source)

            // Is available for single source and single sink only
            require(A[_ix].length == 1 && B.length == 1);

            StandardBurnableToken source = StandardBurnableToken(A[_ix][0]);
            StandardBurnableToken sink = StandardBurnableToken(B[0]);

            uint256 scale = 10 ** 18 * sink.balanceOf(this) / source.totalSupply();

            uint256 allowance = source.allowance(msg.sender, this);
            require(allowance > 0);
            require(source.transferFrom(msg.sender, this, allowance));
            source.burn(allowance);

            uint256 reward = scale * allowance / 10 ** 18;
            require(reward > 0);
            require(sink.transfer(msg.sender, reward));
        }
    }
}


Claim function renamed  to the anonymous function

pragma solidity ^0.4.8;

//This contract is backed by the constitution of superDAO deployed at : .
//The constitution of the superDAO is the social contract, terms, founding principles and definitions of the vision,
//mission, anti-missions, rules and operation guidelines of superDAO.
//The total number of 3,000,000 represents 3% of 100,000,000 immutable number of superDAO tokens,
//which is the alloted budget of operation for the earliest funding activities.
//Every prommissory token is exchangeable for the real superDAO tokens on a one on one basis.
//Promissiory contract will be deployed with the actual superDAO token contract.
//Early backers can call the "redeem" function on the actual token contract to exchange promissory tokens for the final tokens.

/**
 * @title Promisory Token Contract
 * @author ola
 * --- Collaborators ---
 * @author zlatinov
 * @author panos
 * @author yemi
 * @author archil
 * @author anthony
 */
contract PromissoryToken {

    event FounderSwitchRequestEvent(address _newFounderAddr);
    event FounderSwitchedEvent(address _newFounderAddr);
    event CofounderSwitchedEvent(address _newCofounderAddr);

    event AddedPrepaidTokensEvent(address backer, uint index, uint price, uint amount);
    event PrepaidTokensClaimedEvent(address backer, uint index, uint price, uint amount);
    event TokensClaimedEvent(address backer, uint index, uint price, uint amount);

    event RedeemEvent(address backer, uint amount);

    event WithdrawalCreatedEvent(uint withdrawalId, uint amount, bytes reason);
    event WithdrawalVotedEvent(uint withdrawalId, address backer, uint backerStakeWeigth, uint totalStakeWeight);
    event WithdrawalApproved(uint withdrawalId, uint stakeWeight, bool isMultiPayment, uint amount, bytes reason);

    address founder; //deployer of constitution and PromissoryToken
    bytes32 founderHash; // hash must be confirmed in order to replace founder address
    mapping(address => bytes32) tempHashes; // structure to contain new address to hash storage,
    address cofounder;//helper to aid founder key exchange in case of key loss
    address [] public previousFounders; //list of addresses replaced using the switching process.
    uint constant discountAmount = 60; //discount amount
    uint constant divisor = 100; //divisor to get discount value

    uint public constant minimumPrepaidClaimedPercent = 65;
    uint public promissoryUnits = 3000000; //amount of tokens contants set
    uint public prepaidUnits = 0; //prepaid and set by founder out of 3 million tokens
    uint public claimedUnits = 0; //claimed tokens out of 3 million tokens
    uint public claimedPrepaidUnits = 0; //claimed tokens out of the early backer's tokens/prepaidUnits
    uint public redeemedTokens = 0; //number of tokens out of claimed tokens, redeemed by superDAO token call
    uint public lastPrice = 0; //latest price of token acquired by backer in Wei
    uint public numOfBackers; //number of early backers

    struct backerData {
       uint tokenPrice;
       uint tokenAmount;
       bytes32 privateHash;
       bool prepaid;
       bool claimed;
       uint backerRank;
    }

    address[] public earlyBackerList; //addresses of earliest backers
    address[] public backersAddresses; //addresses of all backers
    mapping(address => backerData[]) public backers;// backer address to backer info mapping
    mapping(address => bool) public backersRedeemed;

    struct withdrawalData {
       uint Amount;
       bool approved;
       bool spent;
       bytes reason;
       address[] backerApprovals;
       uint totalStake;
       address[] destination;
    }

    withdrawalData[] public withdrawals; // Data structure specifying withdrawal
    mapping(address => mapping(uint => bool)) public withdrawalsVotes;

    /**
    * @notice Deploy PromissoryToken contract with `msg.sender.address()` as founder with `_prepaidBackers.number()` prepaid backers
    * @dev This is the constructor of the promisory token contract
    * @param _founderHash Founders password hash, preferable a message digest to further obfuscate duplicaion
    * @param _cofounderAddress The helper cofounder to aid founder key exchange in case of key loss/
    * @param _numOfBackers The number of Early backers. Will be used to control setting early backers
    */
    function PromissoryToken( bytes32 _founderHash, address _cofounderAddress, uint _numOfBackers){
        founder = msg.sender;
        founderHash = sha3(_founderHash);
        cofounder = _cofounderAddress;
        numOfBackers = _numOfBackers;
    }

    /**
    * @notice `msg.sender.address()` updating cofounder address to `_newFounderAddr.address()`
    * @dev allows cofounder to switch out addres for a new one.Can be repeated as many times as needed
    * @param _newCofounderAddr New Address of Cofounder
    * @return True if the coFounder address successfully updated
    */
    function cofounderSwitchAddress(address _newCofounderAddr) external returns (bool success){
        if (msg.sender != cofounder) throw;

        cofounder = _newCofounderAddr;
        CofounderSwitchedEvent(_newCofounderAddr);

        return true;
    }

    /**
    * @notice Founder address update to `_newFounderAddr.address()` is being requested
    * @dev founderSwitchAddress founder indicates intent to switch addresses with new address,
    * hash of pass phrase and a "onetime shared phrase shared with coufounder"
    * @param _founderHash Secret Key to be used to confirm Address update
    * @param _oneTimesharedPhrase Secret phrase to be shared with coFounder to approve Address update
    * @return True if Address switch request successfully created and Temporary hash Values set
    */
    function founderSwitchRequest(bytes32 _founderHash, bytes32 _oneTimesharedPhrase) returns (bool success){
        if(sha3(_founderHash) != founderHash) throw;

        tempHashes[msg.sender] = sha3(msg.sender, founderHash, _oneTimesharedPhrase);
        FounderSwitchRequestEvent(msg.sender);

        return true;
    }

   /**
    * @notice `msg.sender.address()` approving `_newFounderAddr.address()` as new founder address
    * @dev CofounderSwitchAddress which allows previously set cofounder to approve address
    * switch by founder. Must have a one time shared phrase thats is shared with founder that corresponding with a
    * hashed value.
    * @param _newFounderAddr The address of Founder to be newly set
    * @param _oneTimesharedPhrase Secret Keyword to be provide access to the approval function
    * @return True if new Founder address successfully approved
    */
    function cofounderApproveSwitchRequest(address _newFounderAddr, bytes32 _oneTimesharedPhrase) external returns (bool success){
        if(msg.sender != cofounder || sha3(_newFounderAddr, founderHash, _oneTimesharedPhrase) != tempHashes[_newFounderAddr]) throw;

        previousFounders.push(founder);
        founder = _newFounderAddr;
        FounderSwitchedEvent(_newFounderAddr);

        return true;
    }

    /**
    * @notice Adding `_backer.address()` as an early backer
    * @dev Add Early backers to Contract setting the transacton details
    * @param _backer The address of the superDAO backer
    * @param _tokenPrice The price/rate at which the superDAO tokens were bought
    * @param _tokenAmount The total number of superDAO token purcgased at the indicated rate
    * @param _privatePhrase Secret or passphrase
    * @param _backerRank Rank of the backer in the backers list
    * @return Thre index of _backer  in the backers list
    */
    function setPrepaid(address _backer, uint _tokenPrice, uint _tokenAmount, string _privatePhrase, uint _backerRank)
        external
        founderCall
        returns (uint)
    {
        if (_tokenPrice == 0 || _tokenAmount == 0 || claimedPrepaidUnits>0 ||
            _tokenAmount + prepaidUnits + claimedUnits > promissoryUnits) throw;
        if (earlyBackerList.length == numOfBackers && backers[_backer].length == 0) throw ;
        if (backers[_backer].length == 0) {
            earlyBackerList.push(_backer);
            backersAddresses.push(_backer);
        }
        backers[_backer].push(backerData(_tokenPrice, _tokenAmount, sha3(_privatePhrase, _backer), true, false, _backerRank));

        prepaidUnits +=_tokenAmount;
        lastPrice = _tokenPrice;

        AddedPrepaidTokensEvent(_backer, backers[_backer].length - 1, _tokenPrice, _tokenAmount);

        return backers[_backer].length - 1;
    }

    /**
    * @notice Claiming `_tokenAmount.number()` superDAO tokens by `msg.sender.address()`
    * @dev Claim superDAO Early backer tokens
    * @param _index index of tokens to claim
    * @param _boughtTokensPrice Price at which the superDAO tokens were bought
    * @param _tokenAmount Number of superDAO tokens to be claimed
    * @param _privatePhrase Secret key for Offline shared pre-hashed phrase offline price negotiation for online attestation of superDAO tokens ownership
    * @param _backerRank Backer rank of the backer in the superDAO
    */
    function claimPrepaid(uint _index, uint _boughtTokensPrice, uint _tokenAmount, string _privatePhrase, uint _backerRank)
        external
        EarliestBackersSet
    {
        if(backers[msg.sender][_index].prepaid == true &&
           backers[msg.sender][_index].claimed == false &&
           backers[msg.sender][_index].tokenAmount == _tokenAmount &&
           backers[msg.sender][_index].tokenPrice == _boughtTokensPrice &&
           backers[msg.sender][_index].privateHash == sha3( _privatePhrase, msg.sender) &&
           backers[msg.sender][_index].backerRank == _backerRank)
        {
            backers[msg.sender][_index].claimed = true;
            claimedPrepaidUnits += _tokenAmount;

            PrepaidTokensClaimedEvent(msg.sender, _index, _boughtTokensPrice, _tokenAmount);
        } else {
            throw;
        }
    }

    /**
    * @notice `msg.sender.address()` is Purchasing `(msg.value / lastPrice).toFixed(0)` superDAO Tokens at `lastPrice`
    * @dev Purchase new superDAO Tokens if the amount of tokens are still available for purchase
    */
    function ()
        payable
        MinimumBackersClaimed
   {
        if (lastPrice == 0) throw;

        //don`t accept transactions with zero value
        if (msg.value == 0) throw;

        //Effective discount for Pre-crowdfunding backers of 40% Leaving effective rate of 60%
        uint discountPrice = lastPrice * discountAmount / divisor;

        uint tokenAmount = (msg.value / discountPrice);//Effect the discount rate 0f 40%

        if (tokenAmount + claimedUnits + prepaidUnits > promissoryUnits) throw;

        if (backers[msg.sender].length == 0) {
            backersAddresses.push(msg.sender);
        }
        backers[msg.sender].push(backerData(discountPrice, tokenAmount, sha3(msg.sender), false, true, 0));

        claimedUnits += tokenAmount;

        TokensClaimedEvent(msg.sender, backers[msg.sender].length - 1, discountPrice, tokenAmount);
    }

    /**
     * @notice checking `_backerAddress.address()` superDAO Token balance: `index`
     * @dev Check Token balance by index of backer, return values can be used to instantiate a backerData struct
     * @param _backerAddress The Backer's address
     * @param index The balance to check
     * @return tokenPrice The Price at which the tokens were bought
     * @return tokenAmount The number of tokens that were bought
     * @return privateHash Secret phrase for authentication by the backer
     * @return prepaid True if backer is an early backer
     * @return claimed True if the Token has already been claimed by the backer
     */
    function checkBalance(address _backerAddress, uint index) constant returns (uint, uint, bytes32, bool, bool){
        return (
            backers[_backerAddress][index].tokenPrice,
            backers[_backerAddress][index].tokenAmount,
            backers[_backerAddress][index].privateHash,
            backers[_backerAddress][index].prepaid,
            backers[_backerAddress][index].claimed
            );
    }

    /**
    * @notice Approving withdrawal `_withdrawalID`
    * @dev Approve a withdrawal from the superDAO and mark the withdrawal as spent
    * @param _withdrawalID The ID of the withdrawal
    */
    function approveWithdraw(uint _withdrawalID)
        external
        backerCheck(_withdrawalID)
    {
        withdrawalsVotes[msg.sender][_withdrawalID] = true;

        uint backerStake = 0;
        for (uint i = 0; i < backers[msg.sender].length; i++) {
            backerStake += backers[msg.sender][i].tokenAmount;
        }
        withdrawals[_withdrawalID].backerApprovals.push(msg.sender);
        withdrawals[_withdrawalID].totalStake += backerStake;

        WithdrawalVotedEvent(_withdrawalID, msg.sender, backerStake, withdrawals[_withdrawalID].totalStake);

        if(withdrawals[_withdrawalID].totalStake >= (claimedPrepaidUnits + claimedUnits) / 3) {
            uint amountPerAddr;
            bool isMultiPayment = withdrawals[_withdrawalID].destination.length > 1;

            if(isMultiPayment == false){
                amountPerAddr = withdrawals[_withdrawalID].Amount;
            }
            else {
                amountPerAddr = withdrawals[_withdrawalID].Amount / withdrawals[_withdrawalID].destination.length;
            }

            withdrawals[_withdrawalID].approved = true;
            withdrawals[_withdrawalID].spent = true;

            for(i = 0; i < withdrawals[_withdrawalID].destination.length; i++){
                if(!withdrawals[_withdrawalID].destination[i].send(amountPerAddr)) throw;
            }

            WithdrawalApproved(_withdrawalID,
                withdrawals[_withdrawalID].totalStake,
                isMultiPayment,
                withdrawals[_withdrawalID].Amount,
                withdrawals[_withdrawalID].reason);
        }
    }

    /**
    * @notice Requestng withdrawal of `_totalAmount` to `_destination.address()`
    * @dev Create a new withdrawal request
    * @param _totalAmount The total amount of tokens to be withdrawan, should be equal to the total number of owned tokens
    * @param _reason Reason/Description for the withdrawal
    * @param _destination The receiving address
    */
    function withdraw(uint _totalAmount, bytes _reason, address[] _destination)
        external
        founderCall
    {
        if (this.balance < _totalAmount) throw;

        uint withdrawalID = withdrawals.length++;

        withdrawals[withdrawalID].Amount = _totalAmount;
        withdrawals[withdrawalID].reason = _reason;
        withdrawals[withdrawalID].destination = _destination;
        withdrawals[withdrawalID].approved = false;
        withdrawals[withdrawalID].spent = false;

        WithdrawalCreatedEvent(withdrawalID, _totalAmount, _reason);
    }

    /**
    * @notice Backer `_bacherAddr.address()` is redeeming `_amount` superDAO Tokens
    * @dev Check if backer tokens have been claimed but not redeemed, then redeem them
    * @param _amount The total number of redeemable tokens
    * @param _backerAddr The address of the backer
    * @return True if tokens were successfully redeemed else false
    */
    function redeem(uint _amount, address _backerAddr) returns(bool){
        if (backersRedeemed[_backerAddr] == true) {
            return false;
        }

        uint totalTokens = 0;

        for (uint i = 0; i < backers[_backerAddr].length; i++) {
            if (backers[_backerAddr][i].claimed == false) {
                return false;
            }
            totalTokens += backers[_backerAddr][i].tokenAmount;
        }

        if (totalTokens == _amount){
            backersRedeemed[_backerAddr] = true;

            RedeemEvent(_backerAddr, totalTokens);

            return true;
        }
        else {
            return false;
        }
    }

    /**
    * @notice check withdrawal status of `_withdrawalID`
    * @dev Get the withdrawal of a withdrawal. Return values can be used to instantiate a withdrawalData struct
    * @param _withdrawalID The ID of the withdrawal
    * @return Amount The Amount requested in the withdrawal
    * @return approved True if the withdrawal has been approved
    * @return reason Reason/Description of the Withdrawal
    * @return backerApprovals Addresses of backers who approved the withdrawal
    * @return totalStake Total number of tokens which backed the withdrawal(Total number of tokens owned by backers who approved the withdrawal)
    * @return destination Receiving address of the withdrawal
    */
    function getWithdrawalData(uint _withdrawalID) constant public returns (uint, bool, bytes, address[], uint, address[]){
        return (
            withdrawals[_withdrawalID].Amount,
            withdrawals[_withdrawalID].approved,
            withdrawals[_withdrawalID].reason,
            withdrawals[_withdrawalID].backerApprovals,
            withdrawals[_withdrawalID].totalStake,
            withdrawals[_withdrawalID].destination);
    }

    modifier founderCall{
        if (msg.sender != founder) throw;
        _;
    }

    modifier backerCheck(uint _withdrawalID){
        if(backers[msg.sender].length == 0 || withdrawals[_withdrawalID].spent == true || withdrawalsVotes[msg.sender][_withdrawalID] == true) throw;
        _;
    }

    modifier EarliestBackersSet{
       if(earlyBackerList.length < numOfBackers) throw;
       _;
    }

    modifier MinimumBackersClaimed(){
      if(prepaidUnits == 0 ||
        claimedPrepaidUnits == 0 ||
        (claimedPrepaidUnits * divisor / prepaidUnits) < minimumPrepaidClaimedPercent) {
            throw;
        }
      _;
    }

    /*
     * Safeguard function.
     * This function gets executed if a transaction with invalid data is sent to
     * the contract or just ether without data.
     */
     /*
        function () {
            throw;
        }
    */

}

pragma solidity ^0.4.8;

//This contract is backed by the constitution of superDAO deployed at : .
//The constitution of the superDAO is the social contract, terms, founding principles and definitions of the vision,
//mission, anti-missions, rules and operation guidelines of superDAO.
//The total number of 3,000,000 represents 3% of 100,000,000 immutable number of superDAO tokens,
//which is the alloted budget of operation for the earliest funding activities.
//Every prommissory token is exchangeable for the real superDAO tokens on a one on one basis.
//Promissiory contract will be deployed with the actual superDAO token contract.
//Early backers can call the "redeem" function on the actual token contract to exchange promissory tokens for the final tokens.

/**
 * @title Promisory Token Contract
 * @author ola
 * --- Collaborators ---
 * @author zlatinov
 * @author panos
 * @author yemi
 * @author archil
 * @author anthony
 */
contract PromissoryToken {

    event FounderSwitchRequestEvent(address _newFounderAddr);
    event FounderSwitchedEvent(address _newFounderAddr);
    event CofounderSwitchedEvent(address _newCofounderAddr);

    event AddedPrepaidTokensEvent(address backer, uint index, uint price, uint amount);
    event PrepaidTokensClaimedEvent(address backer, uint index, uint price, uint amount);
    event TokensClaimedEvent(address backer, uint index, uint price, uint amount);

    event RedeemEvent(address backer, uint amount);

    event WithdrawalCreatedEvent(uint withdrawalId, uint amount, bytes reason);
    event WithdrawalVotedEvent(uint withdrawalId, address backer, uint backerStakeWeigth, uint totalStakeWeight);
    event WithdrawalApproved(uint withdrawalId, uint stakeWeight, bool isMultiPayment, uint amount, bytes reason);

    address founder; //deployer of constitution and PromissoryToken
    bytes32 founderHash; // hash must be confirmed in order to replace founder address
    mapping(address => bytes32) tempHashes; // structure to contain new address to hash storage,
    address cofounder;//helper to aid founder key exchange in case of key loss
    address [] public previousFounders; //list of addresses replaced using the switching process.
    uint constant discountAmount = 60; //discount amount
    uint constant divisor = 100; //divisor to get discount value

    uint public constant minimumPrepaidClaimedPercent = 65;
    uint public promissoryUnits = 3000000; //amount of tokens contants set
    uint public prepaidUnits = 0; //prepaid and set by founder out of 3 million tokens
    uint public claimedUnits = 0; //claimed tokens out of 3 million tokens
    uint public claimedPrepaidUnits = 0; //claimed tokens out of the early backer's tokens/prepaidUnits
    uint public redeemedTokens = 0; //number of tokens out of claimed tokens, redeemed by superDAO token call
    uint public lastPrice = 0; //latest price of token acquired by backer in Wei
    uint public numOfBackers; //number of early backers

    struct backerData {
       uint tokenPrice;
       uint tokenAmount;
       bytes32 privateHash;
       bool prepaid;
       bool claimed;
       uint backerRank;
    }

    address[] public earlyBackerList; //addresses of earliest backers
    address[] public backersAddresses; //addresses of all backers
    mapping(address => backerData[]) public backers;// backer address to backer info mapping
    mapping(address => bool) public backersRedeemed;

    struct withdrawalData {
       uint Amount;
       bool approved;
       bool spent;
       bytes reason;
       address[] backerApprovals;
       uint totalStake;
       address[] destination;
    }

    withdrawalData[] public withdrawals; // Data structure specifying withdrawal
    mapping(address => mapping(uint => bool)) public withdrawalsVotes;

    /**
    * @notice Deploy PromissoryToken contract with `msg.sender.address()` as founder with `_prepaidBackers.number()` prepaid backers
    * @dev This is the constructor of the promisory token contract
    * @param _founderHash Founders password hash, preferable a message digest to further obfuscate duplicaion
    * @param _cofounderAddress The helper cofounder to aid founder key exchange in case of key loss/
    * @param _numOfBackers The number of Early backers. Will be used to control setting early backers
    */
    function PromissoryToken( bytes32 _founderHash, address _cofounderAddress, uint _numOfBackers){
        founder = msg.sender;
        founderHash = sha3(_founderHash);
        cofounder = _cofounderAddress;
        numOfBackers = _numOfBackers;
    }

    /**
    * @notice `msg.sender.address()` updating cofounder address to `_newFounderAddr.address()`
    * @dev allows cofounder to switch out addres for a new one.Can be repeated as many times as needed
    * @param _newCofounderAddr New Address of Cofounder
    * @return True if the coFounder address successfully updated
    */
    function cofounderSwitchAddress(address _newCofounderAddr) external returns (bool success){
        if (msg.sender != cofounder) throw;

        cofounder = _newCofounderAddr;
        CofounderSwitchedEvent(_newCofounderAddr);

        return true;
    }

    /**
    * @notice Founder address update to `_newFounderAddr.address()` is being requested
    * @dev founderSwitchAddress founder indicates intent to switch addresses with new address,
    * hash of pass phrase and a "onetime shared phrase shared with coufounder"
    * @param _founderHash Secret Key to be used to confirm Address update
    * @param _oneTimesharedPhrase Secret phrase to be shared with coFounder to approve Address update
    * @return True if Address switch request successfully created and Temporary hash Values set
    */
    function founderSwitchRequest(bytes32 _founderHash, bytes32 _oneTimesharedPhrase) returns (bool success){
        if(sha3(_founderHash) != founderHash) throw;

        tempHashes[msg.sender] = sha3(msg.sender, founderHash, _oneTimesharedPhrase);
        FounderSwitchRequestEvent(msg.sender);

        return true;
    }

   /**
    * @notice `msg.sender.address()` approving `_newFounderAddr.address()` as new founder address
    * @dev CofounderSwitchAddress which allows previously set cofounder to approve address
    * switch by founder. Must have a one time shared phrase thats is shared with founder that corresponding with a
    * hashed value.
    * @param _newFounderAddr The address of Founder to be newly set
    * @param _oneTimesharedPhrase Secret Keyword to be provide access to the approval function
    * @return True if new Founder address successfully approved
    */
    function cofounderApproveSwitchRequest(address _newFounderAddr, bytes32 _oneTimesharedPhrase) external returns (bool success){
        if(msg.sender != cofounder || sha3(_newFounderAddr, founderHash, _oneTimesharedPhrase) != tempHashes[_newFounderAddr]) throw;

        previousFounders.push(founder);
        founder = _newFounderAddr;
        FounderSwitchedEvent(_newFounderAddr);

        return true;
    }

    /**
    * @notice Adding `_backer.address()` as an early backer
    * @dev Add Early backers to Contract setting the transacton details
    * @param _backer The address of the superDAO backer
    * @param _tokenPrice The price/rate at which the superDAO tokens were bought
    * @param _tokenAmount The total number of superDAO token purcgased at the indicated rate
    * @param _privatePhrase Secret or passphrase
    * @param _backerRank Rank of the backer in the backers list
    * @return Thre index of _backer  in the backers list
    */
    function setPrepaid(address _backer, uint _tokenPrice, uint _tokenAmount, string _privatePhrase, uint _backerRank)
        external
        founderCall
        returns (uint)
    {
        if (_tokenPrice == 0 || _tokenAmount == 0 || claimedPrepaidUnits>0 ||
            _tokenAmount + prepaidUnits + claimedUnits > promissoryUnits) throw;
        if (earlyBackerList.length == numOfBackers && backers[_backer].length == 0) throw ;
        if (backers[_backer].length == 0) {
            earlyBackerList.push(_backer);
            backersAddresses.push(_backer);
        }
        backers[_backer].push(backerData(_tokenPrice, _tokenAmount, sha3(_privatePhrase, _backer), true, false, _backerRank));

        prepaidUnits +=_tokenAmount;
        lastPrice = _tokenPrice;

        AddedPrepaidTokensEvent(_backer, backers[_backer].length - 1, _tokenPrice, _tokenAmount);

        return backers[_backer].length - 1;
    }

    /**
    * @notice Claiming `_tokenAmount.number()` superDAO tokens by `msg.sender.address()`
    * @dev Claim superDAO Early backer tokens
    * @param _index index of tokens to claim
    * @param _boughtTokensPrice Price at which the superDAO tokens were bought
    * @param _tokenAmount Number of superDAO tokens to be claimed
    * @param _privatePhrase Secret key for Offline shared pre-hashed phrase offline price negotiation for online attestation of superDAO tokens ownership
    * @param _backerRank Backer rank of the backer in the superDAO
    */
    function claimPrepaid(uint _index, uint _boughtTokensPrice, uint _tokenAmount, string _privatePhrase, uint _backerRank)
        external
        EarliestBackersSet
    {
        if(backers[msg.sender][_index].prepaid == true &&
           backers[msg.sender][_index].claimed == false &&
           backers[msg.sender][_index].tokenAmount == _tokenAmount &&
           backers[msg.sender][_index].tokenPrice == _boughtTokensPrice &&
           backers[msg.sender][_index].privateHash == sha3( _privatePhrase, msg.sender) &&
           backers[msg.sender][_index].backerRank == _backerRank)
        {
            backers[msg.sender][_index].claimed = true;
            claimedPrepaidUnits += _tokenAmount;

            PrepaidTokensClaimedEvent(msg.sender, _index, _boughtTokensPrice, _tokenAmount);
        } else {
            throw;
        }
    }

    /**
    * @notice `msg.sender.address()` is Purchasing `(msg.value / lastPrice).toFixed(0)` superDAO Tokens at `lastPrice`
    * @dev Purchase new superDAO Tokens if the amount of tokens are still available for purchase
    */
    function claim()
        payable
        external
        MinimumBackersClaimed
   {
        if (lastPrice == 0) throw;

        //Effective discount for Pre-crowdfunding backers of 40% Leaving effective rate of 60%
        uint discountPrice = lastPrice * discountAmount / divisor;

        uint tokenAmount = (msg.value / discountPrice);//Effect the discount rate 0f 40%

        if (tokenAmount + claimedUnits + prepaidUnits > promissoryUnits) throw;

        if (backers[msg.sender].length == 0) {
            backersAddresses.push(msg.sender);
        }
        backers[msg.sender].push(backerData(discountPrice, tokenAmount, sha3(msg.sender), false, true, 0));

        claimedUnits += tokenAmount;

        TokensClaimedEvent(msg.sender, backers[msg.sender].length - 1, discountPrice, tokenAmount);
    }

    /**
     * @notice checking `_backerAddress.address()` superDAO Token balance: `index`
     * @dev Check Token balance by index of backer, return values can be used to instantiate a backerData struct
     * @param _backerAddress The Backer's address
     * @param index The balance to check
     * @return tokenPrice The Price at which the tokens were bought
     * @return tokenAmount The number of tokens that were bought
     * @return privateHash Secret phrase for authentication by the backer
     * @return prepaid True if backer is an early backer
     * @return claimed True if the Token has already been claimed by the backer
     */
    function checkBalance(address _backerAddress, uint index) constant returns (uint, uint, bytes32, bool, bool){
        return (
            backers[_backerAddress][index].tokenPrice,
            backers[_backerAddress][index].tokenAmount,
            backers[_backerAddress][index].privateHash,
            backers[_backerAddress][index].prepaid,
            backers[_backerAddress][index].claimed
            );
    }

    /**
    * @notice Approving withdrawal `_withdrawalID`
    * @dev Approve a withdrawal from the superDAO and mark the withdrawal as spent
    * @param _withdrawalID The ID of the withdrawal
    */
    function approveWithdraw(uint _withdrawalID)
        external
        backerCheck(_withdrawalID)
    {
        withdrawalsVotes[msg.sender][_withdrawalID] = true;

        uint backerStake = 0;
        for (uint i = 0; i < backers[msg.sender].length; i++) {
            backerStake += backers[msg.sender][i].tokenAmount;
        }
        withdrawals[_withdrawalID].backerApprovals.push(msg.sender);
        withdrawals[_withdrawalID].totalStake += backerStake;

        WithdrawalVotedEvent(_withdrawalID, msg.sender, backerStake, withdrawals[_withdrawalID].totalStake);

        if(withdrawals[_withdrawalID].totalStake >= (claimedPrepaidUnits + claimedUnits) / 3) {
            uint amountPerAddr;
            bool isMultiPayment = withdrawals[_withdrawalID].destination.length > 1;

            if(isMultiPayment == false){
                amountPerAddr = withdrawals[_withdrawalID].Amount;
            }
            else {
                amountPerAddr = withdrawals[_withdrawalID].Amount / withdrawals[_withdrawalID].destination.length;
            }

            withdrawals[_withdrawalID].approved = true;
            withdrawals[_withdrawalID].spent = true;

            for(i = 0; i < withdrawals[_withdrawalID].destination.length; i++){
                if(!withdrawals[_withdrawalID].destination[i].send(amountPerAddr)) throw;
            }

            WithdrawalApproved(_withdrawalID,
                withdrawals[_withdrawalID].totalStake,
                isMultiPayment,
                withdrawals[_withdrawalID].Amount,
                withdrawals[_withdrawalID].reason);
        }
    }

    /**
    * @notice Requestng withdrawal of `_totalAmount` to `_destination.address()`
    * @dev Create a new withdrawal request
    * @param _totalAmount The total amount of tokens to be withdrawan, should be equal to the total number of owned tokens
    * @param _reason Reason/Description for the withdrawal
    * @param _destination The receiving address
    */
    function withdraw(uint _totalAmount, bytes _reason, address[] _destination)
        external
        founderCall
    {
        if (this.balance < _totalAmount) throw;

        uint withdrawalID = withdrawals.length++;

        withdrawals[withdrawalID].Amount = _totalAmount;
        withdrawals[withdrawalID].reason = _reason;
        withdrawals[withdrawalID].destination = _destination;
        withdrawals[withdrawalID].approved = false;
        withdrawals[withdrawalID].spent = false;

        WithdrawalCreatedEvent(withdrawalID, _totalAmount, _reason);
    }

    /**
    * @notice Backer `_bacherAddr.address()` is redeeming `_amount` superDAO Tokens
    * @dev Check if backer tokens have been claimed but not redeemed, then redeem them
    * @param _amount The total number of redeemable tokens
    * @param _backerAddr The address of the backer
    * @return True if tokens were successfully redeemed else false
    */
    function redeem(uint _amount, address _backerAddr) returns(bool){
        if (backersRedeemed[_backerAddr] == true) {
            return false;
        }

        uint totalTokens = 0;

        for (uint i = 0; i < backers[_backerAddr].length; i++) {
            if (backers[_backerAddr][i].claimed == false) {
                return false;
            }
            totalTokens += backers[_backerAddr][i].tokenAmount;
        }

        if (totalTokens == _amount){
            backersRedeemed[_backerAddr] = true;

            RedeemEvent(_backerAddr, totalTokens);

            return true;
        }
        else {
            return false;
        }
    }

    /**
    * @notice check withdrawal status of `_withdrawalID`
    * @dev Get the withdrawal of a withdrawal. Return values can be used to instantiate a withdrawalData struct
    * @param _withdrawalID The ID of the withdrawal
    * @return Amount The Amount requested in the withdrawal
    * @return approved True if the withdrawal has been approved
    * @return reason Reason/Description of the Withdrawal
    * @return backerApprovals Addresses of backers who approved the withdrawal
    * @return totalStake Total number of tokens which backed the withdrawal(Total number of tokens owned by backers who approved the withdrawal)
    * @return destination Receiving address of the withdrawal
    */
    function getWithdrawalData(uint _withdrawalID) constant public returns (uint, bool, bytes, address[], uint, address[]){
        return (
            withdrawals[_withdrawalID].Amount,
            withdrawals[_withdrawalID].approved,
            withdrawals[_withdrawalID].reason,
            withdrawals[_withdrawalID].backerApprovals,
            withdrawals[_withdrawalID].totalStake,
            withdrawals[_withdrawalID].destination);
    }

    modifier founderCall{
        if (msg.sender != founder) throw;
        _;
    }

    modifier backerCheck(uint _withdrawalID){
        if(backers[msg.sender].length == 0 || withdrawals[_withdrawalID].spent == true || withdrawalsVotes[msg.sender][_withdrawalID] == true) throw;
        _;
    }

    modifier EarliestBackersSet{
       if(earlyBackerList.length < numOfBackers) throw;
       _;
    }

    modifier MinimumBackersClaimed(){
      if(prepaidUnits == 0 ||
        claimedPrepaidUnits == 0 ||
        (claimedPrepaidUnits * divisor / prepaidUnits) < minimumPrepaidClaimedPercent) {
            throw;
        }
      _;
    }

    /*
     * Safeguard function.
     * This function gets executed if a transaction with invalid data is sent to
     * the contract or just ether without data.
     */
    function () {
        throw;
    }

}


make TokenVesting variables public

make TokenVesting variables public

pragma solidity ^0.4.11;

import './ERC20Basic.sol';
import '../ownership/Ownable.sol';
import '../math/Math.sol';
import '../math/SafeMath.sol';

/**
 * @title TokenVesting
 * @dev A token holder contract that can release its token balance gradually like a
 * typical vesting scheme, with a cliff and vesting period. Optionally revocable by the
 * owner.
 */
contract TokenVesting is Ownable {
  using SafeMath for uint256;

  event Released(uint256 amount);
  event Revoked();

  // beneficiary of tokens after they are released
  address public beneficiary;

  uint256 public cliff;
  uint256 public start;
  uint256 public duration;

  bool public revocable;

  mapping (address => uint256) public released;
  mapping (address => bool) public revoked;

  /**
   * @dev Creates a vesting contract that vests its balance of any ERC20 token to the
   * _beneficiary, gradually in a linear fashion until _start + _duration. By then all
   * of the balance will have vested.
   * @param _beneficiary address of the beneficiary to whom vested tokens are transferred
   * @param _cliff duration in seconds of the cliff in which tokens will begin to vest
   * @param _duration duration in seconds of the period in which the tokens will vest
   * @param _revocable whether the vesting is revocable or not
   */
  function TokenVesting(address _beneficiary, uint256 _start, uint256 _cliff, uint256 _duration, bool _revocable) {
    require(_beneficiary != 0x0);
    require(_cliff <= _duration);

    beneficiary = _beneficiary;
    revocable = _revocable;
    duration = _duration;
    cliff = _start + _cliff;
    start = _start;
  }

  /**
   * @notice Transfers vested tokens to beneficiary.
   * @param token ERC20 token which is being vested
   */
  function release(ERC20Basic token) {
    uint256 vested = vestedAmount(token);

    require(vested > 0);

    token.transfer(beneficiary, vested);

    released[token] = released[token].add(vested);

    Released(vested);
  }

  /**
   * @notice Allows the owner to revoke the vesting. Tokens already vested
   * remain in the contract, the rest are returned to the owner.
   * @param token ERC20 token which is being vested
   */
  function revoke(ERC20Basic token) onlyOwner {
    require(revocable);
    require(!revoked[token]);

    uint256 balance = token.balanceOf(this);

    uint256 vested = vestedAmount(token);
    uint256 vesting = balance - vested;

    revoked[token] = true;

    token.transfer(owner, vesting);

    Revoked();
  }

  /**
   * @dev Calculates the amount that has already vested but hasn't been released yet.
   * @param token ERC20 token which is being vested
   */
  function vestedAmount(ERC20Basic token) constant returns (uint256) {
    if (now < cliff) {
      return 0;
    } else if (now >= start + duration || revoked[token]) {
      return token.balanceOf(this);
    } else {
      uint256 currentBalance = token.balanceOf(this);
      uint256 totalBalance = currentBalance.add(released[token]);

      uint256 vested = totalBalance.mul(now - start).div(duration);
      uint256 unreleased = vested.sub(released[token]);

      // currentBalance can be 0 in case of vesting being revoked earlier.
      return Math.min256(currentBalance, unreleased);
    }
  }
}

pragma solidity ^0.4.11;

import './ERC20Basic.sol';
import '../ownership/Ownable.sol';
import '../math/Math.sol';
import '../math/SafeMath.sol';

/**
 * @title TokenVesting
 * @dev A token holder contract that can release its token balance gradually like a
 * typical vesting scheme, with a cliff and vesting period. Optionally revocable by the
 * owner.
 */
contract TokenVesting is Ownable {
  using SafeMath for uint256;

  event Released(uint256 amount);
  event Revoked();

  // beneficiary of tokens after they are released
  address beneficiary;

  uint256 cliff;
  uint256 start;
  uint256 duration;

  bool revocable;

  mapping (address => uint256) released;
  mapping (address => bool) revoked;

  /**
   * @dev Creates a vesting contract that vests its balance of any ERC20 token to the
   * _beneficiary, gradually in a linear fashion until _start + _duration. By then all
   * of the balance will have vested.
   * @param _beneficiary address of the beneficiary to whom vested tokens are transferred
   * @param _cliff duration in seconds of the cliff in which tokens will begin to vest
   * @param _duration duration in seconds of the period in which the tokens will vest
   * @param _revocable whether the vesting is revocable or not
   */
  function TokenVesting(address _beneficiary, uint256 _start, uint256 _cliff, uint256 _duration, bool _revocable) {
    require(_beneficiary != 0x0);
    require(_cliff <= _duration);

    beneficiary = _beneficiary;
    revocable = _revocable;
    duration = _duration;
    cliff = _start + _cliff;
    start = _start;
  }

  /**
   * @notice Transfers vested tokens to beneficiary.
   * @param token ERC20 token which is being vested
   */
  function release(ERC20Basic token) {
    uint256 vested = vestedAmount(token);

    require(vested > 0);

    token.transfer(beneficiary, vested);

    released[token] = released[token].add(vested);

    Released(vested);
  }

  /**
   * @notice Allows the owner to revoke the vesting. Tokens already vested
   * remain in the contract, the rest are returned to the owner.
   * @param token ERC20 token which is being vested
   */
  function revoke(ERC20Basic token) onlyOwner {
    require(revocable);
    require(!revoked[token]);

    uint256 balance = token.balanceOf(this);

    uint256 vested = vestedAmount(token);
    uint256 vesting = balance - vested;

    revoked[token] = true;

    token.transfer(owner, vesting);

    Revoked();
  }

  /**
   * @dev Calculates the amount that has already vested but hasn't been released yet.
   * @param token ERC20 token which is being vested
   */
  function vestedAmount(ERC20Basic token) constant returns (uint256) {
    if (now < cliff) {
      return 0;
    } else if (now >= start + duration || revoked[token]) {
      return token.balanceOf(this);
    } else {
      uint256 currentBalance = token.balanceOf(this);
      uint256 totalBalance = currentBalance.add(released[token]);

      uint256 vested = totalBalance.mul(now - start).div(duration);
      uint256 unreleased = vested.sub(released[token]);

      // currentBalance can be 0 in case of vesting being revoked earlier.
      return Math.min256(currentBalance, unreleased);
    }
  }
}