The RMRKable Explainer

A Livepaper by RMRK Association, April 2021

This is a livepaper. It will evolve with new details as we flesh out the protocol and test our proof-of-concept tooling and gain new partnerships.

Summary

RMRK (pronounced “remark”) is a protocol for adding logic to blockchains without on-chain logic (like smart contracts), inspired by colored coins from Bitcoin[1]. Custom messages get interpreted in a special way according to a predetermined specification, adding value where there technically is none. The end result is NFTs and other programmable features on a logic-less blockchain. RMRK 2.0 takes this concept further by defining multi-chain standards for evolving, reactive, multi-resource conditional NFTs that go beyond being digital-dust-gathering collectibles. The full feature set of RMRK 2.0 is described below in the RMRK 2.0 section. RMRK is currently deployed on the Kusama[2] Relay Chain but is out-of-the-box compatible with Polkadot[3] and any other Substrate-based[4] chain.

The RMRK protocol is spearheaded by the RMRK Association, a Verein in Zug, Switzerland.

Introduction

NFTs or Non Fungible Tokens are digital collectibles of varying utility. They can be any or all of the following: access passes, digital real estate rights in virtual worlds, in-game items, provenance documents for real-world goods, copyrighted multimedia, art, entire programs and websites and more.[5]

What sets them apart from collectibles of the past is their mathematically provable ownership and originality, as well as provable scarcity. When coupled with real world assets like certificates, real estate, art, and more, NFTs open up a new world of global liquidity for assets that were historically considered highly illiquid.

The Basics of NFTs

The blockchain is a world-wide database of operations, but can, in an oversimplified way, be viewed as one big Google Sheet that many thousands of computers are keeping an eye on at any given moment.

This sheet logs the balances of all users, and if Alice wants to send Bob 2 coins, she can reduce her balance by 2 and then has permission to increase someone else’s (Bob’s) by 2.

Account

Balance

Alice

5

Bob

4

Alice

3 (5-2)

Bob

6 (4+2)

The “miners” or “validators” of a blockchain (collectively: block producers, BPs), depending on block production and validation method used (Proof of Work vs Proof of Stake[6]) are rewarded by the “sheet” itself with permission to increase their own number of coins without someone else having to reduce theirs.

The BP who is first to notice a change in the sheet, repackage it in a format understandable by everyone, and for whom everyone agrees did indeed do a good job of notifying the world about a change in the sheet is the one who is rewarded.

This is how regular token balances work on almost every blockchain.

NFTs are the same thing, only the sheet layout is a little different, with more columns:

NFT ID

Image URI

Owner

Metadata URI

...

0001

image.jpeg

0x0

ipfs://ipfs/hash

...

0002

image2.jpeg

bruno.eth

ipfs://ipfs/hash

...

0003

image3.jpeg

0x568763123

ipfs://ipfs/hash

...

Each NFT collection can be thought of as a separate sheet, and each row an NFT, a single instance in that collection. For example, a collection of trading cards can be thought of as a single sheet, and each row is an instance of one of those cards belonging to this collection. Each card has a field “owner”, which denotes which blockchain address owns it. Changing this field is equivalent to “sending” the token.

NFTs can have an arbitrary number of additional columns for extra values, this is entirely up to the developer of the NFT’s smart contract. An NFT’s smart contract is an application, a script that lives on the blockchain that defines how and which values are stored in the sheet.

Current State of NFTs

Right now, NFTs exist almost exclusively on the Ethereum blockchain in any meaningful capacity. Almost every alternative chain is now also competing for relevance in this new market, but Ethereum has an undeniable advantage due to being the first mover[7] and due to having an incredibly vibrant and rich developer and user community.

The downside of NFTs on Ethereum is that right now, due to the chain’s growing popularity, the gas fees (the expenses for interacting with the blockchain) are out of the general public’s reach. As an example, a simple emote on an NFT - a feature natively supported by RMRK - would cost ~$100 on Ethereum, compared to ~$0.03 on RMRK after runtime upgrade v2031 (April 2021).

NFT Stats and Volume

The NFT ecosystem is enjoying unprecedented popularity.

March alone has seen almost 200m USD in trading volume on Ethereum, and this is without the 69 million USD Beeple sale[8], excludes the marketplace Opensea[9], and ignores the various non-Ethereum platforms out there like RMRK or Hicetnunc[10].

Even taking into account bubble mechanics and a degree of wash trading present on all these platforms, it’s undeniable that NFTs are on their way up and into the mainstream where they will completely usurp the traditional model of digital ownership and data provenance.

In short, ignoring this market is irresponsible.

NFTs in the Polkadot Ecosystem

Polkadot and Kusama are each a Relay Chain. A Relay Chain’s purpose is to connect other blockchains to each other, facilitating a sharing of features through shared security[11] via one common set of validators native to the Relay Chain.

As an example, Bitcoin could connect to Polkadot, and Acala (an upcoming DeFi chain) could connect to Polkadot. Bitcoin could then seamlessly move to Acala and be used there as DeFi collateral without chain-to-chain specific bridges.

Any new chain connecting to the existing set gains immediate access to the other already connected chains, growing the ecosystem’s feature set and market cap exponentially with every new chain connection.

Several NFT projects are in progress in the Polkadot ecosystem - from Enjin’s recent Efinity announcement[12], to dedicated NFT chains like Unique[13] and user interfaces like CSCanonizer[14], there is no shortage of NFT enthusiasm. All of these projects want to deploy on Polkadot and Kusama for the reason stated above - automatic connectability to all other incoming chains. Day-one multiverse expansion.

Kusama started out as Polkadot’s Canary network - a value-bearing proving ground for new code that would eventually (usually) reach Polkadot. With shorter governance periods and its artsy, cypherpunky attitude, Kusama evolved into its own sovereign chain with a separate community, audience, and set of excited stakeholders. Kusama was, thus, the ideal place to start building RMRK on.

RMRK

RMRK was originally designed in September 2020 when creator Bruno Škvorc[15] noticed the NFT craze heating up again on Ethereum. He felt like it would be a shame for Kusama to miss out on this movement, and decided to come up with a way to “hack” NFTs onto the chain even though it had no smart contract functionality[16].

RMRK is a protocol for adding logic to blockchains without on-chain logic (like smart contracts), inspired by colored coins from Bitcoin. Custom messages get interpreted in a special way according to a predetermined specification, adding value where there technically is none - like NFTs and other custom data formations like polls, tokens, even entire websites (see the section on Future Development and Ecosystem Growth plans for more info).

RMRK is compatible with any Substrate-based blockchain, covering hundreds of upcoming chains whether or not they have smart contracts built-in - although those that do will benefit from additional RMRK functionality.

Around November, several teams decided to implement the standard. Some time in late January, the RMRK team was officially formed in order to raise the bar of quality of RMRK implementations, and to be the dedicated steward of the protocol and its planned expansions.

At the moment of writing, a total of ~12000 NFTs have been minted and around $3 million dollars in traffic has been transacted with the RMRK protocol.

The RMRK team has been a key player in forming Kusama’s long term NFT strategy[17], building out the ecosystem, and driving adoption of Kusama-based NFTs across official and third party tools.

How RMRK Works

All Substrate-based chains have a function called remark in the core system module (this is where the name RMRK comes from). This function, when called with an argument (any arbitrary message), will “remark” this message in a block of the chain, but will do nothing else. It is a non-state-altering function, so it does not change the chain’s values - it is merely stored in the chain’s database on a local disk on all the nodes that sync to the chain. Think of remarks like graffiti on a chain.

The RMRK protocol is a set of rules and tools able to fetch and interpret these remarks in special ways. For example, the remark:

rmrk::EMOTE::1.0.0::5105000-0aff6865bed3a66b-DLEP-DL15-0000000000000001::1F389

… means:

“Using the RMRK protocol’s EMOTE interaction from the 1.0.0 version of the specification, send the emoticon 1F389 (🎉) to the NFT with the ID 5105000-0aff6865bed3a66b-DLEP-DL15-0000000000000001”.

RMRK’s tools can interpret this message and accurately display the Party Popper 🎉 emote on that particular NFT.

There are different types of messages that can be sent to the chain and interpreted by RMRK tools. All are specified and exemplified in the RMRK Specs repository[18] and briefly covered in the following section.

Current Capabilities

At the moment, two entities exist in RMRK’s NFT specification: Collections and NFTs. Every NFT must be part of a collection, even if it’s a one-off (in that case, a client UI should default to a “user’s collection”). This requirement exists to maintain compatibility between RMRK NFTs and internft.org as well as previous Eth-based standards like ERC1155 and ERC721.

There are six possible interactions with these entities:

RMRK Downsides

Not having smart contracts does not come without tradeoffs. Two notable downsides exist in the RMRK protocol’s current version.

  1. Slow synchronization

Because of the append-only graffiti-way used by RMRK, for a client to be aware of the most recent state of the RMRK universe of NFTs, that client has to be aware of all the RMRK entries from the past in order to squash them all into a single point of truth at its final block. This is only possible with Archive nodes (those that keep the full history of the chain) and the sync process is very slow (up to a day when done from scratch). Regular automated appendable dumps are recommended, and the RMRK team offers such public endpoints, even going as far as regularly hosting a dump of pre-processed data on IPFS.

  1. Buy race condition

Were two people to buy the same NFT that is listed for sale in the same block, both transactions would go through and the seller would be paid twice, but only the first buyer (as ordered in the block) would become the new owner. This happens because there is no way to automatically refund a purchase without smart contracts. This can be mitigated by monitoring for unfinalized blocks and requests in-flight, and preventing interaction with pending items on the UI level. This is the approach used in Kanaria - see below.

In March 2021, the RMRK team built and deployed a tech demo and in-production test of their toolkit which serves to minimize these downsides. Notably, the RMRK team has created:

Kanaria

In March 2021, the RMRK Association launched the Kanaria platform. The Kanaria platform is a tech demo and in-production test of the tools built to protect users and developers from the above downsides.

The Kanaria project began with a pre-claim process during which interested parties could claim Kanaria digital eggs in exchange for KSM. This first phase functioned as a seed round for the team’s independence and had very strict limits per-account in order to keep the launch and distribution as fair as possible. This part of the project was built to test the NFT minting, emoting, and sending functionality, and worked as expected.

The second stage of the Kanaria project started on April 4th. During this time the claiming process is open to the public, and is meant to test double-buy protection. So far, the system has proven successful against these bugs with minor exceptions that were quickly fixed.

The third stage is the activation of P2P trading functionality on April 16th, allowing egg-owners to list their eggs for sale and buy them from others. With sufficient protections against double-buy in place, we believe the system is mature enough to handle the demand, but will monitor it closely.

The fourth stage is the hatching phase, which is scheduled to occur on June 1st. The hatching will produce unique birds, some with randomly generated art only, and others with dual-art which the owner can flip between (this functionality is reserved for the top 100 birds by serial number and top 25 most emoted-on birds[19]).

Kanaria’s Randomness

TODO: Detailed traits and probabilities post + egg types post

This was originally explained in How it all Works[20]. This section expands on that post.

NFTs built on top of RMRK (including Kanaria digital eggs) can be emoted on. It's possible to send them reactions as on social media.

Emotes can have an effect on the type of bird one gets when hatching the egg. There are two main types of traits, cosmetic and functional.

Cosmetic Elements

The birds will all have a common base form, with several different sub-elements that can vary:

Certain emoticon groups can have specific effects on a specific sub-element of the illustration. The groups are as follows (note that the list is not exhaustive or final and will evolve over time):

Group 1: Mood - effect on EYES, BEAK/MOUTH

"Face" emoji define the main sentiment, mood, emotion.

These will affect the bird's mood, its facial expression. This aspect of the bird cannot be changed - it affects the bird’s permanent look.

Group 2: Mutagens - effect on BODY, EYES, BEAK/MOUTH

These define the primary 'mutagen', distinctive physical properties. A bird could have properties from other animals or be influenced by nature's forces.

These will affect the body and head. Additionally, the body could have a different color based on the average color of all emoji on the egg. If, for example, one sends their egg all purple emoji, the bird is skewed (but not guaranteed!) towards having purple skin.

This aspect of the bird cannot be changed - it affects the bird’s permanent look.

Group 3: Accessories - effect on WINGS, WINGS-DECAL, NECK, HAND, HEADWEAR, FOREGROUND, FEET

Holding items. Jewellery pieces. Eating food.

These are NFTs in their own right. This means that upon hatching a bird can get other NFTs, and the owner might end up with more than one NFT in their possession. The accessories will vary by rarity - common, uncommon, rare, epic, legendary, unique, and special (promo items). The rarer an egg, the better the chances of this bird getting a rarer accessory.

Group 4: Environment - effect on BACKGROUND, FOREGROUND

These affect the bird's environment.

This can affect what the environment looks like, but will also have influence on the foreground. While it is possible to have a surfboard in a dojo, it is less likely than another, more reasonable combo.

This aspect of the bird cannot be changed - it affects the bird’s permanent look.

Group 5: Misc - various effects

"Meta" attributes which could influence other parameters like randomness modifiers, bird colors (purple symbols, etc.). Flags could add some national attributes. Special flags (pirate flag, rainbow) could also have a different effect.

Some of these will result in new accessories (tradeable NFTs), while others will be permanent alterations to the bird’s look.

Probabilities

It's important to note that emotes DO NOT guarantee an outcome. They only affect probabilities to get a certain trait.

For example, say one wants their bird to hold a tennis racket 🎾. A tennis racket might have a default chance of 0.001%. The owner collects 120 tennis rackets on the bird, and if we apply the modifier of 0.001% to each tennis racket emote, this bird now has 0.121% chance to get it.

The chances will not scale linearly. i.e. 100000 🎾 won't guarantee a racket. Instead, every trait has a maximum probability (e.g. if we set 🎾 to max 5%, then 100000 will be the same as 5000 rackets).

The important thing to remember is that emotes only influence chances, they do not guarantee anything other than the possibility of getting custom art[21].

You also cannot know what effect an emote might have. Each 💧 might add 0.001% chance for the bird to made out of water, but a 0.005% chance for the bird to be standing in the rain. Different traits will have different chances - some will be legendary, some will be rare, some common.

If an egg is among the top eggs who got a particular emote, it has a higher chance of scoring a legendary trait related to that emote. As an example, if there are 3 eggs with 10, 20, and 30 💧 respectively, and say that a body made out of water has a 0.001% chance (legendary) then the egg with 30 💧 has the most chance to get this legendary trait - its base chance is raised by a certain percentage so that the "water body" trait is now 0.1% probable on that egg instead of 0.001%.

Trait System

Every bird will have a certain number of trait sockets. If you've ever played the Diablo games, you'll understand the reference.

Super Founder egg birds have 5 sockets, with one pre-filled with the 0.5% Rev trait (0.5% revenue share of the team in perpetuity). They are also guaranteed a legendary (12 in 9999 eggs can possibly have this) tradable prop.

Founder egg birds have a minimum of 2 sockets, up to 5, depending on how many from this category are claimed, and one will be pre-filled with the 0.1% Rev trait. They are also guaranteed an epic (95 of 9999 eggs can possibly have this) tradable prop.

Rare egg birds have a minimum of 2 sockets, up to 4 if all are claimed. 50 of them will have one trait socket pre-filled with the 0.1% Rev trait. They are also guaranteed a rare tradable prop (950 of 9999 eggs can possibly have this). All rare eggs will also have flock pairings with one or more LE eggs (see below).

Limited edition egg birds have a minimum of 1 socket, up to 4 traits if all are claimed. 15 of them will have one trait socket pre-filled with the 0.1% Rev trait. Some Limited Edition eggs will have a special trait that can only be rolled if the same address also holds a matching Rare egg (they are in a flock). We will reveal these flock pairings in an upcoming post.

Other traits one can randomly get during the hatching:

But rather than box ourselves into a corner with trying to think up all the traits we'll possibly launch in the future, we're filling the empty sockets with a "free trait" Trait. This means that you will be able to replace this trait with any trait we publish in the future. Most will be accessible to all, some will be limited to the certain rarity of a bird (e.g. only rares or higher). All eggs except the LEs will have all their slots filled with the "free trait" Trait, except LEs - these will have 1/2 of the total number of achieved trait sockets, minimum of 1 (e.g. if 6000 are claimed, that's 2 trait sockets, and one will be filled, the other empty).

Functional Trait Replacement

You will not be stuck with all of the traits you get or equip. The traits are NFTs too, only they are not transferable. In order to make room for another functional trait, you must CONSUME (burn) an existing one. This system allows you to continuously upgrade and evolve your bird over time with additional platform-specific bonus functionality that will only become apparent as our ecosystem grows.

This is where the birds will get their TRUE long term power. This is what makes them revolutionary utility-bearing NFTs, never before seen elsewhere.

RMRK 2.0

Kanaria is a tech-demo and testing ground for RMRK 2.0 functionality as well. All the functionality listed above is only possible with the innovations we’re bringing into the world with RMRK 2.0. The innovations consist of new RIPs (RMRK Improvement Proposals) that define new features in the specification. They are:

Nested NFTs

NFTs that can own other NFTs. Think in-game characters and their inventories. NFTs can be minted and equipped into other NFTs which can then gain alternative renders and functionalities based on what they “own”. This can also be abstracted into user made collections, where a basket of NFTs can be for sale rather than listing them all one by one.

Child NFTs are given instructions like “SEND” or “CONSUME” by proxy, through their parent NFT.

This RIP is documented and being discussed here: TODO

Conditional Rendering and Reactive NFTs

Conditional rendering is the ability of a certain NFT to display different visuals depending on certain conditions. Imagine a digital painting of a moon which when the condition of having 50x 🚀 sent to it adds a rocket onto the moon.

Another example is being in control of an NFT that is placed somewhere, like a billboard in a virtual world. The owner can put the billboard’s space up for sale and anyone who buys it can send the billboard’s texture into the billboard NFT. The owner can then tell the billboard to EQUIP this texture, thus displaying it.

Yet another example is something as banal as checking if the current block number is even or odd and having the NFT display something different based on that. A collection could exist which represents real-world coordinates as each of its NFTs. Each such “land” NFT could then also EQUIP another NFT to show there - from 3D models to 2D floor textures and tiles. Other on-chain parameters and values can also be extracted, parametrized, and used within the conditional rendering logic of the NFTs.

This RIP is documented and being discussed here: TODO

Multi-Resource NFTs

An NFT can have multiple resources defined on it.

An NFT of a 3D model can have a resource that is a 3D model file, a resource that is a high resolution image, and a resource that is a thumbnail image. Depending on the context it is being loaded into, a different resource will be loaded. With the RMRK plugin, a 3D tool like Sketchup or 3DS Max can load the 3D file directly, listing on Opensea can show the high res image in single-item view, and on the search results page the thumbnail can automatically be shown.

This RIP is documented and being discussed here: TODO

NFTs as DAOs

NFTs are now interactive, and can emit actions, send items, equip them, change state, and more. Some of these might be unique and too expensive for individuals to hold in their entirety. This is why in RMRK 2.0 - the version we’ll re-launch on Unique Network (see below under Future Plans) - we will have NFTs as DAOs. Each NFT will be breakable into a predetermined number of fungible tokens where these tokens can be used to issue DAO-like commands to the NFT.

Example: a digital billboard in the Metaverse costs $1’000’000, and was minted a fractionality of 5000 (max 5000 fungible tokens). 5000 token holders then come up with $200 each to each own one $BB token. Pepsi, Coca Cola, and the r/cryptocurrency subreddit all express interest in advertising on this billboard, mint their billboard face NFT (as per Conditional Rendering and Reactive NFTs documented above), and send it to the billboard as a child NFT. The $BB holders then vote on which face to equip by using their tokens to issue a collective EQUIP command.

Another example is an in-game character preparing for battle, let’s call him $BOB, fractionalized to 10000 $BOB tokens. A Twitch streamer controls the character, and they outsource the character’s loadout (inventory setup) to the viewers. In real-time, the viewers propose inventory loadouts and vote on them. Once the loadout has been voted on by the majority of the tokenholders, the character is equipped and proceeds into battle. The skirmish is viewed by all.

Mint-to-recipient

Right now in order to send an NFT to someone, it is necessary to mint it first, then send it. This has two downsides: one, it requires two transactions. Two, it makes non-transferable NFTs a non-starter, since they have to be minted to be transferred and cannot be transferred if they are non-transferable. This RIP fixes this by allowing the minting directly to an address or even into a specific NFT.

In addition, the “Mint and Equip” interaction is also being added which will allow an NFT’s owner to at the same time mint an NFT’s sub-NFT and equip it, again only using a single transaction.

This RIP is documented and being discussed here: TODO

RMRK Token

In order to further secure the independence of the RMRK team and to be able to decentralize the governance over the entire multi-chain protocol that RMRK aims to become, the Association is launching a governance token under the ticker $RMRK.

We aim to completely decentralize governance of the protocol within the next three years, such that the organization owns a minority of the tokens in their balance and treasury combined (under 20% total).

A total of 10 million (10’000’000) tokens will be minted, matching Kusama’s KSM supply[22]. The tokens will be minted on the common-good chain Statemint[23].

The tokens will be distributed according to a mechanism we call the Fairdrop.

The Fairdrop

X% of all tokens will be airdropped to everyone who had an egg or a bird in their address on June 2nd, as a gesture of thanks to all our earliest supporters.

If SF are Super Founder eggs, F are Founder, R are rare, and LE are Limited edition, then the value X is calculated as: X = (SF*150 + F*100 + R*20 + LE*2) / 46350

This means it’s possible for 100% of the tokens to be distributed if all eggs are claimed.

In other words, the value of tokens per egg is:

The remainder of the tokens if all eggs are not claimed will be distributed according to the following formula:

The RMRK Association’s intention is to fully decentralize governance over the RMRK platform and all its affiliated products, UIs, tools, and chain deployments within three years of launching the token.

Token Utility

The RMRK token has several utility functions pre-determined, and more being planned out:

Ecosystem Expansion and Future Development

Immediate plans for RMRK include an expansion across the Kusama ecosystem. Notably:

Aside from launching across the entire ecosystem of both Kusama and Polkadot for other teams to easily deploy their NFT infrastructure on, our long term plans include:

Competition

A common question is “Who is your competition?”

The answer is consistently “there is none”. In its post-NFT stage, RMRK will focus on ultimate UX - the area of Web3.0 we feel is sorely lacking. If another project does it better than we do, we all win - what’s easier for the users draws the users in, and the whole ecosystem benefits.

In the NFT context, we don’t see competition either - there’s Enjin’s Efinity, there’s all the NFT ports that are coming to Moonbeam, and there’s even the Parity-made Statemint system-level chain which they say will support NFTs one day, but none of these are in production (we are) and none of these have innovated nearly as much as we have on the above functionality as described in the RMRK 2.0 section. It is our hope and expectation that alternative NFT platforms will work with us to adopt our innovations, integrate them into their offerings and improve the ecosystem as a whole for all of its users. We will do our best to actively work with all projects in the ecosystem to expand our reach and standardize access to these new primitives.

Code

Official accounts and contact info


[1] https://en.bitcoin.it/wiki/Colored_Coins 

[2] https://www.youtube.com/watch?v=Kke1FmIAYfo 

[3] https://www.youtube.com/watch?v=5NAn-MnRJtk 

[4] https://www.youtube.com/watch?v=--7t596sw7E 

[5] https://www.crowdcast.io/e/hello-decentralization/41 

[6] https://bitfalls.com/2018/04/24/whats-the-difference-between-proof-of-work-pow-proof-of-stake-pos-and-delegated-pos/ 

[7] Technically, Bitcoin’s colored coins are the first mover in this context, but this failed to get any traction

[8] https://www.theverge.com/2021/3/11/22325054/beeple-christies-nft-sale-cost-everydays-69-million 

[9] https://dappradar.com/ethereum/marketplaces/opensea 

[10] https://www.hicetnunc.xyz/ 

[11] https://wiki.polkadot.network/docs/en/learn-security#shared-security 

[12] https://enjin.io/blog/efinity 

[13] https://uniquenetwork.io/ 

[14] https://kusama.polkassembly.io/post/313 

[15] https://github.com/swader

[16] Relay chains like Polkadot and Kusama must remain light to be able to process the data from connecting chains (parachains). This prevents the deployment of resource intensive logic (like smart contracts) on these chains.

[17] https://kusama.polkassembly.io/post/303 

[18]https://github.com/rmrk-team/rmrk-spec 

[19] https://app.subsocial.network/2425/kanaria-art-contest-and-timeline-alteration-11008 

[20] https://app.subsocial.network/@rmrkapp/kanaria-how-it-all-works-12172 

[21] https://app.subsocial.network/2425/kanaria-art-contest-and-timeline-alteration-11008 

[22] https://www.coingecko.com/en/coins/kusama

[23] https://medium.com/polkadot-network/statemint-generic-assets-chain-proposing-a-common-good-parachain-to-polkadot-governance-d318071b238

[24] https://uniquenetwork.io/ 

[25] https://github.com/rmrk-team/rmrk-tools