Dotlicense是一个基于Ethereum ERC721的软件许可框架

网友投稿 816 2022-10-28

Dotlicense是一个基于Ethereum ERC721的软件许可框架

Dotlicense是一个基于Ethereum ERC721的软件许可框架

Decentralized software licensing

Dotlicense is an Ethereum ERC721-based software licensing framework.

Built by Dotta and contributors

Overview

Dotlicense 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.

The licenses are ERC721-compatible Tokens. The client app holds the private key that owns the token.

The benefits are:

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.Surveillance free -- There is no "license server" tracking the user. Ownership of the token is validated by any Web3 provider (e.g. Infura or even a self-hosted node)Scarce -- The number of licenses available for a given product can be limitedTransferable -- Users can transfer or resell their licenses (e.g. they can be auctioned on sites such as Rarebits or OpenSea)Cryptocurrency-based -- Normal-cryptocurrency benefits apply such as near-instant payments, permissionless, decentralized ownership, etc. No approvals, Stripe, Shopify store, or bank account necessary.

It is designed for software licenses in desktop or mobile apps. (And there is discussion about using it for subscription web apps.)

Features

Multiple products - Each product has its own inventory levels and total supply, housed in one contractSubscriptions - Products can (optionally) expire and be renewed by paying additional fundsAffiliate program - Affiliates can get a cut of sales they refer with individual, whitelisted rates (including recurring affiliate revenue with subscriptions)Roles-based permissions - The store has three roles: CEO, CFO, and COOFull ERC-721 Compatibility - Each license issued is also an ERC-721-compatible tokenCLI Admin Tools - With Ledger hardware wallet supportEmbeddable Web3 Checkout - UMD JavaScript checkout button with Metamask support

Implementations

Dotlicense is being used in Dottabot, a cryptocurrency trailing-profit stop bot built with Electron.

Packages

Dotlicense is split into several packages:

dot-license-contracts holds the Solidity smart contracts that manage the sale and ownership of tokensdot-license-cli is the CLI admin tools for managing the smart contractsdot-license-checkout a customer checkout widget for purchases using Metamask and Reactdot-license-verifier (open-sourced soon) is a JavaScript wrapper library for client apps that need to list products that are owned, verify the licenses, etc.

Additionally, this repo stores some utilities we've built along the way such as:

dot-abi-cli - Generates a DApp CLI scaffold from an ABI (with Ledger support)

Purchase Model

There are two main models in the contracts:

The Product - which defines a feature or set of features andThe License - (the token) which defines ownership of an instance of a Product

And during operation we have:

The user (our customer) who is buying access to the features andThe client (our software) which runs our application and enables new features on verified ownership

The Products

Products have:

an ida pricethe quantity availablethe totalSupplythe quantity sold

And optionally, if the product is a subscription, it may have:

a renewal interval, e.g. 1 month or 1 year in secondsa renewable setting, which may be used to disable renewals of old plans

The client unlocks features of a given Product id if ownership of a License is proven.

When a new product is created, the totalSupply is fixed and cannot be changed. A totalSupply of 0 means "unlimited".

When a new product is created, the renewal interval is fixed and cannot be changed. An interval of 0 means "unlimited".

The executives can:

Create new ProductsChange the price for future sales of a ProductChange the inventory amount available as long as it does not violate the totalSupplyChange the product's renewable status

The License

The 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.

Licenses have:

an ida productId, which points to the Product this License is forattributes (uint256), which are specific to this individual LicenseissuedTime, which is the time when this License was created (i.e. minted)an owner

And optionally:

an expirationTime when this License expiresan affiliate address, who is credited for the original sale of this License

A 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

An expirationTime of 0 means "does not expire".

The executives can:

Issue promotional (free) Licenses, within the bounds of the supplyIssue promotional (free) renewal of Licenses

Ownership

The private key that owns the license must be readable by the client software.

In Dottabot this private key is:

generated automatically by the software on installation andkept in OS secret storage (such as Keychain on Mac or libsecret on Linux).

In 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.)

Of 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).

To 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.

This helps fulfill the piracy deterrence requirement by incentivizing the user to keep the license private.

Contracts Overview

The smart contracts are split into modules.

LicenseAccessControl - Defines the organizational roles and permission LicenseBase - Defines the License struct and storage LicenseInventory - Controls the Products and inventory for those Products LicenseOwnership - Implements ERC721 and defines ownership and transfer rights LicenseSale - Implements minting tokens when a sale happens LicenseCore - Is the core contract that is deployed to the network AffiliateProgram - Defines a minimal affiliate program, with whitelisting

Roles-based Permissions

Issuance of new products and unsold inventory levels is centrally controlled. There are three roles:

CEOCFO andCOO

Some of the smart contract functions are open to anyone and some are restricted by role. The table below shows the permissions for each:

functionCEOCFOCOOanyone
LicenseAccessControl
setCEO
setCFO
setCOO
setWithdrawalAddress
withdrawBalance
pause
unpause
LicenseBase
licenseProductId
licenseAttributes
licenseIssuedTime
licenseExpirationTime
licenseAffiliate
licenseInfo
LicenseInventory
createProduct
incrementInventory
decrementInventory
clearInventory
setPrice
setRenewable
priceOf
availableInventoryOf
totalSupplyOf
totalSold
intervalOf
renewableOf
productInfo
getAllProductIds
costForProductCycles
isSubscriptionProduct
LicenseOwnership (ERC721)
name
symbol
implementsERC721
tokenMetadata
supportsInterface
setTokenMetadataBaseURI
totalSupply
balanceOf
tokensOf
ownerOf
getApproved
isApprovedForAll
transfer
approve
approveAll
disapproveAll
takeOwnership
transferFrom
LicenseSale
setAffiliateProgramAddress
setRenewalsCreditAffiliatesFor
createPromotionalPurchase
createPromotionalRenewal
purchase
renew
LicenseCore
setNewAddress
unpause

Dotlicense Checkout

dot-license-checkout is a UMD (or React-component) library which embeds a Metamask-enabled checkout.

// React Component const logo = require("path/to/logo.png");const offers = [ { productId: '1', duration: ONE_YEAR, name: '1 year', price: 0.15 }, { productId: '1', duration: ONE_YEAR * 2, name: '2 years', price: 0.15 * 2 }];const config = { httpProviderURL: 'https://rinkeby.infura.io/98sadfnjncadlh8', licenseCoreAddress: '0xc3e2f9aADc4B5c467E0668C2d690a999A91A1a5C'};

CLI Tools

The CLI Admin tool has the following commands:

$ node ./bin/dot-license-cli.js --helpUsage: dot-license-cli.js [options]Commands: dot-license-cli.js affiliateProgram Get the affiliate program address dot-license-cli.js approve Approves another address to claim for the ownership of the given token ID dot-license-cli.js approveAll Approves another address to claim for the ownership of any tokens owned by this account dot-license-cli.js getApproved Gets the approved address to take ownership of a given token ID dot-license-cli.js availableInventoryOf The available inventory of a product dot-license-cli.js balanceOf Gets the balance of the specified address dot-license-cli.js ceoAddress Get the CEO's Address dot-license-cli.js cfoAddress Get the CFO's Address dot-license-cli.js clearInventory clearInventory clears the inventory of a product. dot-license-cli.js cooAddress Get the COOs address dot-license-cli.js createProduct createProduct creates a new product in the system dot-license-cli.js decrementInventory decrementInventory removes inventory levels for a product dot-license-cli.js disapproveAll Removes approval for another address to claim for the ownership of any tokens owned by this account. dot-license-cli.js getAllProductIds Get all product ids dot-license-cli.js incrementInventory incrementInventory - increments the inventory of a product dot-license-cli.js isApprovedForAll Tells whether an operator is approved by a given owner dot-license-cli.js licenseAttributes Get a license's attributes dot-license-cli.js licenseInfo Get a license's info dot-license-cli.js licenseIssuedTime Get a license's issueTime dot-license-cli.js licenseProductId Get a license's productId dot-license-cli.js name token's name dot-license-cli.js newContractAddress Gets the new contract address dot-license-cli.js ownerOf Gets the owner of the specified token ID dot-license-cli.js pause called by any C-level to pause, triggers stopped state dot-license-cli.js paused Checks if the contract is paused dot-license-cli.js priceOf The price of a product dot-license-cli.js productInfo The product info for a product dot-license-cli.js purchase Purchase - makes a purchase of a product. Requires that the value sent is exactly the price of the product dot-license-cli.js setAffiliateProgramAddress

executives * dot-license-cli.js setCEO Sets a new CEO dot-license-cli.js setCFO Sets a new CFO dot-license-cli.js setCOO Sets a new COO dot-license-cli.js setNewAddress Sets a new contract address dot-license-cli.js setPrice setPrice - sets the price of a product dot-license-cli.js setWithdrawalAddress Sets a new withdrawalAddress dot-license-cli.js symbol symbols's name dot-license-cli.js takeOwnership Claims the ownership of a given token ID dot-license-cli.js tokensOf Gets the list of tokens owned by a given address dot-license-cli.js totalSold The total sold of a product dot-license-cli.js totalSupply Gets the total amount of tokens stored by the contract dot-license-cli.js totalSupplyOf The total supply of a product dot-license-cli.js transfer Transfers the ownership of a given token ID to another address dot-license-cli.js transferFrom Transfer a token owned by another address, for which the calling address has previously been granted transfer approval by the owner. dot-license-cli.js unpause Unpause the contract dot-license-cli.js withdrawBalance Withdraw the balance to the withdrawalAddress dot-license-cli.js withdrawalAddress Get the withdrawal address dot-license-cli.js info Describe contract infoOptions: --web3 web3 provider url [default: "http://localhost:8545"] --from from address --gasPrice gas price in wei to use for this transaction [default: "1000000000"] --gasLimit maximum gas provided for this transaction [default: "6500000"] --value The value transferred for the transaction in wei --contract-address address to contract [required] [default: "0xb4f53a030f9d088198cdb66b8ad95aa79a95868f"] --network-id The network ID [default: "101"] --ledger use a ledger [boolean] --hd-path hd-path (used for hardware wallets) [default: "44'/60'/0'/0"] --help Show help [boolean] --version Show version number [boolean]

Objections and Risks

Because licenses are verified on the client, this framework may be susceptible to at least two attacks: cracking and spoofing.

Cracking

Like 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.

Spoofing

Because 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.

Again, 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.

This 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.

FAQ

Q: Is there a fee to use these contracts? 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.) 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 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.) Q: Why are these NFTs and not ERC20 fungible tokens? 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. Q: Do I have to pay affiliates? A: No. Affiliates have a baseline rate, which can be zero. Individual affiliates can be whitelisted

Configuring and deploying

(Coming soon)

Join Us On Telegram

If you're interested in using or developing Dotlicense, come join us on Telegram

Built With

OpenZeppelinTruffleLedgerjsWeb3.js

With inspiration from:

0xCryptokitties

Authors

Originally created by Dotta for Dottabot

License

MIT

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Quarkus中filter过滤器跨域cors问题解决方案
下一篇:Protocol buffers 的问题和滥用
相关文章

 发表评论

暂时没有评论,来抢沙发吧~