본문 바로가기

블록체인_9기/과제

과제_230927_Blockchain(트랜잭션 사용해 로또 추첨하기)

728x90

 

 

 


과제내용

" 스마트 컨트랙트를 이용해서 로또 제작해보세요~ " 가 과제 내용이었다.....

힘... 내볼게요....ㅎㅎ

 


결과물

#. 폴더의 경로는 다음과 같다.

 

1. src/contracts/lotto.sol_로또 작업을 구현하기 위한 solidity 코드를 작성한다.

Lotto 컨트럭트에서 사용할 변수를 선언한다.

  • lottoNums : 로또 숫자를 뽑을 숫자 배열을 담는다. ( 1 ~ 45의 숫자)
  • selecNums : lottoNums에서 뽑은 숫자 6개를 배열로 담는다. (중복되지 않아야 한다.)
  • numHistory : 로또 추첨 결과(selecNums)를 담는다. (이중 배열)

 

getSelecLotto 함수는 로또를 추첨한 결과인 selecNums를 반환한다. 'public view' 속성으로 읽기만 할 수 있는 반환값을 가진다. 반환값은 uint256의 배열 형식을 가진다. 이 부분에서 매개변수에 'returns(uint256[] memory)'로 작성을 했는데, memory를 작성하지 않으면 에러가 발생했다... 왜 작성을 해야하는지 아직 이유는 모르겠어서 나중에 찾아보도록 하자 ㅎㅎ 같은 방식으로 getNums 함수를 작성해 추첨할 수 있는 번호들을 반환했다.

setLotto 함수는 로또를 추천하는 역할을 수행한다.

 

// SPDX-License-Identifier : MIT

pragma solidity ^0.8.13;

contract Lotto{
    uint256[] lottoNums;
    uint256[] selecNums;
    uint256[][] numHistory;

    constructor(){
        // for (uint256 i = 1; i < 46; i++) {
        //     lottoNums.push(i);
        // }
    }

    function getSelecLotto() public view returns(uint256[] memory){
        return selecNums;
    }

    function getNums() public view returns(uint256[] memory){
        return lottoNums;
    }

    function setLotto()public returns(uint256[] memory){
        delete lottoNums;
        delete selecNums;

        for (uint256 i = 1; i < 46; i++) {
            lottoNums.push(i);
        }

        for (uint256 i = 0; i < 6 ; i++) {
        uint256 selec = uint(keccak256(abi.encodePacked(block.timestamp, msg.sender, i))) % lottoNums.length;
            selecNums.push(lottoNums[selec]);
            lottoNums[selec] = lottoNums[lottoNums.length -1];
            lottoNums.pop();
        }
        numHistory.push(selecNums);
        return selecNums;
    }

    function getHistory() public view returns(uint256[][] memory){
        return numHistory;
    }
}

 

import "./App.css";
import { useEffect, useState } from "react";
import Web3 from "web3";

function App() {
  const abi = [
    { inputs: [], stateMutability: "nonpayable", type: "constructor" },
    {
      inputs: [],
      name: "getHistory",
      outputs: [{ internalType: "uint256[][]", name: "", type: "uint256[][]" }],
      stateMutability: "view",
      type: "function",
    },
    {
      inputs: [],
      name: "getNums",
      outputs: [{ internalType: "uint256[]", name: "", type: "uint256[]" }],
      stateMutability: "view",
      type: "function",
    },
    {
      inputs: [],
      name: "getSelecLotto",
      outputs: [{ internalType: "uint256[]", name: "", type: "uint256[]" }],
      stateMutability: "view",
      type: "function",
    },
    {
      inputs: [],
      name: "setLotto",
      outputs: [{ internalType: "uint256[]", name: "", type: "uint256[]" }],
      stateMutability: "nonpayable",
      type: "function",
    },
  ];

  const [account, setAccount] = useState(null);
  const [balance, setBalance] = useState(0);
  const [web3, setWeb3] = useState(null);
  const [res, setRes] = useState("");
  const [lottoNums, setLottoNums] = useState([]);
  const [lotto, setLotto] = useState([]);

  useEffect(() => {
    (async () => {
      const [data] = await window.ethereum.request({
        method: "eth_requestAccounts",
      });
      setWeb3(new Web3(window.ethereum));
      setAccount(data);
    })();
  }, []);

  const getHistory = async () => {
    const getNumsHash = await web3.eth.abi.encodeFunctionCall(abi[1], []);
    const nums = await web3.eth.call({
      to: res,
      data: getNumsHash,
    });
    const hexString = nums;

    const decodedData = web3.eth.abi.decodeParameters(
      ["uint256[][]"],
      hexString
    );

    const historyNums = decodedData[0].map((subArr) =>
      subArr.map((el) => Number(el))
    );


    let temp="";


    temp += "<div>"
    historyNums.forEach((el) => {
      let arr = "";
      el.forEach((e)=>{
         arr += `<span>${e}, </span>`
      });
      temp += "</br>";
      temp += arr;
    });
    temp += "</div>"
    document.querySelector("#history").innerHTML = temp;


  };



  // 전체 번호를 가져옴
  const getnums = async () => {
    const view = document.getElementById("view");
    const getNumsHash = await web3.eth.abi.encodeFunctionCall(abi[2], []);
    const nums = await web3.eth.call({
      to: res,
      data: getNumsHash,
    });
    const hexString = nums;
    let arr = hexString.slice(2).match(/.{1,64}/g);
    arr.shift();
    let length = parseInt(arr.shift(), 16);
    arr = arr.slice(0, length).map((hex) => parseInt(hex, 16));

    view.innerHTML = arr;
    setLottoNums(arr);
  };

  const balanceBtn = async () => {
    const bal = await web3.eth.getBalance(account);
    const balance = await web3.utils.fromWei(bal, "ether");
    setBalance(balance);
  };

  const TransactionBtn = async () => {
    const bintext = document.getElementById("bintext");
    web3.eth
      .sendTransaction({
        from: account,
        gas: "3000000",
        data: bintext.value,
      })
      .then((e) => {
        setRes(e.contractAddress);
        // console.log(e.contractAddress);
      });
  };

  const selecLotto = async () => {
    const setLottoNums = await web3.eth.abi.encodeFunctionCall(abi[4], []);
    const tx = {
      from: account,
      to: res,
      data: setLottoNums,
      gas: 1500000,
      gasPrice: 200000000,
    };
    const data = await web3.eth.sendTransaction(tx);
    getSelecNums();
    getHistory();
  };

  const getSelecNums = async () => {
    const selecview = document.getElementById("selecview");
    const getNumsHash = await web3.eth.abi.encodeFunctionCall(abi[3], []);
    const nums = await web3.eth.call({
      to: res,
      data: getNumsHash,
    });
    const hexString = nums;
    let arr = hexString.slice(2).match(/.{1,64}/g);
    arr.shift();
    let length = parseInt(arr.shift(), 16);
    arr = arr.slice(0, length).map((hex) => parseInt(hex, 16));

    selecview.innerHTML = arr;
    setLotto(arr);
  };
  return (
    <div className="App">
      <div>
        <div>{account}</div>
        <div>{balance} ETH</div>
        <button onClick={balanceBtn}>잔액조회</button>
      </div>
      <div id="view"></div>
      <button onClick={getnums}>로또 전체 번호</button>

      <div id="selecview"></div>
      <button onClick={selecLotto}>로또 추첨</button>
      <div>
        <input type="text" placeholder="bin코드" id="bintext"></input>
        <button onClick={TransactionBtn}>트랜잭션 배포</button>
      </div>
      <div id="history"></div>
    </div>
  );
}

export default App;

 

728x90