Fix typo in comment (#3765)

Fix typo in comment (#3765)

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (governance/TimelockController.sol)

pragma solidity ^0.8.0;

import "../access/AccessControl.sol";
import "../token/ERC721/IERC721Receiver.sol";
import "../token/ERC1155/IERC1155Receiver.sol";
import "../utils/Address.sol";

/**
 * @dev Contract module which acts as a timelocked controller. When set as the
 * owner of an `Ownable` smart contract, it enforces a timelock on all
 * `onlyOwner` maintenance operations. This gives time for users of the
 * controlled contract to exit before a potentially dangerous maintenance
 * operation is applied.
 *
 * By default, this contract is self administered, meaning administration tasks
 * have to go through the timelock process. The proposer (resp executor) role
 * is in charge of proposing (resp executing) operations. A common use case is
 * to position this {TimelockController} as the owner of a smart contract, with
 * a multisig or a DAO as the sole proposer.
 *
 * _Available since v3.3._
 */
contract TimelockController is AccessControl, IERC721Receiver, IERC1155Receiver {
    bytes32 public constant TIMELOCK_ADMIN_ROLE = keccak256("TIMELOCK_ADMIN_ROLE");
    bytes32 public constant PROPOSER_ROLE = keccak256("PROPOSER_ROLE");
    bytes32 public constant EXECUTOR_ROLE = keccak256("EXECUTOR_ROLE");
    bytes32 public constant CANCELLER_ROLE = keccak256("CANCELLER_ROLE");
    uint256 internal constant _DONE_TIMESTAMP = uint256(1);

    mapping(bytes32 => uint256) private _timestamps;
    uint256 private _minDelay;

    /**
     * @dev Emitted when a call is scheduled as part of operation `id`.
     */
    event CallScheduled(
        bytes32 indexed id,
        uint256 indexed index,
        address target,
        uint256 value,
        bytes data,
        bytes32 predecessor,
        uint256 delay
    );

    /**
     * @dev Emitted when a call is performed as part of operation `id`.
     */
    event CallExecuted(bytes32 indexed id, uint256 indexed index, address target, uint256 value, bytes data);

    /**
     * @dev Emitted when operation `id` is cancelled.
     */
    event Cancelled(bytes32 indexed id);

    /**
     * @dev Emitted when the minimum delay for future operations is modified.
     */
    event MinDelayChange(uint256 oldDuration, uint256 newDuration);

    /**
     * @dev Initializes the contract with the following parameters:
     *
     * - `minDelay`: initial minimum delay for operations
     * - `proposers`: accounts to be granted proposer and canceller roles
     * - `executors`: accounts to be granted executor role
     * - `admin`: optional account to be granted admin role; disable with zero address
     *
     * IMPORTANT: The optional admin can aid with initial configuration of roles after deployment
     * without being subject to delay, but this role should be subsequently renounced in favor of
     * administration through timelocked proposals. Previous versions of this contract would assign
     * this admin to the deployer automatically and should be renounced as well.
     */
    constructor(
        uint256 minDelay,
        address[] memory proposers,
        address[] memory executors,
        address admin
    ) {
        _setRoleAdmin(TIMELOCK_ADMIN_ROLE, TIMELOCK_ADMIN_ROLE);
        _setRoleAdmin(PROPOSER_ROLE, TIMELOCK_ADMIN_ROLE);
        _setRoleAdmin(EXECUTOR_ROLE, TIMELOCK_ADMIN_ROLE);
        _setRoleAdmin(CANCELLER_ROLE, TIMELOCK_ADMIN_ROLE);

        // self administration
        _setupRole(TIMELOCK_ADMIN_ROLE, address(this));

        // optional admin
        if (admin != address(0)) {
            _setupRole(TIMELOCK_ADMIN_ROLE, admin);
        }

        // register proposers and cancellers
        for (uint256 i = 0; i < proposers.length; ++i) {
            _setupRole(PROPOSER_ROLE, proposers[i]);
            _setupRole(CANCELLER_ROLE, proposers[i]);
        }

        // register executors
        for (uint256 i = 0; i < executors.length; ++i) {
            _setupRole(EXECUTOR_ROLE, executors[i]);
        }

        _minDelay = minDelay;
        emit MinDelayChange(0, minDelay);
    }

    /**
     * @dev Modifier to make a function callable only by a certain role. In
     * addition to checking the sender's role, `address(0)` 's role is also
     * considered. Granting a role to `address(0)` is equivalent to enabling
     * this role for everyone.
     */
    modifier onlyRoleOrOpenRole(bytes32 role) {
        if (!hasRole(role, address(0))) {
            _checkRole(role, _msgSender());
        }
        _;
    }

    /**
     * @dev Contract might receive/hold ETH as part of the maintenance process.
     */
    receive() external payable {}

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, AccessControl) returns (bool) {
        return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId);
    }

    /**
     * @dev Returns whether an id correspond to a registered operation. This
     * includes both Pending, Ready and Done operations.
     */
    function isOperation(bytes32 id) public view virtual returns (bool registered) {
        return getTimestamp(id) > 0;
    }

    /**
     * @dev Returns whether an operation is pending or not.
     */
    function isOperationPending(bytes32 id) public view virtual returns (bool pending) {
        return getTimestamp(id) > _DONE_TIMESTAMP;
    }

    /**
     * @dev Returns whether an operation is ready or not.
     */
    function isOperationReady(bytes32 id) public view virtual returns (bool ready) {
        uint256 timestamp = getTimestamp(id);
        return timestamp > _DONE_TIMESTAMP && timestamp <= block.timestamp;
    }

    /**
     * @dev Returns whether an operation is done or not.
     */
    function isOperationDone(bytes32 id) public view virtual returns (bool done) {
        return getTimestamp(id) == _DONE_TIMESTAMP;
    }

    /**
     * @dev Returns the timestamp at which an operation becomes ready (0 for
     * unset operations, 1 for done operations).
     */
    function getTimestamp(bytes32 id) public view virtual returns (uint256 timestamp) {
        return _timestamps[id];
    }

    /**
     * @dev Returns the minimum delay for an operation to become valid.
     *
     * This value can be changed by executing an operation that calls `updateDelay`.
     */
    function getMinDelay() public view virtual returns (uint256 duration) {
        return _minDelay;
    }

    /**
     * @dev Returns the identifier of an operation containing a single
     * transaction.
     */
    function hashOperation(
        address target,
        uint256 value,
        bytes calldata data,
        bytes32 predecessor,
        bytes32 salt
    ) public pure virtual returns (bytes32 hash) {
        return keccak256(abi.encode(target, value, data, predecessor, salt));
    }

    /**
     * @dev Returns the identifier of an operation containing a batch of
     * transactions.
     */
    function hashOperationBatch(
        address[] calldata targets,
        uint256[] calldata values,
        bytes[] calldata payloads,
        bytes32 predecessor,
        bytes32 salt
    ) public pure virtual returns (bytes32 hash) {
        return keccak256(abi.encode(targets, values, payloads, predecessor, salt));
    }

    /**
     * @dev Schedule an operation containing a single transaction.
     *
     * Emits a {CallScheduled} event.
     *
     * Requirements:
     *
     * - the caller must have the 'proposer' role.
     */
    function schedule(
        address target,
        uint256 value,
        bytes calldata data,
        bytes32 predecessor,
        bytes32 salt,
        uint256 delay
    ) public virtual onlyRole(PROPOSER_ROLE) {
        bytes32 id = hashOperation(target, value, data, predecessor, salt);
        _schedule(id, delay);
        emit CallScheduled(id, 0, target, value, data, predecessor, delay);
    }

    /**
     * @dev Schedule an operation containing a batch of transactions.
     *
     * Emits one {CallScheduled} event per transaction in the batch.
     *
     * Requirements:
     *
     * - the caller must have the 'proposer' role.
     */
    function scheduleBatch(
        address[] calldata targets,
        uint256[] calldata values,
        bytes[] calldata payloads,
        bytes32 predecessor,
        bytes32 salt,
        uint256 delay
    ) public virtual onlyRole(PROPOSER_ROLE) {
        require(targets.length == values.length, "TimelockController: length mismatch");
        require(targets.length == payloads.length, "TimelockController: length mismatch");

        bytes32 id = hashOperationBatch(targets, values, payloads, predecessor, salt);
        _schedule(id, delay);
        for (uint256 i = 0; i < targets.length; ++i) {
            emit CallScheduled(id, i, targets[i], values[i], payloads[i], predecessor, delay);
        }
    }

    /**
     * @dev Schedule an operation that is to becomes valid after a given delay.
     */
    function _schedule(bytes32 id, uint256 delay) private {
        require(!isOperation(id), "TimelockController: operation already scheduled");
        require(delay >= getMinDelay(), "TimelockController: insufficient delay");
        _timestamps[id] = block.timestamp + delay;
    }

    /**
     * @dev Cancel an operation.
     *
     * Requirements:
     *
     * - the caller must have the 'canceller' role.
     */
    function cancel(bytes32 id) public virtual onlyRole(CANCELLER_ROLE) {
        require(isOperationPending(id), "TimelockController: operation cannot be cancelled");
        delete _timestamps[id];

        emit Cancelled(id);
    }

    /**
     * @dev Execute an (ready) operation containing a single transaction.
     *
     * Emits a {CallExecuted} event.
     *
     * Requirements:
     *
     * - the caller must have the 'executor' role.
     */
    // This function can reenter, but it doesn't pose a risk because _afterCall checks that the proposal is pending,
    // thus any modifications to the operation during reentrancy should be caught.
    // slither-disable-next-line reentrancy-eth
    function execute(
        address target,
        uint256 value,
        bytes calldata payload,
        bytes32 predecessor,
        bytes32 salt
    ) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) {
        bytes32 id = hashOperation(target, value, payload, predecessor, salt);

        _beforeCall(id, predecessor);
        _execute(target, value, payload);
        emit CallExecuted(id, 0, target, value, payload);
        _afterCall(id);
    }

    /**
     * @dev Execute an (ready) operation containing a batch of transactions.
     *
     * Emits one {CallExecuted} event per transaction in the batch.
     *
     * Requirements:
     *
     * - the caller must have the 'executor' role.
     */
    function executeBatch(
        address[] calldata targets,
        uint256[] calldata values,
        bytes[] calldata payloads,
        bytes32 predecessor,
        bytes32 salt
    ) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) {
        require(targets.length == values.length, "TimelockController: length mismatch");
        require(targets.length == payloads.length, "TimelockController: length mismatch");

        bytes32 id = hashOperationBatch(targets, values, payloads, predecessor, salt);

        _beforeCall(id, predecessor);
        for (uint256 i = 0; i < targets.length; ++i) {
            address target = targets[i];
            uint256 value = values[i];
            bytes calldata payload = payloads[i];
            _execute(target, value, payload);
            emit CallExecuted(id, i, target, value, payload);
        }
        _afterCall(id);
    }

    /**
     * @dev Execute an operation's call.
     */
    function _execute(
        address target,
        uint256 value,
        bytes calldata data
    ) internal virtual {
        (bool success, ) = target.call{value: value}(data);
        require(success, "TimelockController: underlying transaction reverted");
    }

    /**
     * @dev Checks before execution of an operation's calls.
     */
    function _beforeCall(bytes32 id, bytes32 predecessor) private view {
        require(isOperationReady(id), "TimelockController: operation is not ready");
        require(predecessor == bytes32(0) || isOperationDone(predecessor), "TimelockController: missing dependency");
    }

    /**
     * @dev Checks after execution of an operation's calls.
     */
    function _afterCall(bytes32 id) private {
        require(isOperationReady(id), "TimelockController: operation is not ready");
        _timestamps[id] = _DONE_TIMESTAMP;
    }

    /**
     * @dev Changes the minimum timelock duration for future operations.
     *
     * Emits a {MinDelayChange} event.
     *
     * Requirements:
     *
     * - the caller must be the timelock itself. This can only be achieved by scheduling and later executing
     * an operation where the timelock is the target and the data is the ABI-encoded call to this function.
     */
    function updateDelay(uint256 newDelay) external virtual {
        require(msg.sender == address(this), "TimelockController: caller must be timelock");
        emit MinDelayChange(_minDelay, newDelay);
        _minDelay = newDelay;
    }

    /**
     * @dev See {IERC721Receiver-onERC721Received}.
     */
    function onERC721Received(
        address,
        address,
        uint256,
        bytes memory
    ) public virtual override returns (bytes4) {
        return this.onERC721Received.selector;
    }

    /**
     * @dev See {IERC1155Receiver-onERC1155Received}.
     */
    function onERC1155Received(
        address,
        address,
        uint256,
        uint256,
        bytes memory
    ) public virtual override returns (bytes4) {
        return this.onERC1155Received.selector;
    }

    /**
     * @dev See {IERC1155Receiver-onERC1155BatchReceived}.
     */
    function onERC1155BatchReceived(
        address,
        address,
        uint256[] memory,
        uint256[] memory,
        bytes memory
    ) public virtual override returns (bytes4) {
        return this.onERC1155BatchReceived.selector;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (governance/TimelockController.sol)

pragma solidity ^0.8.0;

import "../access/AccessControl.sol";
import "../token/ERC721/IERC721Receiver.sol";
import "../token/ERC1155/IERC1155Receiver.sol";
import "../utils/Address.sol";

/**
 * @dev Contract module which acts as a timelocked controller. When set as the
 * owner of an `Ownable` smart contract, it enforces a timelock on all
 * `onlyOwner` maintenance operations. This gives time for users of the
 * controlled contract to exit before a potentially dangerous maintenance
 * operation is applied.
 *
 * By default, this contract is self administered, meaning administration tasks
 * have to go through the timelock process. The proposer (resp executor) role
 * is in charge of proposing (resp executing) operations. A common use case is
 * to position this {TimelockController} as the owner of a smart contract, with
 * a multisig or a DAO as the sole proposer.
 *
 * _Available since v3.3._
 */
contract TimelockController is AccessControl, IERC721Receiver, IERC1155Receiver {
    bytes32 public constant TIMELOCK_ADMIN_ROLE = keccak256("TIMELOCK_ADMIN_ROLE");
    bytes32 public constant PROPOSER_ROLE = keccak256("PROPOSER_ROLE");
    bytes32 public constant EXECUTOR_ROLE = keccak256("EXECUTOR_ROLE");
    bytes32 public constant CANCELLER_ROLE = keccak256("CANCELLER_ROLE");
    uint256 internal constant _DONE_TIMESTAMP = uint256(1);

    mapping(bytes32 => uint256) private _timestamps;
    uint256 private _minDelay;

    /**
     * @dev Emitted when a call is scheduled as part of operation `id`.
     */
    event CallScheduled(
        bytes32 indexed id,
        uint256 indexed index,
        address target,
        uint256 value,
        bytes data,
        bytes32 predecessor,
        uint256 delay
    );

    /**
     * @dev Emitted when a call is performed as part of operation `id`.
     */
    event CallExecuted(bytes32 indexed id, uint256 indexed index, address target, uint256 value, bytes data);

    /**
     * @dev Emitted when operation `id` is cancelled.
     */
    event Cancelled(bytes32 indexed id);

    /**
     * @dev Emitted when the minimum delay for future operations is modified.
     */
    event MinDelayChange(uint256 oldDuration, uint256 newDuration);

    /**
     * @dev Initializes the contract with the following parameters:
     *
     * - `minDelay`: initial minimum delay for operations
     * - `proposers`: accounts to be granted proposer and canceller roles
     * - `executors`: accounts to be granted executor role
     * - `admin`: optional account to be granted admin role; disable with zero address
     *
     * IMPORTANT: The optional admin can aid with initial configuration of roles after deployment
     * without being subject to delay, but this role should be subsequently renounced in favor of
     * administration through timelocked proposals. Previous versions of this contract would assign
     * this admin to the deployer automatically and should be renounced as well.
     */
    constructor(
        uint256 minDelay,
        address[] memory proposers,
        address[] memory executors,
        address admin
    ) {
        _setRoleAdmin(TIMELOCK_ADMIN_ROLE, TIMELOCK_ADMIN_ROLE);
        _setRoleAdmin(PROPOSER_ROLE, TIMELOCK_ADMIN_ROLE);
        _setRoleAdmin(EXECUTOR_ROLE, TIMELOCK_ADMIN_ROLE);
        _setRoleAdmin(CANCELLER_ROLE, TIMELOCK_ADMIN_ROLE);

        // self administration
        _setupRole(TIMELOCK_ADMIN_ROLE, address(this));

        // optional admin
        if (admin != address(0)) {
            _setupRole(TIMELOCK_ADMIN_ROLE, admin);
        }

        // register proposers and cancellers
        for (uint256 i = 0; i < proposers.length; ++i) {
            _setupRole(PROPOSER_ROLE, proposers[i]);
            _setupRole(CANCELLER_ROLE, proposers[i]);
        }

        // register executors
        for (uint256 i = 0; i < executors.length; ++i) {
            _setupRole(EXECUTOR_ROLE, executors[i]);
        }

        _minDelay = minDelay;
        emit MinDelayChange(0, minDelay);
    }

    /**
     * @dev Modifier to make a function callable only by a certain role. In
     * addition to checking the sender's role, `address(0)` 's role is also
     * considered. Granting a role to `address(0)` is equivalent to enabling
     * this role for everyone.
     */
    modifier onlyRoleOrOpenRole(bytes32 role) {
        if (!hasRole(role, address(0))) {
            _checkRole(role, _msgSender());
        }
        _;
    }

    /**
     * @dev Contract might receive/hold ETH as part of the maintenance process.
     */
    receive() external payable {}

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, AccessControl) returns (bool) {
        return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId);
    }

    /**
     * @dev Returns whether an id correspond to a registered operation. This
     * includes both Pending, Ready and Done operations.
     */
    function isOperation(bytes32 id) public view virtual returns (bool registered) {
        return getTimestamp(id) > 0;
    }

    /**
     * @dev Returns whether an operation is pending or not.
     */
    function isOperationPending(bytes32 id) public view virtual returns (bool pending) {
        return getTimestamp(id) > _DONE_TIMESTAMP;
    }

    /**
     * @dev Returns whether an operation is ready or not.
     */
    function isOperationReady(bytes32 id) public view virtual returns (bool ready) {
        uint256 timestamp = getTimestamp(id);
        return timestamp > _DONE_TIMESTAMP && timestamp <= block.timestamp;
    }

    /**
     * @dev Returns whether an operation is done or not.
     */
    function isOperationDone(bytes32 id) public view virtual returns (bool done) {
        return getTimestamp(id) == _DONE_TIMESTAMP;
    }

    /**
     * @dev Returns the timestamp at with an operation becomes ready (0 for
     * unset operations, 1 for done operations).
     */
    function getTimestamp(bytes32 id) public view virtual returns (uint256 timestamp) {
        return _timestamps[id];
    }

    /**
     * @dev Returns the minimum delay for an operation to become valid.
     *
     * This value can be changed by executing an operation that calls `updateDelay`.
     */
    function getMinDelay() public view virtual returns (uint256 duration) {
        return _minDelay;
    }

    /**
     * @dev Returns the identifier of an operation containing a single
     * transaction.
     */
    function hashOperation(
        address target,
        uint256 value,
        bytes calldata data,
        bytes32 predecessor,
        bytes32 salt
    ) public pure virtual returns (bytes32 hash) {
        return keccak256(abi.encode(target, value, data, predecessor, salt));
    }

    /**
     * @dev Returns the identifier of an operation containing a batch of
     * transactions.
     */
    function hashOperationBatch(
        address[] calldata targets,
        uint256[] calldata values,
        bytes[] calldata payloads,
        bytes32 predecessor,
        bytes32 salt
    ) public pure virtual returns (bytes32 hash) {
        return keccak256(abi.encode(targets, values, payloads, predecessor, salt));
    }

    /**
     * @dev Schedule an operation containing a single transaction.
     *
     * Emits a {CallScheduled} event.
     *
     * Requirements:
     *
     * - the caller must have the 'proposer' role.
     */
    function schedule(
        address target,
        uint256 value,
        bytes calldata data,
        bytes32 predecessor,
        bytes32 salt,
        uint256 delay
    ) public virtual onlyRole(PROPOSER_ROLE) {
        bytes32 id = hashOperation(target, value, data, predecessor, salt);
        _schedule(id, delay);
        emit CallScheduled(id, 0, target, value, data, predecessor, delay);
    }

    /**
     * @dev Schedule an operation containing a batch of transactions.
     *
     * Emits one {CallScheduled} event per transaction in the batch.
     *
     * Requirements:
     *
     * - the caller must have the 'proposer' role.
     */
    function scheduleBatch(
        address[] calldata targets,
        uint256[] calldata values,
        bytes[] calldata payloads,
        bytes32 predecessor,
        bytes32 salt,
        uint256 delay
    ) public virtual onlyRole(PROPOSER_ROLE) {
        require(targets.length == values.length, "TimelockController: length mismatch");
        require(targets.length == payloads.length, "TimelockController: length mismatch");

        bytes32 id = hashOperationBatch(targets, values, payloads, predecessor, salt);
        _schedule(id, delay);
        for (uint256 i = 0; i < targets.length; ++i) {
            emit CallScheduled(id, i, targets[i], values[i], payloads[i], predecessor, delay);
        }
    }

    /**
     * @dev Schedule an operation that is to becomes valid after a given delay.
     */
    function _schedule(bytes32 id, uint256 delay) private {
        require(!isOperation(id), "TimelockController: operation already scheduled");
        require(delay >= getMinDelay(), "TimelockController: insufficient delay");
        _timestamps[id] = block.timestamp + delay;
    }

    /**
     * @dev Cancel an operation.
     *
     * Requirements:
     *
     * - the caller must have the 'canceller' role.
     */
    function cancel(bytes32 id) public virtual onlyRole(CANCELLER_ROLE) {
        require(isOperationPending(id), "TimelockController: operation cannot be cancelled");
        delete _timestamps[id];

        emit Cancelled(id);
    }

    /**
     * @dev Execute an (ready) operation containing a single transaction.
     *
     * Emits a {CallExecuted} event.
     *
     * Requirements:
     *
     * - the caller must have the 'executor' role.
     */
    // This function can reenter, but it doesn't pose a risk because _afterCall checks that the proposal is pending,
    // thus any modifications to the operation during reentrancy should be caught.
    // slither-disable-next-line reentrancy-eth
    function execute(
        address target,
        uint256 value,
        bytes calldata payload,
        bytes32 predecessor,
        bytes32 salt
    ) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) {
        bytes32 id = hashOperation(target, value, payload, predecessor, salt);

        _beforeCall(id, predecessor);
        _execute(target, value, payload);
        emit CallExecuted(id, 0, target, value, payload);
        _afterCall(id);
    }

    /**
     * @dev Execute an (ready) operation containing a batch of transactions.
     *
     * Emits one {CallExecuted} event per transaction in the batch.
     *
     * Requirements:
     *
     * - the caller must have the 'executor' role.
     */
    function executeBatch(
        address[] calldata targets,
        uint256[] calldata values,
        bytes[] calldata payloads,
        bytes32 predecessor,
        bytes32 salt
    ) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) {
        require(targets.length == values.length, "TimelockController: length mismatch");
        require(targets.length == payloads.length, "TimelockController: length mismatch");

        bytes32 id = hashOperationBatch(targets, values, payloads, predecessor, salt);

        _beforeCall(id, predecessor);
        for (uint256 i = 0; i < targets.length; ++i) {
            address target = targets[i];
            uint256 value = values[i];
            bytes calldata payload = payloads[i];
            _execute(target, value, payload);
            emit CallExecuted(id, i, target, value, payload);
        }
        _afterCall(id);
    }

    /**
     * @dev Execute an operation's call.
     */
    function _execute(
        address target,
        uint256 value,
        bytes calldata data
    ) internal virtual {
        (bool success, ) = target.call{value: value}(data);
        require(success, "TimelockController: underlying transaction reverted");
    }

    /**
     * @dev Checks before execution of an operation's calls.
     */
    function _beforeCall(bytes32 id, bytes32 predecessor) private view {
        require(isOperationReady(id), "TimelockController: operation is not ready");
        require(predecessor == bytes32(0) || isOperationDone(predecessor), "TimelockController: missing dependency");
    }

    /**
     * @dev Checks after execution of an operation's calls.
     */
    function _afterCall(bytes32 id) private {
        require(isOperationReady(id), "TimelockController: operation is not ready");
        _timestamps[id] = _DONE_TIMESTAMP;
    }

    /**
     * @dev Changes the minimum timelock duration for future operations.
     *
     * Emits a {MinDelayChange} event.
     *
     * Requirements:
     *
     * - the caller must be the timelock itself. This can only be achieved by scheduling and later executing
     * an operation where the timelock is the target and the data is the ABI-encoded call to this function.
     */
    function updateDelay(uint256 newDelay) external virtual {
        require(msg.sender == address(this), "TimelockController: caller must be timelock");
        emit MinDelayChange(_minDelay, newDelay);
        _minDelay = newDelay;
    }

    /**
     * @dev See {IERC721Receiver-onERC721Received}.
     */
    function onERC721Received(
        address,
        address,
        uint256,
        bytes memory
    ) public virtual override returns (bytes4) {
        return this.onERC721Received.selector;
    }

    /**
     * @dev See {IERC1155Receiver-onERC1155Received}.
     */
    function onERC1155Received(
        address,
        address,
        uint256,
        uint256,
        bytes memory
    ) public virtual override returns (bytes4) {
        return this.onERC1155Received.selector;
    }

    /**
     * @dev See {IERC1155Receiver-onERC1155BatchReceived}.
     */
    function onERC1155BatchReceived(
        address,
        address,
        uint256[] memory,
        uint256[] memory,
        bytes memory
    ) public virtual override returns (bytes4) {
        return this.onERC1155BatchReceived.selector;
    }
}


Close #210

Close #210

Added fake move to validate timeout

/**
 * Chess contract
 * Stores any amount of games with two players and current state.
 * State encoding:
 *    positive numbers for white, negative numbers for black
 *    for details, see
 *    https://github.com/ise-ethereum/on-chain-chess/wiki/Chess-board-representation
 */

import "TurnBasedGame.sol";
import "ChessLogic.sol";
import "Auth.sol";
import "ELO.sol";

contract Chess is TurnBasedGame, Auth {
    using ChessLogic for ChessLogic.State;
    mapping (bytes32 => ChessLogic.State) gameStates;

    using ELO for ELO.Scores;
    ELO.Scores eloScores;

    event GameInitialized(bytes32 indexed gameId, address indexed player1, string player1Alias, address playerWhite, uint turnTime, uint pot);
    event GameJoined(bytes32 indexed gameId, address indexed player1, string player1Alias, address indexed player2, string player2Alias, address playerWhite, uint pot);
    event GameStateChanged(bytes32 indexed gameId, int8[128] state);
    event Move(bytes32 indexed gameId, address indexed player, uint256 fromIndex, uint256 toIndex);
    event EloScoreUpdate(address indexed player, uint score);

    function Chess(bool enableDebugging) TurnBasedGame(enableDebugging) {
    }

    /**
     * Initialize a new game
     * string player1Alias: Alias of the player creating the game
     * bool playAsWhite: Pass true or false depending on if the creator will play as white
     */
    function initGame(string player1Alias, bool playAsWhite, uint turnTime) public returns (bytes32) {
        bytes32 gameId = super.initGame(player1Alias, playAsWhite, turnTime);

        // Setup game state
        int8 nextPlayerColor = int8(1);
        gameStates[gameId].setupState(nextPlayerColor);
        if (playAsWhite) {
            // Player 1 will play as white
            gameStates[gameId].playerWhite = msg.sender;

            // Game starts with White, so here player 1
            games[gameId].nextPlayer = games[gameId].player1;
        }

        // Sent notification events
        GameInitialized(gameId, games[gameId].player1, player1Alias, gameStates[gameId].playerWhite, games[gameId].turnTime, games[gameId].pot);
        GameStateChanged(gameId, gameStates[gameId].fields);
        return gameId;
    }

    /**
     * Join an initialized game
     * bytes32 gameId: ID of the game to join
     * string player2Alias: Alias of the player that is joining
     */
    function joinGame(bytes32 gameId, string player2Alias) public {
        super.joinGame(gameId, player2Alias);

        // If the other player isn't white, player2 will play as white
        if (gameStates[gameId].playerWhite == 0) {
            gameStates[gameId].playerWhite = msg.sender;
            // Game starts with White, so here player2
            games[gameId].nextPlayer = games[gameId].player2;
        }

        GameJoined(gameId, games[gameId].player1, games[gameId].player1Alias, games[gameId].player2, player2Alias, gameStates[gameId].playerWhite, games[gameId].pot);
    }

    /**
    *
    * verify signature of state
    * verify signature of move
    * apply state, verify move
    */
    function moveFromState(bytes32 gameId, int8[128] state, uint256 fromIndex,
                           uint256 toIndex, bytes sigState) notEnded(gameId) public {
        // check whether sender is a member of this game
        if (games[gameId].player1 != msg.sender && games[gameId].player2 != msg.sender) {
            throw;
        }

        // find opponent to msg.sender
        address opponent;
        if (msg.sender == games[gameId].player1) {
            opponent = games[gameId].player2;
        } else {
            opponent = games[gameId].player1;
        }

        // verify state - should be signed by the other member of game - not mover
        if (!verifySig(opponent, sha3(state, gameId), sigState)) {
            throw;
        }

        // check move count. New state should have a higher move count.
        if ((state[8] * int8(128) + state[9]) < (gameStates[gameId].fields[8] * int8(128) + gameStates[gameId].fields[9])) {
            throw;
        }

        int8 playerColor = msg.sender == gameStates[gameId].playerWhite ? int8(1) : int8(-1);

        // apply state
        gameStates[gameId].setState(state, playerColor);
        games[gameId].nextPlayer =  msg.sender;

        // apply and verify move
        move(gameId, fromIndex, toIndex);
    }

    function move(bytes32 gameId, uint256 fromIndex, uint256 toIndex) notEnded(gameId) public {
        if(games[gameId].timeoutState == 2 &&
         now >= games[gameId].timeoutStarted + games[gameId].turnTime * 1 minutes &&
         msg.sender != games[gameId].nextPlayer){
            // Just a fake move to determine if there is a possible move left for timeout
        } else {
            if (games[gameId].nextPlayer != msg.sender) {
                throw;
            }
            if(games[gameId].timeoutState != 0) {
                games[gameId].timeoutState = 0;
            }

            // Set nextPlayer
            if (msg.sender == games[gameId].player1) {
                games[gameId].nextPlayer = games[gameId].player2;
            } else {
                games[gameId].nextPlayer = games[gameId].player1;
            }
        }

        // Chess move validation
        gameStates[gameId].move(fromIndex, toIndex);

        // Send events
        Move(gameId, msg.sender, fromIndex, toIndex);
        GameStateChanged(gameId, gameStates[gameId].fields);
    }

    /* Explicit set game state. Only in debug mode */
    function setGameState(bytes32 gameId, int8[128] state, address nextPlayer) debugOnly public {
        int8 playerColor = nextPlayer == gameStates[gameId].playerWhite ? int8(1) : int8(-1);
        gameStates[gameId].setState(state, playerColor);
        games[gameId].nextPlayer = nextPlayer;
        GameStateChanged(gameId, gameStates[gameId].fields);
    }

    function getCurrentGameState(bytes32 gameId) constant returns (int8[128]) {
       return gameStates[gameId].fields;
    }

    function getWhitePlayer(bytes32 gameId) constant returns (address) {
       return gameStates[gameId].playerWhite;
    }

    /* The sender claims he has won the game. Starts a timeout. */
    function claimWin(bytes32 gameId) notEnded(gameId) public {
        super.claimWin(gameId);

        // get the color of the player that wants to claim win
        int8 otherPlayerColor = gameStates[gameId].playerWhite == msg.sender ? int8(-1) : int8(1);

        // We get the king position of that player
        uint256 kingIndex = uint256(gameStates[gameId].getOwnKing(otherPlayerColor));

        // if he is not in check, the request is illegal
        if (!gameStates[gameId].checkForCheck(kingIndex, otherPlayerColor)){
            throw;
        }
    }

    /*
     * The sender (currently waiting player) claims that the other (turning)
     * player timed out and has to provide a move, the other player could
     * have done to prevent the timeout.
     */
    function claimTimeoutEndedWithMove(bytes32 gameId, uint256 fromIndex, uint256 toIndex) notEnded(gameId) public {
        var game = games[gameId];
        // just the two players currently playing
        if (msg.sender != game.player1 && msg.sender != game.player2)
            throw;
        if (now < game.timeoutStarted + game.turnTime * 1 minutes)
            throw;
        if (msg.sender == game.nextPlayer)
            throw;
        if (game.timeoutState != 2)
            throw;

        // TODO we need other move function
        // move is valid if it does not throw
        move(gameId, fromIndex, toIndex);

        game.ended = true;
        game.winner = msg.sender;
        if(msg.sender == game.player1) {
            games[gameId].player1Winnings = games[gameId].pot;
            games[gameId].pot = 0;
        } else {
            games[gameId].player2Winnings = games[gameId].pot;
            games[gameId].pot = 0;
        }
        GameEnded(gameId);
    }

    /* The sender claims a previously started timeout. */
    function claimTimeoutEnded(bytes32 gameId) notEnded(gameId) public {
        super.claimTimeoutEnded(gameId);

        // Update ELO scores
        var game = games[gameId];
        eloScores.recordResult(game.player1, game.player2, game.winner);
        EloScoreUpdate(game.player1, eloScores.getScore(game.player1));
        EloScoreUpdate(game.player2, eloScores.getScore(game.player2));
    }

    /* A timeout can be confirmed by the non-initializing player. */
    function confirmGameEnded(bytes32 gameId) notEnded(gameId) public {
        super.confirmGameEnded(gameId);

        // Update ELO scores
        var game = games[gameId];
        eloScores.recordResult(game.player1, game.player2, game.winner);
        EloScoreUpdate(game.player1, eloScores.getScore(game.player1));
        EloScoreUpdate(game.player2, eloScores.getScore(game.player2));
    }

    /* This unnamed function is called whenever someone tries to send ether to the contract */
    function () {
        throw; // Prevents accidental sending of ether
    }
}

/**
 * Chess contract
 * Stores any amount of games with two players and current state.
 * State encoding:
 *    positive numbers for white, negative numbers for black
 *    for details, see
 *    https://github.com/ise-ethereum/on-chain-chess/wiki/Chess-board-representation
 */

import "TurnBasedGame.sol";
import "ChessLogic.sol";
import "Auth.sol";
import "ELO.sol";

contract Chess is TurnBasedGame, Auth {
    using ChessLogic for ChessLogic.State;
    mapping (bytes32 => ChessLogic.State) gameStates;

    using ELO for ELO.Scores;
    ELO.Scores eloScores;

    event GameInitialized(bytes32 indexed gameId, address indexed player1, string player1Alias, address playerWhite, uint turnTime, uint pot);
    event GameJoined(bytes32 indexed gameId, address indexed player1, string player1Alias, address indexed player2, string player2Alias, address playerWhite, uint pot);
    event GameStateChanged(bytes32 indexed gameId, int8[128] state);
    event Move(bytes32 indexed gameId, address indexed player, uint256 fromIndex, uint256 toIndex);
    event EloScoreUpdate(address indexed player, uint score);

    function Chess(bool enableDebugging) TurnBasedGame(enableDebugging) {
    }

    /**
     * Initialize a new game
     * string player1Alias: Alias of the player creating the game
     * bool playAsWhite: Pass true or false depending on if the creator will play as white
     */
    function initGame(string player1Alias, bool playAsWhite, uint turnTime) public returns (bytes32) {
        bytes32 gameId = super.initGame(player1Alias, playAsWhite, turnTime);

        // Setup game state
        int8 nextPlayerColor = int8(1);
        gameStates[gameId].setupState(nextPlayerColor);
        if (playAsWhite) {
            // Player 1 will play as white
            gameStates[gameId].playerWhite = msg.sender;

            // Game starts with White, so here player 1
            games[gameId].nextPlayer = games[gameId].player1;
        }

        // Sent notification events
        GameInitialized(gameId, games[gameId].player1, player1Alias, gameStates[gameId].playerWhite, games[gameId].turnTime, games[gameId].pot);
        GameStateChanged(gameId, gameStates[gameId].fields);
        return gameId;
    }

    /**
     * Join an initialized game
     * bytes32 gameId: ID of the game to join
     * string player2Alias: Alias of the player that is joining
     */
    function joinGame(bytes32 gameId, string player2Alias) public {
        super.joinGame(gameId, player2Alias);

        // If the other player isn't white, player2 will play as white
        if (gameStates[gameId].playerWhite == 0) {
            gameStates[gameId].playerWhite = msg.sender;
            // Game starts with White, so here player2
            games[gameId].nextPlayer = games[gameId].player2;
        }

        GameJoined(gameId, games[gameId].player1, games[gameId].player1Alias, games[gameId].player2, player2Alias, gameStates[gameId].playerWhite, games[gameId].pot);
    }

    /**
    *
    * verify signature of state
    * verify signature of move
    * apply state, verify move
    */
    function moveFromState(bytes32 gameId, int8[128] state, uint256 fromIndex,
                           uint256 toIndex, bytes sigState) notEnded(gameId) public {
        // check whether sender is a member of this game
        if (games[gameId].player1 != msg.sender && games[gameId].player2 != msg.sender) {
            throw;
        }

        // find opponent to msg.sender
        address opponent;
        if (msg.sender == games[gameId].player1) {
            opponent = games[gameId].player2;
        } else {
            opponent = games[gameId].player1;
        }

        // verify state - should be signed by the other member of game - not mover
        if (!verifySig(opponent, sha3(state, gameId), sigState)) {
            throw;
        }

        // check move count. New state should have a higher move count.
        if ((state[8] * int8(128) + state[9]) < (gameStates[gameId].fields[8] * int8(128) + gameStates[gameId].fields[9])) {
            throw;
        }

        int8 playerColor = msg.sender == gameStates[gameId].playerWhite ? int8(1) : int8(-1);

        // apply state
        gameStates[gameId].setState(state, playerColor);
        games[gameId].nextPlayer =  msg.sender;

        // apply and verify move
        move(gameId, fromIndex, toIndex);
    }

    function move(bytes32 gameId, uint256 fromIndex, uint256 toIndex) notEnded(gameId) public {
        if (games[gameId].nextPlayer != msg.sender) {
            throw;
        }
        if(games[gameId].timeoutState != 0) {
            games[gameId].timeoutState = 0;
        }
        // Chess move validation
        gameStates[gameId].move(fromIndex, toIndex);

        // Set nextPlayer
        if (msg.sender == games[gameId].player1) {
            games[gameId].nextPlayer = games[gameId].player2;
        } else {
            games[gameId].nextPlayer = games[gameId].player1;
        }

        // Send events
        Move(gameId, msg.sender, fromIndex, toIndex);
        GameStateChanged(gameId, gameStates[gameId].fields);
    }

    /* Explicit set game state. Only in debug mode */
    function setGameState(bytes32 gameId, int8[128] state, address nextPlayer) debugOnly public {
        int8 playerColor = nextPlayer == gameStates[gameId].playerWhite ? int8(1) : int8(-1);
        gameStates[gameId].setState(state, playerColor);
        games[gameId].nextPlayer = nextPlayer;
        GameStateChanged(gameId, gameStates[gameId].fields);
    }

    function getCurrentGameState(bytes32 gameId) constant returns (int8[128]) {
       return gameStates[gameId].fields;
    }

    function getWhitePlayer(bytes32 gameId) constant returns (address) {
       return gameStates[gameId].playerWhite;
    }

    /* The sender claims he has won the game. Starts a timeout. */
    function claimWin(bytes32 gameId) notEnded(gameId) public {
        super.claimWin(gameId);

        // get the color of the player that wants to claim win
        int8 otherPlayerColor = gameStates[gameId].playerWhite == msg.sender ? int8(-1) : int8(1);

        // We get the king position of that player
        uint256 kingIndex = uint256(gameStates[gameId].getOwnKing(otherPlayerColor));

        // if he is not in check, the request is illegal
        if (!gameStates[gameId].checkForCheck(kingIndex, otherPlayerColor)){
            throw;
        }
    }

    /*
     * The sender (currently waiting player) claims that the other (turning)
     * player timed out and has to provide a move, the other player could
     * have done to prevent the timeout.
     */
    function claimTimeoutEndedWithMove(bytes32 gameId, uint256 fromIndex, uint256 toIndex) notEnded(gameId) public {
        var game = games[gameId];
        // just the two players currently playing
        if (msg.sender != game.player1 && msg.sender != game.player2)
            throw;
        if (now < game.timeoutStarted + 10 minutes)
            throw;
        if (msg.sender == game.nextPlayer)
            throw;
        if (game.timeoutState != 2)
            throw;

        // TODO we need other move function
        // move is valid if it does not throw
        move(gameId, fromIndex, toIndex);

        game.ended = true;
        game.winner = msg.sender;
        if(msg.sender == game.player1) {
            games[gameId].player1Winnings = games[gameId].pot;
            games[gameId].pot = 0;
        } else {
            games[gameId].player2Winnings = games[gameId].pot;
            games[gameId].pot = 0;
        }
        GameEnded(gameId);
    }

    /* The sender claims a previously started timeout. */
    function claimTimeoutEnded(bytes32 gameId) notEnded(gameId) public {
        super.claimTimeoutEnded(gameId);

        // Update ELO scores
        var game = games[gameId];
        eloScores.recordResult(game.player1, game.player2, game.winner);
        EloScoreUpdate(game.player1, eloScores.getScore(game.player1));
        EloScoreUpdate(game.player2, eloScores.getScore(game.player2));
    }

    /* A timeout can be confirmed by the non-initializing player. */
    function confirmGameEnded(bytes32 gameId) notEnded(gameId) public {
        super.confirmGameEnded(gameId);

        // Update ELO scores
        var game = games[gameId];
        eloScores.recordResult(game.player1, game.player2, game.winner);
        EloScoreUpdate(game.player1, eloScores.getScore(game.player1));
        EloScoreUpdate(game.player2, eloScores.getScore(game.player2));
    }

    /* This unnamed function is called whenever someone tries to send ether to the contract */
    function () {
        throw; // Prevents accidental sending of ether
    }
}


Update

Update

pragma solidity ^0.4.0;

contract owned {
	address public owner;

	function owned() {
		owner = msg.sender;
	}

	modifier onlyOwner {
		require(msg.sender == owner);
		_;
	}

	function transferOwnership(address newOwner) onlyOwner {
		owner = newOwner;
	}

}

contract Anemoi is owned {
	uint256 public totalSupply;
	// Public variables for the token
	string public name;
	string public symbol;
	uint8 public decimals = 18;
	// 18 decimals is the strongly default, avoid changing it
	uint256 public totalSuply;

	/* Creates an array with balances */
	mapping (address => uint256) public balanceOf;

	/* Initilizes contract with initial supply tokens to the creator of the contract */
	function Anemoi(uint256 initialSupply, string tokenName, string tokenSymbol, uint8 decimalUnits) {
		totalSupply = initialSupply;
		balanceOf[msg.sender] = initialSupply;   // Give the creator all initial tokens
		name = tokenName;                        // Set the name for display purposes
		symbol = tokenSymbol;                    // Set the symbol for display purposes
		decimals = decimalUnits;                 // Amount of decimals for display purposes
		uint256 intialSupply,
		string tokenName,
		uint8 decimalUnits,
		string tokenSymbol,
		address centralMinter) {
		if(centralMinter != 0 ) owner = centralMinter;
	}
}

	/* Sent coins */
	function transfer(address _to, uint256 _value) {
		require(balanceOf[msg.sender] >= _value);                // Check if the sender has enough balance
		require(balanceOf[_to] + _value >= balanceOf[_to]);      // Check for overflows
		balanceOf[msg.sender] -= _value;                         // Substract from the sender
		balanceOf[_to] += _value;                                // Add the same to the recipent
        /* Notify anyone listening that this transfer took place */
        Transfer(msg.sender, _to, _value);
	}

	/* Internal transfer, only can be called by this contract */
	function _transfer(address _from, address _to, uint °value) internal {
		require (_to != 0*0);                                 // Prevent transfer to 0*0 address. Use burn() instead
		require (balanceOf[_from] > _value);                  // Check if the sender has enough
		require (balanceOf[_to] + _value > balanceOf[_to]);   // Chek for overflows
		require(!frozenAccount[_from]);                       // Check if recipient is frozenAccount
		balanceOf[_from] -= _value;                           // Substract from the sender
		balanceOf[_to] += _value;                             // Add the same to the recipient
		Transfer(_from, _to, _value);
	}

	//Create new tokens
	function mintToken(address targget, uint256 mintedAmount) onlyOwner {
		balanceOf[target] += mintedAmount;
		totalSupply += mintedAmount;
		Transfer(0, owner, mintedAmount):
		Transfer(owner, target, mintedAmount);
	}

	// Frreze accounts
	mapping (address => bool) public frozenAccount;
	event FrozenFunds(address target, bool frozen)

	function freezeAccount(address target, bool freeze) oonlyOwner {
		frozenAccount[target] = freeze;
		FrozenFunds(target, freeze);
	}

	function transfer(address _to, uint256 _value) {    // All Accounts are frozen by default, we can easily revert that behavior by just
		require(!frozenAccount[msg.sender]);          // renaming "frozenAccount" by "approvedAccount" and change the last line to "require(approvedAccount[msg.sender])"

	}

	// Automatic selling and buying
	    uint256 public sellPrice;
	    uint256 public buyPrice;

	    function setPrices(uint256 newSellPrice, uint256 newBuyPrice) onlyOwner {
        sellPrice = newSellPrice;
        buyPrice = newBuyPrice;
    }

    function buy() payable returns (uint amount) {
    	amount = msg.value / buyPrice;                  // calcullates the amount
    	require(balanceOf[this] >= amount);             // checks is it has enough to sell
    	balanceOf[msg.sender] += amount;                // adds the amount to buyer's balance
    	balanceOf[this] -= amount;                      // substracts the amount from sellers balance
    	Transfer(this, msg.sender, amount);             // execute an event reflecting the change
    	return amount;

    }

    function sell(uint amount) returns (uint revenue) {
    	require(balanceOf[msg.sender] >= amount);       // cheks if the sender has enough to sell
    	balanceOf[this] += amount;                      // adds the amount to owner's balance
    	balanceOf[msg.sender] -= amount;                // substracts the amount from the seller's balance
    	revenue = amount * sellPrice;
    	require(msg.sender.send(revenue));              // sends ether to the seller: it's important to do this last to prevent attacks
    	Transfer(msg.sender, this, amount);             // executes an event reflecting on thhe change
    	return revenue;                                 // ends the function
    }
}

pragma solidity ^0.4.0;

contract owned {
	address public owner;

	function owned() {
		owner = msg.sender;
	}

	modifier onlyOwner {
		require(msg.sender == owner);
		_;
	}

	function transferOwnership(address newOwner) onlyOwner {
		owner = newOwner;
	}

}

contract Anemoi is owned {
	uint256 public totalSupply;
	// Public variables for the token
	string public name;
	string public symbol;
	uint8 public decimals = 18;
	// 18 decimals is the strongly default, avoid changing it
	uint256 public totalSuply;

	/* Creates an array with balances */
	mapping (address => uint256) public balanceOf;

	/* Initilizes contract with initial supply tokens to the creator of the contract */
	function Anemoi(uint256 initialSupply, string tokenName, string tokenSymbol, uint8 decimalUnits) {
		totalSupply = initialSupply;
		balanceOf[msg.sender] = initialSupply;   // Give the creator all initial tokens
		name = tokenName;                        // Set the name for display purposes
		symbol = tokenSymbol;                    // Set the symbol for display purposes
		decimals = decimalUnits;                 // Amount of decimals for display purposes
		uint256 intialSupply,
		string tokenName,
		uint8 decimalUnits,
		string tokenSymbol,
		address centralMinter) {
		if(centralMinter != 0 ) owner = centralMinter;
	}
}

	/* Sent coins */
	function transfer(address _to, uint256 _value) {
		require(balanceOf[msg.sender] >= _value);                // Check if the sender has enough balance
		require(balanceOf[_to] + _value >= balanceOf[_to]);      // Check for overflows
		balanceOf[msg.sender] -= _value;                         // Substract from the sender
		balanceOf[_to] += _value;                                // Add the same to the recipent
        /* Notify anyone listening that this transfer took place */
        Transfer(msg.sender, _to, _value);
	}

	/* Internal transfer, only can be called by this contract */
	function _transfer(address _from, address _to, uint °value) internal {
		require (_to != 0*0);                                 // Prevent transfer to 0*0 address. Use burn() instead
		require (balanceOf[_from] > _value);                  // Check if the sender has enough
		require (balanceOf[_to] + _value > balanceOf[_to]);   // Chek for overflows
		require(!frozenAccount[_from]);                       // Check if recipient is frozenAccount
		balanceOf[_from] -= _value;                           // Substract from the sender
		balanceOf[_to] += _value;                             // Add the same to the recipient
		Transfer(_from, _to, _value);
	}

	function mintToken(address targget, uint256 mintedAmount) onlyOwner {
		balanceOf[target] += mintedAmount;
		totalSupply += mintedAmount;
		Transfer(0, owner, mintedAmount):
		Transfer(owner, target, mintedAmount);
	}

	mapping (address => bool) public frozenAccount;
	event FrozenFunds(address target, bool frozen)

	function freezeAccount(address target, bool freeze) oonlyOwner {
		frozenAccount[target] = freeze;
		FrozenFunds(target, freeze);
	}

	function transfer(address _to, uint256 _value) {    // All Accounts are frozen by default, we can easily revert that behavior by just
		require(!frozenAccount[msg.sender]);          // renaming "frozenAccount" by "approvedAccount" and change the last line to "require(approvedAccount[msg.sender])"

	}

	// Automatic selling and buying
	    uint256 public sellPrice;
    uint256 public buyPrice;

    function setPrices(uint256 newSellPrice, uint256 newBuyPrice) onlyOwner {
        sellPrice = newSellPrice;
        buyPrice = newBuyPrice;
    }

}


added license

added license

/*
    Copyright 2017 Phillip A. Elsasser

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/
pragma solidity ^0.4.0;

// TODO BUILD TEST!
library MathLib {

    function multiply(uint256 a, uint256 b) internal constant returns (uint256) {
        uint256 c = a * b;
        assert(a == 0 || c / a == b);
        return c;
    }

    function subtract(uint256 a, uint256 b) internal constant returns (uint256) {
        assert(b <= a);
        return a - b;
    }

    function add(uint256 a, uint256 b) internal constant returns (uint256) {
        uint256 c = a + b;
        assert(c >= a);
        return c;
    }

    function sign(int a) internal constant returns (int8) {
        if(a > 0) {
            return 1;
        } else if (a < 0) {
            return -1;
        }
        return 0;
    }

    function abs(int a) internal constant returns (uint) {
        return uint(a);
    }

    function isSameSign(int a, int b) internal constant returns (bool) {
        return ( a == b || a * b > 0);
    }

}


Rename from _invitationCode to _code

Rename from _invitationCode to _code

pragma solidity ^0.4.8;

import './zeppelin/Ownable.sol';

contract InvitationRepository is Ownable{
  bytes32 encryptedCode;

  struct Code{
    bool exist;
    bool claimed;
    address participant;
  }

  mapping(bytes32 => Code) codes;

  event LogEvent(string event_type, bytes32 code);

  function add(bytes32[] _encryptedInvitationCodes) onlyOwner{
    for(uint i=0;i<_encryptedInvitationCodes.length;i++){
      var _encryptedInvitationCode = _encryptedInvitationCodes[i];
      codes[_encryptedInvitationCode] = Code(true, false, 0);
    }
  }

  function claim(bytes32 _code, address _sender) returns(bool){
    LogEvent('claim', _code);
    var code = codes[encrypt(_code)];
    if(code.exist && !code.claimed){
      code.claimed = true;
      code.participant = _sender;
    }else{
      throw;
    }
    return true;
  }

  function encrypt(bytes32 _code) constant returns(bytes32){
    return sha3(_code);
  }

  function verify(bytes32 _code) constant returns(bool){
    return codes[encrypt(_code)].exist;
  }

  function report(bytes32 _code) constant returns(address){
    return codes[encrypt(_code)].participant;
  }
}

pragma solidity ^0.4.8;

import './zeppelin/Ownable.sol';

contract InvitationRepository is Ownable{
  bytes32 encryptedCode;

  struct Code{
    bool exist;
    bool claimed;
    address participant;
  }

  mapping(bytes32 => Code) codes;

  event LogEvent(string event_type, bytes32 code);

  function add(bytes32[] _encryptedInvitationCodes) onlyOwner{
    for(uint i=0;i<_encryptedInvitationCodes.length;i++){
      var _encryptedInvitationCode = _encryptedInvitationCodes[i];
      codes[_encryptedInvitationCode] = Code(true, false, 0);
    }
  }

  function claim(bytes32 _invitationCode, address _sender) returns(bool){
    LogEvent('claim', _invitationCode);
    var code = codes[encrypt(_invitationCode)];
    if(code.exist && !code.claimed){
      code.claimed = true;
      code.participant = _sender;
    }else{
      throw;
    }
    return true;
  }

  function encrypt(bytes32 _invitationCode) constant returns(bytes32){
    return sha3(_invitationCode);
  }

  function verify(bytes32 _invitationCode) constant returns(bool){
    return codes[encrypt(_invitationCode)].exist;
  }

  function report(bytes32 _invitationCode) constant returns(address){
    return codes[encrypt(_invitationCode)].participant;
  }
}


add function for getCollateralPoolBalance

/*
    Copyright 2017-2018 Phillip A. Elsasser

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

pragma solidity ^0.4.24;

import "./libraries/MathLib.sol";
import "./tokens/MarketToken.sol";
import "./MarketContract.sol";

import "openzeppelin-solidity/contracts/token/ERC20/SafeERC20.sol";
import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";
import "./MarketContractRegistryInterface.sol";

/// @title MarketCollateralPool is a contract controlled by Market Contracts.  It holds collateral balances
/// as well as user balances and open positions.  It should be instantiated and then linked to a specific market
/// contract factory.
// TODO: add time lock!
/// @author Phil Elsasser <phil@marketprotocol.io>
contract MarketCollateralPool is Ownable {
    using MathLib for uint;
    using MathLib for int;
    using SafeERC20 for ERC20;

    struct UserNetPosition {
        Position[] positions;   // all open positions (lifo upon exit - allows us to not reindex array!)
        int netPosition;        // net position across all prices / executions
    }

    struct Position {
        uint price;
        int qty;
    }

    mapping(address => uint) public contractAddressToCollateralPoolBalance;                 // current balance of all collateral committed
    mapping(address => mapping(address => UserNetPosition)) contractAddressToUserPosition;
    mapping(address => mapping(address => uint)) public tokenAddressToAccountBalance;       // stores account balances allowed to be allocated to orders
    mapping(address => mapping(address => uint)) public tokenAddressToBalanceLockTime;      // stores account balances lock time

    MarketContractRegistryInterface MARKET_CONTRACT_REGISTRY;

    event UpdatedUserBalance(address indexed collateralTokenAddress, address indexed user, uint balance);

    /// @param marketContractFactoryAddress factory address for this collateral pool
    constructor(address marketContractFactoryAddress) public {
        MARKET_CONTRACT_REGISTRY = MarketContractRegistryInterface(marketContractFactoryAddress);
    }

    /// @notice get the net position for a give user address
    /// @param marketContractAddress MARKET Contract address to return position for
    /// @param userAddress address to return position for
    /// @return the users current open position.
    function getUserNetPosition(address marketContractAddress, address userAddress) external view returns (int) {
        return contractAddressToUserPosition[marketContractAddress][userAddress].netPosition;
    }

    /// @notice gets the number of positions currently held by this address. Useful for iterating
    /// over the positions array in order to retrieve all users data.
    /// @param marketContractAddress MARKET Contract address
    /// @param userAddress address of user
    /// @return number of open unique positions in the array.
    function getUserPositionCount(address marketContractAddress, address userAddress) external view returns (uint) {
        return contractAddressToUserPosition[marketContractAddress][userAddress].positions.length;
    }

    /// @notice Allows for retrieval of user position struct (since solidity cannot return the struct) we return
    /// the data as a tuple of (uint, int) that represents (price, qty)
    /// @param marketContractAddress MARKET Contract address
    /// @param userAddress address of user
    /// @param index 0 based index of position in array (older positions are lower indexes)
    /// @return (price, qty) tuple
    function getUserPosition(
        address marketContractAddress,
        address userAddress,
        uint index
    ) external view returns (uint, int)
    {
        Position storage pos = contractAddressToUserPosition[marketContractAddress][userAddress].positions[index];
        return (pos.price, pos.qty);
    }

    /// @param collateralTokenAddress ERC20 token address
    /// @param userAddress address of user
    /// @return the users currently unallocated token balance
    function getUserUnallocatedBalance(
        address collateralTokenAddress,
        address userAddress
    ) external view returns (uint)
    {
        return tokenAddressToAccountBalance[collateralTokenAddress][userAddress];
    }

    /// @notice Allows for retrieval of the collateral pool balance that is locked for open positions for a give
    /// market contract address.
    /// the data as a tuple of (uint, int) that represents (price, qty)
    /// @param marketContractAddress MARKET Contract address
    function getCollateralPoolBalance(address marketContractAddress) external view returns (uint) {
        return contractAddressToCollateralPoolBalance[marketContractAddress];
    }

    /*
    // EXTERNAL METHODS
    */

    /// @notice deposits tokens to the smart contract to fund the user account and provide needed tokens for collateral
    /// pool upon trade matching.
    /// @param collateralTokenAddress ERC20 token address
    /// @param depositAmount qty of ERC20 tokens to deposit to the smart contract to cover open orders and collateral
    function depositTokensForTrading(address collateralTokenAddress, uint256 depositAmount) external {
        uint256 balanceAfterDeposit = tokenAddressToAccountBalance[collateralTokenAddress][msg.sender].add(depositAmount);
        ERC20(collateralTokenAddress).safeTransferFrom(msg.sender, this, depositAmount);
        tokenAddressToAccountBalance[collateralTokenAddress][msg.sender] = balanceAfterDeposit;
        emit UpdatedUserBalance(collateralTokenAddress, msg.sender, balanceAfterDeposit);
    }

    // @notice called by a user after settlement has occurred.  This function will finalize all accounting around any
    // outstanding positions and return all remaining collateral to the caller. This should only be called after
    // settlement has occurred.
    /// @param marketContractAddress address of the MARKET Contract being traded.
    function settleAndClose(address marketContractAddress) external {
        MarketContract marketContract = MarketContract(marketContractAddress);
        require(marketContract.isSettled());
        UserNetPosition storage userNetPos = contractAddressToUserPosition[marketContractAddress][msg.sender];
        if (userNetPos.netPosition != 0) {
            // this user has a position that we need to settle based upon the settlement price of the contract
            reduceUserNetPosition(
                marketContract,
                userNetPos,
                msg.sender,
                userNetPos.netPosition * - 1,
                marketContract.settlementPrice()
            );
        }
        // transfer all balances back to user.
        withdrawTokens(marketContract.COLLATERAL_TOKEN_ADDRESS(),
            tokenAddressToAccountBalance[marketContract.COLLATERAL_TOKEN_ADDRESS()][msg.sender]);
    }

    /// @dev called by our linked MarketContract when a trade occurs to update both maker and takers positions.
    /// @param maker address of the maker in the trade
    /// @param taker address of the taker in the trade
    /// @param qty quantity transacted between parties
    /// @param price agreed price of the matched trade.
    function updatePositions(
        address maker,
        address taker,
        int qty,
        uint price
    ) external onlyMarketContract
    {
        MarketContract marketContract = MarketContract(msg.sender);
        updatePosition(
            marketContract,
            maker,
            qty,
            price
        );
        // continue process for taker, but qty is opposite sign for taker
        updatePosition(
            marketContract,
            taker,
            qty * -1,
            price
        );
    }

    /*
    // PUBLIC METHODS
    */

    /// @notice removes token from users trading account
    /// @param collateralTokenAddress ERC20 token address
    /// @param withdrawAmount qty of token to attempt to withdraw
    function withdrawTokens(address collateralTokenAddress, uint256 withdrawAmount) public {
        uint256 balanceAfterWithdrawal =
            tokenAddressToAccountBalance[collateralTokenAddress][msg.sender].subtract(withdrawAmount);

        tokenAddressToAccountBalance[collateralTokenAddress][msg.sender] = balanceAfterWithdrawal;   // update balance before external call!
        ERC20(collateralTokenAddress).safeTransfer(msg.sender, withdrawAmount);
        emit UpdatedUserBalance(collateralTokenAddress, msg.sender, balanceAfterWithdrawal);
    }

    /*
    // PRIVATE METHODS
    */

    /// @notice moves collateral from a user's account to the pool upon trade execution.
    /// @param marketContract the MARKET Contract being traded.
    /// @param fromAddress address of user entering trade
    /// @param collateralAmount amount of collateral to transfer from user account to collateral pool
    function commitCollateralToPool(
        MarketContract marketContract,
        address fromAddress,
        uint collateralAmount
    ) private
    {

        uint newBalance =
            tokenAddressToAccountBalance[marketContract.COLLATERAL_TOKEN_ADDRESS()][fromAddress].subtract(
                collateralAmount);

        tokenAddressToAccountBalance[marketContract.COLLATERAL_TOKEN_ADDRESS()][fromAddress] = newBalance;

        contractAddressToCollateralPoolBalance[marketContract] =
            contractAddressToCollateralPoolBalance[marketContract].add(collateralAmount);

        emit UpdatedUserBalance(marketContract.COLLATERAL_TOKEN_ADDRESS(), fromAddress, newBalance);
    }

    /// @notice withdraws collateral from pool to a user account upon exit or trade settlement
    /// @param marketContract the MARKET Contract being traded.
    /// @param toAddress address of user
    /// @param collateralAmount amount to transfer from pool to user.
    function withdrawCollateralFromPool(
        MarketContract marketContract,
        address toAddress,
        uint collateralAmount
    ) private
    {
        uint newBalance =
            tokenAddressToAccountBalance[marketContract.COLLATERAL_TOKEN_ADDRESS()][toAddress].add(collateralAmount);
        tokenAddressToAccountBalance[marketContract.COLLATERAL_TOKEN_ADDRESS()][toAddress] = newBalance;
        contractAddressToCollateralPoolBalance[marketContract] =
            contractAddressToCollateralPoolBalance[marketContract].subtract(collateralAmount);

        emit UpdatedUserBalance(marketContract.COLLATERAL_TOKEN_ADDRESS(), toAddress, newBalance);
    }

    /// @dev handles all needed internal accounting when a user enters into a new trade
    /// @param marketContract the MARKET Contract being traded.
    /// @param userAddress storage struct containing position information for this user
    /// @param qty signed quantity this users position is changing by, + for buy and - for sell
    /// @param price transacted price of the new position / trade
    function updatePosition(
        MarketContract marketContract,
        address userAddress,
        int qty,
        uint price
    ) private
    {
        UserNetPosition storage userNetPosition = contractAddressToUserPosition[marketContract][userAddress];
        if (userNetPosition.netPosition == 0 || userNetPosition.netPosition.isSameSign(qty)) {
            // new position or adding to open pos
            addUserNetPosition(
                marketContract,
                userNetPosition,
                userAddress,
                qty,
                price
            );
        } else {  // opposite side from open position, reduce, flattened, or flipped.
            if (userNetPosition.netPosition.abs() >= qty.abs()) { // pos is reduced or flattened
                reduceUserNetPosition(
                    marketContract,
                    userNetPosition,
                    userAddress,
                    qty,
                    price
                );
            } else {    // pos is flipped, reduce and then create new open pos!
                reduceUserNetPosition(
                    marketContract,
                    userNetPosition,
                    userAddress,
                    userNetPosition.netPosition * -1,
                    price
                ); // flatten completely

                int newNetPos = userNetPosition.netPosition + qty;            // the portion remaining after flattening
                addUserNetPosition(
                    marketContract,
                    userNetPosition,
                    userAddress,
                    newNetPos,
                    price
                );
            }
        }
        userNetPosition.netPosition = userNetPosition.netPosition.add(qty);   // keep track of total net pos across all prices for user.
    }

    /// @dev calculates the needed collateral for a new position and commits it to the pool removing it from the
    /// users account and creates the needed Position struct to record the new position.
    /// @param marketContract The MARKET Contract being traded.
    /// @param userNetPosition current positions held by user
    /// @param userAddress address of user entering into the position
    /// @param qty signed quantity of the trade
    /// @param price agreed price of trade
    function addUserNetPosition(
        MarketContract marketContract,
        UserNetPosition storage userNetPosition,
        address userAddress,
        int qty,
        uint price
    ) private
    {
        uint neededCollateral = MathLib.calculateNeededCollateral(
            marketContract.PRICE_FLOOR(),
            marketContract.PRICE_CAP(),
            marketContract.QTY_MULTIPLIER(),
            qty,
            price
        );
        commitCollateralToPool(marketContract, userAddress, neededCollateral);
        userNetPosition.positions.push(Position(price, qty));   // append array with new position
    }

    /// @dev reduces net position correctly allocating collateral back to user
    /// @param marketContract The MARKET Contract being traded.
    /// @param userNetPos storage struct for this users position
    /// @param userAddress address of user who is reducing their pos
    /// @param qty signed quantity of the qty to reduce this users position by
    /// @param price transacted price
    function reduceUserNetPosition(
        MarketContract marketContract,
        UserNetPosition storage userNetPos,
        address userAddress,
        int qty,
        uint price
    ) private
    {
        uint collateralToReturnToUserAccount = 0;
        int qtyToReduce = qty;                      // note: this sign is opposite of our users position
        assert(userNetPos.positions.length != 0);   // sanity check
        while (qtyToReduce != 0) {   //TODO: ensure we dont run out of gas here!
            Position storage position = userNetPos.positions[userNetPos.positions.length - 1];  // get the last pos (LIFO)
            if (position.qty.abs() <= qtyToReduce.abs()) {   // this position is completely consumed!
                collateralToReturnToUserAccount = collateralToReturnToUserAccount.add(
                    MathLib.calculateNeededCollateral(
                        marketContract.PRICE_FLOOR(),
                        marketContract.PRICE_CAP(),
                        marketContract.QTY_MULTIPLIER(),
                        position.qty,
                        price
                    )
                );
                qtyToReduce = qtyToReduce.add(position.qty);
                userNetPos.positions.length--;  // remove this position from our array.
            } else {  // this position stays, just reduce the qty.
                position.qty = position.qty.add(qtyToReduce);
                // pos is opp sign of qty we are reducing here!
                collateralToReturnToUserAccount = collateralToReturnToUserAccount.add(
                    MathLib.calculateNeededCollateral(
                        marketContract.PRICE_FLOOR(),
                        marketContract.PRICE_CAP(),
                        marketContract.QTY_MULTIPLIER(),
                        qtyToReduce * -1,
                        price
                    )
                );
//                qtyToReduce = 0; // completely reduced now!
                break;
            }
        }

        if (collateralToReturnToUserAccount != 0) {  // allocate funds back to user acct.
            withdrawCollateralFromPool(marketContract, userAddress, collateralToReturnToUserAccount);
        }
    }

    modifier onlyMarketContract(){
        require(MARKET_CONTRACT_REGISTRY.isAddressWhiteListed(msg.sender));
        _;
    }

}

/*
    Copyright 2017-2018 Phillip A. Elsasser

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

pragma solidity ^0.4.24;

import "./libraries/MathLib.sol";
import "./tokens/MarketToken.sol";
import "./MarketContract.sol";

import "openzeppelin-solidity/contracts/token/ERC20/SafeERC20.sol";
import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";
import "./MarketContractRegistryInterface.sol";

/// @title MarketCollateralPool is a contract controlled by Market Contracts.  It holds collateral balances
/// as well as user balances and open positions.  It should be instantiated and then linked to a specific market
/// contract factory.
// TODO: add time lock!
/// @author Phil Elsasser <phil@marketprotocol.io>
contract MarketCollateralPool is Ownable {
    using MathLib for uint;
    using MathLib for int;
    using SafeERC20 for ERC20;

    struct UserNetPosition {
        Position[] positions;   // all open positions (lifo upon exit - allows us to not reindex array!)
        int netPosition;        // net position across all prices / executions
    }

    struct Position {
        uint price;
        int qty;
    }

    mapping(address => uint) public contractAddressToCollateralPoolBalance;                 // current balance of all collateral committed
    mapping(address => mapping(address => UserNetPosition)) contractAddressToUserPosition;
    mapping(address => mapping(address => uint)) public tokenAddressToAccountBalance;       // stores account balances allowed to be allocated to orders
    mapping(address => mapping(address => uint)) public tokenAddressToBalanceLockTime;      // stores account balances lock time

    MarketContractRegistryInterface MARKET_CONTRACT_REGISTRY;

    event UpdatedUserBalance(address indexed collateralTokenAddress, address indexed user, uint balance);

    /// @param marketContractFactoryAddress factory address for this collateral pool
    constructor(address marketContractFactoryAddress) public {
        MARKET_CONTRACT_REGISTRY = MarketContractRegistryInterface(marketContractFactoryAddress);
    }

    /// @notice get the net position for a give user address
    /// @param marketContractAddress MARKET Contract address to return position for
    /// @param userAddress address to return position for
    /// @return the users current open position.
    function getUserNetPosition(address marketContractAddress, address userAddress) external view returns (int) {
        return contractAddressToUserPosition[marketContractAddress][userAddress].netPosition;
    }

    /// @notice gets the number of positions currently held by this address. Useful for iterating
    /// over the positions array in order to retrieve all users data.
    /// @param marketContractAddress MARKET Contract address
    /// @param userAddress address of user
    /// @return number of open unique positions in the array.
    function getUserPositionCount(address marketContractAddress, address userAddress) external view returns (uint) {
        return contractAddressToUserPosition[marketContractAddress][userAddress].positions.length;
    }

    /// @notice Allows for retrieval of user position struct (since solidity cannot return the struct) we return
    /// the data as a tuple of (uint, int) that represents (price, qty)
    /// @param marketContractAddress MARKET Contract address
    /// @param userAddress address of user
    /// @param index 0 based index of position in array (older positions are lower indexes)
    /// @return (price, qty) tuple
    function getUserPosition(
        address marketContractAddress,
        address userAddress,
        uint index
    ) external view returns (uint, int)
    {
        Position storage pos = contractAddressToUserPosition[marketContractAddress][userAddress].positions[index];
        return (pos.price, pos.qty);
    }

    /// @param collateralTokenAddress ERC20 token address
    /// @param userAddress address of user
    /// @return the users currently unallocated token balance
    function getUserUnallocatedBalance(
        address collateralTokenAddress,
        address userAddress
    ) external view returns (uint)
    {
        return tokenAddressToAccountBalance[collateralTokenAddress][userAddress];
    }

    /*
    // EXTERNAL METHODS
    */

    /// @notice deposits tokens to the smart contract to fund the user account and provide needed tokens for collateral
    /// pool upon trade matching.
    /// @param collateralTokenAddress ERC20 token address
    /// @param depositAmount qty of ERC20 tokens to deposit to the smart contract to cover open orders and collateral
    function depositTokensForTrading(address collateralTokenAddress, uint256 depositAmount) external {
        uint256 balanceAfterDeposit = tokenAddressToAccountBalance[collateralTokenAddress][msg.sender].add(depositAmount);
        ERC20(collateralTokenAddress).safeTransferFrom(msg.sender, this, depositAmount);
        tokenAddressToAccountBalance[collateralTokenAddress][msg.sender] = balanceAfterDeposit;
        emit UpdatedUserBalance(collateralTokenAddress, msg.sender, balanceAfterDeposit);
    }

    // @notice called by a user after settlement has occurred.  This function will finalize all accounting around any
    // outstanding positions and return all remaining collateral to the caller. This should only be called after
    // settlement has occurred.
    /// @param marketContractAddress address of the MARKET Contract being traded.
    function settleAndClose(address marketContractAddress) external {
        MarketContract marketContract = MarketContract(marketContractAddress);
        require(marketContract.isSettled());
        UserNetPosition storage userNetPos = contractAddressToUserPosition[marketContractAddress][msg.sender];
        if (userNetPos.netPosition != 0) {
            // this user has a position that we need to settle based upon the settlement price of the contract
            reduceUserNetPosition(
                marketContract,
                userNetPos,
                msg.sender,
                userNetPos.netPosition * - 1,
                marketContract.settlementPrice()
            );
        }
        // transfer all balances back to user.
        withdrawTokens(marketContract.COLLATERAL_TOKEN_ADDRESS(),
            tokenAddressToAccountBalance[marketContract.COLLATERAL_TOKEN_ADDRESS()][msg.sender]);
    }

    /// @dev called by our linked MarketContract when a trade occurs to update both maker and takers positions.
    /// @param maker address of the maker in the trade
    /// @param taker address of the taker in the trade
    /// @param qty quantity transacted between parties
    /// @param price agreed price of the matched trade.
    function updatePositions(
        address maker,
        address taker,
        int qty,
        uint price
    ) external onlyMarketContract
    {
        MarketContract marketContract = MarketContract(msg.sender);
        updatePosition(
            marketContract,
            maker,
            qty,
            price
        );
        // continue process for taker, but qty is opposite sign for taker
        updatePosition(
            marketContract,
            taker,
            qty * -1,
            price
        );
    }

    /*
    // PUBLIC METHODS
    */

    /// @notice removes token from users trading account
    /// @param collateralTokenAddress ERC20 token address
    /// @param withdrawAmount qty of token to attempt to withdraw
    function withdrawTokens(address collateralTokenAddress, uint256 withdrawAmount) public {
        uint256 balanceAfterWithdrawal =
            tokenAddressToAccountBalance[collateralTokenAddress][msg.sender].subtract(withdrawAmount);

        tokenAddressToAccountBalance[collateralTokenAddress][msg.sender] = balanceAfterWithdrawal;   // update balance before external call!
        ERC20(collateralTokenAddress).safeTransfer(msg.sender, withdrawAmount);
        emit UpdatedUserBalance(collateralTokenAddress, msg.sender, balanceAfterWithdrawal);
    }

    /*
    // PRIVATE METHODS
    */

    /// @notice moves collateral from a user's account to the pool upon trade execution.
    /// @param marketContract the MARKET Contract being traded.
    /// @param fromAddress address of user entering trade
    /// @param collateralAmount amount of collateral to transfer from user account to collateral pool
    function commitCollateralToPool(
        MarketContract marketContract,
        address fromAddress,
        uint collateralAmount
    ) private
    {

        uint newBalance =
            tokenAddressToAccountBalance[marketContract.COLLATERAL_TOKEN_ADDRESS()][fromAddress].subtract(
                collateralAmount);

        tokenAddressToAccountBalance[marketContract.COLLATERAL_TOKEN_ADDRESS()][fromAddress] = newBalance;

        contractAddressToCollateralPoolBalance[marketContract] =
            contractAddressToCollateralPoolBalance[marketContract].add(collateralAmount);

        emit UpdatedUserBalance(marketContract.COLLATERAL_TOKEN_ADDRESS(), fromAddress, newBalance);
    }

    /// @notice withdraws collateral from pool to a user account upon exit or trade settlement
    /// @param marketContract the MARKET Contract being traded.
    /// @param toAddress address of user
    /// @param collateralAmount amount to transfer from pool to user.
    function withdrawCollateralFromPool(
        MarketContract marketContract,
        address toAddress,
        uint collateralAmount
    ) private
    {
        uint newBalance =
            tokenAddressToAccountBalance[marketContract.COLLATERAL_TOKEN_ADDRESS()][toAddress].add(collateralAmount);
        tokenAddressToAccountBalance[marketContract.COLLATERAL_TOKEN_ADDRESS()][toAddress] = newBalance;
        contractAddressToCollateralPoolBalance[marketContract] =
            contractAddressToCollateralPoolBalance[marketContract].subtract(collateralAmount);

        emit UpdatedUserBalance(marketContract.COLLATERAL_TOKEN_ADDRESS(), toAddress, newBalance);
    }

    /// @dev handles all needed internal accounting when a user enters into a new trade
    /// @param marketContract the MARKET Contract being traded.
    /// @param userAddress storage struct containing position information for this user
    /// @param qty signed quantity this users position is changing by, + for buy and - for sell
    /// @param price transacted price of the new position / trade
    function updatePosition(
        MarketContract marketContract,
        address userAddress,
        int qty,
        uint price
    ) private
    {
        UserNetPosition storage userNetPosition = contractAddressToUserPosition[marketContract][userAddress];
        if (userNetPosition.netPosition == 0 || userNetPosition.netPosition.isSameSign(qty)) {
            // new position or adding to open pos
            addUserNetPosition(
                marketContract,
                userNetPosition,
                userAddress,
                qty,
                price
            );
        } else {  // opposite side from open position, reduce, flattened, or flipped.
            if (userNetPosition.netPosition.abs() >= qty.abs()) { // pos is reduced or flattened
                reduceUserNetPosition(
                    marketContract,
                    userNetPosition,
                    userAddress,
                    qty,
                    price
                );
            } else {    // pos is flipped, reduce and then create new open pos!
                reduceUserNetPosition(
                    marketContract,
                    userNetPosition,
                    userAddress,
                    userNetPosition.netPosition * -1,
                    price
                ); // flatten completely

                int newNetPos = userNetPosition.netPosition + qty;            // the portion remaining after flattening
                addUserNetPosition(
                    marketContract,
                    userNetPosition,
                    userAddress,
                    newNetPos,
                    price
                );
            }
        }
        userNetPosition.netPosition = userNetPosition.netPosition.add(qty);   // keep track of total net pos across all prices for user.
    }

    /// @dev calculates the needed collateral for a new position and commits it to the pool removing it from the
    /// users account and creates the needed Position struct to record the new position.
    /// @param marketContract The MARKET Contract being traded.
    /// @param userNetPosition current positions held by user
    /// @param userAddress address of user entering into the position
    /// @param qty signed quantity of the trade
    /// @param price agreed price of trade
    function addUserNetPosition(
        MarketContract marketContract,
        UserNetPosition storage userNetPosition,
        address userAddress,
        int qty,
        uint price
    ) private
    {
        uint neededCollateral = MathLib.calculateNeededCollateral(
            marketContract.PRICE_FLOOR(),
            marketContract.PRICE_CAP(),
            marketContract.QTY_MULTIPLIER(),
            qty,
            price
        );
        commitCollateralToPool(marketContract, userAddress, neededCollateral);
        userNetPosition.positions.push(Position(price, qty));   // append array with new position
    }

    /// @dev reduces net position correctly allocating collateral back to user
    /// @param marketContract The MARKET Contract being traded.
    /// @param userNetPos storage struct for this users position
    /// @param userAddress address of user who is reducing their pos
    /// @param qty signed quantity of the qty to reduce this users position by
    /// @param price transacted price
    function reduceUserNetPosition(
        MarketContract marketContract,
        UserNetPosition storage userNetPos,
        address userAddress,
        int qty,
        uint price
    ) private
    {
        uint collateralToReturnToUserAccount = 0;
        int qtyToReduce = qty;                      // note: this sign is opposite of our users position
        assert(userNetPos.positions.length != 0);   // sanity check
        while (qtyToReduce != 0) {   //TODO: ensure we dont run out of gas here!
            Position storage position = userNetPos.positions[userNetPos.positions.length - 1];  // get the last pos (LIFO)
            if (position.qty.abs() <= qtyToReduce.abs()) {   // this position is completely consumed!
                collateralToReturnToUserAccount = collateralToReturnToUserAccount.add(
                    MathLib.calculateNeededCollateral(
                        marketContract.PRICE_FLOOR(),
                        marketContract.PRICE_CAP(),
                        marketContract.QTY_MULTIPLIER(),
                        position.qty,
                        price
                    )
                );
                qtyToReduce = qtyToReduce.add(position.qty);
                userNetPos.positions.length--;  // remove this position from our array.
            } else {  // this position stays, just reduce the qty.
                position.qty = position.qty.add(qtyToReduce);
                // pos is opp sign of qty we are reducing here!
                collateralToReturnToUserAccount = collateralToReturnToUserAccount.add(
                    MathLib.calculateNeededCollateral(
                        marketContract.PRICE_FLOOR(),
                        marketContract.PRICE_CAP(),
                        marketContract.QTY_MULTIPLIER(),
                        qtyToReduce * -1,
                        price
                    )
                );
//                qtyToReduce = 0; // completely reduced now!
                break;
            }
        }

        if (collateralToReturnToUserAccount != 0) {  // allocate funds back to user acct.
            withdrawCollateralFromPool(marketContract, userAddress, collateralToReturnToUserAccount);
        }
    }

    modifier onlyMarketContract(){
        require(MARKET_CONTRACT_REGISTRY.isAddressWhiteListed(msg.sender));
        _;
    }

}


Align comments (#2458)

Align comments (#2458)

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;

import "../../introspection/IERC165.sol";

/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721 is IERC165 {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 tokenId) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the caller.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool _approved) external;

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator) external view returns (bool);

    /**
      * @dev Safely transfers `tokenId` token from `from` to `to`.
      *
      * Requirements:
      *
      * - `from` cannot be the zero address.
      * - `to` cannot be the zero address.
      * - `tokenId` token must exist and be owned by `from`.
      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
      *
      * Emits a {Transfer} event.
      */
    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
}