Adds getOffer function.

Adds getOffer function.

contract Custodian {
    function reserve(address owner, uint amount);
    function unreserve(address owner, uint amount);
    function transfer(address oldOwner, address newOwner, uint shares);
}

contract Exchange {
    enum Side { Bid, Ask }
    struct Offer {
        address owner;
        uint price;
        bool active;
        Side side;
        int16 nextIndex;
        uint32 shares;
    }

    int32 constant maximumDepth = 1000;
    int16 topAskIndex = -1;
    int16 topBidIndex = -1;
    mapping (address => uint) balances;
    Custodian custodian;
    Offer[1000] offers;

    function Exchange() {
        custodian = Custodian(msg.sender);
    }

    function postOffer(Side side, uint price, uint32 shares) {
        if (price == 0 || shares == 0) {
            throw;
        }
        if (side == Side.Bid) {
            if (price * shares != msg.value) {
                throw;
            }
        } else {
            custodian.reserve(msg.sender, shares);
        }
        uint32 remainingShares = shares;
        int16 index = side == Side.Ask ? topBidIndex : topAskIndex;
        int16 parentIndex = -1;
        while (index != -1 && remainingShares > 0) {
            Offer next = offers[uint(index)];
            bool matches = (
                (side == Side.Bid && next.price <= price) ||
                (side == Side.Ask && next.price >= price)
            );
            if (!next.active || !matches) {
                break;
            }
            address seller = side == Side.Bid ? next.owner : msg.sender;
            address buyer = side == Side.Bid ? msg.sender : next.owner;
            if (next.shares <= remainingShares) {
                balances[seller] += next.shares * next.price;
                remainingShares -= next.shares;
                offers[uint(index)].active = false;
                spliceOffer(next.side, parentIndex, next.nextIndex);
                custodian.unreserve(seller, next.shares);
                custodian.transfer(seller, buyer, next.shares);
            } else {
                balances[seller] += remainingShares * next.price;
                offers[uint(index)].shares = next.shares - remainingShares;
                custodian.unreserve(seller, remainingShares);
                custodian.transfer(seller, buyer, remainingShares);
                remainingShares = 0;
            }
            parentIndex = index;
            index = next.nextIndex;
        }
        if (remainingShares == 0) {
            return;
        }
        int16 newIndex = 0;
        while (offers[uint(newIndex)].active) {
            if (++newIndex >= maximumDepth) {
                throw;
            }
        }
        int16 previousIndex = -1;
        int16 nextIndex = side == Side.Bid ? topBidIndex : topAskIndex;
        while (nextIndex != -1 && offers[uint(nextIndex)].price > price) {
            previousIndex = nextIndex;
            nextIndex = offers[uint(nextIndex)].nextIndex;
        }
        if (previousIndex == -1) {
            if (side == Side.Bid) {
                topBidIndex = newIndex;
            } else {
                topAskIndex = newIndex;
            }
        } else {
            offers[uint(previousIndex)].nextIndex = newIndex;
        }
        offers[uint(newIndex)] = Offer(msg.sender, price, true, side, nextIndex, remainingShares);
    }

    function getNumberOfOffers(Side side) returns (uint16) {
        uint16 count = 0;
        int16 currentIndex = side == Side.Bid ? topBidIndex : topAskIndex;
        while (currentIndex != -1) {
            count++;
            currentIndex = offers[uint(currentIndex)].nextIndex;
        }
        return count;
    }

    function getTopOffer(Side side) returns (uint price, uint32 shares) {
        return getOffer(side, 0);
    }

    function getOffer(Side side, uint depth) returns (uint price, uint32 shares) {
        int16 currentIndex = side == Side.Bid ? topBidIndex : topAskIndex;
        while (currentIndex != -1 && depth > 0) {
            currentIndex = offers[uint(currentIndex)].nextIndex;
            depth--;
        }
        if (currentIndex == -1) {
            throw;
        }
        price = offers[uint(currentIndex)].price;
        shares = offers[uint(currentIndex)].shares;
    }

    function cancelOffer(Side side, uint price, uint32 shares) {
        bool found = false;
        int16 parentIndex = -1;
        int16 currentIndex = side == Side.Bid ? topBidIndex : topAskIndex;
        while (currentIndex != -1 && !found) {
            Offer offer = offers[uint(currentIndex)];
            found = (
                offer.owner == msg.sender &&
                offer.side == side &&
                offer.price == price &&
                offer.shares >= shares
            );
            if (found) {
                break;
            }
            parentIndex = currentIndex;
            currentIndex = offer.nextIndex;
        }
        if (!found) {
            throw;
        }
        Offer matchingOffer = offers[uint(currentIndex)];
        uint32 remainingShares = shares - matchingOffer.shares;
        if (remainingShares > 0) {
            offers[uint(currentIndex)].shares -= shares;
        } else {
            matchingOffer.active = false;
            spliceOffer(side, parentIndex, matchingOffer.nextIndex);
        }
        if (side == Side.Bid) {
            balances[msg.sender] += price * shares;
        } else {
            custodian.unreserve(msg.sender, shares);
        }
    }

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

    function getBalance() returns (uint) {
        return balances[msg.sender];
    }

    function spliceOffer(Side side, int16 parentIndex, int16 nextIndex) private {
        if (parentIndex != -1) {
            offers[uint(parentIndex)].nextIndex = nextIndex;
        } else {
            if (side == Side.Bid) {
                topBidIndex = nextIndex;
            } else {
                topAskIndex = nextIndex;
            }
        }
    }

    function() {
        throw;
    }
}

contract Custodian {
    function reserve(address owner, uint amount);
    function unreserve(address owner, uint amount);
    function transfer(address oldOwner, address newOwner, uint shares);
}

contract Exchange {
    enum Side { Bid, Ask }
    struct Offer {
        address owner;
        uint price;
        bool active;
        Side side;
        int16 nextIndex;
        uint32 shares;
    }

    int32 constant maximumDepth = 1000;
    int16 topAskIndex = -1;
    int16 topBidIndex = -1;
    mapping (address => uint) balances;
    Custodian custodian;
    Offer[1000] offers;

    function Exchange() {
        custodian = Custodian(msg.sender);
    }

    function postOffer(Side side, uint price, uint32 shares) {
        if (price == 0 || shares == 0) {
            throw;
        }
        if (side == Side.Bid) {
            if (price * shares != msg.value) {
                throw;
            }
        } else {
            custodian.reserve(msg.sender, shares);
        }
        uint32 remainingShares = shares;
        int16 index = side == Side.Ask ? topBidIndex : topAskIndex;
        int16 parentIndex = -1;
        while (index != -1 && remainingShares > 0) {
            Offer next = offers[uint(index)];
            bool matches = (
                (side == Side.Bid && next.price <= price) ||
                (side == Side.Ask && next.price >= price)
            );
            if (!next.active || !matches) {
                break;
            }
            address seller = side == Side.Bid ? next.owner : msg.sender;
            address buyer = side == Side.Bid ? msg.sender : next.owner;
            if (next.shares <= remainingShares) {
                balances[seller] += next.shares * next.price;
                remainingShares -= next.shares;
                offers[uint(index)].active = false;
                spliceOffer(next.side, parentIndex, next.nextIndex);
                custodian.unreserve(seller, next.shares);
                custodian.transfer(seller, buyer, next.shares);
            } else {
                balances[seller] += remainingShares * next.price;
                offers[uint(index)].shares = next.shares - remainingShares;
                custodian.unreserve(seller, remainingShares);
                custodian.transfer(seller, buyer, remainingShares);
                remainingShares = 0;
            }
            parentIndex = index;
            index = next.nextIndex;
        }
        if (remainingShares == 0) {
            return;
        }
        int16 newIndex = 0;
        while (offers[uint(newIndex)].active) {
            if (++newIndex >= maximumDepth) {
                throw;
            }
        }
        int16 previousIndex = -1;
        int16 nextIndex = side == Side.Bid ? topBidIndex : topAskIndex;
        while (nextIndex != -1 && offers[uint(nextIndex)].price > price) {
            previousIndex = nextIndex;
            nextIndex = offers[uint(nextIndex)].nextIndex;
        }
        if (previousIndex == -1) {
            if (side == Side.Bid) {
                topBidIndex = newIndex;
            } else {
                topAskIndex = newIndex;
            }
        } else {
            offers[uint(previousIndex)].nextIndex = newIndex;
        }
        offers[uint(newIndex)] = Offer(msg.sender, price, true, side, nextIndex, remainingShares);
    }

    function getNumberOfOffers(Side side) returns (uint16) {
        uint16 count = 0;
        int16 currentIndex = side == Side.Bid ? topBidIndex : topAskIndex;
        while (currentIndex != -1) {
            count++;
            currentIndex = offers[uint(currentIndex)].nextIndex;
        }
        return count;
    }

    function getTopOffer(Side side) returns (uint price, uint32 shares) {
        int16 currentIndex = side == Side.Bid ? topBidIndex : topAskIndex;
        if (currentIndex == -1) {
            throw;
        }
        price = offers[uint(currentIndex)].price;
        shares = offers[uint(currentIndex)].shares;
    }

    function cancelOffer(Side side, uint price, uint32 shares) {
        bool found = false;
        int16 parentIndex = -1;
        int16 currentIndex = side == Side.Bid ? topBidIndex : topAskIndex;
        while (currentIndex != -1 && !found) {
            Offer offer = offers[uint(currentIndex)];
            found = (
                offer.owner == msg.sender &&
                offer.side == side &&
                offer.price == price &&
                offer.shares >= shares
            );
            if (found) {
                break;
            }
            parentIndex = currentIndex;
            currentIndex = offer.nextIndex;
        }
        if (!found) {
            throw;
        }
        Offer matchingOffer = offers[uint(currentIndex)];
        uint32 remainingShares = shares - matchingOffer.shares;
        if (remainingShares > 0) {
            offers[uint(currentIndex)].shares -= shares;
        } else {
            matchingOffer.active = false;
            spliceOffer(side, parentIndex, matchingOffer.nextIndex);
        }
        if (side == Side.Bid) {
            balances[msg.sender] += price * shares;
        } else {
            custodian.unreserve(msg.sender, shares);
        }
    }

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

    function getBalance() returns (uint) {
        return balances[msg.sender];
    }

    function spliceOffer(Side side, int16 parentIndex, int16 nextIndex) private {
        if (parentIndex != -1) {
            offers[uint(parentIndex)].nextIndex = nextIndex;
        } else {
            if (side == Side.Bid) {
                topBidIndex = nextIndex;
            } else {
                topAskIndex = nextIndex;
            }
        }
    }

    function() {
        throw;
    }
}


Simplify team allocation function

Simplify team allocation function

pragma solidity ^0.4.15;
import './ERC20Token.sol';
import './Owned.sol';

contract ENJToken is ERC20Token, Owned {

///////////////////////////////////////// VARIABLE INITIALIZATION /////////////////////////////////////////

    uint256 public totalSupply = 1 * (10**9) * 10**18;

    //  Constants
    uint256 public maxPresaleSupply = 600 * 10**6 * 10**18;           // Total presale supply at max bonus
    uint256 public minCrowdsaleAllocation = 200 * 10**6 * 10**18;     // Min amount for crowdsale
    uint256 public incentivisationAllocation = 100 * 10**6 * 10**18;  // Incentivisation Allocation
    uint256 public advisorsAllocation = 50 * 10**6 * 10**18;          // Advisors Allocation
    uint256 public enjinTeamAllocation = 50 * 10**6 * 10**18;         // Enjin Team allocation

    address public crowdFundAddress;                                  // Address of the crowdfund
    address public advisorAddress;                                    // Enjin advisor's address
    address public incentivisationFundAddress;                        // Address that holds the incentivization funds
    address public enjinTeamAddress;                                  // Enjin Team address

    //  Variables
    uint256 public totalAllocatedToAdvisors = 0;                      // Counter to keep track of total Advisor allocation
    uint256 public totalAllocatedToTeam = 0;                          // Counter to keep track of team token allocation
    uint256 public totalAllocated = 0;                                // Counter to keep track of team token allocation
    uint256 public endTime = 1509494340;                              // 10/31/2017 @ 11:59pm (UTC) crowdsale end time (in seconds)

    bool internal isReleasedToPublic = false;                         // Flag to allow transfer/transferFrom before the end of the crowdfund

    uint256 internal teamTranchesReleased = 0;                          // Track how many tranches (allocations of 12.5% team tokens) have been released
    uint256 internal maxTeamTranches = 8;                               // The number of tranches allowed to the team until depleted

///////////////////////////////////////// MODIFIERS /////////////////////////////////////////

    // Enjin Team timelock
    modifier safeTimelock() {
        require(now >= endTime + 6 * 4 weeks);
        _;
    }

    // Advisor Team timelock
    modifier advisorTimelock() {
        require(now >= endTime + 2 * 4 weeks);
        _;
    }

    // Function only accessible by the Crowdfund contract
    modifier crowdfundOnly() {
        require(msg.sender == crowdFundAddress);
        _;
    }

    ///////////////////////////////////////// CONSTRUCTOR /////////////////////////////////////////

    /**
        @dev constructor
        @param _crowdFundAddress   Crowdfund address
        @param _advisorAddress     Advisor address
    */
    function ENJToken(address _crowdFundAddress, address _advisorAddress, address _incentivisationFundAddress, address _enjinTeamAddress)
    ERC20Token("Enjin Coin", "ENJ", 18)
     {
        crowdFundAddress = _crowdFundAddress;
        advisorAddress = _advisorAddress;
        enjinTeamAddress = _enjinTeamAddress;
        incentivisationFundAddress = _incentivisationFundAddress;
        balanceOf[_crowdFundAddress] = minCrowdsaleAllocation + maxPresaleSupply; // Total presale + crowdfund tokens
        balanceOf[_incentivisationFundAddress] = incentivisationAllocation;       // 10% Allocated for Marketing and Incentivisation
        totalAllocated += incentivisationAllocation;                              // Add to total Allocated funds
    }

///////////////////////////////////////// ERC20 OVERRIDE /////////////////////////////////////////

    /**
        @dev send coins
        throws on any error rather then return a false flag to minimize user errors
        in addition to the standard checks, the function throws if transfers are disabled

        @param _to      target address
        @param _value   transfer amount

        @return true if the transfer was successful, throws if it wasn't
    */
    function transfer(address _to, uint256 _value) greaterThanZero(_value) public returns (bool success) {
        if (isTransferAllowed() == true || msg.sender == crowdFundAddress || msg.sender == incentivisationFundAddress) {
            assert(super.transfer(_to, _value));
            return true;
        }
        revert();
    }

    /**
        @dev an account/contract attempts to get the coins
        throws on any error rather then return a false flag to minimize user errors
        in addition to the standard checks, the function throws if transfers are disabled

        @param _from    source address
        @param _to      target address
        @param _value   transfer amount

        @return true if the transfer was successful, throws if it wasn't
    */
    function transferFrom(address _from, address _to, uint256 _value) greaterThanZero(_value) public returns (bool success) {
        if (isTransferAllowed() == true || msg.sender == crowdFundAddress || msg.sender == incentivisationFundAddress) {
            assert(super.transferFrom(_from, _to, _value));
            return true;
        }
        revert();
    }

///////////////////////////////////////// ALLOCATION FUNCTIONS /////////////////////////////////////////

    /**
        @dev Release one single tranche of the Enjin Team Token allocation
        throws if before timelock (6 months) ends and if not initiated by the owner of the contract
        returns true if valid
        Schedule goes as follows:
        3 months: 12.5% (this tranche can only be released after the initial 6 months has passed)
        6 months: 12.5%
        9 months: 12.5%
        12 months: 12.5%
        15 months: 12.5%
        18 months: 12.5%
        21 months: 12.5%
        24 months: 12.5%
        @return true if successful, throws if not
    */
    function releaseEnjinTeamTokens() ownerOnly returns(bool success) {
        require(totalAllocatedToTeam < enjinTeamAllocation);

        uint256 enjinTeamAlloc = enjinTeamAllocation / 1000;
        uint256 currentTranche = uint256(now - endTime) / 12 weeks;     // "months" after crowdsale end time (division floored)

        if (now > endTime + 6 * 4 weeks) {
            if(teamTranchesReleased < maxTeamTranches && currentTranche > teamTranchesReleased) {
                teamTranchesReleased++;
                transferTeamAllocation(safeMul(enjinTeamAlloc, 125));
            }
            return true;
        }
        revert();
    }

    /**
        @dev transfers Tokens from Enjin allocation to Team
        throws if before first timelock (6 months) ends and if no initiated by the owner of the contract
        @return true if successful, throws if not
    */
    function transferTeamAllocation(uint256 _amount) ownerOnly internal {
        balanceOf[enjinTeamAddress] = safeAdd(balanceOf[enjinTeamAddress], _amount);
        Transfer(this, enjinTeamAddress, _amount);
        totalAllocated = safeAdd(totalAllocated, _amount);
        totalAllocatedToTeam = safeAdd(totalAllocatedToTeam, _amount);
    }

    /**
        @dev release Advisors Token allocation
        throws if before timelock (2 months) ends or if no initiated by the advisors address
        or if there is no more allocation to give out
        returns true if valid

        @return true if successful, throws if not
    */
    function releaseAdvisorTokens() advisorTimelock ownerOnly returns(bool success) {
        require(totalAllocatedToAdvisors == 0);
        balanceOf[advisorAddress] = safeAdd(balanceOf[advisorAddress], advisorsAllocation);
        Transfer(this, advisorAddress, advisorsAllocation);
        totalAllocated = safeAdd(totalAllocated, advisorsAllocation);
        totalAllocatedToAdvisors = advisorsAllocation;
        return true;
    }

    /**
        @dev Retrieve unsold tokens from the crowdfund
        throws if before timelock (6 months from end of Crowdfund) ends and if no initiated by the owner of the contract
        returns true if valid

        @return true if successful, throws if not
    */
    function retrieveUnsoldTokens() safeTimelock ownerOnly returns(bool success) {
        uint256 amountOfTokens = balanceOf[crowdFundAddress];
        balanceOf[incentivisationFundAddress] = safeAdd(balanceOf[incentivisationFundAddress], amountOfTokens);
        totalAllocated = safeAdd(totalAllocated, amountOfTokens);
        balanceOf[crowdFundAddress] = 0;
        return true;
    }

    /**
        @dev Keep track of token allocations
        can only be called by the crowdfund contract
    */
    function addToAllocation(uint256 _amount) crowdfundOnly {
        totalAllocated = safeAdd(totalAllocated, _amount);
    }

    /**
        @dev Function to allow transfers
        can only be called by the owner of the contract
        Transfers will be allowed regardless after the crowdfund end time.
    */
    function allowTransfers() ownerOnly {
        isReleasedToPublic = true;
    }

    /**
        @dev User transfers are allowed/rejected
        Transfers are forbidden before the end of the crowdfund
    */
    function isTransferAllowed() internal returns(bool) {
        if (now > endTime || isReleasedToPublic == true) {
            return true;
        }
        return false;
    }

    function () {
        revert();
    }
}

pragma solidity ^0.4.15;
import './ERC20Token.sol';
import './Owned.sol';

contract ENJToken is ERC20Token, Owned {

///////////////////////////////////////// VARIABLE INITIALIZATION /////////////////////////////////////////

    uint256 public totalSupply = 1 * (10**9) * 10**18;

    //  Constants
    uint256 public maxPresaleSupply = 600 * 10**6 * 10**18;           // Total presale supply at max bonus
    uint256 public minCrowdsaleAllocation = 200 * 10**6 * 10**18;     // Min amount for crowdsale
    uint256 public incentivisationAllocation = 100 * 10**6 * 10**18;  // Incentivisation Allocation
    uint256 public advisorsAllocation = 50 * 10**6 * 10**18;          // Advisors Allocation
    uint256 public enjinTeamAllocation = 50 * 10**6 * 10**18;         // Enjin Team allocation

    address public crowdFundAddress;                                  // Address of the crowdfund
    address public advisorAddress;                                    // Enjin advisor's address
    address public incentivisationFundAddress;                        // Address that holds the incentivization funds
    address public enjinTeamAddress;                                  // Enjin Team address

    //  Variables
    uint256 public totalAllocatedToAdvisors = 0;                      // Counter to keep track of total Advisor allocation
    uint256 public totalAllocatedToTeam = 0;                          // Counter to keep track of team token allocation
    uint256 public totalAllocated = 0;                                // Counter to keep track of team token allocation
    uint256 public endTime = 1509494340;                              // 10/31/2017 @ 11:59pm (UTC) crowdsale end time (in seconds)

    bool internal isReleasedToPublic = false;                         // Flag to allow transfer/transferFrom before the end of the crowdfund

    bool internal releaseFirstAllocationTranche = false;              // Flags to keep track of Team allocation tranches
    bool internal releaseSecondAllocationTranche = false;             // Flags to keep track of Team allocation tranches
    bool internal releaseThirdAllocationTranche = false;              // Flags to keep track of Team allocation tranches
    bool internal releaseFourthAllocationTranche = false;             // Flags to keep track of Team allocation tranches
    bool internal releaseFifthAllocationTranche = false;              // Flags to keep track of Team allocation tranches
    bool internal releaseSixthAllocationTranche = false;              // Flags to keep track of Team allocation tranches
    bool internal releaseSeventhAllocationTranche = false;            // Flags to keep track of Team allocation tranches

///////////////////////////////////////// MODIFIERS /////////////////////////////////////////

    // Enjin Team timelock
    modifier safeTimelock() {
        require(now >= endTime + 6 * 4 weeks);
        _;
    }

    // Advisor Team timelock
    modifier advisorTimelock() {
        require(now >= endTime + 2 * 4 weeks);
        _;
    }

    // Function only accessible by the Crowdfund contract
    modifier crowdfundOnly() {
        require(msg.sender == crowdFundAddress);
        _;
    }

    ///////////////////////////////////////// CONSTRUCTOR /////////////////////////////////////////

    /**
        @dev constructor
        @param _crowdFundAddress   Crowdfund address
        @param _advisorAddress     Advisor address
    */
    function ENJToken(address _crowdFundAddress, address _advisorAddress, address _incentivisationFundAddress, address _enjinTeamAddress)
    ERC20Token("Enjin Coin", "ENJ", 18)
     {
        crowdFundAddress = _crowdFundAddress;
        advisorAddress = _advisorAddress;
        enjinTeamAddress = _enjinTeamAddress;
        incentivisationFundAddress = _incentivisationFundAddress;
        balanceOf[_crowdFundAddress] = minCrowdsaleAllocation + maxPresaleSupply; // Total presale + crowdfund tokens
        balanceOf[_incentivisationFundAddress] = incentivisationAllocation;       // 10% Allocated for Marketing and Incentivisation
        totalAllocated += incentivisationAllocation;                              // Add to total Allocated funds
    }

///////////////////////////////////////// ERC20 OVERRIDE /////////////////////////////////////////

    /**
        @dev send coins
        throws on any error rather then return a false flag to minimize user errors
        in addition to the standard checks, the function throws if transfers are disabled

        @param _to      target address
        @param _value   transfer amount

        @return true if the transfer was successful, throws if it wasn't
    */
    function transfer(address _to, uint256 _value) greaterThanZero(_value) public returns (bool success) {
        if (isTransferAllowed() == true || msg.sender == crowdFundAddress || msg.sender == incentivisationFundAddress) {
            assert(super.transfer(_to, _value));
            return true;
        }
        revert();
    }

    /**
        @dev an account/contract attempts to get the coins
        throws on any error rather then return a false flag to minimize user errors
        in addition to the standard checks, the function throws if transfers are disabled

        @param _from    source address
        @param _to      target address
        @param _value   transfer amount

        @return true if the transfer was successful, throws if it wasn't
    */
    function transferFrom(address _from, address _to, uint256 _value) greaterThanZero(_value) public returns (bool success) {
        if (isTransferAllowed() == true || msg.sender == crowdFundAddress || msg.sender == incentivisationFundAddress) {
            assert(super.transferFrom(_from, _to, _value));
            return true;
        }
        revert();
    }

///////////////////////////////////////// ALLOCATION FUNCTIONS /////////////////////////////////////////

    /**
        @dev release Enjin Team Token allocation
        throws if before timelock (6 months) ends and if no initiated by the owner of the contract
        returns true if valid
        Schedule goes as follows:
        6 months: 25%
        9 months: 12.5%
        12 months: 12.5%
        15 months: 12.5%
        18 months: 12.5%
        21 months: 12.5%
        24 months: 12.5%
        @return true if successful, throws if not
    */
    function releaseEnjinTeamTokens() ownerOnly returns(bool success) {
        require(totalAllocatedToTeam < enjinTeamAllocation);
        uint256 enjinTeamAlloc = enjinTeamAllocation / 1000;

        if (now > endTime + 6 * 4 weeks && !releaseFirstAllocationTranche) {
            releaseFirstAllocationTranche = true;
            transferTeamAllocation(safeMul(enjinTeamAlloc, 250));
            return true;
        } else  if (now > endTime + 9 * 4 weeks && !releaseSecondAllocationTranche) {
            releaseSecondAllocationTranche = true;
            transferTeamAllocation(safeMul(enjinTeamAlloc, 125));
            return true;
        } else  if (now > endTime + 12 * 4 weeks && !releaseThirdAllocationTranche) {
            releaseThirdAllocationTranche = true;
            transferTeamAllocation(safeMul(enjinTeamAlloc, 125));
            return true;
        } else  if (now > endTime + 15 * 4 weeks && !releaseFourthAllocationTranche) {
            releaseFourthAllocationTranche = true;
            transferTeamAllocation(safeMul(enjinTeamAlloc, 125));
            return true;
        } else  if (now > endTime + 18 * 4 weeks && !releaseFifthAllocationTranche) {
            releaseFifthAllocationTranche = true;
            transferTeamAllocation(safeMul(enjinTeamAlloc, 125));
            return true;
        } else  if (now > endTime + 21 * 4 weeks && !releaseSixthAllocationTranche) {
            releaseSixthAllocationTranche = true;
            transferTeamAllocation(safeMul(enjinTeamAlloc, 125));
            return true;
        } else  if (now > endTime + 24 * 4 weeks && !releaseSeventhAllocationTranche) {
            releaseSeventhAllocationTranche = true;
            transferTeamAllocation(safeMul(enjinTeamAlloc, 125));
            return true;
        }
        revert();
    }

    /**
        @dev transfers Tokens from Enjin allocation to Team
        throws if before first timelock (6 months) ends and if no initiated by the owner of the contract
        @return true if successful, throws if not
    */
    function transferTeamAllocation(uint256 _amount) ownerOnly internal {
        balanceOf[enjinTeamAddress] = safeAdd(balanceOf[enjinTeamAddress], _amount);
        Transfer(this, enjinTeamAddress, _amount);
        totalAllocated = safeAdd(totalAllocated, _amount);
        totalAllocatedToTeam = safeAdd(totalAllocatedToTeam, _amount);
    }

    /**
        @dev release Advisors Token allocation
        throws if before timelock (2 months) ends or if no initiated by the advisors address
        or if there is no more allocation to give out
        returns true if valid

        @return true if successful, throws if not
    */
    function releaseAdvisorTokens() advisorTimelock ownerOnly returns(bool success) {
        require(totalAllocatedToAdvisors == 0);
        balanceOf[advisorAddress] = safeAdd(balanceOf[advisorAddress], advisorsAllocation);
        Transfer(this, advisorAddress, advisorsAllocation);
        totalAllocated = safeAdd(totalAllocated, advisorsAllocation);
        totalAllocatedToAdvisors = advisorsAllocation;
        return true;
    }

    /**
        @dev Retrive unsold tokens from the crowdfund
        throws if before timelock (6 months from end of Crowdfund) ends and if no initiated by the owner of the contract
        returns true if valid

        @return true if successful, throws if not
    */
    function retrieveUnsoldTokens() safeTimelock ownerOnly returns(bool success) {
        uint256 amountOfTokens = balanceOf[crowdFundAddress];
        balanceOf[incentivisationFundAddress] = safeAdd(balanceOf[incentivisationFundAddress], amountOfTokens);
        totalAllocated = safeAdd(totalAllocated, amountOfTokens);
        balanceOf[crowdFundAddress] = 0;
        return true;
    }

    /**
        @dev Keep track of token allocations
        can only be called by the crowdfund contract
    */
    function addToAllocation(uint256 _amount) crowdfundOnly {
        totalAllocated = safeAdd(totalAllocated, _amount);
    }

    /**
        @dev Function to allow transfers
        can only be called by the owner of the contract
        Transfers will be allowed regardless after the crowdfund end time.
    */
    function allowTransfers() ownerOnly {
        isReleasedToPublic = true;
    }

    /**
        @dev User transfers are allowed/rejected
        Transfers are forbidden before the end of the crowdfund
    */
    function isTransferAllowed() internal returns(bool) {
        if (now > endTime || isReleasedToPublic == true) {
            return true;
        }
        return false;
    }

    function () {
        revert();
    }
}


remove UserCreation event

remove UserCreation event

pragma solidity ^0.4.0;

import "./Concept.sol";
import "./ConceptRegistry.sol";

/*
@type: contract
@name: UserRegistry
@purpose: To store data about users for easy, secure access and manage token balances
*/
contract UserRegistry {
  address public conceptRegistry; //Tnce
  mapping (address => uint) public balances; //Maps the addresses of users to their token balances
  mapping (address => bool) public availability;
  mapping (address => mapping (address => uint)) public allowed;
  bool firstUserMade = false; //Keeps track of whether or not the first user has been made yet
  event Notification(address user, address sender, uint topic);
    /*
      0 = You've started an assessment
      1 = Called As A Potential Assessor
      2 = Confirmed for assessing, stake has been taken
      3 = Assessment Cancled and you have been refunded
      4 = Assessment Has Started
      5 = Send in Score
      6 = Payout
    */

  modifier onlyConcept() {
    if(ConceptRegistry(conceptRegistry).conceptExists(msg.sender) == false)
    {
      throw;
    }
    _;
  }

  modifier onlyThis() {
    if(msg.sender != address(this))
    {
      throw;
    }
    _;
  }

  function UserRegistry(address _conceptRegistry) {
    conceptRegistry = _conceptRegistry;
  }

  function toggleAvailability() {
    availability[msg.sender] = !availability[msg.sender];
  }

  function notification(address user, uint topic) {
    Notification(user, msg.sender, topic);
  }

  function firstUser(address userAddress) {
    if(firstUserMade == false) {
      Concept(ConceptRegistry(conceptRegistry).mewAddress()).addFirstUser(userAddress);
      balances[userAddress] = 1000;
    }
  }

  //@purpose: To preform payouts in Asessments
  function addBalance(address _to, uint _amount) returns(bool) {
    if(balances[_to] + _amount > balances[_to]){
      balances[_to] += _amount;
      return true;
    }
    else {
      return false;
    }
  }

  //@purpose: To preform payments and staking for assessments
  function subtractBalance(address _from, uint _amount) returns(bool) {
    if(balances[_from] > _amount){
      balances[_from] -= _amount;
      return true;
    }
    return false;
  }

  function transfer(address _to, uint _amount) returns(bool) {
    if(balances[msg.sender] > _amount &&
       balances[_to] + _amount > balances[_to]) {
      balances[msg.sender] -= _amount;
      balances[_to] += _amount;
      return true;
    }
    else {
      return false;
    }
  }

  function approve(address _spender, uint _amount) returns(bool) {
      allowed[msg.sender][_spender] = _amount;
      return true;
  }

  function transferFrom(address _from, address _to, uint _amount) returns(bool) {
    if(allowed[_from][msg.sender] > _amount &&
       balances[_from] > _amount &&
       balances[_to] > balances[_to] + _amount) {
        balances[_from] -= _amount;
        balances[_to] += _amount;
        allowed[_from][msg.sender] -= _amount;
        return true;
    }
    else {
        return false;
    }
  }

  function remove(address reciever) onlyThis() {
    suicide(reciever);
  }
}

pragma solidity ^0.4.0;

import "./Concept.sol";
import "./ConceptRegistry.sol";

/*
@type: contract
@name: UserRegistry
@purpose: To store data about users for easy, secure access and manage token balances
*/
contract UserRegistry {
  address public conceptRegistry; //Tnce
  mapping (address => uint) public balances; //Maps the addresses of users to their token balances
  mapping (address => bool) public availability;
  mapping (address => mapping (address => uint)) public allowed;
  bool firstUserMade = false; //Keeps track of whether or not the first user has been made yet
  event UserCreation(address _userAddress); //address of the created user contract
  event Notification(address user, address sender, uint topic);
    /*
      0 = You've started an assessment
      1 = Called As A Potential Assessor
      2 = Confirmed for assessing, stake has been taken
      3 = Assessment Cancled and you have been refunded
      4 = Assessment Has Started
      5 = Send in Score
      6 = Payout
    */

  modifier onlyConcept() {
    if(ConceptRegistry(conceptRegistry).conceptExists(msg.sender) == false)
    {
      throw;
    }
    _;
  }

  modifier onlyThis() {
    if(msg.sender != address(this))
    {
      throw;
    }
    _;
  }

  function UserRegistry(address _conceptRegistry) {
    conceptRegistry = _conceptRegistry;
  }

  function toggleAvailability() {
    availability[msg.sender] = !availability[msg.sender];
  }

  function notification(address user, uint topic) {
    Notification(user, msg.sender, topic);
  }

  function firstUser(address userAddress) {
    if(firstUserMade == false) {
      Concept(ConceptRegistry(conceptRegistry).mewAddress()).addFirstUser(userAddress);
      balances[userAddress] = 1000;
      UserCreation(userAddress); //Makes a new UserCreation event with the address of the newly created user
    }
  }

  //@purpose: To preform payouts in Asessments
  function addBalance(address _to, uint _amount) returns(bool) {
    if(balances[_to] + _amount > balances[_to]){
      balances[_to] += _amount;
      return true;
    }
    else {
      return false;
    }
  }

  //@purpose: To preform payments and staking for assessments
  function subtractBalance(address _from, uint _amount) returns(bool) {
    if(balances[_from] > _amount){
      balances[_from] -= _amount;
      return true;
    }
    return false;
  }

  function transfer(address _to, uint _amount) returns(bool) {
    if(balances[msg.sender] > _amount &&
       balances[_to] + _amount > balances[_to]) {
      balances[msg.sender] -= _amount;
      balances[_to] += _amount;
      return true;
    }
    else {
      return false;
    }
  }

  function approve(address _spender, uint _amount) returns(bool) {
      allowed[msg.sender][_spender] = _amount;
      return true;
  }

  function transferFrom(address _from, address _to, uint _amount) returns(bool) {
    if(allowed[_from][msg.sender] > _amount &&
       balances[_from] > _amount &&
       balances[_to] > balances[_to] + _amount) {
        balances[_from] -= _amount;
        balances[_to] += _amount;
        allowed[_from][msg.sender] -= _amount;
        return true;
    }
    else {
        return false;
    }
  }

  function remove(address reciever) onlyThis() {
    suicide(reciever);
  }
}


Fix a grammatical error in a comment (#2352)

changed a comment in the isContract function to make it grammatically right.

// SPDX-License-Identifier: MIT

pragma solidity ^0.6.2;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        // solhint-disable-next-line no-inline-assembly
        assembly { size := extcodesize(account) }
        return size > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (bool success, ) = recipient.call{ value: amount }("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain`call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
      return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
        return _functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        return _functionCallWithValue(target, data, value, errorMessage);
    }

    function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) {
        require(isContract(target), "Address: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.call{ value: weiValue }(data);
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.6.2;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies in extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        // solhint-disable-next-line no-inline-assembly
        assembly { size := extcodesize(account) }
        return size > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (bool success, ) = recipient.call{ value: amount }("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain`call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
      return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
        return _functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        return _functionCallWithValue(target, data, value, errorMessage);
    }

    function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) {
        require(isContract(target), "Address: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.call{ value: weiValue }(data);
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}