관리 메뉴

Leo's Garage

Smart Contract 개발 환경 구축 본문

BlockChain/Smart Contract

Smart Contract 개발 환경 구축

LeoBehindK 2022. 3. 30. 22:00
728x90
반응형

Truffle : Solidity 개발 환경 - 배포, 테스트 등등

Ganache : Ethereum Blockchain Local 환경


https://github.com/DonationMarketNFT/SmartContractForBapp

GitHub - DonationMarketNFT/SmartContractForBapp: smart contract for Bapp

smart contract for Bapp. Contribute to DonationMarketNFT/SmartContractForBapp development by creating an account on GitHub.

github.com

git repository clone 후 아래 명령어 입력

$ npm install
$ cd node_modules/truffle
$ npm install solc@0.5.6
$ cd -
$ ln -s node_modules/truffle/build/cli.bundled.js truffle
$ export PATH=`pwd`:$PATH

위와 같이 하시면 Truffle 환경은 구성이 끝나게 됩니다.
Truffle로 바로 BaoBob 이나 cypress server로 배포할 수 있지만, 우선 저희는 SmartContract를 Test하고 검증해야 하기 때문에 Ganache를 이용하여 로컬 환경에서 배포하도록 하겠습니다.

Truffle과 Ganache 연동


아래 링크에서 Ganache를 설치하고 실행합니다.
https://trufflesuite.com/ganache/
Ganache를 실행하면 아래와 같은 Network ID와 RPC Server 정보가 있습니다.

보시면 Network ID는 1337이고 RPC Server는 HTTP://127.0.0.1 Port는 7545 입니다.
혹시 위와 설정이 다르다면, 가장 오른쪽 톱니바퀴를 누르시고 아래 화면에서 변경해주세요.


위와 같이 설정 후에 truffle-config.js를 아래와 같이 변경해줍니다.

// truffle-config.js
module.exports = {
  networks: {
    klaytn: {
      host: "127.0.0.1", // rpc 주소
      port: 7545, // port name
      //from: "0x75a59b94889a05c03c66c3c84e9d2f8308ca4abd", // 현재는 테스트이기 때문에 필요없지만 추후 배포시에는 account 주소 입력 필요
      network_id: "1337", // 로컬 네트워크 id -> 추후에 메인넷으로 변경 후 배포
      //gas: 20000000, // 트랜잭션 가스 한도
      //gasPrice: 25000000000, // Baobab의 gasPrice는 25 Gpeb입니다
    },
  },
  compilers: {
    solc: {
      version: "0.5.6", // 컴파일러 버전을 0.5.6로 지정
    },
  },
};

Smart Contract 배포하기

우선 배포하고자 하는 Smart Contract를 contracts 폴더 내에 작성합니다.
그 이후에 migrations/1_initial_migraion.js에서 아래와 같이 작성해줍니다.

const Migrations = artifacts.require("./Migrations.sol");
const KlaytnGreeter = artifacts.require("./KlaytnGreeter.sol"); // 작성한 smart contract
module.exports = function (deployer) {
  deployer.deploy(Migrations);
  deployer.deploy(KlaytnGreeter, "Hello, Klaytn"); // 이와 같이 작성해주자
};

위와 같이 하나의 migration js file에 넣어도 되고, 혹은 migrations 폴더 내에 prefix 숫자를 넣어서 2_klaytn_greeter.js 와 같이 폴더를 생성하여 별도로 배포 코드를 작성해도 됩니다.

배포 전의 Ganache를 살펴보면 아래와 같습니다.

총 10개의 지갑이 있고 각각 100이더씩 있는 것을 볼 수 있습니다.

위와 같이 블록도 0개이고 Transaction도 없습니다.

이제 terminal에 아래와 같이 명령어를 넣어봅시다.

truffle migrate --network klaytn// klaytn은 truffle-config.js에서 설정한 network name이다.
 ⚡ ⚙ root@gimdaun-ui-MacBook-Pro  ~/klaytn   main ●  truffle migrate --network klaytn

Compiling your contracts...
===========================
> Everything is up to date, there is nothing to compile.


Starting migrations...
======================
> Network name:    'klaytn'
> Network id:      1337
> Block gas limit: 0x6691b7


1_initial_migration.js
======================

   Replacing 'Migrations'
   ----------------------
   > transaction hash:    0x06b66a084e478939099f01725186bb065e12e56415fe2f4a49d6df47506b199c
   > Blocks: 0            Seconds: 0
   > contract address:    0x6133DA5EB2d6Fb4CBb208D7788491212651BbBa6
   > block number:        1
   > block timestamp:     1644563019
   > account:             0x111CF6AD702092D6D6103F8d18f41006A869A335
   > balance:             99.99619978
   > gas used:            190011
   > gas price:           20 gwei
   > value sent:          0 ETH
   > total cost:          0.00380022 ETH


   Replacing 'KlaytnGreeter'
   -------------------------
   > transaction hash:    0xad84658fe1919822cac7b5c270bfefca8a5d376a8aa5f7941e7be070cd670f21
   > Blocks: 0            Seconds: 0
   > contract address:    0x4FB897FFe54D903ccBd2DE14765A948Bca5235Df
   > block number:        2
   > block timestamp:     1644563019
   > account:             0x111CF6AD702092D6D6103F8d18f41006A869A335
   > balance:             99.9917825
   > gas used:            220864
   > gas price:           20 gwei
   > value sent:          0 ETH
   > total cost:          0.00441728 ETH


   > Saving migration to chain.
   > Saving artifacts
   -------------------------------------
   > Total cost:           0.0082175 ETH


Summary
=======
> Total deployments:   2
> Final cost:          0.0082175 ETH

위와 같이 log가 나오면서 로컬 환경에 배포가 됨을 알 수 있습니다.
이제 Ganache에 가서 확인해보면

위와 같이 smart contract 배포로 인해 Gas가 사용되어 이더가 소모된 부분과 블록이 쌓인 부분, transaction이 발생한 부분을 모니터링 할 수 있습니다.
smart contract의 동작만을 검증하기 때문에 이더리움 로컬 네트워크 상에서 진행해도 문제 없을 것을 판단됩니다.

truffle console 사용하기


정상적으로 서버에 Smart Contract가 배포가 되었다면, truffle console을 이용하여 배포된 smart cotract내에 함수나 변수를 확인할 수 있습니다.

$ truffle console

배포가 정상적으로 된 상태에서 상기 명령어를 치면 아래처럼 terminal 창이 변경됩니다.

$ truffle console
truffle(ganache)>

이제 여기서 아래와 같이 입력하면

truffle(ganache)> NFTSimple.deployed().then(function(instance){it=instance})
undefined

undefined라는 msg가 나오게 되는데 it라는 변수에 NFTSimple smartcontract instance가 들어오게 됩니다.
이 때 Console창에 아래와 같이 입력하면

truffle(ganache)> it
TruffleContract {
  constructor: [Function: TruffleContract] {
    _constructorMethods: {
      setProvider: [Function: setProvider],
      new: [Function: new],
      at: [AsyncFunction: at],
      deployed: [AsyncFunction: deployed],
      defaults: [Function: defaults],
      hasNetwork: [Function: hasNetwork],
      isDeployed: [Function: isDeployed],
      detectNetwork: [AsyncFunction: detectNetwork],
      setNetwork: [Function: setNetwork],
      setNetworkType: [Function: setNetworkType],
      setWallet: [Function: setWallet],
      resetAddress: [Function: resetAddress],
      link: [Function: link],
      clone: [Function: clone],
      addProp: [Function: addProp],
      toJSON: [Function: toJSON],
      decodeLogs: [Function: decodeLogs]
    },
    _properties: {
      contract_name: [Object],
      contractName: [Object],
      gasMultiplier: [Object],
      timeoutBlocks: [Object],
      autoGas: [Object],
      numberFormat: [Object],
      abi: [Object],
      metadata: [Function: metadata],
      network: [Function: network],
      networks: [Function: networks],
      address: [Object],
      transactionHash: [Object],
      links: [Function: links],
      events: [Function: events],
      binary: [Function: binary],
      deployedBinary: [Function: deployedBinary],
      unlinked_binary: [Object],
      bytecode: [Object],
      deployedBytecode: [Object],
      sourceMap: [Object],
      deployedSourceMap: [Object],
      source: [Object],
      sourcePath: [Object],
      legacyAST: [Object],
      ast: [Object],
      compiler: [Object],
      schema_version: [Function: schema_version],
      schemaVersion: [Function: schemaVersion],
      updated_at: [Function: updated_at],
      updatedAt: [Function: updatedAt],
      userdoc: [Function: userdoc],
      devdoc: [Function: devdoc]
    },
    _property_values: {},
    _json: {
      contractName: 'NFTSimple',
      abi: [Array],
      metadata: '{"compiler":{"version":"0.5.6+commit.b259423e"},"language":"Solidity","output":{"abi":[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"tokenOwner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"tokenId","type":"uint256"},{"name":"tokenURI","type":"string"}],"name":"mintWithTokenURI","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"id","type":"uint256"},{"name":"uri","type":"string"}],"name":"setTokenUri","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"tokenURIs","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"owner","type":"address"}],"name":"ownedTokens","outputs":[{"name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"from","type":"address"},{"name":"to","type":"address"},{"name":"tokenId","type":"uint256"},{"name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_addr","type":"address"}],"name":"balance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}],"devdoc":{"methods":{}},"userdoc":{"methods":{}}},"settings":{"compilationTarget":{"/Users/kimdawoon/klaytn/contracts/NFTSimple.sol":"NFTSimple"},"evmVersion":"petersburg","libraries":{},"optimizer":{"enabled":false,"runs":200},"remappings":[]},"sources":{"/Users/kimdawoon/klaytn/contracts/NFTSimple.sol":{"keccak256":"0xf0f74d9232e794b5b9043885d7543ad446f4659cc06cdff5ee1da3886e757d83","urls":["bzzr://ce577591ab3e9d25d63f467e272aff539b0b535cfc78e93ce807eb6d2518a57b"]}},"version":1}',
      bytecode: '0x60806040526040518060400160405280600881526020017f4b6c61794c696f6e0000000000000000000000000000000000000000000000008152506000908051906020019062000051929190620000b4565b506040518060400160405280600281526020017f4b4c000000000000000000000000000000000000000000000000000000000000815250600190805190602001906200009f929190620000b4565b50348015620000ad57600080fd5b5062000163565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620000f757805160ff191683800117855562000128565b8280016001018555821562000128579182015b82811115620001275782518255916020019190600101906200010a565b5b5090506200013791906200013b565b5090565b6200016091905b808211156200015c57600081600090555060010162000142565b5090565b90565b6114b380620001736000396000f3fe608060405234801561001057600080fd5b506004361061009e5760003560e01c806370a082311161006657806370a08231146103fd57806395d89b4114610455578063b12ab40f146104d8578063b88d4fde14610571578063e3d670d7146106765761009e565b806306fdde03146100a35780631caaa4871461012657806350bb4e7f1461019457806357f7789e146102915780636c8b703f14610356575b600080fd5b6100ab6106ce565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100eb5780820151818401526020810190506100d0565b50505050905090810190601f1680156101185780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101526004803603602081101561013c57600080fd5b810190808035906020019092919050505061076c565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610277600480360360608110156101aa57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001906401000000008111156101f157600080fd5b82018360208201111561020357600080fd5b8035906020019184600183028401116401000000008311171561022557600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929050505061079f565b604051808215151515815260200191505060405180910390f35b610354600480360360408110156102a757600080fd5b8101908080359060200190929190803590602001906401000000008111156102ce57600080fd5b8201836020820111156102e057600080fd5b8035906020019184600183028401116401000000008311171561030257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929050505061088f565b005b6103826004803603602081101561036c57600080fd5b81019080803590602001909291905050506108bb565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103c25780820151818401526020810190506103a7565b50505050905090810190601f1680156103ef5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61043f6004803603602081101561041357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061096b565b6040518082815260200191505060405180910390f35b61045d610a3c565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561049d578082015181840152602081019050610482565b50505050905090810190601f1680156104ca5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61051a600480360360208110156104ee57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610ada565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561055d578082015181840152602081019050610542565b505050509050019250505060405180910390f35b6106746004803603608081101561058757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001906401000000008111156105ee57600080fd5b82018360208201111561060057600080fd5b8035906020019184600183028401116401000000008311171561062257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050610b71565b005b6106b86004803603602081101561068c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610df5565b6040518082815260200191505060405180910390f35b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156107645780601f1061073957610100808354040283529160200191610764565b820191906000526020600020905b81548152906001019060200180831161074757829003601f168201915b505050505081565b60026020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000836002600085815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508160036000858152602001908152602001600020908051906020019061081a92919061133d565b50600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020839080600181540180825580915050906001820390600052602060002001600090919290919091505550600190509392505050565b806003600084815260200190815260200160002090805190602001906108b692919061133d565b505050565b60036020528060005260406000206000915090508054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156109635780601f1061093857610100808354040283529160200191610963565b820191906000526020600020905b81548152906001019060200180831161094657829003601f168201915b505050505081565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156109f2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602981526020018061145f6029913960400191505060405180910390fd5b600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490509050919050565b60018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610ad25780601f10610aa757610100808354040283529160200191610ad2565b820191906000526020600020905b815481529060010190602001808311610ab557829003601f168201915b505050505081565b6060600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610b6557602002820191906000526020600020905b815481526020019060010190808311610b51575b50505050509050919050565b3373ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614610c12576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f66726f6d20212d206d73672e73656e646572000000000000000000000000000081525060200191505060405180910390fd5b6002600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614610cc9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602281526020018061143d6022913960400191505060405180910390fd5b610cd38483610e07565b600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020829080600181540180825580915050906001820390600052602060002001600090919290919091505550826002600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610d9a8484848461106e565b610def576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e81526020018061140f602e913960400191505060405180910390fd5b50505050565b6000610e008261096b565b9050919050565b60006001600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905003905060008090505b600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905081101561101557600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208181548110610eeb57fe5b906000526020600020015483141561100857600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208281548110610f4757fe5b9060005260206000200154600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208281548110610f9c57fe5b906000526020600020018190555082600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208381548110610ff557fe5b9060005260206000200181905550611015565b8080600101915050610e57565b50600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548091906001900361106891906113bd565b50505050565b600080606061107c8661132a565b61108b57600192505050611322565b8573ffffffffffffffffffffffffffffffffffffffff16636745782b60e01b33898888604051602401808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561115b578082015181840152602081019050611140565b50505050905090810190601f1680156111885780820380516001836020036101000a031916815260200191505b5095505050505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040518082805190602001908083835b6020831061122057805182526020820191506020810190506020830392506111fd565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114611282576040519150601f19603f3d011682016040523d82523d6000602084013e611287565b606091505b508092508193505050600081511415801561130b5750636745782b60e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168180602001905160208110156112d957600080fd5b81019080805190602001909291905050507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b1561131b57600192505050611322565b6000925050505b949350505050565b600080823b905060008111915050919050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061137e57805160ff19168380011785556113ac565b828001600101855582156113ac579182015b828111156113ab578251825591602001919060010190611390565b5b5090506113b991906113e9565b5090565b8154818355818111156113e4578183600052602060002091820191016113e391906113e9565b5b505050565b61140b91905b808211156114075760008160009055506001016113ef565b5090565b9056fe4b495031373a207472616e7366657220746f206e6f6e204b49503137526563656976657220696d706c656d656e74796f7520617265206e6f7420746865206f776e6572206f662074686520746f6b656e4b495031373a2062616c616e636520717565727920666f7220746865207a65726f2061646472657373a165627a7a7230582074631fbcf9d3afb7a18a7098f93ab03085fef6dcfc8608f48f7cc7585da581380029',
      deployedBytecode: '0x608060405234801561001057600080fd5b506004361061009e5760003560e01c806370a082311161006657806370a08231146103fd57806395d89b4114610455578063b12ab40f146104d8578063b88d4fde14610571578063e3d670d7146106765761009e565b806306fdde03146100a35780631caaa4871461012657806350bb4e7f1461019457806357f7789e146102915780636c8b703f14610356575b600080fd5b6100ab6106ce565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100eb5780820151818401526020810190506100d0565b50505050905090810190601f1680156101185780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101526004803603602081101561013c57600080fd5b810190808035906020019092919050505061076c565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610277600480360360608110156101aa57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001906401000000008111156101f157600080fd5b82018360208201111561020357600080fd5b8035906020019184600183028401116401000000008311171561022557600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929050505061079f565b604051808215151515815260200191505060405180910390f35b610354600480360360408110156102a757600080fd5b8101908080359060200190929190803590602001906401000000008111156102ce57600080fd5b8201836020820111156102e057600080fd5b8035906020019184600183028401116401000000008311171561030257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929050505061088f565b005b6103826004803603602081101561036c57600080fd5b81019080803590602001909291905050506108bb565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103c25780820151818401526020810190506103a7565b50505050905090810190601f1680156103ef5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61043f6004803603602081101561041357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061096b565b6040518082815260200191505060405180910390f35b61045d610a3c565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561049d578082015181840152602081019050610482565b50505050905090810190601f1680156104ca5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61051a600480360360208110156104ee57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610ada565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561055d578082015181840152602081019050610542565b505050509050019250505060405180910390f35b6106746004803603608081101561058757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001906401000000008111156105ee57600080fd5b82018360208201111561060057600080fd5b8035906020019184600183028401116401000000008311171561062257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050610b71565b005b6106b86004803603602081101561068c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610df5565b6040518082815260200191505060405180910390f35b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156107645780601f1061073957610100808354040283529160200191610764565b820191906000526020600020905b81548152906001019060200180831161074757829003601f168201915b505050505081565b60026020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000836002600085815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508160036000858152602001908152602001600020908051906020019061081a92919061133d565b50600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020839080600181540180825580915050906001820390600052602060002001600090919290919091505550600190509392505050565b806003600084815260200190815260200160002090805190602001906108b692919061133d565b505050565b60036020528060005260406000206000915090508054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156109635780601f1061093857610100808354040283529160200191610963565b820191906000526020600020905b81548152906001019060200180831161094657829003601f168201915b505050505081565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156109f2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602981526020018061145f6029913960400191505060405180910390fd5b600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490509050919050565b60018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610ad25780601f10610aa757610100808354040283529160200191610ad2565b820191906000526020600020905b815481529060010190602001808311610ab557829003601f168201915b505050505081565b6060600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610b6557602002820191906000526020600020905b815481526020019060010190808311610b51575b50505050509050919050565b3373ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614610c12576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f66726f6d20212d206d73672e73656e646572000000000000000000000000000081525060200191505060405180910390fd5b6002600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614610cc9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602281526020018061143d6022913960400191505060405180910390fd5b610cd38483610e07565b600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020829080600181540180825580915050906001820390600052602060002001600090919290919091505550826002600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610d9a8484848461106e565b610def576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e81526020018061140f602e913960400191505060405180910390fd5b50505050565b6000610e008261096b565b9050919050565b60006001600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905003905060008090505b600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905081101561101557600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208181548110610eeb57fe5b906000526020600020015483141561100857600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208281548110610f4757fe5b9060005260206000200154600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208281548110610f9c57fe5b906000526020600020018190555082600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208381548110610ff557fe5b9060005260206000200181905550611015565b8080600101915050610e57565b50600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548091906001900361106891906113bd565b50505050565b600080606061107c8661132a565b61108b57600192505050611322565b8573ffffffffffffffffffffffffffffffffffffffff16636745782b60e01b33898888604051602401808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561115b578082015181840152602081019050611140565b50505050905090810190601f1680156111885780820380516001836020036101000a031916815260200191505b5095505050505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040518082805190602001908083835b6020831061122057805182526020820191506020810190506020830392506111fd565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114611282576040519150601f19603f3d011682016040523d82523d6000602084013e611287565b606091505b508092508193505050600081511415801561130b5750636745782b60e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168180602001905160208110156112d957600080fd5b81019080805190602001909291905050507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b1561131b57600192505050611322565b6000925050505b949350505050565b600080823b905060008111915050919050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061137e57805160ff19168380011785556113ac565b828001600101855582156113ac579182015b828111156113ab578251825591602001919060010190611390565b5b5090506113b991906113e9565b5090565b8154818355818111156113e4578183600052602060002091820191016113e391906113e9565b5b505050565b61140b91905b808211156114075760008160009055506001016113ef565b5090565b9056fe4b495031373a207472616e7366657220746f206e6f6e204b49503137526563656976657220696d706c656d656e74796f7520617265206e6f7420746865206f776e6572206f662074686520746f6b656e4b495031373a2062616c616e636520717565727920666f7220746865207a65726f2061646472657373a165627a7a7230582074631fbcf9d3afb7a18a7098f93ab03085fef6dcfc8608f48f7cc7585da581380029',
      sourceMap: '85:4074:1:-;;;110:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;147:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;85:4074;8:9:-1;5:2;;;30:1;27;20:12;5:2;85:4074:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;',
      deployedSourceMap: '85:4074:1:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;85:4074:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;110:31;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;110:31:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;192:45;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;192:45:1;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;659:375;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;659:375:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21:11:-1;8;5:28;2:2;;;46:1;43;36:12;2:2;659:375:1;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;659:375:1;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;659:375:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;93:3;85:6;81:16;74:27;137:4;133:9;126:4;121:3;117:14;113:30;106:37;;169:3;161:6;157:16;147:26;;659:375:1;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;3984:173;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;3984:173:1;;;;;;;;;;;;;;;;;;;21:11:-1;8;5:28;2:2;;;46:1;43;36:12;2:2;3984:173:1;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;3984:173:1;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;3984:173:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;93:3;85:6;81:16;74:27;137:4;133:9;126:4;121:3;117:14;113:30;106:37;;169:3;161:6;157:16;147:26;;3984:173:1;;;;;;;;;;;;;;;:::i;:::-;;266:43;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;266:43:1;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;266:43:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1040:207;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;1040:207:1;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;147:27;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;147:27:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3861:117;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;3861:117:1;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;3861:117:1;;;;;;;;;;;;;;;;;1358:772;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;1358:772:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21:11:-1;8;5:28;2:2;;;46:1;43;36:12;2:2;1358:772:1;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;1358:772:1;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;1358:772:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;93:3;85:6;81:16;74:27;137:4;133:9;126:4;121:3;117:14;113:30;106:37;;169:3;161:6;157:16;147:26;;1358:772:1;;;;;;;;;;;;;;;:::i;:::-;;1250:102;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;1250:102:1;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;110:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;192:45::-;;;;;;;;;;;;;;;;;;;;;;:::o;659:375::-;753:4;890:2;868:10;:19;879:7;868:19;;;;;;;;;;;;:24;;;;;;;;;;;;;;;;;;923:8;902:9;:18;912:7;902:18;;;;;;;;;;;:29;;;;;;;;;;;;:::i;:::-;;975:12;:16;988:2;975:16;;;;;;;;;;;;;;;997:7;975:30;;39:1:-1;33:3;27:10;23:18;57:10;52:3;45:23;79:10;72:17;;0:93;975:30:1;;;;;;;;;;;;;;;;;;;;;;1023:4;1016:11;;659:375;;;;;:::o;3984:173::-;4136:3;4120:9;:13;4130:2;4120:13;;;;;;;;;;;:19;;;;;;;;;;;;:::i;:::-;;3984:173;;:::o;266:43::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;1040:207::-;1095:7;1144:1;1127:19;;:5;:19;;;;1110:95;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1218:12;:19;1231:5;1218:19;;;;;;;;;;;;;;;:26;;;;1211:33;;1040:207;;;:::o;147:27::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;3861:117::-;3918:16;3952:12;:19;3965:5;3952:19;;;;;;;;;;;;;;;3945:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3861:117;;;:::o;1358:772::-;1479:10;1471:18;;:4;:18;;;1463:49;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1600:10;:19;1611:7;1600:19;;;;;;;;;;;;;;;;;;;;;1592:27;;:4;:27;;;1584:74;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1739:35;1760:4;1766:7;1739:20;:35::i;:::-;1784:12;:16;1797:2;1784:16;;;;;;;;;;;;;;;1806:7;1784:30;;39:1:-1;33:3;27:10;23:18;57:10;52:3;45:23;79:10;72:17;;0:93;1784:30:1;;;;;;;;;;;;;;;;;;;;;;1857:2;1835:10;:19;1846:7;1835:19;;;;;;;;;;;;:24;;;;;;;;;;;;;;;;;;2006:47;2028:4;2034:2;2038:7;2047:5;2006:21;:47::i;:::-;1985:128;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1358:772;;;;:::o;1250:102::-;1303:4;1327:16;1337:5;1327:9;:16::i;:::-;1320:23;;1250:102;;;:::o;3216:639::-;3410:20;3461:1;3433:12;:18;3446:4;3433:18;;;;;;;;;;;;;;;:25;;;;:29;3410:52;;3476:9;3488:1;3476:13;;3472:340;3495:12;:18;3508:4;3495:18;;;;;;;;;;;;;;;:25;;;;3491:1;:29;3472:340;;;3554:12;:18;3567:4;3554:18;;;;;;;;;;;;;;;3573:1;3554:21;;;;;;;;;;;;;;;;3543:7;:32;3540:262;;;3673:12;:18;3686:4;3673:18;;;;;;;;;;;;;;;3692:12;3673:32;;;;;;;;;;;;;;;;3649:12;:18;3662:4;3649:18;;;;;;;;;;;;;;;3668:1;3649:21;;;;;;;;;;;;;;;:56;;;;3757:7;3722:12;:18;3735:4;3722:18;;;;;;;;;;;;;;;3741:12;3722:32;;;;;;;;;;;;;;;:42;;;;3782:5;;3540:262;3522:3;;;;;;;3472:340;;;;3821:12;:18;3834:4;3821:18;;;;;;;;;;;;;;;:27;;;;;;;;;;;;:::i;:::-;;3216:639;;;:::o;2182:856::-;2293:4;2308:12;2330:23;2368:14;2379:2;2368:10;:14::i;:::-;2364:94;;2443:4;2436:11;;;;;;2364:94;2492:2;:7;;512:10;2600:15;;2673:10;2701:4;2723:7;2748:5;2560:207;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;2560:207:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;2560:207:1;;;;;;;38:4:-1;29:7;25:18;67:10;61:17;96:58;199:8;192:4;186;182:15;179:29;167:10;160:49;0:215;;;2560:207:1;2492:285;;;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;182:3;176:10;171:3;164:23;98:2;93:3;89:12;82:19;;123:2;118:3;114:12;107:19;;148:2;143:3;139:12;132:19;;36:153;;;274:1;267:3;263:2;259:12;254:3;250:22;246:30;315:4;311:9;305:3;299:10;295:26;356:4;350:3;344:10;340:21;389:7;380;377:20;372:3;365:33;3:399;;;2492:285:1;;;;;;;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;;2468:309:1;;;;;;;;2824:1;2803:10;:17;:22;;:160;;;;;512:10;2948:15;;2912:51;;;2923:10;2912:32;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;2912:32:1;;;;;;;;;;;;;;;;:51;;;;2803:160;2787:223;;;2995:4;2988:11;;;;;;2787:223;3026:5;3019:12;;;;2182:856;;;;;;;:::o;3044:166::-;3103:4;3118:12;3170:7;3158:20;3150:28;;3202:1;3195:4;:8;3188:15;;;3044:166;;;:::o;85:4074::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o',
      source: '//Klaytn IDE uses solidity 0.4.24 0.5.6 versions.\n' +
        'pragma solidity >=0.4.24 <=0.5.6;\n' +
        '\n' +
        'contract NFTSimple {\n' +
        '    string public name = "KlayLion";\n' +
        '    string public symbol = "KL"; // 단위 \n' +
        '\n' +
        '    mapping(uint256 => address) public tokenOwner; // token owner mapping\n' +
        '    mapping(uint256 => string) public tokenURIs; // key - value type declare\n' +
        '\n' +
        '    // 소유한 토큰 리스트\n' +
        '    mapping(address => uint256[]) private _ownedTokens;\n' +
        '    // onKIP17Received bytes value\n' +
        '\n' +
        '    bytes4 private constant _KIP17_RECEIVED = 0x6745782b;\n' +
        '\n' +
        '    // mint(tokenId, uri, owner) : 발행\n' +
        '    // transferFrom(from, to, tokenId) : 전송 -> owner가 바뀌는 것 (from -> to)\n' +
        '\n' +
        '    function mintWithTokenURI(address to, uint256 tokenId, string memory tokenURI) public returns(bool){\n' +
        '        // to에게 tokenId(일련번호)를 발행하겠다. \n' +
        '        // 적힐 글자는 tokenURI\n' +
        '        tokenOwner[tokenId] = to;\n' +
        '        tokenURIs[tokenId] = tokenURI;\n' +
        '\n' +
        '        // add token to the list\n' +
        '        _ownedTokens[to].push(tokenId);\n' +
        '\n' +
        '        return true;\n' +
        '    }\n' +
        '\n' +
        '    function balanceOf(address owner) public view returns (uint256) {\n' +
        '    require(\n' +
        '        owner != address(0),\n' +
        '        "KIP17: balance query for the zero address"\n' +
        '    );\n' +
        '    return _ownedTokens[owner].length;\n' +
        '}\n' +
        '\n' +
        ' function balance (address _addr) public view returns(uint){\n' +
        '          return balanceOf(_addr);\n' +
        '      }\n' +
        '\n' +
        '    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public{\n' +
        '        require(from == msg.sender, "from !- msg.sender"); // 보내는 사람이 현재 이 함수를 실행한 주체 \n' +
        '        require(from == tokenOwner[tokenId], "you are not the owner of the token"); // 보내는 사람이 보내려고 하는 토큰의 주인\n' +
        '        //\n' +
        '        _removeTokenFromList(from, tokenId);\n' +
        '        _ownedTokens[to].push(tokenId);\n' +
        '        //\n' +
        '        tokenOwner[tokenId] = to;\n' +
        '\n' +
        '        // 만약에 받는 쪽이 실행할 코드가 있는 스마트 컨트렉트이면 코드를 실행할 것\n' +
        '        require(\n' +
        '            _checkOnKIP17Received(from, to, tokenId, _data), "KIP17: transfer to non KIP17Receiver implement"\n' +
        '        );\n' +
        '\n' +
        '        \n' +
        '    }\n' +
        '\n' +
        '    //internal option : 외부 호춣 불가 \n' +
        '    function _checkOnKIP17Received(address from, address to, uint256 tokenId, bytes memory _data) internal returns(bool){\n' +
        '        bool success;\n' +
        '        bytes memory returndata;\n' +
        '\n' +
        '        if(!isContract(to)){ // smart contract address인지 판별\n' +
        '            return true;\n' +
        '        }\n' +
        '\n' +
        '        (success, returndata) = to.call( // 성공여부와 return 값을 받아와라 \n' +
        '            abi.encodeWithSelector(\n' +
        '                _KIP17_RECEIVED, //smart contract면 이걸 실행해라\n' +
        '                msg.sender,\n' +
        '                from,\n' +
        '                tokenId,\n' +
        '                _data\n' +
        '            )\n' +
        '        );\n' +
        '        if(\n' +
        '            returndata.length != 0 && //만약 return 값이 존재하며 그 값이 _KIP17_RECEIVED이면, \n' +
        '            abi.decode(returndata, (bytes4)) == _KIP17_RECEIVED\n' +
        '        ) {\n' +
        '            return true;\n' +
        '        }\n' +
        '        return false;\n' +
        '    }\n' +
        '\n' +
        '    function isContract(address account) internal view returns(bool){\n' +
        '        uint256 size;\n' +
        '        assembly {size := extcodesize(account)}\n' +
        '        return size > 0;\n' +
        '    }\n' +
        '\n' +
        '    function _removeTokenFromList(address from, uint256 tokenId) private{\n' +
        '        // [10, 15, 19, 20] -> 19번을 삭제하고 싶어요.\n' +
        '        // [10, 15, 20, 19]\n' +
        '        // [10, 15, 20]\n' +
        '        uint256 lastTokenIdx = _ownedTokens[from].length - 1;\n' +
        '        for(uint256 i = 0; i < _ownedTokens[from].length; i++){\n' +
        '            if(tokenId == _ownedTokens[from][i]){\n' +
        '                // swap last token with deleting token;\n' +
        '               _ownedTokens[from][i] = _ownedTokens[from][lastTokenIdx];\n' +
        '               _ownedTokens[from][lastTokenIdx] = tokenId;\n' +
        '                break;\n' +
        '            }\n' +
        '        }\n' +
        '        _ownedTokens[from].length--;\n' +
        '    }\n' +
        '\n' +
        '    function ownedTokens(address owner) public view returns (uint256[] memory){\n' +
        '        return _ownedTokens[owner];\n' +
        '    }\n' +
        '\n' +
        '    function setTokenUri(uint256 id, string memory uri) public { // memory는 좀 긴 타입의 데이터를 표시할 떄 쓴다. \n' +
        '        tokenURIs[id] = uri; // mapping\n' +
        '    }\n' +
        '} \n' +
        '\n' +
        '\n' +
        'contract NFTMarket {\n' +
        '    //token 보낸 사람을 기억 W\n' +
        '    mapping(uint256 => address) public seller;\n' +
        '\n' +
        '    function buyNFT(uint256 tokenId, address NFTAddress) public payable returns (bool){ //payable이 있어야 KLAY를 보낼 수 있다. \n' +
        '        //NFTAddress에는 NFTSimple이 배포된 주소를 넣어준다. \n' +
        '\n' +
        '        // 판매한 사람에게 0.01 KLAY 전송\n' +
        '        address payable receiver = address(uint160(seller[tokenId])); // 돈을 받을 사람은 seller이다. payable L 돈을 받을 수 있는~\n' +
        '\n' +
        '        // Send 0.01 KAY to receiver\n' +
        '        // 10 ** 18 PEB = 1 KLAY\n' +
        '        // 10 ** 16 PEB = 0.01 KLAY\n' +
        '        receiver.transfer(10 ** 16); // buyNFT를 호출한 사람이 이것까지 낸다. \n' +
        '\n' +
        "        NFTSimple(NFTAddress).safeTransferFrom(address(this), msg.sender, tokenId, '0x00'); // to 대신 msg.sender 무조건 이 함수 호출한 사람에게 보낸다. \n" +
        '        return true;\n' +
        '    }\n' +
        '\n' +
        '    // Market이 토큰을 받았을 때 (판매대에 올라갔을 때), 판매자가 누구인지 기록해야 한다. \n' +
        '    function onKIP17Received(address operator, address from , uint256 tokenId, bytes memory data) public returns (bytes4) {\n' +
        '        seller[tokenId] = from;\n' +
        '\n' +
        '        return bytes4(keccak256("onKIP17Received(address,address,uint256,bytes)"));\n' +
        '        // return이 의미하는 것은 현재 구현된 함수가 이 smart contract에 존재한다는 것을 알리는 용도\n' +
        '    }\n' +
        '}',
      sourcePath: '/Users/kimdawoon/klaytn/contracts/NFTSimple.sol',
      ast: [Object],
      legacyAST: [Object],
      compiler: [Object],
      networks: [Object],
      schemaVersion: '3.0.14',
      updatedAt: '2022-02-12T05:50:19.373Z',
      devdoc: [Object],
      userdoc: [Object]
    },
    setProvider: [Function: bound setProvider],
    new: [Function: bound new] {
      estimateGas: [Function: bound estimateDeployment]
    },
    at: [Function: bound at] AsyncFunction,
    deployed: [Function: bound deployed] AsyncFunction,
    defaults: [Function: bound defaults],
    hasNetwork: [Function: bound hasNetwork],
    isDeployed: [Function: bound isDeployed],
    detectNetwork: [Function: bound detectNetwork] AsyncFunction,
    setNetwork: [Function: bound setNetwork],
    setNetworkType: [Function: bound setNetworkType],
    setWallet: [Function: bound setWallet],
    resetAddress: [Function: bound resetAddress],
    link: [Function: bound link],
    clone: [Function: bound clone],
    addProp: [Function: bound addProp],
    toJSON: [Function: bound toJSON],
    decodeLogs: [Function: bound decodeLogs],
    web3: Web3Shim {
      currentProvider: [Getter/Setter],
      _requestManager: [RequestManager],
      givenProvider: null,
      providers: [Object],
      _provider: [HttpProvider],
      setProvider: [Function (anonymous)],
      BatchRequest: [Function: bound Batch],
      extend: [Function],
      version: '1.2.1',
      utils: [Object],
      eth: [Eth],
      shh: [Shh],
      bzz: [Bzz],
      networkType: 'ethereum'
    },
    class_defaults: {
      from: '0x2a467DA4a19ACac7D793381E0801b463d49a40D0',
      gas: 6721975,
      gasPrice: 20000000000
    },
    currentProvider: HttpProvider {
      host: 'http://127.0.0.1:7545',
      httpAgent: [Agent],
      timeout: 0,
      headers: undefined,
      connected: true,
      send: [Function (anonymous)],
      _alreadyWrapped: true
    },
    network_id: '5777',
    networkType: 'ethereum'
  },
  methods: {
    'name()': [Function (anonymous)] {
      call: [Function (anonymous)],
      sendTransaction: [Function (anonymous)],
      estimateGas: [Function (anonymous)],
      request: [Function (anonymous)]
    },
    'tokenOwner(uint256)': [Function (anonymous)] {
      call: [Function (anonymous)],
      sendTransaction: [Function (anonymous)],
      estimateGas: [Function (anonymous)],
      request: [Function (anonymous)]
    },
    'tokenURIs(uint256)': [Function (anonymous)] {
      call: [Function (anonymous)],
      sendTransaction: [Function (anonymous)],
      estimateGas: [Function (anonymous)],
      request: [Function (anonymous)]
    },
    'symbol()': [Function (anonymous)] {
      call: [Function (anonymous)],
      sendTransaction: [Function (anonymous)],
      estimateGas: [Function (anonymous)],
      request: [Function (anonymous)]
    },
    'mintWithTokenURI(address,uint256,string)': [Function (anonymous)] {
      call: [Function (anonymous)],
      sendTransaction: [Function (anonymous)],
      estimateGas: [Function (anonymous)],
      request: [Function (anonymous)]
    },
    'balanceOf(address)': [Function (anonymous)] {
      call: [Function (anonymous)],
      sendTransaction: [Function (anonymous)],
      estimateGas: [Function (anonymous)],
      request: [Function (anonymous)]
    },
    'balance(address)': [Function (anonymous)] {
      call: [Function (anonymous)],
      sendTransaction: [Function (anonymous)],
      estimateGas: [Function (anonymous)],
      request: [Function (anonymous)]
    },
    'safeTransferFrom(address,address,uint256,bytes)': [Function (anonymous)] {
      call: [Function (anonymous)],
      sendTransaction: [Function (anonymous)],
      estimateGas: [Function (anonymous)],
      request: [Function (anonymous)]
    },
    'ownedTokens(address)': [Function (anonymous)] {
      call: [Function (anonymous)],
      sendTransaction: [Function (anonymous)],
      estimateGas: [Function (anonymous)],
      request: [Function (anonymous)]
    },
    'setTokenUri(uint256,string)': [Function (anonymous)] {
      call: [Function (anonymous)],
      sendTransaction: [Function (anonymous)],
      estimateGas: [Function (anonymous)],
      request: [Function (anonymous)]
    }
  },
  abi: [
    {
      constant: true,
      inputs: [],
      name: 'name',
      outputs: [Array],
      payable: false,
      stateMutability: 'view',
      type: 'function',
      signature: '0x06fdde03'
    },
    {
      constant: true,
      inputs: [Array],
      name: 'tokenOwner',
      outputs: [Array],
      payable: false,
      stateMutability: 'view',
      type: 'function',
      signature: '0x1caaa487'
    },
    {
      constant: true,
      inputs: [Array],
      name: 'tokenURIs',
      outputs: [Array],
      payable: false,
      stateMutability: 'view',
      type: 'function',
      signature: '0x6c8b703f'
    },
    {
      constant: true,
      inputs: [],
      name: 'symbol',
      outputs: [Array],
      payable: false,
      stateMutability: 'view',
      type: 'function',
      signature: '0x95d89b41'
    },
    {
      constant: false,
      inputs: [Array],
      name: 'mintWithTokenURI',
      outputs: [Array],
      payable: false,
      stateMutability: 'nonpayable',
      type: 'function',
      signature: '0x50bb4e7f'
    },
    {
      constant: true,
      inputs: [Array],
      name: 'balanceOf',
      outputs: [Array],
      payable: false,
      stateMutability: 'view',
      type: 'function',
      signature: '0x70a08231'
    },
    {
      constant: true,
      inputs: [Array],
      name: 'balance',
      outputs: [Array],
      payable: false,
      stateMutability: 'view',
      type: 'function',
      signature: '0xe3d670d7'
    },
    {
      constant: false,
      inputs: [Array],
      name: 'safeTransferFrom',
      outputs: [],
      payable: false,
      stateMutability: 'nonpayable',
      type: 'function',
      signature: '0xb88d4fde'
    },
    {
      constant: true,
      inputs: [Array],
      name: 'ownedTokens',
      outputs: [Array],
      payable: false,
      stateMutability: 'view',
      type: 'function',
      signature: '0xb12ab40f'
    },
    {
      constant: false,
      inputs: [Array],
      name: 'setTokenUri',
      outputs: [],
      payable: false,
      stateMutability: 'nonpayable',
      type: 'function',
      signature: '0x57f7789e'
    }
  ],
  address: '0xC4D4a60745bDc14Dd92aD40909A5D162CE77b803',
  transactionHash: undefined,
  contract: Contract {
    currentProvider: [Getter/Setter],
    _requestManager: RequestManager {
      provider: [HttpProvider],
      providers: [Object],
      subscriptions: {}
    },
    givenProvider: null,
    providers: {
      WebsocketProvider: [Function: WebsocketProvider],
      HttpProvider: [Function: HttpProvider],
      IpcProvider: [Function: IpcProvider]
    },
    _provider: HttpProvider {
      host: 'http://127.0.0.1:7545',
      httpAgent: [Agent],
      timeout: 0,
      headers: undefined,
      connected: true,
      send: [Function (anonymous)],
      _alreadyWrapped: true
    },
    setProvider: [Function (anonymous)],
    BatchRequest: [Function: bound Batch],
    extend: [Function: ex] {
      formatters: [Object],
      utils: [Object],
      Method: [Function: Method]
    },
    clearSubscriptions: [Function (anonymous)],
    options: { address: [Getter/Setter], jsonInterface: [Getter/Setter] },
    defaultAccount: [Getter/Setter],
    defaultBlock: [Getter/Setter],
    methods: {
      name: [Function: bound _createTxObject],
      '0x06fdde03': [Function: bound _createTxObject],
      'name()': [Function: bound _createTxObject],
      tokenOwner: [Function: bound _createTxObject],
      '0x1caaa487': [Function: bound _createTxObject],
      'tokenOwner(uint256)': [Function: bound _createTxObject],
      tokenURIs: [Function: bound _createTxObject],
      '0x6c8b703f': [Function: bound _createTxObject],
      'tokenURIs(uint256)': [Function: bound _createTxObject],
      symbol: [Function: bound _createTxObject],
      '0x95d89b41': [Function: bound _createTxObject],
      'symbol()': [Function: bound _createTxObject],
      mintWithTokenURI: [Function: bound _createTxObject],
      '0x50bb4e7f': [Function: bound _createTxObject],
      'mintWithTokenURI(address,uint256,string)': [Function: bound _createTxObject],
      balanceOf: [Function: bound _createTxObject],
      '0x70a08231': [Function: bound _createTxObject],
      'balanceOf(address)': [Function: bound _createTxObject],
      balance: [Function: bound _createTxObject],
      '0xe3d670d7': [Function: bound _createTxObject],
      'balance(address)': [Function: bound _createTxObject],
      safeTransferFrom: [Function: bound _createTxObject],
      '0xb88d4fde': [Function: bound _createTxObject],
      'safeTransferFrom(address,address,uint256,bytes)': [Function: bound _createTxObject],
      ownedTokens: [Function: bound _createTxObject],
      '0xb12ab40f': [Function: bound _createTxObject],
      'ownedTokens(address)': [Function: bound _createTxObject],
      setTokenUri: [Function: bound _createTxObject],
      '0x57f7789e': [Function: bound _createTxObject],
      'setTokenUri(uint256,string)': [Function: bound _createTxObject]
    },
    events: { allEvents: [Function: bound ] },
    _address: '0xC4D4a60745bDc14Dd92aD40909A5D162CE77b803',
    _jsonInterface: [
      [Object], [Object],
      [Object], [Object],
      [Object], [Object],
      [Object], [Object],
      [Object], [Object]
    ]
  },
  name: [Function (anonymous)] {
    call: [Function (anonymous)],
    sendTransaction: [Function (anonymous)],
    estimateGas: [Function (anonymous)],
    request: [Function (anonymous)]
  },
  tokenOwner: [Function (anonymous)] {
    call: [Function (anonymous)],
    sendTransaction: [Function (anonymous)],
    estimateGas: [Function (anonymous)],
    request: [Function (anonymous)]
  },
  tokenURIs: [Function (anonymous)] {
    call: [Function (anonymous)],
    sendTransaction: [Function (anonymous)],
    estimateGas: [Function (anonymous)],
    request: [Function (anonymous)]
  },
  symbol: [Function (anonymous)] {
    call: [Function (anonymous)],
    sendTransaction: [Function (anonymous)],
    estimateGas: [Function (anonymous)],
    request: [Function (anonymous)]
  },
  mintWithTokenURI: [Function (anonymous)] {
    call: [Function (anonymous)],
    sendTransaction: [Function (anonymous)],
    estimateGas: [Function (anonymous)],
    request: [Function (anonymous)]
  },
  balanceOf: [Function (anonymous)] {
    call: [Function (anonymous)],
    sendTransaction: [Function (anonymous)],
    estimateGas: [Function (anonymous)],
    request: [Function (anonymous)]
  },
  balance: [Function (anonymous)] {
    call: [Function (anonymous)],
    sendTransaction: [Function (anonymous)],
    estimateGas: [Function (anonymous)],
    request: [Function (anonymous)]
  },
  safeTransferFrom: [Function (anonymous)] {
    call: [Function (anonymous)],
    sendTransaction: [Function (anonymous)],
    estimateGas: [Function (anonymous)],
    request: [Function (anonymous)]
  },
  ownedTokens: [Function (anonymous)] {
    call: [Function (anonymous)],
    sendTransaction: [Function (anonymous)],
    estimateGas: [Function (anonymous)],
    request: [Function (anonymous)]
  },
  setTokenUri: [Function (anonymous)] {
    call: [Function (anonymous)],
    sendTransaction: [Function (anonymous)],
    estimateGas: [Function (anonymous)],
    request: [Function (anonymous)]
  },
  sendTransaction: [Function (anonymous)],
  send: [Function (anonymous)],
  allEvents: [Function (anonymous)],
  getPastEvents: [Function (anonymous)]
}

각종 smart contract 관련 정보들이 나오게 됩니다.
또한 console에 it. tap을 두번 치게 되면

truffle(ganache)> it.
it.__proto__             it.hasOwnProperty        it.isPrototypeOf
it.propertyIsEnumerable  it.toLocaleString        it.toString
it.valueOf

it.abi                   it.address               it.allEvents
it.balance               it.balanceOf             it.constructor
it.contract              it.getPastEvents         it.methods
it.mintWithTokenURI      it.name                  it.ownedTokens
it.safeTransferFrom      it.send                  it.sendTransaction
it.setTokenUri           it.symbol                it.tokenOwner
it.tokenURIs             it.transactionHash

사용할 수 잇는 변수들을 확인할 수 있습니다.
이제 contract 내에 있는 함수를 테스트 해보면 아래와 같이 할 수 있습니다.

truffle(ganache)> it.mintWithTokenURI("0x2a467DA4a19ACac7D793381E0801b463d49a40D0",10,"happy")
{
  tx: '0xb7aa585552c452b53cef4903ef2a4caa50fb563c4dbc1fed606b62f880f361d6',
  receipt: {
    transactionHash: '0xb7aa585552c452b53cef4903ef2a4caa50fb563c4dbc1fed606b62f880f361d6',
    transactionIndex: 0,
    blockHash: '0x53b59e086e003ac8ddfb30fe9af3cff768e6cf116f74b474cfd2e0f850acafe5',
    blockNumber: 4,
    from: '0x2a467da4a19acac7d793381e0801b463d49a40d0',
    to: '0xc4d4a60745bdc14dd92ad40909a5d162ce77b803',
    gasUsed: 105977,
    cumulativeGasUsed: 105977,
    contractAddress: null,
    logs: [],
    status: true,
    logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
    rawLogs: []
  },
  logs: []
}

위와 같이 mintWithTokenURI function을 실행하여 보았습니다.
이제 제대로 생성됐는지 확인하기 위해 아래와 같이 명령을 입력해보면,

truffle(ganache)> it.balanceOf("0x2a467DA4a19ACac7D793381E0801b463d49a40D0")
BN { negative: 0, words: [ 1, <1 empty item> ], length: 1, red: null }

해당 주소의 balanceOf 명령에 응답으로 1이 나왔음을 알 수 있습니다.
다시 한 번 생성을 해보고 확인을 해보면

truffle(ganache)> it.mintWithTokenURI("0x2a467DA4a19ACac7D793381E0801b463d49a40D0",11,"happy")
{
  tx: '0xd729179c6b15775bc9006efac56060c8b2ade22ced218b8c32c753e353ff6a40',
  receipt: {
    transactionHash: '0xd729179c6b15775bc9006efac56060c8b2ade22ced218b8c32c753e353ff6a40',
    transactionIndex: 0,
    blockHash: '0x2d23e7a9b2aef66a7863c361965412d27e0c254801abf7f97b686047fcda172c',
    blockNumber: 5,
    from: '0x2a467da4a19acac7d793381e0801b463d49a40d0',
    to: '0xc4d4a60745bdc14dd92ad40909a5d162ce77b803',
    gasUsed: 90977,
    cumulativeGasUsed: 90977,
    contractAddress: null,
    logs: [],
    status: true,
    logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
    rawLogs: []
  },
  logs: []
}
truffle(ganache)> it.balanceOf("0x2a467DA4a19ACac7D793381E0801b463d49a40D0")
BN { negative: 0, words: [ 2, <1 empty item> ], length: 1, red: null }

정상적으로 tokenId 2가 생성되고 balanceOf로 확인 시 2개의 token이 할당 됨을 볼 수 있습니다.

Test Code 작성

./test/TestSimpleStorage.sol

상기 경로 내에 예제 Test Code를 작성했습니다.
기본적인 포멧은 해당 코드와 같습니다.

//Klaytn IDE uses solidity 0.4.24 0.5.6 versions.
pragma solidity >=0.4.24 <=0.5.6;

import "truffle/Assert.sol";
import "truffle/DeployedAddresses.sol";
import "../contracts/NFTSimple.sol";

contract TestSimpleStorage{
    function testSimpleStorage() public {

        NFTSimple it = new NFTSimple();

        it.mintWithTokenURI(address(this), 20, "happy");
        uint256 ans = it.balanceOf(address(this));
        Assert.equal(ans, 3, "value equal test");
    }
}

새로 Contract Code를 작성해서 내부에 Test할 Contract의 instance를 생성하고, 원하는 함수를 호출 후 Truffle Assert 함수로 Check하는 식입니다.
현재 해당 코드를 작성 후 Truffle Console에서 Test 하 시에는 아래와 같이 입력합니다.

truffle(ganache)> test
Using network 'ganache'.


Compiling your contracts...
===========================
> Compiling ./test/TestSimpleStorage.sol

    > compilation warnings encountered:

/Users/kimdawoon/klaytn/contracts/NFTSimple.sol:40:2: Warning: Variable is shadowed in inline assembly by an instruction of the same name
 function balance (address _addr) public view returns(uint){
 ^ (Relevant source part starts here and spans across multiple lines).
,/Users/kimdawoon/klaytn/contracts/NFTSimple.sol:140:30: Warning: Unused function parameter. Remove or comment out the variable name to silence this warning.
    function onKIP17Received(address operator, address from , uint256 tokenId, bytes memory data) public returns (bytes4) {
                             ^--------------^
,/Users/kimdawoon/klaytn/contracts/NFTSimple.sol:140:80: Warning: Unused function parameter. Remove or comment out the variable name to silence this warning.
    function onKIP17Received(address operator, address from , uint256 tokenId, bytes memory data) public returns (bytes4) {
                                                                               ^---------------^


TypeError [ERR_INVALID_REPL_INPUT]: Listeners for `uncaughtException` cannot be used in the REPL
    at new NodeError (internal/errors.js:322:7)
    at process.<anonymous> (repl.js:349:15)
    at process.emit (events.js:412:35)
    at process.emit (/usr/local/lib/node_modules/truffle/build/webpack:/~/source-map-support/source-map-support.js:465:1)
    at _addListener (events.js:443:14)
    at process.addListener (events.js:497:10)
    at Runner.run (/usr/local/lib/node_modules/truffle/node_modules/mocha/lib/runner.js:868:11)
    at Mocha.run (/usr/local/lib/node_modules/truffle/node_modules/mocha/lib/mocha.js:612:17)
    at /usr/local/lib/node_modules/truffle/build/webpack:/packages/truffle-core/lib/test.js:116:1
    at new Promise (<anonymous>)
    at Object.run (/usr/local/lib/node_modules/truffle/build/webpack:/packages/truffle-core/lib/test.js:115:1)
    at processTicksAndRejections (internal/process/task_queues.js:95:5)

현재 TypeErr가 나서 정상적으로 결과가 나오지는 않았습니다.
해당 부분은 확인 후 수정 예정이므로 해당 과정만 참고 바랍니다.

상기 오류 부분 수정

truffle 버전을 truffle@nodeLTS로 변경해주시면 test가 정상적으로 수행됩니다.

npm un -g truffle
npm i -g truffle@nodeLTS

이전에 수행하려던 test를 다시 수행하면

test code

//Klaytn IDE uses solidity 0.4.24 0.5.6 versions.
pragma solidity >=0.4.24 <=0.5.6;

import "truffle/Assert.sol";
import "truffle/DeployedAddresses.sol";
import "../contracts/NFTSimple.sol";

contract TestSimpleStorage{
    function testSimpleStorage() public {

        NFTSimple it = new NFTSimple();

        it.mintWithTokenURI(address(this), 20, "happy");
        uint256 ans = it.balanceOf(address(this));
        Assert.equal(ans, 1, "value equal test");
    }
}

코드에서 보다시피 배포한 주소에 1개의 토큰을 mint하고 다시 해당 주소에 대해 balanceOf를 호출한 값과 결과를 비교하게 됩니다.
예상하다시피 1이 나와야 합니다.

truffle(ganache)> test
Using network 'ganache'.


Compiling your contracts...
===========================
> Compiling ./test/TestSimpleStorage.sol
> Compilation warnings encountered:

    /Users/kimdawoon/klaytn/contracts/NFTSimple.sol:40:2: Warning: Variable is shadowed in inline assembly by an instruction of the same name
 function balance (address _addr) public view returns(uint){
 ^ (Relevant source part starts here and spans across multiple lines).
,/Users/kimdawoon/klaytn/contracts/NFTSimple.sol:140:30: Warning: Unused function parameter. Remove or comment out the variable name to silence this warning.
    function onKIP17Received(address operator, address from , uint256 tokenId, bytes memory data) public returns (bytes4) {
                             ^--------------^
,/Users/kimdawoon/klaytn/contracts/NFTSimple.sol:140:80: Warning: Unused function parameter. Remove or comment out the variable name to silence this warning.
    function onKIP17Received(address operator, address from , uint256 tokenId, bytes memory data) public returns (bytes4) {
                                                                               ^---------------^

> Artifacts written to /tmp/test-2022113-8636-1qrqaru.3vqu
> Compiled successfully using:
   - solc: 0.5.6+commit.b259423e.Emscripten.clang



  TestSimpleStorage
    ✓ testSimpleStorage (166ms)


  1 passing (7s)


예상했다시피 test를 통과하고 passing된 결과가 나오게 됩니다.

728x90
반응형
Comments