> For the complete documentation index, see [llms.txt](https://docs.zetrix.com/en/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.zetrix.com/en/developer-resources/smart-contract/ztp-standard/ztp-165.md).

# ZTP-165

## Introduction

### What is the Protocol ZTP-165

`ZTP165` provides a protocol standard similar to `ZEP165` and `ERC165` for detecting smart contract interfaces on the `ZTP` blockchain. It specifies how smart contracts can declare and validate their supported interfaces, ensuring compatibility and ease of integration between different smart contracts.

The `ZTP165` standard introduces a way for contracts on the ZTP blockchain to explicitly declare the interfaces they support. This allows other contracts to interact seamlessly with them, by querying supported interfaces and adjusting their functionality accordingly.

### **Protocol Overview**

#### **Interface Function**

Contracts implementing `ZTP165` must include the following function:

```javascript
const IZEP165 = {
  supportsInterface: function() {
    return this;
  }
};
```

#### **Support Interface Function**

```javascript
this.supportsInterface = function(interfaceId) {
    let iface1 = Utils.sha256(JSON.stringify(IZEP165), 1);
    let iface2 = Utils.sha256(JSON.stringify(IOptimismMintableZTP20), 1);
    return interfaceId === iface1 || interfaceId === iface2;
};
```

#### **Support Interface Validation in Init Function**

```javascript
function init(input_str) {
  let input = JSON.parse(input_str);

  Utils.assert(implementsInterface(OptimismMintableZTP20, IOptimismMintableZTP20), 'OptimismMintableZTP20 does not implement IOptimismMintableZTP20');
  Utils.assert(implementsInterface(OptimismMintableZTP20, IZEP165), 'OptimismMintableZTP20 does not implement IZEP165');

  return true;
}
```

#### **Usage**

```javascript
this.isOptimismMintableZTP20 = function (token) {
    let interfaceId = utils.sha256(JSON.stringify(interfaceId), 1);
    let queryInput = {
        'method': 'supportsInterface',
        'params': {
            'interfaceId' : interfaceId
        }
    };

    let ret = Chain.contractQuery(token, JSON.stringify(queryInput));
    utils.assert(ret !== false, 'Contract does not exist');

    if (ret.err === null && ret.error) {
        return false;
    }

    return JSON.parse(ret.result).data;
    
```

### Full ZTP-165 contract example:

```javascript
'use strict';

const IOptimismMintableZTP20 = {
  remoteToken: function() {
    return this;
  },
  bridge: function() {
    return this;
  },
  mint: function() {
    return this;
  },
  burn: function() {
    return this;
  }
};

const IZEP165 = {
  supportsInterface: function() {
    return this;
  }
};

function implementsInterface(obj, interfaceObj) {
  let keys = Object.keys(interfaceObj);
  let i;
  for (i = 0; i < keys.length; i += 1) {
    if (!obj.hasOwnProperty(keys[i]) || typeof obj[keys[i]] !== "function") {
      return false;
    }
  }
  return true;
}

const OptimismMintableZTP20Class = function() {
  this.remoteToken = function() {
    Chain.tlog('remoteToken1');
  };

  this.bridge = function() {
    Chain.tlog('bridge1');
  };

  this.mint = function() {
    Chain.tlog('mint1');
  };

  this.burn = function() {
    Chain.tlog('burn1');
  };

  this.supportsInterface = function(interfaceId) {
    let iface1 = Utils.sha256(JSON.stringify(IZEP165), 1);
    let iface2 = Utils.sha256(JSON.stringify(IOptimismMintableZTP20), 1);
    return interfaceId === iface1 || interfaceId === iface2;
  };
};

const OptimismMintableZTP20 = new OptimismMintableZTP20Class();

function init(input_str) {
  let input = JSON.parse(input_str);

  Utils.assert(implementsInterface(OptimismMintableZTP20, IOptimismMintableZTP20), 'OptimismMintableZTP20 does not implement IOptimismMintableZTP20');
  Utils.assert(implementsInterface(OptimismMintableZTP20, IZEP165), 'OptimismMintableZTP20 does not implement IZIP165');

  return true;
}

function main(input_str) {
  let input = JSON.parse(input_str);
  let params = input.params;

  let result = {};
  if (input.method === 'mint') {
    OptimismMintableZTP20Class.mint();
  } else {
    throw 'Unknown operating: ' + input.method + '.';
  }
  return JSON.stringify(result);

}

function query(input_str) {
  let input = JSON.parse(input_str);
  let params = input.params;

  let result = {};
  if (input.method === 'supportsInterface') {
    result.data = OptimismMintableZTP20.supportsInterface(params.interfaceId);
  } else {
    throw 'Unknown operating: ' + input.method + '.';
  }

  return JSON.stringify(result);
}
```
