Contract Address Details

0x7E2e80c91CC7B71D6e8dED82F589D66F56B5e9a0

dgRoulette Last Balance Update: Block #11310731
Created by 0x1fcd–2c0f8a at 0xdc75–7966fd

Balance

0 MATIC

(@ /MATIC)

Fetching tokens...

Contract name:
dgRoulette




Optimization enabled
true
Compiler version
v0.7.5+commit.eb77ed08




Optimization runs
200
EVM Version
default

Constructor Arguments

000000000000000000000000bf79ce2fbd819e5abc2327563d02a200255b7cb30000000000000000000000000000000000000000000000000001c6bf52634000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000011e46db40d4438d1c64f68993ca43b03ac1b6a6b

Arg [0] (address) : 0xbf79ce2fbd819e5abc2327563d02a200255b7cb3
Arg [1] (uint128) : 500000000000000
Arg [2] (uint8) : 36
Arg [3] (address) : 0x11e46db40d4438d1c64f68993ca43b03ac1b6a6b

              

Contract source code

/**
* Submitted for verification at blockscout.com on 2020-12-06 15:26:41.506052Z
*/
// SPDX-License-Identifier: -- 🎲 --
pragma solidity ^0.7.5;
// Roulette Logic Contract ///////////////////////////////////////////////////////////
// Author: Decentral Games ([email protected]) ///////////////////////////////////////
// Roulette - MultiPlayer - TokenIndex 2.0
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, 'SafeMath: addition overflow');
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, 'SafeMath: subtraction overflow');
uint256 c = a - b;
return c;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, 'SafeMath: multiplication overflow');
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, 'SafeMath: division by zero');
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b != 0, 'SafeMath: modulo by zero');
return a % b;
}
}
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 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);
}
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 dgRoulette is AccessController {
using SafeMath for uint128;
using SafeMath for uint256;
uint256 private store;
enum BetType { Single, EvenOdd, RedBlack, HighLow, Column, Dozen }
mapping (address => uint) public totalBets;
mapping (address => uint) public totalPayout;
mapping (uint => uint) public maxSquareBets;
mapping (uint => mapping (uint => mapping (uint => uint))) public currentBets;
Bet[] public bets;
uint256[] winAmounts;
struct Bet {
address player;
uint8 betType;
uint8 number;
uint8 tokenIndex;
uint128 value;
}
event GameResult(
address[] _players,
uint8[] _tokenIndex,
uint256 indexed _landID,
uint256 indexed _number,
uint256 indexed _machineID,
uint256[] _winAmounts
);
TreasuryInstance public treasury;
PointerInstance public pointerContract;
constructor(
address _treasuryAddress,
uint128 _maxSquareBetDefault,
uint8 _maxNumberBets,
address _pointerAddress
) {
treasury = TreasuryInstance(_treasuryAddress);
store |= _maxNumberBets<<0;
store |= _maxSquareBetDefault<<8;
store |= block.timestamp<<136;
pointerContract = PointerInstance(_pointerAddress);
}
function addPoints(
address _player,
uint256 _points,
address _token,
uint256 _numPlayers,
uint256 _wearableBonus
)
private
{
pointerContract.addPoints(
_player,
_points,
_token,
_numPlayers,
_wearableBonus
);
}
function bet(
address _player,
uint8 _betType,
uint8 _number,
uint8 _tokenIndex,
uint128 _value
)
internal
{
currentBets[_tokenIndex][_betType][_number] += _value;
uint256 _maxSquareBet = maxSquareBets[_tokenIndex] == 0
? uint128(store>>8)
: maxSquareBets[_tokenIndex];
require(
currentBets[_tokenIndex][_betType][_number] <= _maxSquareBet,
'Roulette: exceeding maximum bet limit'
);
bets.push(Bet({
player: _player,
betType: _betType,
number: _number,
tokenIndex: _tokenIndex,
value: _value
}));
}
function _launch(
bytes32 _localhash,
address[] memory _players,
uint8[] memory _tokenIndex,
uint256 _landID,
uint256 _machineID
)
private
returns(
uint256[] memory,
uint256 number
)
{
require(block.timestamp > store>>136, 'Roulette: expired round');
require(bets.length > 0, 'Roulette: must have bets');
delete winAmounts;
store ^= (store>>136)<<136;
store |= block.timestamp<<136;
number = uint(
keccak256(
abi.encodePacked(_localhash)
)
) % 37;
for (uint i = 0; i < bets.length; i++) {
bool won = false;
Bet memory b = bets[i];
if (b.betType == uint(BetType.Single) && b.number == number) {
won = true;
} else if (b.betType == uint(BetType.EvenOdd) && number <= 36) {
if (number > 0 && number % 2 == b.number) {
won = true;
}
} else if (b.betType == uint(BetType.RedBlack) && b.number == 0) {
if ((number > 0 && number <= 10) || (number >= 19 && number <= 28)) {
won = (number % 2 == 1);
} else {
if (number > 0 && number <= 36) {
won = (number % 2 == 0);
}
}
} else if (b.betType == uint(BetType.RedBlack) && b.number == 1) {
if ((number > 0 && number <= 10) || (number >= 19 && number <= 28)) {
won = (number % 2 == 0);
} else {
if (number > 0 && number <= 36) {
won = (number % 2 == 1);
}
}
} else if (b.betType == uint(BetType.HighLow) && number <= 36) {
if (number >= 19 && b.number == 0) {
won = true;
}
if (number > 0 && number <= 18 && b.number == 1) {
won = true;
}
} else if (b.betType == uint(BetType.Column) && number <= 36) {
if (b.number == 0 && number > 0) won = (number % 3 == 1);
if (b.number == 1 && number > 0) won = (number % 3 == 2);
if (b.number == 2 && number > 0) won = (number % 3 == 0);
} else if (b.betType == uint(BetType.Dozen) && number <= 36) {
if (b.number == 0) won = (number > 0 && number <= 12);
if (b.number == 1) won = (number > 12 && number <= 24);
if (b.number == 2) won = (number > 24 && number <= 36);
}
if (won) {
uint256 betWin = b.value.mul(
getPayoutForType(b.betType, b.number)
);
winAmounts.push(betWin);
} else {
winAmounts.push(0);
}
currentBets[b.tokenIndex][b.betType][b.number] = 0;
}
delete bets;
emit GameResult(
_players,
_tokenIndex,
_landID,
number,
_machineID,
winAmounts
);
return(
winAmounts,
number
);
}
function play(
address[] memory _players,
uint256 _landID,
uint256 _machineID,
uint8[] memory _betIDs,
uint8[] memory _betValues,
uint128[] memory _betAmount,
bytes32 _localhash,
uint8[] memory _tokenIndex,
uint8 _playerCount,
uint8[] memory _wearableBonus
)
public
whenNotPaused
onlyWorker
{
require(
_betIDs.length == _betValues.length,
'Roulette: inconsistent amount of betsValues'
);
require(
_tokenIndex.length == _betAmount.length,
'Roulette: inconsistent amount of betAmount'
);
require(
_betValues.length == _tokenIndex.length,
'Roulette: inconsistent amount of tokenIndex'
);
require(
_betIDs.length <= uint8(store>>0),
'Roulette: maximum amount of bets reached'
);
/* treasury.consumeHash(
_localhash
);*/
bool[5] memory checkedTokens;
uint8 i;
for (i = 0; i < _betIDs.length; i++) {
require(
treasury.getMaximumBet(_tokenIndex[i]) >= _betAmount[i],
'Roulette: bet amount is more than maximum'
);
treasury.tokenInboundTransfer(
_tokenIndex[i],
_players[i],
_betAmount[i]
);
bet(
_players[i],
_betIDs[i],
_betValues[i],
_tokenIndex[i],
_betAmount[i]
);
if (!checkedTokens[_tokenIndex[i]]) {
uint256 tokenFunds = treasury.checkAllocatedTokens(_tokenIndex[i]);
require(
getNecessaryBalance(_tokenIndex[i]) <= tokenFunds,
'Roulette: not enough tokens for payout'
);
checkedTokens[_tokenIndex[i]] = true;
}
}
uint256 _spinResult;
(winAmounts, _spinResult) = _launch(
_localhash,
_players,
_tokenIndex,
_landID,
_machineID
);
// payout && points preparation
for (i = 0; i < winAmounts.length; i++) {
if (winAmounts[i] > 0) {
treasury.tokenOutboundTransfer(
_tokenIndex[i],
_players[i],
winAmounts[i]
);
// collecting totalPayout
totalPayout[_players[i]] =
totalPayout[_players[i]] + winAmounts[i];
}
totalBets[_players[i]] =
totalBets[_players[i]] + _betAmount[i];
}
// point calculation && bonus
for (i = 0; i < _players.length; i++) {
_issuePointsAmount(
_players[i],
_tokenIndex[i],
_playerCount,
_wearableBonus[i]
);
}
}
function _issuePointsAmount(
address _player,
uint8 _tokenIndex,
uint256 _playerCount,
uint256 _wearableBonus
) private {
if (totalPayout[_player] > totalBets[_player]) {
addPoints(
_player,
totalPayout[_player].sub(totalBets[_player]),
treasury.getTokenAddress(_tokenIndex),
_playerCount,
_wearableBonus
);
totalBets[_player] = 0;
totalPayout[_player] = 0;
}
else if (totalPayout[_player] < totalBets[_player]) {
addPoints(
_player,
totalBets[_player].sub(totalPayout[_player]),
treasury.getTokenAddress(_tokenIndex),
_playerCount,
_wearableBonus
);
totalBets[_player] = 0;
totalPayout[_player] = 0;
}
}
function getPayoutForType(
uint256 _betType,
uint256 _betNumber
)
public
pure
returns(uint256)
{
if (_betType == uint8(BetType.Single))
return _betNumber > 36 ? 0 : 36;
if (_betType == uint8(BetType.EvenOdd))
return _betNumber > 1 ? 0 : 2;
if (_betType == uint8(BetType.RedBlack))
return _betNumber > 1 ? 0 : 2;
if (_betType == uint8(BetType.HighLow))
return _betNumber > 1 ? 0 : 2;
if (_betType == uint8(BetType.Column))
return _betNumber > 2 ? 0 : 3;
if (_betType == uint8(BetType.Dozen))
return _betNumber > 2 ? 0 : 3;
return 0;
}
function getNecessaryBalance(
uint256 _tokenIndex
)
public
view
returns (uint256 _necessaryBalance)
{
uint256 _necessaryForBetType;
uint256[6] memory betTypesMax;
for (uint8 _i = 0; _i < bets.length; _i++) {
Bet memory b = bets[_i];
if (b.tokenIndex == _tokenIndex) {
uint256 _payout = getPayoutForType(b.betType, b.number);
uint256 _square = currentBets[b.tokenIndex][b.betType][b.number];
require(
_payout > 0,
'Roulette: incorrect bet type/value'
);
_necessaryForBetType = _square.mul(_payout);
if (_necessaryForBetType > betTypesMax[b.betType]) {
betTypesMax[b.betType] = _necessaryForBetType;
}
}
}
for (uint8 _i = 0; _i < betTypesMax.length; _i++) {
_necessaryBalance = _necessaryBalance.add(
betTypesMax[_i]
);
}
}
function getBetsCountAndValue()
external
view
returns(uint value, uint)
{
for (uint i = 0; i < bets.length; i++) {
value += bets[i].value;
}
return (bets.length, value);
}
function getBetsCount()
external
view
returns (uint256)
{
return bets.length;
}
function changeMaxSquareBet(
uint256 _tokenIndex,
uint256 _newMaxSquareBet
)
external
onlyCEO
{
maxSquareBets[_tokenIndex] = _newMaxSquareBet;
}
function changeMaxSquareBetDefault(
uint128 _newMaxSquareBetDefault
)
external
onlyCEO
{
store ^= uint128((store>>8))<<8;
store |= _newMaxSquareBetDefault<<8;
}
function changeMaximumBetAmount(
uint8 _newMaximumBetAmount
)
external
onlyCEO
{
store ^= uint8(store)<<0;
store |= _newMaximumBetAmount<<0;
}
function changeTreasury(
address _newTreasuryAddress
)
external
onlyCEO
{
treasury = TreasuryInstance(
_newTreasuryAddress
);
}
function getNextRoundTimestamp()
external
view
returns(uint)
{
return store>>136;
}
function checkMaximumBetAmount()
external
view
returns (uint8)
{
return uint8(store>>0);
}
function checkMaxSquareBetDefault()
external
view
returns (uint128)
{
return uint128(store>>8);
}
function updatePointer(
address _newPointerAddress
)
external
onlyCEO
{
pointerContract = PointerInstance(
_newPointerAddress
);
}
}

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_treasuryAddress","internalType":"address"},{"type":"uint128","name":"_maxSquareBetDefault","internalType":"uint128"},{"type":"uint8","name":"_maxNumberBets","internalType":"uint8"},{"type":"address","name":"_pointerAddress","internalType":"address"}]},{"type":"event","name":"CEOSet","inputs":[{"type":"address","name":"newCEO","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"GameResult","inputs":[{"type":"address[]","name":"_players","internalType":"address[]","indexed":false},{"type":"uint8[]","name":"_tokenIndex","internalType":"uint8[]","indexed":false},{"type":"uint256","name":"_landID","internalType":"uint256","indexed":true},{"type":"uint256","name":"_number","internalType":"uint256","indexed":true},{"type":"uint256","name":"_machineID","internalType":"uint256","indexed":true},{"type":"uint256[]","name":"_winAmounts","internalType":"uint256[]","indexed":false}],"anonymous":false},{"type":"event","name":"Paused","inputs":[],"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":"function","stateMutability":"view","outputs":[{"type":"address","name":"player","internalType":"address"},{"type":"uint8","name":"betType","internalType":"uint8"},{"type":"uint8","name":"number","internalType":"uint8"},{"type":"uint8","name":"tokenIndex","internalType":"uint8"},{"type":"uint128","name":"value","internalType":"uint128"}],"name":"bets","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"ceoAddress","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"changeMaxSquareBet","inputs":[{"type":"uint256","name":"_tokenIndex","internalType":"uint256"},{"type":"uint256","name":"_newMaxSquareBet","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"changeMaxSquareBetDefault","inputs":[{"type":"uint128","name":"_newMaxSquareBetDefault","internalType":"uint128"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"changeMaximumBetAmount","inputs":[{"type":"uint8","name":"_newMaximumBetAmount","internalType":"uint8"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"changeTreasury","inputs":[{"type":"address","name":"_newTreasuryAddress","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint128","name":"","internalType":"uint128"}],"name":"checkMaxSquareBetDefault","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"checkMaximumBetAmount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"currentBets","inputs":[{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getBetsCount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"value","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"}],"name":"getBetsCountAndValue","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"_necessaryBalance","internalType":"uint256"}],"name":"getNecessaryBalance","inputs":[{"type":"uint256","name":"_tokenIndex","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getNextRoundTimestamp","inputs":[]},{"type":"function","stateMutability":"pure","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getPayoutForType","inputs":[{"type":"uint256","name":"_betType","internalType":"uint256"},{"type":"uint256","name":"_betNumber","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"maxSquareBets","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"pause","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"paused","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"play","inputs":[{"type":"address[]","name":"_players","internalType":"address[]"},{"type":"uint256","name":"_landID","internalType":"uint256"},{"type":"uint256","name":"_machineID","internalType":"uint256"},{"type":"uint8[]","name":"_betIDs","internalType":"uint8[]"},{"type":"uint8[]","name":"_betValues","internalType":"uint8[]"},{"type":"uint128[]","name":"_betAmount","internalType":"uint128[]"},{"type":"bytes32","name":"_localhash","internalType":"bytes32"},{"type":"uint8[]","name":"_tokenIndex","internalType":"uint8[]"},{"type":"uint8","name":"_playerCount","internalType":"uint8"},{"type":"uint8[]","name":"_wearableBonus","internalType":"uint8[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract PointerInstance"}],"name":"pointerContract","inputs":[]},{"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":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalBets","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalPayout","inputs":[{"type":"address","name":"","internalType":"address"}]},{"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":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"workerAddress","inputs":[]}]
            

Contract Byte Code

0x608060405234801561001057600080fd5b50600436106101a95760003560e01c806361d027b3116100f9578063bde0489011610097578063cbd88f4811610071578063cbd88f48146107b8578063dca4d1a5146107c0578063dcdfe3e8146107dd578063ef37cfe9146107fb576101a9565b8063bde0489014610743578063c26f6d441461076c578063ca43134114610792576101a9565b80638456cb59116100d35780638456cb59146107055780638c7e347a1461070d578063b14f2a3914610715578063b633b2ab1461073b576101a9565b806361d027b3146106c0578063625c3a5f146106c85780636a5f3d5e146106e8576101a9565b80633a7c48d61161016657806350bfba991161014057806350bfba9914610653578063524b1bbf1461065b5780635c975abb1461067e5780635ccc53021461069a576101a9565b80633a7c48d6146102dc5780633f4ba83a1461030057806342fc40c214610308576101a9565b80630a0f8168146101ae5780630ab5cb64146101d257806322af00fa1461020a57806327d7874c1461026b57806329dd3c9c146102935780633025d9e2146102b6575b600080fd5b6101b661081c565b604080516001600160a01b039092168252519081900360200190f35b6101f8600480360360208110156101e857600080fd5b50356001600160a01b031661082b565b60408051918252519081900360200190f35b6102276004803603602081101561022057600080fd5b503561083d565b604080516001600160a01b03909616865260ff948516602087015292841685840152921660608401526001600160801b039091166080830152519081900360a00190f35b6102916004803603602081101561028157600080fd5b50356001600160a01b031661089f565b005b6101f8600480360360408110156102a957600080fd5b508035906020013561098b565b610291600480360360208110156102cc57600080fd5b50356001600160a01b0316610a30565b6102e4610a9f565b604080516001600160801b039092168252519081900360200190f35b610291610aa8565b610291600480360361014081101561031f57600080fd5b810190602081018135600160201b81111561033957600080fd5b82018360208201111561034b57600080fd5b803590602001918460208302840111600160201b8311171561036c57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295843595602086013595919450925060608101915060400135600160201b8111156103c757600080fd5b8201836020820111156103d957600080fd5b803590602001918460208302840111600160201b831117156103fa57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b81111561044957600080fd5b82018360208201111561045b57600080fd5b803590602001918460208302840111600160201b8311171561047c57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b8111156104cb57600080fd5b8201836020820111156104dd57600080fd5b803590602001918460208302840111600160201b831117156104fe57600080fd5b91908080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525092958435959094909350604081019250602001359050600160201b81111561055557600080fd5b82018360208201111561056757600080fd5b803590602001918460208302840111600160201b8311171561058857600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929560ff853516959094909350604081019250602001359050600160201b8111156105e257600080fd5b8201836020820111156105f457600080fd5b803590602001918460208302840111600160201b8311171561061557600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550610b75945050505050565b6101b66113f4565b6102916004803603604081101561067157600080fd5b5080359060200135611403565b610686611462565b604080519115158252519081900360200190f35b610291600480360360208110156106b057600080fd5b50356001600160801b0316611472565b6101b66114e9565b610291600480360360208110156106de57600080fd5b503560ff166114f8565b6101f8600480360360208110156106fe57600080fd5b503561155a565b610291611729565b6101f861180f565b6102916004803603602081101561072b57600080fd5b50356001600160a01b0316611815565b6101f8611884565b6101f86004803603606081101561075957600080fd5b508035906020810135906040013561188d565b6102916004803603602081101561078257600080fd5b50356001600160a01b03166118b0565b6101f8600480360360208110156107a857600080fd5b50356001600160a01b03166119ad565b6101b66119bf565b6101f8600480360360208110156107d657600080fd5b50356119ce565b6107e56119e0565b6040805160ff9092168252519081900360200190f35b6108036119e6565b6040805192835260208301919091528051918290030190f35b6000546001600160a01b031681565b60036020526000908152604090205481565b6007818154811061084d57600080fd5b6000918252602090912060029091020180546001909101546001600160a01b038216925060ff600160a01b8304811692600160a81b8104821692600160b01b909104909116906001600160801b031685565b6000546001600160a01b031633146108ec576040805162461bcd60e51b81526020600482018190526024820152600080516020612882833981519152604482015290519081900360640190fd5b6001600160a01b0381166109315760405162461bcd60e51b81526004018080602001828103825260228152602001806128a26022913960400191505060405180910390fd5b600080546001600160a01b0319166001600160a01b03838116919091179182905560408051929091168252517ff97cbb4246b709036319093e5ff31674b9f6759076d153e1bea1f60392170fc0916020908290030190a150565b6000826109ae57602482116109a15760246109a4565b60005b60ff169050610a2a565b60018314156109c657600182116109a15760026109a4565b60028314156109de57600182116109a15760026109a4565b60038314156109f657600182116109a15760026109a4565b6004831415610a0e57600282116109a15760036109a4565b6005831415610a2657600282116109a15760036109a4565b5060005b92915050565b6000546001600160a01b03163314610a7d576040805162461bcd60e51b81526020600482018190526024820152600080516020612882833981519152604482015290519081900360640190fd5b600a80546001600160a01b0319166001600160a01b0392909216919091179055565b60025460081c90565b6000546001600160a01b03163314610af5576040805162461bcd60e51b81526020600482018190526024820152600080516020612882833981519152604482015290519081900360640190fd5b600154600160a01b900460ff16610b3d5760405162461bcd60e51b81526004018080602001828103825260238152602001806129316023913960400191505060405180910390fd5b6001805460ff60a01b191690556040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d1693390600090a1565b600154600160a01b900460ff1615610bd4576040805162461bcd60e51b815260206004820152601f60248201527f416363657373436f6e74726f6c3a2063757272656e746c792070617573656400604482015290519081900360640190fd5b6001546001600160a01b03163314610c1d5760405162461bcd60e51b81526004018080602001828103825260238152602001806128c46023913960400191505060405180910390fd5b8551875114610c5d5760405162461bcd60e51b815260040180806020018281038252602b815260200180612857602b913960400191505060405180910390fd5b8451835114610c9d5760405162461bcd60e51b815260040180806020018281038252602a81526020018061282d602a913960400191505060405180910390fd5b8251865114610cdd5760405162461bcd60e51b815260040180806020018281038252602b815260200180612802602b913960400191505060405180910390fd5b6000600254901c60ff1687511115610d265760405162461bcd60e51b81526004018080602001828103825260288152602001806129796028913960400191505060405180910390fd5b610d2e612657565b60005b88518160ff16101561110257868160ff1681518110610d4c57fe5b60200260200101516001600160801b0316600960009054906101000a90046001600160a01b03166001600160a01b03166371da23e9878460ff1681518110610d9057fe5b60200260200101516040518263ffffffff1660e01b8152600401808260ff16815260200191505060206040518083038186803b158015610dcf57600080fd5b505afa158015610de3573d6000803e3d6000fd5b505050506040513d6020811015610df957600080fd5b50516001600160801b03161015610e415760405162461bcd60e51b81526004018080602001828103825260298152602001806129086029913960400191505060405180910390fd5b60095485516001600160a01b03909116906341d4c74f90879060ff8516908110610e6757fe5b60200260200101518e8460ff1681518110610e7e57fe5b60200260200101518a8560ff1681518110610e9557fe5b60200260200101516040518463ffffffff1660e01b8152600401808460ff168152602001836001600160a01b03168152602001826001600160801b031681526020019350505050602060405180830381600087803b158015610ef657600080fd5b505af1158015610f0a573d6000803e3d6000fd5b505050506040513d6020811015610f2057600080fd5b50508b51610fa0908d9060ff8416908110610f3757fe5b60200260200101518a8360ff1681518110610f4e57fe5b60200260200101518a8460ff1681518110610f6557fe5b6020026020010151888560ff1681518110610f7c57fe5b60200260200101518b8660ff1681518110610f9357fe5b6020026020010151611a34565b81858260ff1681518110610fb057fe5b602002602001015160ff1660058110610fc557fe5b60200201516110fa5760095485516000916001600160a01b03169063c70620b590889060ff8616908110610ff557fe5b60200260200101516040518263ffffffff1660e01b8152600401808260ff16815260200191505060206040518083038186803b15801561103457600080fd5b505afa158015611048573d6000803e3d6000fd5b505050506040513d602081101561105e57600080fd5b50518651909150819061108a90889060ff861690811061107a57fe5b602002602001015160ff1661155a565b11156110c75760405162461bcd60e51b81526004018080602001828103825260268152602001806127ba6026913960400191505060405180910390fd5b600183878460ff16815181106110d957fe5b602002602001015160ff16600581106110ee57fe5b91151560209092020152505b600101610d31565b6000611111878e888f8f611c33565b81519092508290611129906008906020850190612675565b505050600091505b60085460ff8316101561137557600060088360ff168154811061115057fe5b906000526020600020015411156112d65760095486516001600160a01b0390911690633129799290889060ff861690811061118757fe5b60200260200101518f8560ff168151811061119e57fe5b602002602001015160088660ff16815481106111b657fe5b90600052602060002001546040518463ffffffff1660e01b8152600401808460ff168152602001836001600160a01b031681526020018281526020019350505050602060405180830381600087803b15801561121157600080fd5b505af1158015611225573d6000803e3d6000fd5b505050506040513d602081101561123b57600080fd5b50506008805460ff841690811061124e57fe5b9060005260206000200154600460008f8560ff168151811061126c57fe5b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205401600460008f8560ff16815181106112a957fe5b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020819055505b878260ff16815181106112e557fe5b60200260200101516001600160801b0316600360008f8560ff168151811061130957fe5b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205401600360008f8560ff168151811061134657fe5b6020908102919091018101516001600160a01b0316825281019190915260400160002055600190910190611131565b600091505b8c518260ff1610156113e5576113da8d8360ff168151811061139857fe5b6020026020010151878460ff16815181106113af57fe5b60200260200101518760ff16878660ff16815181106113ca57fe5b602002602001015160ff1661230a565b60019091019061137a565b50505050505050505050505050565b600a546001600160a01b031681565b6000546001600160a01b03163314611450576040805162461bcd60e51b81526020600482018190526024820152600080516020612882833981519152604482015290519081900360640190fd5b60009182526005602052604090912055565b600154600160a01b900460ff1681565b6000546001600160a01b031633146114bf576040805162461bcd60e51b81526020600482018190526024820152600080516020612882833981519152604482015290519081900360640190fd5b600280546fffffffffffffffffffffffffffffff0080821690911860089390931b16919091179055565b6009546001600160a01b031681565b6000546001600160a01b03163314611545576040805162461bcd60e51b81526020600482018190526024820152600080516020612882833981519152604482015290519081900360640190fd5b6002805460ff92831692811618919091179055565b6000806115656126c0565b60005b60075460ff821610156116e95761157d6126de565b60078260ff168154811061158d57fe5b60009182526020918290206040805160a081018252600290930290910180546001600160a01b038116845260ff600160a01b8204811695850195909552600160a81b8104851692840192909252600160b01b909104909216606082018190526001909201546001600160801b0316608082015291508614156116e0576000611623826020015160ff16836040015160ff1661098b565b606083015160ff9081166000908152600660209081526040808320828801518516845282528083208188015190941683529290522054909150816116985760405162461bcd60e51b81526004018080602001828103825260228152602001806127e06022913960400191505060405180910390fd5b6116a281836124a1565b955084836020015160ff16600681106116b757fe5b60200201518611156116dd578585846020015160ff16600681106116d757fe5b60200201525b50505b50600101611568565b5060005b60068160ff16101561172157611717828260ff166006811061170b57fe5b60200201518590612501565b93506001016116ed565b505050919050565b6001546001600160a01b031633146117725760405162461bcd60e51b81526004018080602001828103825260238152602001806128c46023913960400191505060405180910390fd5b600154600160a01b900460ff16156117d1576040805162461bcd60e51b815260206004820152601f60248201527f416363657373436f6e74726f6c3a2063757272656e746c792070617573656400604482015290519081900360640190fd5b6001805460ff60a01b1916600160a01b1790556040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e75290600090a1565b60075490565b6000546001600160a01b03163314611862576040805162461bcd60e51b81526020600482018190526024820152600080516020612882833981519152604482015290519081900360640190fd5b600980546001600160a01b0319166001600160a01b0392909216919091179055565b60025460881c90565b600660209081526000938452604080852082529284528284209052825290205481565b6001600160a01b0381166118f55760405162461bcd60e51b81526004018080602001828103825260258152602001806127956025913960400191505060405180910390fd5b6000546001600160a01b031633148061191857506001546001600160a01b031633145b6119535760405162461bcd60e51b81526004018080602001828103825260258152602001806127956025913960400191505060405180910390fd5b600180546001600160a01b0319166001600160a01b03838116919091179182905560408051929091168252517f54841e992da2f7bcaa3127409f02e1849c79072740593c398d6670f65f995fa7916020908290030190a150565b60046020526000908152604090205481565b6001546001600160a01b031681565b60056020526000908152604090205481565b60025490565b60008060005b600754811015611a2c5760078181548110611a0357fe5b6000918252602090912060016002909202018101546001600160801b03169390930192016119ec565b505060075491565b60ff808316600081815260066020908152604080832089861684528252808320948816835293815283822080546001600160801b03871601905591815260059091529081205415611a975760ff8316600090815260056020526040902054611aa8565b6008600254901c6001600160801b03165b60ff80851660009081526006602090815260408083208a85168452825280832093891683529290522054909150811015611b135760405162461bcd60e51b81526004018080602001828103825260258152602001806129546025913960400191505060405180910390fd5b506040805160a0810182526001600160a01b03968716815260ff95861660208201908152948616918101918252928516606084019081526001600160801b03928316608085019081526007805460018101825560009190915294517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600290960295860180549751945193516001600160a01b0319909816919099161760ff60a01b1916600160a01b938816939093029290921760ff60a81b1916600160a81b918716919091021760ff60b01b1916600160b01b949095169390930293909317909355517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68990920180546001600160801b03191692909116919091179055565b606060006088600254901c4211611c91576040805162461bcd60e51b815260206004820152601760248201527f526f756c657474653a206578706972656420726f756e64000000000000000000604482015290519081900360640190fd5b600754611ce5576040805162461bcd60e51b815260206004820152601860248201527f526f756c657474653a206d757374206861766520626574730000000000000000604482015290519081900360640190fd5b611cf16008600061270c565b6002805470ffffffffffffffffffffffffffffffffff198116184260881b1790556040805160208082018a9052825180830382018152918301909252805191012060259006905060005b600754811015612195576000611d4f6126de565b60078381548110611d5c57fe5b60009182526020918290206040805160a08101825260029390930290910180546001600160a01b038116845260ff600160a01b82048116958501869052600160a81b8204811693850193909352600160b01b90049091166060830152600101546001600160801b031660808201529150158015611ddf575083816040015160ff16145b15611ded57600191506120b1565b6001816020015160ff16148015611e05575060248411155b15611e3257600084118015611e235750604081015160ff1660028506145b15611e2d57600191505b6120b1565b6002816020015160ff16148015611e4e5750604081015160ff16155b15611eb257600084118015611e645750600a8411155b80611e7c575060138410158015611e7c5750601c8411155b15611e8f57600284066001149150611e2d565b600084118015611ea0575060248411155b15611e2d576002845b061591506120b1565b6002816020015160ff16148015611ed05750806040015160ff166001145b15611f3357600084118015611ee65750600a8411155b80611efe575060138410158015611efe5750601c8411155b15611f0f5760028406159150611e2d565b600084118015611f20575060248411155b15611e2d576002840660011491506120b1565b6003816020015160ff16148015611f4b575060248411155b15611fa15760138410158015611f665750604081015160ff16155b15611f7057600191505b600084118015611f81575060128411155b8015611e235750806040015160ff1660011415611e2d57600191506120b1565b6004816020015160ff16148015611fb9575060248411155b1561202c57604081015160ff16158015611fd35750600084115b15611fe2576003840660011491505b806040015160ff166001148015611ff95750600084115b15612008576003840660021491505b806040015160ff16600214801561201f5750600084115b15611e2d57600384611ea9565b6005816020015160ff16148015612044575060248411155b156120b157604081015160ff16612069576000841180156120665750600c8411155b91505b806040015160ff166001141561208d57600c8411801561208a575060188411155b91505b806040015160ff16600214156120b1576018841180156120ae575060248411155b91505b81156121215760006120e86120d4836020015160ff16846040015160ff1661098b565b60808401516001600160801b0316906124a1565b600880546001810182556000919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee3015550612154565b6008805460018101825560009182527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee301555b606081015160ff9081166000908152600660209081526040808320828601518516845282528083209481015190931682529290925281205550600101611d3b565b506121a26007600061272d565b8281857f9623f640ae1546f2effbb27dd873d724cabc8e76b7df25287c07fcee7b30cf418989600860405180806020018060200180602001848103845287818151815260200191508051906020019060200280838360005b838110156122125781810151838201526020016121fa565b50505050905001848103835286818151815260200191508051906020019060200280838360005b83811015612251578181015183820152602001612239565b50505050905001848103825285818154815260200191508054801561229557602002820191906000526020600020905b815481526020019060010190808311612281575b5050965050505050505060405180910390a4600881818054806020026020016040519081016040528092919081815260200182805480156122f557602002820191906000526020600020905b8154815260200190600101908083116122e1575b50505050509150915091509550959350505050565b6001600160a01b0384166000908152600360209081526040808320546004909252909120541115612415576001600160a01b0384166000908152600360209081526040808320546004909252909120546123ea9186916123699161255b565b60095460408051630b5a7f2360e31b815260ff8916600482015290516001600160a01b0390921691635ad3f91891602480820192602092909190829003018186803b1580156123b757600080fd5b505afa1580156123cb573d6000803e3d6000fd5b505050506040513d60208110156123e157600080fd5b505185856125b8565b6001600160a01b0384166000908152600360209081526040808320839055600490915281205561249b565b6001600160a01b038416600090815260036020908152604080832054600490925290912054101561249b576001600160a01b0384166000908152600460209081526040808320546003909252909120546124749186916123699161255b565b6001600160a01b038416600090815260036020908152604080832083905560049091528120555b50505050565b6000826124b057506000610a2a565b828202828482816124bd57fe5b04146124fa5760405162461bcd60e51b81526004018080602001828103825260218152602001806128e76021913960400191505060405180910390fd5b9392505050565b6000828201838110156124fa576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000828211156125b2576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b600a5460408051630680429560e01b81526001600160a01b03888116600483015260248201889052868116604483015260648201869052608482018590529151919092169163068042959160a48083019260609291908290030181600087803b15801561262457600080fd5b505af1158015612638573d6000803e3d6000fd5b505050506040513d606081101561264e57600080fd5b50505050505050565b6040518060a001604052806005906020820280368337509192915050565b8280548282559060005260206000209081019282156126b0579160200282015b828111156126b0578251825591602001919060010190612695565b506126bc92915061274e565b5090565b6040518060c001604052806006906020820280368337509192915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915290565b508054600082559060005260206000209081019061272a919061274e565b50565b508054600082556002029060005260206000209081019061272a9190612763565b5b808211156126bc576000815560010161274f565b5b808211156126bc5780546001600160b81b03191681556001810180546001600160801b031916905560020161276456fe416363657373436f6e74726f6c3a20696e76616c696420776f726b65722061646472657373526f756c657474653a206e6f7420656e6f75676820746f6b656e7320666f72207061796f7574526f756c657474653a20696e636f72726563742062657420747970652f76616c7565526f756c657474653a20696e636f6e73697374656e7420616d6f756e74206f6620746f6b656e496e646578526f756c657474653a20696e636f6e73697374656e7420616d6f756e74206f6620626574416d6f756e74526f756c657474653a20696e636f6e73697374656e7420616d6f756e74206f66206265747356616c756573416363657373436f6e74726f6c3a2043454f206163636573732064656e696564416363657373436f6e74726f6c3a20696e76616c69642043454f2061646472657373416363657373436f6e74726f6c3a20776f726b6572206163636573732064656e696564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77526f756c657474653a2062657420616d6f756e74206973206d6f7265207468616e206d6178696d756d416363657373436f6e74726f6c3a2063757272656e6c7479206e6f7420706175736564526f756c657474653a20657863656564696e67206d6178696d756d20626574206c696d6974526f756c657474653a206d6178696d756d20616d6f756e74206f6620626574732072656163686564a2646970667358221220de30dc1d53eea0428369b756076c18e93bdfd4f400d3f08f609f08f4769344a164736f6c63430007050033