LoginSignup
1
1

More than 1 year has passed since last update.

合成できるNFT「Marge」のContract(solidity)をのぞいてみる

Last updated at Posted at 2022-01-26

"Marge"とは?

pak氏というデジタルアーテイストが作成したNFTのプロジェクトです。
普通のNFTと違って面白い特徴は、NFT同士が合体(結合=マージ)するという点です!
そう結合すると言われてもイメージがしづらいですよね(笑)

具体的には、MargeのNFTを1つ所持していて2つ目を入手したときに、2つのNFTが結合するようにコントラクトが組まれています。そして、結合する度に表示される白い点が大きくなっていきます
opensea_marge.png

NFTの点の大きさが、それぞれ若干異なるのがわかりますでしょうか?(笑)
タイトル「m(数字)」の数字が大きいほど、白い点が大きく、結合回数が多いということみたいですね。

スマートコントラクト

ethscanのリンクは以下です。
https://etherscan.io/address/0xc3f8a0f5841abff777d3eefa5047e8d413a1c9ab#code

では、実際のコードを見ていきます。

結合

結合は以下のfunction _margeによって行われているようです。
結合と言っても、具体的にここで行っている処理は、2つのNFTの白い点の大きさの比較、結合後の大きさを決定するといった内容です。

//Marge.sol
function _merge(uint256 tokenIdRcvr, uint256 tokenIdSndr) internal returns (uint256 tokenIdDead) {
    require(tokenIdRcvr != tokenIdSndr, "Merge: Illegal argument identical tokenId.");

    uint256 massRcvr = decodeMass(_values[tokenIdRcvr]);
    uint256 massSndr = decodeMass(_values[tokenIdSndr]);
    
    uint256 massSmall = massRcvr;
    uint256 massLarge = massSndr;

    uint256 tokenIdSmall = tokenIdRcvr;
    uint256 tokenIdLarge = tokenIdSndr;

    if (massRcvr >= massSndr) {

        massSmall = massSndr;
        massLarge = massRcvr;

        tokenIdSmall = tokenIdSndr;
        tokenIdLarge = tokenIdRcvr;
    }

    _values[tokenIdLarge] += massSmall;

    uint256 combinedMass = massLarge + massSmall;

    if(combinedMass > _alphaMass) {
        _alphaId = tokenIdLarge;
        _alphaMass = combinedMass;
        emit AlphaMassUpdate(_alphaId, combinedMass);
    }
    
    _mergeCount[tokenIdLarge]++;

    delete _values[tokenIdSmall];

    _countToken -= 1;

    emit MassUpdate(tokenIdSmall, tokenIdLarge, combinedMass);

    return tokenIdSmall;
}

転送

function _margeをどこで呼び出しているかしているかというと、NFTを転送するfunction _transferのようです。
既にMargeを持っている人に転送されると、先ほどの_margeによって白い点が小さい方のNFTはdeadTokenIdはaddress(0)に転送、つまりバーンされるようです。

//marge.sol
function _transfer(address owner, address from, address to, uint256 tokenId) internal notFrozen {
    require(owner == from, "ERC721: transfer of token that is not own");
    require(to != address(0), "ERC721: transfer to the zero address");
    require(!_blacklistAddress[to], "Merge: transfer attempt to blacklist address");
//---略---
            } else {
                uint256 sentTokenId = tokenId;

                // compute token merge, returning the dead token
                uint256 deadTokenId = _merge(currentTokenId, sentTokenId);

                // logically, the token has already been transferred to `to`
                // so log the burning of the dead token id as originating ‘from’ `to`
                emit Transfer(to, address(0), deadTokenId);

                // thus inferring the alive token
                uint256 aliveTokenId = currentTokenId;
                if (currentTokenId == deadTokenId) {
                    aliveTokenId = sentTokenId;
                }

白い点の大きさ

先ほどの_margeの中に以下のようなコードがあります。

    _values[tokenIdLarge] += massSmall;

_values[]の中に保管されているようですね。このコードのもっと前に

// Mapping token ID to mass value.
mapping (uint256 => uint256) private _values;

mappingで定義されていました。(やっとmappingの使い方がわかってきました汗)

おわりに

NFTは単純なアートだけでなく、スマートコントラクトによってさまざまな機能を持たせることが出来て夢いっぱいですね。

Twitterを探索していたらフルオンチェーンやフェニックスNFTなるものまで、いっぱい面白いNFTのプロジェクトが見つかるので、今後も勉強がてら紹介していきたいと思います。
ご覧いただきありがとうございました。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1