owned this note
owned this note
Published
Linked with GitHub
---
###### tags: `Blockchain-Club` `Feral File` `bridge`
---
# Feral File NFT Migration Design
###### tags: `Blockchain-Club` `Feral File` `bridge` `swap` `migration` `ethereum`
## Overview
This document describes our process to migrate a Bitmark NFT to an Ethereum (mainnet) NFT using ERC721.
## Flow
```mermaid
sequenceDiagram
autonumber
Feral File->>+Bitmark: Scan bitmark assets through api
Bitmark-->>-Feral File: Bitmark / Asset / Provenance
Feral File->>Feral File: Generate the IPFS directory<br> includes metadata and provenance
Feral File->>+IPFS: Push to IPFS
IPFS-->>-Feral File: Return ipfs id
Feral File->>+Bitmark: Send bitmark to zero address
Bitmark-->>-Feral File: Done
Feral File->>+Ethereum: Invoke token swap with ipfs id and bitmark id
Ethereum-->>-Feral File: A new token added to a user
```
## Bitmark vs Ethereum Chain Asset Structure
In bitmark blockchain, we have assets and bitmarks(issuances). In Feral File, we create assets for each artwork and issue editions in bitmarkss.
```
+-------+ +---------+
| Asset | <-- | Bitmark |
+-------+ +---------+
(Artwork) (Editions)
```
In ERC721 design, we create a contract for an exhibition. Artist can register its artwork into it. Based on the registered artwork, we mint edition tokens.
```
+------------+ +----------+ +----------+
| Exhibition | <-- | Artworks | <-- | Editions |
+------------+ +----------+ +----------+
```
## Feral File Smart Contracts
Our latest contracts are here: [Feral File Exhibition contract]( https://ropsten.etherscan.io/address/0x14cb7e6c96cd0a352d1bf0d2bc4955cdb5c3c9a7#code) (Etherscan)
### Contract Data
```solidity=
struct Artwork {
string title;
string artistName;
string fingerprint;
uint256 editionSize;
address royaltyAddress;
}
struct ArtworkEdition {
uint256 editionID;
string ipfsCID;
}
// Exihibition information
string public exhibitionTitle;
uint256 public maxEdition;
uint256 public secondarySaleRoyaltyBPS;
uint256 public MaxRoyaltyBPS;
// Move this metadata off-chain
string description; v
string medium; v
address artist; x
uint256 bitmarkID;
uint256 artworkID;
uint256 editionNumber; v
string prevProvenance;
address public curator; v
string public curatorNotes; v
uint256 public basePrice;
```
#### Cost Table
| Function | Gas | TX | Contract |
| ----------- | ----------- | ----------- | ----------- |
| (livenet) Create Artwork | 167,593 | [link](https://rinkeby.etherscan.io/tx/0x563771fbc7f3f74c0da59f54939f48bd42ea0ba3b1ca70ef69baaa84a47ea1d1) | [Contract](https://rinkeby.etherscan.io/address/0x204e6fd8f3231b0497b9c1411d30b35a938486e2)
| (livenet) Swap edition | 343,598 | [link](https://rinkeby.etherscan.io/tx/0x7f0f7ed15c44fd2716ab3c99abb49d9a40dcf11060d58c34160f91ae37c420e2) | [Contract](https://rinkeby.etherscan.io/address/0x204e6fd8f3231b0497b9c1411d30b35a938486e2)
### Exhibition specific methods
`createArtwork` is to register artworks. The`fingerprint` will be used to generate the id of an artwork. It can not be duplicated.
```solidity=
// Create an artwork for an exhibition
function createArtwork(
string memory _fingerprint,
string memory _title,
string memory _description,
address _artist,
string memory _medium,
uint256 _editionSize
) public onlyAuthorized {}
```
`mintArtwork` is for minting new editions for an artwork. Whereas, the `swapArtworkFromBitmarks` is to move the existent artwork from Bitmark blockchain to the ERC721 system.
It takes 300,000 gas for swapping an artwork, and takes 2,680,000 for swapping 10 artworks.
```solidity=
// Swap an existent artwork from bitmark to ERC721
function swapArtworkFromBitmarks(
uint256 _artworkID,
uint256 _bitmarkID,
uint256 _editionNumber,
address _owner,
string memory _prevProvenance,
string memory _ipfsCID
) public onlyAuthorized {}
```
The following function is to mint a new artwork for new exhibitons.
```solidity=
// Mint artwork editions.
function mintArtwork(
uint256 _artworkID,
string[] memory _ipfsCIDs
) public onlyAuthorized {}
```
:::info
Since the length of CID is greater than 32, we can only use string for inputing CIDs. Use string costs more gas since it is an dynamic type.
:::
The following functions help users query their artwork tokens.
```solidity=
// Return total artwork counts of the exhibition
function totalArtworks()
public
view
virtual
returns (uint256)
{}
// Return the token identifier for the `_index`th artwork
function getArtworkByIndex(uint256 index)
public
view
virtual
returns (uint256)
{}
// Return the total minted editions of an artwork
function totalEditionOfArtwork(uint256 artworkID)
public
view
returns (uint256)
{}
// Return editionID of an artwork by index
function getArtworkEditionByIndex(uint256 _artworkID, uint256 _index)
public
view
returns (uint256)
{}
```
## Get the Bitmark NFT's provenance
Here are the steps:
1. Use Bitmark.FullProvenance to get history
2. Summarize the provenance into the following format:
```json
{
"bitmark_provance": [
{
"owner": "ecZ6DenzyjZ1u5vbFEg9Gki91eJduf4hjKCiBdBCen5ghSk7Wh",
"inblock": "39857",
},
{
"owner": "fqDMrr8VESHfAwxxKwkDHmprQZRrnp7Kvsc5L5uG9qHtDgmiTp",
"inblock": "59557",
}
]
}
```
4. Attach the whole JSON string to IPFS metadata of the token which are going to migrate.
## Incorporate the IPFS address link into the reference parameter of erc 721.
At the time we perform `swapArtworkFromBitmarks`, we will attach the IPFS cid of summarized metadata followed the standard provided by Opensea. The contract takes the ID to generate the tokenURI for each tokens. For example,
```
https://ipfs.bitmark.com/ipfs/QmYBfVBh9U5huzY72GucDdwvp35yhrWfgAdiUUfnAZPd7f/metadata.json
```
Here is an example of summarized metadata:
```json
"attributes": [
{
"trait_type": "Medium",
"value": "video"
},
{
"trait_type": "Artist",
"value": "Duyen Bui"
},
{
"display_type": "number",
"trait_type": "Edition Size",
"value": "30"
},
{
"trait_type": "Exhibition",
"value": "The Real Real"
}
],
"description": "Video (color, sound)\n1280 × 1280 pixels\n30 seconds",
"external_url": "https://feralfile.com/artworks/steering-pixels-k6p?sort=0",
"image": "https://ipfs.bitmark.com/ipfs/QmUqMhPndTg7bPjaCitRqJLGVTc4vvQQ9rXXBo38qeANqg",
"name": "Blue Veil #2",
"timestamp": "2021-08-27 12:32:55.225725 +0800 CST m=+2.301450084"
}
```