이더리움으로 크라우드 세일 만들기 #1(완)
토큰 만들기 다음 순서는 크라우드 세일 입니다. 토큰 만들기에 비해서 양은 적지만, 이해하기 어려운 부분이 많은것 같네요 ㅜㅜ
이해가 안되는 부분이나 번역이 애매한 부분은 이더리움 홈페이지에 있는 원문을 참고하면서 보는걸 추천 드립니다.
(본문에 있는 코드는 혹시 모르니 이더리움 홈페이지에서 복사 하는걸 추천 드려요)
원제 : CROWDSALE Raising funds from friends without a third party
출처 : https://ethereum.org/crowdsale
Crowdfund your idea
때때로 좋은 생각은 많은 자금과 공동 노력을 필요로 합니다. 기부금을 요청할 수는 있지만, 기부자는 견인력과 적절한 기금을 받을 확실한 프로젝트에 기부하는 것을 선호합니다. 이것은 크라우드 펀딩이 이상적 일 수 있는 예입니다. 도달 목표를 설정하고 마감일을 설정합니다. 목표를 달성하지 못하면 기부금이 반환되므로 기부자의 위험이 줄어듭니다. 코드가 공개되어있어 감사가 가능하기 때문에 중앙 집중식의 신뢰할 수 있는 플랫폼이 필요하지 않으므로 모든 사람들이 지불하게 되는 유일한 요금은 가스 요금뿐입니다.
TOKENS AND DAOS
이 예에서 우리는 보상을 관리하고 유지하는 방법과 자금이 모금 된 후 돈이 소비되는 방법이라는 두 가지 중요한 문제를 해결하여 더 나은 군중 기금 마련을 할 것입니다.
크라우드 펀딩의 보상은 대개 모든 기증자를 추적 할 수 있는 중앙의 변경 불가능한 데이터베이스에 의해 처리됩니다. 캠페인 기한을 지키지 못한 사람은 더 이상 참여할 수 없으며 마음을 바꾼 기증자는 빠져 나갈 수 없습니다. 대신 우리는 분산 된 방식으로 이를 수행하고 보상을 추적하기 위한 토큰(https://ethereum.org/token)을 만들 것입니다. 기여한 사람은 거래, 판매 또는 나중에 보관할 수 있는 토큰을 얻습니다. 제 보상을 제공 할 때가되면 생산자는 실제 제품에 대한 토큰 만 교환하면 됩니다. 기부자는 프로젝트가 목표를 달성하지 못했다고 하더라도 토큰을 유지할 수 있습니다.
또한 일반적으로 자금을 조달하는 사람들은 기금이 모금 된 후 자금이 어떻게 쓰이는지에 대해 아무런 말을 할 수 없으며 부적절한 관리로 인해 종종 결코 아무것도 제공하지 않는 프로젝트가 생깁니다. 이 프로젝트에서 우리는 시스템에서 나오는 돈을 승인해야하는 Democratic Organization(https://ethereum.org/dao)을 사용할 것입니다. 이것은 종종 crowdsale 또는 crowd equity라고 불리며, 토큰이 어떤 경우에 보상의 대상이 될 수 있는 토대입니다. 특히 집단이 모여 공통의 공공재를 건설하는 프로젝트에서 그러합니다.
- 테스트 중이라면 지갑을 testnet으로 전환하고 마이닝을 시작하십시오.
- 먼저 fixed supply token(https://ethereum.org/token#the-code)을 만듭니다. 이 예에서는 100 개의 공급량을 만들고 name gadgets, 상자 그림 이모티콘 (📦)을 기호로, 소수점이하는 0자리로 사용합니다. Deploy하고 주소를 저장하십시오.
- 이제 shareholder association(https://ethereum.org/dao#the-shareholder-association)을 만드십시오. 이 예에서는 방금 작성한 토큰의 주소를 공유 주소로 사용하고 10 분의 최소 쿼럼과 1500 분 (25 시간)을 투표 시간으로 사용합니다. 이 계약을 전개하고 주소를 저장하십시오.
THE CODE
이제 이 코드를 복사하고 crowdsale을 만들어 봅시다.
...................................................................................................
pragma solidity ^0.4.18;
interfacetoken {
function transfer(address receiver, uint amount) external;
}
contract Crowdsale {
address public beneficiary;
uintpublic fundingGoal;
uintpublic amountRaised;
uintpublic deadline;
uintpublic price;
token public tokenReward;
mapping(address => uint256) public balanceOf;
bool fundingGoalReached = false;
bool crowdsaleClosed = false;
eventGoalReached(address recipient, uint totalAmountRaised);
eventFundTransfer(address backer, uint amount, bool isContribution);
/**
* Constructor function
*
* Setup the owner
*/
function Crowdsale(
address ifSuccessfulSendTo,
uint fundingGoalInEthers,
uint durationInMinutes,
uint etherCostOfEachToken,
address addressOfTokenUsedAsReward
) public{
beneficiary = ifSuccessfulSendTo;
fundingGoal = fundingGoalInEthers * 1 ether;
deadline = now + durationInMinutes * 1 minutes;
price = etherCostOfEachToken * 1 ether;
tokenReward = token(addressOfTokenUsedAsReward);
}
/**
* Fallback function
*
* The function without name is the default function that is called whenever anyone sends funds to a contract
*/
function () payable public {
require(!crowdsaleClosed);
uint amount = msg.value;
balanceOf[msg.sender] += amount;
amountRaised += amount;
tokenReward.transfer(msg.sender, amount / price);
emit FundTransfer(msg.sender, amount, true);
}
modifier afterDeadline() { if (now >= deadline) _; }
/**
* Check if goal was reached
*
* Checks if the goal or time limit has been reached and ends the campaign
*/
function checkGoalReached() public afterDeadline {
if (amountRaised >= fundingGoal){
fundingGoalReached = true;
emit GoalReached(beneficiary, amountRaised);
}
crowdsaleClosed = true;
}
/**
* Withdraw the funds
*
* Checks to see if goal or time limit has been reached, and if so, and the funding goal was reached,
* sends the entire amount to the beneficiary. If goal was not reached, each contributor can withdraw
* the amount they contributed.
*/
function safeWithdrawal() public afterDeadline {
if (!fundingGoalReached) {
uint amount = balanceOf[msg.sender];
balanceOf[msg.sender] = 0;
if (amount > 0) {
if (msg.sender.send(amount)) {
emit FundTransfer(msg.sender, amount, false);
} else {
balanceOf[msg.sender] = amount;
}
}
}
if (fundingGoalReached && beneficiary == msg.sender) {
if (beneficiary.send(amountRaised)) {
emit FundTransfer(beneficiary, amountRaised, false);
} else {
//If we fail to send the funds to beneficiary, unlock funders balance
fundingGoalReached = false;
}
}
}
}
...................................................................................................
CODE HIGHLIGHTS
Crowdsale 함수 (계약 생성시 호출되는 함수)에서 변수 deadline 및 fundingGoal이 설정되는 방식은 다음과 같습니다.
...................................................................................................
fundingGoal = fundingGoalInEthers * 1 ether;
deadline = now + durationInMinutes * 1 minutes;
price = etherCostOfEachToken * 1 ether;
...................................................................................................
그것들은 당신이 솔리디티에서 코딩하는데 도움이 되는 special keywords(https://solidity.readthedocs.io/en/latest/units-and-global-variables.html) 중 하나입니다. 1 ether == 1000 finney 또는 2 days == 48 hours와 같은 것들을 평가할 수 있습니다. 시스템 내부에서 모든 이더 양은 이더의 가장 작은 분배 단위 인 wei에서 추적됩니다. 위의 코드는 100,000,000,000,000,000을 곱하여 자금 조달 목표를 wei로 변환 합니다(이는 special keyword ether가 변환하는 것입니다). 다음 행은 특수 키워드 now와 minutes의 조합을 사용하여 '현재 시간'에서 정확히 X 분 떨어진 timestamp를 작성합니다. 더 많은 글로벌 키워드를 보려면 solidity documentation on Globally available variables(https://solidity.readthedocs.io/en/latest/units-and-global-variables.html) 문서를 확인하십시오.
다음 줄은 지정된 주소에서 계약을 인스턴스화합니다.
...................................................................................................
tokenReward = token(addressOfTokenUsedAsReward);
...................................................................................................
계약서는 토큰이 무엇인지를 이해합니다. 왜냐하면 먼저 토큰을 정의한 이유는 코드를 다음과 같이 시작함으로써 정의했기 때문입니다.
...................................................................................................
interfacetoken{ functiontransfer(address receiver, uint amount){ } }
...................................................................................................
이것은 계약이 어떻게 작동하는지 또는 그것이 가지고 있는 모든 기능을 완전히 설명하지는 않지만이 계약이 필요로하는 것만을 설명합니다. 토큰은 전달 함수를 가진 계약이며 이 주소에 하나의 계약이 있습니다.
HOW TO USE
contracts로 이동 한 다음 계약서를 deploy하십시오.
- 성공한 경우 필드에 방금 만든 조직의 주소를 입력하십시오.
- 250개의 이더를 자금 조달 목표로 넣으십시오.
- 시험이나 보여주기를 위해 그냥 하는 경우, 3~10분으로 crowdsale 지속 시간을 넣으십시오. 그러나 정말로 기금을 모으고 있다면 45,000 (31 일)과 같이 더 많은 양을 입력할 수 있습니다.
- 각 토큰의 이더 비용은 판매를 위탁하는 토큰 수 (이전 단계에서 토큰의 "초기 공급"로 추가 한 최대 개수)에 따라 계산되어야합니다. 이 예에서는 5 개의 이더를 넣습니다.
- 작성한 토큰 주소는 토큰 보상 주소에 추가해야합니다.
가스 가격을 입력하고 deploy를 클릭하고 crowdsale이 생성 될 때까지 기다리십시오. crowdsale 페이지가 생성되면 보상을 지불 할 수 있도록 충분한 보상을 입금해야합니다. 군중의 주소를 클릭 한 다음 50 개의 gadgets를 입금하여 군중에게 보냅니다.
나는 100 개의 gadgets를 가지고 있다. 왜 모두 판매하지 않습니까?
이것은 매우 중요한 포인트입니다. 우리가 만들고있는 크라우드 세일은 토큰 소지자들에 의해 완전히 통제 될 것입니다. 이것은 모든 토큰 중 50 % + 1을 통제하는 사람이 모든 자금을 그들 자신에게 보낼 수 있는 위험을 만듭니다.
이러한 적대적 인수를 방지하기 위해 association contract에 특별한 코드를 만들거나 모든 자금을 단순한 주소로 보낼 수 있습니다. 단순화하기 위해 모든 gadgets의 절반 만 팔아 버리고 있습니다. 더 분산시키려는 경우 나머지 절반을 신뢰할 수있는 조직으로 분할하십시오.
RAISE FUNDS
crowdsale에 필요한 모든 토큰이 있으면 쉽게 기여할 수 있으며 모든 ethereum 지갑에서 수행 할 수 있습니다. 자금을 송금하십시오. 여기에서 관련 코드 비트를 볼 수 있습니다.
...................................................................................................
function () {
require(!crowdsaleClosed);
uint amount = msg.value;
// ...
...................................................................................................
unnamed function(https://solidity.readthedocs.io/en/latest/contracts.html#fallback-function)은 계약서에서 이더를 수신 할 때마다 실행되는 기본 함수입니다. 이 함수는 crowdsale이 활성화되어 있는지 자동으로 확인하고 호출자가 구입 한 토큰 수를 계산하여 해당 값을 보냅니다. crowdsale이 끝났거나 계약서에 토큰이 없으면 계약은 실행을 중지하고 보내진 이더는 반환됩니다(그러나 모든 가스는 소비됩니다).
이것은 계약이 누군가가 이더나 토큰 없이 떠날 수 있는 상황에 빠지지 않도록 하는 이점이 있습니다. 이 계약의 이전 버전에서 우리는 crowdsale이 끝난 후에도 계약을 self destruct(https://solidity.readthedocs.io/en/latest/units-and-global-variables.html#contract-related) 할 것입니다. 즉, 그 순간에 보내진 거래는 자금을 잃을 것입니다. 판매가 끝나면 던져 버리는 기능을 만들어서 돈을 잃어버리는 사람을 막을 수 있습니다.
계약에는 매개 변수가 없는 safeWithdrawl() 함수가 있는데, 수혜자가 모금 한 금액에 액세스하거나 기금 모금자가 실패한 경우 기금을 회수 할 수 있습니다.
Extending the crowdsale
WHAT IF THE CROWDSALE OVERSHOOTS ITS TARGET?
우리 코드에서는 두 가지 일만 일어날 수 있습니다. 즉, 군중이 목표에 도달했는지 또는 그렇지 않은지 입니다. 토큰 금액이 제한되어 있으므로 일단 목표에 도달하면 아무도 기여할 수 없음을 의미합니다. 그러나 crowdfunding의 역사에서는 예상보다 훨씬 적은 시간에 목표를 초과 달성하거나 필요한 금액을 여러번 올리는 프로젝트로 가득합니다.
UNLIMITED CROWDSALE
그래서 우리는 프로젝트를 약간 수정하여 제한된 토큰 세트를 보내는 대신, 누군가가 이더를 보낼 때마다 실제로 새 토큰을 만들어 냈습니다. 우선 Mintable Token(https://ethereum.org/token#central-mint)을 만들어야합니다.
그런 다음 crowdsale을 수정하여 mintToken에 대한 모든 멘션의 이름을 바꿉니다.
...................................................................................................
contract token { functionmintToken(address receiver, uint amount){ } }
// ...
function () {
// ...
tokenReward.mintToken(msg.sender, amount / price);
// ...
}
...................................................................................................
crowedsale 계약서를 게시하고 나면 주소를 가져 와서 토큰 계약서로 이동하여 소유권 변경 기능을 실행하십시오. 이것은 당신이 원하는 만큼 Mint Token 기능을 호출 할 수 있습니다.
Warning: 이것은 당신을 적대적인 인수 위험에 빠뜨립니다. crowdsale의 어느 시점에서든 이미 모인 금액 이상을 기부하면 누군가 파이 전체를 통제하고 훔칠 수 있습니다. 이를 막기 위한 많은 전략이 있지만 구현은 독자의 연습 과제로 남게 됩니다.
- 토큰을 구입할 때 프로젝트의 50 %를 항상 제어 할 수 있도록 동일한 양의 토큰을 창업자의 계정으로 보내도록 crowdsale을 수정하십시오.
- 적대적 제안을 막을 수 있는 신뢰할만한 제 3 자에게 거부권을 행사하도록 조직을 수정하십시오.
- 중앙 신뢰할 수 있는 당사자가 토큰 계정을 동결 할 수 있도록 토큰을 수정하여 대다수를 제어하는 단일 entity가 없음을 확인해야합니다.
읽어봤는데 내용을 이해하기 어렵네요.ㅠㅠ
저도 번역하면서 무슨내용인지 혼란스럽더라구요;;;
ICO 관련해서는 이곳(https://steemit.com/kr/@twinbraid/ico-01)의 내용도 참고하시면 좀 더 도움이 되실 것 같아요 ㅠㅠ
Congratulations @elysia! You received a personal award!
You can view your badges on your Steem Board and compare to others on the Steem Ranking
Vote for @Steemitboard as a witness to get one more award and increased upvotes!