Sanity check against wrapper owning a token that is about to be reminted

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

import "./ERC1155Fuse.sol";
import "./Controllable.sol";
import "../interfaces/INameWrapper.sol";
import "../interfaces/IMetadataService.sol";
import "@ensdomains/ens-contracts/contracts/registry/ENS.sol";
import "@ensdomains/ens-contracts/contracts/ethregistrar/BaseRegistrar.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "./BytesUtil.sol";
import "hardhat/console.sol";

contract NameWrapper is
    Ownable,
    ERC1155Fuse,
    INameWrapper,
    Controllable,
    IERC721Receiver
{
    using BytesUtils for bytes;
    ENS public immutable ens;
    BaseRegistrar public immutable registrar;
    IMetadataService public metadataService;
    mapping(bytes32 => bytes) public names;

    bytes32 private constant ETH_NODE =
        0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae;
    bytes32 private constant ROOT_NODE =
        0x0000000000000000000000000000000000000000000000000000000000000000;

    constructor(
        ENS _ens,
        BaseRegistrar _registrar,
        IMetadataService _metadataService
    ) {
        ens = _ens;
        registrar = _registrar;
        metadataService = _metadataService;

        /* Burn CANNOT_REPLACE_SUBDOMAIN and CANNOT_UNWRAP fuses for ROOT_NODE and ETH_NODE */

        _setData(
            uint256(ETH_NODE),
            address(0x0),
            uint96(CANNOT_REPLACE_SUBDOMAIN | CANNOT_UNWRAP)
        );
        _setData(
            uint256(ROOT_NODE),
            address(0x0),
            uint96(CANNOT_REPLACE_SUBDOMAIN | CANNOT_UNWRAP)
        );
        names[ROOT_NODE] = "\x00";
        names[ETH_NODE] = "\x03eth\x00";
    }

    function supportsInterface(bytes4 interfaceId)
        public
        view
        virtual
        override(ERC1155Fuse, IERC165)
        returns (bool)
    {
        return
            interfaceId == type(INameWrapper).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    /* Metadata service */

    /**
     * @notice Set the metadata service. only admin can do this
     */

    function setMetadataService(IMetadataService _newMetadataService)
        public
        onlyOwner()
    {
        metadataService = _newMetadataService;
    }

    /**
     * @notice Get the metadata uri
     * @return String uri of the metadata service
     */

    function uri(uint256 tokenId) public view override returns (string memory) {
        return metadataService.uri(tokenId);
    }

    /**
     * @notice Checks if msg.sender is the owner or approved by the owner of a name
     * @param node namehash of the name to check
     */

    modifier onlyTokenOwner(bytes32 node) {
        require(
            isTokenOwnerOrApproved(node, msg.sender),
            "NameWrapper: msg.sender is not the owner or approved"
        );
        _;
    }

    /**
     * @notice Checks if owner or approved by owner
     * @param node namehash of the name to check
     * @param addr which address to check permissions for
     * @return whether or not is owner or approved
     */

    function isTokenOwnerOrApproved(bytes32 node, address addr)
        public
        view
        override
        returns (bool)
    {
        return
            ownerOf(uint256(node)) == addr ||
            isApprovedForAll(ownerOf(uint256(node)), addr);
    }

    /**
     * @notice Gets fuse permissions for a specific name
     * @dev Fuses are represented by a uint96 where each permission is represented by 1 bit
     *      The interface has predefined fuses for all registry permissions, but additional
     *      fuses can be added for other use cases
     * @param node namehash of the name to check
     * @return fuses A number that represents the permissions a name has
     * @return vulnerability The type of vulnerability
     * @return vulnerableNode Which node is vulnerable
     */
    function getFuses(bytes32 node)
        public
        view
        override
        returns (
            uint96 fuses,
            NameSafety vulnerability,
            bytes32 vulnerableNode
        )
    {
        bytes memory name = names[node];
        require(name.length > 0, "NameWrapper: Name not found");
        (, vulnerability, vulnerableNode) = _checkHierarchy(name, 0);
        (, fuses) = getData(uint256(node));
    }

    /**
     * @notice Wraps a .eth domain, creating a new token and sending the original ERC721 token to this *         contract
     * @dev Can be called by the owner of the name in the .eth registrar or an authorised caller on the *      registrar
     * @param label label as a string of the .eth domain to wrap
     * @param _fuses initial fuses to set
     * @param wrappedOwner Owner of the name in this contract
     */

    function wrapETH2LD(
        string calldata label,
        address wrappedOwner,
        uint96 _fuses,
        address resolver
    ) public override {
        bytes32 labelhash = keccak256(bytes(label));
        uint256 tokenId = uint256(labelhash);
        address owner = registrar.ownerOf(tokenId);

        require(
            owner == msg.sender ||
                isApprovedForAll(owner, msg.sender) ||
                registrar.isApprovedForAll(owner, msg.sender),
            "NameWrapper: Sender is not owner or authorised by the owner or authorised on the .eth registrar"
        );

        // transfer the ens record back to the new owner (this contract)
        registrar.reclaim(uint256(labelhash), address(this));

        _wrapETH2LD(label, wrappedOwner, _fuses, resolver);

        // transfer the token from the user to this contract
        registrar.transferFrom(owner, address(this), tokenId);
    }

    /**
     * @dev Registers a new .eth second-level domain and wraps it.
     *      Only callable by authorised controllers.
     * @param label The label to register (Eg, 'foo' for 'foo.eth').
     * @param wrappedOwner The owner of the wrapped name.
     * @param duration The duration, in seconds, to register the name for.
     * @param resolver The resolver address to set on the ENS registry (optional).
     * @return expires The expiry date of the new name, in seconds since the Unix epoch.
     */
    function registerAndWrapETH2LD(
        string calldata label,
        address wrappedOwner,
        uint256 duration,
        address resolver,
        uint96 _fuses
    ) external override onlyController returns (uint256 expires) {
        bytes32 labelhash = keccak256(bytes(label));
        uint256 tokenId = uint256(labelhash);

        expires = registrar.register(tokenId, address(this), duration);
        _wrapETH2LD(label, wrappedOwner, _fuses, resolver);
    }

    /**
     * @dev Renews a .eth second-level domain.
     *      Only callable by authorised controllers.
     * @param labelHash The hash of the label to register (eg, `keccak256('foo')`, for 'foo.eth').
     * @param duration The number of seconds to renew the name for.
     * @return expires The expiry date of the name, in seconds since the Unix epoch.
     */
    function renew(uint256 labelHash, uint256 duration)
        external
        override
        onlyController
        returns (uint256 expires)
    {
        return registrar.renew(labelHash, duration);
    }

    /**
     * @notice Wraps a non .eth domain, of any kind. Could be a DNSSEC name vitalik.xyz or a subdomain
     * @dev Can be called by the owner in the registry or an authorised caller in the registry
     * @param name The name to wrap, in DNS format
     * @param _fuses initial fuses to set represented as a number. Check getFuses() for more info
     * @param wrappedOwner Owner of the name in this contract
     */

    function wrap(
        bytes calldata name,
        address wrappedOwner,
        uint96 _fuses,
        address resolver
    ) public override {
        (bytes32 node, bytes32 parentNode, ) = _storeNamehash(name);
        address owner = ens.owner(node);
        require(
            owner == msg.sender ||
                isApprovedForAll(owner, msg.sender) ||
                ens.isApprovedForAll(owner, msg.sender),
            "NameWrapper: Domain is not owned by the sender"
        );

        if (resolver != address(0)) {
            ens.setResolver(node, resolver);
        }

        _wrap(name, node, parentNode, wrappedOwner, _fuses);
        ens.setOwner(node, address(this));
    }

    /**
     * @notice Unwraps a .eth domain. e.g. vitalik.eth
     * @dev Can be called by the owner in the wrapper or an authorised caller in the wrapper
     * @param label label as a string of the .eth domain to wrap e.g. vitalik.xyz would be 'vitalik'
     * @param newRegistrant sets the owner in the .eth registrar to this address
     * @param newController sets the owner in the registry to this address
     */

    function unwrapETH2LD(
        bytes32 label,
        address newRegistrant,
        address newController
    ) public override onlyTokenOwner(_makeNode(ETH_NODE, label)) {
        _unwrap(_makeNode(ETH_NODE, label), newController);
        registrar.transferFrom(address(this), newRegistrant, uint256(label));
    }

    /**
     * @notice Unwraps a non .eth domain, of any kind. Could be a DNSSEC name vitalik.xyz or a subdomain
     * @dev Can be called by the owner in the wrapper or an authorised caller in the wrapper
     * @param parentNode parent namehash of the name to wrap e.g. vitalik.xyz would be namehash('xyz')
     * @param label label as a string of the .eth domain to wrap e.g. vitalik.xyz would be 'vitalik'
     * @param newController sets the owner in the registry to this address
     */

    function unwrap(
        bytes32 parentNode,
        bytes32 label,
        address newController
    ) public override onlyTokenOwner(_makeNode(parentNode, label)) {
        require(
            parentNode != ETH_NODE,
            "NameWrapper: .eth names must be unwrapped with unwrapETH2LD()"
        );
        _unwrap(_makeNode(parentNode, label), newController);
    }

    /**
     * @notice Burns any fuse passed to this function for a name
     * @dev Fuse burns are always additive and will not unburn already burnt fuses
     * @param node namehash of the name. e.g. vitalik.xyz would be namehash('vitalik.xyz')
     * @param _fuses Fuses you want to burn.
     */

    function burnFuses(bytes32 node, uint96 _fuses)
        public
        override
        onlyTokenOwner(node)
        operationAllowed(node, CANNOT_BURN_FUSES)
    {
        (address owner, uint96 fuses) = getData(uint256(node));

        uint96 newFuses = fuses | _fuses;

        _setData(uint256(node), owner, newFuses);

        emit FusesBurned(node, newFuses);
    }

    /**
     * @notice Sets records for the subdomain in the ENS Registry
     * @param parentNode namehash of the parent name
     * @param label labelhash of the subnode
     * @param owner newOwner in the registry
     * @param resolver the resolver contract in the registry
     * @param ttl ttl in the registry
     */

    function setSubnodeRecord(
        bytes32 parentNode,
        bytes32 label,
        address owner,
        address resolver,
        uint64 ttl
    )
        public
        override
        onlyTokenOwner(parentNode)
        canCallSetSubnodeOwner(parentNode, label)
    {
        ens.setSubnodeRecord(parentNode, label, owner, resolver, ttl);
    }

    /**
     * @notice Sets the subnode owner in the registry
     * @param parentNode namehash of the parent name
     * @param label labelhash of the subnode
     * @param owner newOwner in the registry
     */

    function setSubnodeOwner(
        bytes32 parentNode,
        bytes32 label,
        address owner
    )
        public
        override
        onlyTokenOwner(parentNode)
        canCallSetSubnodeOwner(parentNode, label)
        returns (bytes32)
    {
        return ens.setSubnodeOwner(parentNode, label, owner);
    }

    /**
     * @notice Sets the subdomain owner in the registry and then wraps the subdomain
     * @param parentNode parent namehash of the subdomain
     * @param label label of the subdomain as a string
     * @param newOwner newOwner in the registry
     * @param _fuses initial fuses for the wrapped subdomain
     */

    function setSubnodeOwnerAndWrap(
        bytes32 parentNode,
        string calldata label,
        address newOwner,
        uint96 _fuses
    ) public override returns (bytes32 node) {
        bytes32 labelhash;
        bytes memory name = _addLabel(label, names[parentNode]);
        (node, , labelhash) = _storeNamehash(name);
        setSubnodeOwner(parentNode, labelhash, address(this));
        _wrap(name, node, parentNode, newOwner, _fuses);
    }

    /**
     * @notice Sets the subdomain owner in the registry with records and then wraps the subdomain
     * @param parentNode parent namehash of the subdomain
     * @param label label of the subdomain as a string
     * @param newOwner newOwner in the registry
     * @param resolver resolver contract in the registry
     * @param ttl ttl in the regsitry
     * @param _fuses initial fuses for the wrapped subdomain
     */

    function setSubnodeRecordAndWrap(
        bytes32 parentNode,
        string calldata label,
        address newOwner,
        address resolver,
        uint64 ttl,
        uint96 _fuses
    ) public override {
        bytes memory name = _addLabel(label, names[parentNode]);
        (bytes32 node, , bytes32 labelhash) = _storeNamehash(name);
        setSubnodeRecord(parentNode, labelhash, address(this), resolver, ttl);
        _wrap(name, node, parentNode, newOwner, _fuses);
    }

    /**
     * @notice Sets records for the name in the ENS Registry
     * @param node namehash of the name to set a record for
     * @param owner newOwner in the registry
     * @param resolver the resolver contract
     * @param ttl ttl in the registry
     */

    function setRecord(
        bytes32 node,
        address owner,
        address resolver,
        uint64 ttl
    )
        public
        override
        onlyTokenOwner(node)
        operationAllowed(
            node,
            CANNOT_TRANSFER | CANNOT_SET_RESOLVER | CANNOT_SET_TTL
        )
    {
        ens.setRecord(node, owner, resolver, ttl);
    }

    /**
     * @notice Sets resolver contract in the registry
     * @param node namehash of the name
     * @param resolver the resolver contract
     */

    function setResolver(bytes32 node, address resolver)
        public
        override
        onlyTokenOwner(node)
        operationAllowed(node, CANNOT_SET_RESOLVER)
    {
        ens.setResolver(node, resolver);
    }

    /**
     * @notice Sets TTL in the registry
     * @param node namehash of the name
     * @param ttl TTL in the registry
     */

    function setTTL(bytes32 node, uint64 ttl)
        public
        override
        onlyTokenOwner(node)
        operationAllowed(node, CANNOT_SET_TTL)
    {
        ens.setTTL(node, ttl);
    }

    /**
     * @dev Allows an operation only if none of the specified fuses are burned.
     * @param node The namehash of the name to check fuses on.
     * @param fuseMask A bitmask of fuses that must not be burned.
     */
    modifier operationAllowed(bytes32 node, uint96 fuseMask) {
        (, uint96 fuses) = getData(uint256(node));
        require(
            fuses & fuseMask == 0,
            "NameWrapper: Operation prohibited by fuses"
        );
        _;
    }

    /**
     * @notice Check whether a name can call setSubnodeOwner/setSubnodeRecord
     * @dev Checks both canCreateSubdomain and canReplaceSubdomain and whether not they have been burnt
     *      and checks whether the owner of the subdomain is 0x0 for creating or already exists for
     *      replacing a subdomain. If either conditions are true, then it is possible to call
     *      setSubnodeOwner
     * @param node namehash of the name to check
     * @param label labelhash of the name to check
     */

    modifier canCallSetSubnodeOwner(bytes32 node, bytes32 label) {
        bytes32 subnode = _makeNode(node, label);
        address owner = ens.owner(subnode);
        (, uint96 fuses) = getData(uint256(node));

        require(
            (owner == address(0) && fuses & CANNOT_CREATE_SUBDOMAIN == 0) ||
                (owner != address(0) && fuses & CANNOT_REPLACE_SUBDOMAIN == 0),
            "NameWrapper: Operation prohibited by fuses"
        );
        _;
    }

    /**
     * @notice Checks all Fuses in the mask are burned for the node
     * @param node namehash of the name
     * @param fuseMask the fuses you want to check
     * @return Boolean of whether or not all the selected fuses are burned
     */

    function allFusesBurned(bytes32 node, uint96 fuseMask)
        public
        view
        override
        returns (bool)
    {
        (, uint96 fuses) = getData(uint256(node));
        return fuses & fuseMask == fuseMask;
    }

    function onERC721Received(
        address to,
        address,
        uint256 tokenId,
        bytes calldata data
    ) public override returns (bytes4) {
        //check if it's the eth registrar ERC721
        require(
            msg.sender == address(registrar),
            "NameWrapper: Wrapper only supports .eth ERC721 token transfers"
        );

        (
            string memory label,
            address owner,
            uint96 fuses,
            address resolver
        ) = abi.decode(data, (string, address, uint96, address));

        require(
            keccak256(bytes(label)) == bytes32(tokenId),
            "NameWrapper: Token id does match keccak(label) of label provided in data field"
        );

        bytes32 labelhash = keccak256(bytes(label));

        // transfer the ens record back to the new owner (this contract)
        registrar.reclaim(uint256(labelhash), address(this));

        _wrapETH2LD(label, owner, fuses, resolver);

        return IERC721Receiver(to).onERC721Received.selector;
    }

    /***** Internal functions */

    function _canTransfer(uint96 fuses) internal pure override returns (bool) {
        return fuses & CANNOT_TRANSFER == 0;
    }

    function _makeNode(bytes32 node, bytes32 label)
        private
        pure
        returns (bytes32)
    {
        return keccak256(abi.encodePacked(node, label));
    }

    function _addLabel(string memory label, bytes memory name)
        internal
        pure
        returns (bytes memory ret)
    {
        require(bytes(label).length > 0, "NameWrapper: Label too short");
        require(bytes(label).length < 256, "NameWrapper: Label too long");
        return abi.encodePacked(uint8(bytes(label).length), label, name);
    }

    function _mint(
        bytes32 node,
        address wrappedOwner,
        uint96 _fuses
    ) internal override {
        address oldWrappedOwner = ownerOf(uint256(node));
        if (oldWrappedOwner != address(0)) {
            // sanity check that a new token isn't owned by the wrapper
            assert(oldWrappedOwner != address(this));
            // burn and unwrap old token of old owner
            _burn(uint256(node));
            emit NameUnwrapped(node, address(0));
        }
        super._mint(node, wrappedOwner, _fuses);
    }

    function _wrap(
        bytes memory name,
        bytes32 node,
        bytes32 parentNode,
        address wrappedOwner,
        uint96 _fuses
    ) private {
        require(
            parentNode != ETH_NODE,
            "NameWrapper: .eth domains need to use wrapETH2LD()"
        );

        _mint(node, wrappedOwner, _fuses);
        emit NameWrapped(node, name, wrappedOwner, _fuses);
    }

    function _wrapETH2LD(
        string memory label,
        address wrappedOwner,
        uint96 _fuses,
        address resolver
    ) private returns (bytes32 labelhash) {
        labelhash = keccak256(bytes(label));
        // mint a new ERC1155 token with fuses
        bytes memory name = _addLabel(label, "\x03eth\x00");
        (bytes32 node, , ) = _storeNamehash(name);

        if (resolver != address(0)) {
            ens.setResolver(node, resolver);
        }

        _mint(node, wrappedOwner, _fuses);

        emit NameWrapped(node, name, wrappedOwner, _fuses);
    }

    function _unwrap(bytes32 node, address newOwner) private {
        require(
            newOwner != address(0x0),
            "NameWrapper: Target owner cannot be 0x0"
        );
        require(
            newOwner != address(this),
            "NameWrapper: Target owner cannot be the NameWrapper contract"
        );
        require(
            !allFusesBurned(node, CANNOT_UNWRAP),
            "NameWrapper: Domain is not unwrappable"
        );

        // burn token and fuse data
        _burn(uint256(node));
        ens.setOwner(node, newOwner);

        emit NameUnwrapped(node, newOwner);
    }

    function _setData(
        uint256 tokenId,
        address owner,
        uint96 fuses
    ) internal override {
        require(
            fuses == CAN_DO_EVERYTHING || fuses & CANNOT_UNWRAP != 0,
            "NameWrapper: Cannot burn fuses: domain can be unwrapped"
        );
        super._setData(tokenId, owner, fuses);
    }

    /**
     * @dev Internal function that checks all a name's ancestors to ensure fuse values will be respected and parent controller/registrant are set to the Wrapper
     * @param name The name to check.
     * @param offset The offset into the name to start at.
     * @return node The calculated namehash for this part of the name.
     * @return vulnerability what kind of vulnerability the node has
     * @return vulnerableNode which node is at risk
     */
    function _checkHierarchy(bytes memory name, uint256 offset)
        internal
        view
        returns (
            bytes32 node,
            NameSafety vulnerability,
            bytes32 vulnerableNode
        )
    {
        // Read the first label. If it's the root, return immediately.
        (bytes32 labelhash, uint256 newOffset) = name.readLabel(offset);
        if (labelhash == bytes32(0)) {
            // Root node
            return (bytes32(0), NameSafety.Safe, 0);
        }

        // Check the parent name
        bytes32 parentNode;
        (parentNode, vulnerability, vulnerableNode) = _checkHierarchy(
            name,
            newOffset
        );

        node = _makeNode(parentNode, labelhash);

        // stop function checking any other nodes if a parent is not safe
        if (vulnerability != NameSafety.Safe) {
            return (node, vulnerability, vulnerableNode);
        }

        // Check the parent name's fuses to see if replacing subdomains is forbidden
        if (parentNode == ROOT_NODE) {
            // Save ourselves some gas; root node can't be replaced
            return (node, NameSafety.Safe, 0);
        }

        (vulnerability, vulnerableNode) = _checkOwnership(
            labelhash,
            node,
            parentNode
        );

        if (vulnerability != NameSafety.Safe) {
            return (node, vulnerability, vulnerableNode);
        }

        if (!allFusesBurned(parentNode, CANNOT_REPLACE_SUBDOMAIN)) {
            return (node, NameSafety.SubdomainReplacementAllowed, parentNode);
        }

        return (node, NameSafety.Safe, 0);
    }

    function _checkOwnership(
        bytes32 labelhash,
        bytes32 node,
        bytes32 parentNode
    ) internal view returns (NameSafety vulnerability, bytes32 vulnerableNode) {
        if (parentNode == ETH_NODE) {
            // Special case .eth: Check registrant or name isexpired

            try registrar.ownerOf(uint256(labelhash)) returns (
                address registrarOwner
            ) {
                if (registrarOwner != address(this)) {
                    return (NameSafety.RegistrantNotWrapped, node);
                }
            } catch {
                return (NameSafety.Expired, node);
            }
        }

        if (ens.owner(node) != address(this)) {
            return (NameSafety.ControllerNotWrapped, node);
        }
    }

    function _storeNamehash(bytes memory name)
        internal
        returns (
            bytes32 node,
            bytes32 parentNode,
            bytes32 labelhash
        )
    {
        (bytes32 currentLabelhash, uint256 offset) = name.readLabel(0);
        labelhash = currentLabelhash;
        parentNode = name.namehash(offset);
        node = _makeNode(parentNode, labelhash);
        names[node] = name;
    }
}

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

import "./ERC1155Fuse.sol";
import "./Controllable.sol";
import "../interfaces/INameWrapper.sol";
import "../interfaces/IMetadataService.sol";
import "@ensdomains/ens-contracts/contracts/registry/ENS.sol";
import "@ensdomains/ens-contracts/contracts/ethregistrar/BaseRegistrar.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "./BytesUtil.sol";
import "hardhat/console.sol";

contract NameWrapper is
    Ownable,
    ERC1155Fuse,
    INameWrapper,
    Controllable,
    IERC721Receiver
{
    using BytesUtils for bytes;
    ENS public immutable ens;
    BaseRegistrar public immutable registrar;
    IMetadataService public metadataService;
    mapping(bytes32 => bytes) public names;

    bytes32 private constant ETH_NODE =
        0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae;
    bytes32 private constant ROOT_NODE =
        0x0000000000000000000000000000000000000000000000000000000000000000;

    constructor(
        ENS _ens,
        BaseRegistrar _registrar,
        IMetadataService _metadataService
    ) {
        ens = _ens;
        registrar = _registrar;
        metadataService = _metadataService;

        /* Burn CANNOT_REPLACE_SUBDOMAIN and CANNOT_UNWRAP fuses for ROOT_NODE and ETH_NODE */

        _setData(
            uint256(ETH_NODE),
            address(0x0),
            uint96(CANNOT_REPLACE_SUBDOMAIN | CANNOT_UNWRAP)
        );
        _setData(
            uint256(ROOT_NODE),
            address(0x0),
            uint96(CANNOT_REPLACE_SUBDOMAIN | CANNOT_UNWRAP)
        );
        names[ROOT_NODE] = "\x00";
        names[ETH_NODE] = "\x03eth\x00";
    }

    function supportsInterface(bytes4 interfaceId)
        public
        view
        virtual
        override(ERC1155Fuse, IERC165)
        returns (bool)
    {
        return
            interfaceId == type(INameWrapper).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    /* Metadata service */

    /**
     * @notice Set the metadata service. only admin can do this
     */

    function setMetadataService(IMetadataService _newMetadataService)
        public
        onlyOwner()
    {
        metadataService = _newMetadataService;
    }

    /**
     * @notice Get the metadata uri
     * @return String uri of the metadata service
     */

    function uri(uint256 tokenId) public view override returns (string memory) {
        return metadataService.uri(tokenId);
    }

    /**
     * @notice Checks if msg.sender is the owner or approved by the owner of a name
     * @param node namehash of the name to check
     */

    modifier onlyTokenOwner(bytes32 node) {
        require(
            isTokenOwnerOrApproved(node, msg.sender),
            "NameWrapper: msg.sender is not the owner or approved"
        );
        _;
    }

    /**
     * @notice Checks if owner or approved by owner
     * @param node namehash of the name to check
     * @param addr which address to check permissions for
     * @return whether or not is owner or approved
     */

    function isTokenOwnerOrApproved(bytes32 node, address addr)
        public
        view
        override
        returns (bool)
    {
        return
            ownerOf(uint256(node)) == addr ||
            isApprovedForAll(ownerOf(uint256(node)), addr);
    }

    /**
     * @notice Gets fuse permissions for a specific name
     * @dev Fuses are represented by a uint96 where each permission is represented by 1 bit
     *      The interface has predefined fuses for all registry permissions, but additional
     *      fuses can be added for other use cases
     * @param node namehash of the name to check
     * @return fuses A number that represents the permissions a name has
     * @return vulnerability The type of vulnerability
     * @return vulnerableNode Which node is vulnerable
     */
    function getFuses(bytes32 node)
        public
        view
        override
        returns (
            uint96 fuses,
            NameSafety vulnerability,
            bytes32 vulnerableNode
        )
    {
        bytes memory name = names[node];
        require(name.length > 0, "NameWrapper: Name not found");
        (, vulnerability, vulnerableNode) = _checkHierarchy(name, 0);
        (, fuses) = getData(uint256(node));
    }

    /**
     * @notice Wraps a .eth domain, creating a new token and sending the original ERC721 token to this *         contract
     * @dev Can be called by the owner of the name in the .eth registrar or an authorised caller on the *      registrar
     * @param label label as a string of the .eth domain to wrap
     * @param _fuses initial fuses to set
     * @param wrappedOwner Owner of the name in this contract
     */

    function wrapETH2LD(
        string calldata label,
        address wrappedOwner,
        uint96 _fuses,
        address resolver
    ) public override {
        bytes32 labelhash = keccak256(bytes(label));
        uint256 tokenId = uint256(labelhash);
        address owner = registrar.ownerOf(tokenId);

        require(
            owner == msg.sender ||
                isApprovedForAll(owner, msg.sender) ||
                registrar.isApprovedForAll(owner, msg.sender),
            "NameWrapper: Sender is not owner or authorised by the owner or authorised on the .eth registrar"
        );

        // transfer the ens record back to the new owner (this contract)
        registrar.reclaim(uint256(labelhash), address(this));

        _wrapETH2LD(label, wrappedOwner, _fuses, resolver);

        // transfer the token from the user to this contract
        registrar.transferFrom(owner, address(this), tokenId);
    }

    /**
     * @dev Registers a new .eth second-level domain and wraps it.
     *      Only callable by authorised controllers.
     * @param label The label to register (Eg, 'foo' for 'foo.eth').
     * @param wrappedOwner The owner of the wrapped name.
     * @param duration The duration, in seconds, to register the name for.
     * @param resolver The resolver address to set on the ENS registry (optional).
     * @return expires The expiry date of the new name, in seconds since the Unix epoch.
     */
    function registerAndWrapETH2LD(
        string calldata label,
        address wrappedOwner,
        uint256 duration,
        address resolver,
        uint96 _fuses
    ) external override onlyController returns (uint256 expires) {
        bytes32 labelhash = keccak256(bytes(label));
        uint256 tokenId = uint256(labelhash);

        expires = registrar.register(tokenId, address(this), duration);
        _wrapETH2LD(label, wrappedOwner, _fuses, resolver);
    }

    /**
     * @dev Renews a .eth second-level domain.
     *      Only callable by authorised controllers.
     * @param labelHash The hash of the label to register (eg, `keccak256('foo')`, for 'foo.eth').
     * @param duration The number of seconds to renew the name for.
     * @return expires The expiry date of the name, in seconds since the Unix epoch.
     */
    function renew(uint256 labelHash, uint256 duration)
        external
        override
        onlyController
        returns (uint256 expires)
    {
        return registrar.renew(labelHash, duration);
    }

    /**
     * @notice Wraps a non .eth domain, of any kind. Could be a DNSSEC name vitalik.xyz or a subdomain
     * @dev Can be called by the owner in the registry or an authorised caller in the registry
     * @param name The name to wrap, in DNS format
     * @param _fuses initial fuses to set represented as a number. Check getFuses() for more info
     * @param wrappedOwner Owner of the name in this contract
     */

    function wrap(
        bytes calldata name,
        address wrappedOwner,
        uint96 _fuses,
        address resolver
    ) public override {
        (bytes32 node, bytes32 parentNode, ) = _storeNamehash(name);
        address owner = ens.owner(node);
        require(
            owner == msg.sender ||
                isApprovedForAll(owner, msg.sender) ||
                ens.isApprovedForAll(owner, msg.sender),
            "NameWrapper: Domain is not owned by the sender"
        );

        if (resolver != address(0)) {
            ens.setResolver(node, resolver);
        }

        _wrap(name, node, parentNode, wrappedOwner, _fuses);
        ens.setOwner(node, address(this));
    }

    /**
     * @notice Unwraps a .eth domain. e.g. vitalik.eth
     * @dev Can be called by the owner in the wrapper or an authorised caller in the wrapper
     * @param label label as a string of the .eth domain to wrap e.g. vitalik.xyz would be 'vitalik'
     * @param newRegistrant sets the owner in the .eth registrar to this address
     * @param newController sets the owner in the registry to this address
     */

    function unwrapETH2LD(
        bytes32 label,
        address newRegistrant,
        address newController
    ) public override onlyTokenOwner(_makeNode(ETH_NODE, label)) {
        _unwrap(_makeNode(ETH_NODE, label), newController);
        registrar.transferFrom(address(this), newRegistrant, uint256(label));
    }

    /**
     * @notice Unwraps a non .eth domain, of any kind. Could be a DNSSEC name vitalik.xyz or a subdomain
     * @dev Can be called by the owner in the wrapper or an authorised caller in the wrapper
     * @param parentNode parent namehash of the name to wrap e.g. vitalik.xyz would be namehash('xyz')
     * @param label label as a string of the .eth domain to wrap e.g. vitalik.xyz would be 'vitalik'
     * @param newController sets the owner in the registry to this address
     */

    function unwrap(
        bytes32 parentNode,
        bytes32 label,
        address newController
    ) public override onlyTokenOwner(_makeNode(parentNode, label)) {
        require(
            parentNode != ETH_NODE,
            "NameWrapper: .eth names must be unwrapped with unwrapETH2LD()"
        );
        _unwrap(_makeNode(parentNode, label), newController);
    }

    /**
     * @notice Burns any fuse passed to this function for a name
     * @dev Fuse burns are always additive and will not unburn already burnt fuses
     * @param node namehash of the name. e.g. vitalik.xyz would be namehash('vitalik.xyz')
     * @param _fuses Fuses you want to burn.
     */

    function burnFuses(bytes32 node, uint96 _fuses)
        public
        override
        onlyTokenOwner(node)
        operationAllowed(node, CANNOT_BURN_FUSES)
    {
        (address owner, uint96 fuses) = getData(uint256(node));

        uint96 newFuses = fuses | _fuses;

        _setData(uint256(node), owner, newFuses);

        emit FusesBurned(node, newFuses);
    }

    /**
     * @notice Sets records for the subdomain in the ENS Registry
     * @param parentNode namehash of the parent name
     * @param label labelhash of the subnode
     * @param owner newOwner in the registry
     * @param resolver the resolver contract in the registry
     * @param ttl ttl in the registry
     */

    function setSubnodeRecord(
        bytes32 parentNode,
        bytes32 label,
        address owner,
        address resolver,
        uint64 ttl
    )
        public
        override
        onlyTokenOwner(parentNode)
        canCallSetSubnodeOwner(parentNode, label)
    {
        ens.setSubnodeRecord(parentNode, label, owner, resolver, ttl);
    }

    /**
     * @notice Sets the subnode owner in the registry
     * @param parentNode namehash of the parent name
     * @param label labelhash of the subnode
     * @param owner newOwner in the registry
     */

    function setSubnodeOwner(
        bytes32 parentNode,
        bytes32 label,
        address owner
    )
        public
        override
        onlyTokenOwner(parentNode)
        canCallSetSubnodeOwner(parentNode, label)
        returns (bytes32)
    {
        return ens.setSubnodeOwner(parentNode, label, owner);
    }

    /**
     * @notice Sets the subdomain owner in the registry and then wraps the subdomain
     * @param parentNode parent namehash of the subdomain
     * @param label label of the subdomain as a string
     * @param newOwner newOwner in the registry
     * @param _fuses initial fuses for the wrapped subdomain
     */

    function setSubnodeOwnerAndWrap(
        bytes32 parentNode,
        string calldata label,
        address newOwner,
        uint96 _fuses
    ) public override returns (bytes32 node) {
        bytes32 labelhash;
        bytes memory name = _addLabel(label, names[parentNode]);
        (node, , labelhash) = _storeNamehash(name);
        setSubnodeOwner(parentNode, labelhash, address(this));
        _wrap(name, node, parentNode, newOwner, _fuses);
    }

    /**
     * @notice Sets the subdomain owner in the registry with records and then wraps the subdomain
     * @param parentNode parent namehash of the subdomain
     * @param label label of the subdomain as a string
     * @param newOwner newOwner in the registry
     * @param resolver resolver contract in the registry
     * @param ttl ttl in the regsitry
     * @param _fuses initial fuses for the wrapped subdomain
     */

    function setSubnodeRecordAndWrap(
        bytes32 parentNode,
        string calldata label,
        address newOwner,
        address resolver,
        uint64 ttl,
        uint96 _fuses
    ) public override {
        bytes memory name = _addLabel(label, names[parentNode]);
        (bytes32 node, , bytes32 labelhash) = _storeNamehash(name);
        setSubnodeRecord(parentNode, labelhash, address(this), resolver, ttl);
        _wrap(name, node, parentNode, newOwner, _fuses);
    }

    /**
     * @notice Sets records for the name in the ENS Registry
     * @param node namehash of the name to set a record for
     * @param owner newOwner in the registry
     * @param resolver the resolver contract
     * @param ttl ttl in the registry
     */

    function setRecord(
        bytes32 node,
        address owner,
        address resolver,
        uint64 ttl
    )
        public
        override
        onlyTokenOwner(node)
        operationAllowed(
            node,
            CANNOT_TRANSFER | CANNOT_SET_RESOLVER | CANNOT_SET_TTL
        )
    {
        ens.setRecord(node, owner, resolver, ttl);
    }

    /**
     * @notice Sets resolver contract in the registry
     * @param node namehash of the name
     * @param resolver the resolver contract
     */

    function setResolver(bytes32 node, address resolver)
        public
        override
        onlyTokenOwner(node)
        operationAllowed(node, CANNOT_SET_RESOLVER)
    {
        ens.setResolver(node, resolver);
    }

    /**
     * @notice Sets TTL in the registry
     * @param node namehash of the name
     * @param ttl TTL in the registry
     */

    function setTTL(bytes32 node, uint64 ttl)
        public
        override
        onlyTokenOwner(node)
        operationAllowed(node, CANNOT_SET_TTL)
    {
        ens.setTTL(node, ttl);
    }

    /**
     * @dev Allows an operation only if none of the specified fuses are burned.
     * @param node The namehash of the name to check fuses on.
     * @param fuseMask A bitmask of fuses that must not be burned.
     */
    modifier operationAllowed(bytes32 node, uint96 fuseMask) {
        (, uint96 fuses) = getData(uint256(node));
        require(
            fuses & fuseMask == 0,
            "NameWrapper: Operation prohibited by fuses"
        );
        _;
    }

    /**
     * @notice Check whether a name can call setSubnodeOwner/setSubnodeRecord
     * @dev Checks both canCreateSubdomain and canReplaceSubdomain and whether not they have been burnt
     *      and checks whether the owner of the subdomain is 0x0 for creating or already exists for
     *      replacing a subdomain. If either conditions are true, then it is possible to call
     *      setSubnodeOwner
     * @param node namehash of the name to check
     * @param label labelhash of the name to check
     */

    modifier canCallSetSubnodeOwner(bytes32 node, bytes32 label) {
        bytes32 subnode = _makeNode(node, label);
        address owner = ens.owner(subnode);
        (, uint96 fuses) = getData(uint256(node));

        require(
            (owner == address(0) && fuses & CANNOT_CREATE_SUBDOMAIN == 0) ||
                (owner != address(0) && fuses & CANNOT_REPLACE_SUBDOMAIN == 0),
            "NameWrapper: Operation prohibited by fuses"
        );
        _;
    }

    /**
     * @notice Checks all Fuses in the mask are burned for the node
     * @param node namehash of the name
     * @param fuseMask the fuses you want to check
     * @return Boolean of whether or not all the selected fuses are burned
     */

    function allFusesBurned(bytes32 node, uint96 fuseMask)
        public
        view
        override
        returns (bool)
    {
        (, uint96 fuses) = getData(uint256(node));
        return fuses & fuseMask == fuseMask;
    }

    function onERC721Received(
        address to,
        address,
        uint256 tokenId,
        bytes calldata data
    ) public override returns (bytes4) {
        //check if it's the eth registrar ERC721
        require(
            msg.sender == address(registrar),
            "NameWrapper: Wrapper only supports .eth ERC721 token transfers"
        );

        (
            string memory label,
            address owner,
            uint96 fuses,
            address resolver
        ) = abi.decode(data, (string, address, uint96, address));

        require(
            keccak256(bytes(label)) == bytes32(tokenId),
            "NameWrapper: Token id does match keccak(label) of label provided in data field"
        );

        bytes32 labelhash = keccak256(bytes(label));

        // transfer the ens record back to the new owner (this contract)
        registrar.reclaim(uint256(labelhash), address(this));

        _wrapETH2LD(label, owner, fuses, resolver);

        return IERC721Receiver(to).onERC721Received.selector;
    }

    /***** Internal functions */

    function _canTransfer(uint96 fuses) internal pure override returns (bool) {
        return fuses & CANNOT_TRANSFER == 0;
    }

    function _makeNode(bytes32 node, bytes32 label)
        private
        pure
        returns (bytes32)
    {
        return keccak256(abi.encodePacked(node, label));
    }

    function _addLabel(string memory label, bytes memory name)
        internal
        pure
        returns (bytes memory ret)
    {
        require(bytes(label).length > 0, "NameWrapper: Label too short");
        require(bytes(label).length < 256, "NameWrapper: Label too long");
        return abi.encodePacked(uint8(bytes(label).length), label, name);
    }

    function _mint(
        bytes32 node,
        address wrappedOwner,
        uint96 _fuses
    ) internal override {
        address oldWrappedOwner = ownerOf(uint256(node));
        if (oldWrappedOwner != address(0)) {
            // burn and unwrap old token of old owner
            _burn(uint256(node));
            emit NameUnwrapped(node, address(0));
        }
        super._mint(node, wrappedOwner, _fuses);
    }

    function _wrap(
        bytes memory name,
        bytes32 node,
        bytes32 parentNode,
        address wrappedOwner,
        uint96 _fuses
    ) private {
        require(
            parentNode != ETH_NODE,
            "NameWrapper: .eth domains need to use wrapETH2LD()"
        );

        _mint(node, wrappedOwner, _fuses);
        emit NameWrapped(node, name, wrappedOwner, _fuses);
    }

    function _wrapETH2LD(
        string memory label,
        address wrappedOwner,
        uint96 _fuses,
        address resolver
    ) private returns (bytes32 labelhash) {
        labelhash = keccak256(bytes(label));
        // mint a new ERC1155 token with fuses
        bytes memory name = _addLabel(label, "\x03eth\x00");
        (bytes32 node, , ) = _storeNamehash(name);

        if (resolver != address(0)) {
            ens.setResolver(node, resolver);
        }

        _mint(node, wrappedOwner, _fuses);

        emit NameWrapped(node, name, wrappedOwner, _fuses);
    }

    function _unwrap(bytes32 node, address newOwner) private {
        require(
            newOwner != address(0x0),
            "NameWrapper: Target owner cannot be 0x0"
        );
        require(
            newOwner != address(this),
            "NameWrapper: Target owner cannot be the NameWrapper contract"
        );
        require(
            !allFusesBurned(node, CANNOT_UNWRAP),
            "NameWrapper: Domain is not unwrappable"
        );

        // burn token and fuse data
        _burn(uint256(node));
        ens.setOwner(node, newOwner);

        emit NameUnwrapped(node, newOwner);
    }

    function _setData(
        uint256 tokenId,
        address owner,
        uint96 fuses
    ) internal override {
        require(
            fuses == CAN_DO_EVERYTHING || fuses & CANNOT_UNWRAP != 0,
            "NameWrapper: Cannot burn fuses: domain can be unwrapped"
        );
        super._setData(tokenId, owner, fuses);
    }

    /**
     * @dev Internal function that checks all a name's ancestors to ensure fuse values will be respected and parent controller/registrant are set to the Wrapper
     * @param name The name to check.
     * @param offset The offset into the name to start at.
     * @return node The calculated namehash for this part of the name.
     * @return vulnerability what kind of vulnerability the node has
     * @return vulnerableNode which node is at risk
     */
    function _checkHierarchy(bytes memory name, uint256 offset)
        internal
        view
        returns (
            bytes32 node,
            NameSafety vulnerability,
            bytes32 vulnerableNode
        )
    {
        // Read the first label. If it's the root, return immediately.
        (bytes32 labelhash, uint256 newOffset) = name.readLabel(offset);
        if (labelhash == bytes32(0)) {
            // Root node
            return (bytes32(0), NameSafety.Safe, 0);
        }

        // Check the parent name
        bytes32 parentNode;
        (parentNode, vulnerability, vulnerableNode) = _checkHierarchy(
            name,
            newOffset
        );

        node = _makeNode(parentNode, labelhash);

        // stop function checking any other nodes if a parent is not safe
        if (vulnerability != NameSafety.Safe) {
            return (node, vulnerability, vulnerableNode);
        }

        // Check the parent name's fuses to see if replacing subdomains is forbidden
        if (parentNode == ROOT_NODE) {
            // Save ourselves some gas; root node can't be replaced
            return (node, NameSafety.Safe, 0);
        }

        (vulnerability, vulnerableNode) = _checkOwnership(
            labelhash,
            node,
            parentNode
        );

        if (vulnerability != NameSafety.Safe) {
            return (node, vulnerability, vulnerableNode);
        }

        if (!allFusesBurned(parentNode, CANNOT_REPLACE_SUBDOMAIN)) {
            return (node, NameSafety.SubdomainReplacementAllowed, parentNode);
        }

        return (node, NameSafety.Safe, 0);
    }

    function _checkOwnership(
        bytes32 labelhash,
        bytes32 node,
        bytes32 parentNode
    ) internal view returns (NameSafety vulnerability, bytes32 vulnerableNode) {
        if (parentNode == ETH_NODE) {
            // Special case .eth: Check registrant or name isexpired

            try registrar.ownerOf(uint256(labelhash)) returns (
                address registrarOwner
            ) {
                if (registrarOwner != address(this)) {
                    return (NameSafety.RegistrantNotWrapped, node);
                }
            } catch {
                return (NameSafety.Expired, node);
            }
        }

        if (ens.owner(node) != address(this)) {
            return (NameSafety.ControllerNotWrapped, node);
        }
    }

    function _storeNamehash(bytes memory name)
        internal
        returns (
            bytes32 node,
            bytes32 parentNode,
            bytes32 labelhash
        )
    {
        (bytes32 currentLabelhash, uint256 offset) = name.readLabel(0);
        labelhash = currentLabelhash;
        parentNode = name.namehash(offset);
        node = _makeNode(parentNode, labelhash);
        names[node] = name;
    }
}


Created a more useful SimpleToken contract;

pragma solidity ^0.4.15;

import "./Owned.sol";
import "./TokenEIP20.sol";
import "./TokenNotifier.sol";
import "./SafeMathLib.sol";

contract SimpleToken is Owned, TokenEIP20 {
    using SafeMathLib for uint256;

    mapping (address => uint256) balances;
    mapping (address => mapping (address => uint256)) allowed;

    string public name;
    string public symbol;

    uint256 public decimals;
    uint256 public totalSupply;

    function SimpleToken(string _name, string _symbol, uint256 _decimals, uint256 _totalSupply) {
        name = _name;
        symbol = _symbol;
        decimals = _decimals;
        totalSupply = decimals > 0 ? _totalSupply * 10**decimals : _totalSupply;
        balances[owner] = totalSupply;
    }

    function transfer(address _to, uint256 _value) returns (bool success) {
        if (balances[msg.sender] < _value) {
            return false;
        }
        balances[msg.sender] = balances[msg.sender].sub(_value);
        assert(balances[msg.sender] >= 0);
        balances[_to] = balances[_to].add(_value);
        assert(balances[_to] <= totalSupply);
        Transfer(msg.sender, _to, _value);
        return true;
    }

    function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {
        if (balances[_from] < _value || allowed[_from][msg.sender] < _value) {
            return false;
        }
        balances[_from] = balances[_from].sub(_value);
        assert(balances[_from] >= 0);
        allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);
        balances[_to] = balances[_to].add(_value);
        assert(balances[_to] <= totalSupply);
        Transfer(_from, _to, _value);
        return true;
    }

    function approve(address _spender, uint256 _value) returns (bool success) {
        allowed[msg.sender][_spender] = _value;
        Approval(msg.sender, _spender, _value);
        return true;
    }

    function approveAndCall(address _spender, uint256 _value, bytes _extraData) returns (bool success) {
        if (!approve(_spender, _value)) {
            return false;
        }
        TokenNotifier(_spender).receiveApproval(msg.sender, _value, this, _extraData);
        return true;
    }

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

    function allowance(address _owner, address _spender) constant returns (uint256 remaining) {
        return allowed[_owner][_spender];
    }
}

pragma solidity ^0.4.15;

import "./Owned.sol";
import "./TokenEIP20.sol";
import "./TokenNotifier.sol";
import "./SafeMathLib.sol";

contract SimpleToken is Owned, TokenEIP20 {
    using SafeMathLib for uint256;

    mapping (address => uint256) balances;
    mapping (address => mapping (address => uint256)) allowed;

    string public name;
    string public symbol;

    uint8 public decimals;

    uint256 public totalSupply;

    function SimpleToken(string _name, string _symbol, uint8 _decimals, uint256 _totalSupply) {
        name = _name;
        symbol = _symbol;
        decimals = _decimals;
        totalSupply = _totalSupply;
        balances[owner] = _totalSupply;
    }

    function transfer(address _to, uint256 _value) returns (bool success) {
        if (balances[msg.sender] < _value) {
            return false;
        }
        balances[msg.sender] = balances[msg.sender].sub(_value);
        assert(balances[msg.sender] >= 0);
        balances[_to] = balances[_to].add(_value);
        assert(balances[_to] <= totalSupply);
        Transfer(msg.sender, _to, _value);
        return true;
    }

    function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {
        if (balances[_from] < _value || allowed[_from][msg.sender] < _value) {
            return false;
        }
        balances[_from] = balances[_from].sub(_value);
        assert(balances[_from] >= 0);
        allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);
        balances[_to] = balances[_to].add(_value);
        assert(balances[_to] <= totalSupply);
        Transfer(_from, _to, _value);
        return true;
    }

    function approve(address _spender, uint256 _value) returns (bool success) {
        allowed[msg.sender][_spender] = _value;
        Approval(msg.sender, _spender, _value);
        return true;
    }

    function approveAndCall(address _spender, uint256 _value, bytes _extraData) returns (bool success) {
        if (!approve(_spender, _value)) {
            return false;
        }
        TokenNotifier(_spender).receiveApproval(msg.sender, _value, this, _extraData);
        return true;
    }

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

    function allowance(address _owner, address _spender) constant returns (uint256 remaining) {
        return allowed[_owner][_spender];
    }
}


contract: numDonations

contract: numDonations

//! Fundraiser contract. Just records who sent what.
//! By Parity Technologies, 2017.
//! Released under the Apache Licence 2.
//! Modified by the Interchain Foundation.

pragma solidity ^0.4.8;

/// Will accept Ether "contributions" and record each both as a log and in a
/// queryable record.
contract Fundraiser {

    // How much is enough?
    uint public constant dust = 1 finney; // XXX: change for production

    // Special addresses:
    //  administrator can halt/unhalt/kill/adjustRate;
    //  treasury receives all the funds
    address public admin;
    address public treasury;

    // Begin and end block for the fundraising period
    uint public beginBlock;
    uint public endBlock;

    // Number of wei per atom
    uint public weiPerAtom;

    // Are contributions abnormally halted?
    bool public isHalted = false;

    // The `record` mapping maps cosmos addresses to the amount of atoms.
    mapping (address => uint) public record;

    // The total amount of ether raised
    uint public totalWei = 0;
    // The total amount of atoms suggested for allocation
    uint public totalAtom = 0;
    // The number of donation
    uint public numDonations = 0;

    /// Constructor. `_admin` has the ability to pause the
    /// contribution period and, eventually, kill this contract. `_treasury`
    /// receives all funds. `_beginBlock` and `_endBlock` define the begin and
    /// end of the period. `_weiPerAtom` is the ratio of atoms to ether.
    function Fundraiser(address _admin, address _treasury, uint _beginBlock, uint _endBlock, uint _weiPerAtom) {
        admin = _admin;
        treasury = _treasury;
        beginBlock = _beginBlock;
        endBlock = _endBlock;
	weiPerAtom = _weiPerAtom;
    }

    // Can only be called by _admin.
    modifier only_admin { if (msg.sender != admin) throw; _; }
    // Can only be called by prior to the period.
    modifier only_before_period { if (block.number >= beginBlock) throw; _; }
    // Can only be called during the period when not halted.
    modifier only_during_period { if (block.number < beginBlock || block.number >= endBlock || isHalted) throw; _; }
    // Can only be called during the period when halted.
    modifier only_during_halted_period { if (block.number < beginBlock || block.number >= endBlock || !isHalted) throw; _; }
    // Can only be called after the period.
    modifier only_after_period { if (block.number < endBlock) throw; _; }
    // The value of the message must be sufficiently large to not be considered dust.
    modifier is_not_dust { if (msg.value < dust) throw; _; }

    /// Some contribution `amount` received from `recipient` at rate of `currentRate` with emergency return of `returnAddr`.
    event Received(address indexed recipient, address returnAddr, uint amount, uint currentRate);
    /// Period halted abnormally.
    event Halted();
    /// Period restarted after abnormal halt.
    event Unhalted();

    /// Receive a contribution for a donor cosmos address.
    function donate(address _donor, address _returnAddress, bytes4 checksum) payable only_during_period is_not_dust {
	// checksum is the first 4 bytes of the sha3 of the xor of the bytes32 versions of the cosmos address and the return address
	if ( !( bytes4(sha3( bytes32(_donor)^bytes32(_returnAddress) )) == checksum )) throw;

	// forward the funds to the treasurer
        if (!treasury.send(msg.value)) throw;

	// calculate the number of atoms at the current rate
	var atoms = msg.value / weiPerAtom;

	// update the donor details
        record[_donor] += atoms;

	// update the totals
        totalWei += msg.value;
	totalAtom += atoms;
	numDonations += 1;

        Received(_donor, _returnAddress, msg.value, weiPerAtom);
    }

    /// Adjust the weiPerAtom
    function adjustRate(uint newRate) only_admin {
	weiPerAtom = newRate;
    }

    /// Halt the contribution period. Any attempt at contributing will fail.
    function halt() only_admin only_during_period {
        isHalted = true;
        Halted();
    }

    /// Unhalt the contribution period.
    function unhalt() only_admin only_during_halted_period {
        isHalted = false;
        Unhalted();
    }

    /// Kill this contract.
    function kill() only_admin only_after_period {
        suicide(treasury);
    }
}

//! Fundraiser contract. Just records who sent what.
//! By Parity Technologies, 2017.
//! Released under the Apache Licence 2.
//! Modified by the Interchain Foundation.

pragma solidity ^0.4.8;

/// Will accept Ether "contributions" and record each both as a log and in a
/// queryable record.
contract Fundraiser {

    // How much is enough?
    uint public constant dust = 1 finney; // XXX: change for production

    // Special addresses:
    //  administrator can halt/unhalt/kill/adjustRate;
    //  treasury receives all the funds
    address public admin;
    address public treasury;

    // Begin and end block for the fundraising period
    uint public beginBlock;
    uint public endBlock;

    // Number of wei per atom
    uint public weiPerAtom;

    // Are contributions abnormally halted?
    bool public isHalted = false;

    // The `record` mapping maps cosmos addresses to the amount of atoms.
    mapping (address => uint) public record;

    // The total amount of ether raised
    uint public totalWei = 0;
    // The total amount of atoms suggested for allocation
    uint public totalAtom = 0;

    /// Constructor. `_admin` has the ability to pause the
    /// contribution period and, eventually, kill this contract. `_treasury`
    /// receives all funds. `_beginBlock` and `_endBlock` define the begin and
    /// end of the period. `_weiPerAtom` is the ratio of atoms to ether.
    function Fundraiser(address _admin, address _treasury, uint _beginBlock, uint _endBlock, uint _weiPerAtom) {
        admin = _admin;
        treasury = _treasury;
        beginBlock = _beginBlock;
        endBlock = _endBlock;
	weiPerAtom = _weiPerAtom;
    }

    // Can only be called by _admin.
    modifier only_admin { if (msg.sender != admin) throw; _; }
    // Can only be called by prior to the period.
    modifier only_before_period { if (block.number >= beginBlock) throw; _; }
    // Can only be called during the period when not halted.
    modifier only_during_period { if (block.number < beginBlock || block.number >= endBlock || isHalted) throw; _; }
    // Can only be called during the period when halted.
    modifier only_during_halted_period { if (block.number < beginBlock || block.number >= endBlock || !isHalted) throw; _; }
    // Can only be called after the period.
    modifier only_after_period { if (block.number < endBlock) throw; _; }
    // The value of the message must be sufficiently large to not be considered dust.
    modifier is_not_dust { if (msg.value < dust) throw; _; }

    /// Some contribution `amount` received from `recipient` at rate of `currentRate` with emergency return of `returnAddr`.
    event Received(address indexed recipient, address returnAddr, uint amount, uint currentRate);
    /// Period halted abnormally.
    event Halted();
    /// Period restarted after abnormal halt.
    event Unhalted();

    /// Receive a contribution for a donor cosmos address.
    function donate(address _donor, address _returnAddress, bytes4 checksum) payable only_during_period is_not_dust {
	// checksum is the first 4 bytes of the sha3 of the xor of the bytes32 versions of the cosmos address and the return address
	if ( !( bytes4(sha3( bytes32(_donor)^bytes32(_returnAddress) )) == checksum )) throw;

	// forward the funds to the treasurer
        if (!treasury.send(msg.value)) throw;

	// calculate the number of atoms at the current rate
	var atoms = msg.value / weiPerAtom;

	// update the donor details
        record[_donor] += atoms;

	// update the totals
        totalWei += msg.value;
	totalAtom += atoms;

        Received(_donor, _returnAddress, msg.value, weiPerAtom);
    }

    /// Adjust the weiPerAtom
    function adjustRate(uint newRate) only_admin {
	weiPerAtom = newRate;
    }

    /// Halt the contribution period. Any attempt at contributing will fail.
    function halt() only_admin only_during_period {
        isHalted = true;
        Halted();
    }

    /// Unhalt the contribution period.
    function unhalt() only_admin only_during_halted_period {
        isHalted = false;
        Unhalted();
    }

    /// Kill this contract.
    function kill() only_admin only_after_period {
        suicide(treasury);
    }
}


Correcao de erro no stopselling

Correcao de erro no stopselling

/*
    Contract Address: "0x2ba25711fa1f94998d875bf80acbc2cccdf9abbb"

    PokeCoinAddress:"0x037D274575fE52239BfeB4911A09Cc5cfCe0C9FD"
    PokemonsAdress:"0x13EccD104f4012F857a9cD32C1E4877275f78Cec"
    "0x037D274575fE52239BfeB4911A09Cc5cfCe0C9FD","0x13EccD104f4012F857a9cD32C1E4877275f78Cec"

    PokeSeller Address: "0xfFAe2A502A6142a00DBB54361E244ED55461C7Aa"
    PokeBuyer Address: "0xf09c7cbD8B7D27ac12e82b8bC6d8fe7EEfC9E7C8"
    Main Wallet: "0x6A5b342ec71DEF8aAc337b82969D9dDd811023C9"

*/

contract pokeCoin { mapping (address => uint256) public balanceOf; function transferFrom(address _from, address _to, uint256 _value){  } }
contract pokemon { mapping (uint256 => address) public pokemonToMaster; function transferPokemon(address _from, address _to, uint256 _pokemonID) {  } }

contract MarketPokemon {
    pokeCoin public pokeCoinDapp;
    pokemon public pokemonDapp;
    uint public totalPokemonSales;

    PokeSale[] public pokeSales;

    mapping (uint => bool) public pokeSelling;
    mapping (address => uint[]) public pokeMasterSelling;
    mapping (uint => uint) public pokeSaleIndex;

    struct PokeSale{
        address pokeSeller;
        address pokeBuyer;
        uint pokeID;
        uint pokePrice;
        bool pokeSold;
        bool pokeSellActive;
    }

    event NewSale(address pokeSellerAddress, uint pokemonID, uint pokemonSalePrice);
    event StopSale(address pokeSellerAddress, uint pokemonID);
    event PokeTrade(address pokeBuyerAddress, address pokeSellerAddress, uint pokemonID );
    event Log1(bool status);

    function MarketPokemon(pokeCoin pokeCoinAddress, pokemon pokeRepositoryAddress) {
        pokeCoinDapp = pokeCoin(pokeCoinAddress);
        pokemonDapp = pokemon(pokeRepositoryAddress);

    }

    function newSale(address pokeSellerAddress, uint pokemonID, uint pokemonSalePrice) returns (bool success){
        if (pokeSellerAddress != pokemonDapp.pokemonToMaster(pokemonID)) throw;
        if (pokeSelling[pokemonID]) throw;
        uint pokeSalesID = pokeSales.length++;
        PokeSale p = pokeSales[pokeSalesID];
        if (p.pokeSellActive) throw;
        p.pokeSeller = pokeSellerAddress;
        p.pokeID = pokemonID;
        p.pokePrice = pokemonSalePrice;
        p.pokeSold = false;
        p.pokeSellActive = true;

        pokeSelling[pokemonID] = true;
        pokeSaleIndex[pokemonID] = pokeSalesID;

        addPokemonToSellingList(pokeSellerAddress, pokemonID);

        totalPokemonSales+=1;

        NewSale(pokeSellerAddress, pokemonID, pokemonSalePrice);
        return (true);
    }

    function stopSale(address pokeSellerAddress, uint pokemonID){
        if (pokeSellerAddress != pokemonDapp.pokemonToMaster(pokemonID)) throw;
        if (!pokeSelling[pokemonID]) throw;

        uint pokeSalesID = pokeSaleIndex[pokemonID];
        PokeSale p = pokeSales[pokeSalesID];
        if (!p.pokeSellActive) throw;
        p.pokeSellActive = false;
        pokeSelling[pokemonID] = false;

        delPokemonFromSellingList(pokeSellerAddress, pokemonID);

        totalPokemonSales-=1;

        StopSale(pokeSellerAddress, pokemonID);
    }

    function buyPokemon(address pokeBuyerAddress, uint pokemonID){
        if (!pokeSelling[pokemonID]) throw;
        uint pokeSalesID = pokeSaleIndex[pokemonID];
        PokeSale p = pokeSales[pokeSalesID];
        if (!p.pokeSellActive) throw;
        if (pokeCoinDapp.balanceOf(pokeBuyerAddress) < p.pokePrice) throw;

        pokeCoinDapp.transferFrom(pokeBuyerAddress, p.pokeSeller, p.pokePrice);
        pokemonDapp.transferPokemon(p.pokeSeller, pokeBuyerAddress, pokemonID);
        p.pokeBuyer = pokeBuyerAddress;
        p.pokeSold = true;

        stopSale(pokeBuyerAddress,pokemonID);

        PokeTrade(pokeBuyerAddress, p.pokeSeller, pokemonID );

    }

    function transferCoin(address _from, address _to, uint _value){
        pokeCoinDapp.transferFrom(_from, _to, _value);
    }

    function transferPokemon(address _from, address _to, uint _pokemonID){
        pokemonDapp.transferPokemon(_from, _to, _pokemonID);
    }

    function addPokemonToSellingList(address pokeSellerAddress, uint pokemonID) internal {
        uint[] tempList = pokeMasterSelling[pokeSellerAddress];
        tempList[tempList.length++] = pokemonID;

        pokeMasterSelling[pokeSellerAddress] = cleanArray(tempList);
    }

    function delPokemonFromSellingList(address pokeSellerAddress, uint pokemonID) internal {
        uint[] tempList = pokeMasterSelling[pokeSellerAddress];
        uint count = tempList.length;

        for (uint i=0; i<count; i++){
            if (tempList[i] == pokemonID) delete tempList[i];
        }

        pokeMasterSelling[pokeSellerAddress] = cleanArray(tempList);
    }

    /* Esta funcao elimina todos os itens com zero do array, ao custo de gas */
    function cleanArray(uint[] pokeList) internal returns (uint[]){
        uint[] memory tempList = new uint[](pokeList.length);
        uint j = 0;
        for (uint i=0; i < pokeList.length; i++){
            if ( pokeList[i] > 0 ){
                tempList[j] = pokeList[i];
                j++;
            }
        }
        uint[] memory tempList2 = new uint[](j);
        for (i=0; i< j; i++) tempList2[i] = tempList[i];
        return tempList2;
    }

    function (){
        throw;
    }

}

/*
    Contract Address: "0x2ba25711fa1f94998d875bf80acbc2cccdf9abbb"

    PokeCoinAddress:"0x037D274575fE52239BfeB4911A09Cc5cfCe0C9FD"
    PokemonsAdress:"0x13EccD104f4012F857a9cD32C1E4877275f78Cec"
    "0x037D274575fE52239BfeB4911A09Cc5cfCe0C9FD","0x13EccD104f4012F857a9cD32C1E4877275f78Cec"

    PokeSeller Address: "0xfFAe2A502A6142a00DBB54361E244ED55461C7Aa"
    PokeBuyer Address: "0xf09c7cbD8B7D27ac12e82b8bC6d8fe7EEfC9E7C8"
    Main Wallet: "0x6A5b342ec71DEF8aAc337b82969D9dDd811023C9"

*/

contract pokeCoin { mapping (address => uint256) public balanceOf; function transferFrom(address _from, address _to, uint256 _value){  } }
contract pokemon { mapping (uint256 => address) public pokemonToMaster; function transferPokemon(address _from, address _to, uint256 _pokemonID) {  } }

contract MarketPokemon {
    pokeCoin public pokeCoinDapp;
    pokemon public pokemonDapp;
    uint public totalPokemonSales;

    PokeSale[] public pokeSales;

    mapping (uint => bool) public pokeSelling;
    mapping (address => uint[]) public pokeMasterSelling;
    mapping (uint => uint) public pokeSaleIndex;

    struct PokeSale{
        address pokeSeller;
        address pokeBuyer;
        uint pokeID;
        uint pokePrice;
        bool pokeSold;
        bool pokeSellActive;
    }

    event NewSale(address pokeSellerAddress, uint pokemonID, uint pokemonSalePrice);
    event StopSale(address pokeSellerAddress, uint pokemonID);
    event PokeTrade(address pokeBuyerAddress, address pokeSellerAddress, uint pokemonID );
    event Log1(bool status);

    function MarketPokemon(pokeCoin pokeCoinAddress, pokemon pokeRepositoryAddress) {
        pokeCoinDapp = pokeCoin(pokeCoinAddress);
        pokemonDapp = pokemon(pokeRepositoryAddress);

    }

    function newSale(address pokeSellerAddress, uint pokemonID, uint pokemonSalePrice) returns (bool success){
        if (pokeSellerAddress != pokemonDapp.pokemonToMaster(pokemonID)) throw;
        if (pokeSelling[pokemonID]) throw;
        uint pokeSalesID = pokeSales.length++;
        PokeSale p = pokeSales[pokeSalesID];
        if (p.pokeSellActive) throw;
        p.pokeSeller = pokeSellerAddress;
        p.pokeID = pokemonID;
        p.pokePrice = pokemonSalePrice;
        p.pokeSold = false;
        p.pokeSellActive = true;

        pokeSelling[pokemonID] = true;
        pokeSaleIndex[pokemonID] = pokeSalesID;

        addPokemonToSellingList(pokeSellerAddress, pokemonID);

        totalPokemonSales+=1;

        NewSale(pokeSellerAddress, pokemonID, pokemonSalePrice);
        return (true);
    }

    function stopSale(address pokeSellerAddress, uint pokemonID){
        //if (pokeSellerAddress != pokemonDapp.pokemonToMaster(pokemonID)) throw;
        //if (!pokeSelling[pokemonID]) throw;

        uint pokeSalesID = pokeSaleIndex[pokemonID];
        PokeSale p = pokeSales[pokeSalesID];
        //if (!p.pokeSellActive) throw;
        p.pokeSellActive = false;
        pokeSelling[pokemonID] = false;

        delPokemonFromSellingList(pokeSellerAddress, pokemonID);

        totalPokemonSales-=1;

        StopSale(pokeSellerAddress, pokemonID);
    }

    function buyPokemon(address pokeBuyerAddress, uint pokemonID){
        //if (!pokeSelling[pokemonID]) throw;
        uint pokeSalesID = pokeSaleIndex[pokemonID];
        PokeSale p = pokeSales[pokeSalesID];
        //if (!p.pokeSellActive) throw;
        //if (pokeCoinDapp.balanceOf(pokeBuyerAddress) < p.pokePrice) throw;

        pokeCoinDapp.transferFrom(pokeBuyerAddress, p.pokeSeller, p.pokePrice);
        pokemonDapp.transferPokemon(p.pokeSeller, pokeBuyerAddress, pokemonID);
        p.pokeBuyer = pokeBuyerAddress;
        p.pokeSold = true;
        stopSale(p.pokeSeller,pokemonID);

        PokeTrade(pokeBuyerAddress, p.pokeSeller, pokemonID );

    }

    function transferCoin(address _from, address _to, uint _value){
        pokeCoinDapp.transferFrom(_from, _to, _value);
    }

    function transferPokemon(address _from, address _to, uint _pokemonID){
        pokemonDapp.transferPokemon(_from, _to, _pokemonID);
    }

    function addPokemonToSellingList(address pokeSellerAddress, uint pokemonID) internal {
        uint[] tempList = pokeMasterSelling[pokeSellerAddress];
        tempList[tempList.length++] = pokemonID;

        pokeMasterSelling[pokeSellerAddress] = cleanArray(tempList);
    }

    function delPokemonFromSellingList(address pokeSellerAddress, uint pokemonID) internal {
        uint[] tempList = pokeMasterSelling[pokeSellerAddress];
        uint count = tempList.length;

        for (uint i=0; i<count; i++){
            if (tempList[i] == pokemonID) delete tempList[i];
        }

        pokeMasterSelling[pokeSellerAddress] = cleanArray(tempList);
    }

    /* Esta funcao elimina todos os itens com zero do array, ao custo de gas */
    function cleanArray(uint[] pokeList) internal returns (uint[]){
        uint[] memory tempList = new uint[](pokeList.length);
        uint j = 0;
        for (uint i=0; i < pokeList.length; i++){
            if ( pokeList[i] > 0 ){
                tempList[j] = pokeList[i];
                j++;
            }
        }
        uint[] memory tempList2 = new uint[](j);
        for (i=0; i< j; i++) tempList2[i] = tempList[i];
        return tempList2;
    }

    function (){
        throw;
    }

}


Update

Update

pragma solidity ^0.4.16;

contract owned {
    address public owner;

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

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

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

interface tokenRecipient { function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData) public; }

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

    // This creates an array with all balances
    mapping (address => uint256) public balanceOf;
    mapping (address => mapping (address => uint256)) public allowance;

    // This generates a public event on the blockchain that will notify clients
    event Transfer(address indexed from, address indexed to, uint256 value);

    // This notifies clients about the amount burnt
    event Burn(address indexed from, uint256 value);

    /**
     * Constrctor function
     *
     * Initializes contract with initial supply tokens to the creator of the contract
     */
    function Anemoi(
        uint256 initialSupply,
        string tokenName,
        string tokenSymbol
    ) public {
        totalSupply = initialSupply * 10 ** uint256(decimals);  // Update total supply with the decimal amount
        balanceOf[msg.sender] = totalSupply;                // Give the creator all initial tokens
        name = tokenName;                                   // Set the name for display purposes
        symbol = tokenSymbol;                               // Set the symbol for display purposes
    }

    /**
     * Internal transfer, only can be called by this contract
     */
    function _transfer(address _from, address _to, uint _value) internal {
        // Prevent transfer to 0x0 address. Use burn() instead
        require(_to != 0x0);
        // Check if the sender has enough
        require(balanceOf[_from] >= _value);
        // Check for overflows
        require(balanceOf[_to] + _value > balanceOf[_to]);
        // Save this for an assertion in the future
        uint previousBalances = balanceOf[_from] + balanceOf[_to];
        // Subtract from the sender
        balanceOf[_from] -= _value;
        // Add the same to the recipient
        balanceOf[_to] += _value;
        Transfer(_from, _to, _value);
        // Asserts are used to use static analysis to find bugs in your code. They should never fail
        assert(balanceOf[_from] + balanceOf[_to] == previousBalances);
    }

    /**
     * Transfer tokens
     *
     * Send `_value` tokens to `_to` from your account
     *
     * @param _to The address of the recipient
     * @param _value the amount to send
     */
    function transfer(address _to, uint256 _value) public {
        _transfer(msg.sender, _to, _value);
    }

    /**
     * Transfer tokens from other address
     *
     * Send `_value` tokens to `_to` in behalf of `_from`
     *
     * @param _from The address of the sender
     * @param _to The address of the recipient
     * @param _value the amount to send
     */
    function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
        require(_value <= allowance[_from][msg.sender]);     // Check allowance
        allowance[_from][msg.sender] -= _value;
        _transfer(_from, _to, _value);
        return true;
    }

    /**
     * Set allowance for other address
     *
     * Allows `_spender` to spend no more than `_value` tokens in your behalf
     *
     * @param _spender The address authorized to spend
     * @param _value the max amount they can spend
     */
    function approve(address _spender, uint256 _value) public
        returns (bool success) {
        allowance[msg.sender][_spender] = _value;
        return true;
    }

    /**
     * Set allowance for other address and notify
     *
     * Allows `_spender` to spend no more than `_value` tokens in your behalf, and then ping the contract about it
     *
     * @param _spender The address authorized to spend
     * @param _value the max amount they can spend
     * @param _extraData some extra information to send to the approved contract
     */
    function approveAndCall(address _spender, uint256 _value, bytes _extraData)
        public
        returns (bool success) {
        tokenRecipient spender = tokenRecipient(_spender);
        if (approve(_spender, _value)) {
            spender.receiveApproval(msg.sender, _value, this, _extraData);
            return true;
        }
    }

    /**
     * Destroy tokens
     *
     * Remove `_value` tokens from the system irreversibly
     *
     * @param _value the amount of money to burn
     */
    function burn(uint256 _value) public returns (bool success) {
        require(balanceOf[msg.sender] >= _value);   // Check if the sender has enough
        balanceOf[msg.sender] -= _value;            // Subtract from the sender
        totalSupply -= _value;                      // Updates totalSupply
        Burn(msg.sender, _value);
        return true;
    }

    /**
     * Destroy tokens from other ccount
     *
     * Remove `_value` tokens from the system irreversibly on behalf of `_from`.
     *
     * @param _from the address of the sender
     * @param _value the amount of money to burn
     */
    function burnFrom(address _from, uint256 _value) public returns (bool success) {
        require(balanceOf[_from] >= _value);                // Check if the targeted balance is enough
        require(_value <= allowance[_from][msg.sender]);    // Check allowance
        balanceOf[_from] -= _value;                         // Subtract from the targeted balance
        allowance[_from][msg.sender] -= _value;             // Subtract from the sender's allowance
        totalSupply -= _value;                              // Update totalSupply
        Burn(_from, _value);
        return true;
    }
}

/*******************************/
/*     Advanced Token          */
/*******************************/

contract Advanced_Anemoi is owned, Anemoi {

	uint256 public sellPrice;
	uint256 public buyPrice;

	mapping (address => bool) public frozenAccount;

	/* This generates a public event on the blockchain that will notify clients */
	event FrozenFunds(address target, bool frozen);

	/* Initializes contract with initial supply tokens to the creator of the contract */
	function Advanced_Anemoi(
		uint256 initialSupply,
		string tokenName,
		string tokenSymbol
		) Anemoi(initialSupply, tokenName, tokenSymbol) public {}

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

    /// @notice Create `mintedAmount` tokens and send it to `target`
    /// @param target Address to receive the tokens
    /// @param mintedAmount the amount of tokens it will receive
    function mintToken(address target, uint256 mintedAmount) onlyOwner public {
        balanceOf[target] += mintedAmount;
        totalSupply += mintedAmount;
        Transfer(0, this, mintedAmount);
        Transfer(this, target, mintedAmount);
    }

    /// @notice `freeze? Prevent | Allow` `target` from sending & receiving tokens
    /// @param target Address to be frozen
    /// @param freeze either to freeze it or not
    function freezeAccount(address target, bool freeze) onlyOwner public {
        frozenAccount[target] = freeze;
        FrozenFunds(target, freeze);
    }

    /// @notice Allow users to buy tokens for `newBuyPrice` eth and sell tokens for `newSellPrice` eth
    /// @param newSellPrice Price the users can sell to the contract
    /// @param newBuyPrice Price users can buy from the contract
    function setPrices(uint256 newSellPrice, uint256 newBuyPrice) onlyOwner public {
        sellPrice = newSellPrice;
        buyPrice = newBuyPrice;
    }

    /// @notice Buy tokens from contract by sending ether
    function buy() payable public {
        uint amount = msg.value / buyPrice;               // calculates the amount
        _transfer(this, msg.sender, amount);              // makes the transfers
    }

    /// @notice Sell `amount` tokens to contract
    /// @param amount amount of tokens to be sold
    function sell(uint256 amount) public {
        require(this.balance >= amount * sellPrice);      // checks if the contract has enough ether to buy
        _transfer(msg.sender, this, amount);              // makes the transfers
        msg.sender.transfer(amount * sellPrice);          // sends ether to the seller. It's important to do this last to avoid recursion attacks
    }
}

pragma solidity ^0.4.0;

contract owned {
	address public owner;

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

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

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

}

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

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

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

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

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

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

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

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

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

	}

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

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

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

    }

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