3.24 vchain原始碼分析2
接下來是合約的第二部分,直接上程式碼,註釋都在程式碼中
// Contract to sell and distribute VEN tokens
// 分發VEN 代幣
contract VENSale is Owned{
/// chart of stage transition
///
/// deploy initialize startTime endTime finalize
/// | <-earlyStageLasts-> | | <- closedStageLasts -> |
/// O-----------O---------------O---------------------O-------------O------------------------O------------>
/// Created Initialized Early Normal Closed Finalized
enum Stage {
NotCreated,
Created,
Initialized,
Early,
Normal,
Closed,
Finalized
}
using SafeMath for uint256;
uint256 public constant totalSupply = (10 ** 9) * (10 ** 18); // 1 billion VEN, decimals set to 18 // 總量 10億枚
uint256 constant privateSupply = totalSupply * 9 / 100; // 9% for private ICO 私募
uint256 constant commercialPlan = totalSupply * 23 / 100; // 23% for commercial plan 企業投資人
uint256 constant reservedForTeam = totalSupply * 5 / 100; // 5% for team // 團隊保留
uint256 constant reservedForOperations = totalSupply * 22 / 100; // 22 for operations 持續經營及技術發展+ 商業落地推廣
// 59%
uint256 public constant nonPublicSupply = privateSupply + commercialPlan + reservedForTeam + reservedForOperations; // 非公開銷售 59%
// 41%
uint256 public constant publicSupply = totalSupply - nonPublicSupply; // 公開銷售41%
uint256 public constant officialLimit = 64371825 * (10 ** 18); // 官方銷售總量
uint256 public constant channelsLimit = publicSupply - officialLimit; // 渠道銷售總量
// packed to 256bit
struct SoldOut {
uint16 placeholder; // placeholder to make struct pre-alloced
// amount of tdokens officially sol out.
// max value of 120bit is about 1e36, it's enough for token amount
uint120 official; // 官方銷售數量
// 通過渠道銷售的代幣數量
uint120 channels; // amount of tokens sold out via channels
}
SoldOut soldOut;
uint256 constant venPerEth = 3500; // normal exchange rate 與以太幣的兌換 1 eth = 3500 ven
uint256 constant venPerEthEarlyStage = venPerEth + venPerEth * 15 / 100; // early stage has 15% reward 在早期階段,因為有獎勵 所以 1 eth = 3500 + 3500 * 15% = 4025 ven
uint constant minBuyInterval = 30 minutes; // each account can buy once in 30 minutes 每個帳戶可以在30分鐘內購買一次
uint constant maxBuyEthAmount = 30 ether; // 每個賬戶最大購買數量為30個eth等值的ven
VEN ven; // VEN token contract follows ERC20 standard
address ethVault; // the account to keep received ether 接收以太幣的賬戶
address venVault; // the account to keep non-public offered VEN tokens 傳送非公開提供VEN的賬戶
uint public constant startTime = 1503057600; // time to start sale 眾籌開始時間
uint public constant endTime = 1504180800; // tiem to close sale 眾籌結束時間
uint public constant earlyStageLasts = 3 days; // early bird stage lasts in seconds 早期階段的持續時間
bool initialized; // 初始化
bool finalized; // 結束
function VENSale() {
soldOut.placeholder = 1;
}
/// @notice calculte exchange rate according to current stage
/// @return exchange rate. zero if not in sale.
// 計算當前階段的兌換比例
function exchangeRate() constant returns (uint256){
if (stage() == Stage.Early) {
return venPerEthEarlyStage; // 早期階段的比例
}
if (stage() == Stage.Normal) {
return venPerEth; // 正常階段的比例
}
return 0;
}
/// @notice for test purpose
// 區塊產生時間
function blockTime() constant returns (uint32) {
return uint32(block.timestamp);
}
/// @notice estimate stage
/// @return current stage
// 得到當前處於哪一個階段
function stage() constant returns (Stage) {
if (finalized) {
return Stage.Finalized;
}
if (!initialized) {
// deployed but not initialized // 合約剛剛部署
return Stage.Created;
}
// 尚未開始眾籌
if (blockTime() < startTime) {
// not started yet
return Stage.Initialized;
}
// 售罄
if (uint256(soldOut.official).add(soldOut.channels) >= publicSupply) {
// all sold out
return Stage.Closed;
}
// 眾籌階段
if (blockTime() < endTime) {
// in sale
if (blockTime() < startTime.add(earlyStageLasts)) {
// early bird stage
return Stage.Early;
}
// normal stage
return Stage.Normal;
}
// closed
return Stage.Closed;
}
// 檢查是否是一個合約地址
function isContract(address _addr) constant internal returns(bool) {
uint size;
if (_addr == 0) return false;
assembly {
size := extcodesize(_addr)
}
return size > 0;
}
/// @notice entry to buy tokens
function () payable {
buy();
}
/// @notice entry to buy tokens
// 買幣
function buy() payable {
// reject contract buyer to avoid breaking interval limit
// 禁止合約賬戶購買代幣
require(!isContract(msg.sender));
require(msg.value >= 0.01 ether);
uint256 rate = exchangeRate(); //獲取兌換比例
// here don't need to check stage. rate is only valid when in sale
require(rate > 0);
// each account is allowed once in minBuyInterval
require(blockTime() >= ven.lastMintedTimestamp(msg.sender) + minBuyInterval);// 指定的時間內只允許買一次
uint256 requested;
// and limited to maxBuyEthAmount
// 限制購買數量
if (msg.value > maxBuyEthAmount) {
requested = maxBuyEthAmount.mul(rate); // 超過允許購買數量 , 就使用最大允許購買值乘以兌換率
} else {
requested = msg.value.mul(rate);
}
uint256 remained = officialLimit.sub(soldOut.official);
if (requested > remained) { // 要購買的數量 大於剩餘數量
//exceed remained
requested = remained;
}
uint256 ethCost = requested.div(rate); // 計算花費的以太幣
if (requested > 0) {
ven.mint(msg.sender, requested, true, blockTime());
// transfer ETH to vault
ethVault.transfer(ethCost); // 轉入以太幣
soldOut.official = requested.add(soldOut.official).toUINT120(); // 修改官方銷售的數量
onSold(msg.sender, requested, ethCost);
}
uint256 toReturn = msg.value.sub(ethCost); // (簡單來說,此處就是)找零
if(toReturn > 0) {
// return over payed ETH
msg.sender.transfer(toReturn);
}
}
/// @notice returns tokens sold officially
// 返回正式銷售的代幣
function officialSold() constant returns (uint256) {
return soldOut.official;
}
/// @notice returns tokens sold via channels
// 通過渠道銷售的幣
function channelsSold() constant returns (uint256) {
return soldOut.channels;
}
/// @notice manually offer tokens to channel // 手動為渠道提供token
function offerToChannel(address _channelAccount, uint256 _venAmount) onlyOwner {
Stage stg = stage(); // 獲取當前處於哪個階段
// since the settlement may be delayed, so it's allowed in closed stage
require(stg == Stage.Early || stg == Stage.Normal || stg == Stage.Closed);
soldOut.channels = _venAmount.add(soldOut.channels).toUINT120(); // 修改渠道銷售的token數量
//should not exceed limit 不能超過渠道銷售數量的限制
require(soldOut.channels <= channelsLimit);
ven.mint(
_channelAccount,
_venAmount,
true, // unsold tokens can be claimed by channels portion 未售出的代幣可以通過渠道部分來申領
blockTime()
);
onSold(_channelAccount, _venAmount, 0);
}
/// @notice initialize to prepare for sale
/// @param _ven The address VEN token contract following ERC20 standard
/// @param _ethVault The place to store received ETH
/// @param _venVault The place to store non-publicly supplied VEN tokens
// 初始化
function initialize(
VEN _ven, // 合約例項
address _ethVault, // 接收買家以太幣的地址
address _venVault) onlyOwner { // 傳送ven的地址
require(stage() == Stage.Created); //階段限制
// ownership of token contract should already be this
require(_ven.owner() == address(this)); // 所有許可權制
require(address(_ethVault) != 0); // 不能為空
require(address(_venVault) != 0);
ven = _ven;
ethVault = _ethVault;
venVault = _venVault;
// 團隊保留鑄幣
ven.mint(
venVault,
reservedForTeam.add(reservedForOperations),
false, // team and operations reserved portion can't share unsold tokens
blockTime()
);
// 私募和個人投資人的幣
ven.mint(
venVault,
privateSupply.add(commercialPlan),
true, // private ICO and commercial plan can share unsold tokens 可以共享未出售的token
blockTime()
);
initialized = true;
onInitialized();
}
/// @notice finalize
function finalize() onlyOwner {
// only after closed stage
require(stage() == Stage.Closed); // 階段限制
uint256 unsold = publicSupply.sub(soldOut.official).sub(soldOut.channels); // 計算未出售的代幣
if (unsold > 0) {
// unsold VEN as bonus
ven.offerBonus(unsold); // 將未出售的代幣作為獎勵
}
ven.seal();
finalized = true;
onFinalized();
}
event onInitialized(); // 初始化事件
event onFinalized(); // 完成事件
event onSold(address indexed buyer, uint256 venAmount, uint256 ethCost); // 事件 表示有人購買ven
}
-
學院Go語言視訊主頁
https://edu.csdn.net/lecturer/1928 -
掃碼獲取海量視訊及原始碼 QQ群:721929980
相關文章
- 3.23 vchain原始碼分析1AI原始碼
- 集合原始碼分析[2]-AbstractList 原始碼分析原始碼
- NettyPipeline原始碼分析(2)Netty原始碼
- Redis【2】- SDS原始碼分析Redis原始碼
- Redux原始碼分析(2) - createStoreRedux原始碼
- Netty Pipeline原始碼分析(2)Netty原始碼
- Architecture(2)Volley原始碼分析原始碼
- RxJava2原始碼分析RxJava原始碼
- Struts2 原始碼分析-----工作原理分析原始碼
- tomcat nio2原始碼分析Tomcat原始碼
- AFL二三事 -- 原始碼分析 2原始碼
- 【JDK】JDK原始碼分析-AbstractQueuedSynchronizer(2)JDK原始碼
- leveldb原始碼分析(2)-bloom filter原始碼OOMFilter
- Thinkphp3原始碼分析(2)PHP原始碼
- 3.22 以太貓原始碼分析2原始碼
- 以太坊原始碼分析(44)p2p-database.go原始碼分析原始碼DatabaseGo
- 以太坊原始碼分析(45)p2p-dial.go原始碼分析原始碼Go
- 以太坊原始碼分析(46)p2p-peer.go原始碼分析原始碼Go
- 以太坊原始碼分析(48)p2p-server.go原始碼分析原始碼ServerGo
- 以太坊原始碼分析(49)p2p-table.go原始碼分析原始碼Go
- 以太坊原始碼分析(50)p2p-udp.go原始碼分析原始碼UDPGo
- 3.24
- RxJava2原始碼分析(一):基本流程分析RxJava原始碼
- Java容器類框架分析(2)LinkedList原始碼分析Java框架原始碼
- Yii2原始碼分析(一):入口原始碼
- EOS原始碼分析(2)EOS執行原始碼
- cache2go – cachetable原始碼分析Go原始碼
- Struts2 原始碼分析-----攔截器原始碼解析 --- ParametersInterceptor原始碼
- 友好 RxJava2.x 原始碼解析(三)zip 原始碼分析RxJava原始碼
- 以太坊原始碼分析(14)P2P分析原始碼
- django-rest-framework原始碼分析2—認證(Authentication)原始碼解析DjangoRESTFramework原始碼
- iOS開發原始碼閱讀篇--FMDB原始碼分析2(FMResultSet)iOS原始碼
- Retrofit原始碼分析三 原始碼分析原始碼
- RxJava2.x 從原始碼分析原理RxJava原始碼
- RxJava2原始碼分析(二):操作符原理分析RxJava原始碼
- 【JDK原始碼分析系列】ArrayBlockingQueue原始碼分析JDK原始碼BloC
- 集合原始碼分析[3]-ArrayList 原始碼分析原始碼
- 集合原始碼分析[1]-Collection 原始碼分析原始碼