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:

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

Support Interface Function

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

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

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:

'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);
}

Last updated