<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jonas Pauli</title>
    <description>The latest articles on DEV Community by Jonas Pauli (@jonas089).</description>
    <link>https://dev.to/jonas089</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F951465%2F30744d5d-d724-4e35-9308-8e7e756f0e47.jpeg</url>
      <title>DEV Community: Jonas Pauli</title>
      <link>https://dev.to/jonas089</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jonas089"/>
    <language>en</language>
    <item>
      <title>Casper CEP-78 Enhanced NFT Standard</title>
      <dc:creator>Jonas Pauli</dc:creator>
      <pubDate>Fri, 21 Oct 2022 18:41:32 +0000</pubDate>
      <link>https://dev.to/casperblockchain/casper-cep-78-enhanced-nft-standard-4ibe</link>
      <guid>https://dev.to/casperblockchain/casper-cep-78-enhanced-nft-standard-4ibe</guid>
      <description>&lt;p&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;br&gt;
Most people only have experience with NFTs in the form of JPEGs and art collections, despite the wide variety of use-cases beyond this implementation. The new enhanced NFT standard on Casper is designed to support more than ordinary NFT collections and even allows for developers to associate real world objects with digital representations in the form of NFTs on the blockchain.&lt;/p&gt;

&lt;p&gt;There are now three different "metadata_types":&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Physical&lt;/strong&gt;: The NFT represents a real-world physical item e.g a house.&lt;br&gt;
&lt;strong&gt;Digital&lt;/strong&gt;: The NFT represents a digital item, e.g a unique JPEG or a digital art.&lt;br&gt;
&lt;strong&gt;Virtual&lt;/strong&gt;: The NFT is the virtual representation of a physical notion, e.g a patent or copyright.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This article introduces the &lt;a href="https://github.com/casper-ecosystem/cep-78-enhanced-nft"&gt;Casper Cep-78 token standard&lt;/a&gt;, which is an upgrade of the deprecated Cep-47 standard. Essentially, the Cep-78 token standard is more flexible and supports “modalities”.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Casper NFT Visualizer&lt;/strong&gt;&lt;br&gt;
Thanks to the &lt;a href="https://github.com/casper-ecosystem/cep-78-enhanced-nft"&gt;casper-signer&lt;/a&gt; and the &lt;a href="https://github.com/casper-ecosystem/casper-js-sdk"&gt;casper-javascript-sdk&lt;/a&gt;, building Dapps on Casper is achievable. To showcase this, I built a “Casper-Sandbox” demo application using React that is open source and can be found &lt;a href="https://github.com/jonas089/casper-nft-sandbox-demo"&gt;here&lt;/a&gt;. If you want to install and test the react app follow the setup guide. You will need &lt;a href="https://reactjs.org/docs/getting-started.html"&gt;React&lt;/a&gt; and &lt;a href="https://www.digitalocean.com/community/tutorials/how-to-install-node-js-on-ubuntu-20-04"&gt;Node.js&lt;/a&gt; to run the app.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pQ7l3G6y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y35j7p358gx3ixzv21og.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pQ7l3G6y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y35j7p358gx3ixzv21og.png" alt="example account on NFT Sandbox" width="720" height="376"&gt;&lt;/a&gt;&lt;br&gt;
The “Casper-Sandbox” is an open-source NFT visualizer built to demonstrate some of the capabilities of the Casper Blockchain and the CEP-78 Standard. The app is still under development but already supports minting of “digital” NFTs. The &lt;a href="https://github.com/jonas089/casper-nft-sandbox-demo/blob/master/README.md"&gt;readme&lt;/a&gt; includes the latest documentation for the project.&lt;br&gt;
&lt;strong&gt;Metadata&lt;/strong&gt;&lt;br&gt;
The structure of an NFTs metadata is defined by a json schema. Cep-78 supports both standardized and custom json schemes. Standardized schemes are easier to integrate, whilst custom schemes can be individualized to suit a projects needs best.&lt;br&gt;
&lt;em&gt;An example for a standardized json schema (CEP78):&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "name": "Example NFT",
  "token_uri": "https://SOME_BACKEND/id",
  "checksum":
"SOME_CHECKSUM"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example the webserver at "token_uri" should return json data containing all relevant information regarding the NFT, such as a url to the image/jpg file, name and description.&lt;/p&gt;

&lt;p&gt;Alternatively, one could define a custom metadata schema to store binary data instead of a weblink as the NFTs metadata.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;An example of custom metadata:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
   "properties":{
      "nft_name":{
         "name":"some_name",
         "description":"some_description",
         "required":true
      },
      "nft_binary_data":{
         "name":"some_binary_data",
         "description":"some_description",
         "required":true
      },
   }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;_More examples can be found in the &lt;a href="https://github.com/casper-ecosystem/cep-78-enhanced-nft/blob/dev/README.md"&gt;readme&lt;/a&gt; of the enhanced NFT standard.&lt;br&gt;
_&lt;br&gt;
&lt;strong&gt;Deploy the Contract&lt;/strong&gt;&lt;br&gt;
In the following, I will explain how to deploy the enhanced NFT standard on Ubuntu.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Requirements:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;**Dependencies**:
- libssl-dev
- curl
- cmake
- pkg-config
$ sudo apt install libssl-dev curl cmake pkg-config
Setup:
1. install Rust and default to nightly toolchain:
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
$ source $HOME/.cargo/env
$ rustup toolchain install nightly
$ rustup default nightly
2. install the casper-client
$ cargo install casper-client
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next step is to compile the Rust smart contract to WebAssembly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;casper@jonas:~/Desktop/cep-78-enhanced-nft-dev$ make prepare
casper@jonas:~/Desktop/cep-78-enhanced-nft-dev$ make build-contract
the compiled contract.wasm will be in ./contract/target/wasm32-unknown-unknown/release
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Deploy the compiled contract.wasm to casper testnet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ casper-client put-deploy --node-address &amp;lt;NODE_ADDRESS&amp;gt; --chain-name casper-test --secret-key &amp;lt;PATH_TO_SECRET_KEY&amp;gt; --payment-amount &amp;lt;GAS_FEE_IN_MOTE&amp;gt; --session-path &amp;lt;PATH_TO_contract.wasm&amp;gt; --session-arg &amp;lt;see below&amp;gt;,
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Session Arguments:&lt;/strong&gt;&lt;br&gt;
A list of mandatory session arguments for an NFT contract on Casper:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"collection_name": The name of the NFT collection, passed in as a String. This parameter is required and cannot be changed post installation.&lt;/li&gt;
&lt;li&gt;"collection_symbol": The symbol representing a given NFT collection, passed in as a String. This parameter is required and cannot be changed post installation.&lt;/li&gt;
&lt;li&gt;"total_token_supply": The total number of NFTs that a specific instance of a contract will mint passed in as a U64 value. This parameter is required and cannot be changed post installation.&lt;/li&gt;
&lt;li&gt;"ownership_mode": The OwnershipMode modality that dictates the ownership behavior of the NFT contract. This argument is passed in as a u8 value and is required at the time of installation.&lt;/li&gt;
&lt;li&gt;"nft_kind": The NFTKind modality that specifies the off-chain items represented by the on-chain NFT data. This argument is passed in as a u8 value and is required at the time of installation.&lt;/li&gt;
&lt;li&gt;"json_schema": The JSON schema for the NFT tokens that will be minted by the NFT contract passed in as a String. This parameter is required if the metadata kind is set to CustomValidated(4) and cannot be changed post installation.&lt;/li&gt;
&lt;li&gt;"nft_metadata_kind": The metadata schema for the NFTs to be minted by the NFT contract. This argument is passed in as a u8 value and is required at the time of installation.&lt;/li&gt;
&lt;li&gt;"identifier_mode": The NFTIdentifierMode modality dictates the primary identifier for NFTs minted by the contract. This argument is passed in as a u8 value and is required at the time of installation.&lt;/li&gt;
&lt;li&gt;"metadata_mutability": The MetadataMutability modality dictates whether the metadata of minted NFTs can be updated. This argument is passed in as a u8 value and is required at the time of installation.
&lt;a href="https://github.com/casper-ecosystem/cep-78-enhanced-nft/blob/dev/README.md"&gt;More&lt;/a&gt; on session args
&lt;strong&gt;Mint an NFT&lt;/strong&gt;
Before we can mint an NFT using our installed contract, we have to find the "contract_hash"of our deploy.
In order to accomplish this, we will have to query the "state-root-hash" after our deploy has been successfully processed, use that "state-root-hash" to query our account and copy the "contract_hash" associated with the "contract_name". ( which in this case will be "nft_contract", as specified in &lt;a href="https://github.com/casper-ecosystem/cep-78-enhanced-nft/blob/dev/contract/src/constants.rs"&gt;constants.rs&lt;/a&gt;)
&lt;em&gt;Query your account:&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ casper-client get-state-root-hash &amp;lt;node-address&amp;gt;
-&amp;gt; outputs "state-root-hash"
$ casper-client get-account-state --node-address&amp;lt;NODE_ADDRESS&amp;gt; --state-root-hash &amp;lt;STATE_ROOT_HASH&amp;gt; --key &amp;lt;account-hash-YOUR_ACCOUNT_HASH&amp;gt;
-&amp;gt; find "contract_hash" of deploy named "nft_contract" in output and copy it. 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;em&gt;Use the "contract_hash"of the deploy to call the mint() and deploy your first NFT to the Casper Blockchain:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A copy of the command I used to mint a Cep-78 digital NFT on Casper, using the standard metadata schema and dummy metadata from the README:
$ casper-client put-deploy \
--node-address http://136.243.187.84:7777 \
--chain-name casper-test \
--secret-key ./private.pem \
--payment-amount 1000000000 \
--session-hash hash-b4b78992e0324be09f174637c3dda2d29cc5c21c44430b72a0943d3ba6d2c827 \
--session-entry-point mint \
--session-arg "token_owner:key='account-hash-5a54f173e71d3c219940dcb9dfec222b024cd81aa7e0672de59ba5fab296448b'" \
--session-arg "token_meta_data:string='{\"name\":\"John Doe\",\"token_uri\":\"https://www.barfoo.cong\",\"checksum\":\"940bffb3f2bba35f84313aa26da09ece3ad47045c6a1292c2bbd2df4ab1a55fc\"}'"
-&amp;gt; outputs a deploy hash.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Get a List of all owned NFTs by Account&lt;/strong&gt;&lt;br&gt;
In order to access the Metadata of an NFT, it is necessary to know which NFTs are owned by a given account. The Cep-78 contract’s named_keys store contain a dictionary named “owned_tokens”.&lt;/p&gt;

&lt;p&gt;Find the Ids or Hashs of NFTs owned by your account. Whether your NFT is identified by a hash identifier or numerical Id depends on the modalityNFTIdentifierModethat defaults to “Ordinal” (numerical instead of hash):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A copy of the command I used to query the NFTs owned by my Account:
$ casper-client get-dictionary-item \
-n http://136.243.187.84:7777 \
-s 256d0445121f1144a09394c739c9baf82b5624b66dced181a0c1c8b8e936652b \
--account-hash hash-b4b78992e0324be09f174637c3dda2d29cc5c21c44430b72a0943d3ba6d2c827 \
--dictionary-name owned_tokens \
--dictionary-item-key 5a54f173e71d3c219940dcb9dfec222b024cd81aa7e0672de59ba5fab296448b
where --dictionary-item-key is set to my account-hash and -s is a new state-root-hash.
A copy of the output:
{
  "id": 6249115604543280689,
  "jsonrpc": "2.0",
  "result": {
    "api_version": "1.4.6",
    "dictionary_key": "dictionary-6bded5cf061dd95463e0064996f24cb88d19a6a7b24962a1347a5392356a35a0",
    "merkle_proof": "[38054 hex chars]",
    "stored_value": {
      "CLValue": {
        "bytes": "[280 hex chars]",
        "cl_type": {
          "List": "String"
        },
        "parsed": [
          "8bc73bf6cfdb48d0e88f16e0c02d5adff6c60a61a4b6bd65349d75fcb7b500d8",
          "0e557acd2b5a43a91c23c2f0e01687cc8a5342e105be22777b7bf97daf757c4f"
        ]
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The parsed value is a list of hash identifiers representing NFTs owned by the account:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"8bc73bf6cfdb48d0e88f16e0c02d5adff6c60a61a4b6bd65349d75fcb7b500d8",
          "0e557acd2b5a43a91c23c2f0e01687cc8a5342e105be22777b7bf97daf757c4f"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Read NFT Metadata&lt;/strong&gt;&lt;br&gt;
The metadata that is passed as an argument when minting an NFT using CEP-78 is saved in a hashmap on the blockchain, where the key is the hash or numeric identifier, depending on theidentifier_mode modality. The name of the dictionary depends on the metadata_kind modality.&lt;br&gt;
&lt;em&gt;The NFT metadata can be found in the related dictionary:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. "metadata_custom_validated"
2. "metadata_cep78"
3. "metadata_nft721"
4. "metadata_raw"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  const client = await new CasperClient(node_addr);
  var product_contract = new Contracts.Contract(client);
  product_contract.setContractHash(cep78_contract_hash);
  const list = [YOUR_NFT_HASH_IDs];
  let meta = [];
  for (item in list) {
    console.log("Item is: ", list[item].toString());
    await product_contract.queryContractDictionary(
      "metadata_custom_validated",
      list[item]
    ).then(response =&amp;gt; {
      meta.push(response.data);
    }).catch(error =&amp;gt; {
      console.log(error);
    })
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;This example shows how a javascript application can query a deployed cep-78 instance with custom validated metadata as metadata_kind.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Youtube Workshop&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Learn to configure and install the CEP-78 smart contract &lt;a href="https://www.youtube.com/watch?v=29eGzDn4HmM&amp;amp;list=PLq1atlGCXMqMgoMPKvMiA219LQXA_iPEI&amp;amp;index=2"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Learn to use the Sandbox application &lt;a href="https://www.youtube.com/watch?v=9Ybp3zZvfx4&amp;amp;list=PLq1atlGCXMqMgoMPKvMiA219LQXA_iPEI&amp;amp;index=2"&gt;here&lt;/a&gt;. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;br&gt;
Minting NFTs on Casper is a straight forward process and the enhanced Token standard is a major improvement over the &lt;a href="https://github.com/casper-ecosystem/casper-nft-cep47"&gt;CEP47 Token standard&lt;/a&gt;. It’s a more flexible and future proof implementation, setting a metadata standard which allows for the integration of Casper NFTs in both on- and off-chain applications.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Tip: When passing metadata or json schemes using the casper-client, the json strings need to be escaped. When deploying a Cep-78 instance, I use &lt;a href="https://jsontostring.com/"&gt;this tool&lt;/a&gt; to escape my json schema.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>nft</category>
      <category>blockchain</category>
      <category>opensource</category>
      <category>web3</category>
    </item>
    <item>
      <title>a16z "Can't be Evil" licenses - a practical guide</title>
      <dc:creator>Jonas Pauli</dc:creator>
      <pubDate>Fri, 21 Oct 2022 18:19:22 +0000</pubDate>
      <link>https://dev.to/casperblockchain/a16z-licenses-a-practical-guide-3p17</link>
      <guid>https://dev.to/casperblockchain/a16z-licenses-a-practical-guide-3p17</guid>
      <description>&lt;p&gt;&lt;em&gt;This guide provides detailed documentation on how to install and use a16z “Can’t be Evil” licenses on Casper.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;br&gt;
There are many uncertainties regarding copyright and ownership in the NFT space. Users purchase tokenized avatars and artworks, whilst unaware of the legal situation. Resarachers at the venture capital firm “a16z” have made an effort to solve these issues with their “Can’t be evil” NFT licenses. According to a16z, NFTs need to be licensed, as owning the token Id on the blockchain may not be enough to legally reproduce or display an artwork.&lt;/p&gt;

&lt;p&gt;The a16z “Can’t be evil” NFT licenses include &lt;a href="https://www.plagiarismtoday.com/wp-content/uploads/2022/09/CBE_LicenseChart_FA-1536x864-1-700x394.webp"&gt;sets of rules&lt;/a&gt; regarding ownership and copyright. Rights and permissions granted through the license only apply to the owner of the NFT. Licenses make it easier to clearly communicate which rights are or are not granted to the customer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://a16zcrypto.com/introducing-nft-licenses/"&gt;Read more&lt;/a&gt; on a16z “Can’t be Evil” licenses.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Smart Contracts&lt;/strong&gt;&lt;br&gt;
a16z has already published their licenses on Arweave. Additionally, a16z released this Solidity smart contract:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
// a16z Contracts v0.0.1 (CantBeEvil.sol)
pragma solidity ^0.8.13;

import "@openzeppelin/contracts/utils/Strings.sol";
import "@openzeppelin/contracts/utils/introspection/ERC165.sol";
import "./ICantBeEvil.sol";

enum LicenseVersion {
    CBE_CC0,
    CBE_ECR,
    CBE_NECR,
    CBE_NECR_HS,
    CBE_PR,
    CBE_PR_HS
}

contract CantBeEvil is ERC165, ICantBeEvil {
    using Strings for uint;
    string internal constant _BASE_LICENSE_URI = "ar://_D9kN1WrNWbCq55BSAGRbTB4bS3v8QAPTYmBThSbX3A/";
    LicenseVersion public licenseVersion; // return string
    constructor(LicenseVersion _licenseVersion) {
        licenseVersion = _licenseVersion;
    }

    function getLicenseURI() public view returns (string memory) {
        return string.concat(_BASE_LICENSE_URI, uint(licenseVersion).toString());
    }

    function getLicenseName() public view returns (string memory) {
        return _getLicenseVersionKeyByValue(licenseVersion);
    }

    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165) returns (bool) {
        return
            interfaceId == type(ICantBeEvil).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    function _getLicenseVersionKeyByValue(LicenseVersion _licenseVersion) internal pure returns (string memory) {
        require(uint8(_licenseVersion) &amp;lt;= 6);
        if (LicenseVersion.CBE_CC0 == _licenseVersion) return "CBE_CC0";
        if (LicenseVersion.CBE_ECR == _licenseVersion) return "CBE_ECR";
        if (LicenseVersion.CBE_NECR == _licenseVersion) return "CBE_NECR";
        if (LicenseVersion.CBE_NECR_HS == _licenseVersion) return "CBE_NECR_HS";
        if (LicenseVersion.CBE_PR == _licenseVersion) return "CBE_PR";
        else return "CBE_PR_HS";
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order to support “Can’t be Evil” licenses in Casper smart contracts, the above contract has been translated to Rust:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#![no_std]
#![no_main]

#[cfg(not(target_arch = "wasm32"))]
compile_error!("target arch should be wasm32: compile with '--target wasm32-unknown-unknown'");
extern crate alloc;

use alloc::{
    string::{String, ToString},
    vec,
};

use casper_types::{
    contracts::NamedKeys, runtime_args, ApiError, CLType, CLValue, ContractHash, EntryPoint,
    EntryPointAccess, EntryPointType, EntryPoints, Parameter, RuntimeArgs, URef,
};

use casper_contract::{
    contract_api::{
        runtime,
        storage::{self},
    },
    unwrap_or_revert::UnwrapOrRevert,
};

#[repr(u16)]
enum A16ZError {
    InvalidLicenseVersion = 0,
}
impl From&amp;lt;A16ZError&amp;gt; for ApiError {
    fn from(e: A16ZError) -&amp;gt; Self {
        ApiError::User(e as u16)
    }
}

const _BASE_LICENSE_URI: &amp;amp;str = "ar://_D9kN1WrNWbCq55BSAGRbTB4bS3v8QAPTYmBThSbX3A/";
const CONTRACT_PACKAGE_HASH: &amp;amp;str = "a16z-contract-hash";
const CONTRACT_HASH_KEY_NAME: &amp;amp;str = "contract_hash";

#[no_mangle]
pub extern "C" fn getLicenseURI() {
    let licenseVersion: u64 = runtime::get_named_arg("_licenseVersion");
    match licenseVersion {
        0 =&amp;gt; licenseVersion,
        1 =&amp;gt; licenseVersion,
        2 =&amp;gt; licenseVersion,
        3 =&amp;gt; licenseVersion,
        4 =&amp;gt; licenseVersion,
        5 =&amp;gt; licenseVersion,
        _ =&amp;gt; runtime::revert(A16ZError::InvalidLicenseVersion),
    };

    let licenseURI: String = String::from(_BASE_LICENSE_URI) + &amp;amp;licenseVersion.to_string();
    let licenseUriCLValue: CLValue = CLValue::from_t(licenseURI).unwrap_or_revert();
    runtime::ret(licenseUriCLValue);
}

#[no_mangle]
pub extern "C" fn getLicenseName() {
    let licenseVersion: u64 = runtime::get_named_arg("_licenseVersion");
    match licenseVersion {
        0 =&amp;gt; runtime::ret(CLValue::from_t(String::from("CBE_CC0")).unwrap_or_revert()),
        1 =&amp;gt; runtime::ret(CLValue::from_t(String::from("CBE_ECR")).unwrap_or_revert()),
        2 =&amp;gt; runtime::ret(CLValue::from_t(String::from("CBE_NECR")).unwrap_or_revert()),
        3 =&amp;gt; runtime::ret(CLValue::from_t(String::from("CBE_NECR_HS")).unwrap_or_revert()),
        4 =&amp;gt; runtime::ret(CLValue::from_t(String::from("CBE_PR")).unwrap_or_revert()),
        5 =&amp;gt; runtime::ret(CLValue::from_t(String::from("CBE_PR_HS")).unwrap_or_revert()),
        _ =&amp;gt; runtime::revert(A16ZError::InvalidLicenseVersion),
    };
}

#[no_mangle]
pub extern "C" fn call() {
    let entry_points = {
        let mut entry_points = EntryPoints::new();
        let getLicenseURI = EntryPoint::new(
            "getLicenseURI",
            vec![Parameter::new("_licenseVersion", CLType::U64)],
            CLType::String,
            EntryPointAccess::Public,
            EntryPointType::Contract,
        );
        let getLicenseName = EntryPoint::new(
            "getLicenseName",
            vec![Parameter::new("_licenseVersion", CLType::U64)],
            CLType::String,
            EntryPointAccess::Public,
            EntryPointType::Contract,
        );
        entry_points.add_entry_point(getLicenseURI);
        entry_points.add_entry_point(getLicenseName);
        entry_points
    };
    let named_keys = {
        let mut named_keys = NamedKeys::new();
        named_keys
    };
    storage::new_contract(
        entry_points,
        Some(named_keys),
        Some(String::from(CONTRACT_PACKAGE_HASH)),
        Some(String::from(CONTRACT_HASH_KEY_NAME)),
    );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;a16z license URIs ( for NFT-developers )&lt;/strong&gt;&lt;br&gt;
Platforms like Opensea comply with the &lt;a href="https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md"&gt;eip-721 metadata standard&lt;/a&gt;. Learn more &lt;a href="https://docs.opensea.io/docs/metadata-standards"&gt;here&lt;/a&gt; .&lt;/p&gt;

&lt;p&gt;Where the “Can’t be Evil” license URI is stored depends on which metadata schema or standard makes the most sense for a project to follow. Most NFT platforms on Casper will likely comply with the &lt;a href="https://github.com/casper-ecosystem/cep-78-enhanced-nft/blob/dev/README.md"&gt;CEP-78 metadata standard&lt;/a&gt;. As a metadata URI is a link to a server that returns JSON data, it makes the most sense to include the license in the data returned by the backend.&lt;/p&gt;

&lt;p&gt;Important: The NFT metadata URI is not the same as the License URI. The License URI is an arweave link to a .doc file, whilst the NFT URI fetches JSON, such as the name, description and image URL from a backend.&lt;/p&gt;

&lt;p&gt;As a16z licenses are quite novel, there is not yet a standardized schema to follow. Depending on the legal situation, it might be appropriate to include a license URI or URL in an NFT’s “description”. Casper supports custom metadata schemata, therefore the license URI could be included in the NFT metadata on mint. However, when using custom metadata, other platforms may not be able to integrate the NFTs without manually adding support for a collection / metadata schema.&lt;/p&gt;

&lt;p&gt;Read more about metadata on Casper &lt;a href="https://github.com/casper-ecosystem/cep-78-enhanced-nft/blob/dev/README.md"&gt;here&lt;/a&gt;.&lt;br&gt;
&lt;strong&gt;Casper a16z Installation guide&lt;/strong&gt;&lt;br&gt;
Follow the steps below to compile, and deploy the a16z “Can’t be Evil” contract on casper.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clone the git repository
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chef@jonas:~/Desktop$ git clone https://github.com/jonas089/a16z-casper
chef@jonas:~/Desktop$ cd a16z-casper/contract
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Compile the a16z contract
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chef@jonas:~/Desktop/a16z-casper/contract$ cargo build --release --target wasm32-unknown-unknown
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;=&amp;gt; compiles contract.wasm to ./target/wasm32-unknown-unknown/release&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Mm5EopQh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/86gvw7wq3rqn2yqb0djz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Mm5EopQh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/86gvw7wq3rqn2yqb0djz.png" alt="project structure" width="671" height="348"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deploy the a16z contract ( to Casper Testnet )
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chef@jonas:~/Desktop/a16z-casper/contract/target/wasm32-unknown-unknown/release$ casper-client put-deploy --node-address NODE_ADDRESS --secret-key PRIVATE_KEY_PATH --payment-amount GAS --chain-name casper-test --session-path contract.wasm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Example:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zxCTteJu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cob8zwuvigiq8iua57vd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zxCTteJu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cob8zwuvigiq8iua57vd.png" alt="explorer snapshot" width="565" height="340"&gt;&lt;/a&gt;&lt;br&gt;
Verify the deploy was successful using the &lt;a href="https://testnet.cspr.live/"&gt;explorer&lt;/a&gt;:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---n20-SqG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0r69igb2ht2thg79c7wh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---n20-SqG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0r69igb2ht2thg79c7wh.png" alt="Image description" width="720" height="397"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Query the contract hash of the installed contract
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chef@jonas:~/Desktop$ casper-client get-state-root-hash -n NODE_ADDRESS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;=&amp;gt; outputs a state root hash.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chef@jonas:~/Desktop$ casper-client query-global-state -n NODE_ADDRESS -s STATE_ROOT_HASH --key YOUR_ACCOUNT_HASH
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;=&amp;gt; outputs account information, including the contract hash.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Call the a16z Contract to get a License URI&lt;/strong&gt;&lt;br&gt;
Query the URI for a “Can’t be Evil” license by calling the “getLicenseURI” endpoint, passing the a16z contract hash and the license version as runtime arguments:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
#[no_mangle]
pub extern "C" fn simulateThirdParty(){
    let _licenseVersion:u64 = 0;
    let contract_hash:ContractHash = runtime::get_named_arg("CONTRACT_HASH");
    let licenseURI:String = runtime::call_contract::&amp;lt;String&amp;gt;(
        contract_hash,
        "getLicenseURI",
        runtime_args!{
            "_licenseVersion" =&amp;gt; _licenseVersion
        }
    );
    // do something with licenseURI
}
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;runtime::call_contract&lt;/em&gt; takes in the contract hashto call the “getLicenseURI” entry point of the a16z contract.&lt;br&gt;
The “getLicenseURI”entry point will return a URI for the “CBE_CC0” license ( licenseVersion 0 ).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;list of all a16z license versions&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0 =&amp;gt; CBE_CC0
1 =&amp;gt; CBE_ECR
2 =&amp;gt; CBE_NECR
3 =&amp;gt; CBE_NECR_HS
4 =&amp;gt; CBE_PR
5 =&amp;gt; CBE_PR_HS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;br&gt;
Thanks to a16z, licensing NFTs is simple and straightforward. Both a Solidity and Rust smart contract is available today and users can start using “Can’t be Evil” licenses on various blockchains now. Licenses are relevant, as the current legal situation regarding NFT copyrights is unclear and users should have an interest in knowing which data they actually own and to what extent they can use it.&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>opensource</category>
      <category>crypto</category>
      <category>nft</category>
    </item>
  </channel>
</rss>
