LP-6525
FinalLRC-3525 Semi-Fungible Token
Token standard for financial instruments with slot-based fungibility
LP-3525: LRC-3525 Semi-Fungible Token
Abstract
LRC-3525 defines a semi-fungible token where tokens are grouped into "slots" - tokens in the same slot are fungible with each other, but tokens in different slots are not. Ideal for financial instruments like bonds, options, and structured products.
Motivation
Financial instruments often have:
- Fungibility within class: All bonds of same series are equal
- Non-fungibility across class: Different series are distinct
- Fractional quantities: Holdings can be divided
LRC-3525 provides:
- Slot-based grouping for instrument classes
- Fractional token values within slots
- Rich metadata per slot and token
Specification
Core Interface
interface ILRC3525 is ILRC165, ILRC721 {
// Events
event TransferValue(
uint256 indexed fromTokenId,
uint256 indexed toTokenId,
uint256 value
);
event SlotChanged(
uint256 indexed tokenId,
uint256 indexed oldSlot,
uint256 indexed newSlot
);
// Value operations
function valueDecimals() external view returns (uint8);
function balanceOf(uint256 tokenId) external view returns (uint256);
function slotOf(uint256 tokenId) external view returns (uint256);
// Transfer value between tokens in same slot
function transferFrom(
uint256 fromTokenId,
uint256 toTokenId,
uint256 value
) external payable returns (uint256);
// Transfer value to address, minting new token
function transferFrom(
uint256 fromTokenId,
address to,
uint256 value
) external payable returns (uint256);
// Approve value transfer
function approve(
uint256 tokenId,
address operator,
uint256 value
) external payable;
function allowance(
uint256 tokenId,
address operator
) external view returns (uint256);
}
Slot Metadata
interface ILRC3525Metadata is ILRC3525 {
function slotURI(uint256 slot) external view returns (string memory);
}
interface ILRC3525SlotEnumerable is ILRC3525 {
function slotCount() external view returns (uint256);
function slotByIndex(uint256 index) external view returns (uint256);
function tokenSupplyInSlot(uint256 slot) external view returns (uint256);
function tokenInSlotByIndex(uint256 slot, uint256 index)
external view returns (uint256);
}
Implementation
contract LRC3525Token is ERC721, ILRC3525 {
struct TokenData {
uint256 slot;
uint256 value;
}
mapping(uint256 => TokenData) private _tokens;
mapping(uint256 => mapping(address => uint256)) private _valueAllowances;
uint8 public constant override valueDecimals = 18;
function balanceOf(uint256 tokenId) public view returns (uint256) {
return _tokens[tokenId].value;
}
function slotOf(uint256 tokenId) public view returns (uint256) {
return _tokens[tokenId].slot;
}
function transferFrom(
uint256 fromTokenId,
uint256 toTokenId,
uint256 value
) public payable returns (uint256) {
require(_isApprovedOrOwner(msg.sender, fromTokenId), "Not approved");
require(
_tokens[fromTokenId].slot == _tokens[toTokenId].slot,
"Slot mismatch"
);
_tokens[fromTokenId].value -= value;
_tokens[toTokenId].value += value;
emit TransferValue(fromTokenId, toTokenId, value);
return toTokenId;
}
}
Use Cases
Bond Series
// Slot = bond series, Value = principal amount
contract BondToken is LRC3525Token {
struct BondSeries {
uint256 maturityDate;
uint256 couponRate;
address paymentToken;
}
mapping(uint256 => BondSeries) public series;
function createSeries(
uint256 slot,
uint256 maturity,
uint256 coupon
) external onlyIssuer {
series[slot] = BondSeries(maturity, coupon, USDC);
}
}
Options
// Slot = strike/expiry combo, Value = number of contracts
contract OptionsToken is LRC3525Token {
struct OptionSeries {
address underlying;
uint256 strikePrice;
uint256 expiry;
bool isCall;
}
mapping(uint256 => OptionSeries) public options;
}
Rationale
- Slot-based design enables financial instrument modeling
- Compatible with LRC-721 for NFT infrastructure
- Value transfers enable fractional trades
Backwards Compatibility
This standard is fully backwards compatible with existing contracts and infrastructure. The standard is additive and does not modify existing functionality.
Security Considerations
- Slot validation prevents cross-class transfers
- Value overflow checks required
- Approval system mirrors LRC-20
References
Copyright
Copyright and related rights waived via CC0.