- ๋ธ๋ก์ฒด์ธ ๊ธฐ์ ๊ธฐ๋ฐ ํ ํฐ ์ด์ฝ๋ ธ๋ฏธ๋ฅผ ํ์ฉํ์ฌ ์ง์๊ฐ๋ฅํ ์ ์ํ ์ง์๊ณต์ ํ์ต ํ๋ซํผ์ ๊ตฌ์ถ
- ๋ฏผ์ฃผ์ ๋ฐฉ์์ ์ปค๋ฎค๋ํฐ ํ๋์ ํตํด์ ํ๋ซํผ ์ฐธ์ฌ์๋ค์ด ๋น๋ฉดํ ๊ต์ก๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ธ๋ก์ฒด์ธ ๊ธฐ๋ฐ ํ์ค์ ๊ต์ก ์ฝํ ์ธ ํ๋ซํผ
- MVC๋ Minimum Viable Community์ ์ฝ์๋ก ์ปค๋ฎค๋ํฐ ์์ฑ์ ์ํด ํ์ํ ์ต์ ๊ทธ๋ฃน(์ ์ )
- MVC์ ์ด๊ธฐ ๊ตฌ์ถ์ ํตํด์ ์ ์ ์ ๋์ฆ๋ฅผ ๋น ๋ฅด๊ฒ ํ์ ํ์ฌ ๋น ๋ฅธ ํ์ฅ์ ๋๋ชจํจ.
- MVC๋ ๋ฆฌ์์ค๊ฐ ์ ๊ฒ๋๋ ์ฅ์ ์ด ์์.
ํ๋ธ๋ฃจํ DAO ๋ฐฑ์ ๋ฐ๋ก๊ฐ๊ธฐ
ํ๋ธ๋ฃจํ DAO ์น์ฌ์ดํธ ๋ฐ๋ก๊ฐ๊ธฐ
- ์ด๋ฏธ์ง ํด๋ฆญ ์ ์ ํ๋ธ๋ก ์ด๋
- ์ด๋ฏธ์ง ํด๋ฆญ ์ ์ ํ๋ธ๋ก ์ด๋
<ํ๋ธ๋ฃจํ DAO ํ ํฐ ์ด์ฝ๋ ธ๋ฏธ ๊ตฌ์กฐ>
- ์ ์ ๋ค์๊ฒ ๊ณตํํ ํ ํฐ ๋ณด์์ ์ํด ํฌํ ํ๋ก์ธ์ค๋ฅผ ํตํด ๊ณตํํ ์ฐธ์ฌ์ ๊ธฐํ ๋ณด์ฅ
- ์ฒซ๋ฒ์งธ ๋จ๊ณ, ์ฌ์ฉ์๋ค์ ์ฐธ์ฌ๋์ ๋ฐ๋ผ ๋งค์ผ ๊ณ ์ ๋ ํํ ๋ถ๋ฐฐ ๊ธ์ก์ ๊ฒฐ์
- ๋๋ฒ์งธ ๋จ๊ณ, ์ง์๊ฐ๋ฅํ ์ฐธ์ฌ๋ฅผ ๋์ด๊ธฐ ์ํด ์ฝํ ์ธ ์์ฑ๊ณผ ํ๊ฐ ๋ณด์์ ์ ๊ธฐ์ ์ธ ์ฒด๊ณ๋ฅผ ๊ตฌ์ฑ
ํ๋ธ๋ฃจํ DAO์ ์ฌ์ฉ์๋ ์ปค๋ฎค๋ํฐ ํ๋์ ํตํด์ ํ ํฐ์ ๋ณด์ ๋ฐ์ ์ ์๋ค. ํ ํฐ ๋ณด์์ ๋น์จ์ ํ๋ฃจ ๋์ ์ฐธ์ฌํ ์ปค๋ฎค๋ํฐ ์ฐธ์ฌ๋์ ๋น๋กํ๋ฉฐ ์๋ ๊ณต์๊ณผ ๊ฐ๋ค.
- Parameter a: ๊ธ ์์ฑ ์
- Parameter c: ๋๊ธ ์์ฑ ์
- Parameter l: ์ข์์ ํ๋ ์
๊ฐ์ ์ฝํ ์ธ ์ ์์ ์์ํ๋ ค๋ฉด ๋จผ์ ์ผ์ ์๋์ ํ ํฐ์ ์ง๋ถํ์ฌ ์ฝํ ์ธ ์ ์์ ๋ํ ๋น์ฉ์ ์๋นํ๊ฒ๋๋ค. ์ด๋ ๋ฎ์ ์ง์ ๊ฐ์ ์ฝํ ์ธ ๊ฐ ๋ฌด๋ถ๋ณํ๊ฒ ๊ฒ์๋๋ ํ์๋ฅผ ๋ฐฉ์งํ ์ ์๋ค. ์ดํ ๊ฒ์๋ ๊ฐ์๋ฅผ ์๋นํ๋ ์ฌ์ฉ์์ ์ํ์ฌ ์ฝํ ์ธ ์์ฐ์๊ฐ ์ง์ ํ ๋น์ฉ์ ํ ํฐ์ ๋ณด์์ผ๋ก ๋ฐ์ ์ ์๋ค.
ํ๋ธ๋ฃจํ DAO์ ์ฌ์ฉ์์๊ฒ ๋ฐฐํฌ๋๋ ์ด ํ ํฐ์ ์์ ์ ํ์ด ์๋ค. ๊ทธ๋ฌ๋ ๋ฌด์ ํ์ ์ธ ํ ํฐ ์์ ์ฆ๊ฐ๋ ์ธํ๋ ์ด์ ์ ์ด๋ํ๋ฉฐ ์ด๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด ํ๋ฃจ์ ๋ฐํ๋๋ ํ ํฐ์ ์์ด ์ ํ ๋๋ค. ํ์ฌ ์ด๊ธฐ ํ๋ฃจ ๋ฐํ๋์ 500๊ฐ๋ก ์ ํ ๋๋ฉฐ, ํด๋น ์๋์ ์ธํ๋ ์ด์ ์ ์ถ์ด์ ๋ฐ๋ผ ๋ณ๋์ด ๊ฐ๋ฅํ๋ค.
- ฮผ = ํ๋ฃจ ์ด ํ ํฐ ๋ฐํ ์ ํ๋
- ฮฑ = ํ๋ฃจ ์ด ํ ํฐ ๋ฐํ๋
ํ๋ธ๋ฃจํ DAO์ ์ฌ์ฉ์๊ฐ ๊ฐ์ ์ฝํ ์ธ ๋ฅผ ์์ฑํ ๊ฒฝ์ฐ ์ผ์ ๋์ ํ ํฐ์ด ์์๋๋ค. ์ด ๊ฒฝ์ฐ ์ฌ์ฉ๋ ํ ํฐ์ ๋ค์ ์ฌ์ฉํ ์ ์๋ ํ ํฐ์ด ๋๋ฉฐ ์ด๋ ๊ฐ์ ์์ฑ ์ ๋น์ฉ์ ๊ฐ๋ ์ผ๋ก ์ฒ๋ฆฌ๋๋ค. ์ง์์ ๊ณต์ ํ๋ ์ด๊ฐ ํ ํฐ์ ์๋นํจ์ผ๋ก์จ ํ ํฐ ํ๋ ๋ง์ ์ํ ๋ฌด๋ถ๋ณํ ๊ฐ์ ์์ฑ์ ๋ฐฉ์งํ๊ธฐ ์ํจ์ด๋ค.
ํ๋ธ๋ฃจํ DAO์ ์ฌ์ฉ์๋ ์์ ์ด ๊ฐ๊ณ ์๋ ํ ํฐ์ ํ์ฉํ์ฌ ๊ฐ์ ์ฝํ ์ธ ๋ฅผ ์๊ฐ ํ ์ ์์ผ๋ฉฐ, ๊ธฐํ ํ๋์ ์์ํ ์ ์๋ค. ๋ชจ๋ ํ ํฐ ์์ง ์ ๋ถ์กฑํ ํ ํฐ์ ์ปค๋ฎค๋ํฐ ํ๋์ผ๋ก ๋ณด์ถฉ์ด ๊ฐ๋ฅํ๋ค.
์ฌ์ฉ์๋ ์ผ์ ํ ํฐ์ ์๋นํ์ฌ HADA PASS๋ฅผ ๊ตฌ๋งคํ ์ ์๋ค. HADA PASS๋ฅผ ๋ณด์ ํ ์ฌ์ฉ์๋ ํ๋ธ๋ฃจํ DAO ๋ด ๋ชจ๋ ๊ฐ์๋ฅผ ๋ฌด๋ฃ๋ก ์๊ฐํ ์ ์๋ค. HADA PASS์ ์ ํจ ๊ธฐ๊ฐ์ ์ค์ ํ์ฌ, HADA PASS์ ๊ฐ์น๊ฐ ๋ฌดํ์ผ๋ก ๋์์ง๋ ๊ฒ์ ๋ฐฉ์งํ๋ค. ์ผ์ ์ฃผ๊ธฐ๋ง๋ค ์๋ก์ด NFT๋ฅผ ๋ฐํํ์ฌ ์ฌ์ฉ์๋ HADA PASS๋ฅผ ๊ฐฑ์ ํด์ผ ํ๋ค. HADA PASS๋ฅผ ๊ตฌ๋งคํ๋ ๋ฐ ์ฌ์ฉ๋ ํ ํฐ์ ๋ค์ ์ฌ์ฉํ ์ ์๋ ํ ํฐ์ด ๋๋ค.
- ํ๋ธ๋ฃจํ DAO ๋ ๊ฐ ์ ์ ์๊ฒ ํ ํฐ์ ๊ฐ์ง ๊ตฌ์ฑ์๋ค์๊ฒ ์๊ฒฐ๊ถ์ ๋ฐฐ๋ถํ๊ณ , 1์ธ 1ํ์ ๋ฅผ ์ฑํํ๋ค. ๋ธ๋ก์ฒด์ธ ๊ธฐ์ ์ ๊ธฐ๋ฐํ์ฌ ํฌํ๋ฅผ ํตํด ๋ค์ํ ์๊ฑด์ ๊ดํด ์์ฌ๊ฒฐ์ ์ ํ ์ ์๋ค.
- ํ๋ธ๋ฃจํ DAO์ ์ด์ ๋ฐฉํฅ๋ ํฌํ๋ฅผ ํตํด ๊ฒฐ์ ํ ์ ์๋ค.
ํ ๋ฌ์ด๋ผ๋ ์๊ฐ์์ ๊ฐ์ฅ ์์ฐ์ฑ์ ๋ํ๊ธฐ ์ํ ๊ธฐ์ ๋ค์ ์ ๋ณ, ์ฑํํ์๊ณ , Team Vote์ ๊ตฌ์ฑ์๋ค์ด ํ๋ธ๋ฃจํ DAO ํ๋ก์ ํธ๋ฅผ ํตํด ์ฑ์ฅ์ ํ์ฌ, ๊ฐ๋ฐ ์ ๊ณ๋ก ๋์๊ฐ ๊ฒ์ ๊ณ ๋ คํ์ฌ ํ์ฌ ๊ฐ๋ฐ ์ ๊ณ์์ ์ ํธํ๋ ๊ธฐ์ ์คํ๋ค์ ํ์ตํ๋๋ก ํ์๋ค. ๋ฐ๋ผ์ ํด๋น ๊ธฐ์ ์ ์ตํ๊ธฐ ์ํด Team Vote์ ๊ตฌ์ฑ์๋ค์ ๋ณธ๊ฒฉ์ ์ธ ํ๋ก์ ํธ ๊ฐ๋ฐ ์์์ ์์ ํ์ต์ ์งํํ ๋ค ๊ฐ๋ฐ์ ์์ํ์๋ค. ํ๋ธ๋ฃจํ DAO ํ๋ก์ ํธ์ ์ฌ์ฉํ ๊ธฐ์ ์คํ์ ์๋์ ๊ฐ๋ค.
ํผ๊ทธ๋ง ๋์์ธ ๋ชฉ์ ๋ฐ๋ก๊ฐ๊ธฐ
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
-
๋ก๊ทธ์ธ(์ง๊ฐ์ฐ๊ฒฐ)
-
์ปค๋ฎค๋ํฐ
- ๊ฒ์๊ธ ์ ๋ก๋ (์ค๊ธฐ๊ฐ ๊ธ ์ ๋ฐ์ดํธ ๊ธฐ๋ฅ)
- ๊ฒ์๊ธ ์์ธ๋ณด๊ธฐ ํ์ด์ง ์ด๋
- ์ข์์
- ๋๊ธ
- ์ญ์
- ์ ์ ํ๋กํ ๋ฐ๋ก๋ณด๊ธฐ
-
์ง์ ๊ณต์ (๊ฐ์ ์ ๋ก๋)
- ๊ฐ ํญ๋ชฉ ์ ๋ ฅ ํ ์ ๋ก๋
- ๊ฐ ํญ๋ชฉ์ validation ์ฒดํฌ ๋ฑ
-
๊ฐ์ ํ์(๊ฐ์ ์๊ฐํ๊ธฐ)
- ๊ฐ์ํ์ ํ์ด์ง ์ด๋ ํ ๊ฐ์ ์ ํ
- ์๊ฐ์ ์ฒญ์ ํ ํฐ ์๋น
- ๊ฐ์์ค๋ก ์ด๋ํ๊ธฐ
- ๊ฐ์ ์๊ฐ
-
๋ง์ดํ์ด์ง
- ๋ด ์ ๋ณด ์์
- ๋ด๊ฐ ์ด ๊ธ, ๋๊ธ ๋ชฉ๋ก ํ์ธ
- ์๊ฐ ์ค์ธ ๊ฐ์, ์์ฑํ ๊ฐ์ ํ์ธ
- ํ๋คํ ํฐ ์ง๊ฐ์ ์ถ๊ฐ
- ํจ์ค ๋ฐํ
-
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);
});
์ง์ | ์ง๋ฌด | ์ด๋ฆ | Github |
---|---|---|---|
ํ์ฅ | ํ๋ก ํธ์๋, ์ค๋งํธ ์ปจํธ๋ํธ, ์ธํ๋ผ | ์คํํฌ | https://github.com/thyoondev |
ํ์ | ๋ฐฑ์๋, ์ธํ๋ผ | ์ค์ฅ์ | https://github.com/yjjjwww |
ํ์ | ๋์์ธ, ํ๋ก ํธ์๋ | ์ด์ฑ๋ง | https://github.com/sungman5 |
ํ์ | ํ๋ก ํธ์๋ | ๊น์ค๋ฏธ | https://github.com/yoonmi-cyber |
ํ์ | ๋ฐฑ์๋ | ์ด๋ํ | https://github.com/dhjefflee |