Simple NFT Example (1)

김현학·2024년 6월 15일
0

speedrun-ethereum

목록 보기
1/5

https://speedrunethereum.com/challenge/simple-nft-example

다음 기본 내용들을 숙지하고 있음을 가정한다.
ref-1 // ref-2

🎟 Simple NFT Example

Scaffold-eth의 기본 사항을 배우기 위해 간단한 NFT를 만들어 보세요. HardHat을 사용하여 스마트 계약을 컴파일하고 배포합니다. 그런 다음 중요한 Ethereum 컴포넌트와 훅이 가득한 React 템플릿을 사용합니다. 마지막으로, 친구들과 공유할 수 있는 공개 네트워크에 NFT를 배포합니다! 🚀

  1. Install dependencies yarn install
  2. Start a local instance of a blockchain yarn chain
  3. Deploy contract locally yarn deploy
  4. Start frontend yarn start

준비를 마친 이후 실행한 dApp에서는 다음과 같은 화면을 확인할 수 있다. 상태가 유지되는 것을 방지하기 위해 incognito window (시크릿창)으로 실행한다.

Gas & Wallets

  1. 사용 중인 계정의 연결을 해제하고 재연결한다.

  2. Brave 브라우저에서는 다음과 같은 UI를 제공한다. Burner Wallet을 연결하면, 최소한의 스펙을 가진 익명의 계좌를 생성하여 연결한다.

  1. Local Faucet에서 localhost test funds로부터 ETH를 자유롭게 공급받을 수 있다. 생성된 wallet의 주소를 Destination으로 입력하면 된다.

    • yarn chain을 실행한 터미널에서는 트랜잭션을 포함하여, 실행되는 함수들을 다.
      ...
      eth_sendTransaction
        Transaction:         0xa0e82de60ae9ab5f16df389236701f1e645b1e6ec04f01ddc0ca4e829cdf9c3a
        From:                0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266
        To:                  0xab6c5086e09a0b6b0b801394f129275cf4472d50
        Value:               3579.3579 ETH
        Gas used:            21000 of 30000000
        Block #4:            0x4ca435df9bad686a4431bddbee9aac0771f50aa33515654b5b6518dda3554ea1
    • Block Explorer에서는 테스트넷에서의 트랜잭션 기록을 UI로 제공한다.

Minting

  1. Mint NFT 또한 Transaction을 수반하기 때문에, 이에 필요한 gas가 충분한지 확인해야 한다.

    • Block Explorer에서 각 트랜잭션의 상세 정보를 확인할 수 있다.

    • 소비되는 가스의 양은 네트워크의 현재 상황과 수요에 따라 동적으로 변동된다. 실제 거래에서는 사용자들은 이러한 가스 가격을 설정하여 거래의 우선 순위를 결정할 수 있다.

    1.447298621 Gwei
    1.392738142 Gwei
    1.344602637 Gwei
    1.263613049 Gwei
    • 내부적으로는 Scaffold-ETH를 기반으로 deployedContracts.ts 파일을 자동 갱신한다. 이 파일에는 실행 가능한 함수의 인터페이스를 명시하는데, 이에 대한 구현으로 @openzeppelin 라이브러리를 사용한 것을 확인할 수 있었다. 이는 이더리움의 토큰 표준인 ERC20, ERC721 인터페이스를 구현하는 계약 함수를 제공한다.
  2. 새로운 브라우저 창을 실행하여 계정을 만들고, NFT를 다른 계정으로 이동시킬 수 있다. transferFrom 함수를 통해 이동된 NFT 데이터는 다음과 같다. 이 데이터가 어떤 과정으로 활용 가능하도록 변하는지 살펴보자.

0x23b872dd000000000000000000000000ab6c5086e09a0b6b0b801394f129275cf4472d500000000000000000000000001c415d68f299241654177ff4d16ed7ad0f757ea20000000000000000000000000000000000000000000000000000000000000002
  1. transferFrom 함수는 다음 계약의 내용을 따른다.

    @openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol

참고: Solidity 계약 살펴보기

transferFrom & Transfer

// openzeppelin/contracts/token/ERC721/ERC721.sol

  /**
    * @dev See {IERC721-transferFrom}.
    */
function transferFrom(address from, address to, uint256 tokenId) public virtual override {
    //solhint-disable-next-line max-line-length
    require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved");

    _transfer(from, to, tokenId);
}

이는 일종의 래퍼 함수로서, tokenId를 활용하여 msgSender에 대한 인가 과정을 진행한다. 내부적으로는 _transfer을 호출하며, 여기서는 함수의 인자로 전달된 from에 대한 토큰 인가 과정을 진행한다. 이 두 가지가 구분된 것은 토큰에 대해 적절한 권한이 없는 주체가 함수를 실행하는 것을 차단하기 위함으로 보인다.

// @openzeppelin/contracts/token/ERC721/ERC721.sol

/**
    * @dev Transfers `tokenId` from `from` to `to`.
    *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
    *
    * Requirements:
    *
    * - `to` cannot be the zero address.
    * - `tokenId` token must be owned by `from`.
    *
    * Emits a {Transfer} event.
    */
function _transfer(address from, address to, uint256 tokenId) internal virtual {
   ...
}

마치며

우선 기본적으로 동작을 확인/검증하는 수준에서 실습을 진행했다. 이후 포스팅에서는 실제로 이 dApp을 배포하기 위한 준비하고, 그 과정 중 알아야 하는 개념들을 정리하여 소개한다.

0개의 댓글