---
# System prepended metadata

title: ERC3664

---

ERC3664
===

docs : https://github.com/DRepublic-io/EIPs/blob/master/EIPS/eip-3664.md

ERC3664是一個可以新型的NFT協議，可以在NFT上面附加attribute，attribute當中包含了數值，同時也可以為attribute擴充各種功能，例如更新、升級、轉移等等，讓NFT運用更靈活

例如可在**Sword**這個NFT上添加**Power**，並把Power這個attribute設定為10

ERC3664也支持複合式的NFT(Synthetic)，此時的NFT分為**token(主體)** 跟 **subToken(配件)**，兩種NFT都可以是分開的，也可以合在一起成為一個個體，且支援ERC721的所有功能

# 概念圖

此為ERC3664的運作方式，下面在說明功能皆會以此做例子，方便理解

![](https://i.imgur.com/8evD7KC.png)


# Attribute

上圖中Name Sex Level Power都屬於attribute

必須`attach()`進Token中，並設定數值(amount)儲存在`attrBalances`中，不過在`attach()`之前**必須先調用ERC3664中的`_mint()`來鑄造attribute**

被`_mint()`出來的attribute可以重複`attach()`在不同的token上，不過不能重複`attach()`在同個token上

## Updatable

可以去調整attribute在token中的數值，有`increase` `decrease` `remove`三個function

以圖片的例子來說就是可以去增加跟刪減Sword的Power數值

## Upgradable

在attribute中增加一個Level的數值，Upgradable可以去調整attribute的level，可以用來做裝備的升級

這邊要特別注意attribute中的amount跟level是分開的數值

如果確定attribute要添加level這個擴充功能的話，`_mint()`的地方需用`mintWithLevel()`取代

圖片中的Level就是需採用Upgradable

## Evolvable(待補充)

多加了個**status**在attribute中，顯示這個token的attribute是normal還是broken，並多加了個`repair` `evolutive`來更改狀態

## Transfer

可將token上的attribute轉移到其他token上

# Synthetic

一個NFT會變成複合式的，圖片中Role跟Sword這兩個Token就是Synthetic token，Role屬於token(主體)，Sword屬於subToken(配件)，subToken會被存在`mapping(uint256 => SynthesizedToken[]) public synthesizedTokens`這個mapping中

```solidity
struct SynthesizedToken {
    address owner;
    uint256 id;
}
```

**若沒有Separate**，那麼在交易的時候，是視做一個Token一併被轉移過去的，Role跟Sword都是屬於新買家的

**若有先Separate**，那拆離出來的Role跟Sword就是單獨的兩個Token，你可以選擇單獨把Sword交易出去，留Role在身上，甚至可像上圖那樣，買了一個Axe來combine進Role，取代原本Sword的地方


> 注意！ Separate跟Combine不是內建的function，需自己實作功能，可以藉由變更synthesizedTokens來達到Separate跟Combine的功能

## Primary Attribute

用來表示一個物品主要屬性為何，以上圖例子來說Role的primary attribute可以設定為**Main**，Sword的primary attribute可以設定為**Equipment**，以便在Separate跟Combine有一套可以遵循的邏輯

例如
- 兩個primary attribute同為**Main**的token不可以執行Combine
- 假捨最多只能有一個**Equipment**，那麼如果synthetic token中已經有**Equipment**，那麼想要再combine一個**Equipment**就會發生錯誤

# 問題

最後是我在使用的時候觀察到的一些可能較不方便的地方，如果這些設計是為了某些目的而製作的，那也歡迎大家告訴我

- **attribute沒有嚴格的規範**，documentation雖然指出attribute有六種功能，但是其實可以混用，例如角色性別或出生日期這些不可變的attribute，跟其他可變attribute的操作function其實都一樣，因此若沒有自己標註跟去做檢查，很有可能會去改到這些不可變的attribute

- **setPrimaryAttribute()沒有一套規則或規範可以遵循**，跟上一點類似，只能自己標註跟做檢查，若使用原本裡面setPrimaryAttribute()，可以隨意做設定，例如把Sword的primary attribute設定為**Main**，甚至設為**Power**都可以，且原本的是public，也沒設定權限，因此任何人可以隨意調用更改

- **token的圖片問題**，在 separate 跟 combine 後，token的外觀勢必要有所改變，但是在合約內沒辦法執行組圖的功能，只能自己另架後台來組圖，並把產生的URI放入到合約中

- `separate` `combine` 需要自己實作，在實作可能要注意`ERC721.ownerOf(subTokenId)`的問題，我這邊參考的做法是
    - 若還沒separate --> 先將subToken暫存在合約地址中，而不是自己的地址中
    - 若separate之後 --> 就將subToken從合約transfer到自己的地址
    - 若不這樣做，假設subToken還沒從synthetic token中separate出來，但因為在ERC721中有標記**你有這個subToken**(ownerOf(subTokenId) = yourAddress)，所以你可以直接交易出去，這樣就跟功能需求不符合，

- `increase` `decrease`沒有設定調用權限

# 總結

ERC3664目前的功能較針對遊戲去做特化，Evolvable跟Upgradable尤為明顯，網路上資料過少，因此有些功能是結合documentation跟原始碼推測出來，若有人有其他想法，或覺得我哪寫錯的，歡迎跟我說

實作範例參考

Legoot: https://polygonscan.com/address/0xdb35a85748e3fe59d1cc3d039d03ddeeab8875e1#code

everyday-avatar:
https://github.com/everydayavatar/everyday-avatar

Pet-game:
https://github.com/LI-YONG-QI/Pet-Game















