SFT Whitepaper 04 |Chapter 3:ERC-3525: Semi-Fungible Token Standard

The ERC-3525 Semi-Fungible Token (SFT) standard , a general-purpose standard for advanced financial instruments, has the potential to solve problems too costly to solve with ERC-721s or 1155s.

3.1 Transcending Financial Instruments

In a broad sense, financial instruments are monetary contracts between parties. All financial instruments are on some level financial contracts, and the easiest way for someone to enter into or get out of a financial contract is by purchasing or selling a financial instrument. The traditional finance sector (TradFi) is home to diverse financial instruments including bonds, commercial papers, options contracts, futures contracts, repurchase agreements (repos), swaps, ETFs, and ABS. These instruments (shown in figure 3.1) have a few things in common: they are fairly standardized, easy to use, and to a great extent, liquid.

Figure 3.1 Types of financial instruments in TradFi (Source: Wikipedia)
  • Fungible (can be fractionalized). A user should be able to split up a token denominated in $100 USD into two $50 tokens or four $25 tokens, etc. This same applies to combining tokens as well.
  • Transitive. Fractionalizing and combining tokens should not alter the token type but only the value tied to the tokens.

3.2 An Overview on Token Technology

The Ethereum whitepaper describes a currency, or a token system, as “a database with one operation.” A token or tokenized asset, in other words, is a certain type of data that can be operated upon.

Figure 3.2 Semi-Fungible Token Standard
Figure 3.3 A comparison of token standards: ERC-20, ERC-721, ERC-1155 & ERC-3525
Figure 3.4 The two-layer structure of ERC-3525’s token data

3.3 ERC-3525 Core Mechanisms

ERC-3525’s greatest innovation is the <ID, SLOT, VALUE> Triple Scalar Model. _slot/Slot Metadata enables quantitative operations for NFTs through the utilization of standard balanceOf() / _value mechanism.

3.3.1 Token Operations

The address-to-address transfer in ERC-3525 is compatible with that of ERC-721. Please refer to the code sample in 2.1.1 if needed.

/**
* @notice Transfer value from a specified token to another specified token with the same slot.
* @dev Caller MUST be the current owner, an authorized operator or an operator who has been
* approved the whole `_fromTokenId` or part of it.
* MUST revert if `_fromTokenId` or `_toTokenId` is zero token id or does not exist.
* MUST revert if slots of `_fromTokenId` and `_toTokenId` do not match.
* MUST revert if `_value` exceeds the balance of `_fromTokenId` or its allowance to the
* operator.
* MUST emit `TransferValue` event.
* @param _fromTokenId The token to transfer value from
* @param _toTokenId The token to transfer value to
* @param _value The transferred value
*/
function transferFrom(uint256 _fromTokenId, uint256 _toTokenId, uint256 _value) external payable;
/**
* @notice Transfer value from a specified token to an address. The caller should confirm that
* `_to` is capable of receiving ERC-3525 tokens.
* @dev This function MUST create a new ERC-3525 token with the same slot for `_to` to receive
* the transferred value.
* MUST revert if `_fromTokenId` is zero token id or does not exist.
* MUST revert if `_to` is zero address.
* MUST revert if `_value` exceeds the balance of `_fromTokenId` or its allowance to the
* operator.
* MUST emit `Transfer` and `TransferValue` events.
* @param _fromTokenId The token to transfer value from
* @param _to The address to transfer value to
* @param _value The transferred value
* @return ID of the new token created for `_to`, which receives the transferred value
*/
function transferFrom(uint256 _fromTokenId, address _to, uint256 _value) external payable returns (uint256);

3.3.2 “Slot” Metadata

“Slot” metadata describes the details of the abstracted properties that are hashed as the value of the _slot attribute. The value of these properties may be strings, numbers, objects, or arrays. Slot metadata can implement various classifications to describe complex DeFi assets. Here’s the JSON schema of slot metadata:

{
"title": "Token Metadata",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Identifies the asset to which this NFT represents"
},
"description": {
"type": "string",
"description": "Describes the asset to which this NFT represents"
},
"image": {
"type": "string",
"description": "A URI pointing to a resource with mime type image/* representing the asset to which this NFT represents."
},
"balance": {
"type": "BigNumber",
"description": ""
},
"slot": {
"type": "BigNumber",
"description": "The id of the slot that this token belongs to."
},
"properties": {
"type": "object",
"description": "Arbitrary properties. Values may be strings, numbers, objects or arrays."
}
}
}
function getSlot(
uint8 claimType_,
uint64[] memory maturities_,
uint32[] memory percentages_,
uint64 term_
) internal pure virtual returns (uint256) {
uint256 first = uint256(
keccak256(
abi.encodePacked(
claimType_,
term_,
maturities_[0],
percentages_[0]
)
)
);
if (maturities_.length == 1) {
return first;
}
uint256 second;
for (uint256 i = 1; i < maturities_.length; i++) {
second = uint256(
keccak256(
abi.encodePacked(second, maturities_[i], percentages_[i])
)
);
}
return uint256(keccak256(abi.encodePacked(first, second)));
}

3.4 A Paradigm Shift in Asset Transfer

ERC-3525’s token(_tokenId)-to-token(_tokenId) transfer transforms the way blockchain-based assets are transferred. To understand why it is important, let’s look at an example based on the use of bitcoin.

APPLY({ Alice: $50, Bob: $50 }, "send $20 from Alice to Bob") = { Alice: $30, Bob: $70 }
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success)
function transferFrom(uint256 _fromTokenId, uint256 _toTokenId, uint256 _value) external payable
Figure 3.5 ERC-3525’s token(id)-to-token(id) transfer

3.5 Smart Contract Visualization

ERC-3525 also utilizes metadata extensions which enhance the ways strings, numbers, objects or arrays, or images of ERC-3525 tokens are visually delivered. ERC-3525’s metadata’s JSON schema is as follows:

{
"title": "Token Metadata",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Identifies the asset to which this token represents"
},
"decimals": {
"type": "integer",
"description": "The number of decimal places that the token amount should display - e.g. 18, means to divide the token amount by 1000000000000000000 to get its user representation."
},
"description": {
"type": "string",
"description": "Describes the asset to which this token represents"
},
"image": {
"type": "string",
"description": "A URI pointing to a resource with mime type image/* representing the asset to which this token represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive."
},
"properties": {
"type": "object",
"description": "Arbitrary properties. Values may be strings, numbers, objects, or arrays."
}
}
}
{
"title": "Contract Metadata",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Contract Name"
},
"description": {
"type": "string",
"description": "Describes the contract "
},
"unitDecimals": {
"type": "integer",
"description": "The number of decimal places that the units should display - e.g. 18, means to divide the token units by 1000000000000000000 to get its user representation."
},
"properties": {
"type": "object",
"description": "Arbitrary properties. Values may be strings, numbers, object or arrays."
}
}
}

3.6 The Roadmap

October 2020: Inception of an ERC-721 compatible token standard in response to the absence of sophisticated financial instruments in DeFi

--

--

Co-founder of Solv Protocol, Co-author of ERC-3525 standard

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store