SafeMath is now more consistent with itself. (#1168)

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) {
    // 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;
    }

    uint256 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 c;
  }

  /**
  * @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);
    uint256 c = _a - _b;

    return c;
  }

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

    return c;
  }
}

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;
  }
}


Import std.sol from hack.ether.camp

Import std.sol from hack.ether.camp

// This si marker
// for contract not
// to be deployed to
// any environment
contract abstract {}

contract owned is abstract {
  address owner;
  function owned() {
    owner = msg.sender;
  }
  function changeOwner(address newOwner) onlyowner {
    owner = newOwner;
  }
  modifier onlyowner() {
    if (msg.sender==owner) _
  }
}

contract administrated is abstract, owned {
    mapping (address => uint) admins;

    function addAdministrator(address admin) onlyowner {
        admins[admin] = 1;
    }

    function removeAdministrator(address admin) onlyowner {
        admins[admin] = 0;
    }

    modifier onlyadmin() {
        if (msg.sender == owner || admins[msg.sender] == 1) _
    }
}

contract mortal is abstract, owned {
  function kill() onlyowner {
    if (msg.sender == owner) suicide(owner);
  }
}

contract NameReg is abstract {
  function register(bytes32 name) {}
  function unregister() {}
  function addressOf(bytes32 name) constant returns (address addr) {}
  function nameOf(address addr) constant returns (bytes32 name) {}
  function kill() {}
}

contract nameRegAware is abstract {
  function nameRegAddress() returns (address) {
    return 0x084f6a99003dae6d3906664fdbf43dd09930d0e3;
  }

  function named(bytes32 name) returns (address) {
    return NameReg(nameRegAddress()).addressOf(name);
  }
}

contract named is abstract, nameRegAware {
  function named(bytes32 name) {
    NameReg(nameRegAddress()).register(name);
  }
}

// contract with util functions
contract util is abstract {
  // Converts 'string' to 'bytes32'
  function s2b(string s) internal returns (bytes32) {
      bytes memory b = bytes(s);
      uint r = 0;
      for (uint i = 0; i < 32; i++) {
          if (i < b.length) {
              r = r | uint(b[i]);
          }
          if (i < 31) r = r * 256;
      }
      return bytes32(r);
  }
}

error: pathspec 'contracts/std.sol' did not match any file(s) known to git


Add getBalance method

Add getBalance method

import "LockedStateWithFunds.sol";

/**
 * TicTacToeLockedState
 *
 * The LockedState for a TicTacToe game.
 */
contract TicTacToeLockedState is LockedState {

    /* bit mappings for state
     * 0: X gets winnings
     * 1: O gets winnings
     * 2: X forfeits adjudication deposit
     * 3: O forfeits adjudication deposit
     * 4: X forfeits disconnect deposit
     * 5: O forfeits disconnect deposit
     * 6: used to indicate cheating. Doesn't change where funds will be sent
     * note, if tie, bits 0 and 1 should both be 0 to indicate tie
     */
    address addressX;
    address addressO;
    address burner;

    uint[6] funds;

    /**
     * addressX: the address of X
     * addressO: the address of O
     * burner: the address which funds will be burned to (usually 0)
     */
    function TicTacToeLockedState(address _addressX, address _addressO, address _burner) {
        addressX = _addressX;
        addressO = _addressO;
        burner = _burner;
    }

    /*
     * Deposits funds into an escrow account.
     *
     * Accounts are as follows:
     * 0: X's bet
     * 1: O's bet
     * 2: X's adjudication deposit
     * 3: O's adjudication deposit
     * 4: X's disconnect deposit
     * 5: O's disconnect deposit
     */
    function deposit(uint account) external {
        if (account >= 6) {
            throw;
        } else {
            funds[account] += msg.value;
        }
    }

    /**
     * Returns the balance of the account corresponding to the above.
     */
    function getBalance(uint account) constant external returns (uint) {
        if (account >= 6) { throw;
        } else {
            return funds[account];
        }
    }

    /**
     * Checks if a given state is valid.
     * Must be a bytes1 that holds the specified values above.
     * Bits 0 and 1 must not both be 1.
     *
     * state: the state to check
     * returns: true if the state is valid, otherwise false
     */
    function checkState(bytes state) constant returns (bool) {
        if (state.length == 1) {
            return uint8(state[0]) & 0x03 != 0x03;
        } else {
            return false;
        }
    }

    /**
     * Splits the funds according to the state.
     *
     * state: the state that will be broadcast
     * returns: true if transaction sent sucessfully, otherwise false
     */
    function broadcastState(bytes state) external onlyOwner returns (bool) {
        if (!checkState(state)) {
            return false;
        }

        uint sendToX = 0;
        uint sendToO = 0;

        uint uintState = uint(state[0]);

        if (uintState & 0x03 == 0x01) {// X wins, gets bet
            sendToX += funds[0] + funds[1];
        } else if (uintState & 0x03 == 0x02) {// O wins, gets bet
            sendToO += funds[0] + funds[1];
        } else {// tie, they get individual bets back
            sendToX += funds[0];
            sendToO += funds[1];
        }

        // checks if funds should be forfeited
        sendToX += (uintState & 0x04 == 0x00 ? funds[2] : 0) + (uintState & 0x10 == 0x00 ? funds[4] : 0);
        sendToO += (uintState & 0x08 == 0x00 ? funds[3] : 0) + (uintState & 0x20 == 0x00 ? funds[5] : 0);

        if (!addressX.send(sendToX)) {
            throw;
        }

        if (!addressO.send(sendToO)) {
            throw;
        }

        // burns the remaining funds
        if (!burner.send(this.balance)) {
            throw;
        }

        return true;
    }

    // funds should only be sent through the deposit method
    function () {
        throw;
    }
}

import "LockedStateWithFunds.sol";

/**
 * TicTacToeLockedState
 *
 * The LockedState for a TicTacToe game.
 */
contract TicTacToeLockedState is LockedState {

    /* bit mappings for state
     * 0: X gets winnings
     * 1: O gets winnings
     * 2: X forfeits adjudication deposit
     * 3: O forfeits adjudication deposit
     * 4: X forfeits disconnect deposit
     * 5: O forfeits disconnect deposit
     * 6: used to indicate cheating. Doesn't change where funds will be sent
     * note, if tie, bits 0 and 1 should both be 0 to indicate tie
     */
    address addressX;
    address addressO;
    address burner;

    uint[6] funds;

    /**
     * addressX: the address of X
     * addressO: the address of O
     * burner: the address which funds will be burned to (usually 0)
     */
    function TicTacToeLockedState(address _addressX, address _addressO, address _burner) {
        addressX = _addressX;
        addressO = _addressO;
        burner = _burner;
    }

    /*
     * Deposits funds into an escrow account.
     *
     * Accounts are as follows:
     * 0: X's bet
     * 1: O's bet
     * 2: X's adjudication deposit
     * 3: O's adjudication deposit
     * 4: X's disconnect deposit
     * 5: O's disconnect deposit
     */
    function deposit(uint account) external {
        if (account >= 6) {
            throw;
        } else {
            funds[account] += msg.value;
        }
    }

    /**
     * Checks if a given state is valid.
     * Must be a bytes1 that holds the specified values above.
     * Bits 0 and 1 must not both be 1.
     *
     * state: the state to check
     * returns: true if the state is valid, otherwise false
     */
    function checkState(bytes state) constant returns (bool) {
        if (state.length == 1) {
            return uint8(state[0]) & 0x03 != 0x03;
        } else {
            return false;
        }
    }

    /**
     * Splits the funds according to the state.
     *
     * state: the state that will be broadcast
     * returns: true if transaction sent sucessfully, otherwise false
     */
    function broadcastState(bytes state) external onlyOwner returns (bool) {
        if (!checkState(state)) {
            return false;
        }

        uint sendToX = 0;
        uint sendToO = 0;

        uint uintState = uint(state[0]);

        if (uintState & 0x03 == 0x01) {// X wins, gets bet
            sendToX += funds[0] + funds[1];
        } else if (uintState & 0x03 == 0x02) {// O wins, gets bet
            sendToO += funds[0] + funds[1];
        } else {// tie, they get individual bets back
            sendToX += funds[0];
            sendToO += funds[1];
        }

        // checks if funds should be forfeited
        sendToX += (uintState & 0x04 == 0x00 ? funds[2] : 0) + (uintState & 0x10 == 0x00 ? funds[4] : 0);
        sendToO += (uintState & 0x08 == 0x00 ? funds[3] : 0) + (uintState & 0x20 == 0x00 ? funds[5] : 0);

        if (!addressX.send(sendToX)) {
            throw;
        }

        if (!addressO.send(sendToO)) {
            throw;
        }

        // burns the remaining funds
        if (!burner.send(this.balance)) {
            throw;
        }

        return true;
    }

    // funds should only be sent through the deposit method
    function () {
        throw;
    }
}


Added EventsHistoryAndStorageUser.sol

Added EventsHistoryAndStorageUser.sol


fix token style

fix token style

// Source: https://github.com/nexusdev/erc20
// Flat file implementation of `dappsys/token/base.sol::DSTokenBase`

// Everything throws instead of returning false on failure.
import 'ERC20.sol';

contract Token is ERC20 {

  mapping( address => uint ) _balances;
  mapping( address => mapping( address => uint ) ) _approvals;
  uint _supply;

  function Token( uint initial_balance ) {
    _balances[msg.sender] = initial_balance;
    _supply = initial_balance;
  }

  function totalSupply() constant returns (uint supply) {
    return _supply;
  }

  function balanceOf( address who ) constant returns (uint value) {
    return _balances[who];
  }

  function transfer( address to, uint value) returns (bool ok) {
    if( _balances[msg.sender] < value ) {
        throw;
    }
    if( !safeToAdd(_balances[to], value) ) {
        throw;
    }
    _balances[msg.sender] -= value;
    _balances[to] += value;
    Transfer( msg.sender, to, value );
    return true;
  }

  function transferFrom( address from, address to, uint value) returns (bool ok) {
    // if you don't have enough balance, throw
    if( _balances[from] < value ) {
        throw;
    }
    // if you don't have approval, throw
    if( _approvals[from][msg.sender] < value ) {
        throw;
    }
    if( !safeToAdd(_balances[to], value) ) {
        throw;
    }
    // transfer and return true
    _approvals[from][msg.sender] -= value;
    _balances[from] -= value;
    _balances[to] += value;
    Transfer( from, to, value );
    return true;
  }

  function approve(address spender, uint value) returns (bool ok) {
    _approvals[msg.sender][spender] = value;
    Approval( msg.sender, spender, value );
    return true;
  }

  function allowance(address owner, address spender) constant returns (uint _allowance) {
    return _approvals[owner][spender];
  }

  function safeToAdd(uint a, uint b) internal returns (bool) {
    return (a + b >= a);
  }
}


Clarify PaymentSplitter shares are static

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (finance/PaymentSplitter.sol)

pragma solidity ^0.8.0;

import "../token/ERC20/utils/SafeERC20.sol";
import "../utils/Address.sol";
import "../utils/Context.sol";

/**
 * @title PaymentSplitter
 * @dev This contract allows to split Ether payments among a group of accounts. The sender does not need to be aware
 * that the Ether will be split in this way, since it is handled transparently by the contract.
 *
 * The split can be in equal parts or in any other arbitrary proportion. The way this is specified is by assigning each
 * account to a number of shares. Of all the Ether that this contract receives, each account will then be able to claim
 * an amount proportional to the percentage of total shares they were assigned. The distribution of shares is set at the
 * time of contract deployment and can't be updated thereafter.
 *
 * `PaymentSplitter` follows a _pull payment_ model. This means that payments are not automatically forwarded to the
 * accounts but kept in this contract, and the actual transfer is triggered as a separate step by calling the {release}
 * function.
 *
 * NOTE: This contract assumes that ERC20 tokens will behave similarly to native tokens (Ether). Rebasing tokens, and
 * tokens that apply fees during transfers, are likely to not be supported as expected. If in doubt, we encourage you
 * to run tests before sending real value to this contract.
 */
contract PaymentSplitter is Context {
    event PayeeAdded(address account, uint256 shares);
    event PaymentReleased(address to, uint256 amount);
    event ERC20PaymentReleased(IERC20 indexed token, address to, uint256 amount);
    event PaymentReceived(address from, uint256 amount);

    uint256 private _totalShares;
    uint256 private _totalReleased;

    mapping(address => uint256) private _shares;
    mapping(address => uint256) private _released;
    address[] private _payees;

    mapping(IERC20 => uint256) private _erc20TotalReleased;
    mapping(IERC20 => mapping(address => uint256)) private _erc20Released;

    /**
     * @dev Creates an instance of `PaymentSplitter` where each account in `payees` is assigned the number of shares at
     * the matching position in the `shares` array.
     *
     * All addresses in `payees` must be non-zero. Both arrays must have the same non-zero length, and there must be no
     * duplicates in `payees`.
     */
    constructor(address[] memory payees, uint256[] memory shares_) payable {
        require(payees.length == shares_.length, "PaymentSplitter: payees and shares length mismatch");
        require(payees.length > 0, "PaymentSplitter: no payees");

        for (uint256 i = 0; i < payees.length; i++) {
            _addPayee(payees[i], shares_[i]);
        }
    }

    /**
     * @dev The Ether received will be logged with {PaymentReceived} events. Note that these events are not fully
     * reliable: it's possible for a contract to receive Ether without triggering this function. This only affects the
     * reliability of the events, and not the actual splitting of Ether.
     *
     * To learn more about this see the Solidity documentation for
     * https://solidity.readthedocs.io/en/latest/contracts.html#fallback-function[fallback
     * functions].
     */
    receive() external payable virtual {
        emit PaymentReceived(_msgSender(), msg.value);
    }

    /**
     * @dev Getter for the total shares held by payees.
     */
    function totalShares() public view returns (uint256) {
        return _totalShares;
    }

    /**
     * @dev Getter for the total amount of Ether already released.
     */
    function totalReleased() public view returns (uint256) {
        return _totalReleased;
    }

    /**
     * @dev Getter for the total amount of `token` already released. `token` should be the address of an IERC20
     * contract.
     */
    function totalReleased(IERC20 token) public view returns (uint256) {
        return _erc20TotalReleased[token];
    }

    /**
     * @dev Getter for the amount of shares held by an account.
     */
    function shares(address account) public view returns (uint256) {
        return _shares[account];
    }

    /**
     * @dev Getter for the amount of Ether already released to a payee.
     */
    function released(address account) public view returns (uint256) {
        return _released[account];
    }

    /**
     * @dev Getter for the amount of `token` tokens already released to a payee. `token` should be the address of an
     * IERC20 contract.
     */
    function released(IERC20 token, address account) public view returns (uint256) {
        return _erc20Released[token][account];
    }

    /**
     * @dev Getter for the address of the payee number `index`.
     */
    function payee(uint256 index) public view returns (address) {
        return _payees[index];
    }

    /**
     * @dev Getter for the amount of payee's releasable Ether.
     */
    function releasable(address account) public view returns (uint256) {
        uint256 totalReceived = address(this).balance + totalReleased();
        return _pendingPayment(account, totalReceived, released(account));
    }

    /**
     * @dev Getter for the amount of payee's releasable `token` tokens. `token` should be the address of an
     * IERC20 contract.
     */
    function releasable(IERC20 token, address account) public view returns (uint256) {
        uint256 totalReceived = token.balanceOf(address(this)) + totalReleased(token);
        return _pendingPayment(account, totalReceived, released(token, account));
    }

    /**
     * @dev Triggers a transfer to `account` of the amount of Ether they are owed, according to their percentage of the
     * total shares and their previous withdrawals.
     */
    function release(address payable account) public virtual {
        require(_shares[account] > 0, "PaymentSplitter: account has no shares");

        uint256 payment = releasable(account);

        require(payment != 0, "PaymentSplitter: account is not due payment");

        _released[account] += payment;
        _totalReleased += payment;

        Address.sendValue(account, payment);
        emit PaymentReleased(account, payment);
    }

    /**
     * @dev Triggers a transfer to `account` of the amount of `token` tokens they are owed, according to their
     * percentage of the total shares and their previous withdrawals. `token` must be the address of an IERC20
     * contract.
     */
    function release(IERC20 token, address account) public virtual {
        require(_shares[account] > 0, "PaymentSplitter: account has no shares");

        uint256 payment = releasable(token, account);

        require(payment != 0, "PaymentSplitter: account is not due payment");

        _erc20Released[token][account] += payment;
        _erc20TotalReleased[token] += payment;

        SafeERC20.safeTransfer(token, account, payment);
        emit ERC20PaymentReleased(token, account, payment);
    }

    /**
     * @dev internal logic for computing the pending payment of an `account` given the token historical balances and
     * already released amounts.
     */
    function _pendingPayment(
        address account,
        uint256 totalReceived,
        uint256 alreadyReleased
    ) private view returns (uint256) {
        return (totalReceived * _shares[account]) / _totalShares - alreadyReleased;
    }

    /**
     * @dev Add a new payee to the contract.
     * @param account The address of the payee to add.
     * @param shares_ The number of shares owned by the payee.
     */
    function _addPayee(address account, uint256 shares_) private {
        require(account != address(0), "PaymentSplitter: account is the zero address");
        require(shares_ > 0, "PaymentSplitter: shares are 0");
        require(_shares[account] == 0, "PaymentSplitter: account already has shares");

        _payees.push(account);
        _shares[account] = shares_;
        _totalShares = _totalShares + shares_;
        emit PayeeAdded(account, shares_);
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (finance/PaymentSplitter.sol)

pragma solidity ^0.8.0;

import "../token/ERC20/utils/SafeERC20.sol";
import "../utils/Address.sol";
import "../utils/Context.sol";

/**
 * @title PaymentSplitter
 * @dev This contract allows to split Ether payments among a group of accounts. The sender does not need to be aware
 * that the Ether will be split in this way, since it is handled transparently by the contract.
 *
 * The split can be in equal parts or in any other arbitrary proportion. The way this is specified is by assigning each
 * account to a number of shares. Of all the Ether that this contract receives, each account will then be able to claim
 * an amount proportional to the percentage of total shares they were assigned.
 *
 * `PaymentSplitter` follows a _pull payment_ model. This means that payments are not automatically forwarded to the
 * accounts but kept in this contract, and the actual transfer is triggered as a separate step by calling the {release}
 * function.
 *
 * NOTE: This contract assumes that ERC20 tokens will behave similarly to native tokens (Ether). Rebasing tokens, and
 * tokens that apply fees during transfers, are likely to not be supported as expected. If in doubt, we encourage you
 * to run tests before sending real value to this contract.
 */
contract PaymentSplitter is Context {
    event PayeeAdded(address account, uint256 shares);
    event PaymentReleased(address to, uint256 amount);
    event ERC20PaymentReleased(IERC20 indexed token, address to, uint256 amount);
    event PaymentReceived(address from, uint256 amount);

    uint256 private _totalShares;
    uint256 private _totalReleased;

    mapping(address => uint256) private _shares;
    mapping(address => uint256) private _released;
    address[] private _payees;

    mapping(IERC20 => uint256) private _erc20TotalReleased;
    mapping(IERC20 => mapping(address => uint256)) private _erc20Released;

    /**
     * @dev Creates an instance of `PaymentSplitter` where each account in `payees` is assigned the number of shares at
     * the matching position in the `shares` array.
     *
     * All addresses in `payees` must be non-zero. Both arrays must have the same non-zero length, and there must be no
     * duplicates in `payees`.
     */
    constructor(address[] memory payees, uint256[] memory shares_) payable {
        require(payees.length == shares_.length, "PaymentSplitter: payees and shares length mismatch");
        require(payees.length > 0, "PaymentSplitter: no payees");

        for (uint256 i = 0; i < payees.length; i++) {
            _addPayee(payees[i], shares_[i]);
        }
    }

    /**
     * @dev The Ether received will be logged with {PaymentReceived} events. Note that these events are not fully
     * reliable: it's possible for a contract to receive Ether without triggering this function. This only affects the
     * reliability of the events, and not the actual splitting of Ether.
     *
     * To learn more about this see the Solidity documentation for
     * https://solidity.readthedocs.io/en/latest/contracts.html#fallback-function[fallback
     * functions].
     */
    receive() external payable virtual {
        emit PaymentReceived(_msgSender(), msg.value);
    }

    /**
     * @dev Getter for the total shares held by payees.
     */
    function totalShares() public view returns (uint256) {
        return _totalShares;
    }

    /**
     * @dev Getter for the total amount of Ether already released.
     */
    function totalReleased() public view returns (uint256) {
        return _totalReleased;
    }

    /**
     * @dev Getter for the total amount of `token` already released. `token` should be the address of an IERC20
     * contract.
     */
    function totalReleased(IERC20 token) public view returns (uint256) {
        return _erc20TotalReleased[token];
    }

    /**
     * @dev Getter for the amount of shares held by an account.
     */
    function shares(address account) public view returns (uint256) {
        return _shares[account];
    }

    /**
     * @dev Getter for the amount of Ether already released to a payee.
     */
    function released(address account) public view returns (uint256) {
        return _released[account];
    }

    /**
     * @dev Getter for the amount of `token` tokens already released to a payee. `token` should be the address of an
     * IERC20 contract.
     */
    function released(IERC20 token, address account) public view returns (uint256) {
        return _erc20Released[token][account];
    }

    /**
     * @dev Getter for the address of the payee number `index`.
     */
    function payee(uint256 index) public view returns (address) {
        return _payees[index];
    }

    /**
     * @dev Getter for the amount of payee's releasable Ether.
     */
    function releasable(address account) public view returns (uint256) {
        uint256 totalReceived = address(this).balance + totalReleased();
        return _pendingPayment(account, totalReceived, released(account));
    }

    /**
     * @dev Getter for the amount of payee's releasable `token` tokens. `token` should be the address of an
     * IERC20 contract.
     */
    function releasable(IERC20 token, address account) public view returns (uint256) {
        uint256 totalReceived = token.balanceOf(address(this)) + totalReleased(token);
        return _pendingPayment(account, totalReceived, released(token, account));
    }

    /**
     * @dev Triggers a transfer to `account` of the amount of Ether they are owed, according to their percentage of the
     * total shares and their previous withdrawals.
     */
    function release(address payable account) public virtual {
        require(_shares[account] > 0, "PaymentSplitter: account has no shares");

        uint256 payment = releasable(account);

        require(payment != 0, "PaymentSplitter: account is not due payment");

        _released[account] += payment;
        _totalReleased += payment;

        Address.sendValue(account, payment);
        emit PaymentReleased(account, payment);
    }

    /**
     * @dev Triggers a transfer to `account` of the amount of `token` tokens they are owed, according to their
     * percentage of the total shares and their previous withdrawals. `token` must be the address of an IERC20
     * contract.
     */
    function release(IERC20 token, address account) public virtual {
        require(_shares[account] > 0, "PaymentSplitter: account has no shares");

        uint256 payment = releasable(token, account);

        require(payment != 0, "PaymentSplitter: account is not due payment");

        _erc20Released[token][account] += payment;
        _erc20TotalReleased[token] += payment;

        SafeERC20.safeTransfer(token, account, payment);
        emit ERC20PaymentReleased(token, account, payment);
    }

    /**
     * @dev internal logic for computing the pending payment of an `account` given the token historical balances and
     * already released amounts.
     */
    function _pendingPayment(
        address account,
        uint256 totalReceived,
        uint256 alreadyReleased
    ) private view returns (uint256) {
        return (totalReceived * _shares[account]) / _totalShares - alreadyReleased;
    }

    /**
     * @dev Add a new payee to the contract.
     * @param account The address of the payee to add.
     * @param shares_ The number of shares owned by the payee.
     */
    function _addPayee(address account, uint256 shares_) private {
        require(account != address(0), "PaymentSplitter: account is the zero address");
        require(shares_ > 0, "PaymentSplitter: shares are 0");
        require(_shares[account] == 0, "PaymentSplitter: account already has shares");

        _payees.push(account);
        _shares[account] = shares_;
        _totalShares = _totalShares + shares_;
        emit PayeeAdded(account, shares_);
    }
}


arbitrum: Pin solc 0.8.8 for DummyGateway

//SPDX-License-Identifier: MIT
pragma solidity 0.8.8;

contract DummyGateway {
    function calculateL2TokenAddress(address _token) external pure returns (address) {
        return _token;
    }

    function counterpartGateway() external view returns (address) {
        return address(this);
    }
}

pragma solidity ^0.5.11;

contract DummyGateway {
    function calculateL2TokenAddress(address _token) external pure returns (address) {
        return _token;
    }

    function counterpartGateway() external view returns (address) {
        return address(this);
    }
}


- Removed noWaitPeriod flag from the contract as it was not necessary

pragma solidity ^0.4.2;

import "./priced.sol";
import "./stateMachine.sol";
import "./accessRestricted.sol";

/// @title Brehon Contract
contract BrehonContract is
    priced,
    stateMachine,
    accessRestricted {

  struct Party {
    address addr;
    uint deposit;
    bool contractAccepted;
  }

  struct Brehon {
    address addr;
    bool contractAccepted;
    uint fixedFee;
    uint disputeFee;
  }

  struct Resolution {
    address proposerAddr;
    uint awardPartyA;
    uint awardPartyB;
    bool partyAAccepted;
    bool partyBAccepted;
  }

  uint public transactionAmount;
  uint public minimumContractAmt;
  bytes32 public contractTermsHash;
  Party public partyA;
  Party public partyB;
  Brehon public primaryBrehon;
  Brehon public secondaryBrehon;
  Brehon public tertiaryBrehon;
  Brehon public activeBrehon;

  mapping (address => uint) public awards;
  Resolution public proposedSettlement;

  uint8 public appealPeriodInDays = 5;
  uint public appealPeriodStartTime;

  event ExecutionStarted(address _caller, uint _totalDeposits);
  event ContractDisputed(address _disputingParty, address _activeBrehon);
  event AppealPeriodStarted(uint _appealPeriodStartTime, address _activeBrehon, uint _awardPartyA, uint _awardPartyB);
  //TODO: Provide the information about the party which appealed
  event AppealRaised(address appealingParty, address activeBrehon);
  event SecondAppealRaised(address appealingParty, address activeBrehon);
  event SettlementProposed(address _proposingParty, uint _awardPartyA, uint _awardPartyB);
  event DisputeResolved(uint _awardPartyA, uint _awardPartyB);
  event FundsClaimed(address claimingParty, uint amount);

  modifier byEitherEntities() {
    if (msg.sender != primaryBrehon.addr &&
        msg.sender != secondaryBrehon.addr &&
        msg.sender != tertiaryBrehon.addr &&
        msg.sender != partyA.addr &&
        msg.sender != partyB.addr) {
        throw;
    }
    _;
  }

  modifier eitherByParty(Party _party1, Party _party2)
  {
    if (msg.sender != _party1.addr &&
        msg.sender != _party2.addr)
        throw;
    _;
  }

  modifier atAdjudicatableStages()
  {
    if(stage != Stages.Dispute &&
       stage != Stages.Appeal &&
       stage != Stages.SecondAppeal)
        throw;
    _;
  }

  modifier duringDispute()
  {
    if(stage == Stages.Negotiation ||
       stage == Stages.Completed)
        throw;
    _;
  }

  modifier onlyByBrehon(Brehon _brehon) {
    if (msg.sender != _brehon.addr)
        throw;
    _;
  }

  function BrehonContract(
      address _partyA,
      address _partyB,
      uint _transactionAmount,
      bytes32 _contractTermsHash,
      address _primaryBrehon,
      uint _primaryBrehonFixedFee,
      uint _primaryBrehonDisputeFee,
      address _secondaryBrehon,
      uint _secondaryBrehonFixedFee,
      uint _secondaryBrehonDisputeFee,
      address _tertiaryBrehon,
      uint _tertiaryBrehonFixedFee,
      uint _tertiaryBrehonDisputeFee
  ) {
    partyA.addr = _partyA;
    transactionAmount = _transactionAmount;
    contractTermsHash = _contractTermsHash;

    partyB.addr = _partyB;

    primaryBrehon.addr = _primaryBrehon;
    primaryBrehon.fixedFee = _primaryBrehonFixedFee;
    primaryBrehon.disputeFee = _primaryBrehonDisputeFee;

    secondaryBrehon.addr = _secondaryBrehon;
    secondaryBrehon.fixedFee = _secondaryBrehonFixedFee;
    secondaryBrehon.disputeFee = _secondaryBrehonDisputeFee;

    tertiaryBrehon.addr = _tertiaryBrehon;
    tertiaryBrehon.fixedFee = _tertiaryBrehonFixedFee;
    tertiaryBrehon.disputeFee = _tertiaryBrehonDisputeFee;

    minimumContractAmt = primaryBrehon.fixedFee + primaryBrehon.disputeFee +
        secondaryBrehon.fixedFee + secondaryBrehon.disputeFee +
        tertiaryBrehon.fixedFee + tertiaryBrehon.disputeFee +
        transactionAmount;

    //Defaults
    stage = Stages.Negotiation;
    partyA.contractAccepted = false;
    partyA.deposit = 0;

    partyB.contractAccepted = false;
    partyB.deposit = 0;

    primaryBrehon.contractAccepted = false;
    secondaryBrehon.contractAccepted = false;
    tertiaryBrehon.contractAccepted = false;
  }

  function acceptContract()
    atStage(Stages.Negotiation)
  {
      if (msg.sender == partyA.addr) {
          partyA.contractAccepted = true;
      } else if (msg.sender == partyB.addr) {
          partyB.contractAccepted = true;
      } else if(msg.sender == primaryBrehon.addr) {
          primaryBrehon.contractAccepted = true;
      } else if(msg.sender == secondaryBrehon.addr) {
          secondaryBrehon.contractAccepted = true;
      } else if(msg.sender == tertiaryBrehon.addr) {
          tertiaryBrehon.contractAccepted = true;
      } else throw;
  }

  function deposit()
    payable
  {
      if(msg.sender == partyA.addr) {
          partyA.deposit += msg.value;
      } else if (msg.sender == partyB.addr) {
          partyB.deposit += msg.value;
      } else throw;
  }

  function startContract()
    atStage(Stages.Negotiation)
    eitherByParty(partyA, partyB)
  {
      if(!partyA.contractAccepted ||
         !partyB.contractAccepted ||
         !primaryBrehon.contractAccepted ||
         !secondaryBrehon.contractAccepted ||
         !tertiaryBrehon.contractAccepted) throw;

      if ((partyA.deposit + partyB.deposit) >=
          minimumContractAmt) {
             ExecutionStarted(msg.sender, partyA.deposit + partyB.deposit);
             stage = Stages.Execution; // STATECHANGE
             awards[primaryBrehon.addr] = primaryBrehon.fixedFee;
             awards[secondaryBrehon.addr] = secondaryBrehon.fixedFee;
             awards[tertiaryBrehon.addr] = tertiaryBrehon.fixedFee;
      } else throw;
  }

  function raiseDispute()
    atStage(Stages.Execution)
    eitherByParty(partyA, partyB)
  {
    stage = Stages.Dispute; // STATECHANGE
    awards[primaryBrehon.addr] += primaryBrehon.disputeFee;
    activeBrehon = primaryBrehon;
    ContractDisputed(msg.sender, primaryBrehon.addr);
  }

  function adjudicate(uint _awardPartyA, uint _awardPartyB)
    atAdjudicatableStages()
    onlyByBrehon(activeBrehon)
  {
    if((_awardPartyA + _awardPartyB) > (partyA.deposit + partyB.deposit)) throw;

    if (stage == Stages.Dispute) {
        stage = Stages.AppealPeriod; // STATECHANGE
    } else if (stage == Stages.Appeal) {
        stage = Stages.SecondAppealPeriod;  // STATECHANGE
    } else if (stage == Stages.SecondAppeal) {
        stage = Stages.Completed; // STATECHANGE
    } else {
        throw;
    }

    awards[partyA.addr] = _awardPartyA;
    awards[partyB.addr] = _awardPartyB;

    if (stage != Stages.Completed) {
        appealPeriodStartTime = now;

        AppealPeriodStarted(appealPeriodStartTime, activeBrehon.addr, _awardPartyA, _awardPartyB);
    } else {
        stage = Stages.Completed;
    }
  }

  function getActiveJudgmentByParty(address _partyAddress)
    returns (uint)
  {
      if(_partyAddress != partyA.addr &&
         _partyAddress != partyB.addr) throw;
    return awards[_partyAddress];
  }

  function claimFunds()
    byEitherEntities()
  {
    if (stage != Stages.Completed) {
        if (stage != Stages.AppealPeriod && stage != Stages.SecondAppealPeriod) {
            throw;
        }
        if (now >= appealPeriodStartTime + (appealPeriodInDays * 1 days)) {
            stage = Stages.Completed; // STATECHANGE
        }
    }

    if (stage != Stages.Completed) throw;

    uint amount = awards[msg.sender];

    if (amount == 0) {
      throw;
    }

    if (this.balance < amount) {
      throw;
    }

    awards[msg.sender] = 0;

    if(msg.sender.send(amount)) {
      FundsClaimed(msg.sender, amount);
    } else {
      awards[msg.sender] = amount;
      throw;
    }
  }

  function raiseAppeal()
    atStage(Stages.AppealPeriod)
    eitherByParty(partyA, partyB)
  {
    stage = Stages.Appeal; // STATECHANGE
    awards[secondaryBrehon.addr] += secondaryBrehon.disputeFee;

    activeBrehon = secondaryBrehon;

    AppealRaised(msg.sender, activeBrehon.addr);
  }

  function raise2ndAppeal()
    atStage(Stages.SecondAppealPeriod)
    eitherByParty(partyA, partyB)
  {
    stage = Stages.SecondAppeal; // STATECHANGE
    awards[tertiaryBrehon.addr] += tertiaryBrehon.disputeFee;

    activeBrehon = tertiaryBrehon;

    SecondAppealRaised(msg.sender, activeBrehon.addr);
  }

  function proposeSettlement(uint _awardPartyA, uint _awardPartyB)
    duringDispute()
    eitherByParty(partyA, partyB)
  {
      proposedSettlement.proposerAddr = msg.sender;
      proposedSettlement.awardPartyA = _awardPartyA;
      proposedSettlement.awardPartyB = _awardPartyB;
      if (msg.sender == partyA.addr) {
          proposedSettlement.partyAAccepted = true;
          proposedSettlement.partyBAccepted = false;
      } else if (msg.sender == partyB.addr) {
          proposedSettlement.partyAAccepted = false;
          proposedSettlement.partyBAccepted = true;
      }

      SettlementProposed(msg.sender, _awardPartyA, _awardPartyB);
  }

  function acceptSettlement(uint _awardPartyA, uint _awardPartyB)
    duringDispute()
    eitherByParty(partyA, partyB)
  {
      if((proposedSettlement.awardPartyA != _awardPartyA) ||
         (proposedSettlement.awardPartyB != _awardPartyB))
          throw;

      if(msg.sender == partyA.addr) {
          proposedSettlement.partyAAccepted = true;
      }

      if(msg.sender == partyB.addr) {
          proposedSettlement.partyBAccepted = true;
      }

      if(proposedSettlement.partyAAccepted && proposedSettlement.partyBAccepted) {
          awards[partyA.addr] = proposedSettlement.awardPartyA;
          awards[partyB.addr] = proposedSettlement.awardPartyB;
          stage = Stages.Completed; // STATECHANGE
          DisputeResolved(_awardPartyA, _awardPartyB);
      }
  }
}

pragma solidity ^0.4.2;

import "./priced.sol";
import "./stateMachine.sol";
import "./accessRestricted.sol";

/// @title Brehon Contract
contract BrehonContract is
    priced,
    stateMachine,
    accessRestricted {

  struct Party {
    address addr;
    uint deposit;
    bool contractAccepted;
  }

  struct Brehon {
    address addr;
    bool contractAccepted;
    uint fixedFee;
    uint disputeFee;
  }

  struct Resolution {
    address proposerAddr;
    uint awardPartyA;
    uint awardPartyB;
    bool partyAAccepted;
    bool partyBAccepted;
  }

  uint public transactionAmount;
  uint public minimumContractAmt;
  bytes32 public contractTermsHash;
  bool public noWaitPeriod;
  Party public partyA;
  Party public partyB;
  Brehon public primaryBrehon;
  Brehon public secondaryBrehon;
  Brehon public tertiaryBrehon;
  Brehon public activeBrehon;

  mapping (address => uint) public awards;
  Resolution public proposedSettlement;

  uint8 public appealPeriodInDays = 5;
  uint public appealPeriodStartTime;

  event ExecutionStarted(address _caller, uint _totalDeposits);
  event ContractDisputed(address _disputingParty, address _activeBrehon);
  event AppealPeriodStarted(uint _appealPeriodStartTime, address _activeBrehon, uint _awardPartyA, uint _awardPartyB);
  //TODO: Provide the information about the party which appealed
  event AppealRaised(address appealingParty, address activeBrehon);
  event SecondAppealRaised(address appealingParty, address activeBrehon);
  event SettlementProposed(address _proposingParty, uint _awardPartyA, uint _awardPartyB);
  event DisputeResolved(uint _awardPartyA, uint _awardPartyB);
  event FundsClaimed(address claimingParty, uint amount);

  modifier byEitherEntities() {
    if (msg.sender != primaryBrehon.addr &&
        msg.sender != secondaryBrehon.addr &&
        msg.sender != tertiaryBrehon.addr &&
        msg.sender != partyA.addr &&
        msg.sender != partyB.addr) {
        throw;
    }
    _;
  }

  modifier eitherByParty(Party _party1, Party _party2)
  {
    if (msg.sender != _party1.addr &&
        msg.sender != _party2.addr)
        throw;
    _;
  }

  modifier atAdjudicatableStages()
  {
    if(stage != Stages.Dispute &&
       stage != Stages.Appeal &&
       stage != Stages.SecondAppeal)
        throw;
    _;
  }

  modifier duringDispute()
  {
    if(stage == Stages.Negotiation ||
       stage == Stages.Completed)
        throw;
    _;
  }

  modifier onlyByBrehon(Brehon _brehon) {
    if (msg.sender != _brehon.addr)
        throw;
    _;
  }

  function BrehonContract(
      address _partyA,
      address _partyB,
      uint _transactionAmount,
      bytes32 _contractTermsHash,
      address _primaryBrehon,
      uint _primaryBrehonFixedFee,
      uint _primaryBrehonDisputeFee,
      address _secondaryBrehon,
      uint _secondaryBrehonFixedFee,
      uint _secondaryBrehonDisputeFee,
      address _tertiaryBrehon,
      uint _tertiaryBrehonFixedFee,
      uint _tertiaryBrehonDisputeFee
  ) {
    partyA.addr = _partyA;
    transactionAmount = _transactionAmount;
    contractTermsHash = _contractTermsHash;

    partyB.addr = _partyB;

    primaryBrehon.addr = _primaryBrehon;
    primaryBrehon.fixedFee = _primaryBrehonFixedFee;
    primaryBrehon.disputeFee = _primaryBrehonDisputeFee;

    secondaryBrehon.addr = _secondaryBrehon;
    secondaryBrehon.fixedFee = _secondaryBrehonFixedFee;
    secondaryBrehon.disputeFee = _secondaryBrehonDisputeFee;

    tertiaryBrehon.addr = _tertiaryBrehon;
    tertiaryBrehon.fixedFee = _tertiaryBrehonFixedFee;
    tertiaryBrehon.disputeFee = _tertiaryBrehonDisputeFee;

    minimumContractAmt = primaryBrehon.fixedFee + primaryBrehon.disputeFee +
        secondaryBrehon.fixedFee + secondaryBrehon.disputeFee +
        tertiaryBrehon.fixedFee + tertiaryBrehon.disputeFee +
        transactionAmount;

    //Defaults
    stage = Stages.Negotiation;
    noWaitPeriod = false;
    partyA.contractAccepted = false;
    partyA.deposit = 0;

    partyB.contractAccepted = false;
    partyB.deposit = 0;

    primaryBrehon.contractAccepted = false;
    secondaryBrehon.contractAccepted = false;
    tertiaryBrehon.contractAccepted = false;
  }

  function acceptContract()
    atStage(Stages.Negotiation)
  {
      if (msg.sender == partyA.addr) {
          partyA.contractAccepted = true;
      } else if (msg.sender == partyB.addr) {
          partyB.contractAccepted = true;
      } else if(msg.sender == primaryBrehon.addr) {
          primaryBrehon.contractAccepted = true;
      } else if(msg.sender == secondaryBrehon.addr) {
          secondaryBrehon.contractAccepted = true;
      } else if(msg.sender == tertiaryBrehon.addr) {
          tertiaryBrehon.contractAccepted = true;
      } else throw;
  }

  function deposit()
    payable
  {
      if(msg.sender == partyA.addr) {
          partyA.deposit += msg.value;
      } else if (msg.sender == partyB.addr) {
          partyB.deposit += msg.value;
      } else throw;
  }

  function startContract()
    atStage(Stages.Negotiation)
    eitherByParty(partyA, partyB)
  {
      if(!partyA.contractAccepted ||
         !partyB.contractAccepted ||
         !primaryBrehon.contractAccepted ||
         !secondaryBrehon.contractAccepted ||
         !tertiaryBrehon.contractAccepted) throw;

      if ((partyA.deposit + partyB.deposit) >=
          minimumContractAmt) {
             ExecutionStarted(msg.sender, partyA.deposit + partyB.deposit);
             stage = Stages.Execution; // STATECHANGE
             awards[primaryBrehon.addr] = primaryBrehon.fixedFee;
             awards[secondaryBrehon.addr] = secondaryBrehon.fixedFee;
             awards[tertiaryBrehon.addr] = tertiaryBrehon.fixedFee;
      } else throw;
  }

  function raiseDispute()
    atStage(Stages.Execution)
    eitherByParty(partyA, partyB)
  {
    stage = Stages.Dispute; // STATECHANGE
    awards[primaryBrehon.addr] += primaryBrehon.disputeFee;
    activeBrehon = primaryBrehon;
    ContractDisputed(msg.sender, primaryBrehon.addr);
  }

  function adjudicate(uint _awardPartyA, uint _awardPartyB)
    atAdjudicatableStages()
    onlyByBrehon(activeBrehon)
  {
    if((_awardPartyA + _awardPartyB) > (partyA.deposit + partyB.deposit)) throw;

    if (stage == Stages.Dispute) {
        stage = Stages.AppealPeriod; // STATECHANGE
    } else if (stage == Stages.Appeal) {
        stage = Stages.SecondAppealPeriod;  // STATECHANGE
    } else if (stage == Stages.SecondAppeal) {
        stage = Stages.Completed; // STATECHANGE
    } else {
        throw;
    }

    awards[partyA.addr] = _awardPartyA;
    awards[partyB.addr] = _awardPartyB;

    if (stage != Stages.Completed) {
        appealPeriodStartTime = now;

        AppealPeriodStarted(appealPeriodStartTime, activeBrehon.addr, _awardPartyA, _awardPartyB);
    } else {
        noWaitPeriod = true;
    }
  }

  function getActiveJudgmentByParty(address _partyAddress)
    returns (uint)
  {
      if(_partyAddress != partyA.addr &&
         _partyAddress != partyB.addr) throw;
    return awards[_partyAddress];
  }

  function claimFunds()
    byEitherEntities()
  {
    if (stage != Stages.Completed) {
        if (stage != Stages.AppealPeriod && stage != Stages.SecondAppealPeriod) {
            throw;
        }
        if (noWaitPeriod || now >= appealPeriodStartTime + (appealPeriodInDays * 1 days)) {
            stage = Stages.Completed; // STATECHANGE
        }
    }

    if (stage != Stages.Completed) throw;

    uint amount = awards[msg.sender];

    if (amount == 0) {
      throw;
    }

    if (this.balance < amount) {
      throw;
    }

    awards[msg.sender] = 0;

    if(msg.sender.send(amount)) {
      FundsClaimed(msg.sender, amount);
    } else {
      awards[msg.sender] = amount;
      throw;
    }
  }

  function raiseAppeal()
    atStage(Stages.AppealPeriod)
    eitherByParty(partyA, partyB)
  {
    stage = Stages.Appeal; // STATECHANGE
    awards[secondaryBrehon.addr] += secondaryBrehon.disputeFee;

    activeBrehon = secondaryBrehon;

    AppealRaised(msg.sender, activeBrehon.addr);
  }

  function raise2ndAppeal()
    atStage(Stages.SecondAppealPeriod)
    eitherByParty(partyA, partyB)
  {
    stage = Stages.SecondAppeal; // STATECHANGE
    awards[tertiaryBrehon.addr] += tertiaryBrehon.disputeFee;

    activeBrehon = tertiaryBrehon;

    SecondAppealRaised(msg.sender, activeBrehon.addr);
  }

  function proposeSettlement(uint _awardPartyA, uint _awardPartyB)
    duringDispute()
    eitherByParty(partyA, partyB)
  {
      proposedSettlement.proposerAddr = msg.sender;
      proposedSettlement.awardPartyA = _awardPartyA;
      proposedSettlement.awardPartyB = _awardPartyB;
      if (msg.sender == partyA.addr) {
          proposedSettlement.partyAAccepted = true;
          proposedSettlement.partyBAccepted = false;
      } else if (msg.sender == partyB.addr) {
          proposedSettlement.partyAAccepted = false;
          proposedSettlement.partyBAccepted = true;
      }

      SettlementProposed(msg.sender, _awardPartyA, _awardPartyB);
  }

  function acceptSettlement(uint _awardPartyA, uint _awardPartyB)
    duringDispute()
    eitherByParty(partyA, partyB)
  {
      if((proposedSettlement.awardPartyA != _awardPartyA) ||
         (proposedSettlement.awardPartyB != _awardPartyB))
          throw;

      if(msg.sender == partyA.addr) {
          proposedSettlement.partyAAccepted = true;
      }

      if(msg.sender == partyB.addr) {
          proposedSettlement.partyBAccepted = true;
      }

      if(proposedSettlement.partyAAccepted && proposedSettlement.partyBAccepted) {
          awards[partyA.addr] = proposedSettlement.awardPartyA;
          awards[partyB.addr] = proposedSettlement.awardPartyB;
          noWaitPeriod = true;
          stage = Stages.Completed; // STATECHANGE
          DisputeResolved(_awardPartyA, _awardPartyB);
      }
  }
}


Makes withdrawal pattern consistent with other contracts.

import {Exchange, Custodian} from './Exchange.sol';
import {PatronageRegistry} from './PatronageRegistry.sol';

contract RevenueSharing is Custodian {
    struct Shareholder {
        bool active;
        int16 nextHolder;
        uint32 shareCount;
        address owner;
    }

    int16 head = -1;
    uint16 constant maximumShareholders = 10000;
    uint32 constant totalShares = 10000000;
    address owner;
    mapping (address => uint32) reservedShares;
    mapping (address => uint) dividendBalances;
    Shareholder[10000] shareholders;
    Exchange exchange;
    PatronageRegistry registry;

    function RevenueSharingContract() {
        owner = msg.sender;
        exchange = new Exchange();
        registry = new PatronageRegistry(address(this));
        shareholders[0] = Shareholder(true, -1, totalShares, owner);
        head = 0;
    }

    function withdrawal() returns (bool success) {
        uint amount = dividendBalances[msg.sender];
        if (amount == 0) {
            throw;
        }
        dividendBalances[msg.sender] = 0;
        if (!msg.sender.send(amount)) {
            throw
        }
    }

    function allocateDividends() {
        uint balance = this.balance;
        int16 currentHolder = head;
        while (currentHolder != -1) {
            uint index = uint(currentHolder);
            address shareholder = shareholders[index].owner;
            uint32 shareCount = shareholders[index].shareCount;
            uint allocation = balance * shareCount / totalShares;
            dividendBalances[shareholder] += allocation;
        }
    }

    function transfer(address oldOwner, address newOwner, uint shares) {
        var (ownerIndex, ownerParentIndex) = findShareholder(oldOwner);
        if (ownerIndex == -1) {
            throw;
        }
        uint32 ownerBalance = shareholders[uint(ownerIndex)].shareCount - reservedShares[oldOwner];
        if (ownerBalance < shares) {
            throw;
        }
        if (ownerBalance == shares) {
            int16 nextIndex = shareholders[uint(ownerIndex)].nextHolder;
            if (ownerParentIndex != -1) {
                shareholders[uint(ownerParentIndex)].nextHolder = nextIndex;
            } else {
                head = nextIndex;
            }
            shareholders[uint(ownerIndex)].active = false;
        }
        var (newIndex, newParent) = findShareholder(newOwner);
        if (newIndex != -1) {
            shareholders[uint(newIndex)].shareCount += uint32(shares);
        } else {
            int16 targetIndex = allocateShareholder(newOwner, uint32(shares));
            if (newParent != -1) {
                shareholders[uint(newParent)].nextHolder = targetIndex;
            } else {
                head = targetIndex;
            }
        }
    }

    function reserve(address owner, uint shares) {
        if (msg.sender != address(exchange)) {
            throw;
        }
        var (index, _) = findShareholder(owner);
        if (index == -1) {
            throw;
        }
        uint32 ownedShares = shareholders[uint(index)].shareCount;
        uint32 availableShares = ownedShares - reservedShares[owner];
        if (availableShares < shares) {
            throw;
        }
        reservedShares[owner] = uint32(shares);
    }

    function unreserve(address owner, uint shares) {
        if (msg.sender != address(exchange)) {
            throw;
        }
        var (index, _) = findShareholder(owner);
        if (index == -1) {
            throw;
        }
        uint32 reserved = reservedShares[owner];
        if (reserved < shares) {
            throw;
        }
        reservedShares[owner] -= uint32(shares);
    }

    function findShareholder(address owner) private returns (int16 index, int16 parent) {
        int16 previous = -1;
        int16 current = head;
        while (current != -1) {
            if (shareholders[uint(current)].owner == owner) {
                return (current, previous);
            }
            previous = current;
            current = shareholders[uint(current)].nextHolder;
        }
        return (-1, previous);
    }

    function allocateShareholder(address owner, uint32 shares) private returns (int16 index) {
        for (uint i = 0; i < maximumShareholders; i++) {
            if (!shareholders[i].active) {
                shareholders[i] = Shareholder(true, -1, shares, owner);
                return int16(i);
            }
        }
        throw;
    }

    function () {
    }
}

import {Exchange, Custodian} from './Exchange.sol';
import {PatronageRegistry} from './PatronageRegistry.sol';

contract RevenueSharing is Custodian {
    struct Shareholder {
        bool active;
        int16 nextHolder;
        uint32 shareCount;
        address owner;
    }

    int16 head = -1;
    uint16 constant maximumShareholders = 10000;
    uint32 constant totalShares = 10000000;
    address owner;
    mapping (address => uint32) reservedShares;
    mapping (address => uint) dividendBalances;
    Shareholder[10000] shareholders;
    Exchange exchange;
    PatronageRegistry registry;

    function RevenueSharingContract() {
        owner = msg.sender;
        exchange = new Exchange();
        registry = new PatronageRegistry(address(this));
        shareholders[0] = Shareholder(true, -1, totalShares, owner);
        head = 0;
    }

    function withdrawal() returns (bool success) {
        uint amount = dividendBalances[msg.sender];
        if (amount == 0) {
            throw;
        }
        dividendBalances[msg.sender] = 0;
        if (msg.sender.send(amount)) {
            return true;
        }
        dividendBalances[msg.sender] = amount;
        return false;
    }

    function allocateDividends() {
        uint balance = this.balance;
        int16 currentHolder = head;
        while (currentHolder != -1) {
            uint index = uint(currentHolder);
            address shareholder = shareholders[index].owner;
            uint32 shareCount = shareholders[index].shareCount;
            uint allocation = balance * shareCount / totalShares;
            dividendBalances[shareholder] += allocation;
        }
    }

    function transfer(address oldOwner, address newOwner, uint shares) {
        var (ownerIndex, ownerParentIndex) = findShareholder(oldOwner);
        if (ownerIndex == -1) {
            throw;
        }
        uint32 ownerBalance = shareholders[uint(ownerIndex)].shareCount - reservedShares[oldOwner];
        if (ownerBalance < shares) {
            throw;
        }
        if (ownerBalance == shares) {
            int16 nextIndex = shareholders[uint(ownerIndex)].nextHolder;
            if (ownerParentIndex != -1) {
                shareholders[uint(ownerParentIndex)].nextHolder = nextIndex;
            } else {
                head = nextIndex;
            }
            shareholders[uint(ownerIndex)].active = false;
        }
        var (newIndex, newParent) = findShareholder(newOwner);
        if (newIndex != -1) {
            shareholders[uint(newIndex)].shareCount += uint32(shares);
        } else {
            int16 targetIndex = allocateShareholder(newOwner, uint32(shares));
            if (newParent != -1) {
                shareholders[uint(newParent)].nextHolder = targetIndex;
            } else {
                head = targetIndex;
            }
        }
    }

    function reserve(address owner, uint shares) {
        if (msg.sender != address(exchange)) {
            throw;
        }
        var (index, _) = findShareholder(owner);
        if (index == -1) {
            throw;
        }
        uint32 ownedShares = shareholders[uint(index)].shareCount;
        uint32 availableShares = ownedShares - reservedShares[owner];
        if (availableShares < shares) {
            throw;
        }
        reservedShares[owner] = uint32(shares);
    }

    function unreserve(address owner, uint shares) {
        if (msg.sender != address(exchange)) {
            throw;
        }
        var (index, _) = findShareholder(owner);
        if (index == -1) {
            throw;
        }
        uint32 reserved = reservedShares[owner];
        if (reserved < shares) {
            throw;
        }
        reservedShares[owner] -= uint32(shares);
    }

    function findShareholder(address owner) private returns (int16 index, int16 parent) {
        int16 previous = -1;
        int16 current = head;
        while (current != -1) {
            if (shareholders[uint(current)].owner == owner) {
                return (current, previous);
            }
            previous = current;
            current = shareholders[uint(current)].nextHolder;
        }
        return (-1, previous);
    }

    function allocateShareholder(address owner, uint32 shares) private returns (int16 index) {
        for (uint i = 0; i < maximumShareholders; i++) {
            if (!shareholders[i].active) {
                shareholders[i] = Shareholder(true, -1, shares, owner);
                return int16(i);
            }
        }
        throw;
    }

    function () {
    }
}


Forbid NOOP reparameterizations thru dupe props

pragma solidity^0.4.11;

import "./PLCRVoting.sol";
import "./historical/StandardToken.sol";

contract Parameterizer {

  // ------
  // EVENTS
  // ------

  event _ReparameterizationProposal(address proposer, string name, uint value, bytes32 propID);

  mapping(bytes32 => uint) public params;

  struct ParamProposal {
    uint appExpiry;
    uint challengeID;
    uint deposit;
    string name;
    address owner;
    uint processBy;
    uint value;
  }

  struct Challenge {
    uint rewardPool;        // (remaining) pool of tokens distributed amongst winning voters
    address challenger;     // owner of Challenge
    bool resolved;          // indication of if challenge is resolved
    uint stake;             // number of tokens at risk for either party during challenge
    uint totalTokens;       // (remaining) amount of tokens used for voting by the winning side
  }

  // maps pollIDs to intended data change if poll passes
  mapping(bytes32 => ParamProposal) public proposalMap;

  // maps challengeIDs to associated challenge data
  mapping(uint => Challenge) public challengeMap;

  // maps challengeIDs and address to token claim data
  mapping(uint => mapping(address => bool)) public tokenClaims;

  // Global Variables
  StandardToken public token;
  PLCRVoting public voting;
  uint public PROCESSBY = 604800; // 7 days

  /**
  @dev constructor
  @param _tokenAddr        address of the token which parameterizes this system
  @param _plcrAddr         address of a PLCR voting contract for the provided token
  @param _minDeposit       minimum deposit for listing to be whitelisted
  @param _pMinDeposit      minimum deposit to propose a reparameterization
  @param _applyStageLen    period over which applicants wait to be whitelisted
  @param _pApplyStageLen   period over which reparmeterization proposals wait to be processed
  @param _dispensationPct  percentage of losing party's deposit distributed to winning party
  @param _pDispensationPct percentage of losing party's deposit distributed to winning party in parameterizer
  @param _commitPeriodLen  length of commit period for voting
  @param _pCommitPeriodLen length of commit period for voting in parameterizer
  @param _revealPeriodLen  length of reveal period for voting
  @param _pRevealPeriodLen length of reveal period for voting in parameterizer
  @param _voteQuorum       type of majority out of 100 necessary for vote success
  @param _pVoteQuorum      type of majority out of 100 necessary for vote success in parameterizer
  */
  function Parameterizer(
    address _tokenAddr,
    address _plcrAddr,
    uint _minDeposit,
    uint _pMinDeposit,
    uint _applyStageLen,
    uint _pApplyStageLen,
    uint _commitPeriodLen,
    uint _pCommitPeriodLen,
    uint _revealPeriodLen,
    uint _pRevealPeriodLen,
    uint _dispensationPct,
    uint _pDispensationPct,
    uint _voteQuorum,
    uint _pVoteQuorum
    ) {
      token = StandardToken(_tokenAddr);
      voting = PLCRVoting(_plcrAddr);

      set("minDeposit", _minDeposit);
      set("pMinDeposit", _pMinDeposit);
      set("applyStageLen", _applyStageLen);
      set("pApplyStageLen", _pApplyStageLen);
      set("commitPeriodLen", _commitPeriodLen);
      set("pCommitPeriodLen", _pCommitPeriodLen);
      set("revealPeriodLen", _revealPeriodLen);
      set("pRevealPeriodLen", _pRevealPeriodLen);
      set("dispensationPct", _dispensationPct);
      set("pDispensationPct", _pDispensationPct);
      set("voteQuorum", _voteQuorum);
      set("pVoteQuorum", _pVoteQuorum);
  }

  // -----------------------
  // TOKEN HOLDER INTERFACE:
  // -----------------------

  /**
  @notice propose a reparamaterization of the key _name's value to _value.
  @param _name the name of the proposed param to be set
  @param _value the proposed value to set the param to be set
  */
  function proposeReparameterization(string _name, uint _value) public returns (bytes32) {
    uint deposit = get("pMinDeposit");
    bytes32 propID = sha3(_name, _value);

    require(!propExists(propID)); // Forbid duplicate proposals
    require(get(_name) != _value); // Forbid NOOP reparameterizations
    require(token.transferFrom(msg.sender, this, deposit)); // escrow tokens (deposit amt)

    // attach name and value to pollID
    proposalMap[propID] = ParamProposal({
      appExpiry: now + get("pApplyStageLen"),
      challengeID: 0,
      deposit: deposit,
      name: _name,
      owner: msg.sender,
      processBy: now + get("pApplyStageLen") + get("pCommitPeriodLen") +
        get("pRevealPeriodLen") + PROCESSBY,
      value: _value
    });

    _ReparameterizationProposal(msg.sender, _name, _value, propID);
    return propID;
  }

  /**
  @notice challenge the provided proposal ID, and put tokens at stake to do so.
  @param _propID the proposal ID to challenge
  */
  function challengeReparameterization(bytes32 _propID) public returns (uint challengeID) {
    ParamProposal memory prop = proposalMap[_propID];
    uint deposit = get("pMinDeposit");

    require(propExists(_propID) && prop.challengeID == 0);

    //take tokens from challenger
    require(token.transferFrom(msg.sender, this, deposit));
    //start poll
    uint pollID = voting.startPoll(
      get("pVoteQuorum"),
      get("pCommitPeriodLen"),
      get("pRevealPeriodLen")
    );

    challengeMap[pollID] = Challenge({
      challenger: msg.sender,
      rewardPool: ((100 - get("pDispensationPct")) * deposit) / 100,
      stake: deposit,
      resolved: false,
      totalTokens: 0
    });

    proposalMap[_propID].challengeID = pollID;       // update listing to store most recent challenge
    return pollID;
  }

  /**
  @notice for the provided proposal ID, set it, resolve its challenge, or delete it depending on whether it can be set, has a challenge which can be resolved, or if its "process by" date has passed
  @param _propID the proposal ID to make a determination and state transition for
  */
  function processProposal(bytes32 _propID) public {
    ParamProposal storage prop = proposalMap[_propID];

    if (canBeSet(_propID)) {
      set(prop.name, prop.value);
    } else if (challengeCanBeResolved(_propID)) {
      resolveChallenge(_propID);
    } else if (now > prop.processBy) {
    } else {
      revert();
    }

    delete proposalMap[_propID];
  }

  /**
  @notice claim the tokens owed for the msg.sender in the provided challenge
  @param _challengeID the challenge ID to claim tokens for
  @param _salt the salt used to vote in the challenge being withdrawn for
  */
  function claimReward(uint _challengeID, uint _salt) public {
    // ensure voter has not already claimed tokens and challenge results have been processed
    require(tokenClaims[_challengeID][msg.sender] == false);
    require(challengeMap[_challengeID].resolved = true);

    uint voterTokens = voting.getNumPassingTokens(msg.sender, _challengeID, _salt);
    uint reward = calculateVoterReward(msg.sender, _challengeID, _salt);

    // subtract voter's information to preserve the participation ratios of other voters
    // compared to the remaining pool of rewards
    challengeMap[_challengeID].totalTokens -= voterTokens;
    challengeMap[_challengeID].rewardPool -= reward;

    require(token.transfer(msg.sender, reward));

    // ensures a voter cannot claim tokens again
    tokenClaims[_challengeID][msg.sender] = true;
  }

  // --------
  // GETTERS:
  // --------

  /**
  @dev Calculate the provided voter's token reward for the given poll
  @param _voter Address of the voter whose reward balance is to be returned
  @param _challengeID pollID of the challenge a reward balance is being queried for
  @param _salt the salt for the voter's commit hash in the given poll
  @return a uint indicating the voter's reward in nano-adToken
  */
  function calculateVoterReward(address _voter, uint _challengeID, uint _salt)
  public constant returns (uint) {
    uint totalTokens = challengeMap[_challengeID].totalTokens;
    uint rewardPool = challengeMap[_challengeID].rewardPool;
    uint voterTokens = voting.getNumPassingTokens(_voter, _challengeID, _salt);
    return (voterTokens * rewardPool) / totalTokens;
  }

  /**
  @notice Determines whether a proposal passed its application stage without a challenge
  @param _propID The proposal ID for which to determine whether its application stage passed without a challenge
  */
  function canBeSet(bytes32 _propID) constant public returns (bool) {
    ParamProposal memory prop = proposalMap[_propID];

    return (propExists(_propID) && now > prop.appExpiry && now < prop.processBy &&
        prop.challengeID == 0);
  }

  /**
  @notice Determines whether a proposal exists for the provided proposal ID
  @param _propID The proposal ID whose existance is to be determined
  */
  function propExists(bytes32 _propID) constant public returns (bool) {
    return proposalMap[_propID].processBy > 0;
  }

  /**
  @notice Determines whether the provided proposal ID has a challenge which can be resolved
  @param _propID The proposal ID whose challenge to inspect
  */
  function challengeCanBeResolved(bytes32 _propID) constant public returns (bool) {
    ParamProposal memory prop = proposalMap[_propID];

    return (prop.challengeID > 0 && now < prop.processBy);
  }

  /**
  @notice Determines the number of tokens to awarded to the winning party in a challenge
  @param _challengeID The challengeID to determine a reward for
  */
  function determineReward(uint _challengeID) public constant returns (uint) {
    require(!challengeMap[_challengeID].resolved && voting.pollEnded(_challengeID));

    if(voting.getTotalNumberOfTokensForWinningOption(_challengeID) == 0) {
      // Edge case, nobody voted, give all tokens to the winner.
      return 2 * challengeMap[_challengeID].stake;
    }

    return (2 * challengeMap[_challengeID].stake) - challengeMap[_challengeID].rewardPool;
  }

  /**
  @notice gets the parameter keyed by the provided name value from the params mapping
  @param _name the key whose value is to be determined
  */
  function get(string _name) public constant returns (uint value) {
    return params[sha3(_name)];
  }

  // ----------------
  // PRIVATE FUNCTIONS:
  // ----------------

  /**
  @dev sets the param keted by the provided name to the provided value
  @param _name the name of the param to be set
  @param _value the value to set the param to be set
  */
  function set(string _name, uint _value) private {
    params[sha3(_name)] = _value;
  }

  /**
  @dev resolves a challenge for the provided _propID. It must be checked in advance whether the _propID has a challenge on it
  @param _propID the proposal ID whose challenge is to be resolved.
  */
  function resolveChallenge(bytes32 _propID) private {
    ParamProposal memory prop = proposalMap[_propID];

    // winner gets back their full staked deposit, and dispensationPct*loser's stake
    uint reward = determineReward(prop.challengeID);

    if (voting.isPassed(prop.challengeID)) { // The challenge failed
      set(prop.name, prop.value);
      require(token.transfer(prop.owner, reward));
    }
    else { // The challenge succeeded
      require(token.transfer(challengeMap[prop.challengeID].challenger, reward));
    }

    // set flag on challenge being processed
    challengeMap[prop.challengeID].resolved = true;

    // store the total tokens used for voting by the winning side for reward purposes
    challengeMap[prop.challengeID].totalTokens =
      voting.getTotalNumberOfTokensForWinningOption(prop.challengeID);
  }
}

pragma solidity^0.4.11;

import "./PLCRVoting.sol";
import "./historical/StandardToken.sol";

contract Parameterizer {

  // ------
  // EVENTS
  // ------

  event _ReparameterizationProposal(address proposer, string name, uint value, bytes32 propID);

  mapping(bytes32 => uint) public params;

  struct ParamProposal {
    uint appExpiry;
    uint challengeID;
    uint deposit;
    string name;
    address owner;
    uint processBy;
    uint value;
  }

  struct Challenge {
    uint rewardPool;        // (remaining) pool of tokens distributed amongst winning voters
    address challenger;     // owner of Challenge
    bool resolved;          // indication of if challenge is resolved
    uint stake;             // number of tokens at risk for either party during challenge
    uint totalTokens;       // (remaining) amount of tokens used for voting by the winning side
  }

  // maps pollIDs to intended data change if poll passes
  mapping(bytes32 => ParamProposal) public proposalMap;

  // maps challengeIDs to associated challenge data
  mapping(uint => Challenge) public challengeMap;

  // maps challengeIDs and address to token claim data
  mapping(uint => mapping(address => bool)) public tokenClaims;

  // Global Variables
  StandardToken public token;
  PLCRVoting public voting;
  uint public PROCESSBY = 604800; // 7 days

  /**
  @dev constructor
  @param _tokenAddr        address of the token which parameterizes this system
  @param _plcrAddr         address of a PLCR voting contract for the provided token
  @param _minDeposit       minimum deposit for listing to be whitelisted
  @param _pMinDeposit      minimum deposit to propose a reparameterization
  @param _applyStageLen    period over which applicants wait to be whitelisted
  @param _pApplyStageLen   period over which reparmeterization proposals wait to be processed
  @param _dispensationPct  percentage of losing party's deposit distributed to winning party
  @param _pDispensationPct percentage of losing party's deposit distributed to winning party in parameterizer
  @param _commitPeriodLen  length of commit period for voting
  @param _pCommitPeriodLen length of commit period for voting in parameterizer
  @param _revealPeriodLen  length of reveal period for voting
  @param _pRevealPeriodLen length of reveal period for voting in parameterizer
  @param _voteQuorum       type of majority out of 100 necessary for vote success
  @param _pVoteQuorum      type of majority out of 100 necessary for vote success in parameterizer
  */
  function Parameterizer(
    address _tokenAddr,
    address _plcrAddr,
    uint _minDeposit,
    uint _pMinDeposit,
    uint _applyStageLen,
    uint _pApplyStageLen,
    uint _commitPeriodLen,
    uint _pCommitPeriodLen,
    uint _revealPeriodLen,
    uint _pRevealPeriodLen,
    uint _dispensationPct,
    uint _pDispensationPct,
    uint _voteQuorum,
    uint _pVoteQuorum
    ) {
      token = StandardToken(_tokenAddr);
      voting = PLCRVoting(_plcrAddr);

      set("minDeposit", _minDeposit);
      set("pMinDeposit", _pMinDeposit);
      set("applyStageLen", _applyStageLen);
      set("pApplyStageLen", _pApplyStageLen);
      set("commitPeriodLen", _commitPeriodLen);
      set("pCommitPeriodLen", _pCommitPeriodLen);
      set("revealPeriodLen", _revealPeriodLen);
      set("pRevealPeriodLen", _pRevealPeriodLen);
      set("dispensationPct", _dispensationPct);
      set("pDispensationPct", _pDispensationPct);
      set("voteQuorum", _voteQuorum);
      set("pVoteQuorum", _pVoteQuorum);
  }

  // -----------------------
  // TOKEN HOLDER INTERFACE:
  // -----------------------

  /**
  @notice propose a reparamaterization of the key _name's value to _value.
  @param _name the name of the proposed param to be set
  @param _value the proposed value to set the param to be set
  */
  function proposeReparameterization(string _name, uint _value) public returns (bytes32) {
    uint deposit = get("pMinDeposit");
    bytes32 propID = sha3(_name, _value);

    require(get(_name) != _value); // Forbid NOOP reparameterizations
    require(token.transferFrom(msg.sender, this, deposit)); // escrow tokens (deposit amt)

    // attach name and value to pollID
    proposalMap[propID] = ParamProposal({
      appExpiry: now + get("pApplyStageLen"),
      challengeID: 0,
      deposit: deposit,
      name: _name,
      owner: msg.sender,
      processBy: now + get("pApplyStageLen") + get("pCommitPeriodLen") +
        get("pRevealPeriodLen") + PROCESSBY,
      value: _value
    });

    _ReparameterizationProposal(msg.sender, _name, _value, propID);
    return propID;
  }

  /**
  @notice challenge the provided proposal ID, and put tokens at stake to do so.
  @param _propID the proposal ID to challenge
  */
  function challengeReparameterization(bytes32 _propID) public returns (uint challengeID) {
    ParamProposal memory prop = proposalMap[_propID];
    uint deposit = get("pMinDeposit");

    require(propExists(_propID) && prop.challengeID == 0);

    //take tokens from challenger
    require(token.transferFrom(msg.sender, this, deposit));
    //start poll
    uint pollID = voting.startPoll(
      get("pVoteQuorum"),
      get("pCommitPeriodLen"),
      get("pRevealPeriodLen")
    );

    challengeMap[pollID] = Challenge({
      challenger: msg.sender,
      rewardPool: ((100 - get("pDispensationPct")) * deposit) / 100,
      stake: deposit,
      resolved: false,
      totalTokens: 0
    });

    proposalMap[_propID].challengeID = pollID;       // update listing to store most recent challenge
    return pollID;
  }

  /**
  @notice for the provided proposal ID, set it, resolve its challenge, or delete it depending on whether it can be set, has a challenge which can be resolved, or if its "process by" date has passed
  @param _propID the proposal ID to make a determination and state transition for
  */
  function processProposal(bytes32 _propID) public {
    ParamProposal storage prop = proposalMap[_propID];

    if (canBeSet(_propID)) {
      set(prop.name, prop.value);
    } else if (challengeCanBeResolved(_propID)) {
      resolveChallenge(_propID);
    } else if (now > prop.processBy) {
    } else {
      revert();
    }

    delete proposalMap[_propID];
  }

  /**
  @notice claim the tokens owed for the msg.sender in the provided challenge
  @param _challengeID the challenge ID to claim tokens for
  @param _salt the salt used to vote in the challenge being withdrawn for
  */
  function claimReward(uint _challengeID, uint _salt) public {
    // ensure voter has not already claimed tokens and challenge results have been processed
    require(tokenClaims[_challengeID][msg.sender] == false);
    require(challengeMap[_challengeID].resolved = true);

    uint voterTokens = voting.getNumPassingTokens(msg.sender, _challengeID, _salt);
    uint reward = calculateVoterReward(msg.sender, _challengeID, _salt);

    // subtract voter's information to preserve the participation ratios of other voters
    // compared to the remaining pool of rewards
    challengeMap[_challengeID].totalTokens -= voterTokens;
    challengeMap[_challengeID].rewardPool -= reward;

    require(token.transfer(msg.sender, reward));

    // ensures a voter cannot claim tokens again
    tokenClaims[_challengeID][msg.sender] = true;
  }

  // --------
  // GETTERS:
  // --------

  /**
  @dev Calculate the provided voter's token reward for the given poll
  @param _voter Address of the voter whose reward balance is to be returned
  @param _challengeID pollID of the challenge a reward balance is being queried for
  @param _salt the salt for the voter's commit hash in the given poll
  @return a uint indicating the voter's reward in nano-adToken
  */
  function calculateVoterReward(address _voter, uint _challengeID, uint _salt)
  public constant returns (uint) {
    uint totalTokens = challengeMap[_challengeID].totalTokens;
    uint rewardPool = challengeMap[_challengeID].rewardPool;
    uint voterTokens = voting.getNumPassingTokens(_voter, _challengeID, _salt);
    return (voterTokens * rewardPool) / totalTokens;
  }

  /**
  @notice Determines whether a proposal passed its application stage without a challenge
  @param _propID The proposal ID for which to determine whether its application stage passed without a challenge
  */
  function canBeSet(bytes32 _propID) constant public returns (bool) {
    ParamProposal memory prop = proposalMap[_propID];

    return (propExists(_propID) && now > prop.appExpiry && now < prop.processBy &&
        prop.challengeID == 0);
  }

  /**
  @notice Determines whether a proposal exists for the provided proposal ID
  @param _propID The proposal ID whose existance is to be determined
  */
  function propExists(bytes32 _propID) constant public returns (bool) {
    return proposalMap[_propID].processBy > 0;
  }

  /**
  @notice Determines whether the provided proposal ID has a challenge which can be resolved
  @param _propID The proposal ID whose challenge to inspect
  */
  function challengeCanBeResolved(bytes32 _propID) constant public returns (bool) {
    ParamProposal memory prop = proposalMap[_propID];

    return (prop.challengeID > 0 && now < prop.processBy);
  }

  /**
  @notice Determines the number of tokens to awarded to the winning party in a challenge
  @param _challengeID The challengeID to determine a reward for
  */
  function determineReward(uint _challengeID) public constant returns (uint) {
    require(!challengeMap[_challengeID].resolved && voting.pollEnded(_challengeID));

    if(voting.getTotalNumberOfTokensForWinningOption(_challengeID) == 0) {
      // Edge case, nobody voted, give all tokens to the winner.
      return 2 * challengeMap[_challengeID].stake;
    }

    return (2 * challengeMap[_challengeID].stake) - challengeMap[_challengeID].rewardPool;
  }

  /**
  @notice gets the parameter keyed by the provided name value from the params mapping
  @param _name the key whose value is to be determined
  */
  function get(string _name) public constant returns (uint value) {
    return params[sha3(_name)];
  }

  // ----------------
  // PRIVATE FUNCTIONS:
  // ----------------

  /**
  @dev sets the param keted by the provided name to the provided value
  @param _name the name of the param to be set
  @param _value the value to set the param to be set
  */
  function set(string _name, uint _value) private {
    params[sha3(_name)] = _value;
  }

  /**
  @dev resolves a challenge for the provided _propID. It must be checked in advance whether the _propID has a challenge on it
  @param _propID the proposal ID whose challenge is to be resolved.
  */
  function resolveChallenge(bytes32 _propID) private {
    ParamProposal memory prop = proposalMap[_propID];

    // winner gets back their full staked deposit, and dispensationPct*loser's stake
    uint reward = determineReward(prop.challengeID);

    if (voting.isPassed(prop.challengeID)) { // The challenge failed
      set(prop.name, prop.value);
      require(token.transfer(prop.owner, reward));
    }
    else { // The challenge succeeded
      require(token.transfer(challengeMap[prop.challengeID].challenger, reward));
    }

    // set flag on challenge being processed
    challengeMap[prop.challengeID].resolved = true;

    // store the total tokens used for voting by the winning side for reward purposes
    challengeMap[prop.challengeID].totalTokens =
      voting.getTotalNumberOfTokensForWinningOption(prop.challengeID);
  }
}


Reverse Registrar tweaks

Reverse Registrar tweaks

pragma solidity >=0.8.4;

import "./ENS.sol";
import "./IReverseRegistrar.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "../root/Controllable.sol";

abstract contract NameResolver {
    function setName(bytes32 node, string memory name) public virtual;
}

bytes32 constant lookup = 0x3031323334353637383961626364656600000000000000000000000000000000;

bytes32 constant ADDR_REVERSE_NODE = 0x91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e2;

// namehash('addr.reverse')

contract ReverseRegistrar is Ownable, Controllable, IReverseRegistrar {
    ENS public immutable ens;
    NameResolver public defaultResolver;

    event ReverseClaimed(address indexed addr, bytes32 indexed node);
    event DefaultResolverChanged(NameResolver indexed resolver);

    /**
     * @dev Constructor
     * @param ensAddr The address of the ENS registry.
     */
    constructor(ENS ensAddr) {
        ens = ensAddr;

        // Assign ownership of the reverse record to our deployer
        ReverseRegistrar oldRegistrar = ReverseRegistrar(
            ensAddr.owner(ADDR_REVERSE_NODE)
        );
        if (address(oldRegistrar) != address(0x0)) {
            oldRegistrar.claim(msg.sender);
        }
    }

    modifier authorised(address addr) {
        require(
            addr == msg.sender ||
                controllers[msg.sender] ||
                ens.isApprovedForAll(addr, msg.sender) ||
                ownsContract(addr),
            "ReverseRegistrar: Caller is not a controller or authorised by address or the address itself"
        );
        _;
    }

    function setDefaultResolver(address resolver) public override onlyOwner {
        require(
            address(resolver) != address(0),
            "ReverseRegistrar: Resolver address must not be 0"
        );
        defaultResolver = NameResolver(resolver);
        emit DefaultResolverChanged(NameResolver(resolver));
    }

    /**
     * @dev Transfers ownership of the reverse ENS record associated with the
     *      calling account.
     * @param owner The address to set as the owner of the reverse record in ENS.
     * @return The ENS node hash of the reverse record.
     */
    function claim(address owner) public override returns (bytes32) {
        return claimForAddr(msg.sender, owner, address(defaultResolver));
    }

    /**
     * @dev Transfers ownership of the reverse ENS record associated with the
     *      calling account.
     * @param addr The reverse record to set
     * @param owner The address to set as the owner of the reverse record in ENS.
     * @param resolver The resolver of the reverse node
     * @return The ENS node hash of the reverse record.
     */
    function claimForAddr(
        address addr,
        address owner,
        address resolver
    ) public override authorised(addr) returns (bytes32) {
        bytes32 labelHash = sha3HexAddress(addr);
        bytes32 reverseNode = keccak256(
            abi.encodePacked(ADDR_REVERSE_NODE, labelHash)
        );
        emit ReverseClaimed(addr, reverseNode);
        ens.setSubnodeRecord(ADDR_REVERSE_NODE, labelHash, owner, resolver, 0);
        return reverseNode;
    }

    /**
     * @dev Transfers ownership of the reverse ENS record associated with the
     *      calling account.
     * @param owner The address to set as the owner of the reverse record in ENS.
     * @param resolver The address of the resolver to set; 0 to leave unchanged.
     * @return The ENS node hash of the reverse record.
     */
    function claimWithResolver(address owner, address resolver)
        public
        override
        returns (bytes32)
    {
        return claimForAddr(msg.sender, owner, resolver);
    }

    /**
     * @dev Sets the `name()` record for the reverse ENS record associated with
     * the calling account. First updates the resolver to the default reverse
     * resolver if necessary.
     * @param name The name to set for this address.
     * @return The ENS node hash of the reverse record.
     */
    function setName(string memory name) public override returns (bytes32) {
        return
            setNameForAddr(
                msg.sender,
                msg.sender,
                address(defaultResolver),
                name
            );
    }

    /**
     * @dev Sets the `name()` record for the reverse ENS record associated with
     * the account provided. Updates the resolver to a designated resolver
     * Only callable by controllers and authorised users
     * @param addr The reverse record to set
     * @param owner The owner of the reverse node
     * @param resolver The resolver of the reverse node
     * @param name The name to set for this address.
     * @return The ENS node hash of the reverse record.
     */
    function setNameForAddr(
        address addr,
        address owner,
        address resolver,
        string memory name
    ) public override returns (bytes32) {
        bytes32 node = claimForAddr(addr, owner, resolver);
        NameResolver(resolver).setName(node, name);
        return node;
    }

    /**
     * @dev Returns the node hash for a given account's reverse records.
     * @param addr The address to hash
     * @return The ENS node hash.
     */
    function node(address addr) public pure override returns (bytes32) {
        return
            keccak256(
                abi.encodePacked(ADDR_REVERSE_NODE, sha3HexAddress(addr))
            );
    }

    /**
     * @dev An optimised function to compute the sha3 of the lower-case
     *      hexadecimal representation of an Ethereum address.
     * @param addr The address to hash
     * @return ret The SHA3 hash of the lower-case hexadecimal encoding of the
     *         input address.
     */
    function sha3HexAddress(address addr) private pure returns (bytes32 ret) {
        assembly {
            for {
                let i := 40
            } gt(i, 0) {

            } {
                i := sub(i, 1)
                mstore8(i, byte(and(addr, 0xf), lookup))
                addr := div(addr, 0x10)
                i := sub(i, 1)
                mstore8(i, byte(and(addr, 0xf), lookup))
                addr := div(addr, 0x10)
            }

            ret := keccak256(0, 40)
        }
    }

    function ownsContract(address addr) internal view returns (bool) {
        try Ownable(addr).owner() returns (address owner) {
            return owner == msg.sender;
        } catch {
            return false;
        }
    }
}

pragma solidity >=0.8.4;

import "./ENS.sol";
import "./IReverseRegistrar.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "../root/Controllable.sol";

abstract contract NameResolver {
    function setName(bytes32 node, string memory name) public virtual;
}

bytes32 constant lookup = 0x3031323334353637383961626364656600000000000000000000000000000000;

bytes32 constant ADDR_REVERSE_NODE = 0x91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e2;

// namehash('addr.reverse')

contract ReverseRegistrar is Ownable, Controllable, IReverseRegistrar {
    ENS public immutable ens;
    NameResolver public defaultResolver;

    event ReverseClaimed(address indexed addr, bytes32 indexed node);

    /**
     * @dev Constructor
     * @param ensAddr The address of the ENS registry.
     */
    constructor(ENS ensAddr) {
        ens = ensAddr;

        // Assign ownership of the reverse record to our deployer
        ReverseRegistrar oldRegistrar = ReverseRegistrar(
            ensAddr.owner(ADDR_REVERSE_NODE)
        );
        if (address(oldRegistrar) != address(0x0)) {
            oldRegistrar.claim(msg.sender);
        }
    }

    modifier authorised(address addr) {
        require(
            addr == msg.sender ||
                controllers[msg.sender] ||
                ens.isApprovedForAll(addr, msg.sender) ||
                ownsContract(addr),
            "ReverseRegistrar: Caller is not a controller or authorised by address or the address itself"
        );
        _;
    }

    function setDefaultResolver(address resolver) public override onlyOwner {
        require(
            address(resolver) != address(0),
            "ReverseRegistrar: Resolver address must not be 0"
        );
        defaultResolver = NameResolver(resolver);
    }

    /**
     * @dev Transfers ownership of the reverse ENS record associated with the
     *      calling account.
     * @param owner The address to set as the owner of the reverse record in ENS.
     * @return The ENS node hash of the reverse record.
     */
    function claim(address owner) public override returns (bytes32) {
        return claimForAddr(msg.sender, owner, address(defaultResolver));
    }

    /**
     * @dev Transfers ownership of the reverse ENS record associated with the
     *      calling account.
     * @param addr The reverse record to set
     * @param owner The address to set as the owner of the reverse record in ENS.
     * @return The ENS node hash of the reverse record.
     */
    function claimForAddr(
        address addr,
        address owner,
        address resolver
    ) public override authorised(addr) returns (bytes32) {
        bytes32 labelHash = sha3HexAddress(addr);
        bytes32 reverseNode = keccak256(
            abi.encodePacked(ADDR_REVERSE_NODE, labelHash)
        );
        emit ReverseClaimed(addr, reverseNode);
        ens.setSubnodeRecord(ADDR_REVERSE_NODE, labelHash, owner, resolver, 0);
        return reverseNode;
    }

    /**
     * @dev Transfers ownership of the reverse ENS record associated with the
     *      calling account.
     * @param owner The address to set as the owner of the reverse record in ENS.
     * @param resolver The address of the resolver to set; 0 to leave unchanged.
     * @return The ENS node hash of the reverse record.
     */
    function claimWithResolver(address owner, address resolver)
        public
        override
        returns (bytes32)
    {
        return claimForAddr(msg.sender, owner, resolver);
    }

    /**
     * @dev Sets the `name()` record for the reverse ENS record associated with
     * the calling account. First updates the resolver to the default reverse
     * resolver if necessary.
     * @param name The name to set for this address.
     * @return The ENS node hash of the reverse record.
     */
    function setName(string memory name) public override returns (bytes32) {
        return
            setNameForAddr(
                msg.sender,
                msg.sender,
                address(defaultResolver),
                name
            );
    }

    /**
     * @dev Sets the `name()` record for the reverse ENS record associated with
     * the account provided. First updates the resolver to the default reverse
     * resolver if necessary.
     * Only callable by controllers and authorised users
     * @param addr The reverse record to set
     * @param owner The owner of the reverse node
     * @param name The name to set for this address.
     * @return The ENS node hash of the reverse record.
     */
    function setNameForAddr(
        address addr,
        address owner,
        address resolver,
        string memory name
    ) public override returns (bytes32) {
        bytes32 node = claimForAddr(addr, owner, resolver);
        NameResolver(resolver).setName(node, name);
        return node;
    }

    /**
     * @dev Returns the node hash for a given account's reverse records.
     * @param addr The address to hash
     * @return The ENS node hash.
     */
    function node(address addr) public pure override returns (bytes32) {
        return
            keccak256(
                abi.encodePacked(ADDR_REVERSE_NODE, sha3HexAddress(addr))
            );
    }

    /**
     * @dev An optimised function to compute the sha3 of the lower-case
     *      hexadecimal representation of an Ethereum address.
     * @param addr The address to hash
     * @return ret The SHA3 hash of the lower-case hexadecimal encoding of the
     *         input address.
     */
    function sha3HexAddress(address addr) private pure returns (bytes32 ret) {
        assembly {
            for {
                let i := 40
            } gt(i, 0) {

            } {
                i := sub(i, 1)
                mstore8(i, byte(and(addr, 0xf), lookup))
                addr := div(addr, 0x10)
                i := sub(i, 1)
                mstore8(i, byte(and(addr, 0xf), lookup))
                addr := div(addr, 0x10)
            }

            ret := keccak256(0, 40)
        }
    }

    function ownsContract(address addr) internal view returns (bool) {
        try Ownable(addr).owner() returns (address owner) {
            return owner == msg.sender;
        } catch {
            return false;
        }
    }
}