{"id":13565546,"url":"https://github.com/cryppadotta/dotta-license","last_synced_at":"2025-04-03T22:31:41.947Z","repository":{"id":50272233,"uuid":"123626530","full_name":"cryppadotta/dotta-license","owner":"cryppadotta","description":"ERC721-based Software Licensing Framework","archived":false,"fork":false,"pushed_at":"2023-10-24T15:34:10.000Z","size":2318,"stargazers_count":501,"open_issues_count":16,"forks_count":99,"subscribers_count":26,"default_branch":"master","last_synced_at":"2024-11-04T19:41:49.952Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cryppadotta.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2018-03-02T20:19:14.000Z","updated_at":"2024-10-22T09:47:47.000Z","dependencies_parsed_at":"2024-01-14T17:20:03.462Z","dependency_job_id":null,"html_url":"https://github.com/cryppadotta/dotta-license","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cryppadotta%2Fdotta-license","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cryppadotta%2Fdotta-license/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cryppadotta%2Fdotta-license/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cryppadotta%2Fdotta-license/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cryppadotta","download_url":"https://codeload.github.com/cryppadotta/dotta-license/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247090271,"owners_count":20881941,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T13:01:49.754Z","updated_at":"2025-04-03T22:31:39.961Z","avatar_url":"https://github.com/cryppadotta.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003e\n  \u003cimg src=\"https://i.imgur.com/Cp9BmvE.png\"\nsrcset=\"https://i.imgur.com/HvP6jpJ.png 2x\"\n  alt=\"Dotlicense\" width=\"970\"\u003e\u003c/a\u003e\n\u003c/h1\u003e\n\n\u003ch3 align=\"center\"\u003eDecentralized software licensing\u003c/h3\u003e\n\u003cdiv align=\"center\"\u003e\n  Dotlicense is an Ethereum ERC721-based software licensing framework.\n\u003c/div\u003e\n\n\u003cbr /\u003e\n\n\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"https://img.shields.io/badge/platform-Ethereum-brightgreen.svg?style=flat-square\" alt=\"Ethereum\" /\u003e \u003cimg src=\"https://img.shields.io/badge/token-ERC721-ff69b4.svg?style=flat-square\" alt=\"Token ERC721\" /\u003e \u003cimg src=\"https://img.shields.io/badge/contributions-welcome-orange.svg?style=flat-square\" alt=\"Contributions Welcome\" /\u003e \u003cimg src=\"https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square\" alt=\"MIT License\" /\u003e \u003ca href=\"https://travis-ci.org/cryppadotta/dotta-license\"\u003e\u003cimg src=\"https://travis-ci.org/cryppadotta/dotta-license.svg?branch=master\u0026style=flat-square\" alt=\"Travis CI\" /\u003e\u003c/a\u003e \u003ca href=\"https://t.me/dotlicense\"\u003e \u003cimg src=\"https://img.shields.io/badge/Join%20Us%20On-Telegram-2599D2.svg?style=flat-square\" alt=\"Join Us On Telegram\" /\u003e\u003c/a\u003e\n\u003c/div\u003e\n\n\u003cdiv align=\"center\"\u003e\n  \u003csub\u003eBuilt by\n  \u003ca href=\"https://twitter.com/cryppadotta\"\u003eDotta\u003c/a\u003e and\n  \u003ca href=\"https://github.com/cryppadotta/dotta-license/graphs/contributors\"\u003e\n    contributors\n  \u003c/a\u003e\n\u003c/div\u003e\n\n# Overview\n\nDotlicense is a set of smart contracts and JavaScript tooling to sell and verify software licenses (e.g. **in-app-purchases** or **feature access tokens**) using Ethereum. It supports both single purchase and (prepaid) subscriptions.\n\nThe licenses are [ERC721-compatible Tokens](http://erc721.org/). The client app holds the private key that owns the token.\n\nThe benefits are:\n\n1. **Piracy deterring** -- Because the private key is used to validate the license, owners are dis-incentivized to share that key. Because if the key is shared, for example, on a file-sharing site the license can be transferred, stolen, and sold.\n1. **Surveillance free** -- There is no \"license server\" tracking the user. Ownership of the token is validated by any [Web3 provider](https://web3js.readthedocs.io/en/1.0/web3.html#setprovider) (e.g. [Infura](https://infura.io/) or even a self-hosted node)\n1. **Scarce** -- The number of licenses available for a given product can be limited\n1. **Transferable** -- Users can transfer or resell their licenses (e.g. they can be auctioned on sites such as [Rarebits](https://rarebits.io/) or [OpenSea](https://opensea.io/))\n1. **Cryptocurrency-based** -- Normal-cryptocurrency benefits apply such as near-instant payments, permissionless, decentralized ownership, etc. No approvals, Stripe, Shopify store, or bank account necessary.\n\nIt is designed for software licenses in desktop or mobile apps. (And there [is discussion](https://github.com/cryppadotta/dotta-license/issues/2) about using it for subscription web apps.)\n\n# Features\n\n* **Multiple products** - Each product has its own inventory levels and total supply, housed in one contract\n* **Subscriptions** - Products can (optionally) expire and be renewed by paying additional funds\n* **Affiliate program** - Affiliates can get a cut of sales they refer with individual, whitelisted rates (including recurring affiliate revenue with subscriptions)\n* **Roles-based permissions** - The store has three roles: CEO, CFO, and COO\n* **Full ERC-721 Compatibility** - Each license issued is also an ERC-721-compatible token\n* **CLI Admin Tools** - With [Ledger hardware wallet](https://www.ledgerwallet.com/) support\n* **Embeddable Web3 Checkout** - UMD JavaScript checkout button with [Metamask](https://github.com/MetaMask) support\n\n# Implementations\n\nDotlicense is being used in [Dottabot](https://www.dottabot.com/), a cryptocurrency trailing-profit stop bot built with [Electron](https://electronjs.org/).\n\n# Packages\n\nDotlicense is split into several packages:\n\n* [`dot-license-contracts`](dot-license-contracts/README.md) holds the Solidity smart contracts that manage the sale and ownership of tokens\n* [`dot-license-cli`](dot-license-cli/README.md) is the CLI admin tools for managing the smart contracts\n* [`dot-license-checkout`](dot-license-checkout/README.md) a customer checkout widget for purchases using Metamask and React\n* [`dot-license-verifier`](#COMING_SOON) (open-sourced soon) is a JavaScript wrapper library for client apps that need to list products that are owned, verify the licenses, etc.\n\nAdditionally, this repo stores some utilities we've built along the way such as:\n\n* [`dot-abi-cli`](dot-abi-cli/README.md) - Generates a DApp CLI scaffold from an ABI (with Ledger support)\n\n# Purchase Model\n\nThere are two main models in the contracts:\n\n* The `Product` - which defines a feature or set of features and\n* The `License` - (the token) which defines ownership of an instance of a `Product`\n\nAnd during operation we have:\n\n* The _user_ (our customer) who is buying access to the features and\n* The _client_ (our software) which runs our application and enables new features on verified ownership\n\n### The `Product`s\n\n`Product`s have:\n\n* an `id`\n* a `price`\n* the quantity `available`\n* the `totalSupply`\n* the quantity `sold`\n\nAnd optionally, if the product is a subscription, it may have:\n\n* a renewal `interval`, e.g. 1 month or 1 year in seconds\n* a `renewable` setting, which may be used to disable renewals of old plans\n\nThe client unlocks features of a given `Product` `id` if ownership of a _`License`_ is proven.\n\nWhen a new product is created, the `totalSupply` is fixed and **cannot be changed**. A `totalSupply` of `0` means \"unlimited\".\n\nWhen a new product is created, the renewal `interval` is fixed and **cannot be changed**. An `interval` of `0` means \"unlimited\".\n\nThe executives can:\n\n* Create new `Product`s\n* Change the price for future sales of a `Product`\n* Change the inventory amount `available` **as long as it does not violate the `totalSupply`**\n* Change the product's `renewable` status\n\n### The `License`\n\nThe `License` represents ownership of one unit of a `Product`. The `License` is the same as a \"token\" - they have the same ID and the two are used interchangeably.\n\n`License`s have:\n\n* an `id`\n* a `productId`, which points to the `Product` this `License` is for\n* `attributes` (`uint256`), which are specific to this individual `License`\n* `issuedTime`, which is the time when this `License` was created (i.e. minted)\n* an owner\n\nAnd optionally:\n\n* an `expirationTime` when this `License` expires\n* an `affiliate` address, who is credited for the original sale of this `License`\n\nA `License` is created (that is, the token is minted) at time of sale. When a sale is made, the inventory for that `Product` is decremented and ownership is transferred to the `assignee`\n\nAn `expirationTime` of `0` means \"does not expire\".\n\nThe executives can:\n\n* Issue promotional (free) `License`s, within the bounds of the supply\n* Issue promotional (free) renewal of `Licenses`\n\n### Ownership\n\nThe private key that owns the license must be readable by the client software.\n\nIn [Dottabot](https://www.dottabot.com) this private key is:\n\n* generated automatically by the software on installation and\n* kept in OS secret storage (such as Keychain on Mac or `libsecret` on Linux).\n\nIn Dottabot, this means that while it is encrypted on disk, it is also readable by the software without user interaction. (It can also be deployed onto a VPS where a hardware wallet may not be available.)\n\nOf course, this raises the problem of funds at purchase: often our users will have an existing wallet that they spend from (and it won't be our application's private key).\n\nTo deal with this issue, we require the user input the `assignee` address at purchase time (that is, the address controlled by the client software). When the token is purchased, **ownership of the token is given to the private key controlled by our software**.\n\nThis helps fulfill the piracy deterrence requirement by incentivizing the user to keep the license private.\n\n# Contracts Overview\n\n\u003cimg align=\"right\" src=\"https://i.imgur.com/nJGej5H.png\" alt=\"Contract Inheritance Architecture\" /\u003e\n\nThe smart contracts are split into modules.\n\n* [`LicenseAccessControl`](dot-license-contracts/contracts/LicenseAccessControl.sol) - Defines the organizational roles and permission\n* [`LicenseBase`](dot-license-contracts/contracts/LicenseBase.sol) - Defines the `License` struct and storage\n* [`LicenseInventory`](dot-license-contracts/contracts/LicenseInventory.sol) - Controls the `Product`s and inventory for those `Product`s\n* [`LicenseOwnership`](dot-license-contracts/contracts/LicenseOwnership.sol) - Implements ERC721 and defines ownership and transfer rights\n* [`LicenseSale`](dot-license-contracts/contracts/LicenseSale.sol) - Implements minting tokens when a sale happens\n* [`LicenseCore`](dot-license-contracts/contracts/LicenseCore.sol) - Is the core contract that is deployed to the network\n\n* [`AffiliateProgram`](dot-license-contracts/contracts/Affiliate/AffiliateProgram.sol) - Defines a minimal affiliate program, with whitelisting\n\n# Roles-based Permissions\n\nIssuance of new products and unsold inventory levels is centrally controlled. There are three roles:\n\n* CEO\n* CFO and\n* COO\n\nSome of the smart contract functions are open to anyone and some are restricted by role. The table below shows the permissions for each:\n\n| function                         | CEO | CFO | COO | anyone |\n| -------------------------------- | --- | --- | --- | ------ |\n| **LicenseAccessControl**         |     |     |     |        |\n| `setCEO`                         | ✔   |     |     |        |\n| `setCFO`                         | ✔   |     |     |        |\n| `setCOO`                         | ✔   |     |     |        |\n| `setWithdrawalAddress`           | ✔   |     |     |        |\n| `withdrawBalance`                | ✔   | ✔   |     |        |\n| `pause`                          | ✔   | ✔   | ✔   |        |\n| `unpause`                        | ✔   |     |     |        |\n|                                  |     |     |     |        |\n| **LicenseBase**                  |     |     |     |        |\n| `licenseProductId`               |     |     |     | ✔      |\n| `licenseAttributes`              |     |     |     | ✔      |\n| `licenseIssuedTime`              |     |     |     | ✔      |\n| `licenseExpirationTime`          |     |     |     | ✔      |\n| `licenseAffiliate`               |     |     |     | ✔      |\n| `licenseInfo`                    |     |     |     | ✔      |\n|                                  |     |     |     |        |\n| **LicenseInventory**             |     |     |     |        |\n| `createProduct`                  | ✔   |     | ✔   |        |\n| `incrementInventory`             | ✔   | ✔   | ✔   |        |\n| `decrementInventory`             | ✔   | ✔   | ✔   |        |\n| `clearInventory`                 | ✔   | ✔   | ✔   |        |\n| `setPrice`                       | ✔   | ✔   | ✔   |        |\n| `setRenewable`                   | ✔   | ✔   | ✔   |        |\n| `priceOf`                        |     |     |     | ✔      |\n| `availableInventoryOf`           |     |     |     | ✔      |\n| `totalSupplyOf`                  |     |     |     | ✔      |\n| `totalSold`                      |     |     |     | ✔      |\n| `intervalOf`                     |     |     |     | ✔      |\n| `renewableOf`                    |     |     |     | ✔      |\n| `productInfo`                    |     |     |     | ✔      |\n| `getAllProductIds`               |     |     |     | ✔      |\n| `costForProductCycles`           |     |     |     | ✔      |\n| `isSubscriptionProduct`          |     |     |     | ✔      |\n|                                  |     |     |     |        |\n| **LicenseOwnership** (ERC721)    |     |     |     |        |\n| `name`                           |     |     |     | ✔      |\n| `symbol`                         |     |     |     | ✔      |\n| `implementsERC721`               |     |     |     | ✔      |\n| `tokenMetadata`                  |     |     |     | ✔      |\n| `supportsInterface`              |     |     |     | ✔      |\n| `setTokenMetadataBaseURI`        | ✔   |     | ✔   |        |\n| `totalSupply`                    |     |     |     | ✔      |\n| `balanceOf`                      |     |     |     | ✔      |\n| `tokensOf`                       |     |     |     | ✔      |\n| `ownerOf`                        |     |     |     | ✔      |\n| `getApproved`                    |     |     |     | ✔      |\n| `isApprovedForAll`               |     |     |     | ✔      |\n| `transfer`                       |     |     |     | ✔      |\n| `approve`                        |     |     |     | ✔      |\n| `approveAll`                     |     |     |     | ✔      |\n| `disapproveAll`                  |     |     |     | ✔      |\n| `takeOwnership`                  |     |     |     | ✔      |\n| `transferFrom`                   |     |     |     | ✔      |\n|                                  |     |     |     |        |\n| **LicenseSale**                  |     |     |     |        |\n| `setAffiliateProgramAddress`     | ✔   |     |     |        |\n| `setRenewalsCreditAffiliatesFor` | ✔   |     |     |        |\n| `createPromotionalPurchase`      | ✔   |     | ✔   |        |\n| `createPromotionalRenewal`       | ✔   |     | ✔   |        |\n| `purchase`                       |     |     |     | ✔      |\n| `renew`                          |     |     |     | ✔      |\n|                                  |     |     |     |        |\n| **LicenseCore**                  |     |     |     |        |\n| `setNewAddress`                  | ✔   |     |     |        |\n| `unpause`                        | ✔   |     |     |        |\n\n# Dotlicense Checkout\n\n`dot-license-checkout` is a UMD (or React-component) library which embeds a Metamask-enabled checkout.\n\n\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"https://i.imgur.com/LNa0A7q.png\"\n  alt=\"dot-checkout\" width=\"975\"\u003e\u003c/a\u003e\n\u003c/div\u003e\n\n```javascript\n// React Component \n\nconst logo = require(\"path/to/logo.png\");\n\nconst offers = [\n  {\n    productId: '1',\n    duration: ONE_YEAR,\n    name: '1 year',\n    price: 0.15\n  },\n  {\n    productId: '1',\n    duration: ONE_YEAR * 2,\n    name: '2 years',\n    price: 0.15 * 2\n  }\n];\n\nconst config = {\n  httpProviderURL: 'https://rinkeby.infura.io/98sadfnjncadlh8',\n  licenseCoreAddress: '0xc3e2f9aADc4B5c467E0668C2d690a999A91A1a5C'\n};\n\n\u003cDotLicenseCheckout\n  productName=\"Dottabot\"\n  productSubheading=\"Unlimited License\"\n  offerLabel=\"Years:\"\n  offers={offers}\n  logo={logo}\n  httpProviderURL={config.httpProviderURL}\n  licenseCoreAddress={config.licenseCoreAddress}\n/\u003e\n```\n\n# CLI Tools\n\n\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"https://i.imgur.com/1MRZQuU.png\" alt=\"dot-license-cli\" /\u003e\n\u003c/div\u003e\n\nThe CLI Admin tool has the following commands:\n\n```bash\n$ node ./bin/dot-license-cli.js --help\nUsage: dot-license-cli.js \u003ccommand\u003e [options]\n\nCommands:\n  dot-license-cli.js affiliateProgram                                             Get the affiliate program address\n  dot-license-cli.js approve \u003cto\u003e \u003ctokenId\u003e                                       Approves another address to claim for the ownership of the given token ID\n  dot-license-cli.js approveAll \u003cto\u003e                                              Approves another address to claim for the ownership of any tokens owned by\n                                                                                  this account\n  dot-license-cli.js getApproved \u003ctokenId\u003e                                        Gets the approved address to take ownership of a given token ID\n  dot-license-cli.js availableInventoryOf \u003cproductId\u003e                             The available inventory of a product\n  dot-license-cli.js balanceOf \u003cowner\u003e                                            Gets the balance of the specified address\n  dot-license-cli.js ceoAddress                                                   Get the CEO's Address\n  dot-license-cli.js cfoAddress                                                   Get the CFO's Address\n  dot-license-cli.js clearInventory \u003cproductId\u003e                                   clearInventory clears the inventory of a product.\n  dot-license-cli.js cooAddress                                                   Get the COOs address\n  dot-license-cli.js createProduct \u003cproductId\u003e \u003cinitialPrice\u003e                     createProduct creates a new product in the system\n  \u003cinitialInventoryQuantity\u003e \u003csupply\u003e\n  dot-license-cli.js decrementInventory \u003cproductId\u003e \u003cinventoryAdjustment\u003e         decrementInventory removes inventory levels for a product\n  dot-license-cli.js disapproveAll \u003cto\u003e                                           Removes approval for another address to claim for the ownership of any\n                                                                                  tokens owned by this account.\n  dot-license-cli.js getAllProductIds                                             Get all product ids\n  dot-license-cli.js incrementInventory \u003cproductId\u003e \u003cinventoryAdjustment\u003e         incrementInventory - increments the inventory of a product\n  dot-license-cli.js isApprovedForAll \u003cowner\u003e \u003coperator\u003e                     Tells whether an operator is approved by a given owner\n  dot-license-cli.js licenseAttributes \u003clicenseId\u003e                                Get a license's attributes\n  dot-license-cli.js licenseInfo \u003clicenseId\u003e                                      Get a license's info\n  dot-license-cli.js licenseIssuedTime \u003clicenseId\u003e                                Get a license's issueTime\n  dot-license-cli.js licenseProductId \u003clicenseId\u003e                                 Get a license's productId\n  dot-license-cli.js name                                                         token's name\n  dot-license-cli.js newContractAddress                                           Gets the new contract address\n  dot-license-cli.js ownerOf \u003ctokenId\u003e                                            Gets the owner of the specified token ID\n  dot-license-cli.js pause                                                        called by any C-level to pause, triggers stopped state\n  dot-license-cli.js paused                                                       Checks if the contract is paused\n  dot-license-cli.js priceOf \u003cproductId\u003e                                          The price of a product\n  dot-license-cli.js productInfo \u003cproductId\u003e                                      The product info for a product\n  dot-license-cli.js purchase \u003cproductId\u003e \u003cassignee\u003e \u003caffiliate\u003e                  Purchase - makes a purchase of a product. Requires that the value sent is\n                                                                                  exactly the price of the product\n  dot-license-cli.js setAffiliateProgramAddress \u003caddress\u003e                         executives *\n  dot-license-cli.js setCEO \u003cnewCEO\u003e                                              Sets a new CEO\n  dot-license-cli.js setCFO \u003cnewCFO\u003e                                              Sets a new CFO\n  dot-license-cli.js setCOO \u003cnewCOO\u003e                                              Sets a new COO\n  dot-license-cli.js setNewAddress \u003cv2Address\u003e                                    Sets a new contract address\n  dot-license-cli.js setPrice \u003cproductId\u003e \u003cprice\u003e                                 setPrice - sets the price of a product\n  dot-license-cli.js setWithdrawalAddress \u003cnewWithdrawalAddress\u003e                  Sets a new withdrawalAddress\n  dot-license-cli.js symbol                                                       symbols's name\n  dot-license-cli.js takeOwnership \u003ctokenId\u003e                                      Claims the ownership of a given token ID\n  dot-license-cli.js tokensOf \u003cowner\u003e                                             Gets the list of tokens owned by a given address\n  dot-license-cli.js totalSold \u003cproductId\u003e                                        The total sold of a product\n  dot-license-cli.js totalSupply                                                  Gets the total amount of tokens stored by the contract\n  dot-license-cli.js totalSupplyOf \u003cproductId\u003e                                    The total supply of a product\n  dot-license-cli.js transfer \u003cto\u003e \u003ctokenId\u003e                                      Transfers the ownership of a given token ID to another address\n  dot-license-cli.js transferFrom \u003cfrom\u003e \u003cto\u003e \u003ctokenId\u003e                           Transfer a token owned by another address, for which the calling address\n                                                                                  has previously been granted transfer approval by the owner.\n  dot-license-cli.js unpause                                                      Unpause the contract\n  dot-license-cli.js withdrawBalance                                              Withdraw the balance to the withdrawalAddress\n  dot-license-cli.js withdrawalAddress                                            Get the withdrawal address\n  dot-license-cli.js info                                                         Describe contract info\n\nOptions:\n  --web3              web3 provider url                                                                                   [default: \"http://localhost:8545\"]\n  --from              from address\n  --gasPrice          gas price in wei to use for this transaction                                                                   [default: \"1000000000\"]\n  --gasLimit          maximum gas provided for this transaction                                                                         [default: \"6500000\"]\n  --value             The value transferred for the transaction in wei\n  --contract-address  address to contract                                                 [required] [default: \"0xb4f53a030f9d088198cdb66b8ad95aa79a95868f\"]\n  --network-id        The network ID                                                                                                        [default: \"101\"]\n  --ledger            use a ledger                                                                                                                 [boolean]\n  --hd-path           hd-path (used for hardware wallets)                                                                          [default: \"44'/60'/0'/0\"]\n  --help              Show help                                                                                                                    [boolean]\n  --version           Show version number                                                                                                          [boolean]\n```\n\n# Objections and Risks\n\nBecause licenses are verified on the client, this framework may be susceptible to at least two attacks: _cracking_ and _spoofing_.\n\n### Cracking\n\nLike any desktop, mobile, or client-run app it may be possible for a determined hacker to patch the binary in such a way as to bypass the verification mechanism. Over time, we expect to improve our deterrence methods, but cracking is always a risk.\n\n### Spoofing\n\nBecause this software uses the Ethereum blockchain to verify ownership of a license-token, one could \"spoof\" ownership by directing their Web3 provider to a chain fork where they own a token, even when they may have transferred that token on the main net.\n\nAgain, we plan to implement a degree of 'main-chain' verification to make this difficult or cumbersome for an attacker to do. But forks are always a risk.\n\nThis attack could be mitigated by hosting your own Ethereum node and requiring pinning in your client app. However, the tradeoff here is by requiring the user to hit your server the user has reduced privacy and availability.\n\n# FAQ\n\n* **Q**: Is there a fee to use these contracts?\n* **A**: No. This software is free to use and there are no \"rents\" extracted that go back to the Dotlicense team. (Of course, if you use the contracts, Ethereum transactions have fees.)\n\n* **Q**: Why must the client-software hold the private-key ownership of the tokens? Wouldn't it be better for the token to specify the 'allowed client' but restrict transfer to user-held key? This way a user could hold their license-tokens in e.g. a hardware wallet\n* **A**: If the user held the ownership private key independently, they could freely share a license key with no consequences. When the client application requires the private key, then there is incentive to keep it private (because otherwise the license may be stolen.)\n\n* **Q**: Why are these NFTs and not ERC20 fungible tokens?\n* **A**: Because each individual license has it's own attributes. These tokens are somewhat of a hybrid in that you may sell multiple copies of the same feature. However, the tokens aren't fully fungible either -- they each hold unique attributes.\n\n* **Q**: Do I have to pay affiliates?\n* **A**: No. Affiliates have a baseline rate, which can be zero. Individual affiliates can be whitelisted\n\n# Configuring and deploying\n\n_(Coming soon)_\n\n# Join Us On Telegram\n\nIf you're interested in using or developing Dotlicense, come [join us on Telegram](https://t.me/dotlicense)\n\n# Built With\n\n* [OpenZeppelin](https://github.com/OpenZeppelin/zeppelin-solidity)\n* [Truffle](https://truffleframework.com)\n* [Ledgerjs](https://github.com/LedgerHQ/ledgerjs)\n* [Web3.js](https://github.com/ethereum/web3.js/)\n\nWith inspiration from:\n\n* [0x](https://github.com/0xProject/0x.js)\n* [Cryptokitties](https://github.com/axiomzen/cryptokitties-bounty)\n\n# Authors\n\nOriginally created by [Dotta](https://twitter.com/cryppadotta) for [Dottabot](https://www.dottabot.com)\n\n# License\n\n[MIT](https://opensource.org/licenses/MIT)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcryppadotta%2Fdotta-license","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcryppadotta%2Fdotta-license","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcryppadotta%2Fdotta-license/lists"}