Skip to main content

Non-Fungible Token Can't Be Evil Licensing (TIP-4.5)

Requires: TIP-4.1 Requires: TIP-6.1


The standard adds the support of Can't Be Evil NFT licenses introduced by Andreessen.Horowitz.


The purpose of this standard is to provide an on-chain representation of the CantBeEvil license.

The CantBeEvil license is made available as a contract that can be inherited by any other contract.

There are six variants of the CantBeEvil license:

The text of the Licenses is made freely available to the public under the terms of CC0 1.0 Universal. You can also find the full licenses and cover letter in this repo here.


The keywords “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119.

Contracts and interfaces

  • Collection - TIP4.1 contract that mints tokens;
  • NFT - TIP4.1 contract that store token information;
  • CantBeEvil - contract that is meant to be inherited by NFT contracts and any contract that wishes to expose the getLicenseURI and getLicenseName methods.


  • Every TIP-4.1 NFT contract MAY implement instance of CantBeEvil contract. NFT tokens within the same collection MAY have different license versions unless the version is specifically set in the Collection contract;
  • Every TIP-4.1 Collection contract MAY implement instance of CantBeEvil contract. In such case, the derived TIP-4.1 NFT contract MUST inherit the same license from the collection.


pragma ever-solidity >= 0.61.2;

interface ICantBeEvil {
function getLicenseURI() external view responsible returns (string);
function getLicenseName() external view responsible returns (string);


pragma ever-solidity >= 0.61.2;

import "./ICantBeEvil.sol";

enum LicenseVersion {

contract CantBeEvil is ICantBeEvil {
string internal constant _BASE_LICENSE_URI = "ar://_D9kN1WrNWbCq55BSAGRbTB4bS3v8QAPTYmBThSbX3A/";
LicenseVersion public licenseVersion; // return string

constructor(LicenseVersion _licenseVersion) public {
licenseVersion = _licenseVersion;

function getLicenseURI() public view responsible override returns (string) {
return format("{}{}", _BASE_LICENSE_URI, uint(licenseVersion));

function getLicenseName() public view responsible override returns (string) {
return _getLicenseVersionKeyByValue(licenseVersion);

function _getLicenseVersionKeyByValue(LicenseVersion _licenseVersion) internal pure returns (string) {
require(uint8(_licenseVersion) <= 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";

NOTE The TIP-6.1 identifier for this interface is 0x1E4848D4.


Pass the desired version into the CantBeEvil constructor, as shown:

import {LicenseVersion, CantBeEvil} from "./CantBeEvil.sol";

contract MyContract is CantBeEvil(LicenseVersion.CC0) {

You can now call MyContract.getLicenseURI(), which will return an Arweave gateway link to the license text file.

MyContract.getLicenseURI() // => ""