Hi VITE community,
We are LuckyOne team and we are so proud to tell you guys that we have developed a dApp on the top of VITE public chain.
The name of this dApp is called: LuckyOne.
Its rules are quite simple, very similar to a lottery ticket.
- Each time a draw is made, a lottery ticket with a number will be selected from the corresponding prize pool.
- The prizes are categorized as The Prize and Big Prize.
- The frequency for The Prize is one hour per draw. And the frequency for Big Prize is every 24 rounds of drawing The Prize (About 24 hours for each Big Prize)
- The winning number for The Prize is selected from the numbers happened in the current round, however, each winning number for Big Prize will be selected from all numbers happened in 24 rounds of The Prize.
- The probability of winning is only related to the number of tickets purchased in the current round;
- Each number has two chances to win, one chance for its current round of The Prize, and another one for the related Big Prize.
For now, we are requiring the permission from Vite Labs and I believe it will be very soon to put on Vite mobile wallet.
The contract address of this game is: vite_bb34549c9c0a7987b7ac4e0e8bab7fddc8ce04f79e3af4cd56
The source code uploaded to vite explorer: https://explorer.vite.net/account/vite_bb34549c9c0a7987b7ac4e0e8bab7fddc8ce04f79e3af4cd56
And you will find the contract content from below:
pragma soliditypp ^0.4.2;
contract HelloWorld {
struct Range {
address addr;
uint32 startNo;
uint32 endNo;
}
uint32 _joinOffset;
Range[10000000] _joinArr;
uint256 _rewardPool;
uint32 _lastLuckyOffset;
uint32 _nextT;
uint256 _rewardPoolA;
uint256 _rewardPoolB;
uint32 _round;
uint32 _luckyRoundCnt;
uint256 _limitAmount;
uint32 _timeUnit;
uint8 _crayInterval;
tokenId _vToken = "tti_5649544520544f4b454e6e40";
address _owner;
bool _deprecated;
// tp:0 luckyBoy, tp:1 crazyBoy
event _luckyCrazyBoy(uint8 tp, uint32 index, address indexed addr, uint luckyNo, uint256 winAmount);
event _join(uint32 index, address indexed addr, bytes32 indexed request, uint256 startNo, uint256 endNo);
event _error(string m);
constructor() public {
_owner = msg.sender;
_limitAmount = 10 vite;
init(1 hours, 24);
}
onMessage Join(uint32 cnt) payable {
require(!_deprecated);
require(cnt > 0);
require(_limitAmount * uint256(cnt) == msg.amount);
require(msg.tokenid == _vToken);
uint32 curJoinOffset = _joinOffset;
require(curJoinOffset < 10000000);
address fromAddr = msg.sender;
_rewardPool += msg.amount;
uint32 startNo;
if(curJoinOffset > 0) {
Range storage rg = _joinArr[curJoinOffset - 1];
startNo = rg.endNo + 1;
}
uint32 endNo = startNo + cnt - 1;
require(startNo <= endNo);
Range memory rg = Range(fromAddr, startNo, endNo);
_joinArr[curJoinOffset] = rg;
_joinOffset = curJoinOffset + 1;
uint32 curRound = _round;
emit _join(curRound, fromAddr, fromhash(), startNo, endNo);
checkTrigger(curRound, curJoinOffset);
}
onMessage Trigger() {
require(!_deprecated);
if (now < _nextT) {
return;
}
uint32 joinOffset = _joinOffset;
uint32 lastLuckyOffset = _lastLuckyOffset;
if ((lastLuckyOffset == 0 && joinOffset == 0) || lastLuckyOffset == (joinOffset-1) ) {
_nextT = uint32(now) + _timeUnit;
return;
}
checkTrigger(_round, joinOffset - 1);
}
onMessage UpdateArgs(uint32 timeUnit, uint8 crazyInterval) payable {
require(!_deprecated);
require(_owner == msg.sender);
require(timeUnit >= 5 minutes);
require(timeUnit < 2 weeks);
init(timeUnit, crazyInterval);
}
onMessage Upgrade(){
require(_owner == msg.sender);
uint256 amount = balance(msg.tokenid);
msg.sender.transfer(msg.tokenid, amount);
_deprecated = true;
}
function init(uint32 timeUnit, uint8 crayInterval) public {
_nextT = uint32(now) + timeUnit;
_timeUnit = timeUnit;
_crayInterval = crayInterval;
}
function checkTrigger(uint32 curRound, uint32 curJoinOffset) public {
if (now >= _nextT) {
tokenId tk = _vToken;
address owner = _owner;
rewardLuckyBoy(curRound, tk, owner, curJoinOffset);
// start next lucky round
startLuckyNext(curJoinOffset);
curRound = _round;
if (_luckyRoundCnt >= _crayInterval) {
rewardCrazyBoy(curRound, tk, owner, curJoinOffset);
// start next crazy round
startCrazyNext(curRound);
}
}
}
function rewardLuckyBoy(uint32 curRound, tokenId tk, address owner, uint32 curJoinOffset) public {
uint32 luckyNo = calcLuckyNo(curJoinOffset, _luckyRoundCnt);
address luckyAddr;
(luckyAddr,,) = searchAddress(luckyNo, curJoinOffset);
uint256 fee;
uint256 reward;
(reward,fee) = calcLuckyReward();
luckyAddr.transfer(tk, reward);
owner.transfer(tk, fee);
emit _luckyCrazyBoy(0, curRound, luckyAddr, luckyNo, reward);
}
function startLuckyNext(uint32 curJoinOffset) public {
uint256 rewardPool = _rewardPool;
_rewardPoolA = _rewardPoolA + (rewardPool * 2 / 5);
_rewardPoolB = _rewardPoolB + (rewardPool * 1 / 10);
_rewardPool = 0;
_round += 1;
_lastLuckyOffset = curJoinOffset;
_luckyRoundCnt += 1;
_nextT = uint32(now) + _timeUnit;
}
function rewardCrazyBoy(uint32 curRound, tokenId tk, address owner, uint32 curJoinOffset) public {
uint32 crazyNo = calcCrazyNo(curJoinOffset);
address crazyAddr;
(crazyAddr,,) = searchAddress(crazyNo ,curJoinOffset);
uint256 fee;
uint256 reward;
(reward,fee) = calcCrazyReward();
crazyAddr.transfer(tk, reward);
owner.transfer(tk, fee);
emit _luckyCrazyBoy(1, curRound, crazyAddr, crazyNo, reward);
}
function startCrazyNext(uint32 curRound) public {
_rewardPoolA = _rewardPoolB;
_rewardPoolB = 0;
_luckyRoundCnt = 0;
_joinOffset = 0;
_lastLuckyOffset = 0;
}
function calcLuckyReward() public returns(uint256,uint256) {
uint256 allReward = _rewardPool / 2;
return (allReward * 95 / 100, allReward * 5 / 100);
}
function calcCrazyReward() public returns(uint256,uint256) {
uint256 allReward = _rewardPoolA;
return (allReward * 95 / 100, allReward * 5 / 100);
}
function calcLuckyNo(uint32 curJoinOffset, uint32 luckyRoundCnt) public returns(uint32) {
uint64 random = random64();
uint32 lastLuckyTotal;
uint32 luckyTotal;
if (luckyRoundCnt != 0){
Range storage rg = _joinArr[_lastLuckyOffset];
lastLuckyTotal = rg.endNo + 1;
}
Range storage rg = _joinArr[curJoinOffset];
luckyTotal = rg.endNo + 1;
return uint32(random % (luckyTotal - lastLuckyTotal)) + lastLuckyTotal;
}
function searchAddress(uint32 luckyNo, uint32 curJoinOffset) public returns(address,uint32,uint32) {
// if (luckyNo < 3){
// return searchAddressSimple(luckyNo, curJoinOffset);
// }
return searchAddressBinarySearch(luckyNo, curJoinOffset);
}
function searchAddressBinarySearch(uint32 luckyNo, uint32 curJoinOffset) public returns(address,uint32,uint32) {
uint32 endIdx = curJoinOffset;
uint32 startIdx = 0;
for (;;) {
uint32 middleIdx = (endIdx+startIdx)/2;
Range storage rg = _joinArr[middleIdx];
uint32 endNo = rg.endNo;
uint32 startNo = rg.startNo;
if (luckyNo > endNo) {
if (startIdx == middleIdx) {
startIdx = middleIdx + 1;
} else {
startIdx = middleIdx;
}
} else if (luckyNo < startNo) {
if (endIdx == middleIdx) {
endIdx = endIdx - 1;
} else {
endIdx = middleIdx;
}
} else {
return (rg.addr, startNo, endNo);
}
if(startIdx>endIdx){
emit _error("can't calc arr idx by bs.");
break;
}
}
return (_owner, 0, 0);
}
function searchAddressSimple(uint32 luckyNo, uint32 curJoinOffset) public returns(address,uint32,uint32) {
for (uint32 i = 0; i <= curJoinOffset; i++) {
Range storage rg = _joinArr[i];
uint32 startNo = rg.startNo;
uint32 endNo = rg.endNo;
if (luckyNo >= startNo && luckyNo <= endNo) {
return (rg.addr,startNo,endNo);
}
}
return (_owner, 0, 0);
}
function calcCrazyNo(uint32 curJoinOffset) public returns(uint32) {
uint64 random = random64();
Range storage rg = _joinArr[curJoinOffset];
uint32 len = rg.endNo + 1;
return uint32(random % len);
}
getter getState() returns(uint32,uint32,uint,uint,uint,uint256,uint32,uint8,uint256,uint256,uint256) {
return (_round,
(_round - _luckyRoundCnt),
_joinOffset,
_lastLuckyOffset,
_nextT,
_limitAmount,
_timeUnit,
_crayInterval,
_rewardPool,
_rewardPoolA,
_rewardPoolB);
}
getter getBasicState() returns(uint256,uint32,uint32,address) {
return (_limitAmount,
_timeUnit,
_crayInterval,
_owner);
}
getter getJoinState(uint offset) returns(address,uint32,uint32) {
Range storage rg = _joinArr[offset];
return (rg.addr,
rg.startNo,
rg.endNo);
}
}