PlayTrain

年
2023–24
作家
Toshi
媒体
Ethereum mainnet、ENS(NameWrapper)
契約
0x77b01feb029aba23fd3fcfd448b942fdbd437464 — Etherscan で見る

面ではなく、線で考えてみた。

NFT の誕生によって、さまざまなコレクションが生まれ、オンラインで目に見えるものになった。そこでは分散が思い描かれ、点として存在していた個々の存在が、NFT を通じて面になる。

今回は、NFT の領域で個人のアイデンティティの象徴である ENS を使い、一つのコレクションを線として構想した。

tsh.eth が先頭を走る列車に、どうぞ乗ってほしい。

midorikanemitsu.onigiriman1998.yujiym.pon24.haukun.maishumai.caicaikiki.borddy.mayuzou.eotel.june29.yuhei4on6.hiraiken.hasaqui.themassage.gin-graphic.daumkuchen.niinomi.uminonaka.noriakinft.royalmilktea.rugstore.ara721.sanjrow.takawo.hnmhdk.miyakodub.kumaartcollective.bouze.proofofx.tsh.eth

末尾が tsh.eth の連結された名前と、その先頭の機関車

列車への乗り方

新しい乗車は、いまは受け付けていない。乗りたい人は、連絡してほしい。

https://x.com/toshiaki_takase

乗車の状況を確かめる

https://app.ens.domains/midorikanemitsu.onigiriman1998.yujiym.pon24.haukun.maishumai.caicaikiki.borddy.mayuzou.eotel.june29.yuhei4on6.hiraiken.hasaqui.themassage.gin-graphic.daumkuchen.niinomi.uminonaka.noriakinft.royalmilktea.rugstore.ara721.sanjrow.takawo.hnmhdk.miyakodub.kumaartcollective.bouze.proofofx.tsh.eth

OpenSea

https://opensea.io/assets/ethereum/0xd4416b13d2b3a9abae7acd5d6c2bbdbe25686401/52639631494175751531733296501683006532342588420061402245205873236250032378898

Technical Note

このプロジェクトでは、Ethereum Mainnet 上の ENS(Ethereum Name Service)と、その NameWrapper を使っている。ENS は ETH のウォレットアドレスを、人が読みやすい形にする。さまざまなレコードを結びつけることもでき、自分のアイデンティティを表せる。

さらに ENS には、URL のサブドメインにあたる「Subname」というものがある。このプロジェクトでは、この Subname を重ねていくことで「電車ごっこ」をしている。

Subname は NameWrapper 上にすでにあるノードからしか生成されず、NFT として配られるときには、そのノードの保有者に送られる。そのため参加者は、あらかじめ自分の ENS を wrap しておく必要がある。

tsh.eth の後ろにサブネームが車両のように連なり、一つの名前が一本の線になる図

tsh.eth の後ろにサブネームが車両のように連なり、一つの名前が一本の線になる図

Contract

Etherscan で検証済みのソース。

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

import "./INameWrapper.sol";
import "./ENS.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol";
import "https://github.com/ensdomains/name-wrapper/blob/master/contracts/BytesUtil.sol";

contract PlayTrain is Ownable, ERC1155Holder {
    using BytesUtils for bytes;

    INameWrapper nameWrapper;

    uint256 public index;
    address public resolver;
    bool public isMintable;

    mapping(bytes32 => bool) public isMinted;
    mapping(uint256 => bytes32) public indexToNode;
    mapping(uint256 => address) public indexToOwner;

    function setEnsData(address _nameWrapper, address _resolver, bytes32 _startNode) external onlyOwner {
        nameWrapper = INameWrapper(_nameWrapper);
        resolver = _resolver;
        indexToNode[0] = _startNode;
    }

    function getOnTheTrain(bytes32 yourNode, string memory label) public {
        require(isMintable, "PlayTrain: not mintable");
        require(!isMinted[yourNode], "PlayTrain: Already minted");
        bytes memory name = nameWrapper.names(yourNode);
        (bytes32 labelhash, ) = name.readLabel(0);
        require(labelhash == keccak256(bytes(label)), "PlayTrain: label is not correct");

        nameWrapper.setSubnodeRecord(
            indexToNode[index],
            label,
            address(this),
            resolver,
            0,
            0,
            0
        );

        bytes32 nextParentNode = _makeNode(indexToNode[index], labelhash);
        (address owner, ,) = nameWrapper.getData(uint256(yourNode));

        uint256 nextIndex = ++index;
        indexToOwner[nextIndex] = owner;
        indexToNode[nextIndex] = nextParentNode;
        isMinted[yourNode] = true;

        if(index > 2){
            uint256 tokenid = uint256(indexToNode[index - 2]);
            nameWrapper.safeTransferFrom(address(this), indexToOwner[index - 2], tokenid, 1, "");
        }
    }

    function setMintable(bool _isMintable) external onlyOwner {
        isMintable = _isMintable;
    }
    
    function _makeNode(bytes32 node, bytes32 labelhash) private pure returns (bytes32) {
        return keccak256(abi.encodePacked(node, labelhash));
    }

    function getIndex() external view returns(uint256) {
        return index;
    }

    function getNode(uint256 _index) external view returns(bytes32) {
        return indexToNode[_index];
    }

    function transfer(address from, address to, uint256 id) external onlyOwner {
        nameWrapper.safeTransferFrom(from, to, id, 1, "");
    }

    function onERC1155Received(
        address operator,
        address from,
        uint256 id,
        uint256 value,
        bytes memory data
    ) public override(ERC1155Holder) returns(bytes4) {
        return ERC1155Holder.onERC1155Received(operator, from, id, value, data);
    }
}

Read / Write

Ethereum mainnet の契約を直接読み、自分のウォレットから呼び出せる。読むだけならウォレットは要らない。

PlayTrain0x77b01FeB029abA23FD3FCfD448B942FDBd437464

Etherscan の Read ContractEtherscan の Write Contract

Exhibitions

Texts

  1. Fakewhale LOG

    Blockchain As A New Medium For Art

    Mimi NguyenEN

  2. Right Click Save

    On Curation: Yusuke Shono

    Yusuke ShonoEN

  3. MASSAGE MAGAZINE

    Proof of X – Blockchain As A New Medium For Art / 空間との対話から生まれた10の視点

    Yusuke ShonoJA

Links

作品一覧へ戻る