contract ERC721SaleNonceHolder is OwnableOperatorRole {
    /// @notice token nonces
    mapping(bytes32 => uint256) public nonces;
    /// @notice Previous nonce manager contract address.
    IERC721Sale public previous;

    /// @notice The contract constructor.
    /// @param _previous - The value of the previous nonce manager contract.
    constructor(IERC721Sale _previous) public {
        previous = _previous;
    }

    /// @notice Get nonce value for the token.
    /// @param token - Token's contract address.
    /// @param tokenId - Token id.
    /// @return The nonce value.
    function getNonce(IERC721 token, uint256 tokenId) view public returns (uint256) {
        uint256 newNonce = nonces[getPositionKey(token, tokenId)];
        if (newNonce != 0) {
            return newNonce;
        }
        if (address(previous) == address(0x0)) {
            return 0;
        }
        return previous.getNonce(token, tokenId);
    }

    /// @notice Sets new nonce value for the token. Can only be called by the operator.
    /// @param token - Token's contract address.
    /// @param tokenId - Token id.
    /// @param nonce - The new value for the nonce.
    function setNonce(IERC721 token, uint256 tokenId, uint256 nonce) public onlyOperator {
        nonces[getPositionKey(token, tokenId)] = nonce;
    }

    /// @notice Encode the token info to use as a mapping key.
    /// @param token - Token's contract address.
    /// @param tokenId - Token id.
    /// @return Encoded key for the token.
    function getPositionKey(IERC721 token, uint256 tokenId) pure public returns (bytes32) {
        return keccak256(abi.encodePacked(token, tokenId));
    }
}
/// @title ERC721SaleNonceHolder
/// @notice The contract manages nonce values for the sales.
function getNonce(IERC721 token, uint256 tokenId) view public returns (uint256) {
    uint256 newNonce = nonces[getPositionKey(token, tokenId)];
    if (newNonce != 0) {
        return newNonce;
    }
    if (address(previous) == address(0x0)) {
        return 0;
    }
    return previous.getNonce(token, tokenId);
}

/// @notice Get nonce value for the token.
/// @param token - Token's contract address.
/// @param tokenId - Token id.
/// @return The nonce value.