Fix https://github.com/code-423n4/2022-07-ens-findings/issues/201

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
pragma experimental ABIEncoderV2;

import "./Owned.sol";
import "./BytesUtils.sol";
import "./RRUtils.sol";
import "./DNSSEC.sol";
import "./algorithms/Algorithm.sol";
import "./digests/Digest.sol";
import "@ensdomains/buffer/contracts/Buffer.sol";

/*
 * @dev An oracle contract that verifies and stores DNSSEC-validated DNS records.
 */
contract DNSSECImpl is DNSSEC, Owned {
    using Buffer for Buffer.buffer;
    using BytesUtils for bytes;
    using RRUtils for *;

    uint16 constant DNSCLASS_IN = 1;

    uint16 constant DNSTYPE_DS = 43;
    uint16 constant DNSTYPE_DNSKEY = 48;

    uint256 constant DNSKEY_FLAG_ZONEKEY = 0x100;

    error InvalidLabelCount(bytes name, uint256 labelsExpected);
    error SignatureNotValidYet(uint32 inception, uint32 now);
    error SignatureExpired(uint32 expiration, uint32 now);
    error InvalidClass(uint16 class);
    error InvalidRRSet();
    error SignatureTypeMismatch(uint16 rrsetType, uint16 sigType);
    error InvalidSignerName(bytes rrsetName, bytes signerName);
    error InvalidProofType(uint16 proofType);
    error ProofNameMismatch(bytes signerName, bytes proofName);
    error NoMatchingProof(bytes signerName);

    mapping(uint8 => Algorithm) public algorithms;
    mapping(uint8 => Digest) public digests;

    /**
     * @dev Constructor.
     * @param _anchors The binary format RR entries for the root DS records.
     */
    constructor(bytes memory _anchors) {
        // Insert the 'trust anchors' - the key hashes that start the chain
        // of trust for all other records.
        anchors = _anchors;
    }

    /**
     * @dev Sets the contract address for a signature verification algorithm.
     *      Callable only by the owner.
     * @param id The algorithm ID
     * @param algo The address of the algorithm contract.
     */
    function setAlgorithm(uint8 id, Algorithm algo) public owner_only {
        algorithms[id] = algo;
        emit AlgorithmUpdated(id, address(algo));
    }

    /**
     * @dev Sets the contract address for a digest verification algorithm.
     *      Callable only by the owner.
     * @param id The digest ID
     * @param digest The address of the digest contract.
     */
    function setDigest(uint8 id, Digest digest) public owner_only {
        digests[id] = digest;
        emit DigestUpdated(id, address(digest));
    }

    /**
     * @dev Takes a chain of signed DNS records, verifies them, and returns the data from the last record set in the chain.
     *      Reverts if the records do not form an unbroken chain of trust to the DNSSEC anchor records.
     * @param input A list of signed RRSets.
     * @return rrs The RRData from the last RRSet in the chain.
     * @return inception The inception time of the signed record set.
     */
    function verifyRRSet(RRSetWithSignature[] memory input)
        external
        view
        virtual
        override
        returns (bytes memory rrs, uint32 inception)
    {
        return verifyRRSet(input, block.timestamp);
    }

    /**
     * @dev Takes a chain of signed DNS records, verifies them, and returns the data from the last record set in the chain.
     *      Reverts if the records do not form an unbroken chain of trust to the DNSSEC anchor records.
     * @param input A list of signed RRSets.
     * @param now The Unix timestamp to validate the records at.
     * @return rrs The RRData from the last RRSet in the chain.
     * @return inception The inception time of the signed record set.
     */
    function verifyRRSet(RRSetWithSignature[] memory input, uint256 now)
        public
        view
        virtual
        override
        returns (bytes memory rrs, uint32 inception)
    {
        bytes memory proof = anchors;
        for (uint256 i = 0; i < input.length; i++) {
            RRUtils.SignedSet memory rrset = validateSignedSet(
                input[i],
                proof,
                now
            );
            proof = rrset.data;
            inception = rrset.inception;
        }
        return (proof, inception);
    }

    /**
     * @dev Validates an RRSet against the already trusted RR provided in `proof`.
     *
     * @param input The signed RR set. This is in the format described in section
     *        5.3.2 of RFC4035: The RRDATA section from the RRSIG without the signature
     *        data, followed by a series of canonicalised RR records that the signature
     *        applies to.
     * @param proof The DNSKEY or DS to validate the signature against.
     * @param now The current timestamp.
     */
    function validateSignedSet(
        RRSetWithSignature memory input,
        bytes memory proof,
        uint256 now
    ) internal view returns (RRUtils.SignedSet memory rrset) {
        rrset = input.rrset.readSignedSet();

        // Do some basic checks on the RRs and extract the name
        bytes memory name = validateRRs(rrset, rrset.typeCovered);
        if (name.labelCount(0) != rrset.labels) {
            revert InvalidLabelCount(name, rrset.labels);
        }
        rrset.name = name;

        // All comparisons involving the Signature Expiration and
        // Inception fields MUST use "serial number arithmetic", as
        // defined in RFC 1982

        // o  The validator's notion of the current time MUST be less than or
        //    equal to the time listed in the RRSIG RR's Expiration field.
        if (!RRUtils.serialNumberGte(rrset.expiration, uint32(now))) {
            revert SignatureExpired(rrset.expiration, uint32(now));
        }

        // o  The validator's notion of the current time MUST be greater than or
        //    equal to the time listed in the RRSIG RR's Inception field.
        if (!RRUtils.serialNumberGte(uint32(now), rrset.inception)) {
            revert SignatureNotValidYet(rrset.inception, uint32(now));
        }

        // Validate the signature
        verifySignature(name, rrset, input, proof);

        return rrset;
    }

    /**
     * @dev Validates a set of RRs.
     * @param rrset The RR set.
     * @param typecovered The type covered by the RRSIG record.
     */
    function validateRRs(RRUtils.SignedSet memory rrset, uint16 typecovered)
        internal
        pure
        returns (bytes memory name)
    {
        // Iterate over all the RRs
        for (
            RRUtils.RRIterator memory iter = rrset.rrs();
            !iter.done();
            iter.next()
        ) {
            // We only support class IN (Internet)
            if (iter.class != DNSCLASS_IN) {
                revert InvalidClass(iter.class);
            }

            if (name.length == 0) {
                name = iter.name();
            } else {
                // Name must be the same on all RRs. We do things this way to avoid copying the name
                // repeatedly.
                if (
                    name.length != iter.data.nameLength(iter.offset) ||
                    !name.equals(0, iter.data, iter.offset, name.length)
                ) {
                    revert InvalidRRSet();
                }
            }

            // o  The RRSIG RR's Type Covered field MUST equal the RRset's type.
            if (iter.dnstype != typecovered) {
                revert SignatureTypeMismatch(iter.dnstype, typecovered);
            }
        }
    }

    /**
     * @dev Performs signature verification.
     *
     * Throws or reverts if unable to verify the record.
     *
     * @param name The name of the RRSIG record, in DNS label-sequence format.
     * @param data The original data to verify.
     * @param proof A DS or DNSKEY record that's already verified by the oracle.
     */
    function verifySignature(
        bytes memory name,
        RRUtils.SignedSet memory rrset,
        RRSetWithSignature memory data,
        bytes memory proof
    ) internal view {
        // o  The RRSIG RR's Signer's Name field MUST be the name of the zone
        //    that contains the RRset.
        if (
            rrset.signerName.length > name.length ||
            !rrset.signerName.equals(
                0,
                name,
                name.length - rrset.signerName.length
            )
        ) {
            revert InvalidSignerName(name, rrset.signerName);
        }

        RRUtils.RRIterator memory proofRR = proof.iterateRRs(0);
        // Check the proof
        if (proofRR.dnstype == DNSTYPE_DS) {
            verifyWithDS(rrset, data, proofRR);
        } else if (proofRR.dnstype == DNSTYPE_DNSKEY) {
            verifyWithKnownKey(rrset, data, proofRR);
        } else {
            revert InvalidProofType(proofRR.dnstype);
        }
    }

    /**
     * @dev Attempts to verify a signed RRSET against an already known public key.
     * @param rrset The signed set to verify.
     * @param data The original data the signed set was read from.
     * @param proof The serialized DS or DNSKEY record to use as proof.
     */
    function verifyWithKnownKey(
        RRUtils.SignedSet memory rrset,
        RRSetWithSignature memory data,
        RRUtils.RRIterator memory proof
    ) internal view {
        // Check the DNSKEY's owner name matches the signer name on the RRSIG
        for (; !proof.done(); proof.next()) {
            bytes memory proofName = proof.name();
            if (!proofName.equals(rrset.signerName)) {
                revert ProofNameMismatch(rrset.signerName, proofName);
            }

            bytes memory keyrdata = proof.rdata();
            RRUtils.DNSKEY memory dnskey = keyrdata.readDNSKEY(
                0,
                keyrdata.length
            );
            if (verifySignatureWithKey(dnskey, keyrdata, rrset, data)) {
                return;
            }
        }
        revert NoMatchingProof(rrset.signerName);
    }

    /**
     * @dev Attempts to verify some data using a provided key and a signature.
     * @param dnskey The dns key record to verify the signature with.
     * @param rrset The signed RRSET being verified.
     * @param data The original data `rrset` was decoded from.
     * @return True iff the key verifies the signature.
     */
    function verifySignatureWithKey(
        RRUtils.DNSKEY memory dnskey,
        bytes memory keyrdata,
        RRUtils.SignedSet memory rrset,
        RRSetWithSignature memory data
    ) internal view returns (bool) {
        // TODO: Check key isn't expired, unless updating key itself

        // The Protocol Field MUST have value 3 (RFC4034 2.1.2)
        if (dnskey.protocol != 3) {
            return false;
        }

        // o The RRSIG RR's Signer's Name, Algorithm, and Key Tag fields MUST
        //   match the owner name, algorithm, and key tag for some DNSKEY RR in
        //   the zone's apex DNSKEY RRset.
        if (dnskey.algorithm != rrset.algorithm) {
            return false;
        }
        uint16 computedkeytag = keyrdata.computeKeytag();
        if (computedkeytag != rrset.keytag) {
            return false;
        }

        // o The matching DNSKEY RR MUST be present in the zone's apex DNSKEY
        //   RRset, and MUST have the Zone Flag bit (DNSKEY RDATA Flag bit 7)
        //   set.
        if (dnskey.flags & DNSKEY_FLAG_ZONEKEY == 0) {
            return false;
        }

        Algorithm algorithm = algorithms[dnskey.algorithm];
        if(address(algorithm) == address(0)) {
            return false;
        }
        return algorithm.verify(keyrdata, data.rrset, data.sig);
    }

    /**
     * @dev Attempts to verify a signed RRSET against an already known hash. This function assumes
     *      that the record
     * @param rrset The signed set to verify.
     * @param data The original data the signed set was read from.
     * @param proof The serialized DS or DNSKEY record to use as proof.
     */
    function verifyWithDS(
        RRUtils.SignedSet memory rrset,
        RRSetWithSignature memory data,
        RRUtils.RRIterator memory proof
    ) internal view {
        for (
            RRUtils.RRIterator memory iter = rrset.rrs();
            !iter.done();
            iter.next()
        ) {
            if (iter.dnstype != DNSTYPE_DNSKEY) {
                revert InvalidProofType(iter.dnstype);
            }

            bytes memory keyrdata = iter.rdata();
            RRUtils.DNSKEY memory dnskey = keyrdata.readDNSKEY(
                0,
                keyrdata.length
            );
            if (verifySignatureWithKey(dnskey, keyrdata, rrset, data)) {
                // It's self-signed - look for a DS record to verify it.
                if (
                    verifyKeyWithDS(rrset.signerName, proof, dnskey, keyrdata)
                ) {
                    return;
                }
            }
        }
        revert NoMatchingProof(rrset.signerName);
    }

    /**
     * @dev Attempts to verify a key using DS records.
     * @param keyname The DNS name of the key, in DNS label-sequence format.
     * @param dsrrs The DS records to use in verification.
     * @param dnskey The dnskey to verify.
     * @param keyrdata The RDATA section of the key.
     * @return True if a DS record verifies this key.
     */
    function verifyKeyWithDS(
        bytes memory keyname,
        RRUtils.RRIterator memory dsrrs,
        RRUtils.DNSKEY memory dnskey,
        bytes memory keyrdata
    ) internal view returns (bool) {
        uint16 keytag = keyrdata.computeKeytag();
        for (; !dsrrs.done(); dsrrs.next()) {
            bytes memory proofName = dsrrs.name();
            if (!proofName.equals(keyname)) {
                revert ProofNameMismatch(keyname, proofName);
            }

            RRUtils.DS memory ds = dsrrs.data.readDS(
                dsrrs.rdataOffset,
                dsrrs.nextOffset - dsrrs.rdataOffset
            );
            if (ds.keytag != keytag) {
                continue;
            }
            if (ds.algorithm != dnskey.algorithm) {
                continue;
            }

            Buffer.buffer memory buf;
            buf.init(keyname.length + keyrdata.length);
            buf.append(keyname);
            buf.append(keyrdata);
            if (verifyDSHash(ds.digestType, buf.buf, ds.digest)) {
                return true;
            }
        }
        return false;
    }

    /**
     * @dev Attempts to verify a DS record's hash value against some data.
     * @param digesttype The digest ID from the DS record.
     * @param data The data to digest.
     * @param digest The digest data to check against.
     * @return True iff the digest matches.
     */
    function verifyDSHash(
        uint8 digesttype,
        bytes memory data,
        bytes memory digest
    ) internal view returns (bool) {
        if (address(digests[digesttype]) == address(0)) {
            return false;
        }
        return digests[digesttype].verify(data, digest);
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
pragma experimental ABIEncoderV2;

import "./Owned.sol";
import "./BytesUtils.sol";
import "./RRUtils.sol";
import "./DNSSEC.sol";
import "./algorithms/Algorithm.sol";
import "./digests/Digest.sol";
import "@ensdomains/buffer/contracts/Buffer.sol";

/*
 * @dev An oracle contract that verifies and stores DNSSEC-validated DNS records.
 */
contract DNSSECImpl is DNSSEC, Owned {
    using Buffer for Buffer.buffer;
    using BytesUtils for bytes;
    using RRUtils for *;

    uint16 constant DNSCLASS_IN = 1;

    uint16 constant DNSTYPE_DS = 43;
    uint16 constant DNSTYPE_DNSKEY = 48;

    uint256 constant DNSKEY_FLAG_ZONEKEY = 0x100;

    error InvalidLabelCount(bytes name, uint256 labelsExpected);
    error SignatureNotValidYet(uint32 inception, uint32 now);
    error SignatureExpired(uint32 expiration, uint32 now);
    error InvalidClass(uint16 class);
    error InvalidRRSet();
    error SignatureTypeMismatch(uint16 rrsetType, uint16 sigType);
    error InvalidSignerName(bytes rrsetName, bytes signerName);
    error InvalidProofType(uint16 proofType);
    error ProofNameMismatch(bytes signerName, bytes proofName);
    error NoMatchingProof(bytes signerName);

    mapping(uint8 => Algorithm) public algorithms;
    mapping(uint8 => Digest) public digests;

    /**
     * @dev Constructor.
     * @param _anchors The binary format RR entries for the root DS records.
     */
    constructor(bytes memory _anchors) {
        // Insert the 'trust anchors' - the key hashes that start the chain
        // of trust for all other records.
        anchors = _anchors;
    }

    /**
     * @dev Sets the contract address for a signature verification algorithm.
     *      Callable only by the owner.
     * @param id The algorithm ID
     * @param algo The address of the algorithm contract.
     */
    function setAlgorithm(uint8 id, Algorithm algo) public owner_only {
        algorithms[id] = algo;
        emit AlgorithmUpdated(id, address(algo));
    }

    /**
     * @dev Sets the contract address for a digest verification algorithm.
     *      Callable only by the owner.
     * @param id The digest ID
     * @param digest The address of the digest contract.
     */
    function setDigest(uint8 id, Digest digest) public owner_only {
        digests[id] = digest;
        emit DigestUpdated(id, address(digest));
    }

    /**
     * @dev Takes a chain of signed DNS records, verifies them, and returns the data from the last record set in the chain.
     *      Reverts if the records do not form an unbroken chain of trust to the DNSSEC anchor records.
     * @param input A list of signed RRSets.
     * @return rrs The RRData from the last RRSet in the chain.
     * @return inception The inception time of the signed record set.
     */
    function verifyRRSet(RRSetWithSignature[] memory input)
        external
        view
        virtual
        override
        returns (bytes memory rrs, uint32 inception)
    {
        return verifyRRSet(input, block.timestamp);
    }

    /**
     * @dev Takes a chain of signed DNS records, verifies them, and returns the data from the last record set in the chain.
     *      Reverts if the records do not form an unbroken chain of trust to the DNSSEC anchor records.
     * @param input A list of signed RRSets.
     * @param now The Unix timestamp to validate the records at.
     * @return rrs The RRData from the last RRSet in the chain.
     * @return inception The inception time of the signed record set.
     */
    function verifyRRSet(RRSetWithSignature[] memory input, uint256 now)
        public
        view
        virtual
        override
        returns (bytes memory rrs, uint32 inception)
    {
        bytes memory proof = anchors;
        for (uint256 i = 0; i < input.length; i++) {
            RRUtils.SignedSet memory rrset = validateSignedSet(
                input[i],
                proof,
                now
            );
            proof = rrset.data;
            inception = rrset.inception;
        }
        return (proof, inception);
    }

    /**
     * @dev Validates an RRSet against the already trusted RR provided in `proof`.
     *
     * @param input The signed RR set. This is in the format described in section
     *        5.3.2 of RFC4035: The RRDATA section from the RRSIG without the signature
     *        data, followed by a series of canonicalised RR records that the signature
     *        applies to.
     * @param proof The DNSKEY or DS to validate the signature against.
     * @param now The current timestamp.
     */
    function validateSignedSet(
        RRSetWithSignature memory input,
        bytes memory proof,
        uint256 now
    ) internal view returns (RRUtils.SignedSet memory rrset) {
        rrset = input.rrset.readSignedSet();

        // Do some basic checks on the RRs and extract the name
        bytes memory name = validateRRs(rrset, rrset.typeCovered);
        if (name.labelCount(0) != rrset.labels) {
            revert InvalidLabelCount(name, rrset.labels);
        }
        rrset.name = name;

        // All comparisons involving the Signature Expiration and
        // Inception fields MUST use "serial number arithmetic", as
        // defined in RFC 1982

        // o  The validator's notion of the current time MUST be less than or
        //    equal to the time listed in the RRSIG RR's Expiration field.
        if (!RRUtils.serialNumberGte(rrset.expiration, uint32(now))) {
            revert SignatureExpired(rrset.expiration, uint32(now));
        }

        // o  The validator's notion of the current time MUST be greater than or
        //    equal to the time listed in the RRSIG RR's Inception field.
        if (!RRUtils.serialNumberGte(uint32(now), rrset.inception)) {
            revert SignatureNotValidYet(rrset.inception, uint32(now));
        }

        // Validate the signature
        verifySignature(name, rrset, input, proof);

        return rrset;
    }

    /**
     * @dev Validates a set of RRs.
     * @param rrset The RR set.
     * @param typecovered The type covered by the RRSIG record.
     */
    function validateRRs(RRUtils.SignedSet memory rrset, uint16 typecovered)
        internal
        pure
        returns (bytes memory name)
    {
        // Iterate over all the RRs
        for (
            RRUtils.RRIterator memory iter = rrset.rrs();
            !iter.done();
            iter.next()
        ) {
            // We only support class IN (Internet)
            if (iter.class != DNSCLASS_IN) {
                revert InvalidClass(iter.class);
            }

            if (name.length == 0) {
                name = iter.name();
            } else {
                // Name must be the same on all RRs. We do things this way to avoid copying the name
                // repeatedly.
                if (
                    name.length != iter.data.nameLength(iter.offset) ||
                    !name.equals(0, iter.data, iter.offset, name.length)
                ) {
                    revert InvalidRRSet();
                }
            }

            // o  The RRSIG RR's Type Covered field MUST equal the RRset's type.
            if (iter.dnstype != typecovered) {
                revert SignatureTypeMismatch(iter.dnstype, typecovered);
            }
        }
    }

    /**
     * @dev Performs signature verification.
     *
     * Throws or reverts if unable to verify the record.
     *
     * @param name The name of the RRSIG record, in DNS label-sequence format.
     * @param data The original data to verify.
     * @param proof A DS or DNSKEY record that's already verified by the oracle.
     */
    function verifySignature(
        bytes memory name,
        RRUtils.SignedSet memory rrset,
        RRSetWithSignature memory data,
        bytes memory proof
    ) internal view {
        // o  The RRSIG RR's Signer's Name field MUST be the name of the zone
        //    that contains the RRset.
        if (
            rrset.signerName.length > name.length ||
            !rrset.signerName.equals(
                0,
                name,
                name.length - rrset.signerName.length
            )
        ) {
            revert InvalidSignerName(name, rrset.signerName);
        }

        RRUtils.RRIterator memory proofRR = proof.iterateRRs(0);
        // Check the proof
        if (proofRR.dnstype == DNSTYPE_DS) {
            verifyWithDS(rrset, data, proofRR);
        } else if (proofRR.dnstype == DNSTYPE_DNSKEY) {
            verifyWithKnownKey(rrset, data, proofRR);
        } else {
            revert InvalidProofType(proofRR.dnstype);
        }
    }

    /**
     * @dev Attempts to verify a signed RRSET against an already known public key.
     * @param rrset The signed set to verify.
     * @param data The original data the signed set was read from.
     * @param proof The serialized DS or DNSKEY record to use as proof.
     */
    function verifyWithKnownKey(
        RRUtils.SignedSet memory rrset,
        RRSetWithSignature memory data,
        RRUtils.RRIterator memory proof
    ) internal view {
        // Check the DNSKEY's owner name matches the signer name on the RRSIG
        for (; !proof.done(); proof.next()) {
            bytes memory proofName = proof.name();
            if (!proofName.equals(rrset.signerName)) {
                revert ProofNameMismatch(rrset.signerName, proofName);
            }

            bytes memory keyrdata = proof.rdata();
            RRUtils.DNSKEY memory dnskey = keyrdata.readDNSKEY(
                0,
                keyrdata.length
            );
            if (verifySignatureWithKey(dnskey, keyrdata, rrset, data)) {
                return;
            }
        }
        revert NoMatchingProof(rrset.signerName);
    }

    /**
     * @dev Attempts to verify some data using a provided key and a signature.
     * @param dnskey The dns key record to verify the signature with.
     * @param rrset The signed RRSET being verified.
     * @param data The original data `rrset` was decoded from.
     * @return True iff the key verifies the signature.
     */
    function verifySignatureWithKey(
        RRUtils.DNSKEY memory dnskey,
        bytes memory keyrdata,
        RRUtils.SignedSet memory rrset,
        RRSetWithSignature memory data
    ) internal view returns (bool) {
        // TODO: Check key isn't expired, unless updating key itself

        // The Protocol Field MUST have value 3 (RFC4034 2.1.2)
        if (dnskey.protocol != 3) {
            return false;
        }

        // o The RRSIG RR's Signer's Name, Algorithm, and Key Tag fields MUST
        //   match the owner name, algorithm, and key tag for some DNSKEY RR in
        //   the zone's apex DNSKEY RRset.
        if (dnskey.algorithm != rrset.algorithm) {
            return false;
        }
        uint16 computedkeytag = keyrdata.computeKeytag();
        if (computedkeytag != rrset.keytag) {
            return false;
        }

        // o The matching DNSKEY RR MUST be present in the zone's apex DNSKEY
        //   RRset, and MUST have the Zone Flag bit (DNSKEY RDATA Flag bit 7)
        //   set.
        if (dnskey.flags & DNSKEY_FLAG_ZONEKEY == 0) {
            return false;
        }

        return
            algorithms[dnskey.algorithm].verify(keyrdata, data.rrset, data.sig);
    }

    /**
     * @dev Attempts to verify a signed RRSET against an already known hash. This function assumes
     *      that the record
     * @param rrset The signed set to verify.
     * @param data The original data the signed set was read from.
     * @param proof The serialized DS or DNSKEY record to use as proof.
     */
    function verifyWithDS(
        RRUtils.SignedSet memory rrset,
        RRSetWithSignature memory data,
        RRUtils.RRIterator memory proof
    ) internal view {
        for (
            RRUtils.RRIterator memory iter = rrset.rrs();
            !iter.done();
            iter.next()
        ) {
            if (iter.dnstype != DNSTYPE_DNSKEY) {
                revert InvalidProofType(iter.dnstype);
            }

            bytes memory keyrdata = iter.rdata();
            RRUtils.DNSKEY memory dnskey = keyrdata.readDNSKEY(
                0,
                keyrdata.length
            );
            if (verifySignatureWithKey(dnskey, keyrdata, rrset, data)) {
                // It's self-signed - look for a DS record to verify it.
                if (
                    verifyKeyWithDS(rrset.signerName, proof, dnskey, keyrdata)
                ) {
                    return;
                }
            }
        }
        revert NoMatchingProof(rrset.signerName);
    }

    /**
     * @dev Attempts to verify a key using DS records.
     * @param keyname The DNS name of the key, in DNS label-sequence format.
     * @param dsrrs The DS records to use in verification.
     * @param dnskey The dnskey to verify.
     * @param keyrdata The RDATA section of the key.
     * @return True if a DS record verifies this key.
     */
    function verifyKeyWithDS(
        bytes memory keyname,
        RRUtils.RRIterator memory dsrrs,
        RRUtils.DNSKEY memory dnskey,
        bytes memory keyrdata
    ) internal view returns (bool) {
        uint16 keytag = keyrdata.computeKeytag();
        for (; !dsrrs.done(); dsrrs.next()) {
            bytes memory proofName = dsrrs.name();
            if (!proofName.equals(keyname)) {
                revert ProofNameMismatch(keyname, proofName);
            }

            RRUtils.DS memory ds = dsrrs.data.readDS(
                dsrrs.rdataOffset,
                dsrrs.nextOffset - dsrrs.rdataOffset
            );
            if (ds.keytag != keytag) {
                continue;
            }
            if (ds.algorithm != dnskey.algorithm) {
                continue;
            }

            Buffer.buffer memory buf;
            buf.init(keyname.length + keyrdata.length);
            buf.append(keyname);
            buf.append(keyrdata);
            if (verifyDSHash(ds.digestType, buf.buf, ds.digest)) {
                return true;
            }
        }
        return false;
    }

    /**
     * @dev Attempts to verify a DS record's hash value against some data.
     * @param digesttype The digest ID from the DS record.
     * @param data The data to digest.
     * @param digest The digest data to check against.
     * @return True iff the digest matches.
     */
    function verifyDSHash(
        uint8 digesttype,
        bytes memory data,
        bytes memory digest
    ) internal view returns (bool) {
        if (address(digests[digesttype]) == address(0)) {
            return false;
        }
        return digests[digesttype].verify(data, digest);
    }
}


syntax

syntax

pragma solidity ^0.4.11;

import "./SafeMath.sol";
import "./ERC20.sol";
import "./Power.sol";
import "./ERC223ReceivingContract.sol";

/**
 * Nutz implements a price floor and a price ceiling on the token being
 * sold. It is based of the zeppelin token contract.
 */
contract Nutz is ERC20 {
  using SafeMath for uint;

  event Purchase(address indexed purchaser, uint256 value);
  event Sell(address indexed seller, uint256 value);

  string public name = "Acebusters Nutz";
  // acebusters units:
  // 10^12 - Nutz   (NTZ)
  // 10^9 - Jonyz
  // 10^6 - Helcz
  // 10^3 - Pascalz
  // 10^0 - Babz
  string public symbol = "NTZ";
  uint256 public decimals = 12;
  uint256 INFINITY = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;
  uint256 MEGA_WEI = 1000000;   // 1 MEGA_WEI equals 1,000,000 WEI, used as price factor

  uint256 actSupply;
  // contract's ether balance, except all ether parked to be withdrawn
  uint256 public reserve;
  // balanceOf[powerAddr] returns power pool
  // balanceOf[address(this)] returns burn pool
  mapping(address => uint) balances;
  // "allowed[address(this)][x]" ether parked to be withdraw
  mapping (address => mapping (address => uint)) allowed;

  // the Token sale mechanism parameters:
  // ceiling is the number of NTZ returned for 1 ETH
  uint256 public ceiling;
  // floor is the number of NTZ needed, no receive 1 ETH back
  // we say that floor is lower than ceiling, if the number of NTZ needed to sell
  // to receive the same amount of ETH as used in purchase, is higher.
  uint256 setFloor;
  address[] public admins;
  address public powerAddr;

  // this flag allows denies deposits of NTZ into non-contract accounts
  bool public onlyContractHolders = true;

  // returns balance
  function balanceOf(address _owner) constant returns (uint) {
    return balances[_owner];
  }

  function totalSupply() constant returns (uint256) {
    // active supply + power pool + burn pool
    return actSupply.add(balances[powerAddr]).add(balances[address(this)]);
  }

  function activeSupply() constant returns (uint256) {
    return actSupply;
  }

  // return remaining allowance
  // if calling return allowed[address(this)][_spender];
  // returns balance of ether parked to be withdrawn
  function allowance(address _owner, address _spender) constant returns (uint) {
    return allowed[_owner][_spender];
  }

  // returns either the setFloor, or if reserve does not suffice
  // for active supply, returns maxFloor
  function floor() constant returns (uint256) {
    if (reserve == 0) {
      return INFINITY;
    }
    uint256 maxFloor = actSupply.mul(MEGA_WEI).div(reserve);
    // return max of maxFloor or setFloor
    return maxFloor >= setFloor ? maxFloor : setFloor;
  }

  function Nutz(uint256 _downTime) {
    admins.length = 1;
    admins[0] = msg.sender;
    // initial purchase price
    ceiling = 0;
    // initial sale price
    setFloor = INFINITY;
    onlyContractHolders = true;
    powerAddr = new Power(address(this), _downTime);
  }

  // ############################################
  // ########### INTERNAL FUNCTIONS #############
  // ############################################

  function _sellTokens(address _from, uint256 _amountBabz) internal returns (bool) {
    uint256 effectiveFloor = floor();
    assert(effectiveFloor != INFINITY);

    uint256 amountWei = _amountBabz.mul(MEGA_WEI).div(effectiveFloor);
    // make sure power pool shrinks proportional to economy
    uint256 powerPool = balances[powerAddr];
    if (powerPool > 0) {
      uint256 powerShare = powerPool.mul(_amountBabz).div(actSupply);
      balances[powerAddr] = powerPool.sub(powerShare);
    }
    actSupply = actSupply.sub(_amountBabz);
    balances[_from] = balances[_from].sub(_amountBabz);
    reserve = reserve.sub(amountWei);
    allowed[address(this)][_from] = allowed[address(this)][_from].add(amountWei);
    Sell(_from,  _amountBabz);
    return true;
  }

  // withdraw accumulated balance, called by seller or beneficiary
  function _claimEther(address _sender, address _to) internal {
    assert(setFloor < INFINITY);
    uint256 amountWei = allowed[address(this)][_sender];
    assert(0 < amountWei && amountWei <= this.balance);
    allowed[address(this)][_sender] = 0;
    assert(_to.send(amountWei));
  }

  function _checkDestination(address _from, address _to, uint256 _value, bytes _data) internal {
    // erc223: Retrieve the size of the code on target address, this needs assembly .
    uint256 codeLength;
    assembly {
      codeLength := extcodesize(_to)
    }
    if(codeLength>0) {
      ERC223ReceivingContract receiver = ERC223ReceivingContract(_to);
      receiver.tokenFallback(_from, _value, _data);
    } else {
      require(onlyContractHolders == false);
    }
  }

  function _transfer(address _from, address _to, uint256 _amountBabz, bytes _data) internal returns (bool) {
    bytes memory data;
    // power up
    if (_to == powerAddr) {
      data = new bytes(32);
      uint ts = totalSupply();
      assembly { mstore(add(data, 32), ts) }
      actSupply = actSupply.sub(_amountBabz);
    } else {
      data = _data;
    }
    // power down
    if (_from == powerAddr) {
      actSupply = actSupply.add(_amountBabz);
    }

    balances[_from] = balances[_from].sub(_amountBabz);
    balances[_to] = balances[_to].add(_amountBabz);

    _checkDestination(_from, _to, _amountBabz, data);

    Transfer(_from, _to, _amountBabz);
    return true;
  }

  // ############################################
  // ########### ADMIN FUNCTIONS ################
  // ############################################

  modifier onlyAdmins() {
    bool isAdmin = false;
    for (uint256 i = 0; i < admins.length; i++) {
      if (msg.sender == admins[i]) {
        isAdmin = true;
      }
    }
    require(isAdmin == true);
    _;
  }

  function addAdmin(address _admin) onlyAdmins {
    for (uint256 i = 0; i < admins.length; i++) {
      require(_admin != admins[i]);
    }
    require(admins.length < 10);
    admins[admins.length++] = _admin;
  }

  function removeAdmin(address _admin) onlyAdmins {
    uint256 pos = admins.length;
    for (uint256 i = 0; i < admins.length; i++) {
      if (_admin == admins[i]) {
        pos = i;
      }
    }
    require(pos < admins.length);
    // if not last element, switch with last
    if (pos < admins.length - 1) {
      admins[pos] = admins[admins.length - 1];
    }
    // then cut off the tail
    admins.length--;
  }

  function moveCeiling(uint256 _newCeiling) onlyAdmins {
    require(_newCeiling <= setFloor);
    ceiling = _newCeiling;
  }

  function moveFloor(uint256 _newFloor) onlyAdmins {
    require(_newFloor >= ceiling);
    // moveFloor fails if the administrator tries to push the floor so low
    // that the sale mechanism is no longer able to buy back all tokens at
    // the floor price if those funds were to be withdrawn.
    if (_newFloor > 0) {
      uint256 newReserveNeeded = actSupply.mul(MEGA_WEI).div(_newFloor);
      require(reserve >= newReserveNeeded);
    }
    setFloor = _newFloor;
  }

  function setOnlyContractHolders(bool _onlyContractHolders) onlyAdmins {
    onlyContractHolders = _onlyContractHolders;
  }

  function allocateEther(uint256 _amountWei, address _beneficiary) onlyAdmins {
    require(_amountWei > 0);
    // allocateEther fails if allocating those funds would mean that the
    // sale mechanism is no longer able to buy back all tokens at the floor
    // price if those funds were to be withdrawn.
    uint256 leftReserve = reserve.sub(_amountWei);
    require(leftReserve >= actSupply.mul(MEGA_WEI).div(setFloor));
    reserve = reserve.sub(_amountWei);
    allowed[address(this)][_beneficiary] = allowed[address(this)][_beneficiary].add(_amountWei);
  }

  function dilutePower(uint256 _amountBabz) onlyAdmins {
    uint256 burn = balances[address(this)];
    uint256 totalSupply = actSupply.add(balances[powerAddr]).add(burn);
    assert(Power(powerAddr).dilutePower(totalSupply, _amountBabz));
    balances[address(this)] = burn.add(_amountBabz);
  }

  function slashPower(address _holder, uint256 _value, bytes32 _data) onlyAdmins {
    // get the previously outstanding power of which _value was slashed
    uint256 outstandingPower = Power(powerAddr).slashPower(_holder, _value, _data);
    uint256 powerPool = balances[powerAddr];
    uint256 slashingBabz = _value.mul(powerPool).div(outstandingPower);
    balances[powerAddr] = powerPool.sub(slashingBabz);
  }

  function slashDownRequest(uint256 _pos, address _holder, uint256 _value, bytes32 _data) onlyAdmins {
    // get the previously outstanding power of which _value was slashed
    uint256 outstandingPower = Power(powerAddr).slashDownRequest(_pos, _holder, _value, _data);
    uint256 powerPool = balances[powerAddr];
    uint256 slashingBabz = _value.mul(powerPool).div(outstandingPower);
    balances[powerAddr] = powerPool.sub(slashingBabz);
  }

  function setMaxPower(uint256 _maxPower) onlyAdmins {
    Power(powerAddr).setMaxPower(_maxPower);
  }

  // ############################################
  // ########### PAYABLE FUNCTIONS ##############
  // ############################################

  function () payable {
    purchaseTokens();
  }

  function purchaseTokens() payable {
    require(msg.value > 0);
    // disable purchases if ceiling set to 0
    require(ceiling > 0);

    uint256 amountBabz = msg.value.mul(ceiling).div(MEGA_WEI);
    // avoid deposits that issue nothing
    // might happen with very large ceiling
    require(amountBabz > 0);

    reserve = reserve.add(msg.value);
    // make sure power pool grows proportional to economy
    if (powerAddr != 0x0 && balances[powerAddr] > 0) {
      uint256 powerShare = balances[powerAddr].mul(amountBabz).div(actSupply.add(balances[address (this)]));
      balances[powerAddr] = balances[powerAddr].add(powerShare);
    }
    actSupply = actSupply.add(amountBabz);
    balances[msg.sender] = balances[msg.sender].add(amountBabz);

    bytes memory empty;
    _checkDestination(address(this), msg.sender, amountBabz, empty);

    Purchase(msg.sender, amountBabz);
  }

  // ############################################
  // ########### PUBLIC FUNCTIONS ###############
  // ############################################

  function approve(address _spender, uint256 _amountBabz) {
    require(_spender != address(this));
    require(msg.sender != _spender);
    require(_amountBabz != 0);
    allowed[msg.sender][_spender] = _amountBabz;
    Approval(msg.sender, _spender, _amountBabz);
  }

  function transfer(address _to, uint256 _amountBabz) returns (bool) {
    bytes memory empty;
    return transfer(_to, _amountBabz, empty);
  }

  function transData(address _to, uint256 _amountBabz, bytes _data) returns (bool) {
    return transfer(_to, _amountBabz, _data);
  }

  function transfer(address _to, uint256 _amountBabz, bytes _data) returns (bool) {
    require(_amountBabz != 0);
    // sell tokens
    if (_to == address(this)) {
      return _sellTokens(msg.sender, _amountBabz);
    }
    return _transfer(msg.sender, _to, _amountBabz, _data);
  }

  function transferFrom(address _from, address _to, uint256 _amountBabz) returns (bool) {
    require(_from != _to);
    // claim ether
    if (_from == address(this) && _amountBabz == 0) {
      _claimEther(msg.sender, _to);
      return true;
    }
    require(_amountBabz > 0);
    // sell tokens
    if (_to == address(this)) {
      return _sellTokens(_from, _amountBabz);
    }
    bytes memory empty;
    if (_from == powerAddr) {
      // 3rd party power up:
      // - first transfer NTZ to account of receiver
      // - then power up that amount of NTZ in the account of receiver
      balances[msg.sender] = balances[msg.sender].sub(_amountBabz);
      balances[_to] = balances[_to].add(_amountBabz);
      return _transfer(_to, _from, _amountBabz, empty);
    } else {
      // usual transfer
      allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_amountBabz);
      return _transfer(_from, _to, _amountBabz, empty);
    }
  }

}

pragma solidity ^0.4.11;

import "./SafeMath.sol";
import "./ERC20.sol";
import "./Power.sol";
import "./ERC223ReceivingContract.sol";

/**
 * Nutz implements a price floor and a price ceiling on the token being
 * sold. It is based of the zeppelin token contract. Nutz implements the
 * https://github.com/ethereum/EIPs/issues/20 interface.
 */
contract Nutz is ERC20 {
  using SafeMath for uint;

  event Purchase(address indexed purchaser, uint256 value);
  event Sell(address indexed seller, uint256 value);

  string public name = "Acebusters Nutz";
  // acebusters units:
  // 10^12 - Nutz   (NTZ)
  // 10^9 - Jonyz
  // 10^6 - Helcz
  // 10^3 - Pascalz
  // 10^0 - Babz
  string public symbol = "NTZ";
  uint256 public decimals = 12;
  uint256 INFINITY = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;
  uint256 MEGA_WEI = 1000000;   // 1 MEGA_WEI equals 1,000,000 WEI, used as price factor

  uint256 actSupply;
  // contract's ether balance, except all ether parked to be withdrawn
  uint256 public reserve;
  // balanceOf[powerAddr] returns power pool
  // balanceOf[address(this)] returns burn pool
  mapping(address => uint) balances;
  // "allowed[address(this)][x]" ether parked to be withdraw
  mapping (address => mapping (address => uint)) allowed;

  // the Token sale mechanism parameters:
  // ceiling is the number of NTZ returned for 1 ETH
  uint256 public ceiling;
  // floor is the number of NTZ needed, no receive 1 ETH back
  // we say that floor is lower than ceiling, if the number of NTZ needed to sell
  // to receive the same amount of ETH as used in purchase, is higher.
  uint256 setFloor;
  address[] public admins;
  address public powerAddr;

  // this flag allows denies deposits of NTZ into non-contract accounts
  bool public onlyContractHolders = true;

  // returns balance
  function balanceOf(address _owner) constant returns (uint) {
    return balances[_owner];
  }

  function totalSupply() constant returns (uint256) {
    // active supply + power pool + burn pool
    return actSupply.add(balances[powerAddr]).add(balances[address(this)]);
  }

  function activeSupply() constant returns (uint256) {
    return actSupply;
  }

  // return remaining allowance
  // if calling return allowed[address(this)][_spender];
  // returns balance of ether parked to be withdrawn
  function allowance(address _owner, address _spender) constant returns (uint) {
    return allowed[_owner][_spender];
  }

  // returns either the setFloor, or if reserve does not suffice
  // for active supply, returns maxFloor
  function floor() constant returns (uint256) {
    if (reserve == 0) {
      return INFINITY;
    }
    uint256 maxFloor = actSupply.mul(MEGA_WEI).div(reserve);
    // return max of maxFloor or setFloor
    return maxFloor >= setFloor ? maxFloor : setFloor;
  }

  function Nutz(uint256 _downTime) {
    admins.length = 1;
    admins[0] = msg.sender;
    // initial purchase price
    ceiling = 0;
    // initial sale price
    setFloor = INFINITY;
    onlyContractHolders = true;
    powerAddr = new Power(address(this), _downTime);
  }

  // ############################################
  // ########### INTERNAL FUNCTIONS #############
  // ############################################

  function _sellTokens(address _from, uint256 _amountBabz) internal returns (bool) {
    uint256 effectiveFloor = floor();
    assert(effectiveFloor != INFINITY);

    uint256 amountWei = _amountBabz.mul(MEGA_WEI).div(effectiveFloor);
    // make sure power pool shrinks proportional to economy
    uint256 powerPool = balances[powerAddr];
    if (powerPool > 0) {
      uint256 powerShare = powerPool.mul(_amountBabz).div(actSupply);
      balances[powerAddr] = powerPool.sub(powerShare);
    }
    actSupply = actSupply.sub(_amountBabz);
    balances[_from] = balances[_from].sub(_amountBabz);
    reserve = reserve.sub(amountWei);
    allowed[address(this)][_from] = allowed[address(this)][_from].add(amountWei);
    Sell(_from,  _amountBabz);
    return true;
  }

  // withdraw accumulated balance, called by seller or beneficiary
  function _claimEther(address _sender, address _to) internal {
    assert(setFloor < INFINITY);
    uint256 amountWei = allowed[address(this)][_sender];
    assert(0 < amountWei && amountWei <= this.balance);
    allowed[address(this)][_sender] = 0;
    assert(_to.send(amountWei));
  }

  function _checkDestination(address _from, address _to, uint256 _value, bytes _data) internal {
    // erc223: Retrieve the size of the code on target address, this needs assembly .
    uint256 codeLength;
    assembly {
      codeLength := extcodesize(_to)
    }
    if(codeLength>0) {
      ERC223ReceivingContract receiver = ERC223ReceivingContract(_to);
      receiver.tokenFallback(_from, _value, _data);
    } else {
      assert(onlyContractHolders == false);
    }
  }

  function _transfer(address _from, address _to, uint256 _amountBabz, bytes _data) internal returns (bool) {
    bytes memory data;
    // power up
    if (_to == powerAddr) {
      data = new bytes(32);
      uint ts = totalSupply();
      assembly { mstore(add(data, 32), ts) }
      actSupply = actSupply.sub(_amountBabz);
    } else {
      data = _data;
    }
    // power down
    if (_from == powerAddr) {
      actSupply = actSupply.add(_amountBabz);
    }

    balances[_from] = balances[_from].sub(_amountBabz);
    balances[_to] = balances[_to].add(_amountBabz);

    _checkDestination(_from, _to, _amountBabz, data);

    Transfer(_from, _to, _amountBabz);
    return true;
  }

  // ############################################
  // ########### ADMIN FUNCTIONS ################
  // ############################################

  modifier onlyAdmins() {
    bool isAdmin = false;
    for (uint256 i = 0; i < admins.length; i++) {
      if (msg.sender == admins[i]) {
        isAdmin = true;
      }
    }
    if (isAdmin == true) {
      _;
    } else {
      revert();
    }
  }

  function addAdmin(address _admin) onlyAdmins {
    for (uint256 i = 0; i < admins.length; i++) {
      require(_admin != admins[i]);
    }
    require(admins.length <= 10);
    admins[admins.length++] = _admin;
  }

  function removeAdmin(address _admin) onlyAdmins {
    uint256 pos = 1337;
    for (uint256 i = 0; i < admins.length; i++) {
      if (_admin == admins[i]) {
        pos = i;
      }
    }
    // if not last element, switch with last
    if (pos < admins.length - 1) {
      admins[pos] = admins[admins.length - 1];
    }
    // then cut off the tail
    admins.length--;
  }

  function moveCeiling(uint256 _newCeiling) onlyAdmins {
    assert(_newCeiling <= setFloor);
    ceiling = _newCeiling;
  }

  function moveFloor(uint256 _newFloor) onlyAdmins {
    assert(_newFloor >= ceiling);
    // moveFloor fails if the administrator tries to push the floor so low
    // that the sale mechanism is no longer able to buy back all tokens at
    // the floor price if those funds were to be withdrawn.
    if (_newFloor > 0) {
      uint256 newReserveNeeded = actSupply.mul(MEGA_WEI).div(_newFloor);
      assert(reserve >= newReserveNeeded);
    }
    setFloor = _newFloor;
  }

  function setOnlyContractHolders(bool _onlyContractHolders) onlyAdmins {
    onlyContractHolders = _onlyContractHolders;
  }

  function allocateEther(uint256 _amountWei, address _beneficiary) onlyAdmins {
    assert(_amountWei > 0);
    // allocateEther fails if allocating those funds would mean that the
    // sale mechanism is no longer able to buy back all tokens at the floor
    // price if those funds were to be withdrawn.
    uint256 leftReserve = reserve.sub(_amountWei);
    assert(leftReserve >= actSupply.mul(MEGA_WEI).div(setFloor));
    reserve = reserve.sub(_amountWei);
    allowed[address(this)][_beneficiary] = allowed[address(this)][_beneficiary].add(_amountWei);
  }

  function dilutePower(uint256 _amountBabz) onlyAdmins {
    uint256 burn = balances[address(this)];
    uint256 totalSupply = actSupply.add(balances[powerAddr]).add(burn);
    assert(Power(powerAddr).dilutePower(totalSupply, _amountBabz));
    balances[address(this)] = burn.add(_amountBabz);
  }

  function slashPower(address _holder, uint256 _value, bytes32 _data) onlyAdmins {
    // get the previously outstanding power of which _value was slashed
    uint256 outstandingPower = Power(powerAddr).slashPower(_holder, _value, _data);
    uint256 powerPool = balances[powerAddr];
    uint256 slashingBabz = _value.mul(powerPool).div(outstandingPower);
    balances[powerAddr] = powerPool.sub(slashingBabz);
  }

  function slashDownRequest(uint256 _pos, address _holder, uint256 _value, bytes32 _data) onlyAdmins {
    // get the previously outstanding power of which _value was slashed
    uint256 outstandingPower = Power(powerAddr).slashDownRequest(_pos, _holder, _value, _data);
    uint256 powerPool = balances[powerAddr];
    uint256 slashingBabz = _value.mul(powerPool).div(outstandingPower);
    balances[powerAddr] = powerPool.sub(slashingBabz);
  }

  function setMaxPower(uint256 _maxPower) onlyAdmins {
    Power(powerAddr).setMaxPower(_maxPower);
  }

  // ############################################
  // ########### PAYABLE FUNCTIONS ##############
  // ############################################

  function () payable {
    purchaseTokens();
  }

  function purchaseTokens() payable {
    assert(msg.value > 0);
    // disable purchases if ceiling set to 0
    assert(ceiling > 0);

    uint256 amountBabz = msg.value.mul(ceiling).div(MEGA_WEI);
    // avoid deposits that issue nothing
    // might happen with very large ceiling
    assert(amountBabz > 0);

    reserve = reserve.add(msg.value);
    // make sure power pool grows proportional to economy
    if (powerAddr != 0x0 && balances[powerAddr] > 0) {
      uint256 powerShare = balances[powerAddr].mul(amountBabz).div(actSupply.add(balances[address (this)]));
      balances[powerAddr] = balances[powerAddr].add(powerShare);
    }
    actSupply = actSupply.add(amountBabz);
    balances[msg.sender] = balances[msg.sender].add(amountBabz);

    bytes memory empty;
    _checkDestination(address(this), msg.sender, amountBabz, empty);

    Purchase(msg.sender, amountBabz);
  }

  // ############################################
  // ########### PUBLIC FUNCTIONS ###############
  // ############################################

  function approve(address _spender, uint256 _amountBabz) {
    require(_spender != address(this));
    require(msg.sender != _spender);
    require(_amountBabz != 0);
    allowed[msg.sender][_spender] = _amountBabz;
    Approval(msg.sender, _spender, _amountBabz);
  }

  function transfer(address _to, uint256 _amountBabz) returns (bool) {
    bytes memory empty;
    return transfer(_to, _amountBabz, empty);
  }

  function transData(address _to, uint256 _amountBabz, bytes _data) returns (bool) {
    return transfer(_to, _amountBabz, _data);
  }

  function transfer(address _to, uint256 _amountBabz, bytes _data) returns (bool) {
    require(_amountBabz != 0);
    // sell tokens
    if (_to == address(this)) {
      return _sellTokens(msg.sender, _amountBabz);
    }
    return _transfer(msg.sender, _to, _amountBabz, _data);
  }

  function transferFrom(address _from, address _to, uint256 _amountBabz) returns (bool) {
    require(_from != _to);
    // claim ether
    if (_from == address(this) && _amountBabz == 0) {
      _claimEther(msg.sender, _to);
      return true;
    }
    require(_amountBabz > 0);
    // sell tokens
    if (_to == address(this)) {
      return _sellTokens(_from, _amountBabz);
    }
    bytes memory empty;
    if (_from == powerAddr) {
      // 3rd party power up:
      // - first transfer NTZ to account of receiver
      // - then power up that amount of NTZ in the account of receiver
      balances[msg.sender] = balances[msg.sender].sub(_amountBabz);
      balances[_to] = balances[_to].add(_amountBabz);
      return _transfer(_to, _from, _amountBabz, empty);
    } else {
      // usual transfer
      allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_amountBabz);
      return _transfer(_from, _to, _amountBabz, empty);
    }
  }

}


remove unused modifier

remove unused modifier

pragma solidity ^0.4.0;

import "./Concept.sol";

/*
@type: contract
@name: ConceptRegistry
@purpose: To create concepts and store some concept data
*/
contract ConceptRegistry {
  mapping (address => bool) public conceptExists; //Maps concept addresses to a bool to confirm their existance
  address userRegistry; //The address of the userRegistry contract
  bool initialized = false; //Keeps track of whether or not the function to set the userRegistry variable is locked yet or not
  address public mewAddress;

  /*
  @occasion: When a concept is created
  @purpose: To help build a data store of concepts
  */
  event ConceptCreation (address _concept); //the address of the concept that was created

  /*
  @type: function
  @purpose: To set the userRegistry address
  @param: address userRegistry = the address of the userRegistry contract
  @returns: nothing
  */
  function init(address _userRegistry, address mew) {
    if(initialized == false) { //Checks if the function has already been called
      userRegistry = _userRegistry; //Sets the userRegistry address
      mewAddress = mew;
      initialized = true; //Makes it so this function cannot be called again
    }
  }

  /*
  @purpose: To make a concept
  @param: address[] parentList = an array of addresses containing the addresses of the concepts parents
  */
  function makeConcept(address[] parentList) {
    Concept newConcept = new Concept(parentList, userRegistry, address(this)); //Makes a new concept with the provided data
    address newConceptAddress = address(newConcept); //initializes an address variable and sets it equal to the address of the newly created concept
    conceptExists[newConceptAddress] = true; //Maps the concept address to true to show that it exists
    if(parentList.length == 0) {
      Concept(mewAddress).addChild(newConceptAddress);
    }
    for(uint j=0; j < parentList.length; j++) { //Iterates of the parents array in memory
      Concept(parentList[j]).addChild(newConceptAddress); //Adds the newly created concept to each of the parents as a child
    }
    ConceptCreation(newConceptAddress); //Makes ConceptCreation event with provided data
  }
}

pragma solidity ^0.4.0;

import "./Concept.sol";

/*
@type: contract
@name: ConceptRegistry
@purpose: To create concepts and store some concept data
*/
contract ConceptRegistry {
  mapping (address => bool) public conceptExists; //Maps concept addresses to a bool to confirm their existance
  address userRegistry; //The address of the userRegistry contract
  bool initialized = false; //Keeps track of whether or not the function to set the userRegistry variable is locked yet or not
  address public mewAddress;

  modifier onlyThis() {
    if(msg.sender != address(this)) { //Checks if msg.sender is this contract
      throw; //Throws out the function call if it isn't
    }
    _;
  }

  /*
  @occasion: When a concept is created
  @purpose: To help build a data store of concepts
  */
  event ConceptCreation (address _concept); //the address of the concept that was created

  /*
  @type: function
  @purpose: To set the userRegistry address
  @param: address userRegistry = the address of the userRegistry contract
  @returns: nothing
  */
  function init(address _userRegistry, address mew) {
    if(initialized == false) { //Checks if the function has already been called
      userRegistry = _userRegistry; //Sets the userRegistry address
      mewAddress = mew;
      initialized = true; //Makes it so this function cannot be called again
    }
  }

  /*
  @purpose: To make a concept
  @param: address[] parentList = an array of addresses containing the addresses of the concepts parents
  */
  function makeConcept(address[] parentList) {
    Concept newConcept = new Concept(parentList, userRegistry, address(this)); //Makes a new concept with the provided data
    address newConceptAddress = address(newConcept); //initializes an address variable and sets it equal to the address of the newly created concept
    conceptExists[newConceptAddress] = true; //Maps the concept address to true to show that it exists
    if(parentList.length == 0) {
      Concept(mewAddress).addChild(newConceptAddress);
    }
    for(uint j=0; j < parentList.length; j++) { //Iterates of the parents array in memory
      Concept(parentList[j]).addChild(newConceptAddress); //Adds the newly created concept to each of the parents as a child
    }
    ConceptCreation(newConceptAddress); //Makes ConceptCreation event with provided data
  }
}


Update CrowdFundrrShares.sol

Update CrowdFundrrShares.sol

// Crowdfunding System
// Start, donate, payout and refund crowdfunding campaigns
// @authors:
// Nick Dodson <thenickdodson@gmail.com>
// If goal is not reached and campaign is expired, contributers can get their donation refunded individually
// If goal is reached by alloted time, contributions can still be made
// This is speced with shares, not tested TODO.
contract CrowdFundrr
{
    struct User
    {
        uint numCampaigns;
        mapping(uint => uint) campaigns;
    }

    struct Funder
    {
        address addr;
        uint amount;
        uint shares;
    }

    struct Campaign
    {
        address owner;
        address beneficiary;
        uint timelimit;
        uint fundingGoal;
        uint amount;
        uint category;
        uint status;
        uint numFunders;
        uint sharePrice;
        mapping (uint => Funder) funders;
        mapping (address => uint) toFunder;
    }

    uint public numCampaigns;
    mapping (uint => Campaign) public campaigns;
    mapping (address => User) public users;

    modifier hasValue { if(msg.value > 0) _ }

    function newCampaign(address beneficiary, uint goal, uint timelimit, uint category)
    {
        if(goal > 0 && timelimit > block.timestamp){
            uint cid = numCampaigns++; // campaignID is return variable
            Campaign c = campaigns[cid];  // assigns reference
            c.owner = msg.sender;
            c.beneficiary = beneficiary;
            c.fundingGoal = goal;
            c.timelimit = timelimit;
            c.category = category;

            User u = users[msg.sender];
            uint u_cid = u.numCampaigns++;
            u.campaigns[u_cid] = cid;
        }
    }

    function contribute(uint cid) hasValue
    {
        Campaign c = campaigns[cid]; // Cannot be expired.
        if(c.timelimit >= block.timestamp){
            uint fid = c.numFunders++;
            Funder f = c.funders[fid];

            if(c.sharePrice > 0){
                f.shares += uint(msg.value/c.sharePrice);
            }

            f.addr = msg.sender;
            f.amount = msg.value;
            c.amount += f.amount;
            c.toFunder[msg.sender] = fid;
        }
    }

    function refund(uint cid)
    {
        Campaign c = campaigns[cid];
        if (block.timestamp > c.timelimit
        && c.amount < c.fundingGoal && c.amount > 0){
            Funder f = c.funders[c.toFunder[msg.sender]];
            if(f.amount > 0){
                f.addr.send(f.amount);
                c.amount -= f.amount;
                f.shares = 0;
                f.amount = 0;
            }
        }
    }

    function payout(uint cid)
    {
        Campaign c = campaigns[cid];
        if (c.amount >= c.fundingGoal){
            c.beneficiary.send(c.amount);
            c.amount = 0;
            c.status = 1;
        }
    }

    function userCampaigns(address addr, uint u_cid) returns (uint _cid)
    {
        User u = users[addr];
        _cid = u.campaigns[u_cid];
    }

    function getShares(uint cid, address addr) returns (uint shares)
    {
        Campaign c = campaigns[cid];
        if(c.numFunders != 0 && c.toFunder[addr] >= 0){
            Funder f = c.funders[c.toFunder[addr]];
            return f.shares;
        }
    }

    function isFunder(uint cid, address addr) returns (bool b)
    {
        Campaign c = campaigns[cid];

        if(c.numFunders > 0){
            Funder f = c.funders[c.toFunder[addr]];

            if(f.amount > 0){
                return true;
            }
        }

        return false;
    }

    function transferShares(uint cid, address addr, uint amount)
    {
        Campaign c = campaigns[cid];
        if(c.numFunders != 0 && amount > 0 && c.toFunder[msg.sender] >= 0){
            Funder f = c.funders[c.toFunder[msg.sender]];

            if(f.shares > 0 && f.shares < amount){
                f.shares -= amount;
                if(isFunder(cid, addr)){
                    Funder t_f = c.funders[c.toFunder[addr]];
                    t_f.shares += amount;
                }else{
                    uint new_id = c.numFunders += 1;
                    Funder new_f = c.funders[new_id];
                    new_f.shares = amount;
                    c.toFunder[addr] = new_id;
                }
            }
        }
    }
}

/*
// Solidity Interface
contract CrowdFundrr{function campaigns(uint256 )constant returns(string32 name,string32 website,address owner,address beneficiary,uint256 timelimit,uint256 fundingGoal,uint256 amount,uint256 category,uint256 status,uint256 numFunders){}function userCampaigns(address addr,uint256 u_cid)returns(uint256 _cid){}function refund(uint256 cid){}function numCampaigns()constant returns(uint256 ){}function newCampaign(string32 name,string32 website,address beneficiary,uint256 goal,uint256 timelimit,uint256 category){}function users(address )constant returns(uint256 numCampaigns){}function contribute(uint256 cid){}function payout(uint256 cid){}}

// JS Hex (Compiled in AlethZero)
var CrowdFundrrHex = "6104b98061000e6000396000f30060003560e060020a90048063141961bc1461006357806319ac74bd146100b1578063278ecde1146100c95780632c0f7b6f146100da5780639aac25c6146100ec578063a87430ba1461010c578063c1cbbca714610121578063e11523431461013257005b61006e600435610370565b896000528860205287600160a060020a031660405286600160a060020a0316606052856080528460a0528360c0528260e052816101005280610120526101406000f35b6100bf6004356024356103ba565b8060005260206000f35b6100d460043561022e565b60006000f35b6100e2610159565b8060005260206000f35b61010660043560243560443560643560843560a43561015f565b60006000f35b610117600435610144565b8060005260206000f35b61012c6004356103fb565b60006000f35b61013d600435610305565b60006000f35b5b600052600260205260406000208054905081565b5b60005481565b600060006000600060008711801561017657504286115b61017f57610222565b600080549081600101905593506001600085815260200190815260200160002092508983819055503383600201819055508883600101819055508783600301819055508683600501819055508583600401819055508483600701819055506002600033600160a060020a03168152602001908152602001600020915081805490816001019055905083826001016000838152602001908152602001600020819055505b50505050505050505050565b60006000600160008481526020019081526020016000209150816004015442118015610261575081600501548260060154105b8015610271575060008260060154115b61027a57610300565b81600a01600083600b01600033600160a060020a03168152602001908152602001600020548152602001908152602001600020905060008160010154116102c0576102ff565b8054600160a060020a0316600082600101546000600060006000848787f150505050806001015482600601908154039081905550600081600101819055505b5b505050565b60006001600083815260200190815260200160002090508060050154816006015410156103315761036b565b8060030154600160a060020a0316600082600601546000600060006000848787f15050505060008160060181905550600181600801819055505b5050565b5b60005260016020526040600020805490806001015490806002015490806003015490806004015490806005015490806006015490806007015490806008015490806009015490508a565b600060006002600085600160a060020a0316815260200190815260200160002090508060010160008481526020019081526020016000205491505092915050565b6000600060006000341161040e576104b3565b60016000858152602001908152602001600020925042836004015410158061043e57508260050154836006015410155b610447576104b2565b82600901805490816001019055915082600a01600083815260200190815260200160002090503381819055503481600101819055508060010154836006019081540190819055508183600b01600033600160a060020a03168152602001908152602001600020819055505b5b5050505056";

// JS ABI (Generated in AlethZero)
var CrowdFundrrABI = web3.eth.contractFromAbi([{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"campaigns","outputs":[{"name":"name","type":"string32"},{"name":"website","type":"string32"},{"name":"owner","type":"address"},{"name":"beneficiary","type":"address"},{"name":"timelimit","type":"uint256"},{"name":"fundingGoal","type":"uint256"},{"name":"amount","type":"uint256"},{"name":"category","type":"uint256"},{"name":"status","type":"uint256"},{"name":"numFunders","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"},{"name":"u_cid","type":"uint256"}],"name":"userCampaigns","outputs":[{"name":"_cid","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"cid","type":"uint256"}],"name":"refund","outputs":[],"type":"function"},{"constant":true,"inputs":[],"name":"numCampaigns","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"name","type":"string32"},{"name":"website","type":"string32"},{"name":"beneficiary","type":"address"},{"name":"goal","type":"uint256"},{"name":"timelimit","type":"uint256"},{"name":"category","type":"uint256"}],"name":"newCampaign","outputs":[],"type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"users","outputs":[{"name":"numCampaigns","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"cid","type":"uint256"}],"name":"contribute","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"cid","type":"uint256"}],"name":"payout","outputs":[],"type":"function"}]);

*/

// Crowdfunding System
// Start, donate, payout and refund crowdfunding campaigns
// @authors:
// Nick Dodson <thenickdodson@gmail.com>
// If goal is not reached and campaign is expired, contributers can get their donation refunded individually
// If goal is reached by alloted time, contributions can still be made
// This is speced with shares, not tested, just an idea TODO.
contract CrowdFundrr
{
    struct User
    {
        uint numCampaigns;
        mapping(uint => uint) campaigns;
    }

    struct Funder
    {
        address addr;
        uint amount;
        uint shares;
    }

    struct Campaign
    {
        address owner;
        address beneficiary;
        uint timelimit;
        uint fundingGoal;
        uint amount;
        uint category;
        uint status;
        uint numFunders;
        uint sharePrice;
        mapping (uint => Funder) funders;
        mapping (address => uint) toFunder;
    }

    uint public numCampaigns;
    mapping (uint => Campaign) public campaigns;
    mapping (address => User) public users;

    modifier hasValue { if(msg.value > 0) _ }

    function newCampaign(address beneficiary, uint goal, uint timelimit, uint category)
    {
        if(goal > 0 && timelimit > block.timestamp){
            uint cid = numCampaigns++; // campaignID is return variable
            Campaign c = campaigns[cid];  // assigns reference
            c.owner = msg.sender;
            c.beneficiary = beneficiary;
            c.fundingGoal = goal;
            c.timelimit = timelimit;
            c.category = category;

            User u = users[msg.sender];
            uint u_cid = u.numCampaigns++;
            u.campaigns[u_cid] = cid;
        }
    }

    function contribute(uint cid) hasValue
    {
        Campaign c = campaigns[cid]; // Cannot be expired.
        if(c.timelimit >= block.timestamp){
            uint fid = c.numFunders++;
            Funder f = c.funders[fid];
            f.addr = msg.sender;
            f.amount = msg.value;
            c.amount += f.amount;
            c.toFunder[msg.sender] = fid;
        }
    }

    function refund(uint cid)
    {
        Campaign c = campaigns[cid];
        if (block.timestamp > c.timelimit
        && c.amount < c.fundingGoal && c.amount > 0){
            Funder f = c.funders[c.toFunder[msg.sender]];
            if(f.amount > 0){
                f.addr.send(f.amount);
                c.amount -= f.amount;
                f.amount = 0;
            }
        }
    }

    function payout(uint cid)
    {
        Campaign c = campaigns[cid];
        if (c.amount >= c.fundingGoal){
            c.beneficiary.send(c.amount);
            c.amount = 0;
            c.status = 1;
        }
    }

    function userCampaigns(address addr, uint u_cid) returns (uint _cid)
    {
        User u = users[addr];
        _cid = u.campaigns[u_cid];
    }

    function getShares(uint cid, address addr) returns (uint shares)
    {
        Campaign c = campaigns[cid];
        if(c.numFunders != 0 && c.toFunder[addr] >= 0){
            Funder f = c.funders[c.toFunder[addr]];
            return f.shares;
        }
    }

    function isFunder(uint cid, address addr) returns (bool b)
    {
        Campaign c = campaigns[cid];

        if(c.numFunders > 0){
            Funder f = c.funders[c.toFunder[addr]];

            if(f.amount > 0){
                return true;
            }
        }

        return false;
    }

    function transferShares(uint cid, address addr, uint amount)
    {
        Campaign c = campaigns[cid];
        if(c.numFunders != 0 && amount > 0 && c.toFunder[msg.sender] >= 0){
            Funder f = c.funders[c.toFunder[msg.sender]];

            if(f.shares > 0 && f.shares < amount){
                f.shares -= amount;
                if(isFunder(cid, addr)){
                    Funder t_f = c.funders[c.toFunder[addr]];
                    t_f.shares += amount;
                }else{
                    uint new_id = c.numFunders += 1;
                    Funder new_f = c.funders[new_id];
                    new_f.shares = amount;
                    c.toFunder[addr] = new_id;
                }
            }
        }
    }
}

/*
// Solidity Interface
contract CrowdFundrr{function campaigns(uint256 )constant returns(string32 name,string32 website,address owner,address beneficiary,uint256 timelimit,uint256 fundingGoal,uint256 amount,uint256 category,uint256 status,uint256 numFunders){}function userCampaigns(address addr,uint256 u_cid)returns(uint256 _cid){}function refund(uint256 cid){}function numCampaigns()constant returns(uint256 ){}function newCampaign(string32 name,string32 website,address beneficiary,uint256 goal,uint256 timelimit,uint256 category){}function users(address )constant returns(uint256 numCampaigns){}function contribute(uint256 cid){}function payout(uint256 cid){}}

// JS Hex (Compiled in AlethZero)
var CrowdFundrrHex = "6104b98061000e6000396000f30060003560e060020a90048063141961bc1461006357806319ac74bd146100b1578063278ecde1146100c95780632c0f7b6f146100da5780639aac25c6146100ec578063a87430ba1461010c578063c1cbbca714610121578063e11523431461013257005b61006e600435610370565b896000528860205287600160a060020a031660405286600160a060020a0316606052856080528460a0528360c0528260e052816101005280610120526101406000f35b6100bf6004356024356103ba565b8060005260206000f35b6100d460043561022e565b60006000f35b6100e2610159565b8060005260206000f35b61010660043560243560443560643560843560a43561015f565b60006000f35b610117600435610144565b8060005260206000f35b61012c6004356103fb565b60006000f35b61013d600435610305565b60006000f35b5b600052600260205260406000208054905081565b5b60005481565b600060006000600060008711801561017657504286115b61017f57610222565b600080549081600101905593506001600085815260200190815260200160002092508983819055503383600201819055508883600101819055508783600301819055508683600501819055508583600401819055508483600701819055506002600033600160a060020a03168152602001908152602001600020915081805490816001019055905083826001016000838152602001908152602001600020819055505b50505050505050505050565b60006000600160008481526020019081526020016000209150816004015442118015610261575081600501548260060154105b8015610271575060008260060154115b61027a57610300565b81600a01600083600b01600033600160a060020a03168152602001908152602001600020548152602001908152602001600020905060008160010154116102c0576102ff565b8054600160a060020a0316600082600101546000600060006000848787f150505050806001015482600601908154039081905550600081600101819055505b5b505050565b60006001600083815260200190815260200160002090508060050154816006015410156103315761036b565b8060030154600160a060020a0316600082600601546000600060006000848787f15050505060008160060181905550600181600801819055505b5050565b5b60005260016020526040600020805490806001015490806002015490806003015490806004015490806005015490806006015490806007015490806008015490806009015490508a565b600060006002600085600160a060020a0316815260200190815260200160002090508060010160008481526020019081526020016000205491505092915050565b6000600060006000341161040e576104b3565b60016000858152602001908152602001600020925042836004015410158061043e57508260050154836006015410155b610447576104b2565b82600901805490816001019055915082600a01600083815260200190815260200160002090503381819055503481600101819055508060010154836006019081540190819055508183600b01600033600160a060020a03168152602001908152602001600020819055505b5b5050505056";

// JS ABI (Generated in AlethZero)
var CrowdFundrrABI = web3.eth.contractFromAbi([{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"campaigns","outputs":[{"name":"name","type":"string32"},{"name":"website","type":"string32"},{"name":"owner","type":"address"},{"name":"beneficiary","type":"address"},{"name":"timelimit","type":"uint256"},{"name":"fundingGoal","type":"uint256"},{"name":"amount","type":"uint256"},{"name":"category","type":"uint256"},{"name":"status","type":"uint256"},{"name":"numFunders","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"},{"name":"u_cid","type":"uint256"}],"name":"userCampaigns","outputs":[{"name":"_cid","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"cid","type":"uint256"}],"name":"refund","outputs":[],"type":"function"},{"constant":true,"inputs":[],"name":"numCampaigns","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"name","type":"string32"},{"name":"website","type":"string32"},{"name":"beneficiary","type":"address"},{"name":"goal","type":"uint256"},{"name":"timelimit","type":"uint256"},{"name":"category","type":"uint256"}],"name":"newCampaign","outputs":[],"type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"users","outputs":[{"name":"numCampaigns","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"cid","type":"uint256"}],"name":"contribute","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"cid","type":"uint256"}],"name":"payout","outputs":[],"type":"function"}]);

*/


Library access to pure

Library access to pure

pragma solidity ^0.4.11;

library StringUtils {

    function stringToBytes32(string memory source) pure internal returns (bytes32 result) {
	    assembly {
		    result := mload(add(source, 32))
	    }
    }
}

pragma solidity ^0.4.11;

library StringUtils {

    function stringToBytes32(string memory source) internal returns (bytes32 result) {
	    assembly {
		    result := mload(add(source, 32))
	    }
    }
}


error in return type

error in return type

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) returns (uint) {
        return uint(a);
    }

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

}

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) returns (int) {
        return uint(a);
    }

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

}


assessee cant be assess himself

assessee cant be assess himself

pragma solidity ^0.4.11;

import "./Math.sol";
import "./Concept.sol";
import "./FathomToken.sol";

contract Assessment {
    address assessee;
    address[] assessors;

    mapping (address => State) assessorState;
    State public assessmentStage;
    enum State {
        None,
        Called,
        Confirmed,
        Committed,
        Done,
        Burned
    }

    address concept;
    address fathomToken;

    uint public endTime;
    uint public latestConfirmTime;

    uint public size;
    uint cost;

    mapping(address => bytes32) commits;
    uint public done; //counter how many assessors have committed/revealed their score
    mapping(address => int128) scores;
    int public finalScore;

    modifier onlyConcept() {
        require(msg.sender == concept);
        _;
    }

    modifier onlyInStage(State _stage) {
        require(assessmentStage == _stage);
        _;
    }

    function Assessment(address _assessee,
                        uint _size,
                        uint _cost,
                        uint _confirmTime,
                        uint _timeLimit) {
        assessee = _assessee;
        concept = msg.sender;
        fathomToken = Concept(concept).fathomToken();

        endTime = now + _timeLimit;
        latestConfirmTime = now + _confirmTime;
        assert(latestConfirmTime < endTime);

        size = _size;
        cost = _cost;

        FathomToken(fathomToken).notification(assessee, 0); // assesse has started an assessment
        done = 0;
    }

    function cancelAssessment() internal {
        FathomToken(fathomToken).addBalance(assessee, cost*size, concept);
        FathomToken(fathomToken).notification(assessee, 3); //Assessment Cancled and you have been refunded
        for (uint i = 0; i < assessors.length; i++) {
            FathomToken(fathomToken).addBalance(assessors[i], cost, concept);
            FathomToken(fathomToken).notification(assessors[i], 3); //Assessment Cancled and you have been refunded
        }
        suicide(concept);
    }

    //@purpose: adds a user to the pool eligible to accept an assessment
    function addAssessorToPool(address assessor) onlyConcept() returns(bool) {
        if (assessor != assessee && assessorState[assessor] == State.None) {
            FathomToken(fathomToken).notification(assessor, 1); //Called As A Potential Assessor
            assessorState[assessor] = State.Called;
            return true;
        }
        else {
            return false;
        }
    }

    /*
      @purpose: To recursively set the pool to draw assessors from in the assessment
      stops when the pool of potential assessors is 20 times the size of the assessment2
      @param: uint seed = the seed number for random number generation
      @param: address _concept = the concept being called from
      @param: uint num = the total number of assessors to be called
    */
    function setAssessorPool(uint seed, address _concept, uint num) onlyConcept() {
        uint numCalled = 0;
        uint membersOfConcept = Concept(_concept).getMemberLength();
        //we want to call at most half of the members of each concept
        uint maxFromThisPool = num > membersOfConcept/2 ? membersOfConcept/2 : num;
        for (uint k=0; k < maxFromThisPool; k++) {
            address randomUser = Concept(_concept).getWeightedRandomMember(seed + k);
            if (randomUser != address(0x0) && addAssessorToPool(randomUser)) {
                numCalled++;
            }
        }
        uint remaining = num - numCalled;
        if (remaining > 0) {
            for (uint i = 0; i < Concept(_concept).getParentsLength(); i++) {
                setAssessorPool(seed + numCalled + i, Concept(_concept).parents(i), remaining/Concept(_concept).getParentsLength() + 1); //Calls the remaining users from the parent concepts proportional to their size
            }
        }
        assessmentStage = State.Called;
    }

    //@purpose: called by an assessor to confirm and stake
    function confirmAssessor() onlyInStage(State.Called) {
        // cancel if the assessment is older than 12 hours or already past its timelimit
        if (now > latestConfirmTime){
            cancelAssessment();
            return;
        }
        if (assessorState[msg.sender] == State.Called &&
            assessors.length < size &&
            Concept(concept).subtractBalance(msg.sender, cost)
            ) {
            assessors.push(msg.sender);
            assessorState[msg.sender] = State.Confirmed;
            FathomToken(fathomToken).notification(msg.sender, 2); //Confirmed for assessing, stake has been taken
        }
        if (assessors.length == size) {
            notifyAssessors(uint(State.Confirmed), 4);
            FathomToken(fathomToken).notification(assessee, 4);
            assessmentStage = State.Confirmed;
        }
    }

    //@purpose: called by an assessor to commit a hash of their score //TODO explain in more detail what's happening
    function commit(bytes32 _hash) onlyInStage(State.Confirmed) {
        if (now > endTime) {
            burnStakes();
        }
        if (assessorState[msg.sender] == State.Confirmed) {
                commits[msg.sender] = _hash;
                assessorState[msg.sender] = State.Committed;
                done++; //Increases done by 1 to help progress to the next assessment stage.
        }
        if (done == size) {
            notifyAssessors(uint(State.Committed), 5);
            done = 0; //Resets the done counter
            assessmentStage = State.Committed;
        }
    }

    function steal(int128 _score, string _salt, address assessor) {
        if(assessorState[assessor] == State.Committed) {
            if(commits[assessor] == sha3(_score, _salt)) {
                FathomToken(fathomToken).addBalance(msg.sender, cost/2, concept);
                assessorState[assessor] = State.Burned;
                size--;
            }
        }
    }

    //@purpose: called by assessors to reveal their own commits or others
    function reveal(int128 _score, string _salt) onlyInStage(State.Committed) {
        if (now > endTime + 12 hours) { //add bigger zerocheck
            for (uint i = 0; i < assessors.length; i++) {
                if (assessorState[assessors[i]] == State.Committed) { //If the assessor has not revealed their score
                    assessorState[assessors[i]] = State.Burned;
                    size--;
                }
            }
        }

        if(assessorState[msg.sender] == State.Committed &&
           commits[msg.sender] == sha3(_score, _salt)) {
                    scores[msg.sender] = _score;
                    assessorState[msg.sender] = State.Done;
                    done++;
        }

        if (done == size) {
            assessmentStage = State.Done;
            calculateResult();
        }
    }

    //@purpose: burns stakes as a function of how much time has passed since half of the assessors commited
    function burnStakes() internal {
        for (uint i = 0; i < assessors.length; i++) {
            if (assessorState[assessors[i]] == State.Confirmed) {
                assessorState[assessors[i]] = State.Burned;
                size--; //decrease size to help progress to the next assessment stage
           }
        }
    }

    function notifyAssessors(uint _state, uint _topic) private {
        for (uint i=0; i < assessors.length; i++) {
            if (uint(assessorState[assessors[i]]) == _state) {
                FathomToken(fathomToken).notification(assessors[i], _topic);
            }
        }
    }

    function calculateResult() onlyInStage(State.Done) private {
        int[] memory finalScores = new int[] (done);
        uint idx =0;
        for (uint j = 0; j < assessors.length; j++) {
            if (assessorState[assessors[j]] == State.Done) {
                finalScores[idx] = scores[assessors[j]];
                idx++;
            }
        }
        uint mad = Math.calculateMAD(finalScores);
        uint finalClusterLength;
        (finalScore, finalClusterLength) = Math.getFinalScore(finalScores, mad);
        payout(mad);
        if (finalScore > 0) {
            Concept(concept).addMember(assessee, uint(finalScore) * finalClusterLength);
        }
        FathomToken(fathomToken).notification(assessee, 7);
   }

    function payout(uint mad) onlyInStage(State.Done) internal {
        uint q = 1; //INFLATION RATE
        for (uint i = 0; i < assessors.length; i++) {
            if (assessorState[assessors[i]] == State.Done) {
                uint payoutValue = Math.getPayout(Math.abs(scores[assessors[i]] - finalScore), mad, cost, q);
                FathomToken(fathomToken).addBalance(assessors[i], payoutValue, concept);
                FathomToken(fathomToken).notification(assessors[i], 6); //You  got paid!
            }
        }
    }
}

pragma solidity ^0.4.11;

import "./Math.sol";
import "./Concept.sol";
import "./FathomToken.sol";

contract Assessment {
    address assessee;
    address[] assessors;

    mapping (address => State) assessorState;
    State public assessmentStage;
    enum State {
        None,
        Called,
        Confirmed,
        Committed,
        Done,
        Burned
    }

    address concept;
    address fathomToken;

    uint public endTime;
    uint public latestConfirmTime;

    uint public size;
    uint cost;

    mapping(address => bytes32) commits;
    uint public done; //counter how many assessors have committed/revealed their score
    mapping(address => int128) scores;
    int public finalScore;

    modifier onlyConcept() {
        require(msg.sender == concept);
        _;
    }

    modifier onlyInStage(State _stage) {
        require(assessmentStage == _stage);
        _;
    }

    function Assessment(address _assessee,
                        uint _size,
                        uint _cost,
                        uint _confirmTime,
                        uint _timeLimit) {
        assessee = _assessee;
        concept = msg.sender;
        fathomToken = Concept(concept).fathomToken();

        endTime = now + _timeLimit;
        latestConfirmTime = now + _confirmTime;
        assert(latestConfirmTime < endTime);

        size = _size;
        cost = _cost;

        FathomToken(fathomToken).notification(assessee, 0); // assesse has started an assessment
        done = 0;
    }

    function cancelAssessment() internal {
        FathomToken(fathomToken).addBalance(assessee, cost*size, concept);
        FathomToken(fathomToken).notification(assessee, 3); //Assessment Cancled and you have been refunded
        for (uint i = 0; i < assessors.length; i++) {
            FathomToken(fathomToken).addBalance(assessors[i], cost, concept);
            FathomToken(fathomToken).notification(assessors[i], 3); //Assessment Cancled and you have been refunded
        }
        suicide(concept);
    }

    //@purpose: adds a user to the pool eligible to accept an assessment
    function addAssessorToPool(address assessor) onlyConcept() returns(bool) {
        if (assessorState[assessor] == State.None) {
            FathomToken(fathomToken).notification(assessor, 1); //Called As A Potential Assessor
            assessorState[assessor] = State.Called;
            return true;
        }
        else {
            return false;
        }
    }

    /*
      @purpose: To recursively set the pool to draw assessors from in the assessment
      stops when the pool of potential assessors is 20 times the size of the assessment2
      @param: uint seed = the seed number for random number generation
      @param: address _concept = the concept being called from
      @param: uint num = the total number of assessors to be called
    */
    function setAssessorPool(uint seed, address _concept, uint num) onlyConcept() {
        uint numCalled = 0;
        uint membersOfConcept = Concept(_concept).getMemberLength();
        //we want to call at most half of the members of each concept
        uint maxFromThisPool = num > membersOfConcept/2 ? membersOfConcept/2 : num;
        for (uint k=0; k < maxFromThisPool; k++) {
            address randomUser = Concept(_concept).getWeightedRandomMember(seed + k);
            if (randomUser != address(0x0) && addAssessorToPool(randomUser)) {
                numCalled++;
            }
        }
        uint remaining = num - numCalled;
        if (remaining > 0) {
            for (uint i = 0; i < Concept(_concept).getParentsLength(); i++) {
                setAssessorPool(seed + numCalled + i, Concept(_concept).parents(i), remaining/Concept(_concept).getParentsLength() + 1); //Calls the remaining users from the parent concepts proportional to their size
            }
        }
        assessmentStage = State.Called;
    }

    //@purpose: called by an assessor to confirm and stake
    function confirmAssessor() onlyInStage(State.Called) {
        // cancel if the assessment is older than 12 hours or already past its timelimit
        if (now > latestConfirmTime){
            cancelAssessment();
            return;
        }
        if (assessorState[msg.sender] == State.Called &&
            assessors.length < size &&
            Concept(concept).subtractBalance(msg.sender, cost)
            ) {
            assessors.push(msg.sender);
            assessorState[msg.sender] = State.Confirmed;
            FathomToken(fathomToken).notification(msg.sender, 2); //Confirmed for assessing, stake has been taken
        }
        if (assessors.length == size) {
            notifyAssessors(uint(State.Confirmed), 4);
            FathomToken(fathomToken).notification(assessee, 4);
            assessmentStage = State.Confirmed;
        }
    }

    //@purpose: called by an assessor to commit a hash of their score //TODO explain in more detail what's happening
    function commit(bytes32 _hash) onlyInStage(State.Confirmed) {
        if (now > endTime) {
            burnStakes();
        }
        if (assessorState[msg.sender] == State.Confirmed) {
                commits[msg.sender] = _hash;
                assessorState[msg.sender] = State.Committed;
                done++; //Increases done by 1 to help progress to the next assessment stage.
        }
        if (done == size) {
            notifyAssessors(uint(State.Committed), 5);
            done = 0; //Resets the done counter
            assessmentStage = State.Committed;
        }
    }

    function steal(int128 _score, string _salt, address assessor) {
        if(assessorState[assessor] == State.Committed) {
            if(commits[assessor] == sha3(_score, _salt)) {
                FathomToken(fathomToken).addBalance(msg.sender, cost/2, concept);
                assessorState[assessor] = State.Burned;
                size--;
            }
        }
    }

    //@purpose: called by assessors to reveal their own commits or others
    function reveal(int128 _score, string _salt) onlyInStage(State.Committed) {
        if (now > endTime + 12 hours) { //add bigger zerocheck
            for (uint i = 0; i < assessors.length; i++) {
                if (assessorState[assessors[i]] == State.Committed) { //If the assessor has not revealed their score
                    assessorState[assessors[i]] = State.Burned;
                    size--;
                }
            }
        }

        if(assessorState[msg.sender] == State.Committed &&
           commits[msg.sender] == sha3(_score, _salt)) {
                    scores[msg.sender] = _score;
                    assessorState[msg.sender] = State.Done;
                    done++;
        }

        if (done == size) {
            assessmentStage = State.Done;
            calculateResult();
        }
    }

    //@purpose: burns stakes as a function of how much time has passed since half of the assessors commited
    function burnStakes() internal {
        for (uint i = 0; i < assessors.length; i++) {
            if (assessorState[assessors[i]] == State.Confirmed) {
                assessorState[assessors[i]] = State.Burned;
                size--; //decrease size to help progress to the next assessment stage
           }
        }
    }

    function notifyAssessors(uint _state, uint _topic) private {
        for (uint i=0; i < assessors.length; i++) {
            if (uint(assessorState[assessors[i]]) == _state) {
                FathomToken(fathomToken).notification(assessors[i], _topic);
            }
        }
    }

    function calculateResult() onlyInStage(State.Done) private {
        int[] memory finalScores = new int[] (done);
        uint idx =0;
        for (uint j = 0; j < assessors.length; j++) {
            if (assessorState[assessors[j]] == State.Done) {
                finalScores[idx] = scores[assessors[j]];
                idx++;
            }
        }
        uint mad = Math.calculateMAD(finalScores);
        uint finalClusterLength;
        (finalScore, finalClusterLength) = Math.getFinalScore(finalScores, mad);
        payout(mad);
        if (finalScore > 0) {
            Concept(concept).addMember(assessee, uint(finalScore) * finalClusterLength);
        }
        FathomToken(fathomToken).notification(assessee, 7);
   }

    function payout(uint mad) onlyInStage(State.Done) internal {
        uint q = 1; //INFLATION RATE
        for (uint i = 0; i < assessors.length; i++) {
            if (assessorState[assessors[i]] == State.Done) {
                uint payoutValue = Math.getPayout(Math.abs(scores[assessors[i]] - finalScore), mad, cost, q);
                FathomToken(fathomToken).addBalance(assessors[i], payoutValue, concept);
                FathomToken(fathomToken).notification(assessors[i], 6); //You  got paid!
            }
        }
    }
}


Change group admin

Change group admin

pragma solidity ^0.4.19;
import './zeppelin/ownership/Ownable.sol';

/**
 * @title GroupAdmin
 * @dev The contract allows multiple addresses to perform as admin.
 */
contract GroupAdmin is Ownable {
  event AdminGranted(address indexed grantee);
  event AdminRevoked(address indexed grantee);
  address[] public admins;

  modifier onlyAdmin() {
    require(isAdmin(msg.sender));
    _;
  }

  function grant(address[] newAdmins) public onlyOwner{
    for(uint i=0;i<newAdmins.length;i++){
      admins.push(newAdmins[i]);
      AdminGranted(newAdmins[i]);
    }
  }

  function revoke(address[] oldAdmins) public onlyOwner{
    for(uint i=0;i<oldAdmins.length;i++){
        for (uint j = 0; j < admins.length; ++i) {
            if (admins[j] == oldAdmins[i]) {
                admins[j] = admins[admins.length - 1];
                admins.length--;
                AdminRevoked(oldAdmins[i]);
                break;
            }
        }
    }
  }

  function getAdmins() view public returns(address[]){
    // todo: include owner;
    return admins;
  }

  function numOfAdmins() view public returns(uint){
      return admins.length;
  }

  function isAdmin(address admin) public view returns(bool){
    if (admin == owner) return true;
    for(uint i=0;i<admins.length;i++){
      if(admins[i] == admin){
        return true;
      }
    }
    return false;
  }
}

pragma solidity ^0.4.19;
import './zeppelin/ownership/Ownable.sol';

/**
 * @title GroupAdmin
 * @dev The contract allows multiple addresses to perform as admin.
 */
contract GroupAdmin is Ownable {
  event AdminGranted(address indexed grantee);
  event AdminRevoked(address indexed grantee);
  mapping(address=>bool) internal admins;

  modifier onlyAdmin() {
    require(admins[msg.sender] || msg.sender == owner);
    _;
  }

  function grant(address newAdmin) public onlyOwner{
    admins[newAdmin] = true;
    AdminGranted(newAdmin);
  }

  function revoke(address oldAdmin) public onlyOwner{
    admins[oldAdmin] = false;
    AdminRevoked(oldAdmin);
  }

  function isAdmin(address admin) public view returns(bool){
    return(admins[admin] || admin == owner);
  }
}


Add payable to MultisigWalletMock()

Add payable to MultisigWalletMock()

pragma solidity ^0.4.4;
import "../MultisigWallet.sol";

contract MultisigWalletMock is MultisigWallet {
  uint public totalSpending;

  function MultisigWalletMock(address[] _owners, uint _required, uint _daylimit)
    MultisigWallet(_owners, _required, _daylimit) payable { }

  function changeOwner(address _from, address _to) external { }

}

pragma solidity ^0.4.4;
import "../MultisigWallet.sol";

contract MultisigWalletMock is MultisigWallet {
  uint public totalSpending;

  function MultisigWalletMock(address[] _owners, uint _required, uint _daylimit)
    MultisigWallet(_owners, _required, _daylimit) { }

  function changeOwner(address _from, address _to) external { }

}