EthChainId chainId = web3j.ethChainId().send();
System.out.println(chainId.getChainId());

현재 체인의 chain Id를 알 수 있다.

BigInteger blockNumber = web3j.ethBlockNumber().send().getBlockNumber();
System.out.println(blockNumber);

현재 블럭의 번호를 알 수 있다.

 

String contractAddress = "${contractAddress}";

Credentials cutromerCreds = Credentials.create("${privateKey}");
TransactionManager cutomerTokenTxManager = new RawTransactionManager(
        web3j, cutromerCreds, 80001);

Event eventContract = com.event.watcher.contract.Event.load(contractAddress, web3j, cutomerTokenTxManager, new DefaultGasProvider());
try {
    eventContract.test().send();
} catch (Exception e) {
    throw new RuntimeException(e);
}
WebSocketService wss = new WebSocketService("{RPC_URL}", false);
try {
    wss.connect();
} catch (ConnectException e) {
    throw new RuntimeException(e);
}
Web3j web3jWss = Web3j.build(wss);

EthFilter ethFilter = new EthFilter(DefaultBlockParameterName.LATEST, DefaultBlockParameterName.LATEST, "{contractAddress}");
org.web3j.abi.datatypes.Event event = new org.web3j.abi.datatypes.Event("Log", Arrays.asList(new TypeReference<Address>(true) {
}, new TypeReference<Utf8String>() {
}));
String topicData = EventEncoder.encode(event);
ethFilter.addSingleTopic(topicData);
web3j.ethLogFlowable(ethFilter).subscribe(e -> {
    System.out.println(e);
}, error -> {
    System.out.println(error);
});
try {
    Thread.sleep(10000000);
} catch (InterruptedException e) {
    throw new RuntimeException(e);
}

'코딩이야기 > blockchain' 카테고리의 다른 글

_mint vs _safeMint 차이점  (1) 2022.12.23
SmartContract 프레임워크 선택  (1) 2022.12.13
ERC20 토큰 발행 및 ERC721 NFT 발행  (1) 2022.11.21

 

 function _mint(address to, uint256 tokenId) internal virtual {
        require(to != address(0), "ERC721: mint to the zero address");
        require(!_exists(tokenId), "ERC721: token already minted");

        _beforeTokenTransfer(address(0), to, tokenId);

        _balances[to] += 1;
        _owners[tokenId] = to;

        emit Transfer(address(0), to, tokenId);

        _afterTokenTransfer(address(0), to, tokenId);
    }

둘의 차이는 safeMint의 경우 mint 하려고 하는 address가 실제로 존재하는지 체크 하는 로직이 구현되어있다.

_safeMint가 실행 되면 토큰이 전송된 후에 _checkOnERC721Received 함수가 호출되고 정상적으로 이루어지지 않을경우에는 트랜잭션을 되돌리게 됩니다.

   function _safeMint(
        address to,
        uint256 tokenId,
        bytes memory _data
    ) internal virtual {
        _mint(to, tokenId);
        require(
            _checkOnERC721Received(address(0), to, tokenId, _data),
            "ERC721: transfer to non ERC721Receiver implementer"
        );
    }
    
    
    function _checkOnERC721Received(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) private returns (bool) {
        if (to.isContract()) {
            try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {
                return retval == IERC721Receiver.onERC721Received.selector;
            } catch (bytes memory reason) {
                if (reason.length == 0) {
                    revert("ERC721: transfer to non ERC721Receiver implementer");
                } else {
                    assembly {
                        revert(add(32, reason), mload(reason))
                    }
                }
            }
        } else {
            return true;
        }
    }

 

 

'코딩이야기 > blockchain' 카테고리의 다른 글

Web3j  (2) 2023.10.24
SmartContract 프레임워크 선택  (1) 2022.12.13
ERC20 토큰 발행 및 ERC721 NFT 발행  (1) 2022.11.21

Remix 

온라인 Solidity 용 IDE 이며 디버깅 및 테스트를 제공하며, 간단한 Smart contract 를 작성하는데 최적이다.

빠르고 간단한 테스트에 최적이지만 복잡한 로직에는 부적절하다.

Truffle - 스마트 컨트랙트 개발 프레임워크

솔리디티 코드 개발을 로컬에서 보다 편리하게 개발 할 수 있도록 지원해주는 프레임워크이다.

Truffle 은 web3.js 라이브러리를 채택하고 있다.

 

truffle 단점으로 Verify 가 자동으로 지원되지 않는다라고 한다.

최근에는 Hardhat 이라는 프레임워크를 많이 사용하는것 같다. 

HardHat

위에 개발 도구들에 비해 보다 전문개발 도구이며, 작성, 컴파일, 테스트, 배포 등을 가능함

turffle 에 비해 내부적으로 가상 이더리움 네트워크를 제공해주어 별도의 ganache가 필요하지 않는다.

Verify 를 자동으로 지원한다.

Typechain  플러그인을 지원하여 .sol 파일을 타입스크립트로 된 artifact 를 만들어준다.

Hardhat 은 Ethers.js 라이브러리를 사용한다.

 

 

개발환경 셋팅하기

Intellij 에 Soildity 플러그인 설치

자신이 원하는 위치에 비어있는 프로젝트 폴더 생성 후 soildity 파일을 생성합니다.

Hardhat설치

  • node는 기존에 설치가 되어있다는 전제로 진행한다.
  • 설치 버전 2.12.2

https://hardhat.org/guides/project-setup.html

 

Hardhat | Ethereum development environment for professionals by Nomic Foundation

Hardhat is an Ethereum development environment. Compile your contracts and run them on a development network. Get Solidity stack traces, console.log and more.

hardhat.org

npm(Node Package Manager) 이란?

  • node.js의 모듈 관리를 하기 위한 도구
npm install --save-dev hardhat
npx hardhat

 

npx hardhat

 

 

아래와 같이 hardhat 설치 및 solidity를 이용한 SmartContract 작성준비가 끝났습니다. 

열심히 코딩을 시작합니다.

 

'코딩이야기 > blockchain' 카테고리의 다른 글

Web3j  (2) 2023.10.24
_mint vs _safeMint 차이점  (1) 2022.12.23
ERC20 토큰 발행 및 ERC721 NFT 발행  (1) 2022.11.21

openzeppelin을 이용하여 ERC20 기반의 토큰을 Sepolia 테스트넷에 발행 및 ERC721 기반의 NFT 발행하는 작업을 진행해보겠다.

 

yarn add @openzeppelin/contracts

openzeppelin 을 설치하고 싶었지만.... node의 버전 문제가 생겼고 다운그레이드를 진행하였다.

 

내 node --version 은 19.0.1 이고 hardhat이 지원하는 18.0.0.으로 변경하고자 node 버전 관리 모듈인 n을 이용하려고 한다.

 

 

npm install n
sudo n 18.0.0 

n 설치후 노드 버전을 변경하고 싶었으나 

installed된 노드 위치와 active된 노드의 위치가 달라서 노드 버전을 계속 새로 설치하고 버전을 변경해도 active된 노드 버전이 변경되지 않는다고 한다...

 

드럽게 안된다...

실패...

node, nvm, npm 다 지우고 다시 한다...


ERC721 NFT를 발행해보자...

 

ERC721 용 폴더를 생성합니다.

 

npx hardhat

npx 를 이용해서 hardhat 을 설치합니다.

hardhat을 설치하게 되면 위에 사진처럼 샘플 프로젝트가 생성됩니다.

NFT를 생성하기 위해 openzeppelin을 설치 합니다.

npm install @openzeppelin/contracts

 

 

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";

contract Artwork is ERC721 {
    uint256 public tokenCounter;
    mapping (uint256 => string) private _tokenURIs;

    constructor(
        string memory name,
        string memory symbol
    ) ERC721(name, symbol) {
        tokenCounter = 0; //초기 민트하는 nft의 횟수를 0으로 지정합니다.
    }

    function mint(string memory _tokenURI) public {
        _safeMint(msg.sender, tokenCounter);
        _setTokenURI(tokenCounter, _tokenURI);

        tokenCounter++;
    }

    function _setTokenURI(uint256 _tokenId, string memory _tokenURI) internal virtual{
        require(
            _exists(_tokenId),
            "ERC721Metadata : URI set of nonexistent token"
        );
        _tokenURIs[_tokenId] = _tokenURI;
    }

    function tokenURI(uint256 _tokenId) public view virtual override returns(string memory){
        require(
            _exists(_tokenId),
            "ERC721Metadata: URI set of nonexistent token"
        );
        return _tokenURIs[_tokenId];
    }
}

//코드 설명

 

 

 

 

npx hardhat compile

npm install --sava-dev chai

스마트컨트랙트의 경우 자바와 다르게 한번 배포하면 수정은 불가하기에 테스트 코드가 굉장히 중요하다.

 

/test 디렉토리 안에 테스트 파일을 작성합니다. 

const { expect } = require('chai');
const { ethers } = require("hardhat")

describe("Artwork Smart Contract Tests", function() {

    this.beforeEach(async function() {
        // This is executed before each test
        const Artwork = await ethers.getContractFactory("Artwork");
        artwork = await Artwork.deploy("Artwork Con", "ART");
    })

    it("NFT is minted successfully", async function() {
        [account1] = await ethers.getSigners();

        expect(await artwork.balanceOf(account1.address)).to.equal(0);

        const tokenURI = "https://opensea-creatures-api.herokuapp.com/api/creature/1"
        const tx = await artwork.connect(account1).mint(tokenURI);

        expect(await artwork.balanceOf(account1.address)).to.equal(1);
    })

    it("tokenURI is set sucessfully", async function() {
        [account1, account2] = await  ethers.getSigners();
        const tokenURI_1 = "https://opensea-creatures-api.herokuapp.com/api/creature/1"
        const tokenURI_2 = "https://opensea-creatures-api.herokuapp.com/api/creature/2"

        const tx1 = await artwork.connect(account1).mint(tokenURI_1);
        const tx2 = await artwork.connect(account2).mint(tokenURI_2);

        expect(await artwork.tokenURI(0)).to.equal(tokenURI_1);
        expect(await artwork.tokenURI(1)).to.equal(tokenURI_2);

    })

})

테스트 결과

 

npx hardhat test

 

.env 파일을 이용해서 환경변수 방식을 사용하기 위해 dotenv를 설치합니다.

 

npm install dotenv

npm install @nomiclabs/hardhat-etherscan

 

hardhat.config.js 파일을 수정합니다.

require("@nomiclabs/hardhat-waffle");
require("@nomiclabs/hardhat-etherscan")
require("dotenv").config();

task("accounts", "Prints the list of accounts", async (taskArgs, hre) => {
  const accounts = await hre.ethers.getSigners();

  for (const account of accounts) {
    console.log(account.address);
  }
});

task("deploy", "Deploy the smart contracts", async(taskArgs, hre) => {

  const Artwork = await hre.ethers.getContractFactory("Artwork");
  const artwork = await Artwork.deploy("Artwork Contract", "ART");

  await artwork.deployed();

  await hre.run("verify:verify", {
    address: artwork.address,
    constructorArguments: [
      "Artwork Contract",
      "ART"
    ]
  })

})

module.exports = {
  solidity: "0.8.4",
  networks: {
    mumbai: {
      url: "https://matic-testnet-archive-rpc.bwarelabs.com",
      accounts: [
        process.env.PRIVATE_KEY,
      ]
    }
  },
  etherscan: {
    apiKey: process.env.POLYGONSCAN_KEY,
  }
};

 

 

 

npx hardhat deploy --network mumbai

deploy를 진행하는데 오류가 나네요... hardhat-waffle 모듈을 찾을수 없는 문제입니다.

npm install @nomiclabs/hardhat-waffle

실패....

Reason: The Etherscan API responded that the address 0x43aAB3Bf55ee50dCE2b3894393C3948394A47cba does not have bytecode.

이런 오류가 발생하면서 작동하지 않는다... 온갖 방법을 다 써도 안된다...


임시해결

위에 오류가 난 이유로는 etherscan api 자체의 오류로 다들 비슷한 오류를 겪고 있다. 하지만 나는 해당오류랑 또다른 오류에 봉착한 상태이다….

이를 임시로 컨트랙트의 주소를 로그로 찍은뒤 검증하는 부분에 로그로 찍은 주소를 입력했다.

생성한 컨트랙트의 주소를 확인할수 있고 TestNet Scan에서 확인할 수 있다.

https://mumbai.polygonscan.com/

 

TESTNET Polygon (MATIC) Blockchain Explorer

PolygonScan allows you to explore and search the Polygon blockchain for transactions, addresses, tokens, prices and other activities taking place on Polygon (MATIC)

mumbai.polygonscan.com

ipfs metadata 값을 이용해야합니다.

저는 pinta라는 ipfs지원 하는 친구를 사용하였습니다.

https://app.pinata.cloud/pinmanager

 

Pinata

Effortless IPFS File Management

app.pinata.cloud

metamask 연결한 뒤 mint 영역 URI 부분에 ipfs 형태의 이미지 주소를 입력후 Write 를 누르게 되면 아래 사진과 같이 발행이 가능합니다.

https://testnets.opensea.io

 

 

 

 

'코딩이야기 > blockchain' 카테고리의 다른 글

Web3j  (2) 2023.10.24
_mint vs _safeMint 차이점  (1) 2022.12.23
SmartContract 프레임워크 선택  (1) 2022.12.13

+ Recent posts