Contract Address Details

0x01Bd723A15Ef99fe12A05f28C4620454828c33ad

dgBlackJack Last Balance Update: Block #13440336
Created by 0x1fcd–2c0f8a at 0xa6e6–cb0fab

Balance

0 MATIC

(@ /MATIC)

Fetching tokens...

Contract name:
dgBlackJack




Optimization enabled
true
Compiler version
v0.7.4+commit.3f05b770




Optimization runs
200
EVM Version
default

Constructor Arguments

000000000000000000000000bf79ce2fbd819e5abc2327563d02a200255b7cb3000000000000000000000000000000000000000000000000000000000000000400000000000000000000000011e46db40d4438d1c64f68993ca43b03ac1b6a6b

Arg [0] (address) : 0xbf79ce2fbd819e5abc2327563d02a200255b7cb3
Arg [1] (uint8) : 4
Arg [2] (address) : 0x11e46db40d4438d1c64f68993ca43b03ac1b6a6b

              

Contract source code

/**
* Submitted for verification at blockscout.com on 2020-12-07 06:35:50.059907Z
*/
// SPDX-License-Identifier: -- 🎲 --
pragma solidity ^0.7.4;
interface TreasuryInstance {
function getTokenAddress(
uint8 _tokenIndex
) external view returns (address);
function tokenInboundTransfer(
uint8 _tokenIndex,
address _from,
uint256 _amount
) external returns (bool);
function tokenOutboundTransfer(
uint8 _tokenIndex,
address _to,
uint256 _amount
) external returns (bool);
function checkAllocatedTokens(
uint8 _tokenIndex
) external view returns (uint256);
function checkApproval(
address _userAddress,
uint8 _tokenIndex
) external view returns (uint256 approved);
function getMaximumBet(
uint8 _tokenIndex
) external view returns (uint128);
function consumeHash(
bytes32 _localhash
) external returns (bool);
}
contract AccessController {
address public ceoAddress;
address public workerAddress;
bool public paused = false;
// mapping (address => enumRoles) accessRoles; // multiple operators idea
event CEOSet(address newCEO);
event WorkerSet(address newWorker);
event Paused();
event Unpaused();
constructor() {
ceoAddress = msg.sender;
workerAddress = msg.sender;
emit CEOSet(ceoAddress);
emit WorkerSet(workerAddress);
}
modifier onlyCEO() {
require(
msg.sender == ceoAddress,
'AccessControl: CEO access denied'
);
_;
}
modifier onlyWorker() {
require(
msg.sender == workerAddress,
'AccessControl: worker access denied'
);
_;
}
modifier whenNotPaused() {
require(
!paused,
'AccessControl: currently paused'
);
_;
}
modifier whenPaused {
require(
paused,
'AccessControl: currenlty not paused'
);
_;
}
function setCEO(address _newCEO) public onlyCEO {
require(
_newCEO != address(0x0),
'AccessControl: invalid CEO address'
);
ceoAddress = _newCEO;
emit CEOSet(ceoAddress);
}
function setWorker(address _newWorker) external {
require(
_newWorker != address(0x0),
'AccessControl: invalid worker address'
);
require(
msg.sender == ceoAddress || msg.sender == workerAddress,
'AccessControl: invalid worker address'
);
workerAddress = _newWorker;
emit WorkerSet(workerAddress);
}
function pause() external onlyWorker whenNotPaused {
paused = true;
emit Paused();
}
function unpause() external onlyCEO whenPaused {
paused = false;
emit Unpaused();
}
}
interface PointerInstance {
function addPoints(
address _player,
uint256 _points,
address _token,
uint256 _numPlayers,
uint256 _wearableBonus
) external returns (
uint256 newPoints,
uint256 multiplierA,
uint256 multiplierB
);
function addPoints(
address _player,
uint256 _points,
address _token,
uint256 _numPlayers
) external returns (
uint256 newPoints,
uint256 multiplierA,
uint256 multiplierB
);
function addPoints(
address _player,
uint256 _points,
address _token
) external returns (
uint256 newPoints,
uint256 multiplierA,
uint256 multiplierB
);
}
contract BlackJackHelper {
function getCardsRawData(
uint8 _card
)
public
pure
returns (uint8, uint8)
{
return (_card / 13, _card % 13);
}
function getCardsDetails(
uint8 _card
)
public
pure
returns (string memory, string memory)
{
string[4] memory Suits = ["C", "D", "H", "S"];
string[13] memory Vals = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "T", "J", "Q", "K"];
(uint8 _suit, uint8 _val) = getCardsRawData(_card);
return (Suits[_suit], Vals[_val]);
}
function getRandomCardIndex(
bytes32 _localhash,
uint256 _length
)
internal
pure
returns (uint256)
{
return uint256(
keccak256(
abi.encodePacked(
_localhash, _length
)
)
) % _length;
}
function getCardsPower(
uint8 _card
)
public
pure
returns (uint8 power)
{
bytes13 cardsPower = "\x0B\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0A\x0A\x0A";
return uint8(cardsPower[_card % 13]);
}
function getHandsPower(
uint8[] memory _cards
)
public
pure
returns (uint8 powerMax)
{
uint8 aces;
uint8 power;
for (uint8 i = 0; i < _cards.length; i++) {
power = getCardsPower(_cards[i]);
powerMax += power;
if (power == 11) {
aces += 1;
}
}
if (powerMax > 21) {
for (uint8 i = 0; i < aces; i++) {
powerMax -= 10;
if (powerMax <= 21) {
break;
}
}
}
return powerMax;
}
function isBlackJack(
uint8[] memory _cards
)
public
pure
returns (bool)
{
return getHandsPower(_cards) == 21 && _cards.length == 2;
}
function canSplitCards(
uint8[] memory _cards
)
public
pure
returns (bool)
{
return getCardsPower(_cards[0]) == getCardsPower(_cards[1]) && _cards.length == 2;
}
function verifyHiddenCard(
bytes32 _hashChild,
bytes32 _hashParent
)
public
pure
returns (bool)
{
return keccak256(
abi.encodePacked(_hashParent)
) == _hashChild ? true : false;
}
}
contract dgBlackJack is AccessController, BlackJackHelper {
enum inGameState { notJoined, Playing, EndedPlay }
enum GameState { NewGame, OnGoingGame, EndedGame }
enum PlayerState { notBusted, hasSplit, isSplit, isSettled, isBusted, hasBlackJack }
struct Game {
address[] players;
uint128[] bets;
uint8[] tokens;
uint8[] deck;
uint8 playersCount;
PlayerState[] pState;
GameState state;
}
struct HiddenCard {
bytes32 hashChild;
bytes32 hashParent;
}
mapping(bytes16 => Game) public Games;
mapping(bytes16 => HiddenCard) public DealersHidden;
mapping(bytes16 => uint8[]) public DealersVisible;
mapping(bytes16 => uint8[]) public NonBustedPlayers;
mapping(address => mapping(bytes16 => uint8[])) PlayersHand;
mapping(address => mapping(bytes16 => uint8[])) public PlayerSplit;
mapping(address => mapping(bytes16 => bool)) public PlayersInsurance;
mapping(address => mapping(bytes16 => inGameState)) public inGame;
modifier onlyOnGoingGame(bytes16 _gameId) {
require(
Games[_gameId].state == GameState.OnGoingGame
);
_;
}
modifier ifPlayerInGame(bytes16 _gameId, address _player, uint8 _pIndex) {
require(
Games[_gameId].players[_pIndex] == _player &&
inGame[_player][_gameId] == inGameState.Playing
);
_;
}
modifier onlyNonBustedOrSplit(bytes16 _gameId, uint8 _pIndex) {
require(
Games[_gameId].pState[_pIndex] == PlayerState.notBusted ||
Games[_gameId].pState[_pIndex] == PlayerState.hasSplit ||
Games[_gameId].pState[_pIndex] == PlayerState.isSplit
);
_;
}
modifier onlyNonBusted(bytes16 _gameId, uint8 _pIndex) {
require(
Games[_gameId].pState[_pIndex] == PlayerState.notBusted
);
_;
}
modifier whenTableSettled(bytes16 _gameId) {
address[] memory _players = Games[_gameId].players;
for (uint256 i = 0; i < _players.length; i++) {
require(
uint8(Games[_gameId].pState[i]) >= uint8(PlayerState.isSettled)
);
}
_;
}
TreasuryInstance public treasury;
uint8 maxPlayers;
uint256 nonce;
event BetPlaced(
uint8 tokenIndex,
address player,
uint256 betAmount
);
event GameInitializing(
bytes16 gameId
);
event GameInitialized(
bytes16 gameId,
uint128[] bets,
uint8[] tokens,
uint256 landId,
uint256 tableId
);
event PlayerCardDrawn(
bytes16 gameId,
address player,
uint8 playerIndex,
uint8 cardsIndex,
string cardSuit,
string cardVal
);
event DealersCardDrawn(
bytes16 gameId,
uint8 cardsIndex,
string cardSuit,
string cardVal
);
event DealersCardRevealed(
bytes16 gameId,
uint8 cardsIndex,
string cardSuit,
string cardVal
);
event splitHand(
bytes16 gameId,
address player,
uint256 newIndex,
uint8[] hand,
uint8[] split
);
event InsurancePurchased(
bytes16 gameId,
address player,
uint8 playerIndex
);
event InsurancePayout(
address player,
uint256 amount
);
event PlayersPayout(
address player,
uint256 amount
);
event FinishedGame(
bytes16 gameId
);
event DoubleDown(
uint256 powerAfter
);
event Busted(
bool
);
PointerInstance public pointerContract;
constructor(
address _treasuryAddress,
uint8 _maxPlayers,
address _pointerAddress
) {
require(_maxPlayers < 10);
treasury = TreasuryInstance(_treasuryAddress);
maxPlayers = _maxPlayers;
pointerContract = PointerInstance(_pointerAddress);
}
function _addPoints(
address _player,
uint256 _points,
address _token,
uint256 _numPlayers,
uint256 _wearableBonus
)
private
{
pointerContract.addPoints(
_player,
_points,
_token,
_numPlayers,
_wearableBonus
);
}
function checkPlayer(
bytes16 _gameId,
address _player
)
private
{
require(
inGame[_player][_gameId] == inGameState.notJoined ||
inGame[_player][_gameId] == inGameState.EndedPlay
);
inGame[_player][_gameId] = inGameState.Playing;
}
function takePlayersBet(
bytes16 _gameId,
uint8 _playerIndex
)
private
{
uint8 tokenIndex = Games[_gameId].tokens[_playerIndex];
address player = Games[_gameId].players[_playerIndex];
uint256 betAmount = Games[_gameId].bets[_playerIndex];
require(
treasury.getMaximumBet(tokenIndex) >= betAmount
);
treasury.tokenInboundTransfer(
tokenIndex, player, betAmount
);
emit BetPlaced(
tokenIndex, player, betAmount
);
}
function initializePlayer(
bytes16 _gameId,
uint8 _pIndex
)
private
{
address[] memory _players = Games[_gameId].players;
checkPlayer(
_gameId, _players[_pIndex]
);
Games[_gameId].pState[_pIndex] = PlayerState.notBusted;
}
function checkForBlackJack(
bytes16 _gameId,
uint8 _playerIndex
)
private
{
address[] memory _players = Games[_gameId].players;
if (
isBlackJack(
getHand(_gameId, _players[_playerIndex], _playerIndex)
)) {
NonBustedPlayers[_gameId].push(_playerIndex);
Games[_gameId].pState[_playerIndex] = PlayerState.hasBlackJack;
}
}
function drawDealersCard(
bytes16 _gameId,
bytes32 _localhashA
)
private
{
uint8 _card = drawCard(_gameId, _localhashA);
(
string memory _cardsSuit,
string memory _cardsVal
) = getCardsDetails(_card);
DealersVisible[_gameId].push(_card);
emit DealersCardDrawn(
_gameId,
_card,
_cardsSuit,
_cardsVal
);
}
function drawPlayersCard(
bytes16 _gameId,
uint8 _pIndex,
bytes32 _localhashA
)
private
{
address _player = Games[_gameId].players[_pIndex];
uint8 _card = drawCard(_gameId, _localhashA);
(
string memory _cardsSuit,
string memory _cardsVal
) = getCardsDetails(_card);
uint8[] storage playersHand = hasSplit(_gameId, _pIndex)
? PlayerSplit[_player][_gameId]
: PlayersHand[_player][_gameId];
playersHand.push(_card);
emit PlayerCardDrawn(
_gameId,
_player,
_pIndex,
_card,
_cardsSuit,
_cardsVal
);
}
function initializeGame(
address[] calldata _players,
uint128[] calldata _bets,
uint8[] calldata _tokens,
uint256 _serverId,
uint256 _landId,
uint256 _tableId,
bytes32 _localhashA,
bytes32 _localhashB
)
external
whenNotPaused
onlyWorker
returns (bytes16 gameId)
{
require(
_players.length <= maxPlayers &&
_bets.length == _tokens.length &&
_tokens.length == _players.length
);
/* _consumeMulti(
_serverId,
_landId,
_tableId,
_localhashB
); */
// treasury.consumeHash(_localhashA);
gameId = getGameId(_serverId, _landId, _tableId, _players, nonce);
nonce = nonce + 1;
require(
Games[gameId].state == GameState.NewGame ||
Games[gameId].state == GameState.EndedGame
);
// starting to initialize game
emit GameInitializing(gameId);
uint8[] storage _deck = prepareDeck(gameId);
Game memory _game = Game(
_players,
_bets,
_tokens,
_deck,
uint8(_players.length),
new PlayerState[](_players.length),
GameState.OnGoingGame
);
Games[gameId] = _game;
uint8 pIndex; // playersIndex
// first card drawn to each player + take bets
for (pIndex = 0; pIndex < _players.length; pIndex++) {
initializePlayer(
gameId, pIndex
);
takePlayersBet(
gameId, pIndex
);
drawPlayersCard(
gameId, pIndex, _localhashA
);
}
// dealers first card (visible)
drawDealersCard(
gameId, _localhashA
);
delete NonBustedPlayers[gameId];
// players second cards (visible)
for (pIndex = 0; pIndex < _players.length; pIndex++) {
drawPlayersCard(
gameId, pIndex, _localhashA
);
checkForBlackJack(
gameId, pIndex
);
}
delete pIndex;
DealersHidden[gameId] =
HiddenCard({
hashChild: _localhashB,
hashParent: 0x0
});
emit GameInitialized(
gameId,
_bets,
_tokens,
_landId,
_tableId
);
}
function manualPayout(
bytes16 _gameId,
uint256 _serverId,
uint256 _landId,
uint256 _tableId,
uint128[] calldata _payoutAmounts,
uint128[] calldata _refundAmounts,
bytes32[] calldata _localHashes,
uint128[] calldata _wearableBonus
)
external
onlyOnGoingGame(_gameId)
whenNotPaused
onlyWorker
{
_payout(
_gameId,
_payoutAmounts,
_refundAmounts,
_wearableBonus
);
emit FinishedGame(
_gameId
// _localhashB
);
}
function _payout(
bytes16 _gameId,
uint128[] calldata _payoutAmounts,
uint128[] calldata _refundAmounts,
uint128[] calldata _wearableBonus
)
internal
{
Games[_gameId].state = GameState.EndedGame;
for (uint8 i = 0; i < _payoutAmounts.length; i++) {
payoutAmount(
Games[_gameId].tokens[i],
Games[_gameId].players[i],
_payoutAmounts[i] + _refundAmounts[i]
);
_smartPoints(_gameId, i, _refundAmounts[i], _wearableBonus[i]);
}
}
function _smartPoints(
bytes16 _gameId,
uint8 _pIndex,
uint128 _refundAmount,
uint128 _wearableBonus
)
internal
{
require(Games[_gameId].bets[_pIndex] >= _refundAmount);
_addPoints(
Games[_gameId].players[_pIndex],
Games[_gameId].bets[_pIndex] - _refundAmount,
treasury.getTokenAddress(Games[_gameId].tokens[_pIndex]),
Games[_gameId].players.length,
_wearableBonus
);
}
function prepareDeck(
bytes16 _gameId
)
internal
returns (uint8[] storage _deck)
{
_deck = Games[_gameId].deck;
for (uint8 i = 0; i < 52; i++) {
_deck.push(i);
}
}
function drawCard(
bytes16 _gameId,
bytes32 _localhashA
)
internal
returns (uint8)
{
uint8[] storage _deck = Games[_gameId].deck;
uint256 _card = getRandomCardIndex(
_localhashA, _deck.length
);
uint8 card = _deck[_card];
_deck[_card] = _deck[_deck.length - 1];
_deck.pop();
return card;
}
function hitMove(
bytes16 _gameId,
address _player,
uint8 _pIndex,
bytes32 _localhashA
)
external
onlyWorker
onlyOnGoingGame(_gameId)
onlyNonBustedOrSplit(_gameId, _pIndex)
ifPlayerInGame(_gameId, _player, _pIndex)
{
treasury.consumeHash(_localhashA);
drawPlayersCard(
_gameId, _pIndex, _localhashA
);
uint256 playersPower = getHandsPower(
getHand(_gameId, _player, _pIndex)
);
if (playersPower > 21) {
Games[_gameId].pState[_pIndex] = PlayerState.isBusted;
}
if (playersPower == 21) {
NonBustedPlayers[_gameId].push(_pIndex);
Games[_gameId].pState[_pIndex] = PlayerState.isSettled;
}
}
function stayMove(
bytes16 _gameId,
address _player,
uint8 _pIndex
)
external
onlyWorker
onlyOnGoingGame(_gameId)
onlyNonBustedOrSplit(_gameId, _pIndex)
ifPlayerInGame(_gameId, _player, _pIndex)
{
NonBustedPlayers[_gameId].push(_pIndex);
Games[_gameId].pState[_pIndex] = PlayerState.isSettled;
}
function revealDealersCard(
bytes16 _gameId,
uint256 _serverId,
uint256 _landId,
uint256 _tableId,
bytes32 _localhashB
)
internal
{
uint8 revealed = drawCard(_gameId, _localhashB);
(
string memory _cardsSuit,
string memory _cardsVal
) = getCardsDetails(revealed);
DealersVisible[_gameId].push(revealed);
emit DealersCardRevealed(
_gameId,
revealed,
_cardsSuit,
_cardsVal
);
}
function dealersMove(
bytes16 _gameId,
uint256 _serverId,
uint256 _landId,
uint256 _tableId,
bytes32 _localhashA,
bytes32 _localhashB
)
external
onlyWorker
onlyOnGoingGame(_gameId)
whenTableSettled(_gameId)
{
require(
DealersHidden[_gameId].hashParent == 0x0
);
DealersHidden[_gameId].hashParent = _localhashB;
require(
verifyHiddenCard(
DealersHidden[_gameId].hashChild,
DealersHidden[_gameId].hashParent
) == true
);
treasury.consumeHash(_localhashA);
revealDealersCard(
_gameId,
_serverId,
_landId,
_tableId,
_localhashB
);
uint8[] memory _leftPlayers = getNotBustedPlayers(_gameId);
// check if any player left in the game
if (_leftPlayers.length > 0) {
// check if dealer has a blackjack - proceed to payout
if (isBlackJack(DealersVisible[_gameId])) {
$payoutAgainstBlackJack(_gameId, _leftPlayers);
// check if dealer needs more cards
} else {
uint256 dealersPower = getHandsPower(
DealersVisible[_gameId]
);
uint8 _card;
// draw cards for dealer with _localhashA
while (dealersPower <= 16) {
_card = drawCard(_gameId, _localhashA);
(
string memory _cardsSuit,
string memory _cardsVal
) = getCardsDetails(_card);
dealersPower = _dealerAddVisible(
_gameId,
_card,
_cardsSuit,
_cardsVal
);
}
delete _card;
// calculate any winnings and payout
$payoutAgainstDealersHand(_gameId, _leftPlayers, dealersPower);
}
}
// mark all players finishing the game
address[] memory _players = Games[_gameId].players;
for (uint256 i = 0; i < _players.length; i++) {
inGame[_players[i]][_gameId] = inGameState.EndedPlay;
}
// set game status to ended
Games[_gameId].state = GameState.EndedGame;
emit FinishedGame(
_gameId
// _localhashB
);
}
function _dealerAddVisible(
bytes16 _gameId,
uint8 _card,
string memory _cardsSuit,
string memory _cardsVal
)
internal
returns (uint256)
{
DealersVisible[_gameId].push(_card);
emit DealersCardDrawn(
_gameId,
_card,
_cardsSuit,
_cardsVal
);
return getHandsPower(
DealersVisible[_gameId]
);
}
function $payoutAgainstBlackJack(
bytes16 _gameId,
uint8[] memory _leftPlayers
)
private
{
for (uint256 i = 0; i < _leftPlayers.length; i++) {
address player = Games[_gameId].players[_leftPlayers[i]];
// payout if player also has a blackjack
if (Games[_gameId].pState[i] == PlayerState.hasBlackJack) {
uint128 amount = Games[_gameId].bets[_leftPlayers[i]];
payoutAmount(
Games[_gameId].tokens[_leftPlayers[i]],
player,
amount
);
emit PlayersPayout(
player,
amount
);
}
// payout if player purchased insurance
if (PlayersInsurance[player][_gameId] == true) {
uint128 amount = Games[_gameId].bets[_leftPlayers[i]];
payoutAmount(
Games[_gameId].tokens[_leftPlayers[i]],
player,
amount
);
emit InsurancePayout(
player,
amount
);
}
}
}
function $payoutAgainstDealersHand(
bytes16 _gameId,
uint8[] memory _leftPlayers,
uint256 _dealersPower
)
private
{
for (uint256 i = 0; i < _leftPlayers.length; i++) {
uint8 pi = _leftPlayers[i]; // players index
address player = Games[_gameId].players[pi];
uint256 playersPower = getHandsPower(getHand(_gameId, player, pi));
uint128 payout;
if (Games[_gameId].pState[pi] == PlayerState.hasBlackJack) {
payout = Games[_gameId].bets[pi] * 250 / 100;
}
else if (playersPower > _dealersPower) {
payout = Games[_gameId].bets[pi] * 200 / 100;
}
else if (playersPower == _dealersPower) {
payout = Games[_gameId].bets[pi];
}
if (payout > 0) {
payoutAmount(
Games[_gameId].tokens[pi],
player,
payout
);
emit PlayersPayout(
player,
payout
);
}
}
}
function getNotBustedPlayers(
bytes16 _gameId
)
public
view
returns (uint8[] memory)
{
return NonBustedPlayers[_gameId];
}
function payoutAmount(
uint8 _tokenIndex,
address _player,
uint128 _amount
)
private
{
treasury.tokenOutboundTransfer(
_tokenIndex, _player, uint256(_amount)
);
}
function splitCards(
bytes16 _gameId,
address _player,
uint8 _pIndex
)
external
onlyWorker
onlyOnGoingGame(_gameId)
onlyNonBusted(_gameId, _pIndex)
ifPlayerInGame(_gameId, _player, _pIndex)
{
require(
PlayerSplit[_player][_gameId].length == 0 &&
canSplitCards(PlayersHand[_player][_gameId])
);
Games[_gameId].players.push(_player);
Games[_gameId].bets.push(Games[_gameId].bets[_pIndex]);
Games[_gameId].tokens.push(Games[_gameId].tokens[_pIndex]);
Games[_gameId].pState.push(PlayerState.isSplit);
Games[_gameId].pState[_pIndex] = PlayerState.hasSplit;
takePlayersBet(
_gameId, _pIndex
);
PlayersHand[_player][_gameId].pop();
PlayerSplit[_player][_gameId] = PlayersHand[_player][_gameId];
emit splitHand(
_gameId,
_player,
Games[_gameId].players.length - 1,
PlayersHand[_player][_gameId],
PlayerSplit[_player][_gameId]
);
}
function purchaseInsurance(
bytes16 _gameId,
address _player,
uint8 _pIndex
)
external
onlyWorker
onlyOnGoingGame(_gameId)
onlyNonBusted(_gameId, _pIndex)
{
require (
PlayersHand[_player][_gameId].length == 2 &&
PlayersInsurance[_player][_gameId] == false
);
require (
DealersVisible[_gameId].length == 1 &&
getHandsPower(DealersVisible[_gameId]) == 11
);
PlayersInsurance[_player][_gameId] = true;
uint8 playersCount = Games[_gameId].playersCount;
uint8 tokenIndex = Games[_gameId].tokens[_pIndex];
address player = Games[_gameId].players[_pIndex];
uint256 betAmount = Games[_gameId].bets[_pIndex];
_addPoints(
player,
betAmount / 2,
treasury.getTokenAddress(tokenIndex),
playersCount,
0
);
treasury.tokenInboundTransfer(
tokenIndex, player, betAmount / 2
);
emit InsurancePurchased(
_gameId, player, _pIndex
);
}
function doubleDown(
bytes16 _gameId,
address _player,
bytes32 _localhashA,
uint8 _pIndex
)
external
onlyWorker
onlyOnGoingGame(_gameId)
onlyNonBusted(_gameId, _pIndex)
ifPlayerInGame(_gameId, _player, _pIndex)
{
require (
PlayersHand[_player][_gameId].length == 2
);
treasury.consumeHash(_localhashA);
uint8 tokenIndex = Games[_gameId].tokens[_pIndex];
address player = Games[_gameId].players[_pIndex];
uint256 betAmount = Games[_gameId].bets[_pIndex];
uint8 playersCount = Games[_gameId].playersCount;
_addPoints(
player,
betAmount,
treasury.getTokenAddress(tokenIndex),
playersCount,
0
);
treasury.tokenInboundTransfer(
tokenIndex,
player,
betAmount
);
setBetAmount(
_gameId,
_pIndex,
uint128(betAmount * 2)
);
postDoubleDownActions(
_gameId,
_player,
_localhashA,
_pIndex
);
}
function setBetAmount(
bytes16 _gameId,
uint8 _pIndex,
uint128 newBetAmount
)
internal
{
Games[_gameId].bets[_pIndex] = newBetAmount;
}
function postDoubleDownActions(
bytes16 _gameId,
address _player,
bytes32 _localhashA,
uint8 _pIndex
)
internal
{
drawPlayersCard(
_gameId, _pIndex, _localhashA
);
uint256 playersPower = getHandsPower(
getHand(_gameId, _player, _pIndex)
);
emit DoubleDown(
playersPower
);
if (playersPower > 21) {
Games[_gameId].pState[_pIndex] = PlayerState.isBusted;
emit Busted(true);
} else {
NonBustedPlayers[_gameId].push(_pIndex);
Games[_gameId].pState[_pIndex] = PlayerState.isSettled;
emit Busted(false);
}
}
function checkDeck(
bytes16 _gameId
)
external
view
returns (uint8[] memory _deck)
{
return Games[_gameId].deck;
}
function getGameId(
uint256 _serverID,
uint256 _landID,
uint256 _tableID,
address[] memory _players,
uint256 _nonce
)
public
pure
returns (bytes16 gameId)
{
gameId = bytes16(
keccak256(
abi.encodePacked(_serverID, _landID, _tableID, _players, _nonce)
)
);
}
function getHand(
bytes16 _gameId,
address _player,
uint8 _playerIndex
)
public
view
returns (uint8[] memory playersHand)
{
playersHand = hasSplit(_gameId, _playerIndex)
? PlayerSplit[_player][_gameId]
: PlayersHand[_player][_gameId];
}
function hasSplit(
bytes16 _gameId,
uint8 _pIndex
)
public
view
returns (bool)
{
return Games[_gameId].pState[_pIndex] == PlayerState.isSplit;
}
function updatePointer(
address _newPointerAddress
)
external
onlyCEO
{
pointerContract = PointerInstance(_newPointerAddress);
}
}

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_treasuryAddress","internalType":"address"},{"type":"uint8","name":"_maxPlayers","internalType":"uint8"},{"type":"address","name":"_pointerAddress","internalType":"address"}]},{"type":"event","name":"BetPlaced","inputs":[{"type":"uint8","name":"tokenIndex","internalType":"uint8","indexed":false},{"type":"address","name":"player","internalType":"address","indexed":false},{"type":"uint256","name":"betAmount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Busted","inputs":[{"type":"bool","name":"","internalType":"bool","indexed":false}],"anonymous":false},{"type":"event","name":"CEOSet","inputs":[{"type":"address","name":"newCEO","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"DealersCardDrawn","inputs":[{"type":"bytes16","name":"gameId","internalType":"bytes16","indexed":false},{"type":"uint8","name":"cardsIndex","internalType":"uint8","indexed":false},{"type":"string","name":"cardSuit","internalType":"string","indexed":false},{"type":"string","name":"cardVal","internalType":"string","indexed":false}],"anonymous":false},{"type":"event","name":"DealersCardRevealed","inputs":[{"type":"bytes16","name":"gameId","internalType":"bytes16","indexed":false},{"type":"uint8","name":"cardsIndex","internalType":"uint8","indexed":false},{"type":"string","name":"cardSuit","internalType":"string","indexed":false},{"type":"string","name":"cardVal","internalType":"string","indexed":false}],"anonymous":false},{"type":"event","name":"DoubleDown","inputs":[{"type":"uint256","name":"powerAfter","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"FinishedGame","inputs":[{"type":"bytes16","name":"gameId","internalType":"bytes16","indexed":false}],"anonymous":false},{"type":"event","name":"GameInitialized","inputs":[{"type":"bytes16","name":"gameId","internalType":"bytes16","indexed":false},{"type":"uint128[]","name":"bets","internalType":"uint128[]","indexed":false},{"type":"uint8[]","name":"tokens","internalType":"uint8[]","indexed":false},{"type":"uint256","name":"landId","internalType":"uint256","indexed":false},{"type":"uint256","name":"tableId","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"GameInitializing","inputs":[{"type":"bytes16","name":"gameId","internalType":"bytes16","indexed":false}],"anonymous":false},{"type":"event","name":"InsurancePayout","inputs":[{"type":"address","name":"player","internalType":"address","indexed":false},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"InsurancePurchased","inputs":[{"type":"bytes16","name":"gameId","internalType":"bytes16","indexed":false},{"type":"address","name":"player","internalType":"address","indexed":false},{"type":"uint8","name":"playerIndex","internalType":"uint8","indexed":false}],"anonymous":false},{"type":"event","name":"Paused","inputs":[],"anonymous":false},{"type":"event","name":"PlayerCardDrawn","inputs":[{"type":"bytes16","name":"gameId","internalType":"bytes16","indexed":false},{"type":"address","name":"player","internalType":"address","indexed":false},{"type":"uint8","name":"playerIndex","internalType":"uint8","indexed":false},{"type":"uint8","name":"cardsIndex","internalType":"uint8","indexed":false},{"type":"string","name":"cardSuit","internalType":"string","indexed":false},{"type":"string","name":"cardVal","internalType":"string","indexed":false}],"anonymous":false},{"type":"event","name":"PlayersPayout","inputs":[{"type":"address","name":"player","internalType":"address","indexed":false},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Unpaused","inputs":[],"anonymous":false},{"type":"event","name":"WorkerSet","inputs":[{"type":"address","name":"newWorker","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"splitHand","inputs":[{"type":"bytes16","name":"gameId","internalType":"bytes16","indexed":false},{"type":"address","name":"player","internalType":"address","indexed":false},{"type":"uint256","name":"newIndex","internalType":"uint256","indexed":false},{"type":"uint8[]","name":"hand","internalType":"uint8[]","indexed":false},{"type":"uint8[]","name":"split","internalType":"uint8[]","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"hashChild","internalType":"bytes32"},{"type":"bytes32","name":"hashParent","internalType":"bytes32"}],"name":"DealersHidden","inputs":[{"type":"bytes16","name":"","internalType":"bytes16"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"DealersVisible","inputs":[{"type":"bytes16","name":"","internalType":"bytes16"},{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"playersCount","internalType":"uint8"},{"type":"uint8","name":"state","internalType":"enum dgBlackJack.GameState"}],"name":"Games","inputs":[{"type":"bytes16","name":"","internalType":"bytes16"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"NonBustedPlayers","inputs":[{"type":"bytes16","name":"","internalType":"bytes16"},{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"PlayerSplit","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"bytes16","name":"","internalType":"bytes16"},{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"PlayersInsurance","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"bytes16","name":"","internalType":"bytes16"}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"canSplitCards","inputs":[{"type":"uint8[]","name":"_cards","internalType":"uint8[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"ceoAddress","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8[]","name":"_deck","internalType":"uint8[]"}],"name":"checkDeck","inputs":[{"type":"bytes16","name":"_gameId","internalType":"bytes16"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"dealersMove","inputs":[{"type":"bytes16","name":"_gameId","internalType":"bytes16"},{"type":"uint256","name":"_serverId","internalType":"uint256"},{"type":"uint256","name":"_landId","internalType":"uint256"},{"type":"uint256","name":"_tableId","internalType":"uint256"},{"type":"bytes32","name":"_localhashA","internalType":"bytes32"},{"type":"bytes32","name":"_localhashB","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"doubleDown","inputs":[{"type":"bytes16","name":"_gameId","internalType":"bytes16"},{"type":"address","name":"_player","internalType":"address"},{"type":"bytes32","name":"_localhashA","internalType":"bytes32"},{"type":"uint8","name":"_pIndex","internalType":"uint8"}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"string","name":"","internalType":"string"},{"type":"string","name":"","internalType":"string"}],"name":"getCardsDetails","inputs":[{"type":"uint8","name":"_card","internalType":"uint8"}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"uint8","name":"power","internalType":"uint8"}],"name":"getCardsPower","inputs":[{"type":"uint8","name":"_card","internalType":"uint8"}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"uint8","name":"","internalType":"uint8"},{"type":"uint8","name":"","internalType":"uint8"}],"name":"getCardsRawData","inputs":[{"type":"uint8","name":"_card","internalType":"uint8"}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"bytes16","name":"gameId","internalType":"bytes16"}],"name":"getGameId","inputs":[{"type":"uint256","name":"_serverID","internalType":"uint256"},{"type":"uint256","name":"_landID","internalType":"uint256"},{"type":"uint256","name":"_tableID","internalType":"uint256"},{"type":"address[]","name":"_players","internalType":"address[]"},{"type":"uint256","name":"_nonce","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8[]","name":"playersHand","internalType":"uint8[]"}],"name":"getHand","inputs":[{"type":"bytes16","name":"_gameId","internalType":"bytes16"},{"type":"address","name":"_player","internalType":"address"},{"type":"uint8","name":"_playerIndex","internalType":"uint8"}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"uint8","name":"powerMax","internalType":"uint8"}],"name":"getHandsPower","inputs":[{"type":"uint8[]","name":"_cards","internalType":"uint8[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8[]","name":"","internalType":"uint8[]"}],"name":"getNotBustedPlayers","inputs":[{"type":"bytes16","name":"_gameId","internalType":"bytes16"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"hasSplit","inputs":[{"type":"bytes16","name":"_gameId","internalType":"bytes16"},{"type":"uint8","name":"_pIndex","internalType":"uint8"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"hitMove","inputs":[{"type":"bytes16","name":"_gameId","internalType":"bytes16"},{"type":"address","name":"_player","internalType":"address"},{"type":"uint8","name":"_pIndex","internalType":"uint8"},{"type":"bytes32","name":"_localhashA","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"enum dgBlackJack.inGameState"}],"name":"inGame","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"bytes16","name":"","internalType":"bytes16"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bytes16","name":"gameId","internalType":"bytes16"}],"name":"initializeGame","inputs":[{"type":"address[]","name":"_players","internalType":"address[]"},{"type":"uint128[]","name":"_bets","internalType":"uint128[]"},{"type":"uint8[]","name":"_tokens","internalType":"uint8[]"},{"type":"uint256","name":"_serverId","internalType":"uint256"},{"type":"uint256","name":"_landId","internalType":"uint256"},{"type":"uint256","name":"_tableId","internalType":"uint256"},{"type":"bytes32","name":"_localhashA","internalType":"bytes32"},{"type":"bytes32","name":"_localhashB","internalType":"bytes32"}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isBlackJack","inputs":[{"type":"uint8[]","name":"_cards","internalType":"uint8[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"manualPayout","inputs":[{"type":"bytes16","name":"_gameId","internalType":"bytes16"},{"type":"uint256","name":"_serverId","internalType":"uint256"},{"type":"uint256","name":"_landId","internalType":"uint256"},{"type":"uint256","name":"_tableId","internalType":"uint256"},{"type":"uint128[]","name":"_payoutAmounts","internalType":"uint128[]"},{"type":"uint128[]","name":"_refundAmounts","internalType":"uint128[]"},{"type":"bytes32[]","name":"_localHashes","internalType":"bytes32[]"},{"type":"uint128[]","name":"_wearableBonus","internalType":"uint128[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"pause","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"paused","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract PointerInstance"}],"name":"pointerContract","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"purchaseInsurance","inputs":[{"type":"bytes16","name":"_gameId","internalType":"bytes16"},{"type":"address","name":"_player","internalType":"address"},{"type":"uint8","name":"_pIndex","internalType":"uint8"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setCEO","inputs":[{"type":"address","name":"_newCEO","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setWorker","inputs":[{"type":"address","name":"_newWorker","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"splitCards","inputs":[{"type":"bytes16","name":"_gameId","internalType":"bytes16"},{"type":"address","name":"_player","internalType":"address"},{"type":"uint8","name":"_pIndex","internalType":"uint8"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"stayMove","inputs":[{"type":"bytes16","name":"_gameId","internalType":"bytes16"},{"type":"address","name":"_player","internalType":"address"},{"type":"uint8","name":"_pIndex","internalType":"uint8"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract TreasuryInstance"}],"name":"treasury","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"unpause","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updatePointer","inputs":[{"type":"address","name":"_newPointerAddress","internalType":"address"}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"verifyHiddenCard","inputs":[{"type":"bytes32","name":"_hashChild","internalType":"bytes32"},{"type":"bytes32","name":"_hashParent","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"workerAddress","inputs":[]}]
            

Contract Byte Code

0x608060405234801561001057600080fd5b50600436106102275760003560e01c8063659ae43f11610130578063c1e14249116100b8578063d4c575431161007c578063d4c5754314610c1a578063e4c279b714610c50578063e6fae6be14610c70578063efc5e73d14610d11578063f9bf6de314610e0f57610227565b8063c1e1424914610b21578063c26f6d4414610b4e578063c54f0c5214610b74578063cbd88f4814610beb578063d4652cf414610bf357610227565b806382c0e522116100ff57806382c0e52214610a4b57806383cf376d14610a8a5780638456cb5914610aad5780639ac6c3ca14610ab5578063aa8d7c2614610af157610227565b8063659ae43f1461093f578063697c641514610982578063776c2b84146109af578063827e902c14610a0657610227565b80634d41ddaf116101b3578063574a47e311610182578063574a47e3146106b85780635bc57af91461076f5780635c975abb146108f05780635f7b9257146108f857806361d027b31461093757610227565b80634d41ddaf1461048f57806350bfba99146105445780635184c0661461054c57806351e8bab91461059157610227565b80633f4ba83a116101fa5780633f4ba83a146102f0578063433010c0146102f85780634359cb0f146103cb578063457457af1461040a5780634c3544361461044f57610227565b80630a0f81681461022c578063252949491461025057806327d7874c146102a25780633025d9e2146102ca575b600080fd5b610234610e4e565b604080516001600160a01b039092168252519081900360200190f35b6102776004803603602081101561026657600080fd5b50356001600160801b031916610e5d565b604051808360ff16815260200182600281111561029057fe5b81526020019250505060405180910390f35b6102c8600480360360208110156102b857600080fd5b50356001600160a01b0316610e80565b005b6102c8600480360360208110156102e057600080fd5b50356001600160a01b0316610f7e565b6102c8610fff565b6103ae600480360360a081101561030e57600080fd5b81359160208101359160408201359190810190608081016060820135600160201b81111561033b57600080fd5b82018360208201111561034d57600080fd5b803590602001918460208302840111600160201b8311171561036e57600080fd5b91908080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525092955050913592506110de915050565b604080516001600160801b03199092168252519081900360200190f35b6102c8600480360360608110156103e157600080fd5b5080356001600160801b0319169060208101356001600160a01b0316906040013560ff16611158565b6102c86004803603608081101561042057600080fd5b506001600160801b0319813516906001600160a01b036020820135169060ff604082013516906060013561147f565b6104766004803603602081101561046557600080fd5b50356001600160801b0319166118bd565b6040805192835260208301919091528051918290030190f35b610530600480360360208110156104a557600080fd5b810190602081018135600160201b8111156104bf57600080fd5b8201836020820111156104d157600080fd5b803590602001918460208302840111600160201b831117156104f257600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506118d6945050505050565b604080519115158252519081900360200190f35b6102346118fa565b6102c86004803603608081101561056257600080fd5b5080356001600160801b0319169060208101356001600160a01b0316906040810135906060013560ff16611909565b6103ae60048036036101008110156105a857600080fd5b810190602081018135600160201b8111156105c257600080fd5b8201836020820111156105d457600080fd5b803590602001918460208302840111600160201b831117156105f557600080fd5b919390929091602081019035600160201b81111561061257600080fd5b82018360208201111561062457600080fd5b803590602001918460208302840111600160201b8311171561064557600080fd5b919390929091602081019035600160201b81111561066257600080fd5b82018360208201111561067457600080fd5b803590602001918460208302840111600160201b8311171561069557600080fd5b919350915080359060208101359060408101359060608101359060800135611db5565b610759600480360360208110156106ce57600080fd5b810190602081018135600160201b8111156106e857600080fd5b8201836020820111156106fa57600080fd5b803590602001918460208302840111600160201b8311171561071b57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506123b3945050505050565b6040805160ff9092168252519081900360200190f35b6102c8600480360361010081101561078657600080fd5b6001600160801b03198235169160208101359160408201359160608101359181019060a081016080820135600160201b8111156107c257600080fd5b8201836020820111156107d457600080fd5b803590602001918460208302840111600160201b831117156107f557600080fd5b919390929091602081019035600160201b81111561081257600080fd5b82018360208201111561082457600080fd5b803590602001918460208302840111600160201b8311171561084557600080fd5b919390929091602081019035600160201b81111561086257600080fd5b82018360208201111561087457600080fd5b803590602001918460208302840111600160201b8311171561089557600080fd5b919390929091602081019035600160201b8111156108b257600080fd5b8201836020820111156108c457600080fd5b803590602001918460208302840111600160201b831117156108e557600080fd5b50909250905061244a565b610530612587565b6102c86004803603606081101561090e57600080fd5b5080356001600160801b0319169060208101356001600160a01b0316906040013560ff16612597565b610234612a52565b61095f6004803603602081101561095557600080fd5b503560ff16612a61565b604051808360ff1681526020018260ff1681526020019250505060405180910390f35b6107596004803603604081101561099857600080fd5b506001600160801b03198135169060200135612a73565b6109e5600480360360408110156109c557600080fd5b5080356001600160a01b031690602001356001600160801b031916612ab6565b604051808260028111156109f557fe5b815260200191505060405180910390f35b6102c8600480360360c0811015610a1c57600080fd5b506001600160801b03198135169060208101359060408101359060608101359060808101359060a00135612ad6565b6102c860048036036060811015610a6157600080fd5b5080356001600160801b0319169060208101356001600160a01b0316906040013560ff16613013565b61053060048036036040811015610aa057600080fd5b5080359060200135613641565b6102c861367b565b61075960048036036060811015610acb57600080fd5b506001600160a01b03813516906001600160801b03196020820135169060400135613761565b61053060048036036040811015610b0757600080fd5b5080356001600160801b031916906020013560ff166137b1565b61075960048036036040811015610b3757600080fd5b506001600160801b03198135169060200135613813565b6102c860048036036020811015610b6457600080fd5b50356001600160a01b031661382f565b610b9b60048036036020811015610b8a57600080fd5b50356001600160801b03191661392c565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015610bd7578181015183820152602001610bbf565b505050509050019250505060405180910390f35b6102346139b7565b610b9b60048036036020811015610c0957600080fd5b50356001600160801b0319166139c6565b61053060048036036040811015610c3057600080fd5b5080356001600160a01b031690602001356001600160801b031916613a37565b61075960048036036020811015610c6657600080fd5b503560ff16613a57565b61053060048036036020811015610c8657600080fd5b810190602081018135600160201b811115610ca057600080fd5b820183602082011115610cb257600080fd5b803590602001918460208302840111600160201b83111715610cd357600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550613a87945050505050565b610d3160048036036020811015610d2757600080fd5b503560ff16613abf565b604051808060200180602001838103835285818151815260200191508051906020019080838360005b83811015610d72578181015183820152602001610d5a565b50505050905090810190601f168015610d9f5780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b83811015610dd2578181015183820152602001610dba565b50505050905090810190601f168015610dff5780820380516001836020036101000a031916815260200191505b5094505050505060405180910390f35b610b9b60048036036060811015610e2557600080fd5b5080356001600160801b0319169060208101356001600160a01b0316906040013560ff16613cdb565b6000546001600160a01b031681565b6002602052600090815260409020600481015460069091015460ff918216911682565b6000546001600160a01b03163314610edf576040805162461bcd60e51b815260206004820181905260248201527f416363657373436f6e74726f6c3a2043454f206163636573732064656e696564604482015290519081900360640190fd5b6001600160a01b038116610f245760405162461bcd60e51b8152600401808060200182810382526022815260200180615bf16022913960400191505060405180910390fd5b600080546001600160a01b0319166001600160a01b03838116919091179182905560408051929091168252517ff97cbb4246b709036319093e5ff31674b9f6759076d153e1bea1f60392170fc0916020908290030190a150565b6000546001600160a01b03163314610fdd576040805162461bcd60e51b815260206004820181905260248201527f416363657373436f6e74726f6c3a2043454f206163636573732064656e696564604482015290519081900360640190fd5b600c80546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b0316331461105e576040805162461bcd60e51b815260206004820181905260248201527f416363657373436f6e74726f6c3a2043454f206163636573732064656e696564604482015290519081900360640190fd5b600154600160a01b900460ff166110a65760405162461bcd60e51b8152600401808060200182810382526023815260200180615c366023913960400191505060405180910390fd5b6001805460ff60a01b191690556040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d1693390600090a1565b6000858585858560405160200180868152602001858152602001848152602001838051906020019060200280838360005b8381101561112757818101518382015260200161110f565b50505050919091019283525050604080518083038152602092830190915280519101209a9950505050505050505050565b6001546001600160a01b031633146111a15760405162461bcd60e51b8152600401808060200182810382526023815260200180615c136023913960400191505060405180910390fd5b8260016001600160801b0319821660009081526002602081905260409091206006015460ff16908111156111d157fe5b146111db57600080fd5b838260006001600160801b031983166000908152600260205260409020600501805460ff841690811061120a57fe5b90600052602060002090602091828204019190069054906101000a900460ff16600581111561123557fe5b1480611296575060016001600160801b031983166000908152600260205260409020600501805460ff841690811061126957fe5b90600052602060002090602091828204019190069054906101000a900460ff16600581111561129457fe5b145b806112f6575060026001600160801b031983166000908152600260205260409020600501805460ff84169081106112c957fe5b90600052602060002090602091828204019190069054906101000a900460ff1660058111156112f457fe5b145b6112ff57600080fd5b6001600160801b03198616600090815260026020526040902080548791879187916001600160a01b0384169160ff841690811061133857fe5b6000918252602090912001546001600160a01b0316148015611395575060016001600160a01b03831660009081526009602090815260408083206001600160801b03198816845290915290205460ff16600281111561139357fe5b145b61139e57600080fd5b600560008a6001600160801b0319166001600160801b03191681526020019081526020016000208790806001815401808255809150506001900390600052602060002090602091828204019190069091909190916101000a81548160ff021916908360ff1602179055506003600260008b6001600160801b0319166001600160801b03191681526020019081526020016000206005018860ff168154811061144257fe5b90600052602060002090602091828204019190066101000a81548160ff0219169083600581111561146f57fe5b0217905550505050505050505050565b6001546001600160a01b031633146114c85760405162461bcd60e51b8152600401808060200182810382526023815260200180615c136023913960400191505060405180910390fd5b8360016001600160801b0319821660009081526002602081905260409091206006015460ff16908111156114f857fe5b1461150257600080fd5b848360006001600160801b031983166000908152600260205260409020600501805460ff841690811061153157fe5b90600052602060002090602091828204019190069054906101000a900460ff16600581111561155c57fe5b14806115bd575060016001600160801b031983166000908152600260205260409020600501805460ff841690811061159057fe5b90600052602060002090602091828204019190069054906101000a900460ff1660058111156115bb57fe5b145b8061161d575060026001600160801b031983166000908152600260205260409020600501805460ff84169081106115f057fe5b90600052602060002090602091828204019190069054906101000a900460ff16600581111561161b57fe5b145b61162657600080fd5b6001600160801b03198716600090815260026020526040902080548891889188916001600160a01b0384169160ff841690811061165f57fe5b6000918252602090912001546001600160a01b03161480156116bc575060016001600160a01b03831660009081526009602090815260408083206001600160801b03198816845290915290205460ff1660028111156116ba57fe5b145b6116c557600080fd5b600a54604080516365afb44f60e01b8152600481018a905290516001600160a01b03909216916365afb44f916024808201926020929091908290030181600087803b15801561171357600080fd5b505af1158015611727573d6000803e3d6000fd5b505050506040513d602081101561173d57600080fd5b5061174b90508a8989613dc1565b600061176061175b8c8c8c613cdb565b6123b3565b60ff16905060158111156117d0576001600160801b03198b16600090815260026020526040902060050180546004919060ff8c1690811061179d57fe5b90600052602060002090602091828204019190066101000a81548160ff021916908360058111156117ca57fe5b02179055505b80601514156118b057600560008c6001600160801b0319166001600160801b03191681526020019081526020016000208990806001815401808255809150506001900390600052602060002090602091828204019190069091909190916101000a81548160ff021916908360ff1602179055506003600260008d6001600160801b0319166001600160801b03191681526020019081526020016000206005018a60ff168154811061187d57fe5b90600052602060002090602091828204019190066101000a81548160ff021916908360058111156118aa57fe5b02179055505b5050505050505050505050565b6003602052600090815260409020805460019091015482565b60006118e1826123b3565b60ff1660151480156118f4575081516002145b92915050565b600c546001600160a01b031681565b6001546001600160a01b031633146119525760405162461bcd60e51b8152600401808060200182810382526023815260200180615c136023913960400191505060405180910390fd5b8360016001600160801b0319821660009081526002602081905260409091206006015460ff169081111561198257fe5b1461198c57600080fd5b848260006001600160801b031983166000908152600260205260409020600501805460ff84169081106119bb57fe5b90600052602060002090602091828204019190069054906101000a900460ff1660058111156119e657fe5b146119f057600080fd5b6001600160801b03198716600090815260026020526040902080548891889187916001600160a01b0384169160ff8416908110611a2957fe5b6000918252602090912001546001600160a01b0316148015611a86575060016001600160a01b03831660009081526009602090815260408083206001600160801b03198816845290915290205460ff166002811115611a8457fe5b145b611a8f57600080fd5b6001600160a01b03891660009081526006602090815260408083206001600160801b03198e168452909152902054600214611ac957600080fd5b600a54604080516365afb44f60e01b8152600481018b905290516001600160a01b03909216916365afb44f916024808201926020929091908290030181600087803b158015611b1757600080fd5b505af1158015611b2b573d6000803e3d6000fd5b505050506040513d6020811015611b4157600080fd5b50506001600160801b03198a166000908152600260208190526040822001805460ff8a16908110611b6e57fe5b6000918252602080832081830401546001600160801b03198f168452600290915260408320805460ff601f9094166101000a90920483169450918b16908110611bb357fe5b60009182526020808320909101546001600160801b03198f16835260029091526040822060010180546001600160a01b0390921693509060ff8c16908110611bf757fe5b90600052602060002090600291828204019190066010029054906101000a90046001600160801b03166001600160801b031690506000600260008f6001600160801b0319166001600160801b031916815260200190815260200160002060040160009054906101000a900460ff169050611cff8383600a60009054906101000a90046001600160a01b03166001600160a01b0316635ad3f918886040518263ffffffff1660e01b8152600401808260ff16815260200191505060206040518083038186803b158015611cc857600080fd5b505afa158015611cdc573d6000803e3d6000fd5b505050506040513d6020811015611cf257600080fd5b505160ff85166000614014565b600a54604080516341d4c74f60e01b815260ff871660048201526001600160a01b03868116602483015260448201869052915191909216916341d4c74f9160648083019260209291908290030181600087803b158015611d5e57600080fd5b505af1158015611d72573d6000803e3d6000fd5b505050506040513d6020811015611d8857600080fd5b50611d9990508e8c600285026140b3565b611da58e8e8e8e61411f565b5050505050505050505050505050565b600154600090600160a01b900460ff1615611e17576040805162461bcd60e51b815260206004820152601f60248201527f416363657373436f6e74726f6c3a2063757272656e746c792070617573656400604482015290519081900360640190fd5b6001546001600160a01b03163314611e605760405162461bcd60e51b8152600401808060200182810382526023815260200180615c136023913960400191505060405180910390fd5b600a54600160a01b900460ff168b11801590611e7b57508887145b8015611e865750868b145b611e8f57600080fd5b611ed28686868f8f8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050600b5491506110de9050565b600b80546001019055905060006001600160801b0319821660009081526002602081905260409091206006015460ff1690811115611f0c57fe5b1480611f4257506001600160801b0319811660009081526002602081905260409091206006015460ff1681811115611f4057fe5b145b611f4b57600080fd5b604080516001600160801b03198316815290517f5c79138ada278a9e3a8aa175a6ad8833ece98eca3658c5fe3b62edcafad3e5479181900360200190a16000611f93826142eb565b9050611f9d615899565b6040518060e001604052808f8f80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505081526020018d8d808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505050908252506040805160208d810282810182019093528d82529283019290918e918e918291850190849080828437600092019190915250505090825250835460408051602083810282018101909252828152928101929186918301828280156120c657602002820191906000526020600020906000905b825461010083900a900460ff168152602060019283018181049485019490930390920291018084116120975790505b505050918352505060ff8f1660208201526040018e67ffffffffffffffff811180156120f157600080fd5b5060405190808252806020026020018201604052801561211b578160200160208202803683370190505b50815260016020918201526001600160801b03198516600090815260028252604090208251805193945084939192612158928492909101906158e3565b5060208281015180516121719260018501920190615948565b506040820151805161218d9160028401916020909101906159fb565b50606082015180516121a99160038401916020909101906159fb565b50608082015160048201805460ff191660ff90921691909117905560a082015180516121df916005840191602090910190615a8f565b5060c082015160068201805460ff191660018360028111156121fd57fe5b021790555090505060005b60ff81168e111561223a5761221d8482614357565b612227848261444b565b612232848288613dc1565b600101612208565b6122448487614693565b6001600160801b03198416600090815260056020526040812061226691615afe565b5060005b60ff81168e111561229257612280848288613dc1565b61228a8482614818565b60010161226a565b6000905060405180604001604052808681526020016000801b81525060036000866001600160801b0319166001600160801b031916815260200190815260200160002060008201518160000155602082015181600101559050507fe9789e53c56c21d0e64c2ba42c8d7c8b972c820ce9b1439c9bc171fb70b6a823848e8e8e8e8d8d60405180886001600160801b031916815260200180602001806020018581526020018481526020018381038352898982818152602001925060200280828437600083820152601f01601f19169091018481038352878152602090810191508890880280828437600083820152604051601f909101601f19169092018290039b50909950505050505050505050a15050509b9a5050505050505050505050565b60008080805b84518160ff161015612405576123e4858260ff16815181106123d757fe5b6020026020010151613a57565b938401939150600b60ff831614156123fd576001830192505b6001016123b9565b5060158360ff1611156124435760005b8260ff168160ff16101561244157600a8403935060158460ff161161243957612441565b600101612415565b505b5050919050565b8b60016001600160801b0319821660009081526002602081905260409091206006015460ff169081111561247a57fe5b1461248457600080fd5b600154600160a01b900460ff16156124e3576040805162461bcd60e51b815260206004820152601f60248201527f416363657373436f6e74726f6c3a2063757272656e746c792070617573656400604482015290519081900360640190fd5b6001546001600160a01b0316331461252c5760405162461bcd60e51b8152600401808060200182810382526023815260200180615c136023913960400191505060405180910390fd5b61253b8d8a8a8a8a8888614922565b604080516001600160801b03198f16815290517f8a06fcdc0d1be3eae3b1e12e7a91fab33f69e210d923e12bdcaf65436a1659a89181900360200190a150505050505050505050505050565b600154600160a01b900460ff1681565b6001546001600160a01b031633146125e05760405162461bcd60e51b8152600401808060200182810382526023815260200180615c136023913960400191505060405180910390fd5b8260016001600160801b0319821660009081526002602081905260409091206006015460ff169081111561261057fe5b1461261a57600080fd5b838260006001600160801b031983166000908152600260205260409020600501805460ff841690811061264957fe5b90600052602060002090602091828204019190069054906101000a900460ff16600581111561267457fe5b1461267e57600080fd5b6001600160a01b03851660009081526006602090815260408083206001600160801b03198a16845290915290205460021480156126e957506001600160a01b03851660009081526008602090815260408083206001600160801b03198a16845290915290205460ff16155b6126f257600080fd5b6001600160801b0319861660009081526004602052604090205460011480156127a757506001600160801b0319861660009081526004602090815260409182902080548351818402810184019094528084526127a0939283018282801561279657602002820191906000526020600020906000905b825461010083900a900460ff168152602060019283018181049485019490930390920291018084116127675790505b50505050506123b3565b60ff16600b145b6127b057600080fd5b6001600160a01b03851660009081526008602090815260408083206001600160801b03198a1684528252808320805460ff19166001179055600291829052822060048101549101805460ff9283169392881690811061280b57fe5b6000918252602080832081830401546001600160801b03198c168452600290915260408320805460ff601f9094166101000a9092048316945091891690811061285057fe5b60009182526020808320909101546001600160801b03198c16835260029091526040822060010180546001600160a01b0390921693509060ff8a1690811061289457fe5b90600052602060002090600291828204019190066010029054906101000a90046001600160801b03166001600160801b0316905061295f82600283816128d657fe5b600a5460408051630b5a7f2360e31b815260ff8a166004820152905193909204926001600160a01b0390911691635ad3f918916024808301926020929190829003018186803b15801561292857600080fd5b505afa15801561293c573d6000803e3d6000fd5b505050506040513d602081101561295257600080fd5b505160ff88166000614014565b600a546001600160a01b03166341d4c74f8484600285046040518463ffffffff1660e01b8152600401808460ff168152602001836001600160a01b031681526020018281526020019350505050602060405180830381600087803b1580156129c657600080fd5b505af11580156129da573d6000803e3d6000fd5b505050506040513d60208110156129f057600080fd5b5050604080516001600160801b03198c1681526001600160a01b038416602082015260ff8a168183015290517fdb6e35eacf9090f40a5453fd7c372403ecea66a053067bc14a03ba91cc06e1a69181900360600190a150505050505050505050565b600a546001600160a01b031681565b600d60ff919091168181049291900690565b60046020528160005260406000208181548110612a8f57600080fd5b9060005260206000209060209182820401919006915091509054906101000a900460ff1681565b600960209081526000928352604080842090915290825290205460ff1681565b6001546001600160a01b03163314612b1f5760405162461bcd60e51b8152600401808060200182810382526023815260200180615c136023913960400191505060405180910390fd5b8560016001600160801b0319821660009081526002602081905260409091206006015460ff1690811115612b4f57fe5b14612b5957600080fd5b6001600160801b0319871660009081526002602090815260409182902080548351818402810184019094528084528a9360609390929190830182828015612bc957602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612bab575b5050505050905060005b8151811015612c49576001600160801b03198316600090815260026020526040902060050180546003919083908110612c0857fe5b90600052602060002090602091828204019190069054906101000a900460ff166005811115612c3357fe5b60ff161015612c4157600080fd5b600101612bd3565b506001600160801b0319891660009081526003602052604090206001015415612c7157600080fd5b6001600160801b0319891660009081526003602052604090206001810185905554612c9c9085613641565b1515600114612caa57600080fd5b600a54604080516365afb44f60e01b81526004810188905290516001600160a01b03909216916365afb44f916024808201926020929091908290030181600087803b158015612cf857600080fd5b505af1158015612d0c573d6000803e3d6000fd5b505050506040513d6020811015612d2257600080fd5b50612d3290508989898988614a81565b6060612d3d8a61392c565b805190915015612ea3576001600160801b03198a166000908152600460209081526040918290208054835181840281018401909452808452612dd19392830182828015612dc757602002820191906000526020600020906000905b825461010083900a900460ff16815260206001928301818104948501949093039092029101808411612d985790505b50505050506118d6565b15612de557612de08a82614c09565b612ea3565b6001600160801b03198a1660009081526004602090815260408083208054825181850281018501909352808352612e5193830182828015612796576000918252602091829020805460ff16845290820283019290916001910180841161276757905050505050506123b3565b60ff16905060005b60108211612e9257612e6b8c89614f2b565b9050606080612e7983613abf565b91509150612e898e84848461502f565b93505050612e59565b506000612ea08c8484615205565b50505b6001600160801b03198a16600090815260026020908152604091829020805483518184028101840190945280845260609392830182828015612f0e57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612ef0575b5050505050905060005b8151811015612fa857600260096000848481518110612f3357fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008e6001600160801b0319166001600160801b031916815260200190815260200160002060006101000a81548160ff02191690836002811115612f9b57fe5b0217905550600101612f18565b506001600160801b03198b16600081815260026020818152604092839020600601805460ff1916909217909155815192835290517f8a06fcdc0d1be3eae3b1e12e7a91fab33f69e210d923e12bdcaf65436a1659a89281900390910190a15050505050505050505050565b6001546001600160a01b0316331461305c5760405162461bcd60e51b8152600401808060200182810382526023815260200180615c136023913960400191505060405180910390fd5b8260016001600160801b0319821660009081526002602081905260409091206006015460ff169081111561308c57fe5b1461309657600080fd5b838260006001600160801b031983166000908152600260205260409020600501805460ff84169081106130c557fe5b90600052602060002090602091828204019190069054906101000a900460ff1660058111156130f057fe5b146130fa57600080fd5b6001600160801b03198616600090815260026020526040902080548791879187916001600160a01b0384169160ff841690811061313357fe5b6000918252602090912001546001600160a01b0316148015613190575060016001600160a01b03831660009081526009602090815260408083206001600160801b03198816845290915290205460ff16600281111561318e57fe5b145b61319957600080fd5b6001600160a01b03881660009081526007602090815260408083206001600160801b03198d16845290915290205415801561326a57506001600160a01b03881660009081526006602090815260408083206001600160801b03198d168452825291829020805483518184028101840190945280845261326a939283018282801561326057602002820191906000526020600020906000905b825461010083900a900460ff168152602060019283018181049485019490930390920291018084116132315790505b5050505050613a87565b61327357600080fd5b6001600160801b03198916600081815260026020908152604082208054600180820183558285529284200180546001600160a01b0319166001600160a01b038e1617905592909152018054819060ff8a169081106132cd57fe5b600091825260208083206002808404909101548554600180820188559686528386208382040180546001600160801b036010938a16840261010090810a828102199093169a90981690930290960a90920416909302949094179091556001600160801b03198c16825282905260409020018054819060ff8a1690811061334f57fe5b60009182526020808320818304015484546001808201875595855282852083820401805460ff601f93841661010090810a82810219909316978516810a90950481169091029590951790556001600160801b03198f168086526002808552604087206005018054808a01825581895286892096810490960180549690941690940a9081029086021990941693909317905592528154908a169081106133f057fe5b90600052602060002090602091828204019190066101000a81548160ff0219169083600581111561341d57fe5b021790555061342c898861444b565b6001600160a01b03881660009081526006602090815260408083206001600160801b03198d168452909152902080548061346257fe5b60008281526020808220600019909301818104909301805460ff601f86166101000a0219169055919092556001600160a01b038a168083526006825260408084206001600160801b03198e1680865290845281852092855260078452818520908552909252912081546134d59290615b26565b506001600160801b031989166000818152600260209081526040808320546001600160a01b038d16808552600684528285208686528452828520818652600785528386208787528552948390208351968752938601526000190190840181905260a06060850181815284549186018290527f93675dd8ad58ef405624d8b6842ec6095972328ad8eba5238dfbe10b8119af0a958f958f959093909290608083019060c0840190869080156135c657602002820191906000526020600020906000905b825461010083900a900460ff168152602060019283018181049485019490930390920291018084116135975790505b5050838103825284818154815260200191508054801561362357602002820191906000526020600020906000905b825461010083900a900460ff168152602060019283018181049485019490930390920291018084116135f45790505b505097505050505050505060405180910390a1505050505050505050565b60408051602080820184905282518083038201815291830190925280519101206000908314613671576000613674565b60015b9392505050565b6001546001600160a01b031633146136c45760405162461bcd60e51b8152600401808060200182810382526023815260200180615c136023913960400191505060405180910390fd5b600154600160a01b900460ff1615613723576040805162461bcd60e51b815260206004820152601f60248201527f416363657373436f6e74726f6c3a2063757272656e746c792070617573656400604482015290519081900360640190fd5b6001805460ff60a01b1916600160a01b1790556040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e75290600090a1565b6007602052826000526040600020602052816000526040600020818154811061378957600080fd5b906000526020600020906020918282040191900692509250509054906101000a900460ff1681565b600060026001600160801b031984166000908152600260205260409020600501805460ff85169081106137e057fe5b90600052602060002090602091828204019190069054906101000a900460ff16600581111561380b57fe5b149392505050565b60056020528160005260406000208181548110612a8f57600080fd5b6001600160a01b0381166138745760405162461bcd60e51b8152600401808060200182810382526025815260200180615bcc6025913960400191505060405180910390fd5b6000546001600160a01b031633148061389757506001546001600160a01b031633145b6138d25760405162461bcd60e51b8152600401808060200182810382526025815260200180615bcc6025913960400191505060405180910390fd5b600180546001600160a01b0319166001600160a01b03838116919091179182905560408051929091168252517f54841e992da2f7bcaa3127409f02e1849c79072740593c398d6670f65f995fa7916020908290030190a150565b6001600160801b031981166000908152600560209081526040918290208054835181840281018401909452808452606093928301828280156139ab57602002820191906000526020600020906000905b825461010083900a900460ff1681526020600192830181810494850194909303909202910180841161397c5790505b50505050509050919050565b6001546001600160a01b031681565b6001600160801b031981166000908152600260209081526040918290206003018054835181840281018401909452808452606093928301828280156139ab576000918252602091829020805460ff16845290820283019290916001910180841161397c575094979650505050505050565b600860209081526000928352604080842090915290825290205460ff1681565b60006c0581018202830384048505050560991b80600d60ff85160660ff16600d8110613a7f57fe5b1a9392505050565b6000613a99826001815181106123d757fe5b60ff16613aac836000815181106123d757fe5b60ff161480156118f45750505160021490565b606080613aca615b74565b506040805160c081018252600160808201818152604360f81b60a0840152825282518084018452818152601160fa1b6020828101919091528084019190915283518085018552828152600960fb1b81830152838501528351808501909452908352605360f81b908301526060810191909152613b44615b9b565b50604080516101e08101825260016101a08201818152604160f81b6101c0840152825282518084018452818152601960f91b6020828101919091528084019190915283518085018552828152603360f81b818301528385015283518085018552828152600d60fa1b81830152606084015283518085018552828152603560f81b81830152608084015283518085018552828152601b60f91b8183015260a084015283518085018552828152603760f81b8183015260c084015283518085018552828152600760fb1b8183015260e084015283518085018552828152603960f81b8183015261010084015283518085018552828152601560fa1b8183015261012084015283518085018552828152602560f91b8183015261014084015283518085018552828152605160f81b818301526101608401528351808501909452908352604b60f81b90830152610180810191909152600080613ca287612a61565b91509150838260ff1660048110613cb557fe5b6020020151838260ff16600d8110613cc957fe5b60200201519550955050505050915091565b6060613ce784836137b1565b613d1d576001600160a01b03831660009081526006602090815260408083206001600160801b0319881684529091529020613d4b565b6001600160a01b03831660009081526007602090815260408083206001600160801b03198816845290915290205b805480602002602001604051908101604052809291908181526020018280548015613db357602002820191906000526020600020906000905b825461010083900a900460ff16815260206001928301818104948501949093039092029101808411613d845790505b505050505090509392505050565b6001600160801b031983166000908152600260205260408120805460ff8516908110613de957fe5b60009182526020822001546001600160a01b03169150613e098584614f2b565b9050606080613e1783613abf565b915091506000613e2788886137b1565b613e5d576001600160a01b03851660009081526006602090815260408083206001600160801b03198c1684529091529020613e8b565b6001600160a01b03851660009081526007602090815260408083206001600160801b03198c16845290915290205b9050808490806001815401808255809150506001900390600052602060002090602091828204019190069091909190916101000a81548160ff021916908360ff1602179055507f9ba676ec758fab38fbc86eabb1315d0ba9ef270cbddd5e17ef84ae4e6ddf67fb88868987878760405180876001600160801b0319168152602001866001600160a01b031681526020018560ff1681526020018460ff1681526020018060200180602001838103835285818151815260200191508051906020019080838360005b83811015613f6a578181015183820152602001613f52565b50505050905090810190601f168015613f975780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b83811015613fca578181015183820152602001613fb2565b50505050905090810190601f168015613ff75780820380516001836020036101000a031916815260200191505b509850505050505050505060405180910390a15050505050505050565b600c5460408051630680429560e01b81526001600160a01b03888116600483015260248201889052868116604483015260648201869052608482018590529151919092169163068042959160a48083019260609291908290030181600087803b15801561408057600080fd5b505af1158015614094573d6000803e3d6000fd5b505050506040513d60608110156140aa57600080fd5b50505050505050565b6001600160801b031983166000908152600260205260409020600101805482919060ff85169081106140e157fe5b90600052602060002090600291828204019190066010026101000a8154816001600160801b0302191690836001600160801b03160217905550505050565b61412a848284613dc1565b600061413a61175b868685613cdb565b60ff1690507fba94a75104505ced25374f387d8a0bbc1e86fabb868da58dfa47769098c49ec1816040518082815260200191505060405180910390a16015811115614219576001600160801b03198516600090815260026020526040902060050180546004919060ff85169081106141ae57fe5b90600052602060002090602091828204019190066101000a81548160ff021916908360058111156141db57fe5b0217905550604080516001815290517fe096251939cfd59087f1f0ecb1190348aefec0a88f2b6b90bb1e41deb40e50dd9181900360200190a16142e4565b6001600160801b031985166000818152600560208181526040808420805460018101825590855282852083820401805460ff808b16601f9094166101000a848102910219909116179055948452600290915290912001805460039290811061427d57fe5b90600052602060002090602091828204019190066101000a81548160ff021916908360058111156142aa57fe5b0217905550604080516000815290517fe096251939cfd59087f1f0ecb1190348aefec0a88f2b6b90bb1e41deb40e50dd9181900360200190a15b5050505050565b6001600160801b031981166000908152600260205260408120600301905b60348160ff16101561435157815460018181018455600084815260209081902090830401805460ff808616601f9095166101000a948502940219169290921790915501614309565b50919050565b6001600160801b031982166000908152600260209081526040918290208054835181840281018401909452808452606093928301828280156143c257602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116143a4575b505050505090506143e983828460ff16815181106143dc57fe5b60200260200101516154ef565b6001600160801b031983166000908152600260205260408120600501805460ff851690811061441457fe5b90600052602060002090602091828204019190066101000a81548160ff0219169083600581111561444157fe5b0217905550505050565b6001600160801b031982166000908152600260208190526040822001805460ff841690811061447657fe5b6000918252602080832081830401546001600160801b031987168452600290915260408320805460ff601f9094166101000a909204831694509185169081106144bb57fe5b60009182526020808320909101546001600160801b03198716835260029091526040822060010180546001600160a01b0390921693509060ff86169081106144ff57fe5b6000918252602091829020600282040154600a54604080516371da23e960e01b815260ff89166004820152905160019094166010026101000a9092046001600160801b0316945084936001600160a01b03909116926371da23e9926024808201939291829003018186803b15801561457657600080fd5b505afa15801561458a573d6000803e3d6000fd5b505050506040513d60208110156145a057600080fd5b50516001600160801b031610156145b657600080fd5b600a54604080516341d4c74f60e01b815260ff861660048201526001600160a01b03858116602483015260448201859052915191909216916341d4c74f9160648083019260209291908290030181600087803b15801561461557600080fd5b505af1158015614629573d6000803e3d6000fd5b505050506040513d602081101561463f57600080fd5b50506040805160ff851681526001600160a01b038416602082015280820183905290517f65c4542a0147599e0783d3e59208f3bfffb745ae7d147bbe76da70b5676276719181900360600190a15050505050565b600061469f8383614f2b565b90506060806146ad83613abf565b6001600160801b031987166000818152600460209081526040808320805460018101825590845282842083820401805460ff808d16601f9094166101000a848102910219909116179055815194855284830152608090840181815286519185019190915285519597509395507f04a7c204b12e00b9aa84dc954cfe36f5d20da8bf730adc1aeee91f4573d878f5948a948994899489949193606085019260a086019290880191908190849084905b8381101561477357818101518382015260200161475b565b50505050905090810190601f1680156147a05780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b838110156147d35781810151838201526020016147bb565b50505050905090810190601f1680156148005780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390a15050505050565b6001600160801b0319821660009081526002602090815260409182902080548351818402810184019094528084526060939283018282801561488357602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311614865575b505050505090506148b36148ae84838560ff16815181106148a057fe5b602002602001015185613cdb565b6118d6565b1561491d576001600160801b031983166000818152600560208181526040808420805460018101825590855282852083820401805460ff808b16601f9094166101000a84810291021990911617905594845260029091529091208101805491929091811061441457fe5b505050565b6001600160801b0319871660009081526002602081905260408220600601805460ff191690911790555b60ff8116861115614a77576001600160801b031988166000908152600260208190526040909120018054614a27919060ff841690811061498857fe5b6000918252602080832081830401546001600160801b03198d16845260029091526040909220805460ff601f9093166101000a909304821692909185169081106149ce57fe5b6000918252602090912001546001600160a01b0316878760ff86168181106149f257fe5b905060200201356001600160801b03168a8a8660ff16818110614a1157fe5b905060200201356001600160801b0316016155b5565b614a6f888287878560ff16818110614a3b57fe5b905060200201356001600160801b031686868660ff16818110614a5a57fe5b905060200201356001600160801b0316615646565b60010161494c565b5050505050505050565b6000614a8d8683614f2b565b9050606080614a9b83613abf565b6001600160801b03198a166000818152600460209081526040808320805460018101825590845282842083820401805460ff808d16601f9094166101000a848102910219909116179055815194855284830152608090840181815286519185019190915285519597509395507faa37baae2614991b03161d6a3b49ae93b169ffe2e08a4b663e27c3993430eda2948d948994899489949193606085019260a086019290880191908190849084905b83811015614b61578181015183820152602001614b49565b50505050905090810190601f168015614b8e5780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b83811015614bc1578181015183820152602001614ba9565b50505050905090810190601f168015614bee5780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390a15050505050505050565b60005b815181101561491d576001600160801b0319831660009081526002602052604081208351849084908110614c3c57fe5b602002602001015160ff1681548110614c5157fe5b6000918252602090912001546001600160a01b0316905060056001600160801b031985166000908152600260205260409020600501805484908110614c9257fe5b90600052602060002090602091828204019190069054906101000a900460ff166005811115614cbd57fe5b1415614df3576001600160801b0319841660009081526002602052604081208451600190910190859085908110614cf057fe5b602002602001015160ff1681548110614d0557fe5b90600052602060002090600291828204019190066010029054906101000a90046001600160801b03169050614da560026000876001600160801b0319166001600160801b0319168152602001908152602001600020600201858581518110614d6957fe5b602002602001015160ff1681548110614d7e57fe5b90600052602060002090602091828204019190069054906101000a900460ff1683836155b5565b604080516001600160a01b03841681526001600160801b038316602082015281517fc3e855922420cdafb260e047f68ac02de87868df7bd1f28c27b9d9a4de43d1a8929181900390910190a1505b6001600160a01b03811660009081526008602090815260408083206001600160801b03198816845290915290205460ff16151560011415614f22576001600160801b0319841660009081526002602052604081208451600190910190859085908110614e5b57fe5b602002602001015160ff1681548110614e7057fe5b90600052602060002090600291828204019190066010029054906101000a90046001600160801b03169050614ed460026000876001600160801b0319166001600160801b0319168152602001908152602001600020600201858581518110614d6957fe5b604080516001600160a01b03841681526001600160801b038316602082015281517fbf2a3d4d8ec2feaa45dfd5779abcf977ed3565830ebb07bf7db66074d3182528929181900390910190a1505b50600101614c0c565b6001600160801b03198216600090815260026020526040812060030180548290614f5690859061585d565b90506000828281548110614f6657fe5b90600052602060002090602091828204019190069054906101000a900460ff16905082600184805490500381548110614f9b57fe5b90600052602060002090602091828204019190069054906101000a900460ff16838381548110614fc757fe5b90600052602060002090602091828204019190066101000a81548160ff021916908360ff16021790555082805480614ffb57fe5b6000828152602090819020600019909201908104909101805460ff601f84166101000a021916905590559250505092915050565b6001600160801b031984166000818152600460209081526040808320805460018101825590845282842083820401805460ff808b16601f9094166101000a8481029102199091161790558151948552848301526080908401818152865191850191909152855192937f04a7c204b12e00b9aa84dc954cfe36f5d20da8bf730adc1aeee91f4573d878f59389938993899389939092606084019160a08501918701908083838e5b838110156150ed5781810151838201526020016150d5565b50505050905090810190601f16801561511a5780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b8381101561514d578181015183820152602001615135565b50505050905090810190601f16801561517a5780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390a16001600160801b0319851660009081526004602090815260409182902080548351818402810184019094528084526151f99392830182828015612796576000918252602091829020805460ff16845290820283019290916001910180841161276757905050505050506123b3565b60ff1695945050505050565b60005b82518110156154e957600083828151811061521f57fe5b6020908102919091018101516001600160801b03198716600090815260029092526040822080549193509060ff841690811061525757fe5b60009182526020822001546001600160a01b0316915061527b61175b888486613cdb565b60ff169050600060056001600160801b031989166000908152600260205260409020600501805460ff87169081106152af57fe5b90600052602060002090602091828204019190069054906101000a900460ff1660058111156152da57fe5b1415615353576001600160801b03198816600090815260026020526040902060010180546064919060ff871690811061530f57fe5b90600052602060002090600291828204019190066010029054906101000a90046001600160801b031660fa026001600160801b03168161534b57fe5b049050615425565b858211156153c6576001600160801b03198816600090815260026020526040902060010180546064919060ff871690811061538a57fe5b90600052602060002090600291828204019190066010029054906101000a90046001600160801b031660c8026001600160801b03168161534b57fe5b85821415615425576001600160801b031988166000908152600260205260409020600101805460ff86169081106153f957fe5b90600052602060002090600291828204019190066010029054906101000a90046001600160801b031690505b6001600160801b038116156154d9576001600160801b03198816600090815260026020819052604090912001805461548c919060ff871690811061546557fe5b90600052602060002090602091828204019190069054906101000a900460ff1684836155b5565b604080516001600160a01b03851681526001600160801b038316602082015281517fc3e855922420cdafb260e047f68ac02de87868df7bd1f28c27b9d9a4de43d1a8929181900390910190a15b5050600190920191506152089050565b50505050565b6001600160a01b03811660009081526009602090815260408083206001600160801b03198616845290915281205460ff16600281111561552b57fe5b1480615572575060026001600160a01b03821660009081526009602090815260408083206001600160801b03198716845290915290205460ff16600281111561557057fe5b145b61557b57600080fd5b6001600160a01b031660009081526009602090815260408083206001600160801b031994909416835292905220805460ff19166001179055565b600a5460408051631894bcc960e11b815260ff861660048201526001600160a01b0385811660248301526001600160801b03851660448301529151919092169163312979929160648083019260209291908290030181600087803b15801561561c57600080fd5b505af1158015615630573d6000803e3d6000fd5b505050506040513d60208110156142e457600080fd5b6001600160801b03198416600090815260026020526040902060010180546001600160801b038416919060ff861690811061567d57fe5b6000918252602090912060028204015460019091166010026101000a90046001600160801b031610156156af57600080fd5b6001600160801b03198416600090815260026020526040902080546154e9919060ff86169081106156dc57fe5b60009182526020808320909101546001600160801b0319881683526002909152604090912060010180546001600160a01b039092169185919060ff881690811061572257fe5b90600052602060002090600291828204019190066010029054906101000a90046001600160801b0316036001600160801b0316600a60009054906101000a90046001600160a01b03166001600160a01b0316635ad3f918600260008a6001600160801b0319166001600160801b03191681526020019081526020016000206002018860ff16815481106157b157fe5b90600052602060002090602091828204019190069054906101000a900460ff166040518263ffffffff1660e01b8152600401808260ff16815260200191505060206040518083038186803b15801561580857600080fd5b505afa15801561581c573d6000803e3d6000fd5b505050506040513d602081101561583257600080fd5b50516001600160801b031988166000908152600260205260409020546001600160801b038616614014565b6040805160208082018590528183018490528251808303840181526060909201909252805191012060009082908161589157fe5b069392505050565b6040518060e0016040528060608152602001606081526020016060815260200160608152602001600060ff16815260200160608152602001600060028111156158de57fe5b905290565b828054828255906000526020600020908101928215615938579160200282015b8281111561593857825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190615903565b50615944929150615bb6565b5090565b828054828255906000526020600020906001016002900481019282156159385791602002820160005b838211156159bb57835183826101000a8154816001600160801b0302191690836001600160801b031602179055509260200192601001602081600f01049283019260010302615971565b80156159ee5782816101000a8154906001600160801b030219169055601001602081600f010492830192600103026159bb565b5050615944929150615bb6565b82805482825590600052602060002090601f016020900481019282156159385791602002820160005b83821115615a6257835183826101000a81548160ff021916908360ff1602179055509260200192600101602081600001049283019260010302615a24565b80156159ee5782816101000a81549060ff0219169055600101602081600001049283019260010302615a62565b82805482825590600052602060002090601f016020900481019282156159385791602002820160005b83821115615a6257835183826101000a81548160ff02191690836005811115615add57fe5b02179055509260200192600101602081600001049283019260010302615ab8565b50805460008255601f016020900490600052602060002090810190615b239190615bb6565b50565b82805482825590600052602060002090601f0160209004810192821561593857600052602060002091601f016020900482015b82811115615938578254825591600101919060010190615b59565b60405180608001604052806004905b6060815260200190600190039081615b835790505090565b604080516101a0810190915260608152600c60208201615b83565b5b808211156159445760008155600101615bb756fe416363657373436f6e74726f6c3a20696e76616c696420776f726b65722061646472657373416363657373436f6e74726f6c3a20696e76616c69642043454f2061646472657373416363657373436f6e74726f6c3a20776f726b6572206163636573732064656e696564416363657373436f6e74726f6c3a2063757272656e6c7479206e6f7420706175736564a26469706673582212208d7ac856226e6a88cfa7e20ff19bc575f9fe14c5fed798760768a3289122438564736f6c63430007040033