ysheokorea / BEB-05-Team-Vote

지식 공유 학습 플랫폼 : 하브루타 DAO

Home Page:https://www.havruta.guru

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

지식 공유 학습 플랫폼 : 하브루타 DAO

  • 블록체인 기술 기반 토큰 이코노미를 활용하여 지속가능한 선순환 지식공유 학습 플랫폼을 구축
  • 민주적 방식의 커뮤니티 활동을 통해서 플랫폼 참여자들이 당면한 교육문제를 해결하는 블록체인 기반 탈중앙 교육 콘텐츠 플랫폼

MVC의 구축

  • MVCMinimum Viable Community의 약자로 커뮤니티 생성을 위해 필요한 최소 그룹(유저)
  • MVC의 초기 구축을 통해서 유저의 니즈를 빠르게 파악하여 빠른 확장을 도모함.
  • MVC는 리소스가 적게드는 장점이 있음.

백서

하브루타 DAO 백서 바로가기

배포 주소

하브루타 DAO 웹사이트 바로가기

하브루타 DAO 시연 영상

하브루타 DAO 시연 영상

  • 이미지 클릭 시 유튜브로 이동

하브루타 DAO 발표 영상

하브루타 DAO 발표 영상

  • 이미지 클릭 시 유튜브로 이동

하브루타 DAO의 토큰 이코노미

image <하브루타 DAO 토큰 이코노미 구조>

토큰의 보상 체계

  • 유저들에게 공평한 토큰 보상을 위해 투표 프로세스를 통해 공평한 참여의 기회 보장
  • 첫번째 단계, 사용자들의 참여도에 따라 매일 고정된 화폐 분배 금액을 결정
  • 두번째 단계, 지속가능한 참여를 높이기 위해 콘텐츠 생성과 평가 보상의 유기적인 체계를 구성

지속가능한 하브루타 DAO의 생태계

(1) 커뮤니티 활동에 참여

하브루타 DAO의 사용자는 커뮤니티 활동을 통해서 토큰을 보상 받을 수 있다. 토큰 보상의 비율은 하루 동안 참여한 커뮤니티 참여도에 비례하며 아래 공식과 같다.

image

  • Parameter a: 글 작성 수
  • Parameter c: 댓글 작성 수
  • Parameter l: 좋아요 활동 수

(2) 강의 콘텐츠 제작 활동

강의 콘텐츠 제작을 시작하려면 먼저 일정 수량의 토큰을 지불하여 콘텐츠 제작에 대한 비용을 소비하게된다. 이는 낮은 질의 강의 콘텐츠가 무분별하게 게시되는 행위를 방지할 수 있다. 이후 게시된 강의를 소비하는 사용자의 의하여 콘텐츠 생산자가 지정한 비용의 토큰을 보상으로 받을 수 있다.

토큰보상량의 제한

하브루타 DAO의 사용자에게 배포되는 총 토큰의 양은 제한이 없다. 그러나 무제한적인 토큰 양의 증가는 인플레이션을 초래하며 이를 방지하기 위해 하루에 발행되는 토큰의 양이 제한 된다. 현재 초기 하루 발행량은 500개로 제한 되며, 해당 수량은 인플레이션의 추이에 따라 변동이 가능하다.

image

  • μ = 하루 총 토큰 발행 제한량
  • α = 하루 총 토큰 발행량

토큰 소비

(1) 강의 콘텐츠 생성 시

하브루타 DAO의 사용자가 강의 콘텐츠를 생성할 경우 일정량의 토큰이 소요된다. 이 경우 사용된 토큰은 다시 사용할 수 없는 토큰이 되며 이는 강의 생성 시 비용의 개념으로 처리된다. 지식을 공유하는 이가 토큰을 소비함으로써 토큰 획득 만을 위한 무분별한 강의 생성을 방지하기 위함이다.

(2) 강의 콘텐츠 소비

하브루타 DAO의 사용자는 자신이 갖고 있는 토큰을 활용하여 강의 콘텐츠를 수강 할 수 있으며, 기타 활동을 영위할 수 있다. 모든 토큰 소진 시 부족한 토큰은 커뮤니티 활동으로 보충이 가능하다.

(3) HADA PASS NFT 발행

사용자는 일정 토큰을 소비하여 HADA PASS를 구매할 수 있다. HADA PASS를 보유한 사용자는 하브루타 DAO 내 모든 강의를 무료로 수강할 수 있다. HADA PASS의 유효 기간을 설정하여, HADA PASS의 가치가 무한으로 높아지는 것을 방지한다. 일정 주기마다 새로운 NFT를 발행하여 사용자는 HADA PASS를 갱신해야 한다. HADA PASS를 구매하는 데 사용된 토큰은 다시 사용할 수 없는 토큰이 된다.

DAO 투표 (Snapshot 사용)

  • 하브루타 DAO 는 각 유저에게 토큰을 가진 구성원들에게 의결권을 배부하고, 1인 1표제를 채택한다. 블록체인 기술에 기반하여 투표를 통해 다양한 안건에 관해 의사결정을 할 수 있다.
  • 하브루타 DAO의 운영 방향도 투표를 통해 결정할 수 있다.

기술 스택 및 아키텍쳐

image

한 달이라는 시간안에 가장 생산성을 높히기 위한 기술들을 선별, 채택하였고, Team Vote의 구성원들이 하브루타 DAO 프로젝트를 통해 성장을 하여, 개발 업계로 나아갈 것을 고려하여 현재 개발 업계에서 선호하는 기술 스택들을 학습하도록 하였다. 따라서 해당 기술을 익히기 위해 Team Vote의 구성원들은 본격적인 프로젝트 개발 시작에 앞서 학습을 진행한 뒤 개발을 시작하였다. 하브루타 DAO 프로젝트에 사용한 기술 스택은 아래와 같다.

기술스택 목록

image

데이터베이스 스키마

image

피그마 디자인 목업

피그마 디자인 목업 바로가기

시작하기

git clone https://github.com/codestates/BEB-05-Team-Vote.git

빌드 및 실행

BEB-05-Team-Vote 디렉토리에서 아래 명령어를 통해 각각의 Application을 빌드하고 실행할 수 있습니다.

  • client

아래의 .env 파일이 필요합니다.

NEXT_PUBLIC_GA_ID= 구글 애널리틱스 key
NEXT_PUBLIC_SENTRY_DSN= 센트리 key
NEXT_PUBLIC_CHANNEL_IO_KEY= 채널톡 key
SECRET= solt값
NEXTAUTH_URL= 배포 주소
NEXT_PUBLIC_ENDPOINT= api 서버 엔드포인트
NEXT_PUBLIC_HADATOKEN= 토큰 컨트랙트 CA
NEXT_PUBLIC_HADAPASS_CA= NFT 컨트랙트 CA
cd client/havruta_dao
yarn
yarn dev
  • server

아래의 .env 파일이 필요합니다.

PORT=실행 포트
DATABASE_URL= 데이터베이스 주소
TOKEN_CA= 토큰 컨트랙트 CA
BATCH_CA= 토큰 배치 컨트랙트 CA
PASS_CA= NFT 컨트랙트 CA
DEPLOY_ADDRESS= 컨트랙트 배포 계정 공개키
DEPLOY_PRIVATEKEY= 컨트랙트 배포 계정 비밀키
cd server
yarn
yarn postinstall
yarn dev

애플리케이션 워크플로우

주요 기능

  1. 로그인(지갑연결)

  2. 커뮤니티

    • 게시글 업로드 (실기간 글 업데이트 기능)
    • 게시글 상세보기 페이지 이동
    • 좋아요
    • 댓글
    • 삭제
    • 유저 프로필 바로보기
  3. 지식 공유(강의 업로드)

    • 각 항목 입력 후 업로드
    • 각 항목의 validation 체크 등
  4. 강의 탐색(강의 수강하기)

    • 강의탐색 페이지 이동 후 강의 선택
    • 수강신청시 토큰 소비
    • 강의실로 이동하기
    • 강의 수강
  5. 마이페이지

    • 내 정보 수정
    • 내가 쓴 글, 댓글 목록 확인
    • 수강 중인 강의, 생성한 강의 확인
    • 하다토큰 지갑에 추가
    • 패스 발행
  6. DAO 투표(snapshot)

컨트랙트 생성

하브루타 DAO에서는 세 종류의 컨트랙트가 사용됩니다. 하나는 ERC-20 토큰 컨트랙트이며, 하나는 토큰을 여러 계정에 한 번에 보낼 수 있는 배치 컨트랙트, 마지막으로 ERC-721 컨트랙드가 존재합니다.

ERC-20 컨트랙트는 처음에 배치 컨트랙트의 CA를 설정하여 유저들의 포인트들 합산한 점수만큼의 토큰을 배치 컨트랙트에 민팅하게 됩니다. 또한 ERC-20 컨트랙트에 있는 토큰을 소각할 수도 있습니다.

  • HadaToken.sol
... 중략

function updateBatchContractAdress(address _adress) public onlyOwner  {
        batchContractAdress = _adress;
        emit NewBatchContractAdress(_adress);
    }

    function mint( uint256 _amount) public onlyOwner isBatchContract{
        _mint(batchContractAdress, _amount);
    }

    function burn(uint256 amount) public override onlyOwner{
        _burn(address(this), amount);
    }

배치 컨트랙트도 마찬가지로 처음에 토큰 컨트랙트의 CA를 설정해야 합니다. 배치 컨트랙트는 유저들의 주소와 배분할 토큰의 양을 받으면 API 서버에 의해 UTC 기준 매일 0시 0분에 유저들에게 토큰을 분배하게 됩니다.

  • HADATokenBatch.sol
...중략

 function updateTokenContractAdress(address _adress) public onlyOwner {

        tokenContractAdress = ERC20(_adress);
        _tokenContractAdress = _adress;

        emit NewTokenContractAdress(_adress);
    }

... 중략

    function batchTransfer(address[] calldata _address, uint256[] calldata _amounts) external onlyOwner isTokenContract{
        require(_address.length == _amounts.length, "Invalid input parameters");

        for(uint256 i = 0; i < _address.length; i++) {
            require(tokenContractAdress.transfer(_address[i], _amounts[i]), "Unable to transfer token to the account");
        }
    }

ERC-721 컨트랙트는 앞서 배포한 ERC-20 컨트랙트의 토큰으로 NFT를 민팅할 수 있는 기능이 있습니다. NFT의 가격또한 함수로 지정할 수 있습니다.

  • HADAPASS2022.sol
... 중략

    function updateTokenContractAdress (address tokenAddress) public onlyOwner returns (bool) {
        require(tokenAddress != address(0x0));
        token = IERC20(tokenAddress);
        _tokenAdress = tokenAddress;
        return true;
    }

    function updateNFTPrice(uint256 _value) public onlyOwner  {
        nftPrice = _value;
        emit NewNFTPrice(_value);
    }

    function mintNFT(address recipient, string memory tokenURI) public returns (uint256) {
        require(nftPrice > 0, "you must set nft price!");
        require(token.balanceOf(recipient) > nftPrice);

        token.transferFrom(recipient, _tokenAdress, nftPrice);

        _tokenIds.increment();
        uint256 newItemId = _tokenIds.current();
        _mint(recipient, newItemId);
        _setTokenURI(newItemId, tokenURI);

        return newItemId;
    }

클라이언트에서 트랜잭션 생성

클라이언트에서도 배포한 컨트랙트의 CA 주소로 직접 발행한 ERC-20 토큰을 거래할 수 있습니다. 이 프로젝트에서는 클레이튼을 사용하였기 때문에 로직은 아래와 같습니다.

const data = window.caver.klay.abi.encodeFunctionCall(
  {
    name: 'transfer',
    type: 'function',
    inputs: [
      {
        type: 'address',
        name: 'recipient',
      },
      {
        type: 'uint256',
        name: 'amount',
      },
    ],
  },
  [
    user_address,
    window.caver.utils
      .toBN(price)
      .mul(window.caver.utils.toBN(Number(`1e18`)))
      .toString(),
  ]
);

window.caver.klay
  .sendTransaction({
    type: 'SMART_CONTRACT_EXECUTION',
    from: window.klaytn?.selectedAddress,
    to: process.env.NEXT_PUBLIC_HADATOKEN,
    data,
    gas: '3000000',
  })
  .on('transactionHash', (transactionHash: any) => {
    console.log('txHash', transactionHash);
  })
  .on('receipt', (receipt: any) => {
    console.log('receipt', receipt);
  })
  .on('error', (error: any) => {
    console.log('error', error.message);
  });

팀원

팀명 : Team Vote

직위 직무 이름 Github
팀장 프론트엔드, 스마트 컨트랙트, 인프라 윤태희 https://github.com/thyoondev
팀원 백엔드, 인프라 윤장원 https://github.com/yjjjwww
팀원 디자인, 프론트엔드 이성만 https://github.com/sungman5
팀원 프론트엔드 김윤미 https://github.com/yoonmi-cyber
팀원 백엔드 이동현 https://github.com/dhjefflee

About

지식 공유 학습 플랫폼 : 하브루타 DAO

https://www.havruta.guru


Languages

Language:TypeScript 87.5%Language:JavaScript 8.8%Language:Solidity 2.0%Language:Shell 1.1%Language:Less 0.4%Language:CSS 0.2%Language:Dockerfile 0.1%