ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [SmartContract] Truffle ๋กœ Solidity ์ปดํŒŒ์ผ ๋ฐ Ganache ์— ๋ฐฐํฌ
    SECURITY/Blockchain 2022. 1. 11. 14:51

     

    * ์ด์ „ ํฌ์ŠคํŒ…์— ์ด์–ด์ง€๋Š” ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.

     

    SmartContract ๋ฅผ Solidity ๋กœ ์ž‘์„ฑํ•˜๊ณ , truffle ๋กœ ์ปดํŒŒ์ผํ•˜์—ฌ ๊ฒฐ๊ณผ๋ฅผ ์‚ดํŽด๋ด…์‹œ๋‹ค.

    ๋˜ํ•œ, ์ปดํŒŒ์ผํ•œ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ€์ง€๊ณ  ๋ฐฐํฌ๊นŒ์ง€ ์ง„ํ–‰ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

     


    Truffle ์—์„œ Solidity ์ปดํŒŒ์ผํ•˜๊ธฐ

    ์ง€๋‚œ ํฌ์ŠคํŒ…์—์„œ์ฒ˜๋Ÿผ, truffle ํ”„๋กœ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•˜๋ฉด ๋‹ค์Œ์˜ ๊ตฌ์กฐ๋ฅผ ๊ฐ–์Šต๋‹ˆ๋‹ค.

    • contracts: solidity ์†Œ์ŠคํŒŒ์ผ (.sol)
    • migrations: ๋ฐฐํฌ script (.js)
    • test: ํ…Œ์ŠคํŠธ script (.js or .sol)
    • truffe.js: ์„ค์ • ํŒŒ์ผ

     

    truffle ์€ ์ด ๊ตฌ์กฐ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ solidity ํŒŒ์ผ์„ ์ปดํŒŒ์ผํ•˜๊ณ , ๊ฒฐ๊ณผ๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

    ์ง€๊ธˆ์€ ์–ด๋–ป๊ฒŒ ์ปดํŒŒ์ผ ๋ฐ ๋ฐฐํฌ๋ฅผ ํ•˜๋Š”์ง€ ์‚ดํŽด๋ณด๋Š” ๋‹จ๊ณ„์ด๋ฏ€๋กœ, truffle ์˜ ๊ธฐ๋ณธ ์ œ๊ณต ์ฝ”๋“œ๋ฅผ ์ด์šฉํ•ด ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

     

    ๋‹ค์Œ์€ truffle ์˜ Migrations.sol ์ž…๋‹ˆ๋‹ค.

     

    // SPDX-License-Identifier: MIT
    pragma solidity >=0.4.22 <0.9.0;
    
    contract Migrations {
      address public owner = msg.sender;
      uint public last_completed_migration;
    
      modifier restricted() {
        require(
          msg.sender == owner,
          "This function is restricted to the contract's owner"
        );
        _;
      }
    
      function setCompleted(uint completed) public restricted {
        last_completed_migration = completed;
      }
    }

     

     

    truffle ์—์„œ solidity ๋ฅผ ์ปดํŒŒ์ผํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” contracts ํด๋”์— sol ํŒŒ์ผ์„ ์ž‘์„ฑํ•˜๊ณ , ํ„ฐ๋ฏธ๋„์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž…๋ ฅํ•ด์ค๋‹ˆ๋‹ค.

    $ truffle compile

    ๊ทธ๋Ÿผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ปดํŒŒ์ผ์ด ์ง„ํ–‰๋˜๊ณ , ์„ฑ๊ณต์ ์œผ๋กœ ๋๋‚˜๋ฉด build ํด๋”์— ์ปดํŒŒ์ผ ๊ฒฐ๊ณผ๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.

    solidity ์ปดํŒŒ์ผ ๊ฒฐ๊ณผ๋Š” 'abi' ์™€ 'bytecode' ๋กœ, ํ•ด๋‹น ๋‚ด์šฉ์ด ๋“ค์–ด์žˆ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    * abi: application binary interface (contract ์˜ ๋ช…์„ธ ์—ญํ• )

     

     

     

     

    ๋ฐฐํฌ script ์ž‘์„ฑ

    smart contract ๋ฅผ ๋ฐฐํฌํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋ฐฐํฌ script ๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

    deploy (๋˜๋Š” migrate) ๋ฅผ ์œ„ํ•ด์„  ๋ฐฐํฌ ์Šคํฌ๋ฆฝํŠธ๋ฅผ migrations ํด๋”์— ์ž‘์„ฑํ•˜๋ฉด ๋˜๋Š”๋ฐ, ํŒŒ์ผ๋ช… ํ˜•์‹์— ์ •ํ•ด์ง„ ๊ทœ์น™์ด ์žˆ์Šต๋‹ˆ๋‹ค.

     

    {์ˆซ์ž}_{์ด๋ฆ„}.js

     

    ์ˆซ์ž๋Š” truffle ์—์„œ ๊ด€๋ฆฌํ•˜๋Š” '๋ฐฐํฌ ์ˆœ์„œ' ์ž…๋‹ˆ๋‹ค.

    ์ฒ˜์Œ truffle ํ”„๋กœ์ ํŠธ๋ฅผ ๋งŒ๋“ค๋ฉด 1_initial_migration.js ๋ผ๋Š” ํŒŒ์ผ์ด ์žˆ๋Š”๋ฐ, ์ด ์นœ๊ตฌ๊ฐ€ 1๋ฒˆ์ด๊ณ  ์šฐ๋ฆฌ๋Š” 2 ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ด์„œ ์ž‘์„ฑํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ex. 2_HelloWorld_migration.js

     

    ๋ฐฐํฌ ์Šคํฌ๋ฆฝํŠธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ˜•์‹์„ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค.

    const Migrations = artifacts.require("Migrations");
    
    module.exports = function (deployer) {
      deployer.deploy(Migrations);
    };
    • artifacts.require("CONTRACT_NAME"): contract name (๋˜๋Š” ํŒŒ์ผ๋ช…) ์„ ์ ์–ด์ค๋‹ˆ๋‹ค.
    • deployer.deploy(Migrations)
      • ๋‘ ๋ฒˆ์งธ parameter ๋กœ ํ•ด๋‹น contract ์˜ ์ƒ์„ฑ์ž ์ธ์ˆ˜๋ฅผ ๋„ฃ์–ด์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰, contract ์˜ consrtuctor ์— ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ์žˆ์—ˆ๋‹ค๋ฉด, ํ•ด๋‹น ๋‚ด์šฉ์„ ์ฑ„์›Œ์ค๋‹ˆ๋‹ค.
      • ex. deployer.deploy(Migrations, "Hello");
      • * ์ด๋Š” 'argv' ์„ ๋„ฃ์–ด์ค€๋‹ค๊ณ  ์ดํ•ดํ•˜๋ฉด ํŽธํ•  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

     

    ๋ฐฐํฌ๋ฅผ ์œ„ํ•ด์„œ๋Š” contract ์˜ ์ปดํŒŒ์ผ ๊ฒฐ๊ณผ์ธ abi ์™€ bytecode ๋ฅผ ์•Œ์•„์•ผ ํ•˜๋Š”๋ฐ, truffle ์—์„œ๋Š” ์šฐ๋ฆฌ๊ฐ€ ์ง์ ‘ ์ € ์ •๋ณด์— ์ ‘๊ทผํ•˜์ง€ ์•Š๊ณ ๋„ ์†์‰ฝ๊ฒŒ ๋ฐฐํฌํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ค๋‹ˆ๋‹ค.

     

     

     

    Ganache test net ์— ๋ฐฐํฌํ•˜๊ธฐ

    ์ด์ œ contract ๋„ ์ž‘์„ฑํ•ด์„œ ์ปดํŒŒ์ผํ–ˆ๊ณ , ๋ฐฐํฌ ์Šคํฌ๋ฆฝํŠธ๋„ ์ž‘์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

     

    ๋‚จ์€ ๊ฒƒ์€ contract ๋ฅผ ์–ด๋””์— ๋ฐฐํฌํ•˜๋Š๋ƒ, ์ฆ‰ ๋ฐฐํฌ ํƒ€๊ฒŸ์„ ์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

    '๋ฐฐํฌ ํƒ€๊ฒŸ'์€ contract ๋ฅผ ์–ด๋””์— ๋ฐฐํฌํ•˜๊ฒ ๋ƒ๋Š” ๊ฒƒ์œผ๋กœ, ๋กœ์ปฌ (Ganache, geth ๋“ฑ), ์ด๋”๋ฆฌ์›€ ํ…Œ์ŠคํŠธ๋„ท, ์ด๋”๋ฆฌ์›€ ๋ฉ”์ธ๋„ท(๋ฉ”์ธ ์„œ๋ฒ„) ๋“ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

    • Ganache, geth ๋ฅผ ์ด์šฉํ•ด์„œ ๋กœ์ปฌ ํ…Œ์ŠคํŠธ๋„ท์— ๋ฐฐํฌ
    • geth ๋กœ ๋ฉ”์ธ๋„ท ๋˜๋Š” ํ…Œ์ŠคํŠธ๋„ท์— ๋ฐฐํฌ
    • infura ๋ผ๋Š” ํšŒ์‚ฌ๊ฐ€ ์ œ๊ณตํ•˜๋Š” provider ๋ฅผ ํ†ตํ•ด ๋ฉ”์ธ๋„ท ๋˜๋Š” ํ…Œ์ŠคํŠธ๋„ท์— ๋ฐฐํฌ

     

    ์ด๋Š” truffle-config.js ์—์„œ ์„ค์ •ํ•ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

    * ์ด์ „ truffle ์—์„œ๋Š” ์šด์˜์ฒด์ œ์— ๋”ฐ๋ผ tuffle.js ๋˜๋Š” truffle-config.js ๋กœ ์„ค์ • ํŒŒ์ผ์ด ๋ถ„๋ฆฌ๋˜์–ด ์žˆ์—ˆ๋Š”๋ฐ, ์ตœ์‹  truffle ์—์„œ๋Š” truffle-config.js ๋กœ ํ†ต์ผ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

     

    truffle-config.js ์—์„œ๋Š” ๋””ํดํŠธ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋˜์–ด์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. (์ฃผ์„์œผ๋กœ ์ž‘์„ฑ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค)

    module.exports = {
      networks: {
        development: {
          host: "127.0.0.1",     // Localhost (default: none)
          port: 8545,            // Standard Ethereum port (default: none)
          network_id: "*",       // Any network (default: none)
        }
    };

    ์œ„์˜ ์˜ˆ์‹œ์—์„œ์ฒ˜๋Ÿผ ํƒ€๊ฒŸ networks ๋ฅผ ์ง€์ •ํ•ด์ฃผ๋ฉด ๋˜๋Š”๋ฐ, s ๊ฐ€ ๋ถ™์€ ๊ฒƒ์œผ๋กœ ์ง์ž‘ํ•  ์ˆ˜ ์žˆ๋“ฏ์ด ํ•œ๋ฒˆ์— ์—ฌ๋Ÿฌ network ๋ฅผ ์ง€์ •ํ•˜์—ฌ ๋‹ค์ค‘ ๋ฐฐํฌ๋ฅผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

     

    ์—ฌ๊ธฐ์„œ 'network' ์˜ ์ด๋ฆ„์€ ๋งˆ์Œ๋Œ€๋กœ ์ •ํ•ด์ค˜๋„ ๋˜์ง€๋งŒ, 'development' ๋Š” tuffle ์ด ๊ธฐ๋ณธ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๋„คํŠธ์›Œํฌ์ž„์„ ์ฃผ์˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

    ๋˜ํ•œ, network ๋ฅผ ์ž‘์„ฑํ•  ๋•Œ๋Š” 'host', 'port', 'network_id' ์ด ์„ธ ๊ฐ€์ง€ ์š”์†Œ๋ฅผ ๋ฐ˜๋“œ์‹œ ์ž‘์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

     

    ์ด๋•Œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด, tuffle command ๋ฅผ ํ†ตํ•ด ํŠน์ • network ๋ฅผ ์ •ํ•ด์„œ ํ…Œ์ŠคํŠธ๋ฅผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    $ truffle test --network <NETWORK_NAME>

     

    ๋‹ค์Œ์€ ๋‹ค์ค‘ ๋„คํŠธ์›Œํฌ ์„ค์ •์— ๋Œ€ํ•œ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค.

     

    module.exports = {
      networks: {
        development: { host: "127.0.0.1", port: 8545, network_id: "*", },
        dev-ganache: { host: "127.0.0.1", port: 7545, netword_id: "777", },
        advanced: { host:"192.168.0.x", port: 8777, network_id: 1342, gas: 8500000, gasPrice: 20000000000, },
    };

     

     

     

    ์ด๋ฒˆ ํฌ์ŠคํŒ…์—์„œ๋Š” Ganache ๋กœ ๋กœ์ปฌ ํ…Œ์ŠคํŠธ๋„ท์— ๋ฐฐํฌ๋ฅผ ํ•ด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

     

    ๋จผ์ € ์ด์ „์— ์„ค์น˜ํ•ด๋‘” Ganache ๋ฅผ ์‹คํ–‰ํ•ด์ฃผ๊ณ , test net ์„ ๋งŒ๋“ค์–ด์ค๋‹ˆ๋‹ค. (์ €์˜ ๊ฒฝ์šฐ, QuickStart ๋กœ ๋งŒ๋“ค์–ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค)

     

     

    Auto mining ์œผ๋กœ ๋Œ์•„๊ฐ€๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    ๊ทธ ์•„๋ž˜๋กœ๋Š” Ganache ๊ฐ€ ์‹คํ–‰ ์‹œ ๋งŒ๋“ค์–ด์ฃผ๋Š” 10๊ฐœ์˜ ํ…Œ์ŠคํŠธ ๊ณ„์ •์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

     

    truffle-config.js ์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ•ด์ค๋‹ˆ๋‹ค.

    (์ž์‹ ์˜ Ganache ๋ฒ„์ „์— ๋งž๊ฒŒ port, network_id ๋ฅผ ๋ณ€๊ฒฝํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค)

     

    module.exports = {
        networks: {
            development: {
                host: "127.0.0.1",     // Localhost (default: none)
                port: 7545,            // Standard Ethereum port (default: none)
                network_id: 5777,       // Any network (default: none)
            }
        },
    };

     

    ์ด์ œ ํ„ฐ๋ฏธ๋„์„ ์—ด์–ด์„œ, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž…๋ ฅํ•ด์ฃผ๋ฉด ๋ฐฐํฌ ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์ฐจ๋ก€๋กœ ์ง„ํ–‰๋˜๋ฉฐ ๋ฐฐํฌ๋œ ์ฃผ์†Œ๊ฐ€ ๋‚˜์˜ต๋‹ˆ๋‹ค.

     

    $ truffle migrate --network development
    • migrate: Run migrations to deply contracts

    (ํ˜น์‹œ, ์–ด๋– ํ•œ ์ด์œ ๋กœ ์ž˜ ์•ˆ๋œ๋‹ค๋ฉด, power shell ์—์„œ ์‹œ๋„ํ•ด๋ณด์„ธ์š”.)

     

    ๋ฐฐํฌ๋Š” ์ปดํŒŒ์ผ ํ›„ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

     

     

    contract address ๋ฅผ ์ด์šฉํ•ด์„œ ๋ฐฐํฌ๋œ contract ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    ๋‹จ, Ganache ๋Š” local test net ์ด๋ฏ€๋กœ, ์ข…๋ฃŒ์‹œํ‚ค๋ฉด ๋ฐฐํฌํ–ˆ๋˜ ๋‚ด์šฉ์ด ๋ชจ๋‘ ์‚ฌ๋ผ์ง‘๋‹ˆ๋‹ค.

     

    Ganache ๋ฅผ ๋ณด๋ฉด ํ•œ ๊ณ„์ •์˜ ์ด๋”๊ฐ€ ๊ฐ์†Œํ•œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

     

     

     


    ์ด๋ ‡๊ฒŒ ๊ธฐ๋ณธ Solidity ์ฝ”๋“œ๋ฅผ Truffle ์„ ์ด์šฉํ•ด์„œ ์ปดํŒŒ์ผํ•˜๊ณ , Ganache ์— ๋ฐฐํฌํ•˜๋Š” ๊ฒƒ๊นŒ์ง€ ํ•ด๋ดค์Šต๋‹ˆ๋‹ค.

    ๋Œ“๊ธ€

Designed by Tistory.