⚠️ ⚠️ ⚠️ This explorer will be deprecated soon, please use PolygonScan.com

Contract Address Details

0x10743046a484c5987e2cb2856aC3438Cf0FDeF3a

dgBackgammon Last Balance Update: Block #15678775
Created by 0x1fcde1–2c0f8a at 0x06ea39–315d0a

Balance

0 MATIC

(@ /MATIC)

Fetching tokens...

Contract name:
dgBackgammon




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




Optimization runs
200
EVM Version
default

Constructor Arguments

0000000000000000000000008562746aeab494b29394577f15e865d45f3143810000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000085697947b9bac8926bfa1e265a220436e8d0ee84

Arg [0] (address) : 0x8562746aeab494b29394577f15e865d45f314381
Arg [1] (uint8) : 32
Arg [2] (uint8) : 10
Arg [3] (address) : 0x85697947b9bac8926bfa1e265a220436e8d0ee84

              

Contract source code

/**
* Submitted for verification at blockscout.com on 2020-10-29 10:50:20.516552Z
*/
// SPDX-License-Identifier: -- 🎲 --
pragma solidity ^0.7.4;
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 dgBackgammon is AccessController {
using SafeMath for uint128;
using SafeMath for uint256;
enum GameState {NewGame, OnGoingGame, DoublingStage, GameEnded}
event GameStarted(
uint256 gameId,
address indexed playerOne,
address indexed playerTwo,
uint8 tokenIndex
);
event StakeRaised(
uint256 gameId,
address indexed player,
uint256 stake
);
event StakeDoubled(
uint256 gameId,
address indexed player,
uint256 totalStaked
);
event PlayerDropped(
uint256 gameId,
address indexed player
);
event GameResolved(
uint256 gameId,
address indexed winner
);
struct Game {
uint256 stake;
uint256 total;
address playerOne;
address playerTwo;
address lastStaker;
uint8 tokenIndex;
GameState state;
}
mapping(uint256 => Game) public currentGames;
modifier onlyDoublingStage(uint256 gameId) {
require(
currentGames[gameId].state == GameState.DoublingStage,
'must be proposed to double first by one of the players'
);
_;
}
modifier onlyOnGoingGame(uint256 gameId) {
require(
currentGames[gameId].state == GameState.OnGoingGame,
'must be ongoing game'
);
_;
}
modifier isPlayerInGame(uint256 gameId, address player) {
require(
player == currentGames[gameId].playerOne ||
player == currentGames[gameId].playerTwo,
'must be one of the players'
);
_;
}
modifier onlyTreasury() {
require(
msg.sender == address(treasury),
'must be current treasury'
);
_;
}
TreasuryInstance public treasury;
PointerInstance public pointerContract;
struct Store {
uint8 safeFactor;
uint8 feePercent;
}
Store public s;
constructor(
address _treasuryAddress,
uint8 _safeFactor,
uint8 _feePercent,
address _pointerAddress
)
{
treasury = TreasuryInstance(
_treasuryAddress
);
pointerContract = PointerInstance(
_pointerAddress
);
(s.safeFactor, s.feePercent) = (_safeFactor, _feePercent);
}
function initializeGame(
uint128 _defaultStake,
address _playerOneAddress,
address _playerTwoAddress,
uint8 _tokenIndex
)
external
whenNotPaused
onlyWorker
returns (bool)
{
require(
address(_playerOneAddress) != address(_playerTwoAddress),
'must be two different players'
);
uint256 gameId = uint256(
keccak256(
abi.encodePacked(
_playerOneAddress,
_playerTwoAddress
)
)
);
require(
_defaultStake.mul(s.safeFactor) <= treasury.checkApproval(
_playerOneAddress, _tokenIndex
),
'P1 must approve/allow treasury as spender'
);
require(
_defaultStake.mul(s.safeFactor) <= treasury.checkApproval(
_playerTwoAddress, _tokenIndex
),
'P2 must approve/allow treasury as spender'
);
require(
currentGames[gameId].state == GameState.NewGame ||
currentGames[gameId].state == GameState.GameEnded,
'cannot initialize running game'
);
require(
treasury.getTokenAddress(_tokenIndex) != address(0x0),
'token is not delcared in treasury!'
);
require(
_defaultStake <= treasury.getMaximumBet(_tokenIndex),
'exceeding maximum bet defined in treasury'
);
treasury.tokenInboundTransfer(
_tokenIndex,
_playerOneAddress,
_defaultStake
);
treasury.tokenInboundTransfer(
_tokenIndex,
_playerTwoAddress,
_defaultStake
);
Game memory _game = Game(
_defaultStake,
_defaultStake.mul(2),
_playerOneAddress,
_playerTwoAddress,
address(0),
_tokenIndex,
GameState.OnGoingGame
);
currentGames[gameId] = _game;
emit GameStarted(
gameId,
_playerOneAddress,
_playerTwoAddress,
_tokenIndex
);
return true;
}
function raiseDouble(
uint256 _gameId,
address _playerRaising
)
external
whenNotPaused
onlyWorker
onlyOnGoingGame(_gameId)
isPlayerInGame(_gameId, _playerRaising)
{
require(
address(_playerRaising) !=
address(currentGames[_gameId].lastStaker),
'same player cannot raise double again'
);
require(
treasury.tokenInboundTransfer(
currentGames[_gameId].tokenIndex,
_playerRaising,
currentGames[_gameId].stake
),
'raising double transfer failed'
);
currentGames[_gameId].state = GameState.DoublingStage;
currentGames[_gameId].lastStaker = _playerRaising;
currentGames[_gameId].total = currentGames[_gameId].total.add(
currentGames[_gameId].stake
);
emit StakeRaised(
_gameId,
_playerRaising,
currentGames[_gameId].total
);
}
function callDouble(uint256 _gameId, address _playerCalling)
external
whenNotPaused
onlyWorker
onlyDoublingStage(_gameId)
isPlayerInGame(_gameId, _playerCalling)
{
require(
address(_playerCalling) !=
address(currentGames[_gameId].lastStaker),
'call must come from opposite player who doubled'
);
require(
treasury.tokenInboundTransfer(
currentGames[_gameId].tokenIndex,
_playerCalling,
currentGames[_gameId].stake
),
'calling double transfer failed'
);
currentGames[_gameId].total =
currentGames[_gameId].total.add(currentGames[_gameId].stake);
currentGames[_gameId].stake =
currentGames[_gameId].stake.mul(2);
currentGames[_gameId].state = GameState.OnGoingGame;
emit StakeDoubled(
_gameId,
_playerCalling,
currentGames[_gameId].total
);
}
function dropGame(
uint256 _gameId,
address _playerDropping,
uint256 _playerOneWearableBonus,
uint256 _playerTwoWearableBonus
)
external
whenNotPaused
onlyWorker
onlyDoublingStage(_gameId)
isPlayerInGame(_gameId, _playerDropping)
{
require(
_playerDropping != currentGames[_gameId].lastStaker,
'drop must come from opposite player who doubled'
);
require(
treasury.tokenOutboundTransfer(
currentGames[_gameId].tokenIndex,
currentGames[_gameId].lastStaker,
applyPercent(currentGames[_gameId].total)
),
'win amount transfer failed (dropGame)'
);
applyPoints(
_gameId,
_playerOneWearableBonus,
_playerTwoWearableBonus
);
currentGames[_gameId].state = GameState.GameEnded;
emit PlayerDropped(
_gameId,
_playerDropping
);
}
function applyPercent(uint256 _value) public view returns (uint256) {
return _value
.mul(100 - uint256(s.feePercent))
.div(100);
}
function resolveGame(
uint256 _gameId,
address _winPlayer,
uint256 _playerOneWearableBonus,
uint256 _playerTwoWearableBonus
)
external
whenNotPaused
onlyWorker
onlyOnGoingGame(_gameId)
isPlayerInGame(_gameId, _winPlayer)
{
require(
treasury.tokenOutboundTransfer(
currentGames[_gameId].tokenIndex,
_winPlayer,
applyPercent(currentGames[_gameId].total)
),
'win amount transfer failed (resolveGame)'
);
applyPoints(
_gameId,
_playerOneWearableBonus,
_playerTwoWearableBonus
);
currentGames[_gameId].state = GameState.GameEnded;
emit GameResolved(
_gameId,
_winPlayer
);
}
function applyPoints(
uint256 _gameId,
uint256 _playerOneWearableBonus,
uint256 _playerTwoWearableBonus
)
internal
{
uint256 pointsPerPlayerAfterFee = (
currentGames[_gameId].total.sub(
applyPercent(
currentGames[_gameId].total
)
)
);
pointerContract.addPoints(
currentGames[_gameId].playerOne,
pointsPerPlayerAfterFee,
treasury.getTokenAddress(
currentGames[_gameId].tokenIndex
),
1,
_playerOneWearableBonus
);
pointerContract.addPoints(
currentGames[_gameId].playerTwo,
pointsPerPlayerAfterFee,
treasury.getTokenAddress(
currentGames[_gameId].tokenIndex
),
1,
_playerTwoWearableBonus
);
}
function getGameIdOfPlayers(address playerOne, address playerTwo)
external
pure
returns (uint256 gameId)
{
gameId = uint256(
keccak256(
abi.encodePacked(
playerOne,
playerTwo
)
)
);
}
function checkPlayerInGame(
uint256 gameId,
address player
)
external
view
returns (bool)
{
if (
player == currentGames[gameId].playerOne ||
player == currentGames[gameId].playerTwo
) {
return true;
} else {
return false;
}
}
function changeSafeFactor(
uint8 _newFactor
)
external
onlyCEO
{
require(
_newFactor > 0,
'must be above zero'
);
s.safeFactor = _newFactor;
}
function changeFeePercent(
uint8 _newFeePercent
)
external
onlyCEO
{
require(
_newFeePercent < 20,
'must be below 20'
);
s.feePercent = _newFeePercent;
}
function updateTreasury(
address _newTreasuryAddress
)
external
onlyCEO
{
treasury = TreasuryInstance(_newTreasuryAddress);
}
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":"_safeFactor","internalType":"uint8"},{"type":"uint8","name":"_feePercent","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":"GameResolved","inputs":[{"type":"uint256","name":"gameId","internalType":"uint256","indexed":false},{"type":"address","name":"winner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"GameStarted","inputs":[{"type":"uint256","name":"gameId","internalType":"uint256","indexed":false},{"type":"address","name":"playerOne","internalType":"address","indexed":true},{"type":"address","name":"playerTwo","internalType":"address","indexed":true},{"type":"uint8","name":"tokenIndex","internalType":"uint8","indexed":false}],"anonymous":false},{"type":"event","name":"Paused","inputs":[],"anonymous":false},{"type":"event","name":"PlayerDropped","inputs":[{"type":"uint256","name":"gameId","internalType":"uint256","indexed":false},{"type":"address","name":"player","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"StakeDoubled","inputs":[{"type":"uint256","name":"gameId","internalType":"uint256","indexed":false},{"type":"address","name":"player","internalType":"address","indexed":true},{"type":"uint256","name":"totalStaked","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"StakeRaised","inputs":[{"type":"uint256","name":"gameId","internalType":"uint256","indexed":false},{"type":"address","name":"player","internalType":"address","indexed":true},{"type":"uint256","name":"stake","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":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"applyPercent","inputs":[{"type":"uint256","name":"_value","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"callDouble","inputs":[{"type":"uint256","name":"_gameId","internalType":"uint256"},{"type":"address","name":"_playerCalling","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"ceoAddress","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"changeFeePercent","inputs":[{"type":"uint8","name":"_newFeePercent","internalType":"uint8"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"changeSafeFactor","inputs":[{"type":"uint8","name":"_newFactor","internalType":"uint8"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"checkPlayerInGame","inputs":[{"type":"uint256","name":"gameId","internalType":"uint256"},{"type":"address","name":"player","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"stake","internalType":"uint256"},{"type":"uint256","name":"total","internalType":"uint256"},{"type":"address","name":"playerOne","internalType":"address"},{"type":"address","name":"playerTwo","internalType":"address"},{"type":"address","name":"lastStaker","internalType":"address"},{"type":"uint8","name":"tokenIndex","internalType":"uint8"},{"type":"uint8","name":"state","internalType":"enum dgBackgammon.GameState"}],"name":"currentGames","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"dropGame","inputs":[{"type":"uint256","name":"_gameId","internalType":"uint256"},{"type":"address","name":"_playerDropping","internalType":"address"},{"type":"uint256","name":"_playerOneWearableBonus","internalType":"uint256"},{"type":"uint256","name":"_playerTwoWearableBonus","internalType":"uint256"}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"uint256","name":"gameId","internalType":"uint256"}],"name":"getGameIdOfPlayers","inputs":[{"type":"address","name":"playerOne","internalType":"address"},{"type":"address","name":"playerTwo","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"initializeGame","inputs":[{"type":"uint128","name":"_defaultStake","internalType":"uint128"},{"type":"address","name":"_playerOneAddress","internalType":"address"},{"type":"address","name":"_playerTwoAddress","internalType":"address"},{"type":"uint8","name":"_tokenIndex","internalType":"uint8"}]},{"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":"raiseDouble","inputs":[{"type":"uint256","name":"_gameId","internalType":"uint256"},{"type":"address","name":"_playerRaising","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"resolveGame","inputs":[{"type":"uint256","name":"_gameId","internalType":"uint256"},{"type":"address","name":"_winPlayer","internalType":"address"},{"type":"uint256","name":"_playerOneWearableBonus","internalType":"uint256"},{"type":"uint256","name":"_playerTwoWearableBonus","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"safeFactor","internalType":"uint8"},{"type":"uint8","name":"feePercent","internalType":"uint8"}],"name":"s","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":"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":"nonpayable","outputs":[],"name":"updateTreasury","inputs":[{"type":"address","name":"_newTreasuryAddress","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"workerAddress","inputs":[]}]
            

Contract Byte Code

0x608060405234801561001057600080fd5b506004361061014d5760003560e01c80638456cb59116100c3578063c2bbcc7d1161007c578063c2bbcc7d14610378578063cbd88f48146103fe578063cdc28d5b14610406578063d04e662b14610432578063f67214e91461045e578063f97e3e32146104a75761014d565b80638456cb591461028d57806386b714e21461029557806386d7b356146102c0578063a4cd6b09146102f8578063ada0e87e14610324578063c26f6d44146103525761014d565b80633f4ba83a116101155780633f4ba83a1461021357806350bfba991461021b5780635c975abb1461022357806361d027b31461023f5780637a3fc8d9146102475780637f51bb1f146102675761014d565b80630a0f81681461015257806316be726d1461017657806327d7874c146101a55780633025d9e2146101cd57806333375df7146101f3575b600080fd5b61015a6104df565b604080516001600160a01b039092168252519081900360200190f35b6101936004803603602081101561018c57600080fd5b50356104ee565b60408051918252519081900360200190f35b6101cb600480360360208110156101bb57600080fd5b50356001600160a01b031661051c565b005b6101cb600480360360208110156101e357600080fd5b50356001600160a01b0316610608565b6101cb6004803603602081101561020957600080fd5b503560ff16610677565b6101cb61072b565b61015a6107f8565b61022b610807565b604080519115158252519081900360200190f35b61015a610817565b6101cb6004803603602081101561025d57600080fd5b503560ff16610826565b6101cb6004803603602081101561027d57600080fd5b50356001600160a01b03166108d6565b6101cb610945565b61029d610a19565b604051808360ff1681526020018260ff1681526020019250505060405180910390f35b6101cb600480360360808110156102d657600080fd5b508035906001600160a01b036020820135169060408101359060600135610a2b565b61022b6004803603604081101561030e57600080fd5b50803590602001356001600160a01b0316610d8e565b6101936004803603604081101561033a57600080fd5b506001600160a01b0381358116916020013516610deb565b6101cb6004803603602081101561036857600080fd5b50356001600160a01b0316610e32565b6103956004803603602081101561038e57600080fd5b5035610f2f565b60405180888152602001878152602001866001600160a01b03168152602001856001600160a01b03168152602001846001600160a01b031681526020018360ff1681526020018260038111156103e757fe5b815260200197505050505050505060405180910390f35b61015a610f83565b6101cb6004803603604081101561041c57600080fd5b50803590602001356001600160a01b0316610f92565b6101cb6004803603604081101561044857600080fd5b50803590602001356001600160a01b0316611337565b61022b6004803603608081101561047457600080fd5b5080356001600160801b03169060208101356001600160a01b03908116916040810135909116906060013560ff166116da565b6101cb600480360360808110156104bd57600080fd5b508035906001600160a01b036020820135169060408101359060600135611e93565b6000546001600160a01b031681565b60055460009061051690606490610510908590610100900460ff1683036121a6565b90612206565b92915050565b6000546001600160a01b03163314610569576040805162461bcd60e51b81526020600482018190526024820152600080516020612705833981519152604482015290519081900360640190fd5b6001600160a01b0381166105ae5760405162461bcd60e51b81526004018080602001828103825260228152602001806127256022913960400191505060405180910390fd5b600080546001600160a01b0319166001600160a01b03838116919091179182905560408051929091168252517ff97cbb4246b709036319093e5ff31674b9f6759076d153e1bea1f60392170fc0916020908290030190a150565b6000546001600160a01b03163314610655576040805162461bcd60e51b81526020600482018190526024820152600080516020612705833981519152604482015290519081900360640190fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b031633146106c4576040805162461bcd60e51b81526020600482018190526024820152600080516020612705833981519152604482015290519081900360640190fd5b60148160ff161061070f576040805162461bcd60e51b815260206004820152601060248201526f06d7573742062652062656c6f772032360841b604482015290519081900360640190fd5b6005805460ff9092166101000261ff0019909216919091179055565b6000546001600160a01b03163314610778576040805162461bcd60e51b81526020600482018190526024820152600080516020612705833981519152604482015290519081900360640190fd5b600154600160a01b900460ff166107c05760405162461bcd60e51b81526004018080602001828103825260238152602001806128856023913960400191505060405180910390fd5b6001805460ff60a01b191690556040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d1693390600090a1565b6004546001600160a01b031681565b600154600160a01b900460ff1681565b6003546001600160a01b031681565b6000546001600160a01b03163314610873576040805162461bcd60e51b81526020600482018190526024820152600080516020612705833981519152604482015290519081900360640190fd5b60008160ff16116108c0576040805162461bcd60e51b81526020600482015260126024820152716d7573742062652061626f7665207a65726f60701b604482015290519081900360640190fd5b6005805460ff191660ff92909216919091179055565b6000546001600160a01b03163314610923576040805162461bcd60e51b81526020600482018190526024820152600080516020612705833981519152604482015290519081900360640190fd5b600380546001600160a01b0319166001600160a01b0392909216919091179055565b6001546001600160a01b0316331461098e5760405162461bcd60e51b815260040180806020018281038252602381526020018061279f6023913960400191505060405180910390fd5b600154600160a01b900460ff16156109db576040805162461bcd60e51b815260206004820152601f60248201526000805160206126e5833981519152604482015290519081900360640190fd5b6001805460ff60a01b1916600160a01b1790556040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e75290600090a1565b60055460ff8082169161010090041682565b600154600160a01b900460ff1615610a78576040805162461bcd60e51b815260206004820152601f60248201526000805160206126e5833981519152604482015290519081900360640190fd5b6001546001600160a01b03163314610ac15760405162461bcd60e51b815260040180806020018281038252602381526020018061279f6023913960400191505060405180910390fd5b836002600082815260026020526040902060040154600160a81b900460ff166003811115610aeb57fe5b14610b275760405162461bcd60e51b81526004018080602001828103825260368152602001806127c26036913960400191505060405180910390fd5b60008581526002602081905260409091200154859085906001600160a01b0380831691161480610b7357506000828152600260205260409020600301546001600160a01b038281169116145b610bc1576040805162461bcd60e51b815260206004820152601a6024820152796d757374206265206f6e65206f662074686520706c617965727360301b604482015290519081900360640190fd5b6000878152600260205260409020600401546001600160a01b0387811691161415610c1d5760405162461bcd60e51b815260040180806020018281038252602f815260200180612665602f913960400191505060405180910390fd5b600354600088815260026020526040902060048101546001909101546001600160a01b0392831692633129799292600160a01b810460ff1692911690610c62906104ee565b6040518463ffffffff1660e01b8152600401808460ff168152602001836001600160a01b031681526020018281526020019350505050602060405180830381600087803b158015610cb257600080fd5b505af1158015610cc6573d6000803e3d6000fd5b505050506040513d6020811015610cdc57600080fd5b5051610d195760405162461bcd60e51b81526004018080602001828103825260258152602001806128196025913960400191505060405180910390fd5b610d24878686612270565b600087815260026020908152604091829020600401805460ff60a81b1916600360a81b179055815189815291516001600160a01b038916927f9b289f44d11b987dd2c2ee86a87bbcc17b8afbaf93f22162209137f74e64193292908290030190a250505050505050565b6000828152600260208190526040822001546001600160a01b0383811691161480610dd557506000838152600260205260409020600301546001600160a01b038381169116145b15610de257506001610516565b50600092915050565b604080516bffffffffffffffffffffffff19606094851b81166020808401919091529390941b90931660348401528051602881850301815260489093019052815191012090565b6001600160a01b038116610e775760405162461bcd60e51b81526004018080602001828103825260258152602001806126406025913960400191505060405180910390fd5b6000546001600160a01b0316331480610e9a57506001546001600160a01b031633145b610ed55760405162461bcd60e51b81526004018080602001828103825260258152602001806126406025913960400191505060405180910390fd5b600180546001600160a01b0319166001600160a01b03838116919091179182905560408051929091168252517f54841e992da2f7bcaa3127409f02e1849c79072740593c398d6670f65f995fa7916020908290030190a150565b6002602081905260009182526040909120805460018201549282015460038301546004909301549193926001600160a01b03918216929082169181169060ff600160a01b8204811691600160a81b90041687565b6001546001600160a01b031681565b600154600160a01b900460ff1615610fdf576040805162461bcd60e51b815260206004820152601f60248201526000805160206126e5833981519152604482015290519081900360640190fd5b6001546001600160a01b031633146110285760405162461bcd60e51b815260040180806020018281038252602381526020018061279f6023913960400191505060405180910390fd5b816002600082815260026020526040902060040154600160a81b900460ff16600381111561105257fe5b1461108e5760405162461bcd60e51b81526004018080602001828103825260368152602001806127c26036913960400191505060405180910390fd5b60008381526002602081905260409091200154839083906001600160a01b03808316911614806110da57506000828152600260205260409020600301546001600160a01b038281169116145b611128576040805162461bcd60e51b815260206004820152601a6024820152796d757374206265206f6e65206f662074686520706c617965727360301b604482015290519081900360640190fd5b6000858152600260205260409020600401546001600160a01b03858116911614156111845760405162461bcd60e51b815260040180806020018281038252602f815260200180612747602f913960400191505060405180910390fd5b6003546000868152600260209081526040808320600480820154915483516341d4c74f60e01b8152600160a01b90930460ff16918301919091526001600160a01b038a811660248401526044830191909152915191909416936341d4c74f9360648083019493928390030190829087803b15801561120157600080fd5b505af1158015611215573d6000803e3d6000fd5b505050506040513d602081101561122b57600080fd5b505161127e576040805162461bcd60e51b815260206004820152601e60248201527f63616c6c696e6720646f75626c65207472616e73666572206661696c65640000604482015290519081900360640190fd5b6000858152600260205260409020805460019091015461129d91612525565b6000868152600260208190526040909120600181019290925590546112c1916121a6565b60008681526002602090815260409182902092835560048301805460ff60a81b1916600160a81b17905560019092015481518881529283015280516001600160a01b038716927fb1404d34aba26508768134b3809fc0a68c1eb5e40b3f00b69425d267aac7b62992908290030190a25050505050565b600154600160a01b900460ff1615611384576040805162461bcd60e51b815260206004820152601f60248201526000805160206126e5833981519152604482015290519081900360640190fd5b6001546001600160a01b031633146113cd5760405162461bcd60e51b815260040180806020018281038252602381526020018061279f6023913960400191505060405180910390fd5b816001600082815260026020526040902060040154600160a81b900460ff1660038111156113f757fe5b14611440576040805162461bcd60e51b81526020600482015260146024820152736d757374206265206f6e676f696e672067616d6560601b604482015290519081900360640190fd5b60008381526002602081905260409091200154839083906001600160a01b038083169116148061148c57506000828152600260205260409020600301546001600160a01b038281169116145b6114da576040805162461bcd60e51b815260206004820152601a6024820152796d757374206265206f6e65206f662074686520706c617965727360301b604482015290519081900360640190fd5b6000858152600260205260409020600401546001600160a01b03858116911614156115365760405162461bcd60e51b81526004018080602001828103825260258152602001806128606025913960400191505060405180910390fd5b6003546000868152600260209081526040808320600480820154915483516341d4c74f60e01b8152600160a01b90930460ff16918301919091526001600160a01b038a811660248401526044830191909152915191909416936341d4c74f9360648083019493928390030190829087803b1580156115b357600080fd5b505af11580156115c7573d6000803e3d6000fd5b505050506040513d60208110156115dd57600080fd5b5051611630576040805162461bcd60e51b815260206004820152601e60248201527f72616973696e6720646f75626c65207472616e73666572206661696c65640000604482015290519081900360640190fd5b600085815260026020526040902060048101805460ff60a81b1916600160a91b176001600160a01b0319166001600160a01b038716179055805460019091015461167991612525565b60008681526002602090815260409182902060010183905581518881529081019290925280516001600160a01b038716927fdddbcdc7fb5b4c4fe8c3932f585529467531b2a5efeccbc9670fc0ecb69a276592908290030190a25050505050565b600154600090600160a01b900460ff161561172a576040805162461bcd60e51b815260206004820152601f60248201526000805160206126e5833981519152604482015290519081900360640190fd5b6001546001600160a01b031633146117735760405162461bcd60e51b815260040180806020018281038252602381526020018061279f6023913960400191505060405180910390fd5b826001600160a01b0316846001600160a01b031614156117da576040805162461bcd60e51b815260206004820152601d60248201527f6d7573742062652074776f20646966666572656e7420706c6179657273000000604482015290519081900360640190fd5b60408051606086811b6bffffffffffffffffffffffff199081166020808501919091529187901b166034830152825180830360280181526048830180855281519183019190912060035462f887cf60e81b9092526001600160a01b03808a16604c86015260ff8816606c860152945190949091169263f887cf0092608c808301939192829003018186803b15801561187157600080fd5b505afa158015611885573d6000803e3d6000fd5b505050506040513d602081101561189b57600080fd5b50516005546118b7906001600160801b0389169060ff166121a6565b11156118f45760405162461bcd60e51b81526004018080602001828103825260298152602001806126946029913960400191505060405180910390fd5b6003546040805162f887cf60e81b81526001600160a01b03878116600483015260ff871660248301529151919092169163f887cf00916044808301926020929190829003018186803b15801561194957600080fd5b505afa15801561195d573d6000803e3d6000fd5b505050506040513d602081101561197357600080fd5b505160055461198f906001600160801b0389169060ff166121a6565b11156119cc5760405162461bcd60e51b81526004018080602001828103825260298152602001806126176029913960400191505060405180910390fd5b60008082815260026020526040902060040154600160a81b900460ff1660038111156119f457fe5b1480611a2657506003600082815260026020526040902060040154600160a81b900460ff166003811115611a2457fe5b145b611a77576040805162461bcd60e51b815260206004820152601e60248201527f63616e6e6f7420696e697469616c697a652072756e6e696e672067616d650000604482015290519081900360640190fd5b60035460408051630b5a7f2360e31b815260ff8616600482015290516000926001600160a01b031691635ad3f918916024808301926020929190829003018186803b158015611ac557600080fd5b505afa158015611ad9573d6000803e3d6000fd5b505050506040513d6020811015611aef57600080fd5b50516001600160a01b03161415611b375760405162461bcd60e51b815260040180806020018281038252602281526020018061283e6022913960400191505060405180910390fd5b600354604080516371da23e960e01b815260ff8616600482015290516001600160a01b03909216916371da23e991602480820192602092909190829003018186803b158015611b8557600080fd5b505afa158015611b99573d6000803e3d6000fd5b505050506040513d6020811015611baf57600080fd5b50516001600160801b039081169087161115611bfc5760405162461bcd60e51b81526004018080602001828103825260298152602001806127766029913960400191505060405180910390fd5b600354604080516341d4c74f60e01b815260ff861660048201526001600160a01b0388811660248301526001600160801b038a166044830152915191909216916341d4c74f9160648083019260209291908290030181600087803b158015611c6357600080fd5b505af1158015611c77573d6000803e3d6000fd5b505050506040513d6020811015611c8d57600080fd5b5050600354604080516341d4c74f60e01b815260ff861660048201526001600160a01b0387811660248301526001600160801b038a166044830152915191909216916341d4c74f9160648083019260209291908290030181600087803b158015611cf657600080fd5b505af1158015611d0a573d6000803e3d6000fd5b505050506040513d6020811015611d2057600080fd5b50611d2b90506125dc565b6040805160e081019091526001600160801b0388168082526020820190611d539060026121a6565b81526001600160a01b038089166020830152871660408201526000606082015260ff8616608082015260a00160019052600083815260026020818152604092839020845181559084015160018201559183015190820180546001600160a01b039283166001600160a01b03199182161790915560608401516003808501805492851692841692909217909155608085015160048501805460a088015160ff16600160a01b0260ff60a01b1993909616941693909317169290921780825560c085015194955085949260ff60a81b1990911690600160a81b908490811115611e3657fe5b0217905550506040805184815260ff8716602082015281516001600160a01b03808a1694508a16927f3d5614427441c348c9dfca58446e9547c86b70703734eac8730acf415fdc4d8f928290030190a35060019695505050505050565b600154600160a01b900460ff1615611ee0576040805162461bcd60e51b815260206004820152601f60248201526000805160206126e5833981519152604482015290519081900360640190fd5b6001546001600160a01b03163314611f295760405162461bcd60e51b815260040180806020018281038252602381526020018061279f6023913960400191505060405180910390fd5b836001600082815260026020526040902060040154600160a81b900460ff166003811115611f5357fe5b14611f9c576040805162461bcd60e51b81526020600482015260146024820152736d757374206265206f6e676f696e672067616d6560601b604482015290519081900360640190fd5b60008581526002602081905260409091200154859085906001600160a01b0380831691161480611fe857506000828152600260205260409020600301546001600160a01b038281169116145b612036576040805162461bcd60e51b815260206004820152601a6024820152796d757374206265206f6e65206f662074686520706c617965727360301b604482015290519081900360640190fd5b600354600088815260026020526040902060048101546001909101546001600160a01b0390921691633129799291600160a01b900460ff1690899061207a906104ee565b6040518463ffffffff1660e01b8152600401808460ff168152602001836001600160a01b031681526020018281526020019350505050602060405180830381600087803b1580156120ca57600080fd5b505af11580156120de573d6000803e3d6000fd5b505050506040513d60208110156120f457600080fd5b50516121315760405162461bcd60e51b81526004018080602001828103825260288152602001806126bd6028913960400191505060405180910390fd5b61213c878686612270565b600087815260026020908152604091829020600401805460ff60a81b1916600360a81b179055815189815291516001600160a01b038916927fe1bef002fde33ebfa1c25a643ad667aa6dc80f7c8efb4b4161991251f8b4563a92908290030190a250505050505050565b6000826121b557506000610516565b828202828482816121c257fe5b04146121ff5760405162461bcd60e51b81526004018080602001828103825260218152602001806127f86021913960400191505060405180910390fd5b9392505050565b600080821161225c576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b600082848161226757fe5b04949350505050565b6000838152600260205260408120600101546122a79061228f906104ee565b6000868152600260205260409020600101549061257f565b6004805460008781526002602081815260409283902091820154600354928601548451630b5a7f2360e31b8152600160a01b90910460ff169681019690965292519596506001600160a01b0393841695630680429595938516948894931692635ad3f918926024808301939192829003018186803b15801561232857600080fd5b505afa15801561233c573d6000803e3d6000fd5b505050506040513d602081101561235257600080fd5b5051604080516001600160e01b031960e087901b1681526001600160a01b0394851660048201526024810193909352921660448201526001606482015260848101879052905160a48083019260609291908290030181600087803b1580156123b957600080fd5b505af11580156123cd573d6000803e3d6000fd5b505050506040513d60608110156123e357600080fd5b5050600480546000868152600260209081526040918290206003808201549054918601548451630b5a7f2360e31b8152600160a01b90910460ff169681019690965292516001600160a01b0394851695630680429595948516948894931692635ad3f91892602480840193829003018186803b15801561246257600080fd5b505afa158015612476573d6000803e3d6000fd5b505050506040513d602081101561248c57600080fd5b5051604080516001600160e01b031960e087901b1681526001600160a01b0394851660048201526024810193909352921660448201526001606482015260848101869052905160a48083019260609291908290030181600087803b1580156124f357600080fd5b505af1158015612507573d6000803e3d6000fd5b505050506040513d606081101561251d57600080fd5b505050505050565b6000828201838110156121ff576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000828211156125d6576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a081018290529060c08201529056fe5032206d75737420617070726f76652f616c6c6f77207472656173757279206173207370656e646572416363657373436f6e74726f6c3a20696e76616c696420776f726b6572206164647265737364726f70206d75737420636f6d652066726f6d206f70706f7369746520706c617965722077686f20646f75626c65645031206d75737420617070726f76652f616c6c6f77207472656173757279206173207370656e64657277696e20616d6f756e74207472616e73666572206661696c656420287265736f6c766547616d6529416363657373436f6e74726f6c3a2063757272656e746c792070617573656400416363657373436f6e74726f6c3a2043454f206163636573732064656e696564416363657373436f6e74726f6c3a20696e76616c69642043454f206164647265737363616c6c206d75737420636f6d652066726f6d206f70706f7369746520706c617965722077686f20646f75626c6564657863656564696e67206d6178696d756d2062657420646566696e656420696e207472656173757279416363657373436f6e74726f6c3a20776f726b6572206163636573732064656e6965646d7573742062652070726f706f73656420746f20646f75626c65206669727374206279206f6e65206f662074686520706c6179657273536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7777696e20616d6f756e74207472616e73666572206661696c6564202864726f7047616d6529746f6b656e206973206e6f742064656c636172656420696e2074726561737572792173616d6520706c617965722063616e6e6f7420726169736520646f75626c6520616761696e416363657373436f6e74726f6c3a2063757272656e6c7479206e6f7420706175736564a2646970667358221220efbc0269f6775cbf9d75579f70cb3264d1933c0a87fb5ba6d18f21730aafae3664736f6c63430007040033