Bitcoin Forum
May 12, 2024, 06:37:38 PM *
News: Latest Bitcoin Core release: 27.0 [Torrent]
 
  Home Help Search Login Register More  
  Show Posts
Pages: « 1 [2] 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 »
21  Alternate cryptocurrencies / Announcements (Altcoins) / Re: [RLT][SMARTPLAY.TECH] 🎰 Vote for the design and get 100 RLT 🎰 on: March 30, 2018, 03:44:51 PM
RLT token rate dynamics review for March 30, 2018



Current crypto market state as a whole and the strong fall of leading cryptocurrencies such as bitcoin, affected the token value and its trade turnover. Despite this, the token rate has already increased, let's look at the current indicators in more detail: the SmartPlay.tech team has prepared a fresh market survey demonstrating the dynamics of the coin's rate.

According to coinmarketcap.com, RLT token reached Top-5 biggest gainers for the last 24 hours. With respect to the dollar and the bitcoin, the rate rose by 26% and 36%, respectively. At the moment (03/30/2018) the token costs $ 0.064, so now it’s the best time to buy RLT since the price is still not high.


There is also a significant price increase paired with the ether - 32% for the last 24 hours. The market cap exceeded the value of $ 650,000 USD and is now continuing its steady growth, accompanied by an increase in trading turnover. The trading volume for 24 hours is about $ 100,000 USD, more than 99% of which still fall on the RLT / BTC currency pair.

RLT has the real potential, since the team continues to work actively to further develop the project. The end of the month is near - the new version of the site is about to be released. Moreover, negotiations with a number of exchanges for listing are an incentive for the further growth of the exchange rate, which will certainly help increase the volume of trades and attract new project participants.
We remind that at the moment RLT is available on livecoin.net, where it is traded in RLT / BTC, RLT / ETH, RLT / RUR, RLT / USD currency pairs.

Join the Telegram group and chat with the project representative and its investors in the real time mode, be the first to know about the Airdrop launch and release of the new site.
22  Local / Альтернативные криптовалюты / Re: [SmartBox][RLT][BOUNTY] 🎰 Первые в мире блокчейн автоматы SmartPlay.tech 🎰 on: March 23, 2018, 12:34:31 PM
Проект будет перспективен и востребован! Хотелось бы ознакомиться с последними новостями о проекте?!
Все последние новости проекта доступны на данной ветке форума, а также в официальном чате Телеграмм.
23  Local / Альтернативные криптовалюты / Re: [SmartBox][RLT][BOUNTY] 🎰 Первые в мире блокчейн автоматы SmartPlay.tech 🎰 on: March 23, 2018, 12:33:18 PM
интересный проект, хотелось бы конечно разнообразия, а и планируется ли выход все же на другие биржи, а то на лайвкоине купишь монету чтобы поиграть немного, и больше половины оставишь на той самой бирже
Благодарим за Ваш отзыв о проекте!
Да, в настоящий момент продолжаются переговоры с рядом бирж по размещению токена RLT в их листингах.
В качестве разнообразия скоро состоится запуск новой игры, не похожей ни на одну из двух ранее представленных.
24  Local / Альтернативные криптовалюты / Re: [SmartBox][RLT][BOUNTY] 🎰 Первые в мире блокчейн автоматы SmartPlay.tech 🎰 on: March 22, 2018, 07:44:43 PM
Smartplay.tech представила будущий дизайн рулетки

Команда SmartPlay.Tech находится на пути к завершению поставленных в первоначальной дорожной карте задач, одной из которых является запуск рулетки с 3D дизайном.

Что уже сделано:

- добавлены сикслайны
- добавлены стриты
- реализован полноценный спин
- визуальное отображение ставок
- реализован базовый функционал фронтенд-бэкенд
- новые 3D-модели колеса рулетки
- оптимизированы текстуры
- улучшено отображение фишек
- настроена физика шарика-колеса
- добавлен звук падения шарика
- мелкие исправления
- выпадение шарика

Прямо сейчас Вы можете увидеть дизайн, который обретет рулетка. Более того, помимо обновленного дизайна рулетки, уже в скором времени команда SmartPlay.tech порадует всех пользователей запуском обновленной версии сайта и анонсом новой игры.

Оценивай 3D дизайн рулетки, делись своими впечатлениями в нашей группе Телеграмм.

25  Alternate cryptocurrencies / Announcements (Altcoins) / Re: [RLT][SMARTPLAY.TECH] 🎰 Vote for the design and get 100 RLT 🎰 on: March 22, 2018, 07:40:25 PM
SmartPlay.tech: the future roulette design is announced


The SmartPlay.Tech team is on the way to completing the tasks set in the original road map, one of which is the launch of a 3D roulette design. We decided to integrate it in the functional of win-win Roulette which will be advanced for launching the affiliate traffic as a priority.

With new Unity designer the current Roulette game will bring more tecnological and modern view. Fast response and high usability features will be also an integral part of it.

What's upgraded at the moment?

-line bets
-street bets
-full spin
-visual display of rates
-basic functionality of the front-end and back-end (at the moment back-end calls and responses are emulated, afterwards it will be possible to insert commands using API)
-new 3D models of the roulette wheel
-optimized textures
-Improved display of chips
-the physics of the ball-wheel is tuned
-added the sound of the ball drop
-minor fixes

Already now you can see the design that will be integrated into the roulette. Moreover, in addition to the updated roulette design, an updated version of the site and the announcement of a new game will take place.

Check the 3D roulette design and share your opinion in our Telegram group.
26  Alternate cryptocurrencies / Announcements (Altcoins) / Re: [RLT][SMARTPLAY.TECH] 🎰 Vote for the design and get 100 RLT 🎰 on: March 15, 2018, 01:28:45 PM
🚀New stylish design of the main website🚀

The SmartPlay.tech team is glad to present the new stylish design of the main website.


Do not forget to share your opinion with other project participants and leave your feedback on this thread or in the Telegram group.

I think this design is absolutely amazing!
When will the main site with the new design be launched?
The devteam is doing their best to launch the new version of the site before the end of the month.
27  Local / Альтернативные криптовалюты / Re: [SmartBox][RLT][BOUNTY] 🎰 Первые в мире блокчейн автоматы SmartPlay.tech 🎰 on: March 15, 2018, 11:59:09 AM
🚀Новый дизайн сайта Smartplay.tech🚀

Команда проекта SmartPlay.tech рада представить новый дизайн основного сайта.


Не забудьте поделиться своим мнением и оставьте отзыв в этой ветке или в официальной группе в Телеграмм.

в принципе выглядит симпатично. а когда полное обновление сайта будет? это ведь, как я понимаю всего лишь прототип?
Постараемся представить новый сайт до конца месяца.
28  Alternate cryptocurrencies / Announcements (Altcoins) / Re: [RLT][SMARTPLAY.TECH] 🎰 Vote for the design and get 100 RLT 🎰 on: March 14, 2018, 02:18:10 PM
🚀New stylish design of the main website🚀

The SmartPlay.tech team is glad to present the new stylish design of the main website.


Do not forget to share your opinion with other project participants and leave your feedback on this thread or in the Telegram group.

I like that design so much!
Hope we'll be able to test it soon  Grin
Thank you! Our designers are working hard on both the game design and the site design. The launch date will be announced in the nearest time.
29  Alternate cryptocurrencies / Announcements (Altcoins) / Re: [RLT][SMARTPLAY.TECH] 🎰 Vote for the design and get 100 RLT 🎰 on: March 14, 2018, 01:01:46 PM
🚀New stylish design of the main website🚀

The SmartPlay.tech team is glad to present the new stylish design of the main website.


Do not forget to share your opinion with other project participants and leave your feedback on this thread or in the Telegram group.

30  Local / Альтернативные криптовалюты / Re: [SmartBox][RLT][BOUNTY] 🎰 Первые в мире блокчейн автоматы SmartPlay.tech 🎰 on: March 14, 2018, 12:58:07 PM
🚀Новый дизайн сайта Smartplay.tech🚀

Команда проекта SmartPlay.tech рада представить новый дизайн основного сайта.


Не забудьте поделиться своим мнением и оставьте отзыв в этой ветке или в официальной группе в Телеграмм.

31  Alternate cryptocurrencies / Announcements (Altcoins) / Re: [RLT][SMARTPLAY.TECH] 🎰 Vote for the design and get 100 RLT 🎰 on: March 13, 2018, 01:21:41 PM
Hello everybody. I want to say thank you to the developers for the fact that you are promoting the coin. This is a huge plus. I hope that the price will soon be over $ 1. Good luck to all.
Thank you for your support!
Now are working hard to achieve more results and develop the project, but we'll back with great news soon  Smiley
32  Alternate cryptocurrencies / Announcements (Altcoins) / Re: [RLT][SMARTPLAY.TECH] 🎰 Vote for the design and get 100 RLT 🎰 on: March 12, 2018, 11:53:10 AM
How fair is the roulette on the Ethereum smart contract?  An independent audit of the game contract

We present to your attention a roulette audit from an independent developer Paul Rubin. Read, study and share your opinion about roulette!

Today it is very unlikely to meet a person who hasn't heard about cryptocurrencies and, in particular, about Bitcoin. In 2014, on a wave of interest in bitcoin, a new cryptocurrency - Ethereum, has been created. Today, in 2018, it has the largest capitalization after bitcoin. One of its most important differences from bitcoin is the use of a Turing virtual machine - EVM. More information about the Ethererum can be found in its Yellow Paper.

Today we will explore a game that works with Metamask wallet, a plugin for Google Chrome.

The game is the realization of the European roulette: there is the field with 37 cells numbered from 0 to 36. A player can bet on a specific number, or on a set of numbers: even/odd, red/black, 1-12, 1-18, etc. In each round, the player can make multiple bets (the minimum bet size is 0.01 ETH ≈ $ 7.26) on the corresponding field of the game table. Each field corresponds to a winning ratio. For example, the rate "to red" corresponds to a coefficient of 2 - placing a bet in amount of 0.01 ETH, in case of winning, the player will receive 0.02 ETH. And if the player bets on zero, the coefficient will be 36: paying the same 0.01 ETH for the bet the player will get 0.36.

Note
In the game contract, the coefficient for this bet is also listed as 35, and the bet amount is added to the amount of the win before the payment.

When all bets are made, the player presses the "Play" button and, via MetaMask, sends a bet to the Ethereum blockchain to the roulette contract address. The contract determines the random number, calculates the results of the bets and, if necessary, sends the winnings to the player.

In order to understand honestly whether the game is working (that is, if the casino does not manipulate when determining the random number for mercenary purposes), the work of the smart contract should be analyzed.

Its address is listed on the game website. In addition, before confirming the payment, you can check where the bet will be sent. The contract at the address 0xDfC328c19C8De45ac0117f836646378c10e0CdA3 will be analyzed as an example. Etherscan shows its code, and for convenient viewing, you can use Solidity Browser. The work of the contract begins with the placeBet() function:


Code:
function placeBet(uint256 bets, bytes32 values1,bytes32 values2) public payable
{
   if (ContractState == false)
   {
     ErrorLog(msg.sender, "ContractDisabled");
     if (msg.sender.send(msg.value) == false) throw;
     return;
   }
   var gamblesLength = gambles.length;

   if (gamblesLength > 0)
   {
      uint8 gamblesCountInCurrentBlock = 0;
      for(var i = gamblesLength - 1;i > 0; i--)
      {
        if (gambles[i].blockNumber == block.number)
        {
           if (gambles[i].player == msg.sender)
           {
               ErrorLog(msg.sender, "Play twice the same block");
               if (msg.sender.send(msg.value) == false) throw;
               return;
           }

           gamblesCountInCurrentBlock++;
           if (gamblesCountInCurrentBlock >= maxGamblesPerBlock)
           {
              ErrorLog(msg.sender, "maxGamblesPerBlock");
              if (msg.sender.send(msg.value) == false) throw;
              return;
           }
        }
        else
        {
           break;
        }
      }
   }
   
   var _currentMaxBet = currentMaxBet;

   if (msg.value < _currentMaxBet/256 || bets == 0)
   {
      ErrorLog(msg.sender, "Wrong bet value");
      if (msg.sender.send(msg.value) == false) throw;
      return;
   }

   if (msg.value > _currentMaxBet)
   {
      ErrorLog(msg.sender, "Limit for table");
      if (msg.sender.send(msg.value) == false) throw;
      return;
   }

   GameInfo memory g = GameInfo(msg.sender, block.number, 37, bets, values1,values2);

   if (totalBetValue(g) != msg.value)
   {
      ErrorLog(msg.sender, "Wrong bet value");
      if (msg.sender.send(msg.value) == false) throw;
      return;
   }       

   address affiliate = 0;
   uint16 coef_affiliate = 0;
   uint16 coef_player;
   if (address(smartAffiliateContract) > 0)
   {       
     (affiliate, coef_affiliate, coef_player) = smartAffiliateContract.getAffiliateInfo(msg.sender);   
   }
   else
   {
     coef_player = CoefPlayerEmission;
   }

   uint256 playerTokens;
   uint8 errorCodeEmission;
   
   (playerTokens, errorCodeEmission) = smartToken.emission(msg.sender, affiliate, msg.value, coef_player, coef_affiliate);
   if (errorCodeEmission != 0)
   {
      if (errorCodeEmission == 1)
        ErrorLog(msg.sender, "token operations stopped");
      else if (errorCodeEmission == 2)
        ErrorLog(msg.sender, "contract is not in a games list");
      else if (errorCodeEmission == 3)
        ErrorLog(msg.sender, "incorect player address");
      else if (errorCodeEmission == 4)
        ErrorLog(msg.sender, "incorect value bet");
      else if (errorCodeEmission == 5)
        ErrorLog(msg.sender, "incorect Coefficient emissions");
     
      if (msg.sender.send(msg.value) == false) throw;
      return;
   }

   gambles.push(g);

   PlayerBet(gamblesLength, playerTokens);
}



For Solidity newbies: the public and payable modifiers mean that the function is part of the API contract and when you call it, you can send ETH. In this case, information about the sender and the ETH amount will be available via the variable msg. The call parameters are the bit mask of bet types and two 32-byte arrays with the number of bets per type. You can guess this by looking at the definition of the GameInfo type and the functions getBetValueByGamble(), getBetValue ().


Code:
struct GameInfo
{
    address player;
    uint256 blockNumber;
    uint8 wheelResult;
    uint256 bets;
    bytes32 values;
    bytes32 values2;
}



// n - number player bet
// nBit - betIndex
function getBetValueByGamble(GameInfo memory gamble, uint8 n, uint8 nBit) private constant returns (uint256)
{
  if (n <= 32) return getBetValue(gamble.values , n, nBit);
  if (n <= 64) return getBetValue(gamble.values2, n - 32, nBit);
  // there are 64 maximum unique bets (positions) in one game
  throw;
}


// n form 1 <= to <= 32
function getBetValue(bytes32 values, uint8 n, uint8 nBit) private constant returns (uint256)
{
    // bet in credits (1..256)
    uint256 bet = uint256(values[32 - n]) + 1;

    if (bet < uint256(minCreditsOnBet[nBit]+1)) throw;   //default: bet < 0+1
    if (bet > uint256(256-maxCreditsOnBet[nBit])) throw; //default: bet > 256-0     

    return currentMaxBet * bet / 256;       
}


It is worth noting that getBetValue() returns the amount of the bet in wei.

The first thing placeBet() checks is that the contract is not turned off and then bet checks begin.
The gambles array is the repository of all the bets placed in this contract. placeBet() finds all the bets in its block and checks whether the current player has sent another bet in this block and whether the allowed amount of betting in the block is exceeded. Then, restrictions on the minimum and maximum amount of the bet are checked.

In the event of any error, the execution of the contract is terminated by the throw command, which rolls back the transaction, returning ETH to the player.

Further, the parameters passed to the function are stored in the GameInfo structure. It is important for us that the wheelResult field is initialized with the number 37.

After another check that the amount of bets coincides with the amount of ETH sent, the RLT tokens are distributed, the referral program is processed, the bet information is stored in gambles and a PlayerBet event is generated with the number and amount of the bet, which is seen in the game's web part.

RLT tokens
_At each bet, the player is given a certain number of RLT, ERC-20 tokens, which determine the right of the owner of tokens to receive the loyalty rewards from the profits received by the game creators. More information about this is given in White Paper.
The further life of the bet begins with calling the function ProcessGames(), which, after the appearance of a new bet, is being executed, at the present time, from the address 0xa92d36dc1ca4f505f1886503a0626c4aa8106497. Such calls are well visible when viewing the list of transactions of the game contract: they have Value=0.

ProcessGames code
Code:
function ProcessGames(uint256[] gameIndexes, bool simulate) 
{
  if (!simulate)
  {
     if (lastBlockGamesProcessed == block.number)  return;
     lastBlockGamesProcessed = block.number;
  }

  uint8 delay = BlockDelay;
  uint256 length = gameIndexes.length;
  bool success = false;
  for(uint256 i = 0;i < length;i++)
  {     
     if (ProcessGame(gameIndexes[i], delay) == GameStatus.Success) success = true;         
  }     
  if (simulate && !success) throw;
}

In the call parameters, an array with the bet numbers requiring calculation is transmitted, and for each ProcessGame is called.

Code:
function ProcessGame(uint256 index, uint256 delay) private returns (GameStatus)
{           
  GameInfo memory g = gambles[index];
  if (block.number - g.blockNumber >= 256) return GameStatus.Stop;

  if (g.wheelResult == 37 && block.number > g.blockNumber + delay)
  {           
     gambles[index].wheelResult = getRandomNumber(g.player, g.blockNumber);
             
     uint256 playerWinnings = getGameResult(gambles[index]);
     if (playerWinnings > 0)
     {
        if (g.player.send(playerWinnings) == false) throw;
     }

     EndGame(g.player, gambles[index].wheelResult, index);
     return GameStatus.Success;
  }

  return GameStatus.Skipped;
}


The call parameters are the bet number and the number of blocks that must pass between the bet and its processing. When called from ProcessGames() or ProcessGameExt(), this parameter is currently 1, this value can be learned from the result of calling getSettings().

In the event that the number of the block in which processing takes place is more than 255 blocks apart from the betting block, it can not be processed: the block hash is available only for the last 256 blocks, and it is needed to determine the number dropped.

Next, the code checks whether the result of the game has already been calculated (remember, wheelResult was initialized with the number 37, which can't be the game result?) and whether the required number of blocks has already passed.

If the conditions are met, the call to getRandomNumber() is done to determine the random number, the win is calculated by calling getGameResult(). If it is not zero, ETH is sent to the player: g.player.send(playerWinnings). Then an EndGame event is created, which can be read from the web part of the game.

Let's see the most interesting part: how to determine the random number: the function getRandomNumber().


Code:
function getRandomNumber(address player, uint256 playerblock) private returns(uint8 wheelResult)
{
    // block.blockhash - hash of the given block - only works for 256 most recent blocks excluding current
    bytes32 blockHash = block.blockhash(playerblock+BlockDelay);
   
    if (blockHash==0)
    {
      ErrorLog(msg.sender, "Cannot generate random number");
      wheelResult = 200;
    }
    else
    {
      bytes32 shaPlayer = sha3(player, blockHash);

      wheelResult = uint8(uint256(shaPlayer)%37);
    }   
}


Its arguments are the player's address and the block number in which the bet was placed. The first thing the function gets is a block hash, which is separated from the bet block for BlockDelay blocks into the future.

This is an important point because if a player can somehow learn the hash of this block in advance, he can form a bet that is guaranteed to win. If you remember that there are Uncle blocks in Ethereum, there may be a problem and further analysis is required.

Next, SHA-3 is calculated from the gluing of the player's address and the received block hash. The dropped number is calculated by taking the remainder of dividing the result of SHA-3 by 37.

From my point of view, the algorithm is quite honest and the casino has no precedence over the player.

Why does the casino bring profit to its owners?

There are 37 cells on the field. For example, a player wants to make 100 000 bets on one particular field. Probably, about 2703 times the player will win, and all the other times he will lose. In this case, from the casino winnings, the player will receive 2703 * 36 = 97,308 RLT tokens. And 2692 RLT tokens, spent on bets, will go to the casino. Similar calculations can be made for all other types of bets.

It is also interesting to see, how the win is calculated. The getGameResult() function does this:

Code:
function getGameResult(GameInfo memory game) private constant returns (uint256 totalWin) 
{
    totalWin = 0;
    uint8 nPlayerBetNo = 0;
    // we sent count bets at last byte
    uint8 betsCount = uint8(bytes32(game.bets)[0]);
    for(uint8 i=0; i<maxTypeBets; i++)
    {                     
        if (isBitSet(game.bets, i))
        {             
          var winMul = winMatrix.getCoeff(getIndex(i, game.wheelResult)); // get win coef
          if (winMul > 0) winMul++; // + return player bet
          totalWin += winMul * getBetValueByGamble(game, nPlayerBetNo+1,i);
          nPlayerBetNo++;

          if (betsCount == 1) break;
          betsCount--;
        }
    }       
}


Parameter here is the structure of GameInfo with data about the calculated bet. And its wheelResult field is already filled with a random number.
Here is the cycle for all types of bets, in which the bit mask game.bets is checked and if the bit of the type being checked is installed, winMatrix.getCoeff() is requested. winMatrix is the contract with the address 0x073D6621E9150bFf9d1D450caAd3c790b6F071F2, loaded in the SmartRoulettee() constructor.
A parameter of this function is a combination of the bet type and the random number:



Code:
// unique combination of bet and wheelResult, used for access to WinMatrix
function getIndex(uint16 bet, uint16 wheelResult) private constant returns (uint16)
{
  return (bet+1)*256 + (wheelResult+1);
}



Have you played the Blockchain roulette by SmartPlay.tech? Don’t forget to share your opinion with other players, join the Telegram chat with the early project investors and ask you questions to the official representatives.

Aaaand I did not doubt that this roulette is fair, nice job guys. Hope the project will succeed, since I look forward to a new game to play  Grin How long will it take to implement all the changes you've talked about?

Exact launch dates will be known in the nearest time. At the moment, the mechanics of the new game are completely ready, the game design is being drawn.
The unique design is now integrated into the updated version of the site.
33  Local / Альтернативные криптовалюты / Re: [SmartBox][RLT][BOUNTY] 🎰 Первые в мире блокчейн автоматы SmartPlay.tech 🎰 on: March 12, 2018, 11:27:22 AM
Я здесь когда то в подписной участвовал (давно) тогда и следил за проектом .Но потом всё как то стихло , правда приходят новости на почту временами от них .А что за аирдроп здесь планируется ? По поводу самой рулетки , я играл -мне совершенно не понравилось .Но я и не любитель подобной игры .Токены тоже в цене упали . По крайней мере раньше были дороже .Сейчас видимо спроса нет на проект .

Вы считаете, что оборот 10-15 битков в день на бирже Livecoin начиная с 19 января- это упал спрос? https://coinmarketcap.com/currencies/roulettetoken/

И цена с этого времени стабильно держится в районе 9-11 центов...
ну так это говорит о том что как раз 9 центов цена монете и не больше, так как если бы не было объемов, то может цена бы была еще не показатель, а так цена соответствует соотношению спроса с предложением...
любому бизнесу нужно время что-бы встать на ноги, поэтому я бы не стал раньше времени хоронить проект. а если что-то не устраивает, продавайте токены и не трепите себе нервы Wink лично у меня на кошельке лежат чуть больше 1000, жрать не просят и как-то не особо тянутся к ним руки что-бы продать.
Конечно, время обязательно надо, чтобы встать на ноги, особенно сейчас, когда все находится внизу, а продать всегда успеется, это дело не хитрое.
какие у нас в ближайшее время должны быть новости? обещали обновление сайта и запуск новой игры. разработчики, когда примерно это произойдет?

Благодарим за ваш интерес и поддержку проекта.
Точные сроки будут известны уже в ближайшее время. На текущий момент полностью готова механика новой игры, ведется отрисовка дизайна.
Уникальный дизайн сейчас интегрируется в новый обновленный сайт.
34  Local / Альтернативные криптовалюты / Re: [SmartBox][RLT][BOUNTY] 🎰 Первые в мире блокчейн автоматы SmartPlay.tech 🎰 on: March 12, 2018, 11:15:04 AM
Проверяем честность игры в рулетку на смарт-контракте Ethereum. Аудит от независимого разработчика

Представляем вашему вниманию аудит смарт-контракта рулетки от независимого эксперта Павла Рубина. Читайте, изучайте и делитесь мнением о рулетке!

На сегодняшний день уже не осталось людей, которые бы не слышали о криптовалютах и, в частности, о Bitcoin. В 2014-м году, на волне интереса к биткоину, появилась новая криптовалюта — Ethereum. Сегодня, в 2018-м, она является второй по капитализации после биткоина. Одним из важнейших её отличий от биткоина является использование тьюринг-полной виртуальной машины — EVM. Подробнее про эфир можно прочитать в его Yellow Paper.

Сегодня мы будет исследовать игру, работающую через MetaMask, кошелек плагин для браузера Google Chrome.

Игра является реализацией европейской рулетки: на поле 37 клеток, пронумерованных от 0 до 36. Можно делать ставку на конкретный номер либо на набор номеров: чётные/нечётные, красное/черное, 1-12, 1-18 и т.д. В каждом раунде можно сделать несколько ставок путём добавления жетона (стоимостью 0.01 ETH ≈ $0.5) на соответствующее поле игрового стола. Каждому полю соответствует коэффициент выигрыша. Например, ставке «на красное» соответствует коэффициент 2 — то есть заплатив 0.01 ETH вы, в случае выигрыша, получите 0.02 ETH. А если поставите на зеро, то коэффициент будет 36: заплатив тот же 0.01 ETH за ставку вы получите 0.36 в случае выигрыша.

Замечание
В коде контракта коэффициент для этой ставки тоже указан как 35, а к сумме выигрыша, перед выплатой, прибавляется сумма ставки.


Когда все ставки сделаны, игрок нажимает кнопку «Играть» и, через MetaMask, отправляет ставку в Ethereum-блокчейн, на адрес смарт-контракта игры. Контракт определяет выпавшее число, рассчитывает результаты ставок и, в случае необходимости, отсылает выигрыш игроку.

Для того, чтобы понять честно ли работает игра (то есть, не манипулирует ли казино определением выпавшего числа в свою пользу) проанализируем работу смарт-контракта. Его адрес указан на сайте игры. Кроме того, перед подтверждением оплаты можно проверить на какой адрес будет отправлено пари. В качестве примера будет проанализирован контракт по адресу 0xDfC328c19C8De45ac0117f836646378c10e0CdA3. Etherscan показывает его код, а для удобного просмотра можно использовать Solidity Browser.

Работа контракта начинается с вызова функции placeBet():


Code:
function placeBet(uint256 bets, bytes32 values1,bytes32 values2) public payable
{
   if (ContractState == false)
   {
     ErrorLog(msg.sender, "ContractDisabled");
     if (msg.sender.send(msg.value) == false) throw;
     return;
   }
   var gamblesLength = gambles.length;

   if (gamblesLength > 0)
   {
      uint8 gamblesCountInCurrentBlock = 0;
      for(var i = gamblesLength - 1;i > 0; i--)
      {
        if (gambles[i].blockNumber == block.number)
        {
           if (gambles[i].player == msg.sender)
           {
               ErrorLog(msg.sender, "Play twice the same block");
               if (msg.sender.send(msg.value) == false) throw;
               return;
           }

           gamblesCountInCurrentBlock++;
           if (gamblesCountInCurrentBlock >= maxGamblesPerBlock)
           {
              ErrorLog(msg.sender, "maxGamblesPerBlock");
              if (msg.sender.send(msg.value) == false) throw;
              return;
           }
        }
        else
        {
           break;
        }
      }
   }
  
   var _currentMaxBet = currentMaxBet;

   if (msg.value < _currentMaxBet/256 || bets == 0)
   {
      ErrorLog(msg.sender, "Wrong bet value");
      if (msg.sender.send(msg.value) == false) throw;
      return;
   }

   if (msg.value > _currentMaxBet)
   {
      ErrorLog(msg.sender, "Limit for table");
      if (msg.sender.send(msg.value) == false) throw;
      return;
   }

   GameInfo memory g = GameInfo(msg.sender, block.number, 37, bets, values1,values2);

   if (totalBetValue(g) != msg.value)
   {
      ErrorLog(msg.sender, "Wrong bet value");
      if (msg.sender.send(msg.value) == false) throw;
      return;
   }      

   address affiliate = 0;
   uint16 coef_affiliate = 0;
   uint16 coef_player;
   if (address(smartAffiliateContract) > 0)
   {        
     (affiliate, coef_affiliate, coef_player) = smartAffiliateContract.getAffiliateInfo(msg.sender);  
   }
   else
   {
     coef_player = CoefPlayerEmission;
   }

   uint256 playerTokens;
   uint8 errorCodeEmission;
  
   (playerTokens, errorCodeEmission) = smartToken.emission(msg.sender, affiliate, msg.value, coef_player, coef_affiliate);
   if (errorCodeEmission != 0)
   {
      if (errorCodeEmission == 1)
        ErrorLog(msg.sender, "token operations stopped");
      else if (errorCodeEmission == 2)
        ErrorLog(msg.sender, "contract is not in a games list");
      else if (errorCodeEmission == 3)
        ErrorLog(msg.sender, "incorect player address");
      else if (errorCodeEmission == 4)
        ErrorLog(msg.sender, "incorect value bet");
      else if (errorCodeEmission == 5)
        ErrorLog(msg.sender, "incorect Coefficient emissions");
      
      if (msg.sender.send(msg.value) == false) throw;
      return;
   }

   gambles.push(g);

   PlayerBet(gamblesLength, playerTokens);
}



Для новичков в Solidity: модификаторы public и payable означают, что функция является частью API контракта и что при её вызове можно отправить эфир. При этом информация об отправителе и количестве отправленного эфира будет доступна через переменную msg.

Параметрами вызова является битовая маска типов ставок и два 32-байтных массива с количеством жетонов на каждый из типов. Догадаться об этом можно посмотрев на определение типа GameInfo и функций getBetValueByGamble(), getBetValue().


Code:
struct GameInfo
{
    address player;
    uint256 blockNumber;
    uint8 wheelResult;
    uint256 bets;
    bytes32 values;
    bytes32 values2;
}



// n - number player bet
// nBit - betIndex
function getBetValueByGamble(GameInfo memory gamble, uint8 n, uint8 nBit) private constant returns (uint256)
{
  if (n <= 32) return getBetValue(gamble.values , n, nBit);
  if (n <= 64) return getBetValue(gamble.values2, n - 32, nBit);
  // there are 64 maximum unique bets (positions) in one game
  throw;
}


// n form 1 <= to <= 32
function getBetValue(bytes32 values, uint8 n, uint8 nBit) private constant returns (uint256)
{
    // bet in credits (1..256)
    uint256 bet = uint256(values[32 - n]) + 1;

    if (bet < uint256(minCreditsOnBet[nBit]+1)) throw;   //default: bet < 0+1
    if (bet > uint256(256-maxCreditsOnBet[nBit])) throw; //default: bet > 256-0      

    return currentMaxBet * bet / 256;        
}


Стоит отметить, что getBetValue() возвращает сумму ставки уже не в жетонах, а в wei.

Первым делом placeBet() проверяет, что контракт не выключен и затем начинаются проверки пари.
Массив gambles является хранилищем всех сыгранных в данном контракте пари. placeBet() находит все пари в своём блоке и проверяет не присылал ли данный игрок другое пари в этом блоке и не превышено ли разрешенное количество пари на блок. Затем проверяются ограничения на минимальную и максимальную сумму ставки.

В случае любой ошибки выполнение контракта прерывается командой throw, которая откатывает транзакцию, возвращая эфир игроку.

Далее переданные в функцию параметры сохраняются в структуре GameInfo.Здесь нам важно, что поле wheelResult инициализируется числом 37.

После ещё одной проверки, что сумма ставок совпадает с присланным количеством эфира происходит распределение токенов RLT, обрабатывается реферальная программа, информация о пари сохраняется в gambles и создаётся событие PlayerBet с номером и суммой пари, которое затем видно в веб-части игры.

RLT токены
При каждой ставке игроку выдаётся определённое количество RLT, Ethereum-токенов, которыми определяется право владельца токенов на получение бонусов лояльности с прибыли, полученной авторами игры. Подробнее об этом — читайте White Paper. White Paper.

Дальнейшая жизнь ставки начинается с вызова функции ProcessGames(), который, после появления новой ставки, выполняется, в настоящее время, с адреса 0xa92d36dc1ca4f505f1886503a0626c4aa8106497. Такие вызовы хороши видны при просмотре списка транзакций контракта игры: у них Value = 0.


Code:
function ProcessGames(uint256[] gameIndexes, bool simulate) 
{
  if (!simulate)
  {
     if (lastBlockGamesProcessed == block.number)  return;
     lastBlockGamesProcessed = block.number;
  }

  uint8 delay = BlockDelay;
  uint256 length = gameIndexes.length;
  bool success = false;
  for(uint256 i = 0;i < length;i++)
  {      
     if (ProcessGame(gameIndexes[i], delay) == GameStatus.Success) success = true;        
  }      
  if (simulate && !success) throw;
}

В параметрах вызова передаётся массив с номерами пари, которые требуют расчёта, и для каждого вызывается ProcessGame.

Code:
function ProcessGame(uint256 index, uint256 delay) private returns (GameStatus)
{            
  GameInfo memory g = gambles[index];
  if (block.number - g.blockNumber >= 256) return GameStatus.Stop;

  if (g.wheelResult == 37 && block.number > g.blockNumber + delay)
  {            
     gambles[index].wheelResult = getRandomNumber(g.player, g.blockNumber);
            
     uint256 playerWinnings = getGameResult(gambles[index]);
     if (playerWinnings > 0)
     {
        if (g.player.send(playerWinnings) == false) throw;
     }

     EndGame(g.player, gambles[index].wheelResult, index);
     return GameStatus.Success;
  }

  return GameStatus.Skipped;
}


Параметрами вызова являются номер ставки и количество блоков которое должно пройти между ставкой и её обработкой. При вызове из ProcessGames() или ProcessGameExt() этот параметр в настоящее время равен 1, это значение можно узнать из результата вызова getSettings().

В случае, если номер блока, в котором происходит обработка, больше чем на 255 блоков отстоит от блока пари, оно не может быть обработано: хэш блока доступен только для последних 256 блоков, а он нужен для определения выпавшего числа.

Далее выполняется проверка не был ли уже рассчитан результат игры (помните, wheelResult инициализровался числом 37, которое выпасть не может?) и прошло ли уже необходимое количество блоков.

Если условия выполнены, производится вызов getRandomNumber() для определения выпавшего числа, вызовом getGameResult() рассчитывается выигрыш. Если он не нулевой, эфир посылается игроку: g.player.send(playerWinnings). Затем создаётся событие EndGame, которое может быть прочитано из веб-части игры.

Посмотрим самое интересное, то как определяется выпавшее число: функцию getRandomNumber().

Code:
function getRandomNumber(address player, uint256 playerblock) private returns(uint8 wheelResult)
{
    // block.blockhash - hash of the given block - only works for 256 most recent blocks excluding current
    bytes32 blockHash = block.blockhash(playerblock+BlockDelay);
    
    if (blockHash==0)
    {
      ErrorLog(msg.sender, "Cannot generate random number");
      wheelResult = 200;
    }
    else
    {
      bytes32 shaPlayer = sha3(player, blockHash);

      wheelResult = uint8(uint256(shaPlayer)%37);
    }    
}


Её аргументы — адрес игрока и номер блока, в котором была сделана ставка. Первым делом функция получает хэш блока, отстоящего от блока ставки на BlockDelay блоков в будущее.

Это важный момент, поскольку если игрок сможет каким-то образом узнать хэш этого блока заранее, он может сформировать ставку, которая гарантированно выиграет. Если вспомнить, что в Ethereum существуют Uncle-блоки, тут может быть проблема и требуется дальнейший анализ.

Далее рассчитывается SHA-3 от склейки адреса игрока и полученного хэша блока. Выпавшее число вычисляется путём взятия остатка от деления результата SHA-3 на 37.

С моей точки зрения, алгоритм вполне честный и казино никакого преимущества перед игроком не имеет.

Интересно посмотреть, также, как рассчитывается выигрыш. Как мы видели, это делает функция getGameResult().

Code:
function getGameResult(GameInfo memory game) private constant returns (uint256 totalWin) 
{
    totalWin = 0;
    uint8 nPlayerBetNo = 0;
    // we sent count bets at last byte
    uint8 betsCount = uint8(bytes32(game.bets)[0]);
    for(uint8 i=0; i<maxTypeBets; i++)
    {                      
        if (isBitSet(game.bets, i))
        {              
          var winMul = winMatrix.getCoeff(getIndex(i, game.wheelResult)); // get win coef
          if (winMul > 0) winMul++; // + return player bet
          totalWin += winMul * getBetValueByGamble(game, nPlayerBetNo+1,i);
          nPlayerBetNo++;

          if (betsCount == 1) break;
          betsCount--;
        }
    }        
}

Параметром сюда передаётся структура GameInfo с данными о рассчитываемом пари. А её поле wheelResult уже заполнено выпавшим числом.

Видим цикл по всем типам ставок, в котором проверяется битовая маска game.bets и если бит проверяемого типа установлен, то запрашивается winMatrix.getCoeff(). winMatrix — это контракт по адресу 0x073D6621E9150bFf9d1D450caAd3c790b6F071F2, загруженный в конструкторе SmartRoulettee().

В качестве параметра этой функции передаётся комбинация типа ставки и выпавшего числа:

Code:
// unique combination of bet and wheelResult, used for access to WinMatrix
function getIndex(uint16 bet, uint16 wheelResult) private constant returns (uint16)
{
  return (bet+1)*256 + (wheelResult+1);
}



А Вы уже играли в блокчейн рулетку от SmartPlay.tech? Играйте по-честному и делитесь своим мнением о игре с другими участниками проекта, вступайте в Telegram чат для ранних инвесторов и задавайте свои вопросы официальным представителям.
35  Alternate cryptocurrencies / Announcements (Altcoins) / Re: [RLT][SMARTPLAY.TECH] 🎰 Vote for the design and get 100 RLT 🎰 on: March 12, 2018, 10:58:00 AM
How fair is the roulette on the Ethereum smart contract?  An independent audit of the game contract

We present to your attention a roulette audit from an independent developer Paul Rubin. Read, study and share your opinion about roulette!

Today it is very unlikely to meet a person who hasn't heard about cryptocurrencies and, in particular, about Bitcoin. In 2014, on a wave of interest in bitcoin, a new cryptocurrency - Ethereum, has been created. Today, in 2018, it has the largest capitalization after bitcoin. One of its most important differences from bitcoin is the use of a Turing virtual machine - EVM. More information about the Ethererum can be found in its Yellow Paper.

Today we will explore a game that works with Metamask wallet, a plugin for Google Chrome.

The game is the realization of the European roulette: there is the field with 37 cells numbered from 0 to 36. A player can bet on a specific number, or on a set of numbers: even/odd, red/black, 1-12, 1-18, etc. In each round, the player can make multiple bets (the minimum bet size is 0.01 ETH ≈ $ 7.26) on the corresponding field of the game table. Each field corresponds to a winning ratio. For example, the rate "to red" corresponds to a coefficient of 2 - placing a bet in amount of 0.01 ETH, in case of winning, the player will receive 0.02 ETH. And if the player bets on zero, the coefficient will be 36: paying the same 0.01 ETH for the bet the player will get 0.36.

Note
In the game contract, the coefficient for this bet is also listed as 35, and the bet amount is added to the amount of the win before the payment.

When all bets are made, the player presses the "Play" button and, via MetaMask, sends a bet to the Ethereum blockchain to the roulette contract address. The contract determines the random number, calculates the results of the bets and, if necessary, sends the winnings to the player.

In order to understand honestly whether the game is working (that is, if the casino does not manipulate when determining the random number for mercenary purposes), the work of the smart contract should be analyzed.

Its address is listed on the game website. In addition, before confirming the payment, you can check where the bet will be sent. The contract at the address 0xDfC328c19C8De45ac0117f836646378c10e0CdA3 will be analyzed as an example. Etherscan shows its code, and for convenient viewing, you can use Solidity Browser. The work of the contract begins with the placeBet() function:


Code:
function placeBet(uint256 bets, bytes32 values1,bytes32 values2) public payable
{
   if (ContractState == false)
   {
     ErrorLog(msg.sender, "ContractDisabled");
     if (msg.sender.send(msg.value) == false) throw;
     return;
   }
   var gamblesLength = gambles.length;

   if (gamblesLength > 0)
   {
      uint8 gamblesCountInCurrentBlock = 0;
      for(var i = gamblesLength - 1;i > 0; i--)
      {
        if (gambles[i].blockNumber == block.number)
        {
           if (gambles[i].player == msg.sender)
           {
               ErrorLog(msg.sender, "Play twice the same block");
               if (msg.sender.send(msg.value) == false) throw;
               return;
           }

           gamblesCountInCurrentBlock++;
           if (gamblesCountInCurrentBlock >= maxGamblesPerBlock)
           {
              ErrorLog(msg.sender, "maxGamblesPerBlock");
              if (msg.sender.send(msg.value) == false) throw;
              return;
           }
        }
        else
        {
           break;
        }
      }
   }
  
   var _currentMaxBet = currentMaxBet;

   if (msg.value < _currentMaxBet/256 || bets == 0)
   {
      ErrorLog(msg.sender, "Wrong bet value");
      if (msg.sender.send(msg.value) == false) throw;
      return;
   }

   if (msg.value > _currentMaxBet)
   {
      ErrorLog(msg.sender, "Limit for table");
      if (msg.sender.send(msg.value) == false) throw;
      return;
   }

   GameInfo memory g = GameInfo(msg.sender, block.number, 37, bets, values1,values2);

   if (totalBetValue(g) != msg.value)
   {
      ErrorLog(msg.sender, "Wrong bet value");
      if (msg.sender.send(msg.value) == false) throw;
      return;
   }      

   address affiliate = 0;
   uint16 coef_affiliate = 0;
   uint16 coef_player;
   if (address(smartAffiliateContract) > 0)
   {        
     (affiliate, coef_affiliate, coef_player) = smartAffiliateContract.getAffiliateInfo(msg.sender);  
   }
   else
   {
     coef_player = CoefPlayerEmission;
   }

   uint256 playerTokens;
   uint8 errorCodeEmission;
  
   (playerTokens, errorCodeEmission) = smartToken.emission(msg.sender, affiliate, msg.value, coef_player, coef_affiliate);
   if (errorCodeEmission != 0)
   {
      if (errorCodeEmission == 1)
        ErrorLog(msg.sender, "token operations stopped");
      else if (errorCodeEmission == 2)
        ErrorLog(msg.sender, "contract is not in a games list");
      else if (errorCodeEmission == 3)
        ErrorLog(msg.sender, "incorect player address");
      else if (errorCodeEmission == 4)
        ErrorLog(msg.sender, "incorect value bet");
      else if (errorCodeEmission == 5)
        ErrorLog(msg.sender, "incorect Coefficient emissions");
      
      if (msg.sender.send(msg.value) == false) throw;
      return;
   }

   gambles.push(g);

   PlayerBet(gamblesLength, playerTokens);
}



For Solidity newbies: the public and payable modifiers mean that the function is part of the API contract and when you call it, you can send ETH. In this case, information about the sender and the ETH amount will be available via the variable msg. The call parameters are the bit mask of bet types and two 32-byte arrays with the number of bets per type. You can guess this by looking at the definition of the GameInfo type and the functions getBetValueByGamble(), getBetValue ().


Code:
struct GameInfo
{
    address player;
    uint256 blockNumber;
    uint8 wheelResult;
    uint256 bets;
    bytes32 values;
    bytes32 values2;
}



// n - number player bet
// nBit - betIndex
function getBetValueByGamble(GameInfo memory gamble, uint8 n, uint8 nBit) private constant returns (uint256)
{
  if (n <= 32) return getBetValue(gamble.values , n, nBit);
  if (n <= 64) return getBetValue(gamble.values2, n - 32, nBit);
  // there are 64 maximum unique bets (positions) in one game
  throw;
}


// n form 1 <= to <= 32
function getBetValue(bytes32 values, uint8 n, uint8 nBit) private constant returns (uint256)
{
    // bet in credits (1..256)
    uint256 bet = uint256(values[32 - n]) + 1;

    if (bet < uint256(minCreditsOnBet[nBit]+1)) throw;   //default: bet < 0+1
    if (bet > uint256(256-maxCreditsOnBet[nBit])) throw; //default: bet > 256-0      

    return currentMaxBet * bet / 256;        
}


It is worth noting that getBetValue() returns the amount of the bet in wei.

The first thing placeBet() checks is that the contract is not turned off and then bet checks begin.
The gambles array is the repository of all the bets placed in this contract. placeBet() finds all the bets in its block and checks whether the current player has sent another bet in this block and whether the allowed amount of betting in the block is exceeded. Then, restrictions on the minimum and maximum amount of the bet are checked.

In the event of any error, the execution of the contract is terminated by the throw command, which rolls back the transaction, returning ETH to the player.

Further, the parameters passed to the function are stored in the GameInfo structure. It is important for us that the wheelResult field is initialized with the number 37.

After another check that the amount of bets coincides with the amount of ETH sent, the RLT tokens are distributed, the referral program is processed, the bet information is stored in gambles and a PlayerBet event is generated with the number and amount of the bet, which is seen in the game's web part.

RLT tokens
_At each bet, the player is given a certain number of RLT, ERC-20 tokens, which determine the right of the owner of tokens to receive the loyalty rewards from the profits received by the game creators. More information about this is given in White Paper.
The further life of the bet begins with calling the function ProcessGames(), which, after the appearance of a new bet, is being executed, at the present time, from the address 0xa92d36dc1ca4f505f1886503a0626c4aa8106497. Such calls are well visible when viewing the list of transactions of the game contract: they have Value=0.

ProcessGames code
Code:
function ProcessGames(uint256[] gameIndexes, bool simulate) 
{
  if (!simulate)
  {
     if (lastBlockGamesProcessed == block.number)  return;
     lastBlockGamesProcessed = block.number;
  }

  uint8 delay = BlockDelay;
  uint256 length = gameIndexes.length;
  bool success = false;
  for(uint256 i = 0;i < length;i++)
  {      
     if (ProcessGame(gameIndexes[i], delay) == GameStatus.Success) success = true;        
  }      
  if (simulate && !success) throw;
}

In the call parameters, an array with the bet numbers requiring calculation is transmitted, and for each ProcessGame is called.

Code:
function ProcessGame(uint256 index, uint256 delay) private returns (GameStatus)
{            
  GameInfo memory g = gambles[index];
  if (block.number - g.blockNumber >= 256) return GameStatus.Stop;

  if (g.wheelResult == 37 && block.number > g.blockNumber + delay)
  {            
     gambles[index].wheelResult = getRandomNumber(g.player, g.blockNumber);
            
     uint256 playerWinnings = getGameResult(gambles[index]);
     if (playerWinnings > 0)
     {
        if (g.player.send(playerWinnings) == false) throw;
     }

     EndGame(g.player, gambles[index].wheelResult, index);
     return GameStatus.Success;
  }

  return GameStatus.Skipped;
}


The call parameters are the bet number and the number of blocks that must pass between the bet and its processing. When called from ProcessGames() or ProcessGameExt(), this parameter is currently 1, this value can be learned from the result of calling getSettings().

In the event that the number of the block in which processing takes place is more than 255 blocks apart from the betting block, it can not be processed: the block hash is available only for the last 256 blocks, and it is needed to determine the number dropped.

Next, the code checks whether the result of the game has already been calculated (remember, wheelResult was initialized with the number 37, which can't be the game result?) and whether the required number of blocks has already passed.

If the conditions are met, the call to getRandomNumber() is done to determine the random number, the win is calculated by calling getGameResult(). If it is not zero, ETH is sent to the player: g.player.send(playerWinnings). Then an EndGame event is created, which can be read from the web part of the game.

Let's see the most interesting part: how to determine the random number: the function getRandomNumber().


Code:
function getRandomNumber(address player, uint256 playerblock) private returns(uint8 wheelResult)
{
    // block.blockhash - hash of the given block - only works for 256 most recent blocks excluding current
    bytes32 blockHash = block.blockhash(playerblock+BlockDelay);
    
    if (blockHash==0)
    {
      ErrorLog(msg.sender, "Cannot generate random number");
      wheelResult = 200;
    }
    else
    {
      bytes32 shaPlayer = sha3(player, blockHash);

      wheelResult = uint8(uint256(shaPlayer)%37);
    }    
}


Its arguments are the player's address and the block number in which the bet was placed. The first thing the function gets is a block hash, which is separated from the bet block for BlockDelay blocks into the future.

This is an important point because if a player can somehow learn the hash of this block in advance, he can form a bet that is guaranteed to win. If you remember that there are Uncle blocks in Ethereum, there may be a problem and further analysis is required.

Next, SHA-3 is calculated from the gluing of the player's address and the received block hash. The dropped number is calculated by taking the remainder of dividing the result of SHA-3 by 37.

From my point of view, the algorithm is quite honest and the casino has no precedence over the player.

Why does the casino bring profit to its owners?

There are 37 cells on the field. For example, a player wants to make 100 000 bets on one particular field. Probably, about 2703 times the player will win, and all the other times he will lose. In this case, from the casino winnings, the player will receive 2703 * 36 = 97,308 RLT tokens. And 2692 RLT tokens, spent on bets, will go to the casino. Similar calculations can be made for all other types of bets.

It is also interesting to see, how the win is calculated. The getGameResult() function does this:

Code:
function getGameResult(GameInfo memory game) private constant returns (uint256 totalWin) 
{
    totalWin = 0;
    uint8 nPlayerBetNo = 0;
    // we sent count bets at last byte
    uint8 betsCount = uint8(bytes32(game.bets)[0]);
    for(uint8 i=0; i<maxTypeBets; i++)
    {                      
        if (isBitSet(game.bets, i))
        {              
          var winMul = winMatrix.getCoeff(getIndex(i, game.wheelResult)); // get win coef
          if (winMul > 0) winMul++; // + return player bet
          totalWin += winMul * getBetValueByGamble(game, nPlayerBetNo+1,i);
          nPlayerBetNo++;

          if (betsCount == 1) break;
          betsCount--;
        }
    }        
}


Parameter here is the structure of GameInfo with data about the calculated bet. And its wheelResult field is already filled with a random number.
Here is the cycle for all types of bets, in which the bit mask game.bets is checked and if the bit of the type being checked is installed, winMatrix.getCoeff() is requested. winMatrix is the contract with the address 0x073D6621E9150bFf9d1D450caAd3c790b6F071F2, loaded in the SmartRoulettee() constructor.
A parameter of this function is a combination of the bet type and the random number:



Code:
// unique combination of bet and wheelResult, used for access to WinMatrix
function getIndex(uint16 bet, uint16 wheelResult) private constant returns (uint16)
{
  return (bet+1)*256 + (wheelResult+1);
}



Have you played the Blockchain roulette by SmartPlay.tech? Don’t forget to share your opinion with other players, join the Telegram chat with the early project investors and ask you questions to the official representatives.
36  Alternate cryptocurrencies / Announcements (Altcoins) / Re: [RLT][SMARTPLAY.TECH] 🎰 Vote for the design and get 100 RLT 🎰 on: March 11, 2018, 06:17:58 PM
RLT was my very first investment. And it was a success. I am glad that the team is moving forward. Good luck, Smart Play !
Thank you for the words of support!

Join our Telegram group for the early investors and receive information about all the latest project news amont the first users!
37  Alternate cryptocurrencies / Announcements (Altcoins) / Re: [RLT][SMARTPLAY.TECH] 🎰 Vote for the design and get 100 RLT 🎰 on: March 11, 2018, 06:15:18 PM
It's hard to create a game that everyone loves to play. If you want to meet most of the requirements, you'd better ask the player's opinion to make it an excellent project content.

Thank you for your opinion  Smiley
Please, do not hesitate to contact us with your complaints and proposals, we are always open to your offers and comments on the project. You can leave it in this forum thread, in Telegram group or send it via email to info@smartplay.tech.
38  Alternate cryptocurrencies / Announcements (Altcoins) / Re: [RLT][SMARTPLAY.TECH] 🎰 Vote for the design and get 100 RLT 🎰 on: March 05, 2018, 03:57:26 PM
In one of the e-mails received from you, there was information about the new version of the site. When will it be available?
Thank you for your question.
Within a week we will demonstrate first drafts of the new site.
I will surely wait for that and will be the one of the firsts to try the new site and i am hoping that it's just another start of improving this project to stay and be more competitive alongside with the other project of the same concept.
Thank you for the words of support.

Subscribe to our Telegram group for the early investors, where the design of the new site was discussed today, and be along the first to receive the inside info from the devteam  Cheesy
39  Alternate cryptocurrencies / Announcements (Altcoins) / Re: [RLT][SMARTPLAY.TECH] 🎰 Vote for the design and get 100 RLT 🎰 on: March 05, 2018, 03:19:07 PM
In one of the e-mails received from you, there was information about the new version of the site. When will it be available?
Thank you for your question.
Within a week we will demonstrate first drafts of the new site.
40  Alternate cryptocurrencies / Announcements (Altcoins) / Re: [RLT][SMARTPLAY.TECH] 🎰 Vote for the design and get 100 RLT 🎰 on: March 05, 2018, 09:04:27 AM
Maybe airdrop no need? It can lead to a price drop, in my opinion. There are so many coins that airdrop has no effect on anything.
Let us tell you about our plans.
We understand that we've achieved stable turnover on a small exchange, and now for further growth, it is necessary to:
a) build a community
b) expand the product line - we will announce the next game already this month
c) access to larger stock exchanges

Airdrop is necessary to attract new investors, including the large ones.

Nice job, guys, hope your Airdrop will be a success.
Thank you for your support!
Join our Telegram chat for the early investors to discuss all the latest news with the official representatives  Wink
Pages: « 1 [2] 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 »
Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!