Skip to content

Instantly share code, notes, and snippets.

@akirattii
Last active December 22, 2016 10:29
Show Gist options
  • Save akirattii/f9c787eeb50758ce600d70cf0db2ed67 to your computer and use it in GitHub Desktop.
Save akirattii/f9c787eeb50758ce600d70cf0db2ed67 to your computer and use it in GitHub Desktop.
Ethereum クラウドセール・コントラクト(β)
pragma solidity ^0.4.7;
// =======================================================
// クラウドセール・コントラクトのおおまかな処理
// =======================================================
// + コンストラクタで独自コインの総量などを決定
//
// + 出資者からの資金提供と引き換えに独自コインを渡す
//
// + 募集期限終了後、誰でもクラウドセール終了のトリガーを引ける
//
// - 調達額が目標に届いた場合:
// - 終了のトリガーを引いたのがオーナーだった場合:
// + オーナーは調達資金を手に入れる
// + 成功フラグを立てる
// - 終了のトリガーを引いたのがオーナー*以外*だった場合:
// + 成功フラグを立てる
//
// - 調達が目標に届かなかった場合:
// - 終了のトリガーを引いたのが誰であろうと:
// + 出資者はオーナーにコインを返却
// + 出資者はオーナーから資金を取り戻す
// + 成功フラグを倒す
//
// クラウドセール・コントラクト
contract Crowdsale {
// クラウドセールの成功フラグ
bool public succeeded;
// コイン保有者一覧
mapping (address => uint) public coinBalanceOf;
// 出資者に対して発行するコインの単価(ether)
uint public coinPrice;
// コントラクトの作成者
address public owner;
// 調達目標額
uint public fundingGoal;
// 調達額
uint public amountRaised;
// 募集期限
uint public deadline;
// 出資者
Funder[] public funders;
// 出資者の構造体
struct Funder {
address addr;
uint amount;
}
// コイン送金イベント
event CoinTransfer(address sender, address receiver, uint amount);
// 資金送信イベント
event FundTransfer(address backer, uint amount, bool isContribution);
// デバッグログイベント
event Log(string method, address sender, string message);
// このコントラクトのコンストラクタ
function Crowdsale(
uint _fundingGoal,
uint _duration,
uint _coinPrice,
uint _coinSupply
) {
Log("Constructor", msg.sender, "");
succeeded = false;
owner = msg.sender; // オーナーはコントラクト作成者
fundingGoal = _fundingGoal;
deadline = now + _duration * 1 minutes;
coinPrice = _coinPrice;
coinBalanceOf[msg.sender] = _coinSupply;
}
// 無名関数
// Note: 誰かが資金を送信する度に実行されます
function() payable {
Log("Payable anonymous function", msg.sender, "");
uint amount = msg.value;
// 資金送信者を出資者として登録
funders[funders.length++] = Funder({addr: msg.sender, amount: amount});
// 出資額に加算
amountRaised += amount;
// 出資額に見合った数のコインを出資者に発行
sendCoin(owner, msg.sender, amount / coinPrice);
// 資金送信イベント発火
FundTransfer(msg.sender, amount, true);
}
// コイン送金
// @param {address} コイン送金人
// @param {address} コイン受取人
// @param {uint} 数量
function sendCoin(address from, address to, uint amount) returns(bool sufficient) {
Log("sendCoin", msg.sender, "");
if (coinBalanceOf[from] < amount) return false;
// コインを移転
coinBalanceOf[from] -= amount;
coinBalanceOf[to] += amount;
// コイン送信イベント発火
CoinTransfer(from, to, amount);
return true;
}
// 「募集期限満了後」のみ関数を実行するためのmodifier
modifier afterDeadline() { if (now >= deadline) _; }
// 「コントラクトの作成者の場合」のみ関数を実行するためのmodifier
modifier onlyOwner() { if (owner == msg.sender) _; }
// 目標到達をチェックする関数
// Note: 募集期限満了後に実行できます。
function checkGoalReached() afterDeadline {
Log("checkGoalReached", msg.sender, "");
uint i;
if (amountRaised >= fundingGoal){
// *****************************************
// 目標達成
// *****************************************
// オーナーによる実行の場合は、オーナーへ調達額を送金
if(msg.sender == owner && owner.send(amountRaised)){
// sendに成功したら資金送金イベント発火
FundTransfer(owner, amountRaised, false);
}
// 成功フラグを立てる
succeeded = true;
Log("checkGoalReached", msg.sender, "Fundraise succeeded!");
} else {
// *****************************************
// 目標未達
// *****************************************
// FundTransfer(0, 11, false); // ???
// 全出資者に対してループ
for (i = 0; i < funders.length; ++i) {
// 予め受け取っていたトークンをオーナーに返却
if (sendCoin(funders[i].addr, owner, coinBalanceOf[funders[i].addr])) {
// トークンを戻すことに成功したら、出資者に返金
if (funders[i].addr.send(funders[i].amount)) {
// 返金に成功したら資金送金イベント発火
FundTransfer(funders[i].addr, funders[i].amount, false);
}
}
}
// 成功フラグを倒す(つまり失敗)
succeeded = false;
Log("checkGoalReached", msg.sender, "Fundraise failed :(");
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment