# License

*Address:* [*0xaA32a9E74486dd136cCEdF17061Fe4EFC95A621e*](https://polygonscan.com/address/0xaA32a9E74486dd136cCEdF17061Fe4EFC95A621e)

<figure><img src="/files/lstWQcAgdZmY4T0N57JW" alt=""><figcaption></figcaption></figure>

## Flow

1. User/Manufacturer stakes the minimum amount of DIMO tokens&#x20;
2. The contract tracks your staked balance&#x20;
3. \`checkUserIsWhitelisted()\` returns a boolean based on stake requirements
4. The Aftermarket contract checks for eligibility and mints a license to the specified user

## License

The original idea for soulbound tokens comes from [Vitalik Butterin](https://vitalik.ca/general/2022/01/26/soulbound.html). There is no official spec nor EIP for soulbound tokens, but there are several implementations with different trade offs.

**Design Decisions**

We had some requirements to consider for Licensing

* Keep pushing towards a web3/decentralized ecosystem
* Prevent manufacturers from minting infinite licenses
* Track the issuances of licenses
* Easier onboarding of future Manufacturers
* Include specific metadata to prevent abuse

In order to deliver the functionality inachieve the diagram above, where Hardware Manufacturers are licensed to create new DIMO-enabled devices we are heavily influenced by Account Bound Tokens (EIP-4973).

### Advantages of ABT&#x20;

Soulbound tokens override the `ERC721`'s transfer function to revert. This allows for the user to hold a token indefinitely, but it also binds the asset to the user's private key. If a user or institution loses access to their wallet, that asset is permanently unrecoverable. However, with an ABT, the token can be revoked and reassigned (granted they prove their identity/ownership first).

There may be a situation in which an attacker gains access to a SBT and is able to take out a loan in their name for example, whereas this situation can be mitigated with an ABT by simply revoking access.

### Interfaces

In order to be maximally backward-compatible with existing ERC721 Infrastructure, ABTs (Account Bound Tokens) implement existing functions purposefully. Things like `EIP-165` and `ERC721Metadata` which wallets will already be familiar with.

Additionally there is a `checkUserIsWhiteListed(address user)` function that returns a boolean and checks to see that the user has staked greater than the `minStakeAmount` in order to return true.

### ERC165

the IERC165 Interface is a single function `supportsInterface()` with takes in a `bytes4 interfaceId` as the parameter. The interfaceId is the 8bit hex string for the calldata of the function. The purpose of this method is for a contract to "ask" a second contract if it supports a specific method. This prevents sending tokens to a contract that cannot read them. For example, sending an `ERC1155` token to an `ERC20` contract would leave them stuck.

By hashing the function name and it's parameters, you can use the result to check if the method is supported.

`keccak256("tokenByIndex(uint256)") == '0xasdfasdf"`

you would then do

`supportsInterface("0xasdfasdf")`

and the resulting boolean would tell you whether it's safe to proceed or not.

### Events

Our `License` has two main events;

**Attest**

```
(address indexed _to, uint256 indexed _tokenId);
```

Emits when a new token is related and bound to an account by any mechanism

**Revoke**

```
(address indexed _to, uint256 indexed _tokenId);
```

Emits when an existing License is revoked from an account and destroyed by any mechanism.

#### Fund recovery

In the event a user accidentally sends DIMO tokens directly to the contract, the tokens would not be credited to the sender and the tokens would effectively be “stuck” or “lost”. This is a limitation of the ERC20 standard and would apply to any token being sent to any smart contract.

To recover lost DIMO, we implemented a `emergencyWithdraw()` function that first checks for stuck tokens by subtracting the `dimoTotalAmountStaked` value from the total number of DIMO held on the contract. The returning value is only ever positive when the user accidentally sends tokens directly rather than interacting with the `stake()` function.

If there is a positive amount, and the user has a staked balance, the tokens are transferred to the specified user and the `EmergencyWithdrawal(user,amount)` event is emitted.

### Upgradeability

To implement future features for posterity, we are using the Universal Upgradeable Proxy Standard, aka [EIP 1822](https://eips.ethereum.org/EIPS/eip-1822). This pattern is a standard for proxy contracts which is universally compatible with all contracts, and does not create incompatibility between the proxy and business-logic contracts. This is achieved by utilizing a unique storage position in the proxy contract to store the Logic Contract’s address. A compatibility check ensures successful upgrades. Upgrading can be performed unlimited times, or as determined by custom logic. In addition, a method for selecting from multiple constructors is provided, which does not inhibit the ability to verify bytecode.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.dimo.org/protocol/identity-protocol/nodes-and-nfts/license.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
