INSK-1 : Tokens (Outdated)

Will be soon Migrated to INSK-4. Discussion - https://github.com/evm-ink/docs/issues/1

Problems

By the time of writing, there are already a lot of proposed standards like BRC-20, ORC-20, DERC-20, ESC-20, and many more. Each of them tried to add something new using the capabilities of the JSON.

Bad naming

It seems you can change the first letter, which would be enough for people to think it is new. In reality, it just creates confusion. People seem to confuse the protocol name with a tick name, and here is a bit of data. I have all the inscriptions for Ethereum and BNB and a bit of Polygon chains, and here is a list of the most popular tokens by protocol.

ProtocolNumber of inscriptions (any operation)

erc-20

256547

bep-20

60300

nrc-20

55430

prc-20

41983

You will not find what you seek if you search for these protocols by name. ERC-20 and BEP-20 are existing protocol names for contract standards. People replace first later depending on the chain (ERC-20 for Ethereum, BEP-20 for BNB, and PRC-20 for polygon). You might think it is okay, but if you try to index it, how would you know the standard behind it? Do they follow BRC-20, or do they follow ORC-20? They have different rules on what to consider a valid mint operation. And you can not tell the difference because...

The deployment operation looks the same.

You can not confidently state the standard behind them because they all use the same JSON with the same fundamental value pairs to deploy. This will cause many problems because it will be up to the index to choose what is behind, meaning you might see your inscription on one indexer and not see it on another. We want consistency. Now, look at how many inscriptions use the protocol that at least has some documentation.

ProtocolNumber of inscriptions (any operation)

orc-20

136

derc-20

11

brc-20

1109

esc-20

98

There are at least 1000 times fewer inscriptions with documented protocol than with undocumented.

Transfer semantics

To transfer the balance, you must first inscribe the transfer operation and then transfer the new inscription.

Hard to extend

How would you extend it? How can I pause the mint or make the mint function accept money (in case you want to sell tokens)? How do I swap tokens or let someone approve spending my tokens?

General idea

Since we are going to follow the rules proposed on the indexer page, we have the ability to make inscriptions using contracts. We will use contracts. We will not limit ourselves to JSON because we are NOT on Bitcoin, but we will keep the idea of having metalanguage. We will make a contract to do all the inscriptions for us. The contract will identify tokens and inscribe the data we give it. With this approach, we don't need to pass the protocol and ticket JSON key in every operation.

The most important rule: The contract will permanently inscribe all operations to itself. This way, we can focus more on the meta language and not bother about from and to addresses for the transaction.

Tokens always have 18 decimals.

Operations

Deployment

In the constructor, {"op":"deploy","s":"INSK"} This JSON is supposed to be inscribed where

KeyMeaning

op

Operation

s

Token symbol

Transfer

Contract should inscribe

{
   "op": "transfer",
   "f": "1234567890123456789012345678901234567890",
   "t": "1234567890123456789012345678901234567890",
   "a": "12341234"
}
KeyMeaning

op

Operation

f

Sender address (case insensitive)

t

Destination address (case insensitive)

a

Amount to send in desimal format

Approve

This operation lets you approve a valid spender for your balance.

{
   "op": "approve",
   "s": "1234567890123456789012345678901234567890",
   "o": "1234567890123456789012345678901234567890",
   "a": "12341234"
}
KeyMeaning

op

Operation

s

Spender address (case insensitive) which can spend your balance.

o

Owner address (case insensitive) whose balance will be spent

a

Amount to approve in desimal format

Transfer from

Like transfer, it lets you spend the balance, but here on someone's behalf. Will inscribe JSON with the same fields, except the address can be different from yours.

Protocol detection and extension

We have a perfect standard for it. We support ERC165 by adding one will hold.

interface ERC165 {
    function supportsInterface(bytes4 interfaceID) external view returns (bool);
}

Basic token example

Given this interface code below, with the interface ID is 0x83e349d5

interface InscribedToken {
    function transfer(address to, uint256 amount) external;
    function approve(address spender, uint256 amount) external;
    function transferFrom(address from, address to, uint256 amount) external;
}

Our ERC165 function will look like this.

function supportsInterface(bytes4 interfaceID) external view returns (bool) {
    return interfaceID == 0x83e349d5;
}

Extended token example

Suppose we want to make our token mintable, charged per mint, and have a cap for total mint. We can write interfaces for each type of extension

interface MintableToken {
//Interface ID == 0x1d16302d
    function maxMint() external view  returns (uint256);
    function mintPrice() external view  returns (uint256);
}

interface CappedToken {
//Interface ID == 0x355274ea
    function cap() external view  returns (uint256);
}

Here is an example of an inscribed token with a cap(21000000) that can be minted(free mint and 1000 per mint).

contract Token is MintableToken, CappedToken {
...
    function cap() external view returns (uint256) {
        return 21000000 * 10 ** 18;
    }

    function maxMint() external view returns (uint256) {
        return 1000 * 10 ** 18;
    }

    function mintPrice() external view returns (uint256) {
        return 0;
    }
    
    function supportsInterface(bytes4 interfaceID) external view returns (bool) {
    return interfaceID == 0x83e349d5 || interfaceID == 0x355274ea || interfaceID == 0x1d16302d;
}

Mime type

Why not just use JSON? Because we might want to update other endings later. We might want to use GRPC or Message pack later.

We propose to use application/vnd.insc.token+json for any token-related operations.

Examples

Create contract and pre-mint 1M to itself. Simply inscribe these 2 in the constructor.

application/vnd.insc.token+json,{"op":"deploy","s":"INSK"}
application/vnd.insc.token+json,{"op":"mint","o": "1234567890123456789012345678901234567890","a":"1000000000000000000000000"}

The code examples provided here are for educational purposes only and should not be used directly in production environments.

Please note that this approach has not been ratified or approved by the broader community. Consequently, any implementation or deployment carried out in this manner may not be recognized as a valid or standard procedure. It's essential to consult and adhere to established protocols and best practices recognized and endorsed by the relevant professional or technical community.

Last updated