# License

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

<figure><img src="https://117111452-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfmY0p4toAb7e89toAV2R%2Fuploads%2Fm4UnIrjXN3R8Z3Jtr27O%2Fimage.png?alt=media&#x26;token=df7f7b6f-f913-4ced-9492-6348bcdd275c" 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.
