Ver3.0
์ ์ฒด ์ด๋
Ver3.0 ๐ช ํ์ด์ฌ์ผ๋ก ํ ํฐ ๋ฐํ๋ ์ ์ด ์คํฌ๋ฆฝํธ ์์ฑํ๊ธฐ

๐ช ํ์ด์ฌ์ผ๋ก ํ ํฐ ๋ฐํ๋ ์ ์ด ์คํฌ๋ฆฝํธ ์์ฑํ๊ธฐ
๋ธ๋ก์ฒด์ธ ์ธ์์์ ๋ด ์์ผ๋ก ํ ํฐ ๊ฒฝ์ ๋ฅผ ์ค๊ณํ๋ ๋ฐฉ๋ฒ ๐
์๋
! ๐ ์ค๋์ ๋ธ๋ก์ฒด์ธ ์ธ๊ณ์์ ์ ๋ง ์ค์ํ ์ฃผ์ ๋ฅผ ๋ค๋ค๋ณผ ๊ฑฐ์ผ. ๋ฐ๋ก ํ ํฐ ๋ฐํ๋ ์ ์ด์ ๋ํ ์ด์ผ๊ธฐ์ธ๋ฐ, ์ด๊ฒ ์ ์ค์ํ๋๊ณ ? ๐ค
์๊ฐํด๋ด. ๋นํธ์ฝ์ธ์ ์ 2,100๋ง ๊ฐ๋ก ์ ํ๋์ด ์์๊น? ์ด๋๋ฆฌ์์ ์ ๋งค๋ ์ผ์ ๋๋ง ๋ฐํ๋ ๊น? ๋ฐ๋ก ํฌ์์ฑ๊ณผ ๊ฐ์น ๋ณด์กด ๋๋ฌธ์ด์ผ. ๋ง์ฝ ๋๊ตฐ๊ฐ ๋ง์๋๋ก ํ ํฐ์ ๋ฌดํ์ ์ฐ์ด๋ผ ์ ์๋ค๋ฉด? ๊ทธ๊ฑด ์ง๋ฐ๋ธ์จ ๋ฌ๋ฌ์ฒ๋ผ ํด์ง์กฐ๊ฐ์ด ๋๋ ๊ฑฐ์ง. ๐ธ
์ค๋ ์ฐ๋ฆฌ๋ ํ์ด์ฌ์ ํ์ฉํด์ ์ค์ ๋ก ํ ํฐ ๋ฐํ๋์ ์ ์ดํ๋ ์คํฌ๋ฆฝํธ๋ฅผ ๋ง๋ค์ด๋ณผ ๊ฑฐ์ผ. ๋จ์ํ ์ฝ๋๋ง ์์ฑํ๋ ๊ฒ ์๋๋ผ, ์ ์ด๋ฐ ๋ฉ์ปค๋์ฆ์ด ํ์ํ์ง, ์ค์ ํ๋ก์ ํธ์์๋ ์ด๋ป๊ฒ ํ์ฉ๋๋์ง๊น์ง ๊น์ด ์๊ฒ ํํค์ณ๋ณผ๊ฒ! ๐
์๊ฐํด๋ด. ๋นํธ์ฝ์ธ์ ์ 2,100๋ง ๊ฐ๋ก ์ ํ๋์ด ์์๊น? ์ด๋๋ฆฌ์์ ์ ๋งค๋ ์ผ์ ๋๋ง ๋ฐํ๋ ๊น? ๋ฐ๋ก ํฌ์์ฑ๊ณผ ๊ฐ์น ๋ณด์กด ๋๋ฌธ์ด์ผ. ๋ง์ฝ ๋๊ตฐ๊ฐ ๋ง์๋๋ก ํ ํฐ์ ๋ฌดํ์ ์ฐ์ด๋ผ ์ ์๋ค๋ฉด? ๊ทธ๊ฑด ์ง๋ฐ๋ธ์จ ๋ฌ๋ฌ์ฒ๋ผ ํด์ง์กฐ๊ฐ์ด ๋๋ ๊ฑฐ์ง. ๐ธ
์ค๋ ์ฐ๋ฆฌ๋ ํ์ด์ฌ์ ํ์ฉํด์ ์ค์ ๋ก ํ ํฐ ๋ฐํ๋์ ์ ์ดํ๋ ์คํฌ๋ฆฝํธ๋ฅผ ๋ง๋ค์ด๋ณผ ๊ฑฐ์ผ. ๋จ์ํ ์ฝ๋๋ง ์์ฑํ๋ ๊ฒ ์๋๋ผ, ์ ์ด๋ฐ ๋ฉ์ปค๋์ฆ์ด ํ์ํ์ง, ์ค์ ํ๋ก์ ํธ์์๋ ์ด๋ป๊ฒ ํ์ฉ๋๋์ง๊น์ง ๊น์ด ์๊ฒ ํํค์ณ๋ณผ๊ฒ! ๐
๐ฏ ํ ํฐ ๋ฐํ๋ ์ ์ด๊ฐ ๋ญ๊ธธ๋?
ํ ํฐ ๋ฐํ๋ ์ ์ด(Token Supply Control)๋ ๋ง ๊ทธ๋๋ก ๋ธ๋ก์ฒด์ธ ๋คํธ์ํฌ์์ ํ ํฐ์ด ์ผ๋ง๋, ์ธ์ , ์ด๋ป๊ฒ ๋ฐํ๋๋์ง๋ฅผ ๊ด๋ฆฌํ๋ ์์คํ
์ด์ผ. ์ด๊ฑด ๋จ์ํ ์ซ์ ๊ฒ์์ด ์๋๋ผ, ์ ์ฒด ํ ํฐ ๊ฒฝ์ (Tokenomics)์ ํต์ฌ์ด์ง. ๐ก
์ค์ ๋ก ๋ง์ ๋ธ๋ก์ฒด์ธ ํ๋ก์ ํธ๋ค์ด ์ด๊ธฐ์ ํ ํฐ ๋ฐํ๋ ์ค๊ณ๋ฅผ ์๋ชปํด์ ๋งํ์ด. ๋๋ฌด ๋ง์ด ๋ฐํํด์ ๊ฐ์น๊ฐ ํญ๋ฝํ๊ฑฐ๋, ๋ฐ๋๋ก ๋๋ฌด ์ ๊ฒ ๋ฐํํด์ ์ ๋์ฑ ๋ฌธ์ ๊ฐ ์๊ธฐ๊ฑฐ๋. ๊ทธ๋์ ์ฐ๋ฆฌ๊ฐ ๋ฐฐ์ธ ๋ด์ฉ์ ๋จ์ํ ์ฝ๋ฉ ์คํฌ์ด ์๋๋ผ, ์ค์ ํ ํฐ ๊ฒฝ์ ์ค๊ณ ๋ฅ๋ ฅ์ด์ผ! ๐
์ค์ ๋ก ๋ง์ ๋ธ๋ก์ฒด์ธ ํ๋ก์ ํธ๋ค์ด ์ด๊ธฐ์ ํ ํฐ ๋ฐํ๋ ์ค๊ณ๋ฅผ ์๋ชปํด์ ๋งํ์ด. ๋๋ฌด ๋ง์ด ๋ฐํํด์ ๊ฐ์น๊ฐ ํญ๋ฝํ๊ฑฐ๋, ๋ฐ๋๋ก ๋๋ฌด ์ ๊ฒ ๋ฐํํด์ ์ ๋์ฑ ๋ฌธ์ ๊ฐ ์๊ธฐ๊ฑฐ๋. ๊ทธ๋์ ์ฐ๋ฆฌ๊ฐ ๋ฐฐ์ธ ๋ด์ฉ์ ๋จ์ํ ์ฝ๋ฉ ์คํฌ์ด ์๋๋ผ, ์ค์ ํ ํฐ ๊ฒฝ์ ์ค๊ณ ๋ฅ๋ ฅ์ด์ผ! ๐
๐ฐ ํ ํฐ ๋ฐํ๋ ์ ์ด์ ํต์ฌ ์์๋ค
1. ์ด ๋ฐํ๋(Total Supply) - ์ ์ฒด ํ ํฐ์ ์ต๋ ์๋
2. ์ด๊ธฐ ๋ฐํ๋(Initial Supply) - ์ฒ์ ์์ํ ๋ ๋ฐํ๋๋ ์
3. ๋ฐํ ์๋(Emission Rate) - ์๊ฐ๋น/๋ธ๋ก๋น ๋ฐํ๋๋ ์
4. ์๊ฐ ๋ฉ์ปค๋์ฆ(Burn Mechanism) - ํ ํฐ์ ์ ๊ฑฐํ๋ ๋ฐฉ๋ฒ
5. ๋ฒ ์คํ (Vesting) - ์๊ฐ์ ๋ฐ๋ผ ์ ์ง์ ์ผ๋ก ํ๋ฆฌ๋ ๊ตฌ์กฐ
1. ์ด ๋ฐํ๋(Total Supply) - ์ ์ฒด ํ ํฐ์ ์ต๋ ์๋
2. ์ด๊ธฐ ๋ฐํ๋(Initial Supply) - ์ฒ์ ์์ํ ๋ ๋ฐํ๋๋ ์
3. ๋ฐํ ์๋(Emission Rate) - ์๊ฐ๋น/๋ธ๋ก๋น ๋ฐํ๋๋ ์
4. ์๊ฐ ๋ฉ์ปค๋์ฆ(Burn Mechanism) - ํ ํฐ์ ์ ๊ฑฐํ๋ ๋ฐฉ๋ฒ
5. ๋ฒ ์คํ (Vesting) - ์๊ฐ์ ๋ฐ๋ผ ์ ์ง์ ์ผ๋ก ํ๋ฆฌ๋ ๊ตฌ์กฐ
๐ ์ค์ ํ๋ก์ ํธ ์ฌ๋ก ๋ถ์
์ด๋ก ๋ง ๋ฐฐ์ฐ๋ฉด ์ฌ๋ฏธ์์์? ์ค์ ์ ๋ช
ํ๋ก์ ํธ๋ค์ด ์ด๋ป๊ฒ ํ ํฐ ๋ฐํ๋์ ์ ์ดํ๋์ง ์ดํด๋ณด์! ๐
๋นํธ์ฝ์ธ(Bitcoin) ๐
๋นํธ์ฝ์ธ์ ๊ฐ์ฅ ๋จ์ํ๋ฉด์๋ ๊ฐ๋ ฅํ ๋ชจ๋ธ์ด์ผ. ์ด 2,100๋ง ๊ฐ๋ก ์ ํ๋์ด ์๊ณ , ์ฝ 4๋ ๋ง๋ค ๋ฐํ๋์ด ์ ๋ฐ์ผ๋ก ์ค์ด๋๋ '๋ฐ๊ฐ๊ธฐ(Halving)' ๋ฉ์ปค๋์ฆ์ ์ฌ์ฉํด. ์ฒ์์ ๋ธ๋ก๋น 50 BTC์๋๋ฐ, ์ง๊ธ์ 6.25 BTC์ผ. 2140๋ ์ฏค ๋๋ฉด ๋ชจ๋ ๋นํธ์ฝ์ธ์ด ๋ฐํ ์๋ฃ๋ ๊ฑฐ์ผ. โฐ
์ด๋๋ฆฌ์(Ethereum) ๐ท
์ด๋๋ฆฌ์์ ์ด๊ธฐ์ ์ด ๋ฐํ๋ ์ ํ์ด ์์์ด. ํ์ง๋ง EIP-1559 ์ ๋ฐ์ดํธ ์ดํ ๊ฑฐ๋ ์์๋ฃ์ ์ผ๋ถ๋ฅผ ์๊ฐํ๋ฉด์ ์ฌ์ค์ ๋ํ๋ ์ด์ ์์ฐ์ด ๋์ง. ๋ฐํ๋๋ ์๋ณด๋ค ์๊ฐ๋๋ ์์ด ๋ ๋ง์ ๊ฒฝ์ฐ๋ ์๊ฒจ! ๐ฅ
๋ฐ์ด๋ธ์ค ์ฝ์ธ(BNB) ๐ก
BNB๋ ๋ถ๊ธฐ๋ง๋ค ์์ฒด ์์ต์ ์ผ๋ถ๋ก ํ ํฐ์ ๋งค์ ํด์ ์๊ฐํด. ์ด 2์ต ๊ฐ ์ค 1์ต ๊ฐ๊ฐ ์๊ฐ๋ ๋๊น์ง ๊ณ์๋ ์์ ์ด์ผ. ์ด๋ฐ ๊ฑธ 'Buy-back and Burn' ์ ๋ต์ด๋ผ๊ณ ํด. ๐ช
๋นํธ์ฝ์ธ(Bitcoin) ๐
๋นํธ์ฝ์ธ์ ๊ฐ์ฅ ๋จ์ํ๋ฉด์๋ ๊ฐ๋ ฅํ ๋ชจ๋ธ์ด์ผ. ์ด 2,100๋ง ๊ฐ๋ก ์ ํ๋์ด ์๊ณ , ์ฝ 4๋ ๋ง๋ค ๋ฐํ๋์ด ์ ๋ฐ์ผ๋ก ์ค์ด๋๋ '๋ฐ๊ฐ๊ธฐ(Halving)' ๋ฉ์ปค๋์ฆ์ ์ฌ์ฉํด. ์ฒ์์ ๋ธ๋ก๋น 50 BTC์๋๋ฐ, ์ง๊ธ์ 6.25 BTC์ผ. 2140๋ ์ฏค ๋๋ฉด ๋ชจ๋ ๋นํธ์ฝ์ธ์ด ๋ฐํ ์๋ฃ๋ ๊ฑฐ์ผ. โฐ
์ด๋๋ฆฌ์(Ethereum) ๐ท
์ด๋๋ฆฌ์์ ์ด๊ธฐ์ ์ด ๋ฐํ๋ ์ ํ์ด ์์์ด. ํ์ง๋ง EIP-1559 ์ ๋ฐ์ดํธ ์ดํ ๊ฑฐ๋ ์์๋ฃ์ ์ผ๋ถ๋ฅผ ์๊ฐํ๋ฉด์ ์ฌ์ค์ ๋ํ๋ ์ด์ ์์ฐ์ด ๋์ง. ๋ฐํ๋๋ ์๋ณด๋ค ์๊ฐ๋๋ ์์ด ๋ ๋ง์ ๊ฒฝ์ฐ๋ ์๊ฒจ! ๐ฅ
๋ฐ์ด๋ธ์ค ์ฝ์ธ(BNB) ๐ก
BNB๋ ๋ถ๊ธฐ๋ง๋ค ์์ฒด ์์ต์ ์ผ๋ถ๋ก ํ ํฐ์ ๋งค์ ํด์ ์๊ฐํด. ์ด 2์ต ๊ฐ ์ค 1์ต ๊ฐ๊ฐ ์๊ฐ๋ ๋๊น์ง ๊ณ์๋ ์์ ์ด์ผ. ์ด๋ฐ ๊ฑธ 'Buy-back and Burn' ์ ๋ต์ด๋ผ๊ณ ํด. ๐ช
๐ ๏ธ ๊ฐ๋ฐ ํ๊ฒฝ ์ค๋นํ๊ธฐ
์, ์ด์ ๋ณธ๊ฒฉ์ ์ผ๋ก ์ฝ๋ฉ์ ์์ํด๋ณผ๊น? ๋จผ์ ํ์ํ ๋๊ตฌ๋ค์ ์ค๋นํด์ผ ํด! ๐งฐ
โ
ํ์ํ ๊ฒ๋ค
โข Python 3.8 ์ด์
โข Web3.py ๋ผ์ด๋ธ๋ฌ๋ฆฌ (๋ธ๋ก์ฒด์ธ ์ํธ์์ฉ์ฉ)
โข eth-brownie ๋๋ Hardhat (์ค๋งํธ ์ปจํธ๋ํธ ๊ฐ๋ฐ์ฉ)
โข ๊ธฐ๋ณธ์ ์ธ ํ์ด์ฌ ์ง์
โข ๋ธ๋ก์ฒด์ธ ๊ธฐ์ด ๊ฐ๋ ์ดํด
โข Python 3.8 ์ด์
โข Web3.py ๋ผ์ด๋ธ๋ฌ๋ฆฌ (๋ธ๋ก์ฒด์ธ ์ํธ์์ฉ์ฉ)
โข eth-brownie ๋๋ Hardhat (์ค๋งํธ ์ปจํธ๋ํธ ๊ฐ๋ฐ์ฉ)
โข ๊ธฐ๋ณธ์ ์ธ ํ์ด์ฌ ์ง์
โข ๋ธ๋ก์ฒด์ธ ๊ธฐ์ด ๊ฐ๋ ์ดํด
๐ฆ ํ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค์น
pip install web3
pip install eth-brownie
pip install python-dotenv
pip install requests
์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ด ๊ฐ๊ฐ ์ด๋ค ์ญํ ์ ํ๋์ง ์์๋ณผ๊น? ๐ค
web3.py๋ ์ด๋๋ฆฌ์ ๋ธ๋ก์ฒด์ธ๊ณผ ์ํธ์์ฉํ๋ ํ์ด์ฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ผ. ์ค๋งํธ ์ปจํธ๋ํธ๋ฅผ ํธ์ถํ๊ณ , ํธ๋์ญ์ ์ ๋ณด๋ด๊ณ , ๋ธ๋ก์ฒด์ธ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ ์ ์์ด.
eth-brownie๋ ์ค๋งํธ ์ปจํธ๋ํธ ๊ฐ๋ฐ ํ๋ ์์ํฌ์ผ. ์ปจํธ๋ํธ๋ฅผ ์ปดํ์ผํ๊ณ , ํ ์คํธํ๊ณ , ๋ฐฐํฌํ๋ ์ ๊ณผ์ ์ ๊ด๋ฆฌํด์ค.
python-dotenv๋ ํ๊ฒฝ ๋ณ์๋ฅผ ์์ ํ๊ฒ ๊ด๋ฆฌํ๊ธฐ ์ํ ๊ฑฐ์ผ. API ํค๋ ๊ฐ์ธํค ๊ฐ์ ๋ฏผ๊ฐํ ์ ๋ณด๋ฅผ ์ฝ๋์ ์ง์ ๋ฃ์ง ์๊ณ ๊ด๋ฆฌํ ์ ์์ง.
requests๋ HTTP ์์ฒญ์ ๋ณด๋ด๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ผ. ์ธ๋ถ API์ ํต์ ํ ๋ ํ์ํด! ๐ก
web3.py๋ ์ด๋๋ฆฌ์ ๋ธ๋ก์ฒด์ธ๊ณผ ์ํธ์์ฉํ๋ ํ์ด์ฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ผ. ์ค๋งํธ ์ปจํธ๋ํธ๋ฅผ ํธ์ถํ๊ณ , ํธ๋์ญ์ ์ ๋ณด๋ด๊ณ , ๋ธ๋ก์ฒด์ธ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ ์ ์์ด.
eth-brownie๋ ์ค๋งํธ ์ปจํธ๋ํธ ๊ฐ๋ฐ ํ๋ ์์ํฌ์ผ. ์ปจํธ๋ํธ๋ฅผ ์ปดํ์ผํ๊ณ , ํ ์คํธํ๊ณ , ๋ฐฐํฌํ๋ ์ ๊ณผ์ ์ ๊ด๋ฆฌํด์ค.
python-dotenv๋ ํ๊ฒฝ ๋ณ์๋ฅผ ์์ ํ๊ฒ ๊ด๋ฆฌํ๊ธฐ ์ํ ๊ฑฐ์ผ. API ํค๋ ๊ฐ์ธํค ๊ฐ์ ๋ฏผ๊ฐํ ์ ๋ณด๋ฅผ ์ฝ๋์ ์ง์ ๋ฃ์ง ์๊ณ ๊ด๋ฆฌํ ์ ์์ง.
requests๋ HTTP ์์ฒญ์ ๋ณด๋ด๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ผ. ์ธ๋ถ API์ ํต์ ํ ๋ ํ์ํด! ๐ก
๐ป ๊ธฐ๋ณธ ํ ํฐ ์ปจํธ๋ํธ ๊ตฌ์กฐ ์ดํดํ๊ธฐ
ํ ํฐ ๋ฐํ๋์ ์ ์ดํ๋ ค๋ฉด ๋จผ์ ํ ํฐ ์ปจํธ๋ํธ๊ฐ ์ด๋ป๊ฒ ์๊ฒผ๋์ง ์์์ผ ํด. ERC-20 ํ์ค์ ๊ธฐ๋ฐ์ผ๋ก ํ ๊ธฐ๋ณธ ๊ตฌ์กฐ๋ฅผ ์ดํด๋ณด์! ๐
๐ ๊ธฐ๋ณธ ERC-20 ํ ํฐ ์ปจํธ๋ํธ (Solidity)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract ControlledToken {
string public name = "Controlled Token";
string public symbol = "CTK";
uint8 public decimals = 18;
uint256 public totalSupply;
uint256 public maxSupply = 1000000 * 10**18; // 100๋ง ๊ฐ ์ ํ
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
address public owner;
uint256 public emissionRate = 100 * 10**18; // ๋ธ๋ก๋น 100๊ฐ
uint256 public lastMintBlock;
event Transfer(address indexed from, address indexed to, uint256 value);
event Mint(address indexed to, uint256 amount);
event Burn(address indexed from, uint256 amount);
modifier onlyOwner() {
require(msg.sender == owner, "Not owner");
_;
}
constructor() {
owner = msg.sender;
lastMintBlock = block.number;
}
function mint(address to, uint256 amount) public onlyOwner {
require(totalSupply + amount <= maxSupply, "Exceeds max supply");
totalSupply += amount;
balanceOf[to] += amount;
emit Mint(to, amount);
emit Transfer(address(0), to, amount);
}
function burn(uint256 amount) public {
require(balanceOf[msg.sender] >= amount, "Insufficient balance");
balanceOf[msg.sender] -= amount;
totalSupply -= amount;
emit Burn(msg.sender, amount);
emit Transfer(msg.sender, address(0), amount);
}
function autoMint() public {
uint256 blocksPassed = block.number - lastMintBlock;
uint256 mintAmount = blocksPassed * emissionRate;
if (totalSupply + mintAmount > maxSupply) {
mintAmount = maxSupply - totalSupply;
}
if (mintAmount > 0) {
mint(owner, mintAmount);
lastMintBlock = block.number;
}
}
}
์ด ์ปจํธ๋ํธ์ ํต์ฌ ๊ธฐ๋ฅ๋ค์ ํ๋์ฉ ๋ฏ์ด๋ณด์! ๐ฌ
maxSupply๋ ์ ๋ ๋์ ์ ์๋ ์ต๋ ๋ฐํ๋์ด์ผ. ๋นํธ์ฝ์ธ์ 2,100๋ง ๊ฐ ์ ํ๊ณผ ๊ฐ์ ๊ฐ๋ ์ด์ง.
emissionRate๋ ๋ธ๋ก๋น ๋ฐํ๋๋ ํ ํฐ์ ์์ด์ผ. ์ด๊ฑธ ์กฐ์ ํ๋ฉด ์ธํ๋ ์ด์ ์๋๋ฅผ ์ ์ดํ ์ ์์ด.
autoMint() ํจ์๋ ์๋์ผ๋ก ์๊ฐ์ ๋ฐ๋ผ ํ ํฐ์ ๋ฐํํ๋ ๋ฉ์ปค๋์ฆ์ด์ผ. ์ค์ ๋ก๋ ๋ ๋ณต์กํ ๋ก์ง์ด ๋ค์ด๊ฐ์ง๋ง, ๊ธฐ๋ณธ ๊ฐ๋ ์ ์ด๊ฑฐ์ผ! โ๏ธ
maxSupply๋ ์ ๋ ๋์ ์ ์๋ ์ต๋ ๋ฐํ๋์ด์ผ. ๋นํธ์ฝ์ธ์ 2,100๋ง ๊ฐ ์ ํ๊ณผ ๊ฐ์ ๊ฐ๋ ์ด์ง.
emissionRate๋ ๋ธ๋ก๋น ๋ฐํ๋๋ ํ ํฐ์ ์์ด์ผ. ์ด๊ฑธ ์กฐ์ ํ๋ฉด ์ธํ๋ ์ด์ ์๋๋ฅผ ์ ์ดํ ์ ์์ด.
autoMint() ํจ์๋ ์๋์ผ๋ก ์๊ฐ์ ๋ฐ๋ผ ํ ํฐ์ ๋ฐํํ๋ ๋ฉ์ปค๋์ฆ์ด์ผ. ์ค์ ๋ก๋ ๋ ๋ณต์กํ ๋ก์ง์ด ๋ค์ด๊ฐ์ง๋ง, ๊ธฐ๋ณธ ๊ฐ๋ ์ ์ด๊ฑฐ์ผ! โ๏ธ
๐ ํ์ด์ฌ์ผ๋ก ํ ํฐ ๋ฐํ๋ ๋ชจ๋ํฐ๋ง ์คํฌ๋ฆฝํธ ๋ง๋ค๊ธฐ
์ด์ ํ์ด์ฌ์ผ๋ก ์ค์ ํ ํฐ ๋ฐํ๋์ ๋ชจ๋ํฐ๋งํ๊ณ ์ ์ดํ๋ ์คํฌ๋ฆฝํธ๋ฅผ ๋ง๋ค์ด๋ณด์! ์ด๊ฑด ์ค์ ์์ ์ ๋ง ์ ์ฉํด. ๐ฏ
๐ ํ ํฐ ๋ฐํ๋ ๋ชจ๋ํฐ๋ง ์คํฌ๋ฆฝํธ
from web3 import Web3
import json
import time
from datetime import datetime
import os
from dotenv import load_dotenv
load_dotenv()
class TokenSupplyController:
def __init__(self, contract_address, abi_path, rpc_url):
"""
ํ ํฐ ๋ฐํ๋ ์ ์ด ํด๋์ค ์ด๊ธฐํ
"""
self.w3 = Web3(Web3.HTTPProvider(rpc_url))
# ์ฐ๊ฒฐ ํ์ธ
if not self.w3.is_connected():
raise Exception("๋ธ๋ก์ฒด์ธ ์ฐ๊ฒฐ ์คํจ!")
# ์ปจํธ๋ํธ ๋ก๋
with open(abi_path, 'r') as f:
abi = json.load(f)
self.contract = self.w3.eth.contract(
address=Web3.to_checksum_address(contract_address),
abi=abi
)
self.owner_address = os.getenv('OWNER_ADDRESS')
self.private_key = os.getenv('PRIVATE_KEY')
print(f"โ
์ปจํธ๋ํธ ์ฐ๊ฒฐ ์๋ฃ: {contract_address}")
def get_supply_info(self):
"""
ํ์ฌ ํ ํฐ ๋ฐํ๋ ์ ๋ณด ์กฐํ
"""
try:
total_supply = self.contract.functions.totalSupply().call()
max_supply = self.contract.functions.maxSupply().call()
emission_rate = self.contract.functions.emissionRate().call()
# Wei๋ฅผ ํ ํฐ ๋จ์๋ก ๋ณํ
total_supply_tokens = self.w3.from_wei(total_supply, 'ether')
max_supply_tokens = self.w3.from_wei(max_supply, 'ether')
emission_rate_tokens = self.w3.from_wei(emission_rate, 'ether')
supply_percentage = (total_supply / max_supply) * 100
info = {
'total_supply': float(total_supply_tokens),
'max_supply': float(max_supply_tokens),
'emission_rate': float(emission_rate_tokens),
'supply_percentage': supply_percentage,
'remaining': float(max_supply_tokens - total_supply_tokens),
'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
}
return info
except Exception as e:
print(f"โ ์ ๋ณด ์กฐํ ์คํจ: {str(e)}")
return None
def print_supply_dashboard(self):
"""
๋ฐํ๋ ๋์๋ณด๋ ์ถ๋ ฅ
"""
info = self.get_supply_info()
if info:
print("\n" + "="*60)
print("๐ช ํ ํฐ ๋ฐํ๋ ๋์๋ณด๋")
print("="*60)
print(f"๐
์กฐํ ์๊ฐ: {info['timestamp']}")
print(f"๐ฐ ํ์ฌ ๋ฐํ๋: {info['total_supply']:,.2f} ํ ํฐ")
print(f"๐ฏ ์ต๋ ๋ฐํ๋: {info['max_supply']:,.2f} ํ ํฐ")
print(f"๐ ๋ฐํ ๋น์จ: {info['supply_percentage']:.2f}%")
print(f"โฐ ๋ธ๋ก๋น ๋ฐํ: {info['emission_rate']:,.2f} ํ ํฐ")
print(f"๐ ๋จ์ ๋ฐํ๋: {info['remaining']:,.2f} ํ ํฐ")
print("="*60 + "\n")
# ์งํ๋ฅ ๋ฐ ํ์
bar_length = 50
filled = int(bar_length * info['supply_percentage'] / 100)
bar = 'โ' * filled + 'โ' * (bar_length - filled)
print(f"์งํ๋ฅ : [{bar}] {info['supply_percentage']:.1f}%\n")
def calculate_emission_schedule(self, days=365):
"""
ํฅํ ๋ฐํ ์ค์ผ์ค ๊ณ์ฐ
"""
info = self.get_supply_info()
if not info:
return None
# ์ด๋๋ฆฌ์ ๊ธฐ์ค ํ๋ฃจ ์ฝ 6500 ๋ธ๋ก
blocks_per_day = 6500
daily_emission = info['emission_rate'] * blocks_per_day
schedule = []
current_supply = info['total_supply']
for day in range(1, days + 1):
projected_supply = current_supply + (daily_emission * day)
# ์ต๋ ๋ฐํ๋ ์ด๊ณผ ์ฒดํฌ
if projected_supply > info['max_supply']:
projected_supply = info['max_supply']
schedule.append({
'day': day,
'supply': projected_supply,
'note': '์ต๋ ๋ฐํ๋ ๋๋ฌ'
})
break
if day % 30 == 0: # ๋งค์ ๊ธฐ๋ก
schedule.append({
'day': day,
'supply': projected_supply,
'percentage': (projected_supply / info['max_supply']) * 100
})
return schedule
def check_supply_alerts(self):
"""
๋ฐํ๋ ์๋ฆผ ์ฒดํฌ
"""
info = self.get_supply_info()
if not info:
return
alerts = []
# 90% ๋๋ฌ ์๋ฆผ
if info['supply_percentage'] >= 90:
alerts.append("โ ๏ธ ๊ฒฝ๊ณ : ๋ฐํ๋์ด 90%๋ฅผ ์ด๊ณผํ์ต๋๋ค!")
# 95% ๋๋ฌ ์๋ฆผ
if info['supply_percentage'] >= 95:
alerts.append("๐จ ๊ธด๊ธ: ๋ฐํ๋์ด 95%๋ฅผ ์ด๊ณผํ์ต๋๋ค!")
# 99% ๋๋ฌ ์๋ฆผ
if info['supply_percentage'] >= 99:
alerts.append("๐ด ์ต๊ณ ๊ฒฝ๊ณ : ๋ฐํ๋์ด ๊ฑฐ์ ํ๊ณ์ ๋๋ฌํ์ต๋๋ค!")
for alert in alerts:
print(alert)
return alerts
def mint_tokens(self, to_address, amount):
"""
ํ ํฐ ๋ฐํ (owner๋ง ๊ฐ๋ฅ)
"""
try:
# Wei ๋จ์๋ก ๋ณํ
amount_wei = self.w3.to_wei(amount, 'ether')
# ํธ๋์ญ์
์ค๋น
nonce = self.w3.eth.get_transaction_count(self.owner_address)
transaction = self.contract.functions.mint(
Web3.to_checksum_address(to_address),
amount_wei
).build_transaction({
'from': self.owner_address,
'nonce': nonce,
'gas': 200000,
'gasPrice': self.w3.eth.gas_price
})
# ํธ๋์ญ์
์๋ช
signed_txn = self.w3.eth.account.sign_transaction(
transaction,
private_key=self.private_key
)
# ํธ๋์ญ์
์ ์ก
tx_hash = self.w3.eth.send_raw_transaction(signed_txn.rawTransaction)
print(f"โณ ํ ํฐ ๋ฐํ ์ค... TX: {tx_hash.hex()}")
# ํธ๋์ญ์
์๋ฃ ๋๊ธฐ
receipt = self.w3.eth.wait_for_transaction_receipt(tx_hash)
if receipt['status'] == 1:
print(f"โ
{amount} ํ ํฐ ๋ฐํ ์๋ฃ!")
return tx_hash.hex()
else:
print("โ ํธ๋์ญ์
์คํจ")
return None
except Exception as e:
print(f"โ ๋ฐํ ์คํจ: {str(e)}")
return None
def monitor_continuous(self, interval=60):
"""
์ง์์ ์ธ ๋ชจ๋ํฐ๋ง
"""
print("๐ ์ง์ ๋ชจ๋ํฐ๋ง ์์...")
print(f"โฐ ๊ฐฑ์ ์ฃผ๊ธฐ: {interval}์ด\n")
try:
while True:
self.print_supply_dashboard()
self.check_supply_alerts()
time.sleep(interval)
except KeyboardInterrupt:
print("\nโน๏ธ ๋ชจ๋ํฐ๋ง ์ข
๋ฃ")
# ์ฌ์ฉ ์์
if __name__ == "__main__":
# ์ค์
CONTRACT_ADDRESS = "0x..." # ์ค์ ์ปจํธ๋ํธ ์ฃผ์
ABI_PATH = "token_abi.json"
RPC_URL = "https://mainnet.infura.io/v3/YOUR_PROJECT_ID"
# ์ปจํธ๋กค๋ฌ ์ด๊ธฐํ
controller = TokenSupplyController(CONTRACT_ADDRESS, ABI_PATH, RPC_URL)
# ํ์ฌ ์ํ ํ์ธ
controller.print_supply_dashboard()
# ๋ฐํ ์ค์ผ์ค ๊ณ์ฐ
schedule = controller.calculate_emission_schedule(365)
if schedule:
print("\n๐
ํฅํ 12๊ฐ์ ๋ฐํ ์์ธก:")
print("-" * 60)
for item in schedule:
if 'note' in item:
print(f"Day {item['day']}: {item['supply']:,.2f} - {item['note']}")
else:
print(f"Day {item['day']}: {item['supply']:,.2f} ({item['percentage']:.1f}%)")
# ์๋ฆผ ์ฒดํฌ
controller.check_supply_alerts()
# ์ง์ ๋ชจ๋ํฐ๋ง (์ ํ์ฌํญ)
# controller.monitor_continuous(interval=300) # 5๋ถ๋ง๋ค
์! ์ฝ๋๊ฐ ์ข ๊ธธ์ง? ๐
ํ์ง๋ง ํ๋ํ๋ ๋ฏ์ด๋ณด๋ฉด ๋ณ๊ฑฐ ์๋์ผ. ํต์ฌ ๊ธฐ๋ฅ๋ค์ ์ดํด๋ณด์!
get_supply_info()๋ ํ์ฌ ํ ํฐ์ ๋ฐํ ์ํ๋ฅผ ์ค์๊ฐ์ผ๋ก ๊ฐ์ ธ์. ์ด ๋ฐํ๋, ์ต๋ ๋ฐํ๋, ๋ฐํ ์๋ ๋ฑ์ ํ๋์ ๋ณผ ์ ์์ง.
calculate_emission_schedule()์ ๋ฏธ๋์ ๋ฐํ๋์ ์์ธกํด. ์ด๊ฒ ์ง์ง ์ค์ํ๋ฐ, ํ๋ก์ ํธ ์ด๊ธฐ์ ํ ํฐ ๊ฒฝ์ ๋ฅผ ์ค๊ณํ ๋ ์ด๋ฐ ์๋ฎฌ๋ ์ด์ ์ด ํ์์ผ! ๐
check_supply_alerts()๋ ๋ฐํ๋์ด ์ํ ์์ค์ ๋๋ฌํ๋ฉด ์๋ฆผ์ ๋ณด๋ด. ์ค์ ์์๋ ์ด๊ฑธ ํ ๋ ๊ทธ๋จ์ด๋ ์ฌ๋ ๋ด๊ณผ ์ฐ๋ํด์ ์ฌ์ฉํ๋ฉด ์ข์.
mint_tokens()๋ ์ค์ ๋ก ํ ํฐ์ ๋ฐํํ๋ ํจ์์ผ. ๋ฌผ๋ก owner ๊ถํ์ด ์์ด์ผ ํ๊ณ , ๊ฐ์ค๋น๋ ํ์ํด! โฝ
get_supply_info()๋ ํ์ฌ ํ ํฐ์ ๋ฐํ ์ํ๋ฅผ ์ค์๊ฐ์ผ๋ก ๊ฐ์ ธ์. ์ด ๋ฐํ๋, ์ต๋ ๋ฐํ๋, ๋ฐํ ์๋ ๋ฑ์ ํ๋์ ๋ณผ ์ ์์ง.
calculate_emission_schedule()์ ๋ฏธ๋์ ๋ฐํ๋์ ์์ธกํด. ์ด๊ฒ ์ง์ง ์ค์ํ๋ฐ, ํ๋ก์ ํธ ์ด๊ธฐ์ ํ ํฐ ๊ฒฝ์ ๋ฅผ ์ค๊ณํ ๋ ์ด๋ฐ ์๋ฎฌ๋ ์ด์ ์ด ํ์์ผ! ๐
check_supply_alerts()๋ ๋ฐํ๋์ด ์ํ ์์ค์ ๋๋ฌํ๋ฉด ์๋ฆผ์ ๋ณด๋ด. ์ค์ ์์๋ ์ด๊ฑธ ํ ๋ ๊ทธ๋จ์ด๋ ์ฌ๋ ๋ด๊ณผ ์ฐ๋ํด์ ์ฌ์ฉํ๋ฉด ์ข์.
mint_tokens()๋ ์ค์ ๋ก ํ ํฐ์ ๋ฐํํ๋ ํจ์์ผ. ๋ฌผ๋ก owner ๊ถํ์ด ์์ด์ผ ํ๊ณ , ๊ฐ์ค๋น๋ ํ์ํด! โฝ
๐ฎ ๊ณ ๊ธ ๋ฐํ๋ ์ ์ด ์ ๋ต
๊ธฐ๋ณธ์ ์ธ ๋ชจ๋ํฐ๋ง์ ๋์ด์, ์ด์ ์ง์ง ๊ณ ๊ธ ์ ๋ต๋ค์ ๋ฐฐ์๋ณด์! ์ค์ ํ๋ก์ ํธ์์ ์ฌ์ฉ๋๋ ํ
ํฌ๋๋ค์ด์ผ. ๐
โฐ ์๊ฐ ๊ธฐ๋ฐ ๋ฒ ์คํ (Time-based Vesting)
๋ฒ ์คํ
์ ํ ํฐ์ ํ ๋ฒ์ ๋ค ์ฃผ์ง ์๊ณ , ์๊ฐ์ ๋ฐ๋ผ ์กฐ๊ธ์ฉ ํ์ด์ฃผ๋ ๊ฑฐ์ผ. ํ ํ ํฐ์ด๋ ํฌ์์ ํ ํฐ์ ์ฃผ๋ก ์ฌ์ฉ๋ผ. ๊ฐ์๊ธฐ ๋๋ ๋งค๋๋ฅผ ๋ง์ ์ ์๊ฑฐ๋ ! ๐
โณ ๋ฒ ์คํ
์ค์ผ์ค ๊ด๋ฆฌ ์คํฌ๋ฆฝํธ
import time
from datetime import datetime, timedelta
from typing import List, Dict
class VestingScheduler:
def __init__(self):
self.schedules = {}
def create_vesting_schedule(
self,
beneficiary: str,
total_amount: float,
start_date: datetime,
cliff_months: int,
vesting_months: int,
release_frequency: str = 'monthly'
):
"""
๋ฒ ์คํ
์ค์ผ์ค ์์ฑ
Args:
beneficiary: ์ํ์ ์ฃผ์
total_amount: ์ด ํ ํฐ ์
start_date: ์์ ๋ ์ง
cliff_months: ํด๋ฆฌํ ๊ธฐ๊ฐ (์ด ๊ธฐ๊ฐ ๋์์ 0๊ฐ)
vesting_months: ์ด ๋ฒ ์คํ
๊ธฐ๊ฐ
release_frequency: ๋ฆด๋ฆฌ์ฆ ์ฃผ๊ธฐ (monthly, quarterly, etc.)
"""
schedule = {
'beneficiary': beneficiary,
'total_amount': total_amount,
'start_date': start_date,
'cliff_date': start_date + timedelta(days=cliff_months * 30),
'end_date': start_date + timedelta(days=vesting_months * 30),
'cliff_months': cliff_months,
'vesting_months': vesting_months,
'released_amount': 0,
'release_frequency': release_frequency,
'releases': []
}
# ๋ฆด๋ฆฌ์ฆ ์ค์ผ์ค ๊ณ์ฐ
if release_frequency == 'monthly':
periods = vesting_months - cliff_months
amount_per_period = total_amount / vesting_months
for i in range(periods):
release_date = schedule['cliff_date'] + timedelta(days=(i+1) * 30)
schedule['releases'].append({
'date': release_date,
'amount': amount_per_period,
'released': False
})
self.schedules[beneficiary] = schedule
print(f"โ
๋ฒ ์คํ
์ค์ผ์ค ์์ฑ ์๋ฃ")
print(f" ์ํ์: {beneficiary}")
print(f" ์ด์ก: {total_amount:,.2f} ํ ํฐ")
print(f" ํด๋ฆฌํ: {cliff_months}๊ฐ์")
print(f" ๋ฒ ์คํ
: {vesting_months}๊ฐ์")
return schedule
def get_vested_amount(self, beneficiary: str) -> float:
"""
ํ์ฌ๊น์ง ๋ฒ ์คํ
๋ ๊ธ์ก ๊ณ์ฐ
"""
if beneficiary not in self.schedules:
return 0
schedule = self.schedules[beneficiary]
now = datetime.now()
# ํด๋ฆฌํ ๊ธฐ๊ฐ ์ฒดํฌ
if now < schedule['cliff_date']:
return 0
# ๋ฒ ์คํ
์๋ฃ ์ฒดํฌ
if now >= schedule['end_date']:
return schedule['total_amount']
# ์ ํ ๋ฒ ์คํ
๊ณ์ฐ
total_days = (schedule['end_date'] - schedule['cliff_date']).days
elapsed_days = (now - schedule['cliff_date']).days
vested_amount = (schedule['total_amount'] * elapsed_days) / total_days
return vested_amount
def get_releasable_amount(self, beneficiary: str) -> float:
"""
ํ์ฌ ๋ฆด๋ฆฌ์ฆ ๊ฐ๋ฅํ ๊ธ์ก ๊ณ์ฐ
"""
vested = self.get_vested_amount(beneficiary)
schedule = self.schedules.get(beneficiary)
if not schedule:
return 0
releasable = vested - schedule['released_amount']
return max(0, releasable)
def release_tokens(self, beneficiary: str) -> Dict:
"""
ํ ํฐ ๋ฆด๋ฆฌ์ฆ ์คํ
"""
releasable = self.get_releasable_amount(beneficiary)
if releasable <= 0:
return {
'success': False,
'message': '๋ฆด๋ฆฌ์ฆ ๊ฐ๋ฅํ ํ ํฐ์ด ์์ต๋๋ค.'
}
schedule = self.schedules[beneficiary]
schedule['released_amount'] += releasable
return {
'success': True,
'amount': releasable,
'total_released': schedule['released_amount'],
'remaining': schedule['total_amount'] - schedule['released_amount']
}
def print_vesting_status(self, beneficiary: str):
"""
๋ฒ ์คํ
์ํ ์ถ๋ ฅ
"""
if beneficiary not in self.schedules:
print("โ ๋ฒ ์คํ
์ค์ผ์ค์ ์ฐพ์ ์ ์์ต๋๋ค.")
return
schedule = self.schedules[beneficiary]
vested = self.get_vested_amount(beneficiary)
releasable = self.get_releasable_amount(beneficiary)
print("\n" + "="*60)
print(f"๐ ๋ฒ ์คํ
์ํ: {beneficiary[:10]}...")
print("="*60)
print(f"๐ฐ ์ด ํ ๋น๋: {schedule['total_amount']:,.2f} ํ ํฐ")
print(f"โ
๋ฒ ์คํ
์๋ฃ: {vested:,.2f} ํ ํฐ ({vested/schedule['total_amount']*100:.1f}%)")
print(f"๐ ๋ฆด๋ฆฌ์ฆ ์๋ฃ: {schedule['released_amount']:,.2f} ํ ํฐ")
print(f"๐ ๋ฆด๋ฆฌ์ฆ ๊ฐ๋ฅ: {releasable:,.2f} ํ ํฐ")
print(f"๐ ์ ๊ธ ์ํ: {schedule['total_amount'] - vested:,.2f} ํ ํฐ")
print(f"๐
์์์ผ: {schedule['start_date'].strftime('%Y-%m-%d')}")
print(f"โฐ ํด๋ฆฌํ ์ข
๋ฃ: {schedule['cliff_date'].strftime('%Y-%m-%d')}")
print(f"๐ ๋ฒ ์คํ
์ข
๋ฃ: {schedule['end_date'].strftime('%Y-%m-%d')}")
print("="*60 + "\n")
# ์ฌ์ฉ ์์
if __name__ == "__main__":
scheduler = VestingScheduler()
# ํ ํ ํฐ ๋ฒ ์คํ
(12๊ฐ์ ํด๋ฆฌํ, 48๊ฐ์ ๋ฒ ์คํ
)
team_schedule = scheduler.create_vesting_schedule(
beneficiary="0xTeamWallet...",
total_amount=1000000, # 100๋ง ํ ํฐ
start_date=datetime.now(),
cliff_months=12,
vesting_months=48,
release_frequency='monthly'
)
# ํฌ์์ ํ ํฐ ๋ฒ ์คํ
(6๊ฐ์ ํด๋ฆฌํ, 24๊ฐ์ ๋ฒ ์คํ
)
investor_schedule = scheduler.create_vesting_schedule(
beneficiary="0xInvestorWallet...",
total_amount=500000, # 50๋ง ํ ํฐ
start_date=datetime.now(),
cliff_months=6,
vesting_months=24,
release_frequency='monthly'
)
# ์ํ ํ์ธ
scheduler.print_vesting_status("0xTeamWallet...")
# ๋ฆด๋ฆฌ์ฆ ๊ฐ๋ฅ ์ฌ๋ถ ์ฒดํฌ
result = scheduler.release_tokens("0xTeamWallet...")
print(f"๋ฆด๋ฆฌ์ฆ ๊ฒฐ๊ณผ: {result}")
๋ฒ ์คํ
์ ์ ๋ง ์ค์ํด! ๐ฏ ์ค์ ๋ก ๋ง์ ํ๋ก์ ํธ๋ค์ด ํ ํ ํฐ์ ์ ๋๋ก ์ ๊ทธ์ง ์์์ ์ด๊ธฐ์ ๋๋ ๋งค๋๊ฐ ๋ฐ์ํ๊ณ ๊ฐ๊ฒฉ์ด ํญ๋ฝํ๊ฑฐ๋ .
์ผ๋ฐ์ ์ธ ๋ฒ ์คํ ๊ตฌ์กฐ๋ ์ด๋:
โข ํ ํ ํฐ: 12๊ฐ์ ํด๋ฆฌํ + 36~48๊ฐ์ ๋ฒ ์คํ
โข ์ด๋๋ฐ์ด์ : 6๊ฐ์ ํด๋ฆฌํ + 18~24๊ฐ์ ๋ฒ ์คํ
โข ์ด๊ธฐ ํฌ์์: 6~12๊ฐ์ ํด๋ฆฌํ + 18~36๊ฐ์ ๋ฒ ์คํ
โข ์ปค๋ฎค๋ํฐ ๋ณด์: ํด๋ฆฌํ ์์, ์ฆ์ ๋ฆด๋ฆฌ์ฆ ๊ฐ๋ฅ ๐
์ผ๋ฐ์ ์ธ ๋ฒ ์คํ ๊ตฌ์กฐ๋ ์ด๋:
โข ํ ํ ํฐ: 12๊ฐ์ ํด๋ฆฌํ + 36~48๊ฐ์ ๋ฒ ์คํ
โข ์ด๋๋ฐ์ด์ : 6๊ฐ์ ํด๋ฆฌํ + 18~24๊ฐ์ ๋ฒ ์คํ
โข ์ด๊ธฐ ํฌ์์: 6~12๊ฐ์ ํด๋ฆฌํ + 18~36๊ฐ์ ๋ฒ ์คํ
โข ์ปค๋ฎค๋ํฐ ๋ณด์: ํด๋ฆฌํ ์์, ์ฆ์ ๋ฆด๋ฆฌ์ฆ ๊ฐ๋ฅ ๐
๐ฅ ๋์ ์๊ฐ ๋ฉ์ปค๋์ฆ (Dynamic Burn Mechanism)
์๊ฐ์ ํ ํฐ์ ์๊ตฌ์ ์ผ๋ก ์ ๊ฑฐํด์ ํฌ์์ฑ์ ๋์ด๋ ๊ฑฐ์ผ. ์ด๋๋ฆฌ์์ EIP-1559๊ฐ ๋ํ์ ์ธ ์์ง! ๐ฅ
๐ฅ ์ค๋งํธ ์๊ฐ ์์คํ
class DynamicBurnController:
def __init__(self, token_controller):
self.controller = token_controller
self.burn_history = []
self.burn_strategies = {
'fixed': self.fixed_burn,
'percentage': self.percentage_burn,
'dynamic': self.dynamic_burn
}
def fixed_burn(self, amount: float) -> Dict:
"""
๊ณ ์ ๊ธ์ก ์๊ฐ
"""
info = self.controller.get_supply_info()
if amount > info['total_supply']:
return {
'success': False,
'message': '์๊ฐ ๊ธ์ก์ด ์ด ๋ฐํ๋์ ์ด๊ณผํฉ๋๋ค.'
}
# ์ค์ ์๊ฐ ๋ก์ง (์ฌ๊ธฐ์๋ ์๋ฎฌ๋ ์ด์
)
new_supply = info['total_supply'] - amount
burn_record = {
'timestamp': datetime.now(),
'strategy': 'fixed',
'amount': amount,
'supply_before': info['total_supply'],
'supply_after': new_supply,
'burn_percentage': (amount / info['total_supply']) * 100
}
self.burn_history.append(burn_record)
return {
'success': True,
'burned': amount,
'new_supply': new_supply,
'deflation_rate': burn_record['burn_percentage']
}
def percentage_burn(self, percentage: float) -> Dict:
"""
๋น์จ ๊ธฐ๋ฐ ์๊ฐ
"""
info = self.controller.get_supply_info()
burn_amount = info['total_supply'] * (percentage / 100)
return self.fixed_burn(burn_amount)
def dynamic_burn(self, transaction_volume: float, burn_rate: float = 0.1) -> Dict:
"""
๊ฑฐ๋๋ ๊ธฐ๋ฐ ๋์ ์๊ฐ (EIP-1559 ์คํ์ผ)
Args:
transaction_volume: ๊ฑฐ๋๋
burn_rate: ์๊ฐ ๋น์จ (๊ธฐ๋ณธ 10%)
"""
burn_amount = transaction_volume * burn_rate
result = self.fixed_burn(burn_amount)
result['transaction_volume'] = transaction_volume
result['burn_rate'] = burn_rate
return result
def calculate_deflation_impact(self, burn_amount: float) -> Dict:
"""
์๊ฐ์ด ํ ํฐ ๊ฒฝ์ ์ ๋ฏธ์น๋ ์ํฅ ๊ณ์ฐ
"""
info = self.controller.get_supply_info()
# ํ์ฌ ๊ฐ๊ฒฉ ๊ฐ์ (์ค์ ๋ก๋ ์ค๋ผํด์ด๋ DEX์์ ๊ฐ์ ธ์์ผ ํจ)
assumed_price = 1.0 # $1
# ์๊ฐ ํ ๊ณต๊ธ๋
new_supply = info['total_supply'] - burn_amount
# ๋จ์ ๊ณต๊ธ-์์ ๋ชจ๋ธ (์ค์ ๋ก๋ ํจ์ฌ ๋ณต์กํจ)
supply_reduction = (burn_amount / info['total_supply']) * 100
# ๊ฐ๊ฒฉ ์์น ์์ธก (๋งค์ฐ ๋จ์ํ๋ ๋ชจ๋ธ)
# ์ค์ ๋ก๋ ์ ๋์ฑ, ๊ฑฐ๋๋, ์์ฅ ์ฌ๋ฆฌ ๋ฑ ๊ณ ๋ คํด์ผ ํจ
estimated_price_impact = supply_reduction * 0.5 # 50% ํจ๊ณผ ๊ฐ์
return {
'burn_amount': burn_amount,
'supply_reduction_pct': supply_reduction,
'new_supply': new_supply,
'estimated_price_impact_pct': estimated_price_impact,
'estimated_new_price': assumed_price * (1 + estimated_price_impact / 100)
}
def get_optimal_burn_rate(self, target_deflation: float, time_period_days: int) -> float:
"""
๋ชฉํ ๋ํ๋ ์ด์
์จ์ ๋ฌ์ฑํ๊ธฐ ์ํ ์ต์ ์๊ฐ๋ฅ ๊ณ์ฐ
Args:
target_deflation: ๋ชฉํ ๋ํ๋ ์ด์
์จ (%)
time_period_days: ๊ธฐ๊ฐ (์ผ)
"""
info = self.controller.get_supply_info()
# ์ผ์ผ ์๊ฐ๋ ๊ณ์ฐ
total_burn_needed = info['total_supply'] * (target_deflation / 100)
daily_burn = total_burn_needed / time_period_days
# ์ผ์ผ ์๊ฐ๋ฅ
daily_burn_rate = (daily_burn / info['total_supply']) * 100
return {
'target_deflation': target_deflation,
'time_period_days': time_period_days,
'total_burn_needed': total_burn_needed,
'daily_burn_amount': daily_burn,
'daily_burn_rate': daily_burn_rate
}
def print_burn_analytics(self):
"""
์๊ฐ ๋ถ์ ๋ฆฌํฌํธ ์ถ๋ ฅ
"""
if not self.burn_history:
print("๐ ์๊ฐ ๊ธฐ๋ก์ด ์์ต๋๋ค.")
return
total_burned = sum(record['amount'] for record in self.burn_history)
print("\n" + "="*60)
print("๐ฅ ์๊ฐ ๋ถ์ ๋ฆฌํฌํธ")
print("="*60)
print(f"๐
์ด ์๊ฐ ํ์: {len(self.burn_history)}ํ")
print(f"๐ฐ ์ด ์๊ฐ๋: {total_burned:,.2f} ํ ํฐ")
print(f"๐ ํ๊ท ์๊ฐ๋: {total_burned/len(self.burn_history):,.2f} ํ ํฐ")
print("\n์ต๊ทผ ์๊ฐ ๊ธฐ๋ก:")
print("-"*60)
for record in self.burn_history[-5:]: # ์ต๊ทผ 5๊ฐ
print(f"โฐ {record['timestamp'].strftime('%Y-%m-%d %H:%M:%S')}")
print(f" ์ ๋ต: {record['strategy']}")
print(f" ์๊ฐ๋: {record['amount']:,.2f} ({record['burn_percentage']:.2f}%)")
print(f" ๊ณต๊ธ๋: {record['supply_before']:,.2f} โ {record['supply_after']:,.2f}")
print()
print("="*60 + "\n")
# ์ฌ์ฉ ์์
if __name__ == "__main__":
# ๊ธฐ์กด ์ปจํธ๋กค๋ฌ ์ฌ์ฉ
burn_controller = DynamicBurnController(controller)
# ๊ณ ์ ๊ธ์ก ์๊ฐ
result = burn_controller.fixed_burn(1000)
print(f"์๊ฐ ๊ฒฐ๊ณผ: {result}")
# ๊ฑฐ๋๋ ๊ธฐ๋ฐ ๋์ ์๊ฐ
result = burn_controller.dynamic_burn(
transaction_volume=10000, # $10,000 ๊ฑฐ๋๋
burn_rate=0.1 # 10% ์๊ฐ
)
print(f"๋์ ์๊ฐ ๊ฒฐ๊ณผ: {result}")
# ์๊ฐ ์ํฅ ๋ถ์
impact = burn_controller.calculate_deflation_impact(5000)
print(f"\n์๊ฐ ์ํฅ ๋ถ์:")
print(f" ๊ณต๊ธ ๊ฐ์: {impact['supply_reduction_pct']:.2f}%")
print(f" ์์ ๊ฐ๊ฒฉ ์ํฅ: +{impact['estimated_price_impact_pct']:.2f}%")
# ์ต์ ์๊ฐ๋ฅ ๊ณ์ฐ
optimal = burn_controller.get_optimal_burn_rate(
target_deflation=5.0, # 5% ๋ํ๋ ์ด์
๋ชฉํ
time_period_days=365 # 1๋
)
print(f"\n์ต์ ์๊ฐ ์ ๋ต:")
print(f" ์ผ์ผ ์๊ฐ๋: {optimal['daily_burn_amount']:,.2f} ํ ํฐ")
print(f" ์ผ์ผ ์๊ฐ๋ฅ : {optimal['daily_burn_rate']:.4f}%")
# ๋ถ์ ๋ฆฌํฌํธ
burn_controller.print_burn_analytics()
์๊ฐ ๋ฉ์ปค๋์ฆ์ ์ ๋ง ๊ฐ๋ ฅํ ๋๊ตฌ์ผ! ๐ช ํ์ง๋ง ์กฐ์ฌํด์ผ ํ ์ ๋ค์ด ์์ด:
1. ๊ณผ๋ํ ์๊ฐ์ ๋ ์ด ๋ ์ ์์ด
๋๋ฌด ๋ง์ด ์๊ฐํ๋ฉด ์ ๋์ฑ์ด ๋ถ์กฑํด์ ธ์ ๊ฑฐ๋๊ฐ ์ด๋ ค์์ง ์ ์์ด. ์ ์ ํ ๊ท ํ์ด ์ค์ํด! โ๏ธ
2. ์๊ฐ์ ๋๋๋ฆด ์ ์์ด
ํ ๋ฒ ์๊ฐ๋ ํ ํฐ์ ์์ํ ์ฌ๋ผ์ ธ. ๊ทธ๋์ ์ ์คํ๊ฒ ๊ฒฐ์ ํด์ผ ํด. ๐ซ
3. ์์ฅ ๋ฐ์์ ๊ณ ๋ คํด์ผ ํด
์๊ฐ ๋ฐํ๋ง์ผ๋ก๋ ๊ฐ๊ฒฉ์ด ์์ง์ผ ์ ์์ด. ํ์ด๋ฐ๊ณผ ์ปค๋ฎค๋์ผ์ด์ ์ด ์ค์ํ์ง! ๐ข
1. ๊ณผ๋ํ ์๊ฐ์ ๋ ์ด ๋ ์ ์์ด
๋๋ฌด ๋ง์ด ์๊ฐํ๋ฉด ์ ๋์ฑ์ด ๋ถ์กฑํด์ ธ์ ๊ฑฐ๋๊ฐ ์ด๋ ค์์ง ์ ์์ด. ์ ์ ํ ๊ท ํ์ด ์ค์ํด! โ๏ธ
2. ์๊ฐ์ ๋๋๋ฆด ์ ์์ด
ํ ๋ฒ ์๊ฐ๋ ํ ํฐ์ ์์ํ ์ฌ๋ผ์ ธ. ๊ทธ๋์ ์ ์คํ๊ฒ ๊ฒฐ์ ํด์ผ ํด. ๐ซ
3. ์์ฅ ๋ฐ์์ ๊ณ ๋ คํด์ผ ํด
์๊ฐ ๋ฐํ๋ง์ผ๋ก๋ ๊ฐ๊ฒฉ์ด ์์ง์ผ ์ ์์ด. ํ์ด๋ฐ๊ณผ ์ปค๋ฎค๋์ผ์ด์ ์ด ์ค์ํ์ง! ๐ข
๐ ์ค์๊ฐ ๋์๋ณด๋ ๊ตฌ์ถํ๊ธฐ
์ด์ ๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ ์๊ฐํํด์ ๋ณด์ฌ์ฃผ๋ ๋์๋ณด๋๋ฅผ ๋ง๋ค์ด๋ณด์! ์ค์ ์์๋ ์ด๋ฐ ๊ฒ ์ ๋ง ์ค์ํด. ๐
๐ ์น ๊ธฐ๋ฐ ๋ชจ๋ํฐ๋ง ๋์๋ณด๋
from flask import Flask, render_template, jsonify
import plotly.graph_objs as go
import plotly.express as px
from datetime import datetime, timedelta
import json
app = Flask(__name__)
class TokenDashboard:
def __init__(self, controller, burn_controller, vesting_scheduler):
self.controller = controller
self.burn_controller = burn_controller
self.vesting_scheduler = vesting_scheduler
def get_supply_chart_data(self):
"""
๋ฐํ๋ ์ฐจํธ ๋ฐ์ดํฐ ์์ฑ
"""
info = self.controller.get_supply_info()
labels = ['๋ฐํ๋จ', '๋จ์ ๋ฐํ๋']
values = [info['total_supply'], info['remaining']]
colors = ['#66bb6a', '#e0e0e0']
fig = go.Figure(data=[go.Pie(
labels=labels,
values=values,
hole=0.4,
marker=dict(colors=colors),
textinfo='label+percent',
textfont=dict(size=16)
)])
fig.update_layout(
title='ํ ํฐ ๋ฐํ ํํฉ',
showlegend=True,
height=400
)
return fig.to_json()
def get_emission_projection_data(self, days=365):
"""
๋ฐํ ์์ธก ์ฐจํธ ๋ฐ์ดํฐ
"""
schedule = self.controller.calculate_emission_schedule(days)
if not schedule:
return None
dates = [datetime.now() + timedelta(days=item['day']) for item in schedule]
supplies = [item['supply'] for item in schedule]
fig = go.Figure()
fig.add_trace(go.Scatter(
x=dates,
y=supplies,
mode='lines+markers',
name='์์ ๋ฐํ๋',
line=dict(color='#5e35b1', width=3),
marker=dict(size=6)
))
# ์ต๋ ๋ฐํ๋ ๋ผ์ธ
info = self.controller.get_supply_info()
fig.add_hline(
y=info['max_supply'],
line_dash="dash",
line_color="red",
annotation_text="์ต๋ ๋ฐํ๋"
)
fig.update_layout(
title='ํฅํ ๋ฐํ๋ ์์ธก',
xaxis_title='๋ ์ง',
yaxis_title='ํ ํฐ ์๋',
hovermode='x unified',
height=400
)
return fig.to_json()
def get_burn_history_data(self):
"""
์๊ฐ ํ์คํ ๋ฆฌ ์ฐจํธ
"""
if not self.burn_controller.burn_history:
return None
dates = [record['timestamp'] for record in self.burn_controller.burn_history]
amounts = [record['amount'] for record in self.burn_controller.burn_history]
fig = go.Figure()
fig.add_trace(go.Bar(
x=dates,
y=amounts,
name='์๊ฐ๋',
marker=dict(color='#ff6b6b')
))
fig.update_layout(
title='์๊ฐ ํ์คํ ๋ฆฌ',
xaxis_title='๋ ์ง',
yaxis_title='์๊ฐ๋',
height=400
)
return fig.to_json()
def get_metrics_summary(self):
"""
์ฃผ์ ์งํ ์์ฝ
"""
info = self.controller.get_supply_info()
# ์๊ฐ ํต๊ณ
total_burned = sum(
record['amount']
for record in self.burn_controller.burn_history
) if self.burn_controller.burn_history else 0
# ๋ฒ ์คํ
ํต๊ณ
total_vested = 0
total_locked = 0
for beneficiary, schedule in self.vesting_scheduler.schedules.items():
vested = self.vesting_scheduler.get_vested_amount(beneficiary)
total_vested += vested
total_locked += schedule['total_amount'] - vested
return {
'current_supply': info['total_supply'],
'max_supply': info['max_supply'],
'supply_percentage': info['supply_percentage'],
'total_burned': total_burned,
'total_vested': total_vested,
'total_locked': total_locked,
'circulating_supply': info['total_supply'] - total_locked
}
# Flask ๋ผ์ฐํธ
@app.route('/')
def index():
return '''
<!DOCTYPE html>
<html>
<head>
<title>ํ ํฐ ๋ฐํ๋ ๋์๋ณด๋</title>
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
margin: 0;
padding: 20px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.container {
max-width: 1400px;
margin: 0 auto;
background: white;
border-radius: 20px;
padding: 30px;
box-shadow: 0 10px 40px rgba(0,0,0,0.2);
}
h1 {
color: #5e35b1;
text-align: center;
margin-bottom: 40px;
}
.metrics {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
margin-bottom: 40px;
}
.metric-card {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 25px;
border-radius: 15px;
box-shadow: 0 5px 15px rgba(0,0,0,0.1);
}
.metric-value {
font-size: 2em;
font-weight: bold;
margin: 10px 0;
}
.metric-label {
font-size: 0.9em;
opacity: 0.9;
}
.charts {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(500px, 1fr));
gap: 30px;
}
.chart-container {
background: #f8f9fa;
padding: 20px;
border-radius: 15px;
}
</style>
</head>
<body>
<div class="container">
<h1>๐ช ํ ํฐ ๋ฐํ๋ ์ ์ด ๋์๋ณด๋</h1>
<div class="metrics" id="metrics"></div>
<div class="charts">
<div class="chart-container">
<div id="supply-chart"></div>
</div>
<div class="chart-container">
<div id="emission-chart"></div>
</div>
<div class="chart-container">
<div id="burn-chart"></div>
</div>
</div>
</div>
<script>
// ๋ฐ์ดํฐ ๋ก๋ ๋ฐ ์ฐจํธ ๋ ๋๋ง
async function loadDashboard() {
// ๋ฉํธ๋ฆญ ๋ก๋
const metrics = await fetch('/api/metrics').then(r => r.json());
renderMetrics(metrics);
// ์ฐจํธ ๋ก๋
const supplyChart = await fetch('/api/supply-chart').then(r => r.json());
Plotly.newPlot('supply-chart', JSON.parse(supplyChart).data, JSON.parse(supplyChart).layout);
const emissionChart = await fetch('/api/emission-chart').then(r => r.json());
Plotly.newPlot('emission-chart', JSON.parse(emissionChart).data, JSON.parse(emissionChart).layout);
const burnChart = await fetch('/api/burn-chart').then(r => r.json());
if (burnChart) {
Plotly.newPlot('burn-chart', JSON.parse(burnChart).data, JSON.parse(burnChart).layout);
}
}
function renderMetrics(metrics) {
const container = document.getElementById('metrics');
container.innerHTML = `
<div class="metric-card">
<div class="metric-label">ํ์ฌ ๋ฐํ๋</div>
<div class="metric-value">${metrics.current_supply.toLocaleString()}</div>
</div>
<div class="metric-card">
<div class="metric-label">๋ฐํ๋ฅ </div>
<div class="metric-value">${metrics.supply_percentage.toFixed(1)}%</div>
</div>
<div class="metric-card">
<div class="metric-label">์ด ์๊ฐ๋</div>
<div class="metric-value">${metrics.total_burned.toLocaleString()}</div>
</div>
<div class="metric-card">
<div class="metric-label">์ ํต๋</div>
<div class="metric-value">${metrics.circulating_supply.toLocaleString()}</div>
</div>
`;
}
// 5์ด๋ง๋ค ์๋ ๊ฐฑ์
loadDashboard();
setInterval(loadDashboard, 5000);
</script>
</body>
</html>
'''
@app.route('/api/metrics')
def api_metrics():
dashboard = TokenDashboard(controller, burn_controller, vesting_scheduler)
return jsonify(dashboard.get_metrics_summary())
@app.route('/api/supply-chart')
def api_supply_chart():
dashboard = TokenDashboard(controller, burn_controller, vesting_scheduler)
return dashboard.get_supply_chart_data()
@app.route('/api/emission-chart')
def api_emission_chart():
dashboard = TokenDashboard(controller, burn_controller, vesting_scheduler)
return dashboard.get_emission_projection_data()
@app.route('/api/burn-chart')
def api_burn_chart():
dashboard = TokenDashboard(controller, burn_controller, vesting_scheduler)
return dashboard.get_burn_history_data()
if __name__ == '__main__':
app.run(debug=True, port=5000)
์! ์ด์ ์ง์ง ํ๋กํ์
๋ํ ๋์๋ณด๋๊ฐ ์์ฑ๋์ด! ๐
์ด ๋์๋ณด๋๋ ์ค์๊ฐ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๊ฐฑ์ ํ๊ณ , ์ธํฐ๋ํฐ๋ธํ ์ฐจํธ๋ก ์๊ฐํํด์ค. ์ค์ ํ๋ก์ ํธ์์ ์ด๋ฐ ๋์๋ณด๋๊ฐ ์์ผ๋ฉด ํ์๋ค์ด๋ ํฌ์์๋ค์๊ฒ ๋ณด์ฌ์ฃผ๊ธฐ ์ ๋ง ์ข์! ๐
Flask๋ฅผ ์ฌ์ฉํ์ง๋ง, ์ํ๋ค๋ฉด FastAPI๋ Django๋ก๋ ๋ง๋ค ์ ์์ด. ์ค์ํ ๊ฑด ๋ฐ์ดํฐ๋ฅผ ๋ช ํํ๊ฒ ์๊ฐํํ๋ ๊ฑฐ์ผ! ๐
์ด ๋์๋ณด๋๋ ์ค์๊ฐ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๊ฐฑ์ ํ๊ณ , ์ธํฐ๋ํฐ๋ธํ ์ฐจํธ๋ก ์๊ฐํํด์ค. ์ค์ ํ๋ก์ ํธ์์ ์ด๋ฐ ๋์๋ณด๋๊ฐ ์์ผ๋ฉด ํ์๋ค์ด๋ ํฌ์์๋ค์๊ฒ ๋ณด์ฌ์ฃผ๊ธฐ ์ ๋ง ์ข์! ๐
Flask๋ฅผ ์ฌ์ฉํ์ง๋ง, ์ํ๋ค๋ฉด FastAPI๋ Django๋ก๋ ๋ง๋ค ์ ์์ด. ์ค์ํ ๊ฑด ๋ฐ์ดํฐ๋ฅผ ๋ช ํํ๊ฒ ์๊ฐํํ๋ ๊ฑฐ์ผ! ๐
๐ ๋ณด์ ๊ณ ๋ ค์ฌํญ
ํ ํฐ ๋ฐํ๋ ์ ์ด๋ ์์ฒญ๋ ๊ถํ์ด์ผ. ๊ทธ๋งํผ ๋ณด์์ด ์ ๋ง ์ค์ํด! ๐ก๏ธ
โ ๏ธ ์ ๋ ํ์ง ๋ง์์ผ ํ ๊ฒ๋ค
1. ๊ฐ์ธํค๋ฅผ ์ฝ๋์ ํ๋์ฝ๋ฉ
์ ๋๋ก, ์ ๋๋ก ํ์ง ๋ง! ํ๊ฒฝ ๋ณ์๋ ํ๋์จ์ด ์๋ ์ ์ฌ์ฉํด์ผ ํด.
2. ๋จ์ผ ๊ด๋ฆฌ์ ๊ณ์
๋ฉํฐ์๊ทธ(Multi-signature) ์ง๊ฐ์ ์ฌ์ฉํด์ ์ฌ๋ฌ ๋ช ์ ์น์ธ์ด ํ์ํ๋๋ก ํด์ผ ํด.
3. ๋ฌด์ ํ ๋ฐํ ๊ถํ
์ค๋งํธ ์ปจํธ๋ํธ ๋ ๋ฒจ์์ ์ต๋ ๋ฐํ๋์ ๊ฐ์ ํด์ผ ํด.
4. ๊ฐ์ฌ ๋ก๊ทธ ์์
๋ชจ๋ ๋ฐํ/์๊ฐ ํ๋์ ๊ธฐ๋กํ๊ณ ์ถ์ ํ ์ ์์ด์ผ ํด.
1. ๊ฐ์ธํค๋ฅผ ์ฝ๋์ ํ๋์ฝ๋ฉ
์ ๋๋ก, ์ ๋๋ก ํ์ง ๋ง! ํ๊ฒฝ ๋ณ์๋ ํ๋์จ์ด ์๋ ์ ์ฌ์ฉํด์ผ ํด.
2. ๋จ์ผ ๊ด๋ฆฌ์ ๊ณ์
๋ฉํฐ์๊ทธ(Multi-signature) ์ง๊ฐ์ ์ฌ์ฉํด์ ์ฌ๋ฌ ๋ช ์ ์น์ธ์ด ํ์ํ๋๋ก ํด์ผ ํด.
3. ๋ฌด์ ํ ๋ฐํ ๊ถํ
์ค๋งํธ ์ปจํธ๋ํธ ๋ ๋ฒจ์์ ์ต๋ ๋ฐํ๋์ ๊ฐ์ ํด์ผ ํด.
4. ๊ฐ์ฌ ๋ก๊ทธ ์์
๋ชจ๋ ๋ฐํ/์๊ฐ ํ๋์ ๊ธฐ๋กํ๊ณ ์ถ์ ํ ์ ์์ด์ผ ํด.
๐ ๋ณด์ ๊ฐํ ์ฝ๋
import hashlib
import hmac
from cryptography.fernet import Fernet
import logging
from datetime import datetime
class SecureTokenController:
def __init__(self, controller):
self.controller = controller
self.setup_logging()
self.setup_encryption()
self.action_history = []
def setup_logging(self):
"""
๊ฐ์ฌ ๋ก๊ทธ ์ค์
"""
logging.basicConfig(
filename='token_operations.log',
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
self.logger = logging.getLogger(__name__)
def setup_encryption(self):
"""
์ํธํ ์ค์
"""
# ์ค์ ๋ก๋ ์์ ํ ๊ณณ์์ ํค๋ฅผ ๊ฐ์ ธ์์ผ ํจ
self.encryption_key = Fernet.generate_key()
self.cipher = Fernet(self.encryption_key)
def verify_signature(self, message: str, signature: str, secret: str) -> bool:
"""
HMAC ์๋ช
๊ฒ์ฆ
"""
expected_signature = hmac.new(
secret.encode(),
message.encode(),
hashlib.sha256
).hexdigest()
return hmac.compare_digest(signature, expected_signature)
def log_action(self, action: str, details: dict, user: str):
"""
๋ชจ๋ ์ก์
๋ก๊น
"""
log_entry = {
'timestamp': datetime.now().isoformat(),
'action': action,
'user': user,
'details': details
}
self.action_history.append(log_entry)
self.logger.info(f"Action: {action} | User: {user} | Details: {details}")
def require_multisig(self, action: str, approvers: list, required_approvals: int = 2):
"""
๋ฉํฐ์๊ทธ ์น์ธ ์๋ฎฌ๋ ์ด์
"""
print(f"\n๐ ๋ฉํฐ์๊ทธ ์น์ธ ํ์: {action}")
print(f" ํ์ํ ์น์ธ ์: {required_approvals}/{len(approvers)}")
approvals = []
for approver in approvers:
# ์ค์ ๋ก๋ ๊ฐ ์น์ธ์์ ์๋ช
์ ๋ฐ์์ผ ํจ
approval = input(f" {approver}์ ์น์ธ์ ๋ฐ์์ต๋๊น? (y/n): ")
if approval.lower() == 'y':
approvals.append(approver)
if len(approvals) >= required_approvals:
print(f"โ
์ถฉ๋ถํ ์น์ธ์ ๋ฐ์์ต๋๋ค! ({len(approvals)}/{required_approvals})")
return True
print(f"โ ์น์ธ์ด ๋ถ์กฑํฉ๋๋ค. ({len(approvals)}/{required_approvals})")
return False
def secure_mint(self, to_address: str, amount: float, user: str, approvers: list):
"""
๋ณด์ ๊ฐํ๋ ํ ํฐ ๋ฐํ
"""
# 1. ๋ฉํฐ์๊ทธ ์น์ธ
if not self.require_multisig(f"Mint {amount} tokens", approvers):
self.log_action('mint_rejected', {
'to': to_address,
'amount': amount,
'reason': 'insufficient_approvals'
}, user)
return False
# 2. ๋ฐํ๋ ์ ํ ์ฒดํฌ
info = self.controller.get_supply_info()
if info['total_supply'] + amount > info['max_supply']:
self.log_action('mint_rejected', {
'to': to_address,
'amount': amount,
'reason': 'exceeds_max_supply'
}, user)
return False
# 3. ์ค์ ๋ฐํ
try:
result = self.controller.mint_tokens(to_address, amount)
self.log_action('mint_success', {
'to': to_address,
'amount': amount,
'tx_hash': result
}, user)
return True
except Exception as e:
self.log_action('mint_error', {
'to': to_address,
'amount': amount,
'error': str(e)
}, user)
return False
def get_audit_report(self, days: int = 30):
"""
๊ฐ์ฌ ๋ฆฌํฌํธ ์์ฑ
"""
cutoff_date = datetime.now() - timedelta(days=days)
recent_actions = [
action for action in self.action_history
if datetime.fromisoformat(action['timestamp']) > cutoff_date
]
print(f"\n๐ ์ต๊ทผ {days}์ผ ๊ฐ์ฌ ๋ฆฌํฌํธ")
print("="*60)
print(f"์ด ์ก์
์: {len(recent_actions)}")
# ์ก์
ํ์
๋ณ ์ง๊ณ
action_types = {}
for action in recent_actions:
action_type = action['action']
action_types[action_type] = action_types.get(action_type, 0) + 1
print("\n์ก์
ํ์
๋ณ ํต๊ณ:")
for action_type, count in action_types.items():
print(f" {action_type}: {count}ํ")
print("\n์ต๊ทผ ์ก์
:")
for action in recent_actions[-10:]:
print(f" [{action['timestamp']}] {action['action']} by {action['user']}")
print("="*60 + "\n")
# ์ฌ์ฉ ์์
if __name__ == "__main__":
secure_controller = SecureTokenController(controller)
# ๋ณด์ ๊ฐํ๋ ๋ฐํ
approvers = ['Admin1', 'Admin2', 'Admin3']
secure_controller.secure_mint(
to_address="0x...",
amount=10000,
user="Admin1",
approvers=approvers
)
# ๊ฐ์ฌ ๋ฆฌํฌํธ
secure_controller.get_audit_report(days=30)
๋ณด์์ ์๋ฌด๋ฆฌ ๊ฐ์กฐํด๋ ์ง๋์น์ง ์์! ๐
์ค์ ๋ก ๋ง์ ํ๋ก์ ํธ๋ค์ด ๋ณด์ ์ทจ์ฝ์ ๋๋ฌธ์ ํดํน๋นํ์ด. 2021๋ Poly Network ํดํน์์๋ 6์ต ๋ฌ๋ฌ๊ฐ ๋๋ ์ํธํํ๊ฐ ๋๋๋นํ๊ณ , 2022๋ Ronin Bridge ํดํน์์๋ 6์ต 2์ฒ๋ง ๋ฌ๋ฌ๊ฐ ์ฌ๋ผ์ก์ด. ๐ฑ
๊ทธ๋์ ์ฐ๋ฆฌ๊ฐ ๋ง๋ ์์คํ ์๋:
โข ๋ฉํฐ์๊ทธ ์น์ธ - ์ฌ๋ฌ ๋ช ์ ๋์๊ฐ ํ์
โข ๊ฐ์ฌ ๋ก๊ทธ - ๋ชจ๋ ํ๋ ๊ธฐ๋ก
โข ์ํธํ - ๋ฏผ๊ฐํ ๋ฐ์ดํฐ ๋ณดํธ
โข ์ ํ ๊ฒ์ฆ - ์ต๋ ๋ฐํ๋ ๊ฐ์
์ด๋ฐ ๋ณด์ ์ฅ์น๋ค์ด ํ์์ผ! ๐ช
์ค์ ๋ก ๋ง์ ํ๋ก์ ํธ๋ค์ด ๋ณด์ ์ทจ์ฝ์ ๋๋ฌธ์ ํดํน๋นํ์ด. 2021๋ Poly Network ํดํน์์๋ 6์ต ๋ฌ๋ฌ๊ฐ ๋๋ ์ํธํํ๊ฐ ๋๋๋นํ๊ณ , 2022๋ Ronin Bridge ํดํน์์๋ 6์ต 2์ฒ๋ง ๋ฌ๋ฌ๊ฐ ์ฌ๋ผ์ก์ด. ๐ฑ
๊ทธ๋์ ์ฐ๋ฆฌ๊ฐ ๋ง๋ ์์คํ ์๋:
โข ๋ฉํฐ์๊ทธ ์น์ธ - ์ฌ๋ฌ ๋ช ์ ๋์๊ฐ ํ์
โข ๊ฐ์ฌ ๋ก๊ทธ - ๋ชจ๋ ํ๋ ๊ธฐ๋ก
โข ์ํธํ - ๋ฏผ๊ฐํ ๋ฐ์ดํฐ ๋ณดํธ
โข ์ ํ ๊ฒ์ฆ - ์ต๋ ๋ฐํ๋ ๊ฐ์
์ด๋ฐ ๋ณด์ ์ฅ์น๋ค์ด ํ์์ผ! ๐ช
๐ ์ค์ ํ๋ก์ ํธ ์ ์ฉ ์ฌ๋ก
์ด๋ก ๊ณผ ์ฝ๋๋ฅผ ๋ฐฐ์ ์ผ๋, ์ด์ ์ค์ ๋ก ์ด๋ป๊ฒ ์ ์ฉํ๋์ง ์ดํด๋ณด์! ๐
๐ก ์ฌ๋ก 1: DeFi ํ๋กํ ์ฝ์ ๊ฑฐ๋ฒ๋์ค ํ ํฐ
ํ๋ก์ ํธ ๊ฐ์
ํ์ค์ํ ๊ฑฐ๋์(DEX)์ ๊ฑฐ๋ฒ๋์ค ํ ํฐ ๋ฐํ๋ ๊ด๋ฆฌ
ํ ํฐ ๊ฒฝ์ ์ค๊ณ
โข ์ด ๋ฐํ๋: 1์ต ๊ฐ
โข ์ด๊ธฐ ์ ํต๋: 1,000๋ง ๊ฐ (10%)
โข ์ ๋์ฑ ์ฑ๊ตด ๋ณด์: 5,000๋ง ๊ฐ (50%, 4๋ ๊ฐ ๋ถ๋ฐฐ)
โข ํ & ์ด๋๋ฐ์ด์ : 2,000๋ง ๊ฐ (20%, 4๋ ๋ฒ ์คํ )
โข ์ฌ๋จ ๋ณด์ : 2,000๋ง ๊ฐ (20%, ์ํ๊ณ ๋ฐ์ ์ฉ)
๋ฐํ ์ ๋ต
1. ๋งค์ผ ์ ๋์ฑ ๊ณต๊ธ์์๊ฒ ๋ณด์ ๋ถ๋ฐฐ
2. ๊ฑฐ๋ ์์๋ฃ์ 50%๋ฅผ ํ ํฐ์ผ๋ก ์๊ฐ
3. ๋ถ๊ธฐ๋ง๋ค ๋ฐํ ์๋ ์กฐ์ (DAO ํฌํ)
4. ํ ํ ํฐ์ 12๊ฐ์ ํด๋ฆฌํ ํ 36๊ฐ์ ๋ฒ ์คํ
ํ์ค์ํ ๊ฑฐ๋์(DEX)์ ๊ฑฐ๋ฒ๋์ค ํ ํฐ ๋ฐํ๋ ๊ด๋ฆฌ
ํ ํฐ ๊ฒฝ์ ์ค๊ณ
โข ์ด ๋ฐํ๋: 1์ต ๊ฐ
โข ์ด๊ธฐ ์ ํต๋: 1,000๋ง ๊ฐ (10%)
โข ์ ๋์ฑ ์ฑ๊ตด ๋ณด์: 5,000๋ง ๊ฐ (50%, 4๋ ๊ฐ ๋ถ๋ฐฐ)
โข ํ & ์ด๋๋ฐ์ด์ : 2,000๋ง ๊ฐ (20%, 4๋ ๋ฒ ์คํ )
โข ์ฌ๋จ ๋ณด์ : 2,000๋ง ๊ฐ (20%, ์ํ๊ณ ๋ฐ์ ์ฉ)
๋ฐํ ์ ๋ต
1. ๋งค์ผ ์ ๋์ฑ ๊ณต๊ธ์์๊ฒ ๋ณด์ ๋ถ๋ฐฐ
2. ๊ฑฐ๋ ์์๋ฃ์ 50%๋ฅผ ํ ํฐ์ผ๋ก ์๊ฐ
3. ๋ถ๊ธฐ๋ง๋ค ๋ฐํ ์๋ ์กฐ์ (DAO ํฌํ)
4. ํ ํ ํฐ์ 12๊ฐ์ ํด๋ฆฌํ ํ 36๊ฐ์ ๋ฒ ์คํ
๐ฏ DeFi ํ๋กํ ์ฝ ํ ํฐ ์ปจํธ๋กค๋ฌ
class DeFiTokenController:
def __init__(self, base_controller):
self.controller = base_controller
self.liquidity_mining_pool = 50000000 # 5์ฒ๋ง ๊ฐ
self.daily_reward_rate = 0.001 # 0.1% per day
self.fee_burn_rate = 0.5 # 50% of fees
def calculate_liquidity_rewards(self, user_liquidity: float, total_liquidity: float) -> float:
"""
์ ๋์ฑ ์ฑ๊ตด ๋ณด์ ๊ณ์ฐ
"""
# ์ฌ์ฉ์์ ์ ๋์ฑ ๋น์จ
user_share = user_liquidity / total_liquidity
# ์ผ์ผ ์ด ๋ณด์
daily_total_reward = self.liquidity_mining_pool * self.daily_reward_rate
# ์ฌ์ฉ์ ๋ณด์
user_reward = daily_total_reward * user_share
return user_reward
def process_trading_fees(self, fee_amount: float, token_price: float):
"""
๊ฑฐ๋ ์์๋ฃ ์ฒ๋ฆฌ (์ผ๋ถ ์๊ฐ)
"""
# ์๊ฐํ ํ ํฐ ์ ๊ณ์ฐ
burn_amount = (fee_amount * self.fee_burn_rate) / token_price
print(f"๐ฐ ๊ฑฐ๋ ์์๋ฃ: ${fee_amount:.2f}")
print(f"๐ฅ ์๊ฐ ์์ : {burn_amount:.2f} ํ ํฐ")
# ์ค์ ์๊ฐ ์คํ
# burn_controller.fixed_burn(burn_amount)
return burn_amount
def adjust_emission_rate(self, new_rate: float, dao_approval: bool):
"""
๋ฐํ ์๋ ์กฐ์ (DAO ๊ฑฐ๋ฒ๋์ค)
"""
if not dao_approval:
print("โ DAO ์น์ธ์ด ํ์ํฉ๋๋ค!")
return False
old_rate = self.daily_reward_rate
self.daily_reward_rate = new_rate
print(f"โ
๋ฐํ ์๋ ์กฐ์ ์๋ฃ")
print(f" ์ด์ : {old_rate*100:.3f}% per day")
print(f" ๋ณ๊ฒฝ: {new_rate*100:.3f}% per day")
return True
# ์ค์ ์ฌ์ฉ
defi_controller = DeFiTokenController(controller)
# ์ ๋์ฑ ๋ณด์ ๊ณ์ฐ
user_liquidity = 100000 # $100,000
total_liquidity = 10000000 # $10,000,000
reward = defi_controller.calculate_liquidity_rewards(user_liquidity, total_liquidity)
print(f"์ผ์ผ ๋ณด์: {reward:.2f} ํ ํฐ")
# ๊ฑฐ๋ ์์๋ฃ ์ฒ๋ฆฌ
defi_controller.process_trading_fees(fee_amount=1000, token_price=2.5)
๐ฎ ์ฌ๋ก 2: ๊ฒ์ ๋ด ํ ํฐ ๊ฒฝ์
ํ๋ก์ ํธ ๊ฐ์
Play-to-Earn ๊ฒ์์ ์ธ๊ฒ์ ํ ํฐ ๊ด๋ฆฌ
ํ ํฐ ๊ฒฝ์ ์ค๊ณ
โข ๋ฌด์ ํ ๋ฐํ (์ธํ๋ ์ด์ ๋ชจ๋ธ)
โข ํ๋ ์ด์ด ํ๋์ ๋ฐ๋ผ ๋ณด์
โข ๊ฒ์ ๋ด ์์ดํ ๊ตฌ๋งค ์ ์๊ฐ
โข ๋์ ๋ฐธ๋ฐ์ฑ์ผ๋ก ๊ฒฝ์ ์์ ํ
ํต์ฌ ๋ฉ์ปค๋์ฆ
1. ํ๋ ์ด์ด๊ฐ ํ์คํธ ์๋ฃ ์ ํ ํฐ ํ๋
2. ์์ดํ ๊ตฌ๋งค/์ ๊ทธ๋ ์ด๋ ์ ํ ํฐ ์๊ฐ
3. ์ผ์ผ ๋ฐํ๋๊ณผ ์๊ฐ๋ ๋ชจ๋ํฐ๋ง
4. ์ธํ๋ ์ด์ ์จ์ด 5%๋ฅผ ์ด๊ณผํ๋ฉด ๋ณด์ ๊ฐ์
Play-to-Earn ๊ฒ์์ ์ธ๊ฒ์ ํ ํฐ ๊ด๋ฆฌ
ํ ํฐ ๊ฒฝ์ ์ค๊ณ
โข ๋ฌด์ ํ ๋ฐํ (์ธํ๋ ์ด์ ๋ชจ๋ธ)
โข ํ๋ ์ด์ด ํ๋์ ๋ฐ๋ผ ๋ณด์
โข ๊ฒ์ ๋ด ์์ดํ ๊ตฌ๋งค ์ ์๊ฐ
โข ๋์ ๋ฐธ๋ฐ์ฑ์ผ๋ก ๊ฒฝ์ ์์ ํ
ํต์ฌ ๋ฉ์ปค๋์ฆ
1. ํ๋ ์ด์ด๊ฐ ํ์คํธ ์๋ฃ ์ ํ ํฐ ํ๋
2. ์์ดํ ๊ตฌ๋งค/์ ๊ทธ๋ ์ด๋ ์ ํ ํฐ ์๊ฐ
3. ์ผ์ผ ๋ฐํ๋๊ณผ ์๊ฐ๋ ๋ชจ๋ํฐ๋ง
4. ์ธํ๋ ์ด์ ์จ์ด 5%๋ฅผ ์ด๊ณผํ๋ฉด ๋ณด์ ๊ฐ์
๐ฎ ๊ฒ์ ํ ํฐ ๊ฒฝ์ ์์คํ
class GameTokenEconomy:
def __init__(self):
self.total_minted = 0
self.total_burned = 0
self.daily_mint_limit = 1000000
self.target_inflation = 0.05 # 5%
self.base_reward = 100
def calculate_quest_reward(self, difficulty: str, player_level: int) -> float:
"""
ํ์คํธ ๋ณด์ ๊ณ์ฐ
"""
difficulty_multiplier = {
'easy': 1.0,
'medium': 2.0,
'hard': 3.5,
'legendary': 5.0
}
base = self.base_reward
diff_mult = difficulty_multiplier.get(difficulty, 1.0)
level_mult = 1 + (player_level * 0.1)
# ์ธํ๋ ์ด์
์กฐ์
inflation_rate = self.get_inflation_rate()
if inflation_rate > self.target_inflation:
inflation_penalty = 0.8 # 20% ๊ฐ์
else:
inflation_penalty = 1.0
reward = base * diff_mult * level_mult * inflation_penalty
return reward
def process_item_purchase(self, item_price: float, burn_rate: float = 0.3):
"""
์์ดํ
๊ตฌ๋งค ์ฒ๋ฆฌ (์ผ๋ถ ์๊ฐ)
"""
burn_amount = item_price * burn_rate
self.total_burned += burn_amount
print(f"๐ ์์ดํ
๊ตฌ๋งค: {item_price:.2f} ํ ํฐ")
print(f"๐ฅ ์๊ฐ: {burn_amount:.2f} ํ ํฐ")
print(f"๐ฐ ํ๋งค์ ์๋ น: {item_price - burn_amount:.2f} ํ ํฐ")
return burn_amount
def get_inflation_rate(self) -> float:
"""
ํ์ฌ ์ธํ๋ ์ด์
์จ ๊ณ์ฐ
"""
if self.total_burned == 0:
return 1.0
net_supply = self.total_minted - self.total_burned
inflation = (self.total_minted - self.total_burned) / self.total_minted
return inflation
def daily_economy_report(self):
"""
์ผ์ผ ๊ฒฝ์ ๋ฆฌํฌํธ
"""
inflation = self.get_inflation_rate()
net_supply = self.total_minted - self.total_burned
print("\n" + "="*60)
print("๐ฎ ๊ฒ์ ๊ฒฝ์ ์ผ์ผ ๋ฆฌํฌํธ")
print("="*60)
print(f"๐ฐ ์ด ๋ฐํ: {self.total_minted:,.2f} ํ ํฐ")
print(f"๐ฅ ์ด ์๊ฐ: {self.total_burned:,.2f} ํ ํฐ")
print(f"๐ ์ ๊ณต๊ธ: {net_supply:,.2f} ํ ํฐ")
print(f"๐ ์ธํ๋ ์ด์
: {inflation*100:.2f}%")
if inflation > self.target_inflation:
print(f"โ ๏ธ ๊ฒฝ๊ณ : ๋ชฉํ ์ธํ๋ ์ด์
({self.target_inflation*100}%)์ ์ด๊ณผํ์ต๋๋ค!")
print(f" ๋ณด์์ด ์๋์ผ๋ก ์กฐ์ ๋ฉ๋๋ค.")
else:
print(f"โ
๊ฒฝ์ ๊ฐ ์์ ์ ์
๋๋ค.")
print("="*60 + "\n")
# ๊ฒ์ ๊ฒฝ์ ์๋ฎฌ๋ ์ด์
game_economy = GameTokenEconomy()
# ํ๋ ์ด์ด๋ค์ด ํ์คํธ ์๋ฃ
for i in range(100):
reward = game_economy.calculate_quest_reward('medium', player_level=10)
game_economy.total_minted += reward
# ์์ดํ
๊ตฌ๋งค
for i in range(50):
game_economy.process_item_purchase(item_price=200)
# ์ผ์ผ ๋ฆฌํฌํธ
game_economy.daily_economy_report()
๊ฒ์ ํ ํฐ ๊ฒฝ์ ๋ ์ ๋ง ๋ณต์กํด! ๐ฎ
Axie Infinity ๊ฐ์ ๊ฒ์์ด ์ด๊ธฐ์ ์์ฒญ๋ ์ฑ๊ณต์ ๊ฑฐ๋์ง๋ง, ๋์ค์ ํ ํฐ ๊ฒฝ์ ๋ฐธ๋ฐ์ค๊ฐ ๋ฌด๋์ง๋ฉด์ ๋ฌธ์ ๊ฐ ์๊ฒผ์ด. ๋๋ฌด ๋ง์ ํ ํฐ์ด ๋ฐํ๋๊ณ , ์๊ฐ์ ์ถฉ๋ถํ์ง ์์์ ๊ฐ์น๊ฐ ํญ๋ฝํ ๊ฑฐ์ง. ๐
๊ทธ๋์ ๋์ ๋ฐธ๋ฐ์ฑ์ด ์ ๋ง ์ค์ํด! ๋ฐํ๋๊ณผ ์๊ฐ๋์ ์ค์๊ฐ์ผ๋ก ๋ชจ๋ํฐ๋งํ๊ณ , ์๋์ผ๋ก ์กฐ์ ํ๋ ์์คํ ์ด ํ์ํด. ๐ฏ
Axie Infinity ๊ฐ์ ๊ฒ์์ด ์ด๊ธฐ์ ์์ฒญ๋ ์ฑ๊ณต์ ๊ฑฐ๋์ง๋ง, ๋์ค์ ํ ํฐ ๊ฒฝ์ ๋ฐธ๋ฐ์ค๊ฐ ๋ฌด๋์ง๋ฉด์ ๋ฌธ์ ๊ฐ ์๊ฒผ์ด. ๋๋ฌด ๋ง์ ํ ํฐ์ด ๋ฐํ๋๊ณ , ์๊ฐ์ ์ถฉ๋ถํ์ง ์์์ ๊ฐ์น๊ฐ ํญ๋ฝํ ๊ฑฐ์ง. ๐
๊ทธ๋์ ๋์ ๋ฐธ๋ฐ์ฑ์ด ์ ๋ง ์ค์ํด! ๋ฐํ๋๊ณผ ์๊ฐ๋์ ์ค์๊ฐ์ผ๋ก ๋ชจ๋ํฐ๋งํ๊ณ , ์๋์ผ๋ก ์กฐ์ ํ๋ ์์คํ ์ด ํ์ํด. ๐ฏ
๐ง ์ค์ ํ๊ณผ ๋ฒ ์คํธ ํ๋ํฐ์ค
๋ง์ง๋ง์ผ๋ก, ์ค์ ์์ ์ ๋ง ์ ์ฉํ ํ๋ค์ ๊ณต์ ํ ๊ฒ! ์ด๊ฑด ๋ด๊ฐ ์ง์ ๊ฒฝํํ๋ฉด์ ๋ฐฐ์ด ๊ฒ๋ค์ด์ผ. ๐ก
โจ ์ค์ ํ ๋ชจ์
1. ํ ์คํธ๋ท์์ ์ถฉ๋ถํ ํ ์คํธํ๊ธฐ
๋ฉ์ธ๋ท์ ๋ฐฐํฌํ๊ธฐ ์ ์ Goerli, Sepolia ๊ฐ์ ํ ์คํธ๋ท์์ ์ต์ 2์ฃผ๋ ํ ์คํธํด์ผ ํด. ์ค์ ๋์ด ๊ฑธ๋ฆฐ ๋ฌธ์ ๋๊น! ๐งช
2. ์ ์ง์ ๋กค์์
์ฒ์๋ถํฐ ๋ชจ๋ ๊ธฐ๋ฅ์ ๋ค ์ผ์ง ๋ง. ๋จ๊ณ์ ์ผ๋ก ๊ธฐ๋ฅ์ ํ์ฑํํ๋ฉด์ ๋ฌธ์ ๊ฐ ์๋์ง ํ์ธํด. ๐ฆ
3. ์ปค๋ฎค๋ํฐ์ ์ํต
ํ ํฐ ๊ฒฝ์ ๋ณ๊ฒฝ์ฌํญ์ ๋ฐ๋์ ์ฌ์ ์ ๊ณต์งํ๊ณ , ์ปค๋ฎค๋ํฐ ํผ๋๋ฐฑ์ ๋ฐ์. ๊ฐ์์ค๋ฌ์ด ๋ณ๊ฒฝ์ ์ ๋ขฐ๋ฅผ ์๊ฒ ๋ง๋ค์ด. ๐ข
4. ๋น์ ์ ์ง ๋ฉ์ปค๋์ฆ
๋ฌธ์ ๊ฐ ์๊ฒผ์ ๋ ์ฆ์ ์์คํ ์ ๋ฉ์ถ ์ ์๋ 'Circuit Breaker'๋ฅผ ๋ง๋ค์ด๋ฌ. ํดํน์ด๋ ๋ฒ๊ทธ ๋ฐ์ ์ ํผํด๋ฅผ ์ต์ํํ ์ ์์ด. ๐
5. ์ ๊ธฐ์ ์ธ ๊ฐ์ฌ
์ต์ ๋ถ๊ธฐ๋ง๋ค ํ ๋ฒ์ฉ์ ์ ์ฒด ์์คํ ์ ๊ฐ์ฌํด. ์ธ๋ถ ๋ณด์ ์ ์ฒด์ ์๋ขฐํ๋ ๊ฒ๋ ์ข์. ๐
6. ๋ฐ์ดํฐ ๋ฐฑ์
๋ชจ๋ ํธ๋์ญ์ ๋ฐ์ดํฐ์ ๋ก๊ทธ๋ฅผ ์์ ํ๊ฒ ๋ฐฑ์ ํด. ๋์ค์ ๋ถ์์ด ์๊ธฐ๊ฑฐ๋ ๋ถ์์ด ํ์ํ ๋ ํ์์ผ. ๐พ
7. ๊ฐ์ค๋น ์ต์ ํ
์ด๋๋ฆฌ์์์๋ ๊ฐ์ค๋น๊ฐ ๋น์ธ๋๊น, ๋ฐฐ์น ์ฒ๋ฆฌ๋ ๋ ์ด์ด2 ์๋ฃจ์ ์ ๊ณ ๋ คํด๋ด. ์ฌ์ฉ์ ๊ฒฝํ์ด ํจ์ฌ ์ข์์ ธ. โฝ
8. ๋ชจ๋ํฐ๋ง ์๋ฆผ ์ค์
์ด์ ์งํ๊ฐ ๊ฐ์ง๋๋ฉด ์ฆ์ ์๋ฆผ์ ๋ฐ์ ์ ์๋๋ก ์ค์ ํด. ํ ๋ ๊ทธ๋จ, ์ฌ๋, ์ด๋ฉ์ผ ๋ฑ ๋ค์ํ ์ฑ๋์ ํ์ฉํด. ๐จ
1. ํ ์คํธ๋ท์์ ์ถฉ๋ถํ ํ ์คํธํ๊ธฐ
๋ฉ์ธ๋ท์ ๋ฐฐํฌํ๊ธฐ ์ ์ Goerli, Sepolia ๊ฐ์ ํ ์คํธ๋ท์์ ์ต์ 2์ฃผ๋ ํ ์คํธํด์ผ ํด. ์ค์ ๋์ด ๊ฑธ๋ฆฐ ๋ฌธ์ ๋๊น! ๐งช
2. ์ ์ง์ ๋กค์์
์ฒ์๋ถํฐ ๋ชจ๋ ๊ธฐ๋ฅ์ ๋ค ์ผ์ง ๋ง. ๋จ๊ณ์ ์ผ๋ก ๊ธฐ๋ฅ์ ํ์ฑํํ๋ฉด์ ๋ฌธ์ ๊ฐ ์๋์ง ํ์ธํด. ๐ฆ
3. ์ปค๋ฎค๋ํฐ์ ์ํต
ํ ํฐ ๊ฒฝ์ ๋ณ๊ฒฝ์ฌํญ์ ๋ฐ๋์ ์ฌ์ ์ ๊ณต์งํ๊ณ , ์ปค๋ฎค๋ํฐ ํผ๋๋ฐฑ์ ๋ฐ์. ๊ฐ์์ค๋ฌ์ด ๋ณ๊ฒฝ์ ์ ๋ขฐ๋ฅผ ์๊ฒ ๋ง๋ค์ด. ๐ข
4. ๋น์ ์ ์ง ๋ฉ์ปค๋์ฆ
๋ฌธ์ ๊ฐ ์๊ฒผ์ ๋ ์ฆ์ ์์คํ ์ ๋ฉ์ถ ์ ์๋ 'Circuit Breaker'๋ฅผ ๋ง๋ค์ด๋ฌ. ํดํน์ด๋ ๋ฒ๊ทธ ๋ฐ์ ์ ํผํด๋ฅผ ์ต์ํํ ์ ์์ด. ๐
5. ์ ๊ธฐ์ ์ธ ๊ฐ์ฌ
์ต์ ๋ถ๊ธฐ๋ง๋ค ํ ๋ฒ์ฉ์ ์ ์ฒด ์์คํ ์ ๊ฐ์ฌํด. ์ธ๋ถ ๋ณด์ ์ ์ฒด์ ์๋ขฐํ๋ ๊ฒ๋ ์ข์. ๐
6. ๋ฐ์ดํฐ ๋ฐฑ์
๋ชจ๋ ํธ๋์ญ์ ๋ฐ์ดํฐ์ ๋ก๊ทธ๋ฅผ ์์ ํ๊ฒ ๋ฐฑ์ ํด. ๋์ค์ ๋ถ์์ด ์๊ธฐ๊ฑฐ๋ ๋ถ์์ด ํ์ํ ๋ ํ์์ผ. ๐พ
7. ๊ฐ์ค๋น ์ต์ ํ
์ด๋๋ฆฌ์์์๋ ๊ฐ์ค๋น๊ฐ ๋น์ธ๋๊น, ๋ฐฐ์น ์ฒ๋ฆฌ๋ ๋ ์ด์ด2 ์๋ฃจ์ ์ ๊ณ ๋ คํด๋ด. ์ฌ์ฉ์ ๊ฒฝํ์ด ํจ์ฌ ์ข์์ ธ. โฝ
8. ๋ชจ๋ํฐ๋ง ์๋ฆผ ์ค์
์ด์ ์งํ๊ฐ ๊ฐ์ง๋๋ฉด ์ฆ์ ์๋ฆผ์ ๋ฐ์ ์ ์๋๋ก ์ค์ ํด. ํ ๋ ๊ทธ๋จ, ์ฌ๋, ์ด๋ฉ์ผ ๋ฑ ๋ค์ํ ์ฑ๋์ ํ์ฉํด. ๐จ
๐ ํ์ต ๋ฆฌ์์ค์ ๋ค์ ๋จ๊ณ
์ฌ๊ธฐ๊น์ง ๋ฐ๋ผ์๋ค๋ฉด ์ ๋ง ๋๋จํด! ๐ ํ์ง๋ง ๋ฐฐ์์ ์ฌ๊ธฐ์ ๋์ด ์๋์ผ. ๊ณ์ ๊ณต๋ถํ๊ณ ๋ฐ์ ํด์ผ ํด! ๐
๐ ์ถ์ฒ ํ์ต ์๋ฃ
๊ณต์ ๋ฌธ์
โข Ethereum.org - ์ด๋๋ฆฌ์ ๊ณต์ ๋ฌธ์
โข OpenZeppelin Docs - ์ค๋งํธ ์ปจํธ๋ํธ ๋ณด์
โข Web3.py Documentation - ํ์ด์ฌ ๋ธ๋ก์ฒด์ธ ๊ฐ๋ฐ
์จ๋ผ์ธ ์ฝ์ค
โข Coursera - Blockchain Specialization
โข Udemy - Ethereum and Solidity ์์ ์ ๋ณต
โข CryptoZombies - ๊ฒ์์ผ๋ก ๋ฐฐ์ฐ๋ ์ค๋งํธ ์ปจํธ๋ํธ
์ปค๋ฎค๋ํฐ
โข Ethereum Stack Exchange
โข Reddit r/ethdev
โข Discord - Ethereum ๊ฐ๋ฐ์ ์ฑ๋
์ค์ ํ๋ก์ ํธ
โข GitHub์์ ์ ๋ช DeFi ํ๋ก์ ํธ ์ฝ๋ ๋ถ์
โข ํด์ปคํค ์ฐธ์ฌ (ETHGlobal ๋ฑ)
โข ์คํ์์ค ํ๋ก์ ํธ ๊ธฐ์ฌ
๊ณต์ ๋ฌธ์
โข Ethereum.org - ์ด๋๋ฆฌ์ ๊ณต์ ๋ฌธ์
โข OpenZeppelin Docs - ์ค๋งํธ ์ปจํธ๋ํธ ๋ณด์
โข Web3.py Documentation - ํ์ด์ฌ ๋ธ๋ก์ฒด์ธ ๊ฐ๋ฐ
์จ๋ผ์ธ ์ฝ์ค
โข Coursera - Blockchain Specialization
โข Udemy - Ethereum and Solidity ์์ ์ ๋ณต
โข CryptoZombies - ๊ฒ์์ผ๋ก ๋ฐฐ์ฐ๋ ์ค๋งํธ ์ปจํธ๋ํธ
์ปค๋ฎค๋ํฐ
โข Ethereum Stack Exchange
โข Reddit r/ethdev
โข Discord - Ethereum ๊ฐ๋ฐ์ ์ฑ๋
์ค์ ํ๋ก์ ํธ
โข GitHub์์ ์ ๋ช DeFi ํ๋ก์ ํธ ์ฝ๋ ๋ถ์
โข ํด์ปคํค ์ฐธ์ฌ (ETHGlobal ๋ฑ)
โข ์คํ์์ค ํ๋ก์ ํธ ๊ธฐ์ฌ
๊ทธ๋ฆฌ๊ณ ๋ง์ฝ ๋ธ๋ก์ฒด์ธ ๊ฐ๋ฐ์ด๋ ํ ํฐ ๊ฒฝ์ ์ค๊ณ์ ๋ํด ๋ ๋ฐฐ์ฐ๊ณ ์ถ๋ค๋ฉด, ์ฌ๋ฅ๋ท์์ ์ ๋ฌธ๊ฐ๋ค์ ๋์์ ๋ฐ์ ์๋ ์์ด! ์ค์ ํ๋ก์ ํธ ๊ฒฝํ์ด ์๋ ๊ฐ๋ฐ์๋ค์ด ๋ฉํ ๋ง์ ํด์ฃผ๊ฑฐ๋ . ๐ฏ
๋ํ ๋ค๊ฐ ์ด ๋ถ์ผ์์ ์ ๋ฌธ์ฑ์ ์์๋ค๋ฉด, ์ฌ๋ฅ๋ท์์ ๋ค๋ฅธ ์ฌ๋๋ค์ ๋์์ฃผ๋ฉด์ ์์ต๋ ์ฐฝ์ถํ ์ ์์ด. ์ง์์ ๋๋๋ ๊ฑด ์ ๋ง ๋ณด๋์ฐฌ ์ผ์ด์ผ! ๐ช
๋ํ ๋ค๊ฐ ์ด ๋ถ์ผ์์ ์ ๋ฌธ์ฑ์ ์์๋ค๋ฉด, ์ฌ๋ฅ๋ท์์ ๋ค๋ฅธ ์ฌ๋๋ค์ ๋์์ฃผ๋ฉด์ ์์ต๋ ์ฐฝ์ถํ ์ ์์ด. ์ง์์ ๋๋๋ ๊ฑด ์ ๋ง ๋ณด๋์ฐฌ ์ผ์ด์ผ! ๐ช
๐ฏ ๋ง๋ฌด๋ฆฌํ๋ฉฐ
์! ์ ๋ง ๊ธด ์ฌ์ ์ด์์ง? ๐
์ฐ๋ฆฌ๊ฐ ์ค๋ ๋ฐฐ์ด ๋ด์ฉ์ ์ ๋ฆฌํด๋ณด์:
1. ํ ํฐ ๋ฐํ๋ ์ ์ด์ ์ค์์ฑ
ํ ํฐ ๊ฒฝ์ ์ ํต์ฌ์ด๋ฉฐ, ํ๋ก์ ํธ์ ์ฑํจ๋ฅผ ์ข์ฐํด. ๐ฐ
2. ํ์ด์ฌ์ผ๋ก ๋ชจ๋ํฐ๋ง ์์คํ ๊ตฌ์ถ
Web3.py๋ฅผ ํ์ฉํด์ ์ค์๊ฐ์ผ๋ก ํ ํฐ ์ํ๋ฅผ ์ถ์ ํ๊ณ ๊ด๋ฆฌํ ์ ์์ด. ๐
3. ๊ณ ๊ธ ์ ์ด ์ ๋ต
๋ฒ ์คํ , ์๊ฐ, ๋์ ๋ฐธ๋ฐ์ฑ ๋ฑ ๋ค์ํ ๋ฉ์ปค๋์ฆ์ ๋ฐฐ์ ์ด. ๐ฎ
4. ๋ณด์์ ์ค์์ฑ
๋ฉํฐ์๊ทธ, ๊ฐ์ฌ ๋ก๊ทธ, ์ํธํ ๋ฑ ๋ณด์์ ์ ๋ ํํํ ์ ์์ด. ๐
5. ์ค์ ์ ์ฉ ์ฌ๋ก
DeFi์ ๊ฒ์ ๋ฑ ์ค์ ํ๋ก์ ํธ์์ ์ด๋ป๊ฒ ํ์ฉ๋๋์ง ์ดํด๋ดค์ด. ๐
์ด์ ๋๋ ํ ํฐ ๋ฐํ๋์ ์ ์ดํ๋ ์คํฌ๋ฆฝํธ๋ฅผ ๋ง๋ค ์ ์์ด! ๋ฌผ๋ก ์ฒ์์๋ ์ด๋ ค์ธ ์ ์์ง๋ง, ๊ณ์ ์ฐ์ตํ๊ณ ์คํํ๋ค ๋ณด๋ฉด ์ ์ ์ต์ํด์ง ๊ฑฐ์ผ. ๐ช
๋ธ๋ก์ฒด์ธ ์ธ๊ณ๋ ์ ๋ง ๋น ๋ฅด๊ฒ ๋ณํ๊ณ ์์ด. ๋งค์ผ ์๋ก์ด ํ๋ก์ ํธ๊ฐ ๋์ค๊ณ , ์๋ก์ด ๊ธฐ์ ์ด ๊ฐ๋ฐ๋๊ณ ์์ง. ๊ทธ๋์ ๊ณ์ ๋ฐฐ์ฐ๊ณ ๋ฐ์ ํ๋ ๊ฒ ์ค์ํด! ๐
ํน์ ์ด ๊ธ์ ์ฝ์ผ๋ฉด์ ๊ถ๊ธํ ์ ์ด ์๊ธฐ๊ฑฐ๋, ์ค์ ํ๋ก์ ํธ์ ์ ์ฉํ๋ค๊ฐ ๋งํ๋ ๋ถ๋ถ์ด ์๋ค๋ฉด, ๋ธ๋ก์ฒด์ธ ์ปค๋ฎค๋ํฐ์ ์ง๋ฌธํด๋ด. ๋ค๋ค ์น์ ํ๊ฒ ๋์์ค ๊ฑฐ์ผ! ๐ค
๊ทธ๋ฆฌ๊ณ ๊ธฐ์ตํด! ํ ํฐ ๊ฒฝ์ ์ค๊ณ๋ ๋จ์ํ ์ฝ๋๋ฅผ ์์ฑํ๋ ๊ฒ ์ด์์ด์ผ. ๊ฒฝ์ ํ, ๊ฒ์ ์ด๋ก , ์ฌ๋ฆฌํ๊น์ง ๋ค์ํ ๋ถ์ผ์ ์ง์์ด ํ์ํด. ๊ทธ๋์ ๋ ์ฌ๋ฏธ์๊ณ ๋์ ์ ์ด์ง! ๐ฏ
์, ์ด์ ๋๋ง์ ํ ํฐ ๊ฒฝ์ ๋ฅผ ์ค๊ณํด๋ณผ ์๊ฐ์ด์ผ! ํ์ดํ ! ๐โจ
1. ํ ํฐ ๋ฐํ๋ ์ ์ด์ ์ค์์ฑ
ํ ํฐ ๊ฒฝ์ ์ ํต์ฌ์ด๋ฉฐ, ํ๋ก์ ํธ์ ์ฑํจ๋ฅผ ์ข์ฐํด. ๐ฐ
2. ํ์ด์ฌ์ผ๋ก ๋ชจ๋ํฐ๋ง ์์คํ ๊ตฌ์ถ
Web3.py๋ฅผ ํ์ฉํด์ ์ค์๊ฐ์ผ๋ก ํ ํฐ ์ํ๋ฅผ ์ถ์ ํ๊ณ ๊ด๋ฆฌํ ์ ์์ด. ๐
3. ๊ณ ๊ธ ์ ์ด ์ ๋ต
๋ฒ ์คํ , ์๊ฐ, ๋์ ๋ฐธ๋ฐ์ฑ ๋ฑ ๋ค์ํ ๋ฉ์ปค๋์ฆ์ ๋ฐฐ์ ์ด. ๐ฎ
4. ๋ณด์์ ์ค์์ฑ
๋ฉํฐ์๊ทธ, ๊ฐ์ฌ ๋ก๊ทธ, ์ํธํ ๋ฑ ๋ณด์์ ์ ๋ ํํํ ์ ์์ด. ๐
5. ์ค์ ์ ์ฉ ์ฌ๋ก
DeFi์ ๊ฒ์ ๋ฑ ์ค์ ํ๋ก์ ํธ์์ ์ด๋ป๊ฒ ํ์ฉ๋๋์ง ์ดํด๋ดค์ด. ๐
์ด์ ๋๋ ํ ํฐ ๋ฐํ๋์ ์ ์ดํ๋ ์คํฌ๋ฆฝํธ๋ฅผ ๋ง๋ค ์ ์์ด! ๋ฌผ๋ก ์ฒ์์๋ ์ด๋ ค์ธ ์ ์์ง๋ง, ๊ณ์ ์ฐ์ตํ๊ณ ์คํํ๋ค ๋ณด๋ฉด ์ ์ ์ต์ํด์ง ๊ฑฐ์ผ. ๐ช
๋ธ๋ก์ฒด์ธ ์ธ๊ณ๋ ์ ๋ง ๋น ๋ฅด๊ฒ ๋ณํ๊ณ ์์ด. ๋งค์ผ ์๋ก์ด ํ๋ก์ ํธ๊ฐ ๋์ค๊ณ , ์๋ก์ด ๊ธฐ์ ์ด ๊ฐ๋ฐ๋๊ณ ์์ง. ๊ทธ๋์ ๊ณ์ ๋ฐฐ์ฐ๊ณ ๋ฐ์ ํ๋ ๊ฒ ์ค์ํด! ๐
ํน์ ์ด ๊ธ์ ์ฝ์ผ๋ฉด์ ๊ถ๊ธํ ์ ์ด ์๊ธฐ๊ฑฐ๋, ์ค์ ํ๋ก์ ํธ์ ์ ์ฉํ๋ค๊ฐ ๋งํ๋ ๋ถ๋ถ์ด ์๋ค๋ฉด, ๋ธ๋ก์ฒด์ธ ์ปค๋ฎค๋ํฐ์ ์ง๋ฌธํด๋ด. ๋ค๋ค ์น์ ํ๊ฒ ๋์์ค ๊ฑฐ์ผ! ๐ค
๊ทธ๋ฆฌ๊ณ ๊ธฐ์ตํด! ํ ํฐ ๊ฒฝ์ ์ค๊ณ๋ ๋จ์ํ ์ฝ๋๋ฅผ ์์ฑํ๋ ๊ฒ ์ด์์ด์ผ. ๊ฒฝ์ ํ, ๊ฒ์ ์ด๋ก , ์ฌ๋ฆฌํ๊น์ง ๋ค์ํ ๋ถ์ผ์ ์ง์์ด ํ์ํด. ๊ทธ๋์ ๋ ์ฌ๋ฏธ์๊ณ ๋์ ์ ์ด์ง! ๐ฏ
์, ์ด์ ๋๋ง์ ํ ํฐ ๊ฒฝ์ ๋ฅผ ์ค๊ณํด๋ณผ ์๊ฐ์ด์ผ! ํ์ดํ ! ๐โจ
๊ด๋ จ ํค์๋
๋๊ธ ์์ฑ
์ด ๊ธ์ ๋ํ ์ฌ๋ฌ๋ถ์ ์๊ฐ์ ๋ค๋ ค์ฃผ์ธ์
๋ก๊ทธ์ธ์ด ํ์ํฉ๋๋ค
๋๊ธ์ ์์ฑํ๋ ค๋ฉด ๋จผ์ ๋ก๊ทธ์ธํด์ฃผ์ธ์.
๋๊ธ 0
๋๊ธ์ ๋ถ๋ฌ์ค๋ ์ค์
๋๋ค.
๋๊ธ์ ๋ถ๋ฌ์ค์ง ๋ชปํ์ต๋๋ค. ์ฐ๊ฒฐ ์ํ๋ฅผ ํ์ธํ๊ณ ๋ค์ ์๋ํด ์ฃผ์ธ์.
์ง์์ธ์ ์ฒ - ์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
- ์ ์๊ถ ๋ฐ ์์ ๊ถ: ๋ณธ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ๋ ์ AI ๊ธฐ์ ๋ก ์์ฑ๋์์ผ๋ฉฐ, ๋ํ๋ฏผ๊ตญ ์ ์๊ถ๋ฒ ๋ฐ ๊ตญ์ ์ ์๊ถ ํ์ฝ์ ์ํด ๋ณดํธ๋ฉ๋๋ค.
- AI ์์ฑ ์ปจํ ์ธ ์ ๋ฒ์ ์ง์: ๋ณธ AI ์์ฑ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ์ง์ ์ฐฝ์๋ฌผ๋ก ์ธ์ ๋๋ฉฐ, ๊ด๋ จ ๋ฒ๊ท์ ๋ฐ๋ผ ์ ์๊ถ ๋ณดํธ๋ฅผ ๋ฐ์ต๋๋ค.
- ์ฌ์ฉ ์ ํ: ์ฌ๋ฅ๋ท์ ๋ช ์์ ์๋ฉด ๋์ ์์ด ๋ณธ ์ปจํ ์ธ ๋ฅผ ๋ณต์ , ์์ , ๋ฐฐํฌ, ๋๋ ์์ ์ ์ผ๋ก ํ์ฉํ๋ ํ์๋ ์๊ฒฉํ ๊ธ์ง๋ฉ๋๋ค.
- ๋ฐ์ดํฐ ์์ง ๊ธ์ง: ๋ณธ ์ปจํ ์ธ ์ ๋ํ ๋ฌด๋จ ์คํฌ๋ํ, ํฌ๋กค๋ง, ๋ฐ ์๋ํ๋ ๋ฐ์ดํฐ ์์ง์ ๋ฒ์ ์ ์ฌ์ ๋์์ด ๋ฉ๋๋ค.
- AI ํ์ต ์ ํ: ์ฌ๋ฅ๋ท์ AI ์์ฑ ์ปจํ ์ธ ๋ฅผ ํ AI ๋ชจ๋ธ ํ์ต์ ๋ฌด๋จ ์ฌ์ฉํ๋ ํ์๋ ๊ธ์ง๋๋ฉฐ, ์ด๋ ์ง์ ์ฌ์ฐ๊ถ ์นจํด๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.
์์ง ๋๊ธ์ด ์์ต๋๋ค.