Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 43 additions & 21 deletions .gitbook/developers-evm/multivm-token-standard.mdx
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
---
description: Understanding token representation in Injective's multi-VM architecture
title: MultiVM Token Standard
description: Understanding token representation in Injective's multi-VM architecture
---

## What is MultiVM Token Standard (MTS)?

MTS (MultiVM Token Standard) ensures that every token on Injective—whether deployed using Cosmos modules or via the Ethereum Virtual Machine (EVM)—has one canonical balance and identity. This unified approach prevents fragmentation and eliminates the need for bridging or wrapping tokens, thereby enabling seamless interoperability and unified liquidity for decentralized finance (DeFi) and dApp interactions.
MTS (MultiVM Token Standard) ensures that every token on Injective -
whether deployed using Cosmos modules or via the Ethereum Virtual Machine (EVM) —
has one canonical balance and identity.
This unified approach prevents fragmentation and eliminates the need for bridging or wrapping tokens,
thereby enabling seamless interoperability and unified liquidity for decentralized finance (DeFi) and dApp interactions.

## Why is MTS Important?

Expand All @@ -27,46 +31,64 @@ The system comprises two main components:

<figure><img src="/img/multivm-token-single-token-representation-architecture.png" alt="" /><figcaption><p>Single Token Representation Architecture</p></figcaption></figure>

### **Creating an** MT&#x53;**-Compliant Token**
### Creating an MTS-Compliant Token

1. [**Using Our Prebuilt Templates**](https://github.com/InjectiveLabs/solidity-contracts/tree/master/src):
* Start with the provided Solidity templates, such as `BankERC20.sol`, `MintBurnBankERC20.sol`, or `FixedSupplyBankERC20.sol`.
2. [**Deploying the Contract**](/developers-evm/smart-contracts/):
* Deploy your MTS token contract on the Injective EVM network.
* The contract automatically interacts with the Bank Precompile to update the canonical state.

### **Interoperability and Cross-Chain Integration**
### Interoperability and Cross-Chain Integration

#### **Native Interoperability**
#### Native Interoperability*

Injective’s EVM is integrated directly into the Cosmos-based chain.

* EVM smart contracts, when using MTS, perform operations that reflect immediately on native modules (such as the exchange, staking, and governance modules).
* [JSON-RPC endpoints](/developers-evm/network-information/) provided within the Injective binary are compatible with Ethereum, ensuring smooth developer integration.
* EVM smart contracts, when using MTS, perform operations that reflect immediately
on native modules (such as the exchange, staking, and governance modules).
* [JSON-RPC endpoints](/developers-evm/network-information/)
provided within the Injective binary are compatible with Ethereum,
ensuring smooth developer integration.

#### **Cross-Chain Operations**
#### Cross-Chain Operations

* **IBC Compatibility:** Existing native tokens (e.g., those created via a [Token Factory](/developers-native/injective/tokenfactory/) or pegged via Peggy) are accessible from the EVM once an MTS pairing is established.
* **Bridging Alternatives:** While many blockchains require separate bridge operations (lock, mint, unlock), MTS avoids these steps by natively synchronizing states.
* **IBC Compatibility:** Existing native tokens
(e.g., those created via a
[Token Factory](/developers-native/injective/tokenfactory/) or pegged via Peggy)
are accessible from the EVM once an MTS pairing is established.
* **Bridging Alternatives:** While many blockchains require separate bridge operations (lock, mint, unlock),
MTS avoids these steps by natively synchronizing states.

#### **Allowances & Extended ERC20 Functions**
#### Allowances & Extended ERC20 Functions

* MTS contracts maintain standard ERC20 functionalities such as allowances (approve/transferFrom).
* Note that while the allowance mechanism is maintained within the EVM contract for convenience, the ultimate balance is managed by the bank module, preserving integrity.
* MTS contracts maintain standard ERC20 functionalities such as allowances
(approve/transferFrom).
* Note that while the allowance mechanism is maintained within the EVM contract for convenience,
the ultimate balance is managed by the bank module, preserving integrity.

### **Performance, Gas, and Security Considerations**
### Performance, Gas, and Security Considerations

#### **Gas Costs and Efficiency**
#### Gas Costs and Efficiency

* Gas fees are paid in INJ. While MTS operations via the EVM introduce an abstraction layer that may slightly increase gas usage compared to native transactions, the overall cost remains lower than comparable operations on Ethereum.
* Gas fees are paid in INJ.
While MTS operations via the EVM introduce an abstraction layer that may slightly increase gas usage compared to native transactions,
the overall cost remains lower than comparable operations on Ethereum.
* The gas model is designed to reflect a balance between EVM-style opcode costs and native module interactions.

#### **Security**
#### Security

* The [bank module](/developers-native/core/), as the single source of truth, underpins MTS’s security by ensuring that token balances are consistent and verifiable.
* The use of [precompiles](/developers-evm/precompiles/) prevents common pitfalls like state desynchronization, ensuring that all operations—no matter where initiated—update the same canonical ledger.
* Advanced security guidelines and best practices for smart contract development are provided in our security section and external resources.
* The [bank module](/developers-native/core/), as the single source of truth,
underpins MTS’s security by ensuring that token balances are consistent and verifiable.
* The use of [precompiles](/developers-evm/precompiles/) prevents common pitfalls
like state desynchronization, ensuring that all operations -
no matter where initiated—update the same canonical ledger.
* Advanced security guidelines and best practices for smart contract development
are provided in our security section and external resources.

**ℹ️ Note:**

To prevent denom spam, deploying an ERC20 contract via the ERC20 module is a **payable operation** and requires a deployment fee of **1 INJ**. Make sure your ERC20 contract deployment transaction includes this amount, or the operation will be rejected.
To prevent denom spam, deploying an ERC20 contract via the ERC20 module
is a **payable operation** and requires a deployment fee of **1 INJ**.
Make sure your ERC20 contract deployment transaction includes this amount,
or the operation will be rejected.
168 changes: 168 additions & 0 deletions .gitbook/developers-evm/permissioned-multivm-token.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
---
title: Permissioned MTS Tokens
description: Leverage Injective's permissions module in MultiVM Token Standard (MTS) tokens
---

## Injective's Permissions Module

The [`permissions` module](https://docs.injective.network/developers-native/injective/permissions)
is native to Injective, and allows custom management (e.g. roles) for Denoms.
This capability is extended to MultiVM Token Standard (MTS) tokens,
where you can implement those custom management rules within your EVM smart contract code.

## Why Use Permissions on MTS Tokens?

If you are tokenizing real-world assets (RWAs) using MTS on Injective,
and that underlying asset inherently requires permissions,
that is a great use case for tapping into Injective's `permissions` module.

The EVM smart contract of your MTS token simply needs to implement
an additional Solidity interface to leverage the power of the `permissions` module.

## Smart Contract Implementation

In your smart contract, import `IPermissionsHook` from `PermissionsHook.sol` and extend it.

```solidity
interface IPermissionsHook
```

This will involve implementing the `isTransferRestricted` function,
with the following signature:

```solidity
function isTransferRestricted(
address from,
address to,
Cosmos.Coin calldata amount
)
```

You may find the full file on Github:
[`PermissionsHook.sol`](https://github.com/InjectiveLabs/solidity-contracts/blob/master/src/PermissionsHook.sol)

### Smart Contract Example

Create a smart contract that extends `PermissionsHook`:

```solidity
import { Cosmos } from "../src/CosmosTypes.sol";
import { PermissionsHook } from "../src/PermissionsHook.sol";
contract RestrictedAddressTransferHook is PermissionsHook {
/*
...
*/
}
```

Add a custom implementation of the `isTransferRestricted` function.
For example, this function will allow all transfers,
except for ones involving a specific address:

```solidity
function isTransferRestricted(
address from,
address to,
Cosmos.Coin calldata amount
) external pure override returns (bool) {
address restrictedAddress = "0x...";
if (from == restrictedAddress || to == restrictedAddress) {
// this particular address is not allowed to transfer
return true;
}

// All other transfers are allowed
return false;
}
```
Comment on lines +62 to +77
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Fix Solidity syntax error in code example.

Line 68 contains invalid Solidity syntax. Address literals in Solidity must not use quotes (single or double). The current example uses "0x..." which will cause a compilation error.

🔎 Proposed fix
   function isTransferRestricted(
     address from,
     address to,
     Cosmos.Coin calldata amount
   ) external pure override returns (bool) {
-    address restrictedAddress = "0x...";
+    address restrictedAddress = 0x0000000000000000000000000000000000000000; // Replace with actual address
     if (from == restrictedAddress || to == restrictedAddress) {
       // this particular address is not allowed to transfer
       return true;
     }
 
     // All other transfers are allowed
     return false;
   }

Alternatively, for a more realistic example, consider using a state variable or constructor parameter as shown in the previous review.

🤖 Prompt for AI Agents
In @.gitbook/developers-evm/permissioned-multivm-token.mdx around lines 62 - 77,
The isTransferRestricted example uses an invalid quoted address literal; replace
the quoted string in the restrictedAddress declaration with a proper Solidity
address value (remove the quotes and use a valid 0x... hex address literal) or,
better, reference a state variable/constructor-set address (e.g., a
contract-level restrictedAddress) so the function uses a proper address type
rather than a string.


You may find a more detailed example of this on Github:
[`PermissionsHookExamples.sol`](https://github.com/InjectiveLabs/solidity-contracts/blob/master/examples/PermissionsHookExamples.sol)

## Registering Hook

To register the hook for the permissions,
you will need the following:

- Control of the same account that deployed the MTS token.
- The deployed address of the MTS token
- The deployed address of the Permissions Hook

With the above, you can create
[a JSON file similar to this one](https://github.com/InjectiveLabs/stablecoin-evm/blob/fiattoken-inj/scripts/demo/namespace.json).

Then run `injectived` for the registration,
using the same account that deployed the MTS token.

```shell
injectived tx permissions create-namespace ...
```

<Info>
Note that the MTS token and the Permissions Hook can have the same address.
That is an architectural decision that is up to you.
</Info>

### Registering Hook Example

Create a file named `register-hooks.json`, with the following content:

```jsonc
{
"denom": "erc20:0x...", // <-- EVM address of the MTS token
"evm_hook": "0x...", // <-- EVM address of the permissions hook
"role_permissions": [
{
"name": "EVERYONE",
"role_id": 0,
"permissions": 10
}
],
"actor_roles": [
]
}
```

Be sure to replace the value of the
`denom` and `evm_hook` fields with the appropriate values.

<Info>
Delete all comments as well, so that the file is valid JSON.
</Info>

Then run the following command:

```shell
injectived tx permissions create-namespace register-hooks.json [flags]
```

Note that this is merely one specific way to define permissions hooks on an MTS token.
There are multiple variations.
For additional details on this step, including other variations, refer to
[How to Launch Permissioned Assets](https://docs.injective.network/developers-native/injective/permissions/04_launch_permissioned_asset).

## Reference Implementation

A more complete example that demonstrates the use of permissioned MTS tokens
for a stable coin is also available.

This example involves a permissions hook which prevents transfers
when the token is paused, and also maintains a blacklist of addresses.

```solidity
function isTransferRestricted(
address _from,
address _to,
Cosmos.Coin calldata /* _amount */
) external view returns (bool) {
if (fiatToken.paused()) {
return true;
} else if (fiatToken.isBlacklisted(_from) || fiatToken.isBlacklisted(_to)) {
return true;
}

return false;
}
```

See [`PermissionsHook_Inj.sol`](https://github.com/InjectiveLabs/stablecoin-evm/blob/fiattoken-inj/contracts/v2/PermissionsHook_Inj.sol).
1 change: 1 addition & 0 deletions .gitbook/docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,7 @@
},
"developers-evm/evm-equivalence",
"developers-evm/multivm-token-standard",
"developers-evm/permissioned-multivm-token",
"developers-evm/wrapped-inj",
"developers-evm/precompiles",
"developers-evm/bank-precompile",
Expand Down