# TokenF Core

## TokenF Architecture

The central part of the framework consists of two AssetF smart contracts – TokenF and NFTF – each representing a specific tokenized asset.

* TokenF is an ERC-20 compatible contract built on a [Diamond architecture](https://docs.solarity.dev/docs/getting-started/guides/diamond/), which allows for a seamless extension of standard TokenF functionality.&#x20;
* NFTF is an ERC-721 compatible contract, similar in other aspects to the TokenF contract.&#x20;

One of the key benefits is that Diamond architecture enables contracts to bypass the maximum bytecode size restriction, making complex rules and checks feasible.\
\
Another crucial aspect of TokenF architecture is the modules. Every AssetF-based token can be additionally configured with a custom set of modules that work as standalone token plugins. Modules are composed of rules and checks that users have to abide by to use the token. These modules, in turn, integrate with 3rd-party KYC providers, monitoring services, etc.

<figure><img src="/files/gRxW764DzqqDTC6ZQNej" alt=""><figcaption><p>Pic. 1 AssetF architecture</p></figcaption></figure>

The diagram depicts the basic AssetF structure. The token itself is a Diamond proxy contract that extends `AccessControl` and either the ERC-20 or ERC-721 smart contract while containing `KYCCompliance` and `RegulatoryCompliance` as standard Diamond facets.&#x20;

Custom modules may be plugged into the corresponding `KYCCompliance` and `RegulatoryCompliance` facets, giving you flexibility in following any business logic through custom integrations.

## Access Control

TokenF and NFTF contracts extend `AccessControl` (from OpenZeppelin) functionality, which gives you convenience in managing existing roles in the tokenization project.

The role list may be configured according to the given tokenization logic and may include:

* “DAO” role with access to `mint`, `burn`, `recover`, and `forced transfer` functions.
* “Investor” role for `transfer` and `transfer from` functions.
* “Compliance officer” role for setting up and updating compliance rules.

Having custom roles set does not limit you from checking that users follow regulatory compliance rules. Instead, access control allows for an additional layer of security and customization.

## Compliance Control

As mentioned above, AssetF is a Diamond contract with two facets included in the base implementation:

* Compliance Facet (`RegulatoryCompliance`)
* KYC Facet (`KYCCompliance`)

These facets enable module management functionality for compliance contracts, as well as functions for validating rules from the corresponding compliance interfaces.

The compliance control is achieved via hooks that are called every time the user interacts with the AssetF token. These hooks initialize the assembly of “context” that will be forwarded to the plugged-in modules:

1. `_canTransfer` – Read-only hook that is used by `RegulatoryCompliance` modules to check if the token transfer (amount or tokenId) satisfies assigned rules.
2. `_isKYCed` – Read-only hook that is used by `KYCCompliance` modules to check that users follow the set of KYC rules.
3. `_transferred` – Read / Write hook that is used by `RegulatoryCompliance` modules to update some custom state of the accounting system.

Let’s take a look at the TokenF `transfer` function execution flow. By KYC compliance rules we assume that the token sender and receiver have to be KYCed by possessing an SBT token from the trusted KYC provider. Additionally, we assume that not less than 1 token could be sent. In the TokenF terms, we treat this rule as a compliance rule.

As soon as the sender executes `transfer` transaction, the `_canTransfer` hook is called and the minimal transferred amount is checked. If the amount is less than 1 token, the transaction will be reverted. Then, the `_isKYCed` hook gets called. It checks that both the token sender and receiver possess SBT tokens from the KYC provider. If that check fails, the transaction will be reverted.

Having all checks pass, `_transferred` hook gets called after the successful token transfer (balance update). The hook can be used, for example, to update the transaction count for statistics, analytics, or other purposes.

The transfer function execution flow in `NFTF` can be configured similarly to TokenF, with the key difference that it checks a tokenId instead of an amount.

## Execution Context

When users interact with the TokenF or NFTF contract, a certain context is forwarded to the Compliance and KYC modules. Depending on that context, regulatory checks are configured. The `Context` contains the following information:

* function called (selector), for example, `transfer`, `transferFrom`, or other function;
* address from which tokens are transferred;
* address to which tokens are transferred;
* amount of tokens transferred (used in the TokenF contract);
* ID of the token transferred (used in the NFTF contract);
* address of an operator;
* additional bytes data for custom compliance checks.

Simply put, context-based flow allows us to implement diverse regulatory checks. For example, for TokenF transfer function, the minimum transaction amount as 1 token can be set. However, transfer from function may be configured with a minimum amount of 10 tokens.

Moreover, the explicitness of the context makes it possible to implement different rules for different users (`sender` / `recipient` / `operator`). You may require the sender to hold a certain amount of tokens before they are allowed to spend them (in the case of TokenF), or to own a token with a certain ID or an ID in a specific range (in the case of NFTF).

All these checks are explicitly configured via handlers.

## Handlers

Handler is an internal function of a module-contract with a specific signature (specified below) that internally implements the KYC / regulatory checks required for the business logic.

```solidity
function <name>(IAssetF.Context memory) internal view virtual returns (bool);
```

These handler functions are associated with special “handler topics” (handler topic => handler function) that in turn describe what these handlers do. The handler function may integrate with some external service to authenticate the user / perform some accounting system state checks.

## Handler Topics and Context Keys

In a nutshell, a handler topic is an identifier of the handler function that will perform some compliance checks. Since there may be more than one check to execute, the framework has to support the set of handler topics to be configured.

Indeed, the configuration is performed through the specification of “context key” that points to the array of “handler topics”. During the transaction execution, the AssetF module is passed an “execution context” which eventually becomes the source of “context key” construction. The associated “handler topics” are extracted from this “context key”, the corresponding “handler functions” are obtained, and, at last, called.

In the basic implementation, the context key is formed as `keccak256(function selector)`.

Suppose we want to add a rule to the TokenF token contract that no more than 10 ether tokens can be transferred per transaction. In this case, we can define a `bytes32 public constant MIN_TRANSFER_LIMIT_TOPIC = keccak256("MIN_TRANSFER_LIMIT")` handler topic, for which we will set up a handler:

```solidity
function _handleMaxTransferLimitTopic(IAssetF.Context memory ctx_) internal view virtual returns (bool) {
    return ctx_.amount <= 10 ether;
}
```

We will associate the `MIN_TRANSFER_LIMIT_TOPIC` with the “context key” `keccak256(transfer.selector)`. During the transaction execution this “context key” will be reconstructed from the given “execution context” (TokenF will take the context selector) and perform the compliance flow.


---

# 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://tokenf.gitbook.io/tokenf/deep-dive/tokenf-core.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.
