Pages:
Author

Topic: [SmartBox][RLT][BOUNTY] 🎰 Первые в мире блокчейн автоматы SmartPlay.tech 🎰 - page 7. (Read 38183 times)

full member
Activity: 364
Merit: 103
“The P2P Marketplace For Digital Content”
sr. member
Activity: 476
Merit: 253
Official representative
sr. member
Activity: 476
Merit: 253
Official representative
Проверяем честность игры в рулетку на смарт-контракте 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    {                      
        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 чат для ранних инвесторов и задавайте свои вопросы официальным представителям.
full member
Activity: 364
Merit: 103
“The P2P Marketplace For Digital Content”
full member
Activity: 364
Merit: 103
“The P2P Marketplace For Digital Content”
sr. member
Activity: 798
Merit: 253
Я здесь когда то в подписной участвовал (давно) тогда и следил за проектом .Но потом всё как то стихло , правда приходят новости на почту временами от них .А что за аирдроп здесь планируется ? По поводу самой рулетки , я играл -мне совершенно не понравилось .Но я и не любитель подобной игры .Токены тоже в цене упали . По крайней мере раньше были дороже .Сейчас видимо спроса нет на проект .
member
Activity: 280
Merit: 19
судя по балансу эфирной рулетки, там давно не было игр. срочно нужна сильная маркетинговая программа и расширение сообщества.
есть ставки минимальные, но их и правда маловато.
Ждем рекламы, проекту нужны новые участники, и сейчас это чувствуется как никогда. Можно ведь и самим народ приглашать.
Я периодически делюсь ссылкой на проект с друзьями и в своих аккаунтах.
думаю это мало кто оценит как со стороны разработчиков, так и со стороны инвесторов) а вообще если бы хотели сообщества и рекламы, то организовали бы баунти программу, и думаю и народу набралось и пиар был бы, и тогда бы посмотрели стоит ли это того?
Так разработчики сейчас над этим и работают, обещали ведь и эйрдроп, и запуск рекламы. Думаю стоит подождать, все равно ничего не теряем..
ну никто конечно ничего не теряет) но я помню их рекламную акцию на 300 что-ли эх токенов) или меньше, и те которые нужно было отыграть и выиграть) непонятно только зачем, если их выиграть было очень сложно даже с 98% по их заверению отдачи бабок
С этой акции началось мое близкое знакомство с проектом. И я, между прочим, тогда нормально выиграл  Cheesy

Разработчики, когда Airdrop? А то что-то как-то тихо. Снова новости готовите ?))
ну да я тоже помню данную акцию, а еще я помню как все хорошо начиналось и во что это все превратилось когда разработчики тупо забили болт на все и прикрывшись другими делами пропали на пол года... по факту бросив проект...
member
Activity: 266
Merit: 10
судя по балансу эфирной рулетки, там давно не было игр. срочно нужна сильная маркетинговая программа и расширение сообщества.
есть ставки минимальные, но их и правда маловато.
Ждем рекламы, проекту нужны новые участники, и сейчас это чувствуется как никогда. Можно ведь и самим народ приглашать.
Я периодически делюсь ссылкой на проект с друзьями и в своих аккаунтах.
думаю это мало кто оценит как со стороны разработчиков, так и со стороны инвесторов) а вообще если бы хотели сообщества и рекламы, то организовали бы баунти программу, и думаю и народу набралось и пиар был бы, и тогда бы посмотрели стоит ли это того?
Так разработчики сейчас над этим и работают, обещали ведь и эйрдроп, и запуск рекламы. Думаю стоит подождать, все равно ничего не теряем..
ну никто конечно ничего не теряет) но я помню их рекламную акцию на 300 что-ли эх токенов) или меньше, и те которые нужно было отыграть и выиграть) непонятно только зачем, если их выиграть было очень сложно даже с 98% по их заверению отдачи бабок
С этой акции началось мое близкое знакомство с проектом. И я, между прочим, тогда нормально выиграл  Cheesy

Разработчики, когда Airdrop? А то что-то как-то тихо. Снова новости готовите ?))
снова пропали далеко и на долго) заняты придумыванием очередных новостей, чтобы нельзя было придраться и проверить их) это же тоже нужно уметь и не так от балды писать) так что ждем)
newbie
Activity: 54
Merit: 0
судя по балансу эфирной рулетки, там давно не было игр. срочно нужна сильная маркетинговая программа и расширение сообщества.
есть ставки минимальные, но их и правда маловато.
Ждем рекламы, проекту нужны новые участники, и сейчас это чувствуется как никогда. Можно ведь и самим народ приглашать.
Я периодически делюсь ссылкой на проект с друзьями и в своих аккаунтах.
думаю это мало кто оценит как со стороны разработчиков, так и со стороны инвесторов) а вообще если бы хотели сообщества и рекламы, то организовали бы баунти программу, и думаю и народу набралось и пиар был бы, и тогда бы посмотрели стоит ли это того?
Так разработчики сейчас над этим и работают, обещали ведь и эйрдроп, и запуск рекламы. Думаю стоит подождать, все равно ничего не теряем..
ну никто конечно ничего не теряет) но я помню их рекламную акцию на 300 что-ли эх токенов) или меньше, и те которые нужно было отыграть и выиграть) непонятно только зачем, если их выиграть было очень сложно даже с 98% по их заверению отдачи бабок
С этой акции началось мое близкое знакомство с проектом. И я, между прочим, тогда нормально выиграл  Cheesy

Разработчики, когда Airdrop? А то что-то как-то тихо. Снова новости готовите ?))
newbie
Activity: 55
Merit: 0
судя по балансу эфирной рулетки, там давно не было игр. срочно нужна сильная маркетинговая программа и расширение сообщества.
есть ставки минимальные, но их и правда маловато.
Ждем рекламы, проекту нужны новые участники, и сейчас это чувствуется как никогда. Можно ведь и самим народ приглашать.
Я периодически делюсь ссылкой на проект с друзьями и в своих аккаунтах.
думаю это мало кто оценит как со стороны разработчиков, так и со стороны инвесторов) а вообще если бы хотели сообщества и рекламы, то организовали бы баунти программу, и думаю и народу набралось и пиар был бы, и тогда бы посмотрели стоит ли это того?
Так разработчики сейчас над этим и работают, обещали ведь и эйрдроп, и запуск рекламы. Думаю стоит подождать, все равно ничего не теряем..
ну никто конечно ничего не теряет) но я помню их рекламную акцию на 300 что-ли эх токенов) или меньше, и те которые нужно было отыграть и выиграть) непонятно только зачем, если их выиграть было очень сложно даже с 98% по их заверению отдачи бабок
newbie
Activity: 79
Merit: 0
судя по балансу эфирной рулетки, там давно не было игр. срочно нужна сильная маркетинговая программа и расширение сообщества.
есть ставки минимальные, но их и правда маловато.
Ждем рекламы, проекту нужны новые участники, и сейчас это чувствуется как никогда. Можно ведь и самим народ приглашать.
Я периодически делюсь ссылкой на проект с друзьями и в своих аккаунтах.
думаю это мало кто оценит как со стороны разработчиков, так и со стороны инвесторов) а вообще если бы хотели сообщества и рекламы, то организовали бы баунти программу, и думаю и народу набралось и пиар был бы, и тогда бы посмотрели стоит ли это того?
Так разработчики сейчас над этим и работают, обещали ведь и эйрдроп, и запуск рекламы. Думаю стоит подождать, все равно ничего не теряем..
newbie
Activity: 41
Merit: 0
судя по балансу эфирной рулетки, там давно не было игр. срочно нужна сильная маркетинговая программа и расширение сообщества.
ну судя по жадности возможностям команды, сейчас это для них существенная проблема,  как уже предлагали выше, могли бы организовать баунти и думаю было бы больше эффекта и считай бесплатно, чем так
newbie
Activity: 112
Merit: 0
судя по балансу эфирной рулетки, там давно не было игр. срочно нужна сильная маркетинговая программа и расширение сообщества.
есть ставки минимальные, но их и правда маловато.
Ждем рекламы, проекту нужны новые участники, и сейчас это чувствуется как никогда. Можно ведь и самим народ приглашать.
Я периодически делюсь ссылкой на проект с друзьями и в своих аккаунтах.
думаю это мало кто оценит как со стороны разработчиков, так и со стороны инвесторов) а вообще если бы хотели сообщества и рекламы, то организовали бы баунти программу, и думаю и народу набралось и пиар был бы, и тогда бы посмотрели стоит ли это того?
Pages:
Jump to: