Move fuse require into _mint

Move fuse require into _mint

import "./ERC1155.sol";
import "../interfaces/INFTFuseWrapper.sol";
import "../interfaces/ENS.sol";
import "../interfaces/BaseRegistrar.sol";
import "../interfaces/Resolver.sol";
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "./BytesUtil.sol";
import "hardhat/console.sol";

contract NFTFuseWrapper is ERC1155, INFTFuseWrapper {
    using BytesUtils for bytes;
    ENS public ens;
    BaseRegistrar public registrar;
    bytes4 public constant ERC721_RECEIVED = 0x150b7a02;

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

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

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

    /**
     * @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 ownerOnly(bytes32 node) {
        require(
            isOwnerOrApproved(node, msg.sender),
            "NFTFuseWrapper: 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 isOwnerOrApproved(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 A number that represents the permissions a name has
     */

    function getFuses(bytes32 node) public view returns (uint96) {
        (, uint96 fuses) = getData(uint256(node));
        return fuses;
    }

    /**
     * @notice Check whether a name can be unwrapped
     *
     * @param node namehash of the name to check
     * @return Boolean of whether or not can be wrapped
     */

    function canUnwrap(bytes32 node) public view returns (bool) {
        uint96 fuses = getFuses(node);
        return fuses & CANNOT_UNWRAP == 0;
    }

    /**
     * @notice Check whether a name can burn fuses
     *
     * @param node namehash of the name to check
     * @return Boolean of whether or not can burn fuses
     */

    function canBurnFuses(bytes32 node) public view returns (bool) {
        uint96 fuses = getFuses(node);
        return fuses & CANNOT_BURN_FUSES == 0;
    }

    /**
     * @notice Check whether a name can be transferred
     *
     * @param node namehash of the name to check
     * @return Boolean of whether or not can be transferred
     */

    function canTransfer(bytes32 node) public view returns (bool) {
        uint96 fuses = getFuses(node);
        return fuses & CANNOT_TRANSFER == 0;
    }

    /**
     * @notice Check whether a name can set the resolver
     *
     * @param node namehash of the name to check
     * @return Boolean of whether or not resolver can be set
     */

    function canSetResolver(bytes32 node) public view returns (bool) {
        uint96 fuses = getFuses(node);
        return fuses & CANNOT_SET_RESOLVER == 0;
    }

    /**
     * @notice Check whether a name can set the TTL
     *
     * @param node namehash of the name to check
     * @return Boolean of whether or not TTL can be set
     */

    function canSetTTL(bytes32 node) public view returns (bool) {
        uint96 fuses = getFuses(node);
        return fuses & CANNOT_SET_TTL == 0;
    }

    /**
     * @notice Check whether a name can create a subdomain
     * @dev Creating a subdomain is defined as a subdomain that has a 0x0 owner and a new owner is set
     * @param node namehash of the name to check
     * @return Boolean of whether or not subdomains can be created
     */

    function canCreateSubdomain(bytes32 node) public view returns (bool) {
        uint96 fuses = getFuses(node);
        return fuses & CANNOT_CREATE_SUBDOMAIN == 0;
    }

    /**
     * @notice Check whether a name can replace a subdomain
     * @dev Replacing a subdomain is defined as a subdomain that has an existing owner and is overwritten
     * @param node namehash of the name to check
     * @return Boolean of whether or not TTL can be set
     */

    function canReplaceSubdomain(bytes32 node) public view returns (bool) {
        uint96 fuses = getFuses(node);
        return fuses & CANNOT_REPLACE_SUBDOMAIN == 0;
    }

    /**
     * @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
     * @return Boolean of whether or not setSubnodeOwner/setSubnodeRecord can be called
     */

    function canCallSetSubnodeOwner(bytes32 node, bytes32 label)
        public
        view
        returns (bool)
    {
        bytes32 subnode = _makeNode(node, label);
        address owner = ens.owner(subnode);

        return
            (owner == address(0) && canCreateSubdomain(node)) ||
            (owner != address(0) && canReplaceSubdomain(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,
        uint96 _fuses,
        address wrappedOwner
    ) public override {
        bytes32 labelhash = keccak256(bytes(label));
        bytes32 node = _makeNode(ETH_NODE, labelhash);
        uint256 tokenId = uint256(labelhash);
        address owner = registrar.ownerOf(tokenId);

        require(
            owner == msg.sender ||
                registrar.isApprovedForAll(owner, msg.sender) ||
                isApprovedForAll(owner, msg.sender),
            "NFTFuseWrapper: Sender is not owner or authorised by the owner or authorised on the .eth registrar"
        );
        // transfer the token from the user to this contract
        address currentOwner = registrar.ownerOf(tokenId);
        registrar.transferFrom(currentOwner, address(this), tokenId);

        // transfer the ens record back to the new owner (this contract)
        _wrapETH2LD(labelhash, node, _fuses, wrappedOwner);
    }

    /**
     * @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 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 _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(
        bytes32 parentNode,
        string calldata label,
        uint96 _fuses,
        address wrappedOwner
    ) public override {
        bytes32 labelhash = keccak256(bytes(label));
        bytes32 node = _makeNode(parentNode, labelhash);
        _wrap(parentNode, labelhash, _fuses, wrappedOwner);
        address owner = ens.owner(node);

        require(
            owner == msg.sender ||
                ens.isApprovedForAll(owner, msg.sender) ||
                isApprovedForAll(owner, msg.sender),
            "NFTFuseWrapper: Domain is not owned by the sender"
        );
        ens.setOwner(node, address(this));
        emit Wrap(parentNode, label, _fuses, wrappedOwner);
    }

    /**
     * @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 ownerOnly(_makeNode(ETH_NODE, label)) {
        _unwrap(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 ownerOnly(_makeNode(parentNode, label)) {
        require(
            parentNode != ETH_NODE,
            "NFTFuseWrapper: .eth names must be unwrapped with unwrapETH2LD()"
        );
        _unwrap(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 parentNode parent namehash of the name. e.g. vitalik.xyz would be namehash('xyz')
     * @param labelhash labelhash of the name. e.g. vitalik.xyz would be labelhash('vitalik')
     * @param _fuses Fuses you want to burn.
     */

    function burnFuses(
        bytes32 parentNode,
        bytes32 labelhash,
        uint96 _fuses
    ) public ownerOnly(_makeNode(parentNode, labelhash)) {
        bytes32 node = _makeNode(parentNode, labelhash);

        require(
            canBurnFuses(node),
            "NFTFuseWrapper: Fuse has been burned for burning fuses"
        );

        require(
            !canReplaceSubdomain(parentNode),
            "NFTFuseWrapper: Parent has not burned CAN_REPLACE_SUBDOMAIN fuse"
        );

        (address owner, uint96 fuses) = getData(uint256(node));

        setData(uint256(node), owner, fuses | _fuses);

        require(
            !canUnwrap(node),
            "NFTFuseWrapper: Domain has not burned unwrap fuse"
        );
    }

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

    function setSubnodeRecord(
        bytes32 node,
        bytes32 label,
        address owner,
        address resolver,
        uint64 ttl
    ) public ownerOnly(node) {
        require(
            canCallSetSubnodeOwner(node, label),
            "NFTFuseWrapper: Fuse has been burned for creating or replacing a subdomain"
        );

        return ens.setSubnodeRecord(node, label, owner, resolver, ttl);
    }

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

    function setSubnodeOwner(
        bytes32 node,
        bytes32 label,
        address owner
    ) public override ownerOnly(node) returns (bytes32) {
        require(
            canCallSetSubnodeOwner(node, label),
            "NFTFuseWrapper: Fuse has been burned for creating or replacing a subdomain"
        );

        ens.setSubnodeOwner(node, 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) {
        require(
            newOwner != address(this),
            "NFTFuseWrapper: newOwner cannot be the NFTFuseWrapper contract"
        );
        bytes32 labelhash = keccak256(bytes(label));
        setSubnodeOwner(parentNode, labelhash, address(this));
        _wrap(parentNode, labelhash, _fuses, newOwner);
        emit Wrap(parentNode, label, _fuses, newOwner);
    }

    /**
     * @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 returns (bytes32) {
        require(
            newOwner != address(this),
            "NFTFuseWrapper: newOwner cannot be the NFTFuseWrapper contract"
        );
        bytes32 labelhash = keccak256(bytes(label));
        setSubnodeRecord(parentNode, labelhash, address(this), resolver, ttl);
        _wrap(parentNode, labelhash, _fuses, newOwner);
        emit Wrap(parentNode, label, _fuses, newOwner);
    }

    /**
     * @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 ownerOnly(node) {
        require(
            canTransfer(node),
            "NFTFuseWrapper: Fuse is burned for transferring"
        );

        require(
            canSetResolver(node),
            "NFTFuseWrapper: Fuse is burned for setting resolver"
        );

        require(
            canSetTTL(node),
            "NFTFuseWrapper: Fuse is burned for setting 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
        ownerOnly(node)
    {
        require(
            canSetResolver(node),
            "NFTFuseWrapper: Fuse already burned for setting 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 ownerOnly(node) {
        require(
            canSetTTL(node),
            "NFTFuseWrapper: Fuse already burned for setting TTL"
        );
        ens.setTTL(node, ttl);
    }

    /**
     * @notice Sets TTL in the registry
     * @dev only callable by the .eth registrar
     * @param operator sender of the tx, either owner or approved caller
     * @param from owner of the token previously
     * @param tokenId namehash of the name
     * @param data data represents the fuses that will be passed when calling transferFrom on the
     *             .eth registrar
     */

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

        require(
            data.length == 0 || data.length == 12,
            "NFTFuseWrapper: Data is not of length 0 or 12"
        );

        if (data.length == 12) {
            fuses = data.readUint96(0);
        }

        bytes32 node = _makeNode(ETH_NODE, bytes32(tokenId));
        _wrapETH2LD(bytes32(tokenId), node, fuses, from);
        emit WrapETH2LD(bytes32(tokenId), fuses, from);
        return ERC721_RECEIVED;
    }

    /***** Internal functions */

    function _canTransfer(uint96 fuses) internal 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 _mint(
        bytes32 parentNode,
        bytes32 node,
        address newOwner,
        uint96 _fuses
    ) private {
        uint256 tokenId = uint256(node);
        address owner = ownerOf(tokenId);
        require(owner == address(0), "ERC1155: mint of existing token");
        require(newOwner != address(0), "ERC1155: mint to the zero address");
        setData(tokenId, newOwner, _fuses);

        if (_fuses != CAN_DO_EVERYTHING) {
            require(
                !canReplaceSubdomain(parentNode),
                "NFTFuseWrapper: Cannot burn fuses: parent name can replace subdomain"
            );

            require(
                !canUnwrap(node),
                "NFTFuseWrapper: Cannot burn fuses: domain can be unwrapped"
            );
        }
        emit TransferSingle(msg.sender, address(0x0), newOwner, tokenId, 1);
    }

    function _burn(uint256 tokenId) private {
        address owner = ownerOf(tokenId);
        // Clear fuses and set owner to 0
        setData(tokenId, address(0x0), 0);
        emit TransferSingle(msg.sender, owner, address(0x0), tokenId, 1);
    }

    function _wrap(
        bytes32 parentNode,
        bytes32 label,
        uint96 _fuses,
        address wrappedOwner
    ) private {
        require(
            parentNode != ETH_NODE,
            "NFTFuseWrapper: .eth domains need to use the wrapETH2LD"
        );

        bytes32 node = _makeNode(parentNode, label);

        _mint(parentNode, node, wrappedOwner, _fuses);
    }

    function _wrapETH2LD(
        bytes32 label,
        bytes32 node,
        uint96 _fuses,
        address wrappedOwner
    ) private {
        // transfer the ens record back to the new owner (this contract)
        registrar.reclaim(uint256(label), address(this));
        // mint a new ERC1155 token with fuses

        address oldWrappedOwner = ownerOf(uint256(node));
        if (oldWrappedOwner != address(0)) {
            _burn(uint256(node));
        }
        _mint(ETH_NODE, node, wrappedOwner, _fuses);

        emit WrapETH2LD(label, _fuses, wrappedOwner);
    }

    function _unwrap(
        bytes32 parentNode,
        bytes32 label,
        address newOwner
    ) private {
        bytes32 node = _makeNode(parentNode, label);
        require(
            newOwner != address(0x0),
            "NFTFuseWrapper: Target owner cannot be 0x0"
        );
        require(
            newOwner != address(this),
            "NFTFuseWrapper: Target owner cannot be the NFTFuseWrapper contract"
        );
        require(canUnwrap(node), "NFTFuseWrapper: Domain is not unwrappable");

        // burn token and fuse data
        _burn(uint256(node));
        ens.setOwner(node, newOwner);
        emit Unwrap(parentNode, label, newOwner);
    }
}

import "./ERC1155.sol";
import "../interfaces/INFTFuseWrapper.sol";
import "../interfaces/ENS.sol";
import "../interfaces/BaseRegistrar.sol";
import "../interfaces/Resolver.sol";
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "./BytesUtil.sol";
import "hardhat/console.sol";

contract NFTFuseWrapper is ERC1155, INFTFuseWrapper {
    using BytesUtils for bytes;
    ENS public ens;
    BaseRegistrar public registrar;
    bytes4 public constant ERC721_RECEIVED = 0x150b7a02;

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

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

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

    /**
     * @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 ownerOnly(bytes32 node) {
        require(
            isOwnerOrApproved(node, msg.sender),
            "NFTFuseWrapper: 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 isOwnerOrApproved(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 A number that represents the permissions a name has
     */

    function getFuses(bytes32 node) public view returns (uint96) {
        (, uint96 fuses) = getData(uint256(node));
        return fuses;
    }

    /**
     * @notice Check whether a name can be unwrapped
     *
     * @param node namehash of the name to check
     * @return Boolean of whether or not can be wrapped
     */

    function canUnwrap(bytes32 node) public view returns (bool) {
        uint96 fuses = getFuses(node);
        return fuses & CANNOT_UNWRAP == 0;
    }

    /**
     * @notice Check whether a name can burn fuses
     *
     * @param node namehash of the name to check
     * @return Boolean of whether or not can burn fuses
     */

    function canBurnFuses(bytes32 node) public view returns (bool) {
        uint96 fuses = getFuses(node);
        return fuses & CANNOT_BURN_FUSES == 0;
    }

    /**
     * @notice Check whether a name can be transferred
     *
     * @param node namehash of the name to check
     * @return Boolean of whether or not can be transferred
     */

    function canTransfer(bytes32 node) public view returns (bool) {
        uint96 fuses = getFuses(node);
        return fuses & CANNOT_TRANSFER == 0;
    }

    /**
     * @notice Check whether a name can set the resolver
     *
     * @param node namehash of the name to check
     * @return Boolean of whether or not resolver can be set
     */

    function canSetResolver(bytes32 node) public view returns (bool) {
        uint96 fuses = getFuses(node);
        return fuses & CANNOT_SET_RESOLVER == 0;
    }

    /**
     * @notice Check whether a name can set the TTL
     *
     * @param node namehash of the name to check
     * @return Boolean of whether or not TTL can be set
     */

    function canSetTTL(bytes32 node) public view returns (bool) {
        uint96 fuses = getFuses(node);
        return fuses & CANNOT_SET_TTL == 0;
    }

    /**
     * @notice Check whether a name can create a subdomain
     * @dev Creating a subdomain is defined as a subdomain that has a 0x0 owner and a new owner is set
     * @param node namehash of the name to check
     * @return Boolean of whether or not subdomains can be created
     */

    function canCreateSubdomain(bytes32 node) public view returns (bool) {
        uint96 fuses = getFuses(node);
        return fuses & CANNOT_CREATE_SUBDOMAIN == 0;
    }

    /**
     * @notice Check whether a name can replace a subdomain
     * @dev Replacing a subdomain is defined as a subdomain that has an existing owner and is overwritten
     * @param node namehash of the name to check
     * @return Boolean of whether or not TTL can be set
     */

    function canReplaceSubdomain(bytes32 node) public view returns (bool) {
        uint96 fuses = getFuses(node);
        return fuses & CANNOT_REPLACE_SUBDOMAIN == 0;
    }

    /**
     * @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
     * @return Boolean of whether or not setSubnodeOwner/setSubnodeRecord can be called
     */

    function canCallSetSubnodeOwner(bytes32 node, bytes32 label)
        public
        view
        returns (bool)
    {
        bytes32 subnode = _makeNode(node, label);
        address owner = ens.owner(subnode);

        return
            (owner == address(0) && canCreateSubdomain(node)) ||
            (owner != address(0) && canReplaceSubdomain(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,
        uint96 _fuses,
        address wrappedOwner
    ) public override {
        bytes32 labelhash = keccak256(bytes(label));
        bytes32 node = _makeNode(ETH_NODE, labelhash);
        uint256 tokenId = uint256(labelhash);
        address owner = registrar.ownerOf(tokenId);

        require(
            owner == msg.sender ||
                registrar.isApprovedForAll(owner, msg.sender) ||
                isApprovedForAll(owner, msg.sender),
            "NFTFuseWrapper: Sender is not owner or authorised by the owner or authorised on the .eth registrar"
        );
        // transfer the token from the user to this contract
        address currentOwner = registrar.ownerOf(tokenId);
        registrar.transferFrom(currentOwner, address(this), tokenId);

        // transfer the ens record back to the new owner (this contract)
        _wrapETH2LD(labelhash, node, _fuses, wrappedOwner);
    }

    /**
     * @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 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 _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(
        bytes32 parentNode,
        string calldata label,
        uint96 _fuses,
        address wrappedOwner
    ) public override {
        bytes32 labelhash = keccak256(bytes(label));
        bytes32 node = _makeNode(parentNode, labelhash);
        _wrap(parentNode, labelhash, _fuses, wrappedOwner);
        address owner = ens.owner(node);

        require(
            owner == msg.sender ||
                ens.isApprovedForAll(owner, msg.sender) ||
                isApprovedForAll(owner, msg.sender),
            "NFTFuseWrapper: Domain is not owned by the sender"
        );
        ens.setOwner(node, address(this));
        emit Wrap(parentNode, label, _fuses, wrappedOwner);
    }

    /**
     * @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 ownerOnly(_makeNode(ETH_NODE, label)) {
        _unwrap(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 ownerOnly(_makeNode(parentNode, label)) {
        require(
            parentNode != ETH_NODE,
            "NFTFuseWrapper: .eth names must be unwrapped with unwrapETH2LD()"
        );
        _unwrap(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 parentNode parent namehash of the name. e.g. vitalik.xyz would be namehash('xyz')
     * @param labelhash labelhash of the name. e.g. vitalik.xyz would be labelhash('vitalik')
     * @param _fuses Fuses you want to burn.
     */

    function burnFuses(
        bytes32 parentNode,
        bytes32 labelhash,
        uint96 _fuses
    ) public ownerOnly(_makeNode(parentNode, labelhash)) {
        bytes32 node = _makeNode(parentNode, labelhash);

        require(
            canBurnFuses(node),
            "NFTFuseWrapper: Fuse has been burned for burning fuses"
        );

        require(
            !canReplaceSubdomain(parentNode),
            "NFTFuseWrapper: Parent has not burned CAN_REPLACE_SUBDOMAIN fuse"
        );

        (address owner, uint96 fuses) = getData(uint256(node));

        setData(uint256(node), owner, fuses | _fuses);

        require(
            !canUnwrap(node),
            "NFTFuseWrapper: Domain has not burned unwrap fuse"
        );
    }

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

    function setSubnodeRecord(
        bytes32 node,
        bytes32 label,
        address owner,
        address resolver,
        uint64 ttl
    ) public ownerOnly(node) {
        require(
            canCallSetSubnodeOwner(node, label),
            "NFTFuseWrapper: Fuse has been burned for creating or replacing a subdomain"
        );

        return ens.setSubnodeRecord(node, label, owner, resolver, ttl);
    }

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

    function setSubnodeOwner(
        bytes32 node,
        bytes32 label,
        address owner
    ) public override ownerOnly(node) returns (bytes32) {
        require(
            canCallSetSubnodeOwner(node, label),
            "NFTFuseWrapper: Fuse has been burned for creating or replacing a subdomain"
        );

        ens.setSubnodeOwner(node, 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) {
        require(
            newOwner != address(this),
            "NFTFuseWrapper: newOwner cannot be the NFTFuseWrapper contract"
        );
        bytes32 labelhash = keccak256(bytes(label));
        setSubnodeOwner(parentNode, labelhash, address(this));
        _wrap(parentNode, labelhash, _fuses, newOwner);
        emit Wrap(parentNode, label, _fuses, newOwner);
    }

    /**
     * @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 returns (bytes32) {
        require(
            newOwner != address(this),
            "NFTFuseWrapper: newOwner cannot be the NFTFuseWrapper contract"
        );
        bytes32 labelhash = keccak256(bytes(label));
        setSubnodeRecord(parentNode, labelhash, address(this), resolver, ttl);
        _wrap(parentNode, labelhash, _fuses, newOwner);
        emit Wrap(parentNode, label, _fuses, newOwner);
    }

    /**
     * @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 ownerOnly(node) {
        require(
            canTransfer(node),
            "NFTFuseWrapper: Fuse is burned for transferring"
        );

        require(
            canSetResolver(node),
            "NFTFuseWrapper: Fuse is burned for setting resolver"
        );

        require(
            canSetTTL(node),
            "NFTFuseWrapper: Fuse is burned for setting 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
        ownerOnly(node)
    {
        require(
            canSetResolver(node),
            "NFTFuseWrapper: Fuse already burned for setting 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 ownerOnly(node) {
        require(
            canSetTTL(node),
            "NFTFuseWrapper: Fuse already burned for setting TTL"
        );
        ens.setTTL(node, ttl);
    }

    /**
     * @notice Sets TTL in the registry
     * @dev only callable by the .eth registrar
     * @param operator sender of the tx, either owner or approved caller
     * @param from owner of the token previously
     * @param tokenId namehash of the name
     * @param data data represents the fuses that will be passed when calling transferFrom on the
     *             .eth registrar
     */

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

        require(
            data.length == 0 || data.length == 12,
            "NFTFuseWrapper: Data is not of length 0 or 12"
        );

        if (data.length == 12) {
            fuses = data.readUint96(0);
        }

        bytes32 node = _makeNode(ETH_NODE, bytes32(tokenId));
        _wrapETH2LD(bytes32(tokenId), node, fuses, from);
        emit WrapETH2LD(bytes32(tokenId), fuses, from);
        return ERC721_RECEIVED;
    }

    /***** Internal functions */

    function _canTransfer(uint96 fuses) internal 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 _mint(
        uint256 tokenId,
        address newOwner,
        uint96 fuses
    ) private {
        address owner = ownerOf(tokenId);
        require(owner == address(0), "ERC1155: mint of existing token");
        require(newOwner != address(0), "ERC1155: mint to the zero address");
        setData(tokenId, newOwner, fuses);
        emit TransferSingle(msg.sender, address(0x0), newOwner, tokenId, 1);
    }

    function _burn(uint256 tokenId) private {
        address owner = ownerOf(tokenId);
        // Clear fuses and set owner to 0
        setData(tokenId, address(0x0), 0);
        emit TransferSingle(msg.sender, owner, address(0x0), tokenId, 1);
    }

    function _wrap(
        bytes32 parentNode,
        bytes32 label,
        uint96 _fuses,
        address wrappedOwner
    ) private {
        require(
            parentNode != ETH_NODE,
            "NFTFuseWrapper: .eth domains need to use the wrapETH2LD"
        );

        bytes32 node = _makeNode(parentNode, label);

        _mint(uint256(node), wrappedOwner, _fuses);

        if (_fuses != CAN_DO_EVERYTHING) {
            require(
                !canReplaceSubdomain(parentNode),
                "NFTFuseWrapper: Cannot burn fuses: parent name can replace subdomain"
            );

            require(
                !canUnwrap(node),
                "NFTFuseWrapper: Cannot burn fuses: domain can be unwrapped"
            );
        }
    }

    function _wrapETH2LD(
        bytes32 label,
        bytes32 node,
        uint96 _fuses,
        address wrappedOwner
    ) private {
        // transfer the ens record back to the new owner (this contract)
        registrar.reclaim(uint256(label), address(this));
        // mint a new ERC1155 token with fuses

        address oldWrappedOwner = ownerOf(uint256(node));
        if (oldWrappedOwner != address(0)) {
            _burn(uint256(node));
        }
        _mint(uint256(node), wrappedOwner, _fuses);

        if (_fuses != CAN_DO_EVERYTHING) {
            require(
                !canUnwrap(node),
                "NFTFuseWrapper: Cannot burn fuses: domain can be unwrapped"
            );
        }

        emit WrapETH2LD(label, _fuses, wrappedOwner);
    }

    function _unwrap(
        bytes32 parentNode,
        bytes32 label,
        address newOwner
    ) private {
        bytes32 node = _makeNode(parentNode, label);
        require(
            newOwner != address(0x0),
            "NFTFuseWrapper: Target owner cannot be 0x0"
        );
        require(
            newOwner != address(this),
            "NFTFuseWrapper: Target owner cannot be the NFTFuseWrapper contract"
        );
        require(canUnwrap(node), "NFTFuseWrapper: Domain is not unwrappable");

        // burn token and fuse data
        _burn(uint256(node));
        ens.setOwner(node, newOwner);
        emit Unwrap(parentNode, label, newOwner);
    }
}


Change _mint to internal

Change _mint to internal

import "./ERC1155.sol";
import "../interfaces/ENS.sol";
import "../interfaces/BaseRegistrar.sol";
import "../interfaces/Resolver.sol";
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "hardhat/console.sol";

contract NFTFuseWrapper is ERC1155 {
    ENS public ens;
    BaseRegistrar public registrar;
    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;

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

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

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

    /**************************************************************************
     * Wrapper
     *************************************************************************/

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

    modifier ownerOnly(bytes32 node) {
        require(
            isOwnerOrApproved(node, msg.sender),
            "NFTFuseWrapper: msg.sender is not the owner or approved"
        );
        _;
    }

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

    function canUnwrap(bytes32 node) public view returns (bool) {
        (, uint96 fuses) = getData(uint256(node));
        return fuses & CANNOT_UNWRAP == 0;
    }

    function canBurnFuses(bytes32 node) public view returns (bool) {
        (, uint96 fuses) = getData(uint256(node));
        return fuses & CANNOT_BURN_FUSES == 0;
    }

    function canTransfer(bytes32 node) public view returns (bool) {
        (, uint96 fuses) = getData(uint256(node));
        return fuses & CANNOT_TRANSFER == 0;
    }

    function canSetData(bytes32 node) public view returns (bool) {
        (, uint96 fuses) = getData(uint256(node));
        return fuses & CANNOT_SET_DATA == 0;
    }

    function canCreateSubdomain(bytes32 node) public view returns (bool) {
        (, uint96 fuses) = getData(uint256(node));
        return fuses & CANNOT_CREATE_SUBDOMAIN == 0;
    }

    function canReplaceSubdomain(bytes32 node) public view returns (bool) {
        (, uint96 fuses) = getData(uint256(node));
        return fuses & CANNOT_REPLACE_SUBDOMAIN == 0;
    }

    function canCallSetSubnodeOwner(bytes32 node, bytes32 label)
        public
        returns (bool)
    {
        bytes32 subnode = makeNode(node, label);
        address owner = ens.owner(subnode);

        return
            (owner == address(0) && canCreateSubdomain(node)) ||
            (owner != address(0) && canReplaceSubdomain(node));
    }

    function _mint(
        uint256 tokenId,
        address newOwner,
        uint96 fuses
    ) internal {
        address owner = ownerOf(tokenId);
        require(owner == address(0), "ERC1155: mint of existing token");
        require(newOwner != address(0), "ERC1155: mint to the zero address");
        setData(tokenId, newOwner, fuses);
        emit TransferSingle(msg.sender, owner, address(0x0), tokenId, 1);
    }

    function _burn(uint256 tokenId) internal {
        address owner = ownerOf(tokenId);
        // Clear fuses and set owner to 0
        setData(tokenId, address(0x0), 0);
        emit TransferSingle(msg.sender, owner, address(0x0), tokenId, 1);
    }

    function wrapETH2LD(
        string calldata label,
        uint96 _fuses,
        address wrappedOwner
    ) public override {
        bytes32 labelhash = keccak256(bytes(label));
        bytes32 node = makeNode(ETH_NODE, labelhash);
        uint256 tokenId = uint256(labelhash);
        address owner = ens.owner(node);

        // TODO: test account a creates a name, authorised wrapper, account b tries to do something with thename
        require(
            owner == msg.sender ||
                ens.isApprovedForAll(owner, msg.sender) ||
                isApprovedForAll(owner, msg.sender),
            "NFTFuseWrapper: Domain is not owned by the sender"
        );

        // transfer the token from the user to this contract
        address currentOwner = registrar.ownerOf(tokenId);
        registrar.transferFrom(currentOwner, address(this), tokenId);

        // transfer the ens record back to the new owner (this contract)
        _wrapETH2LD(labelhash, node, _fuses, wrappedOwner);

        emit Wrap(ETH_NODE, label, _fuses, owner);
    }

    function _wrapETH2LD(
        bytes32 label,
        bytes32 node,
        uint96 _fuses,
        address wrappedOwner
    ) private {
        // transfer the ens record back to the new owner (this contract)
        registrar.reclaim(uint256(label), address(this));
        // mint a new ERC1155 token with fuses
        _mint(uint256(node), wrappedOwner, _fuses);
    }

    function wrap(
        bytes32 parentNode,
        string calldata label,
        uint96 _fuses,
        address wrappedOwner
    ) public override {
        bytes32 labelhash = keccak256(bytes(label));
        bytes32 node = makeNode(parentNode, labelhash);
        _wrap(parentNode, labelhash, _fuses, wrappedOwner);
        address owner = ens.owner(node);

        require(
            owner == msg.sender ||
                ens.isApprovedForAll(owner, msg.sender) ||
                isApprovedForAll(owner, msg.sender),
            "NFTFuseWrapper: Domain is not owned by the sender"
        );
        ens.setOwner(node, address(this));
        emit Wrap(parentNode, label, _fuses, owner);
    }

    function _wrap(
        bytes32 parentNode,
        bytes32 label,
        uint96 _fuses,
        address wrappedOwner
    ) private {
        require(
            parentNode != ETH_NODE,
            "NFTFuseWrapper: .eth domains need to use the wrapETH2LD"
        );

        bytes32 node = makeNode(parentNode, label);

        _mint(uint256(node), wrappedOwner, _fuses);

        if (_fuses != CAN_DO_EVERYTHING) {
            require(
                !canReplaceSubdomain(parentNode),
                "NFTFuseWrapper: Cannot burn fuses: parent name can replace subdomain"
            );

            require(
                !canUnwrap(node),
                "NFTFuseWrapper: Cannot burn fuses: domain can be unwrapped"
            );
        }
    }

    function unwrap(bytes32 node, address owner)
        public
        override
        ownerOnly(node)
    {
        require(owner != address(0x0));
        require(canUnwrap(node), "NFTFuseWrapper: Domain is not unwrappable");

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

    function unwrapETH2LD(bytes32 label, address owner) public {
        //unwrap checks ownerOnly so no need to add separate modifier
        unwrap(makeNode(ETH_NODE, label), owner);
        //transfer back original ERC721 to owner
        registrar.transferFrom(address(this), owner, uint256(label));
    }

    function burnFuses(
        bytes32 parentNode,
        bytes32 label,
        uint96 _fuses
    ) public ownerOnly(makeNode(parentNode, label)) {
        bytes32 node = makeNode(parentNode, label);

        require(
            canBurnFuses(node),
            "NFTFuseWrapper: Fuse has been burned for burning fuses"
        );

        // check that the parent has the CAN_REPLACE_SUBDOMAIN fuse burned, and the current domain has the CAN_UNWRAP fuse burned

        require(
            !canReplaceSubdomain(parentNode),
            "NFTFuseWrapper: Parent has not burned CAN_REPLACE_SUBDOMAIN fuse"
        );

        (address owner, uint96 fuses) = getData(uint256(node));

        setData(uint256(node), owner, fuses | _fuses);

        require(
            !canUnwrap(node),
            "NFTFuseWrapper: Domain has not burned unwrap fuse"
        );
    }

    function setRecord(
        bytes32 node,
        address owner,
        address resolver,
        uint64 ttl
    ) external {
        require(
            canTransfer(node),
            "NFTFuseWrapper: Fuse is burned for transferring"
        );
        require(
            canSetData(node),
            "NFTFuseWrapper: Fuse is burned for setting data"
        );
        ens.setRecord(node, owner, resolver, ttl);
    }

    function setSubnodeRecord(
        bytes32 node,
        bytes32 label,
        address addr,
        address resolver,
        uint64 ttl
    ) public ownerOnly(node) {
        require(
            canCallSetSubnodeOwner(node, label),
            "NFTFuseWrapper: Fuse has been burned for creating or replacing a subdomain"
        );

        return ens.setSubnodeRecord(node, label, addr, resolver, ttl);
    }

    function setSubnodeOwner(
        bytes32 node,
        bytes32 label,
        address newOwner
    ) public override ownerOnly(node) returns (bytes32) {
        require(
            canCallSetSubnodeOwner(node, label),
            "NFTFuseWrapper: Fuse has been burned for creating or replacing a subdomain"
        );

        ens.setSubnodeOwner(node, label, newOwner);
    }

    function setSubnodeOwnerAndWrap(
        bytes32 node,
        bytes32 label,
        address newOwner,
        uint96 _fuses
    ) public override returns (bytes32) {
        setSubnodeOwner(node, label, address(this));
        _wrap(node, label, _fuses, newOwner);
    }

    function setSubnodeRecordAndWrap(
        bytes32 node,
        bytes32 label,
        address owner,
        address resolver,
        uint64 ttl,
        uint96 _fuses
    ) public override returns (bytes32) {
        setSubnodeRecord(node, label, address(this), resolver, ttl);
        _wrap(node, label, _fuses, owner);
    }

    function setResolver(bytes32 node, address resolver)
        public
        override
        ownerOnly(node)
    {
        require(
            canSetData(node),
            "NFTFuseWrapper: Fuse already burned for setting resolver"
        );
        ens.setResolver(node, resolver);
    }

    function setTTL(bytes32 node, uint64 ttl) public ownerOnly(node) {
        require(
            canSetData(node),
            "NFTFuseWrapper: Fuse already burned for setting TTL"
        );
        ens.setTTL(node, ttl);
    }

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

        bytes32 node = makeNode(ETH_NODE, bytes32(tokenId));
        _wrapETH2LD(bytes32(tokenId), node, uint96(0), from);
        return _ERC721_RECEIVED;
    }
}

import "./ERC1155.sol";
import "../interfaces/ENS.sol";
import "../interfaces/BaseRegistrar.sol";
import "../interfaces/Resolver.sol";
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "hardhat/console.sol";

contract NFTFuseWrapper is ERC1155 {
    ENS public ens;
    BaseRegistrar public registrar;
    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;

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

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

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

    /**************************************************************************
     * Wrapper
     *************************************************************************/

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

    modifier ownerOnly(bytes32 node) {
        require(
            isOwnerOrApproved(node, msg.sender),
            "NFTFuseWrapper: msg.sender is not the owner or approved"
        );
        _;
    }

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

    function canUnwrap(bytes32 node) public view returns (bool) {
        (, uint96 fuses) = getData(uint256(node));
        return fuses & CANNOT_UNWRAP == 0;
    }

    function canBurnFuses(bytes32 node) public view returns (bool) {
        (, uint96 fuses) = getData(uint256(node));
        return fuses & CANNOT_BURN_FUSES == 0;
    }

    function canTransfer(bytes32 node) public view returns (bool) {
        (, uint96 fuses) = getData(uint256(node));
        return fuses & CANNOT_TRANSFER == 0;
    }

    function canSetData(bytes32 node) public view returns (bool) {
        (, uint96 fuses) = getData(uint256(node));
        return fuses & CANNOT_SET_DATA == 0;
    }

    function canCreateSubdomain(bytes32 node) public view returns (bool) {
        (, uint96 fuses) = getData(uint256(node));
        return fuses & CANNOT_CREATE_SUBDOMAIN == 0;
    }

    function canReplaceSubdomain(bytes32 node) public view returns (bool) {
        (, uint96 fuses) = getData(uint256(node));
        return fuses & CANNOT_REPLACE_SUBDOMAIN == 0;
    }

    function canCallSetSubnodeOwner(bytes32 node, bytes32 label)
        public
        returns (bool)
    {
        bytes32 subnode = makeNode(node, label);
        address owner = ens.owner(subnode);

        return
            (owner == address(0) && canCreateSubdomain(node)) ||
            (owner != address(0) && canReplaceSubdomain(node));
    }

    function _mint(
        uint256 tokenId,
        address newOwner,
        uint96 fuses
    ) public {
        address owner = ownerOf(tokenId);
        require(owner == address(0), "ERC1155: mint of existing token");
        require(newOwner != address(0), "ERC1155: mint to the zero address");
        setData(tokenId, newOwner, fuses);
        emit TransferSingle(msg.sender, owner, address(0x0), tokenId, 1);
    }

    function _burn(uint256 tokenId) internal {
        address owner = ownerOf(tokenId);
        // Clear fuses and set owner to 0
        setData(tokenId, address(0x0), 0);
        emit TransferSingle(msg.sender, owner, address(0x0), tokenId, 1);
    }

    function wrapETH2LD(
        string calldata label,
        uint96 _fuses,
        address wrappedOwner
    ) public override {
        bytes32 labelhash = keccak256(bytes(label));
        bytes32 node = makeNode(ETH_NODE, labelhash);
        uint256 tokenId = uint256(labelhash);
        address owner = ens.owner(node);

        // TODO: test account a creates a name, authorised wrapper, account b tries to do something with thename
        require(
            owner == msg.sender ||
                ens.isApprovedForAll(owner, msg.sender) ||
                isApprovedForAll(owner, msg.sender),
            "NFTFuseWrapper: Domain is not owned by the sender"
        );

        // transfer the token from the user to this contract
        address currentOwner = registrar.ownerOf(tokenId);
        registrar.transferFrom(currentOwner, address(this), tokenId);

        // transfer the ens record back to the new owner (this contract)
        _wrapETH2LD(labelhash, node, _fuses, wrappedOwner);

        emit Wrap(ETH_NODE, label, _fuses, owner);
    }

    function _wrapETH2LD(
        bytes32 label,
        bytes32 node,
        uint96 _fuses,
        address wrappedOwner
    ) private {
        // transfer the ens record back to the new owner (this contract)
        registrar.reclaim(uint256(label), address(this));
        // mint a new ERC1155 token with fuses
        _mint(uint256(node), wrappedOwner, _fuses);
    }

    function wrap(
        bytes32 parentNode,
        string calldata label,
        uint96 _fuses,
        address wrappedOwner
    ) public override {
        bytes32 labelhash = keccak256(bytes(label));
        bytes32 node = makeNode(parentNode, labelhash);
        _wrap(parentNode, labelhash, _fuses, wrappedOwner);
        address owner = ens.owner(node);

        require(
            owner == msg.sender ||
                ens.isApprovedForAll(owner, msg.sender) ||
                isApprovedForAll(owner, msg.sender),
            "NFTFuseWrapper: Domain is not owned by the sender"
        );
        ens.setOwner(node, address(this));
        emit Wrap(parentNode, label, _fuses, owner);
    }

    function _wrap(
        bytes32 parentNode,
        bytes32 label,
        uint96 _fuses,
        address wrappedOwner
    ) private {
        require(
            parentNode != ETH_NODE,
            "NFTFuseWrapper: .eth domains need to use the wrapETH2LD"
        );

        bytes32 node = makeNode(parentNode, label);

        _mint(uint256(node), wrappedOwner, _fuses);

        if (_fuses != CAN_DO_EVERYTHING) {
            require(
                !canReplaceSubdomain(parentNode),
                "NFTFuseWrapper: Cannot burn fuses: parent name can replace subdomain"
            );

            require(
                !canUnwrap(node),
                "NFTFuseWrapper: Cannot burn fuses: domain can be unwrapped"
            );
        }
    }

    function unwrap(bytes32 node, address owner)
        public
        override
        ownerOnly(node)
    {
        require(owner != address(0x0));
        require(canUnwrap(node), "NFTFuseWrapper: Domain is not unwrappable");

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

    function unwrapETH2LD(bytes32 label, address owner) public {
        //unwrap checks ownerOnly so no need to add separate modifier
        unwrap(makeNode(ETH_NODE, label), owner);
        //transfer back original ERC721 to owner
        registrar.transferFrom(address(this), owner, uint256(label));
    }

    function burnFuses(
        bytes32 parentNode,
        bytes32 label,
        uint96 _fuses
    ) public ownerOnly(makeNode(parentNode, label)) {
        bytes32 node = makeNode(parentNode, label);

        require(
            canBurnFuses(node),
            "NFTFuseWrapper: Fuse has been burned for burning fuses"
        );

        // check that the parent has the CAN_REPLACE_SUBDOMAIN fuse burned, and the current domain has the CAN_UNWRAP fuse burned

        require(
            !canReplaceSubdomain(parentNode),
            "NFTFuseWrapper: Parent has not burned CAN_REPLACE_SUBDOMAIN fuse"
        );

        (address owner, uint96 fuses) = getData(uint256(node));

        setData(uint256(node), owner, fuses | _fuses);

        require(
            !canUnwrap(node),
            "NFTFuseWrapper: Domain has not burned unwrap fuse"
        );
    }

    function setRecord(
        bytes32 node,
        address owner,
        address resolver,
        uint64 ttl
    ) external {
        require(
            canTransfer(node),
            "NFTFuseWrapper: Fuse is burned for transferring"
        );
        require(
            canSetData(node),
            "NFTFuseWrapper: Fuse is burned for setting data"
        );
        ens.setRecord(node, owner, resolver, ttl);
    }

    function setSubnodeRecord(
        bytes32 node,
        bytes32 label,
        address addr,
        address resolver,
        uint64 ttl
    ) public ownerOnly(node) {
        require(
            canCallSetSubnodeOwner(node, label),
            "NFTFuseWrapper: Fuse has been burned for creating or replacing a subdomain"
        );

        return ens.setSubnodeRecord(node, label, addr, resolver, ttl);
    }

    function setSubnodeOwner(
        bytes32 node,
        bytes32 label,
        address newOwner
    ) public override ownerOnly(node) returns (bytes32) {
        require(
            canCallSetSubnodeOwner(node, label),
            "NFTFuseWrapper: Fuse has been burned for creating or replacing a subdomain"
        );

        ens.setSubnodeOwner(node, label, newOwner);
    }

    function setSubnodeOwnerAndWrap(
        bytes32 node,
        bytes32 label,
        address newOwner,
        uint96 _fuses
    ) public override returns (bytes32) {
        setSubnodeOwner(node, label, address(this));
        _wrap(node, label, _fuses, newOwner);
    }

    function setSubnodeRecordAndWrap(
        bytes32 node,
        bytes32 label,
        address owner,
        address resolver,
        uint64 ttl,
        uint96 _fuses
    ) public override returns (bytes32) {
        setSubnodeRecord(node, label, address(this), resolver, ttl);
        _wrap(node, label, _fuses, owner);
    }

    function setResolver(bytes32 node, address resolver)
        public
        override
        ownerOnly(node)
    {
        require(
            canSetData(node),
            "NFTFuseWrapper: Fuse already burned for setting resolver"
        );
        ens.setResolver(node, resolver);
    }

    function setTTL(bytes32 node, uint64 ttl) public ownerOnly(node) {
        require(
            canSetData(node),
            "NFTFuseWrapper: Fuse already burned for setting TTL"
        );
        ens.setTTL(node, ttl);
    }

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

        bytes32 node = makeNode(ETH_NODE, bytes32(tokenId));
        _wrapETH2LD(bytes32(tokenId), node, uint96(0), from);
        return _ERC721_RECEIVED;
    }
}


AssertUint.sol

AssertUint.sol

pragma solidity >= 0.4.15 < 0.6.0;

library AssertUint {

    uint8 constant ZERO = uint8(byte('0'));
    uint8 constant A = uint8(byte('a'));

    /*
        Event: TestEvent

        Fired when an assertion is made.

        Params:
            result (bool) - Whether or not the assertion holds.
            message (string) - A message to display if the assertion does not hold.
    */
    event TestEvent(bool indexed result, string message);

    // ************************************** uint **************************************

    /*
        Function: equal(uint)

        Assert that two (256 bit) unsigned integers are equal.

        : A == B

        Params:
            A (uint) - The first uint.
            B (uint) - The second uint.
            message (string) - A message that is sent if the assertion fails.

        Returns:
            result (bool) - The result.
    */
    function equal(uint a, uint b, string memory message) public returns (bool result) {
        result = (a == b);
        if (result)
            _report(result, message);
        else
            _report(result, _appendTagged(_tag(a, "Tested"), _tag(b, "Against"), message));
    }

    /*
        Function: notEqual(uint)

        Assert that two (256 bit) unsigned integers are not equal.

        : A != B

        Params:
            A (uint) - The first uint.
            B (uint) - The second uint.
            message (string) - A message that is sent if the assertion fails.

        Returns:
            result (bool) - The result.
    */
    function notEqual(uint a, uint b, string memory message) public returns (bool result) {
        result = (a != b);
        if (result)
            _report(result, message);
        else
            _report(result, _appendTagged(_tag(a, "Tested"), _tag(b, "Against"), message));
    }

    /*
        Function: isAbove(uint)

        Assert that the uint 'A' is greater than the uint 'B'.

        : A > B

        Params:
            A (uint) - The first uint.
            B (uint) - The second uint.
            message (string) - A message that is sent if the assertion fails.

        Returns:
            result (bool) - The result.
    */
    function isAbove(uint a, uint b, string memory message) public returns (bool result) {
        result = (a > b);
        if (result)
            _report(result, message);
        else
            _report(result, _appendTagged(_tag(a, "Tested"), _tag(b, "Against"), message));
    }

    /*
        Function: isAtLeast(uint)

        Assert that the uint 'A' is greater than or equal to the uint 'B'.

        : A >= B

        Params:
            A (uint) - The first uint.
            B (uint) - The second uint.
            message (string) - A message that is sent if the assertion fails.

        Returns:
            result (bool) - The result.
    */
    function isAtLeast(uint a, uint b, string memory message) public returns (bool result) {
        result = (a >= b);
        if (result)
            _report(result, message);
        else
            _report(result, _appendTagged(_tag(a, "Tested"), _tag(b, "Against"), message));
    }

    /*
        Function: isBelow(uint)

        Assert that the uint 'A' is lesser than the uint 'B'.

        : A < B

        Params:
            A (uint) - The first uint.
            B (uint) - The second uint.
            message (string) - A message that is sent if the assertion fails.

        Returns:
            result (bool) - The result.
    */
    function isBelow(uint a, uint b, string memory message) public returns (bool result) {
        result = (a < b);
        if (result)
            _report(result, message);
        else
            _report(result, _appendTagged(_tag(a, "Tested"), _tag(b, "Against"), message));
    }

    /*
        Function: isAtMost(uint)

        Assert that the uint 'A' is lesser than or equal to the uint 'B'.

        : A <= B

        Params:
            A (uint) - The first uint.
            B (uint) - The second uint.
            message (string) - A message that is sent if the assertion fails.

        Returns:
            result (bool) - The result.
    */
    function isAtMost(uint a, uint b, string memory message) public returns (bool result) {
        result = (a <= b);
        if (result)
            _report(result, message);
        else
            _report(result, _appendTagged(_tag(a, "Tested"), _tag(b, "Against"), message));
    }

    /*
        Function: isZero(uint)

        Assert that a (256 bit) unsigned integer is 0.

        : number == 0

        Params:
            number (uint) - The uint.
            message (string) - A message that is sent if the assertion fails.

        Returns:
            result (bool) - The result.
    */
    function isZero(uint number, string memory message) public returns (bool result) {
        result = (number == 0);
        if (result)
            _report(result, message);
        else
            _report(result, _appendTagged(_tag(number, "Tested"), message));
    }

    /*
        Function: isNotZero(uint)

        Assert that a (256 bit) unsigned integer is not 0.

        : number != 0

        Params:
            number (uint) - The uint.
            message (string) - A message that is sent if the assertion fails.

        Returns:
            result (bool) - The result.
    */
    function isNotZero(uint number, string memory message) public returns (bool result) {
        result = (number != 0);
        if (result)
            _report(result, message);
        else
            _report(result, _appendTagged(_tag(number, "Tested"), message));
    }

    /******************************** internal ********************************/

        /*
            Function: _report

            Internal function for triggering <TestEvent>.

            Params:
                result (bool) - The test result (true or false).
                message (string) - The message that is sent if the assertion fails.
        */
    function _report(bool result, string memory message) internal {
        if(result)
            emit TestEvent(true, "");
        else
            emit TestEvent(false, message);
    }

    /*
        Function: _utoa(uint)

        Convert an  unsigned integer to a string.

        Params:
            n (uint) - The unsigned integer.
            radix (uint8) - A number between 2 and 16 (inclusive). Characters used are 0-9,a-f

        Returns:
            result (string) - The resulting string.
    */
    function _utoa(uint n, uint8 radix) internal pure returns (string memory) {
        if (n == 0 || radix < 2 || radix > 16)
            return '0';
        bytes memory bts = new bytes(256);
        uint i;
        while (n > 0) {
            bts[i++] = _utoa(uint8(n % radix)); // Turn it to ascii.
            n /= radix;
        }
        // Reverse
        bytes memory rev = new bytes(i);
        for (uint j = 0; j < i; j++)
            rev[j] = bts[i - j - 1];
        return string(rev);
    }

    /*
        Function: _utoa(uint8)

        Convert an unsigned 8-bit integer to its ASCII byte representation. Numbers 0-9 are converted to '0'-'9',
        numbers 10-16 to 'a'-'f'. Numbers larger then 16 return the null byte.

        Params:
            u (uint8) - The unsigned 8-bit integer.

        Returns:
            result (string) - The ASCII byte.
    */
    function _utoa(uint8 u) internal pure returns (byte) {
        if (u < 10)
            return byte(u + ZERO);
        else if (u < 16)
            return byte(u - 10 + A);
        else
            return 0;
    }

    /*
    function htoa(address addr) constant returns (string) {
        bytes memory bts = new bytes(40);
        bytes20 addrBts = bytes20(addr);
        for (uint i = 0; i < 20; i++) {
            bts[2*i] = addrBts[i] % 16;
            bts[2*i + 1] = (addrBts[i] / 16) % 16;
        }
        return string(bts);
    }
    */

    /*
        Function: _tag(string)

        Add a tag to a string. The 'value' and 'tag' strings are returned on the form "tag: value".

        Params:
            value (string) - The value.
            tag (string) - The tag.

        Returns:
            result (string) - "tag: value"
    */
    function _tag(string memory value, string memory tag) internal pure returns (string memory) {

        bytes memory valueB = bytes(value);
        bytes memory tagB = bytes(tag);

        uint vl = valueB.length;
        uint tl = tagB.length;

        bytes memory newB = new bytes(vl + tl + 2);

        uint i;
        uint j;

        for (i = 0; i < tl; i++)
            newB[j++] = tagB[i];
        newB[j++] = ':';
        newB[j++] = ' ';
        for (i = 0; i < vl; i++)
            newB[j++] = valueB[i];

        return string(newB);
    }

    /*
        Function: _tag(uint)

        Add a tag to an uint.

        Params:
            value (uint) - The value.
            tag (string) - The tag.

        Returns:
            result (string) - "tag: _utoa(value)"
    */
    function _tag(uint value, string memory tag) internal pure returns (string memory) {
        string memory nstr = _utoa(value, 10);
        return _tag(nstr, tag);
    }

    /*
        Function: _appendTagged(string)

        Append a tagged value to a string.

        Params:
            tagged (string) - The tagged value.
            str (string) - The string.

        Returns:
            result (string) - "str (tagged)"
    */
    function _appendTagged(string memory tagged, string memory str) internal pure returns (string memory) {

        bytes memory taggedB = bytes(tagged);
        bytes memory strB = bytes(str);

        uint sl = strB.length;
        uint tl = taggedB.length;

        bytes memory newB = new bytes(sl + tl + 3);

        uint i;
        uint j;

        for (i = 0; i < sl; i++)
            newB[j++] = strB[i];
        newB[j++] = ' ';
        newB[j++] = '(';
        for (i = 0; i < tl; i++)
            newB[j++] = taggedB[i];
        newB[j++] = ')';

        return string(newB);
    }

    /*
        Function: _appendTagged(string, string)

        Append two tagged values to a string.

        Params:
            tagged0 (string) - The first tagged value.
            tagged1 (string) - The second tagged value.
            str (string) - The string.

        Returns:
            result (string) - "str (tagged0, tagged1)"
    */
    function _appendTagged(string memory tagged0, string memory tagged1, string memory str) internal pure returns (string memory) {

        bytes memory tagged0B = bytes(tagged0);
        bytes memory tagged1B = bytes(tagged1);
        bytes memory strB = bytes(str);

        uint sl = strB.length;
        uint t0l = tagged0B.length;
        uint t1l = tagged1B.length;

        bytes memory newB = new bytes(sl + t0l + t1l + 5);

        uint i;
        uint j;

        for (i = 0; i < sl; i++)
            newB[j++] = strB[i];
        newB[j++] = ' ';
        newB[j++] = '(';
        for (i = 0; i < t0l; i++)
            newB[j++] = tagged0B[i];
        newB[j++] = ',';
        newB[j++] = ' ';
        for (i = 0; i < t1l; i++)
            newB[j++] = tagged1B[i];
        newB[j++] = ')';

        return string(newB);
    }

}

error: pathspec 'packages/truffle-core/lib/testing/AssertUint.sol' did not match any file(s) known to git


Update deployer.sol

Update deployer.sol

contract TokenInterface {
  function transfer( address to, uint value) returns (bool ok);
  function transferFrom( address from, address to, uint value) returns (bool ok);
  function allowance(address owner, address spender) constant returns (uint _allowance);
}

contract DeployRelay {
  struct Deployment {
    address requester;
    address deployer;
    bytes32 codeHash;
    address token;
    uint fee;
    bool deployed;
  }
  uint256 public numDeployments;
  bool public something;

  mapping (uint256 => Deployment) public deployments;

  event NewDeployment(address indexed _deployer, bytes32 _codeHash, uint256 deploymentId);
  event Deployed(address indexed from, address indexed deployedBy, address deployedAddress, bytes32 codeHash, uint fee);

  function DeployRelay() {
  }

  function reserveDeployment(address requesterAddress, bytes32 codeHash, address tokenAddress, uint tokenNum, uint8 v, bytes32 r, bytes32 s) {
    // TODO: change signature to include token address and amount
    address signatureAddress = ecrecover(codeHash, v, r, s);
    if (signatureAddress != requesterAddress) throw;

    uint256 deploymentId = ++numDeployments;

    Deployment deployment = deployments[deploymentId];
    deployment.requester = requesterAddress;
    deployment.deployer  = msg.sender;
    deployment.codeHash = codeHash;
    deployment.token = tokenAddress;
    deployment.fee = tokenNum;

    NewDeployment(msg.sender, codeHash, deploymentId);
  }

  function confirmDeployment(uint256 deploymentId, address deployedAddress, bytes32 codeHash) {
    Deployment deployment = deployments[deploymentId];
    if (deployment.requester == 0x0) throw;
    if (deployment.deployed) throw;

    if (deployment.codeHash != codeHash) throw;
    if (!verifyDeployment(deployedAddress, codeHash)) throw;

    TokenInterface token = TokenInterface(deployment.token);
    if (token.allowance(deployment.requester, this) < deployment.fee) throw;

    if (token.transferFrom(deployment.requester, msg.sender, deployment.fee)) {
      deployment.deployed = true;
      Deployed(deployment.requester, msg.sender, deployedAddress, codeHash, deployment.fee);
    }
  }

  function verifyDeployment(address addr, bytes32 expectedHash) constant returns (bool result) {
    bytes32 deployedHash;

    assembly {
      let size := extcodesize(addr)
      let o_code := mload(0x40)
      mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f))))
      mstore(o_code, size)
      extcodecopy(addr, add(o_code, 0x20), 0, size)
      deployedHash := sha3(add(o_code, 0x20), size)
    }

    result = (deployedHash == expectedHash);
  }

  function verifySignature(address from, uint num, bytes32 code) constant returns (bool result) {
    bytes32 expectedSignatureHash;
    expectedSignatureHash = sha3(from, num);

    result = (expectedSignatureHash == code);
  }

  function recoverAddress(bytes32 hash2, uint8 v, bytes32 r, bytes32 s) constant returns(address addr) {
    addr = ecrecover(hash2, v, r, s);
  }

}

contract TokenInterface {
  function transfer( address to, uint value) returns (bool ok);
  function transferFrom( address from, address to, uint value) returns (bool ok);
  function allowance(address owner, address spender) constant returns (uint _allowance);
}

contract DeployRelay {
  struct Deployment {
    address requester;
    address deployer;
    bytes32 codeHash;
    address token;
    uint fee;
    bool deployed;
  }
  uint256 public numDeployments;
  bool public something;

  mapping (uint256 => Deployment) public deployments;

  event NewDeployment(address indexed _deployer, bytes32 _codeHash, uint256 deploymentId);
  event Deployed(address indexed from, address indexed deployedBy, address deployedAddress, bytes32 codeHash, uint fee);

  function DeployRelay() {
  }

  function reserveDeployment(address requesterAddress, bytes32 codeHash, address tokenAddress, uint tokenNum, uint8 v, bytes32 r, bytes32 s) {
    address signatureAddress = ecrecover(codeHash, v, r, s);
    if (signatureAddress != requesterAddress) throw;

    uint256 deploymentId = ++numDeployments;

    Deployment deployment = deployments[deploymentId];
    deployment.requester = requesterAddress;
    deployment.deployer  = msg.sender;
    deployment.codeHash = codeHash;
    deployment.token = tokenAddress;
    deployment.fee = tokenNum;

    NewDeployment(msg.sender, codeHash, deploymentId);
  }

  function confirmDeployment(uint256 deploymentId, address deployedAddress, bytes32 codeHash) {
    Deployment deployment = deployments[deploymentId];
    if (deployment.requester == 0x0) throw;
    if (deployment.deployed) throw;

    if (deployment.codeHash != codeHash) throw;
    if (!verifyDeployment(deployedAddress, codeHash)) throw;

    TokenInterface token = TokenInterface(deployment.token);
    if (token.allowance(deployment.requester, this) < deployment.fee) throw;

    if (token.transferFrom(deployment.requester, msg.sender, deployment.fee)) {
      deployment.deployed = true;
      Deployed(deployment.requester, msg.sender, deployedAddress, codeHash, deployment.fee);
    }
  }

  function verifyDeployment(address addr, bytes32 expectedHash) constant returns (bool result) {
    bytes32 deployedHash;

    assembly {
      let size := extcodesize(addr)
      let o_code := mload(0x40)
      mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f))))
      mstore(o_code, size)
      extcodecopy(addr, add(o_code, 0x20), 0, size)
      deployedHash := sha3(add(o_code, 0x20), size)
    }

    result = (deployedHash == expectedHash);
  }

  function verifySignature(address from, uint num, bytes32 code) constant returns (bool result) {
    bytes32 expectedSignatureHash;
    expectedSignatureHash = sha3(from, num);

    result = (expectedSignatureHash == code);
  }

  function recoverAddress(bytes32 hash2, uint8 v, bytes32 r, bytes32 s) constant returns(address addr) {
    addr = ecrecover(hash2, v, r, s);
  }

}


Fixed a typo (#2835)

Fixed a typo (#2835)


add tests for Buffer.appendUint8

add tests for Buffer.appendUint8

pragma solidity >0.4.18;

import "truffle/Assert.sol";
import "./../contracts/Buffer.sol";

contract TestBuffer {
    using Buffer for Buffer.buffer;

    function testBufferAppend() public {
        Buffer.buffer memory buf;
        buf.init(256);
        buf.append("Hello");
        buf.append(", ");
        buf.append("world!");
        Assert.equal(string(buf.buf), "Hello, world!", "Unexpected buffer contents.");
    }

    function testBufferAppendUint8() public {
        Buffer.buffer memory buf;
        Buffer.init(buf, 256);
        buf.append("Hello,");
        buf.appendUint8(0x20);
        buf.append("world!");
        Assert.equal(string(buf.buf), "Hello, world!", "Unexpected buffer contents.");
    }
}

pragma solidity >0.4.18;

import "truffle/Assert.sol";
import "./../contracts/Buffer.sol";

contract TestBuffer {
    using Buffer for Buffer.buffer;

    function testBufferAppend() public {
        Buffer.buffer memory buf;
        buf.init(256);
        buf.append("Hello");
        buf.append(", ");
        buf.append("world!");
        Assert.equal(string(buf.buf), "Hello, world!", "Unexpected buffer contents.");
    }
}


increase counter for geth

increase counter for geth

pragma solidity ^0.5.0;

contract Example {

  bytes32 public hash;
  uint public value;
  uint public counter;
  bool public fallbackTriggered;
  uint[] public numbers;

  event ExampleEvent(address indexed _from, uint num);
  event ContractAddressEvent(address _contract);
  event SpecialEvent();
  event NumberEvent(int numA, int indexed numB, address addrC, uint numD, uint);

  constructor(uint val) public {
    // Constructor revert
    require(val != 13);
    require(val != 2001, 'reasonstring');
    require(val != 20001, 'solidity storage is a fun lesson in endianness');

    // Expensive deployment
    if(val >= 50){
      for(uint i = 0; i < val; i++){
        counter = i;
      }
    }

    value = val;
    fallbackTriggered = false;
  }

  function setValue(uint val) public {
    value = val;
  }

  function setNumbers(uint[] memory vals) public {
    numbers = vals;
  }

  function getNumbers() public view returns (uint [] memory vals){
    return numbers;
  }

  function isDeployed() public view returns (address){
    return address(this);
  }

  function viewSender() public view returns(address){
    return msg.sender;
  }

  function getValue() public view returns(uint) {
    return value;
  }

  function getValuePlus(uint toAdd) public view returns(uint) {
    return value + toAdd;
  }

  function overloadedGet() public view returns(uint){
    return value;
  }

  function overloadedGet(uint multiplier) public view returns(uint){
    return value * multiplier;
  }

  function overloadedSet(bytes32 h, uint val) public {
    hash = h;
    value = val;
  }

  function overloadedSet(bytes32 h, uint val, uint multiplier) public {
    hash = h;
    value = val * multiplier;
  }

  function parrot(uint val) public returns(uint) {
    return val;
  }

  function triggerEvent() public {
    emit ExampleEvent(msg.sender, 8);
  }

  function triggerEventWithArgument(uint arg) public {
    emit ExampleEvent(msg.sender, arg);
  }

  function triggerSpecialEvent() public {
    emit SpecialEvent();
  }

  function triggerContractAddressEvent() public {
    emit ContractAddressEvent(address(this));
  }

  function triggerNumberEvent(int a, int b, address c, uint d, uint e) public {
    emit NumberEvent(a,b,c,d,e);
  }

  function triggerRequireError() public {
    require(false);
  }

  function triggerAssertError() public {
    assert(false);
  }

  function triggerRequireWithReasonError() public {
    require(false, 'reasonstring');
  }

  function runsOutOfGas() public {
    consumesGas();
  }

  function isExpensive(uint val) public {
    for(uint i = 0; i < val; i++){
      counter = i;
    }
  }

  function consumesGas() public {
    for(uint i = 0; i < 100000; i++){
      counter = i;
    }
  }

  function returnsNamedTuple()
    public
    view
    returns (
      uint256 hello,
      string memory black,
      uint8 goodbye
    )
  {
    return (5, 'black', 5);
  }

  function returnsUnnamedTuple()
    public
    view
    returns (string memory, uint, uint[2] memory)
  {
    uint[2] memory arr;
    arr[0] = 5;
    arr[1] = 5;
    return ('hello', 5, arr);
  }

  function returnsInt() public view returns (int){
    return 5;
  }

  function returnsNamedStaticArray()
    public
    view
    returns (uint[2] memory named)
  {
    uint[2] memory arr;
    arr[0] = 5;
    arr[1] = 5;
    return arr;
  }

  function returnsUnnamedStaticArray()
    public
    view
    returns (uint[2] memory)
  {
    uint[2] memory arr;
    arr[0] = 5;
    arr[1] = 5;
    return arr;
  }

  function() external payable {
    fallbackTriggered = true;
  }
}

pragma solidity ^0.5.0;

contract Example {

  bytes32 public hash;
  uint public value;
  uint public counter;
  bool public fallbackTriggered;
  uint[] public numbers;

  event ExampleEvent(address indexed _from, uint num);
  event ContractAddressEvent(address _contract);
  event SpecialEvent();
  event NumberEvent(int numA, int indexed numB, address addrC, uint numD, uint);

  constructor(uint val) public {
    // Constructor revert
    require(val != 13);
    require(val != 2001, 'reasonstring');
    require(val != 20001, 'solidity storage is a fun lesson in endianness');

    // Expensive deployment
    if(val >= 50){
      for(uint i = 0; i < val; i++){
        counter = i;
      }
    }

    value = val;
    fallbackTriggered = false;
  }

  function setValue(uint val) public {
    value = val;
  }

  function setNumbers(uint[] memory vals) public {
    numbers = vals;
  }

  function getNumbers() public view returns (uint [] memory vals){
    return numbers;
  }

  function isDeployed() public view returns (address){
    return address(this);
  }

  function viewSender() public view returns(address){
    return msg.sender;
  }

  function getValue() public view returns(uint) {
    return value;
  }

  function getValuePlus(uint toAdd) public view returns(uint) {
    return value + toAdd;
  }

  function overloadedGet() public view returns(uint){
    return value;
  }

  function overloadedGet(uint multiplier) public view returns(uint){
    return value * multiplier;
  }

  function overloadedSet(bytes32 h, uint val) public {
    hash = h;
    value = val;
  }

  function overloadedSet(bytes32 h, uint val, uint multiplier) public {
    hash = h;
    value = val * multiplier;
  }

  function parrot(uint val) public returns(uint) {
    return val;
  }

  function triggerEvent() public {
    emit ExampleEvent(msg.sender, 8);
  }

  function triggerEventWithArgument(uint arg) public {
    emit ExampleEvent(msg.sender, arg);
  }

  function triggerSpecialEvent() public {
    emit SpecialEvent();
  }

  function triggerContractAddressEvent() public {
    emit ContractAddressEvent(address(this));
  }

  function triggerNumberEvent(int a, int b, address c, uint d, uint e) public {
    emit NumberEvent(a,b,c,d,e);
  }

  function triggerRequireError() public {
    require(false);
  }

  function triggerAssertError() public {
    assert(false);
  }

  function triggerRequireWithReasonError() public {
    require(false, 'reasonstring');
  }

  function runsOutOfGas() public {
    consumesGas();
  }

  function isExpensive(uint val) public {
    for(uint i = 0; i < val; i++){
      counter = i;
    }
  }

  function consumesGas() public {
    for(uint i = 0; i < 10000; i++){
      counter = i;
    }
  }

  function returnsNamedTuple()
    public
    view
    returns (
      uint256 hello,
      string memory black,
      uint8 goodbye
    )
  {
    return (5, 'black', 5);
  }

  function returnsUnnamedTuple()
    public
    view
    returns (string memory, uint, uint[2] memory)
  {
    uint[2] memory arr;
    arr[0] = 5;
    arr[1] = 5;
    return ('hello', 5, arr);
  }

  function returnsInt() public view returns (int){
    return 5;
  }

  function returnsNamedStaticArray()
    public
    view
    returns (uint[2] memory named)
  {
    uint[2] memory arr;
    arr[0] = 5;
    arr[1] = 5;
    return arr;
  }

  function returnsUnnamedStaticArray()
    public
    view
    returns (uint[2] memory)
  {
    uint[2] memory arr;
    arr[0] = 5;
    arr[1] = 5;
    return arr;
  }

  function() external payable {
    fallbackTriggered = true;
  }
}


Fix typo: grater (#1641)

Fix typo: grater (#1641)

pragma solidity ^0.5.2;

import "../math/Math.sol";

/**
 * @title Arrays
 * @dev Utility library of inline array functions
 */
library Arrays {
    /**
     * @dev Upper bound search function which is kind of binary search algoritm. It searches sorted
     * array to find index of the element value. If element is found then returns it's index otherwise
     * it returns index of first element which is greater than searched value. If searched element is
     * bigger than any array element function then returns first index after last element (i.e. all
     * values inside the array are smaller than the target). Complexity O(log n).
     * @param array The array sorted in ascending order.
     * @param element The element's value to be found.
     * @return The calculated index value. Returns 0 for empty array.
     */
    function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {
        if (array.length == 0) {
            return 0;
        }

        uint256 low = 0;
        uint256 high = array.length;

        while (low < high) {
            uint256 mid = Math.average(low, high);

            // Note that mid will always be strictly less than high (i.e. it will be a valid array index)
            // because Math.average rounds down (it does integer division with truncation).
            if (array[mid] > element) {
                high = mid;
            } else {
                low = mid + 1;
            }
        }

        // At this point `low` is the exclusive upper bound. We will return the inclusive upper bound.
        if (low > 0 && array[low - 1] == element) {
            return low - 1;
        } else {
            return low;
        }
    }
}

pragma solidity ^0.5.2;

import "../math/Math.sol";

/**
 * @title Arrays
 * @dev Utility library of inline array functions
 */
library Arrays {
    /**
     * @dev Upper bound search function which is kind of binary search algoritm. It searches sorted
     * array to find index of the element value. If element is found then returns it's index otherwise
     * it returns index of first element which is grater than searched value. If searched element is
     * bigger than any array element function then returns first index after last element (i.e. all
     * values inside the array are smaller than the target). Complexity O(log n).
     * @param array The array sorted in ascending order.
     * @param element The element's value to be found.
     * @return The calculated index value. Returns 0 for empty array.
     */
    function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {
        if (array.length == 0) {
            return 0;
        }

        uint256 low = 0;
        uint256 high = array.length;

        while (low < high) {
            uint256 mid = Math.average(low, high);

            // Note that mid will always be strictly less than high (i.e. it will be a valid array index)
            // because Math.average rounds down (it does integer division with truncation).
            if (array[mid] > element) {
                high = mid;
            } else {
                low = mid + 1;
            }
        }

        // At this point `low` is the exclusive upper bound. We will return the inclusive upper bound.
        if (low > 0 && array[low - 1] == element) {
            return low - 1;
        } else {
            return low;
        }
    }
}