컨트랙트 배포, 활용 연습

Knave·2021년 8월 3일

BC

목록 보기
8/10

컨트랙트 배포, 연동

remix를 사용하여 컨트랙트를 만들고 web3 provider로 environment 설정을 변경하고 vsc에서 가나슈를 실행하여 연동 시켜주면 가나슈 계정들을 remix에서 확인이 가능하다. 그리고나서 컨트랙트를 deploy한 후에 컨트랙트 주소를 복사하여 작성한 html파일 속에 넣어준다. 아래는 순서대로 작성한 컨트랙트 파일, HTML 파일이다.

컨트랙트 파일

pragma solidity 0.8.6;

contract Hello 
{
    function getBlockNumber() public view returns (uint) 
    {
        return block.number;
    }
}

contract Bal {
    
  
    constructor()  payable {
        
           }
           
    function chkBalance() public view returns(uint) {
        return address(this).balance;
    }
           
    
}

contract counter {
    uint count;
    constructor(uint _count) {
    count = _count;    
    }
    function increment() public returns(uint) {
        return count ++;
    }
    function getCount() public view returns(uint) {
        return count;
    }
}
  1. 블록 넘버를 확인하는 hello 컨트랙트
  2. 생성,배포할때 안에 담은 balance를 확인하는 Bal 컨트랙트
  3. 시작할때 일정 값을 변수에 담고, 현재 변수의 값을 확인하거나
    그 값을 1만큼 증가시키는 counter 컨트랙트가 구현되어 있다.

HTML파일

<!DOCTYPE html>
<html lang="en">

<head>

  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />

  <script type="text/javascript" src="./bignumber.min.js"></script>
  <script type="text/javascript" src="./web3.js"></script>

  <script type="text/javascript">
    if (typeof web3 !== "undefined") {
      web3 = new Web3(web3.currentProvider);
    } else {
      // set the provider you want from Web3.providers
      web3 = new Web3(
        new Web3.providers.HttpProvider("http://localhost:8545")
      );
    }

    console.log(web3);

    if (web3.isConnected()) {
      console.log("connected");
    } else {
      console.log("not connected");
    }

    web3.eth.defaultAccount = web3.eth.accounts[0];

    let abi = [{
      "inputs": [],
      "name": "getBlockNumber",
      "outputs": [{
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }],
      "stateMutability": "view",
      "type": "function"
    }]

    let abi2 = [{
        "inputs": [],
        "stateMutability": "payable",
        "type": "constructor"
      },
      {
        "inputs": [],
        "name": "chkBalance",
        "outputs": [{
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }],
        "stateMutability": "view",
        "type": "function"
      }
    ]

    let abi3 = [{
        "inputs": [{
          "internalType": "uint256",
          "name": "_count",
          "type": "uint256"
        }],
        "stateMutability": "nonpayable",
        "type": "constructor"
      },
      {
        "inputs": [],
        "name": "getCount",
        "outputs": [{
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }],
        "stateMutability": "view",
        "type": "function"
      },
      {
        "inputs": [],
        "name": "increment",
        "outputs": [{
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }],
        "stateMutability": "nonpayable",
        "type": "function"
      }
    ]

    contractAddress = "1번 컨트랙트 주소"

    let smartContract = web3.eth.contract(abi).at(contractAddress)

    console.log(smartContract)

    smartContract.getBlockNumber.call(function (error, result) {
      console.log(result.toNumber())
      document.getElementById("scBlock").value = result.toNumber()
    })

    contractAddress2 = "2번 컨트랙트 주소"

    let smartContract2 = web3.eth.contract(abi2).at(contractAddress2)
    console.log(smartContract2)

    smartContract2.chkBalance.call(function (error, result) {
      console.log(result.toNumber())
      document.getElementById("balance").value = result.toNumber()
    })

    contractAddress3 = "3번 컨트랙트 주소"

    let smartContract3 = web3.eth.contract(abi3).at(contractAddress3)
    console.log(smartContract3)

    function getCount() {
      smartContract3.getCount.call(function (err, result) {
        console.log(result)
        document.getElementById("readCount").value = result
      })
    }

    function inc() {
      smartContract3.increment.sendTransaction(function (err, hash) {
        console.log(hash)
      });
    }
  </script>

</head>

<body>
  <p>Contract info</p>
  <label for="">Hello contract's Block Num</label>
  <input type="text" id="scBlock" value="">

  <br>
  <label for="">balance contract's remaining balance</label>
  <input type="text" id="balance" value="">

  <br>
  <label for="">Count contract</label>
  <button onclick="getCount()">view count</button>
  <button onclick="inc()">count + 1</button>
  <input type="text" id="readCount" value="">
</body>

</html>

이제 html파일을 브라우저로 열고 확인하면 컨트랙트와 관련된 정보가 연결된 것을 볼 수 있다.

컨트랙트 별로 abi는 별개로 형성되므로 3가지 컨트랙트의 주소는 물론 각각의 abi를 모두 적어주어야한다.

배포가 완료된 컨트랙트의 주소는 contractAddress= "주소" 부분에 적고,
abi 부분의 코드는 remix의 컴파일러 탭에서 abi버튼을 클릭하여 복사해서 붙여넣기 하면된다. 컨트랙트 안에 들어있는 함수를 호출하는 방법은 익숙해질 필요가 있는데 view 속성들 같은 경우는 call방식으로 바로바로 실행이 되지만, count++을 시켜주는 increment함수와 같은 경우에는 누군가가 해당 명령을 실행하여 가나슈(체인)상에 변화를 줘야하므로 html 윗부분에 아래와 같은

web3.eth.defaultAccount = web3.eth.accounts[0];

default 계정을 설정해주어야 한다.

이렇게 하면 간단하게 3개의 컨트랙트를 하나의 html파일을 통해서 구현해 볼 수 있고, 브라우저를 통해 웹에서의 사용이 가능하다.

컨트랙트 연결 활용 연습

컨트랙트 파일

pragma solidity 0.8.6;

contract HKbank {
    
    mapping (address => uint) balanceAccount;
    
    function deposit(uint amount) public{
        balanceAccount[msg.sender] += amount;
        
    }
    
    function getBalance() public view returns (uint) {
        return balanceAccount[msg.sender];
    }
}

contract EventContract {    
   	string fName;
   	uint age;

   	event Instructor(
   		string name,
   		uint age
	);

    function setInstructor(string memory _fName, uint _age) public {
        fName = _fName;
        age = _age;
        emit Instructor(_fName, _age);        // Add this
    }
    
    function getInstructor() view public returns (string memory, uint) {
        return (fName, age);
    }

}
  1. 매핑을 통해 주소별로 balance를 예금하고 확인할 수 있는 HKbank 컨트랙트
  2. 강사명과 나이를 입력하고 event 속성을 통해 출력값을 받아 볼 수 있는 EventContract 컨트랙트가 구현되어 있다.

HTML 파일

<!DOCTYPE html>
<html lang="en">

<head>

    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    <script type="text/javascript" src="./bignumber.min.js"></script>
    <script type="text/javascript" src="./web3.js"></script>

    <script type="text/javascript">
        if (typeof web3 !== "undefined") {
            web3 = new Web3(web3.currentProvider);
        } else {
            // set the provider you want from Web3.providers
            web3 = new Web3(
                new Web3.providers.HttpProvider("http://localhost:8545")
            );
        }

        console.log(web3);

        if (web3.isConnected()) {
            console.log("connected");
        } else {
            console.log("not connected");
        }

        web3.eth.defaultAccount = web3.eth.accounts[0];

        let abi = [{
                "inputs": [{
                    "internalType": "uint256",
                    "name": "amount",
                    "type": "uint256"
                }],
                "name": "deposit",
                "outputs": [],
                "stateMutability": "nonpayable",
                "type": "function"
            },
            {
                "inputs": [],
                "name": "getBalance",
                "outputs": [{
                    "internalType": "uint256",
                    "name": "",
                    "type": "uint256"
                }],
                "stateMutability": "view",
                "type": "function"
            }
        ]
        let abi2 = [{
                "anonymous": false,
                "inputs": [{
                        "indexed": false,
                        "internalType": "string",
                        "name": "name",
                        "type": "string"
                    },
                    {
                        "indexed": false,
                        "internalType": "uint256",
                        "name": "age",
                        "type": "uint256"
                    }
                ],
                "name": "Instructor",
                "type": "event"
            },
            {
                "inputs": [],
                "name": "getInstructor",
                "outputs": [{
                        "internalType": "string",
                        "name": "",
                        "type": "string"
                    },
                    {
                        "internalType": "uint256",
                        "name": "",
                        "type": "uint256"
                    }
                ],
                "stateMutability": "view",
                "type": "function"
            },
            {
                "inputs": [{
                        "internalType": "string",
                        "name": "_fName",
                        "type": "string"
                    },
                    {
                        "internalType": "uint256",
                        "name": "_age",
                        "type": "uint256"
                    }
                ],
                "name": "setInstructor",
                "outputs": [],
                "stateMutability": "nonpayable",
                "type": "function"
            }
        ]

        contractAddress = "0x3E596A17baFBaA1B124CD94C7DEa8CB274EFa59B"
        let smartContract = web3.eth.contract(abi).at(contractAddress)
        console.log(smartContract)

        smartContract.getBalance.call(function (err, result) {
            console.log(result)
            document.getElementById("bank_balance").value = result
        })

        function deposit() {
            let A;
            A = document.getElementById("deposit_amount").value
            console.log(A)
            smartContract.deposit(A).sendTransaction(function (err, hash) {
                console.log(hash)
                document.getElementById("deposit_amount").value = ""
            })
        }

        contractAddress2 = "0x9b8404D99b3d6486225AD572a230E5E5E324b357"
        let contract = web3.eth.contract(abi2).at(contractAddress2)

        let instructorEvent = contract.Instructor();

        instructorEvent.watch(function (error, result) {
            console.log(result.args);
        })

        function setInstructor() {
            contract.setInstructor.sendTransaction("hyun", 11, {
                from: web3.eth.accounts[0]
            }, function (err, hash) {});
        }

        function getInstructor() {
            contract.getInstructor.call(function (err, result) {});
            console.log(result)
        }
    </script>

</head>

<body>
    <p>HK bank Contract</p>
    <div>
        <label for="">Current Balance</label>
        <input type="text" id="bank_balance" value="">
        <button onclick="deposit()">Deposit</button>
        <input type="text" id="deposit_amount" value="" placeholder="Deposit amount">

    </div>
    <div>
        <button onclick="setInstructor()">setInstructor</button>
        <button onclick="getInstructor()">getInstructor</button>
    </div>
</body>

</html>

마찬가지로 두개의 컨트랙트를 하나의 html파일을 통해 확인해 볼 수 있다.
이런식으로 컨트랙트를 작성하고 배포하는 연습, 해당 컨트랙트를 배포한 곳의 네트워크와 html파일을 연동시키고, 웹 영역에서 컨트랙트로부터 받아온 데이터들을 활용하는 연습 들을 통해 Dapp 개발을 간접적으로 체험할 수 있다.

cf). event 속성에 담을 값은 자유지만 event로 지정했다면 event명은 필수적으로 부여되어야 한다.

profile
Hello

0개의 댓글