Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0.8635 ETH
Eth Value
$2,724.47 (@ $3,155.15/ETH)More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 2,479 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
Value | ||||
---|---|---|---|---|---|---|---|---|---|
Collect Fees | 18850033 | 194 days ago | IN | 0 ETH | 0.00087019 | ||||
Leave | 18647397 | 222 days ago | IN | 0 ETH | 0.00162318 | ||||
Leave | 18617823 | 226 days ago | IN | 0 ETH | 0.00175839 | ||||
Leave | 18616102 | 226 days ago | IN | 0 ETH | 0.00199619 | ||||
Leave | 18588203 | 230 days ago | IN | 0 ETH | 0.00120905 | ||||
Leave | 18587596 | 230 days ago | IN | 0 ETH | 0.00183247 | ||||
Leave | 18566187 | 233 days ago | IN | 0 ETH | 0.00181792 | ||||
Leave | 18562767 | 234 days ago | IN | 0 ETH | 0.0022293 | ||||
Leave | 18561622 | 234 days ago | IN | 0 ETH | 0.00158396 | ||||
Leave | 18561456 | 234 days ago | IN | 0 ETH | 0.00191961 | ||||
Leave | 18561453 | 234 days ago | IN | 0 ETH | 0.00173046 | ||||
Leave | 18561451 | 234 days ago | IN | 0 ETH | 0.001689 | ||||
Leave | 18561422 | 234 days ago | IN | 0 ETH | 0.00193862 | ||||
Leave | 18560517 | 234 days ago | IN | 0 ETH | 0.00176874 | ||||
Leave | 18560514 | 234 days ago | IN | 0 ETH | 0.00178511 | ||||
Leave | 18560128 | 234 days ago | IN | 0 ETH | 0.00240627 | ||||
Leave | 18560126 | 234 days ago | IN | 0 ETH | 0.00248468 | ||||
Leave | 18559368 | 234 days ago | IN | 0 ETH | 0.00141681 | ||||
Leave | 18559367 | 234 days ago | IN | 0 ETH | 0.00135612 | ||||
Leave | 18559361 | 234 days ago | IN | 0 ETH | 0.00163378 | ||||
Claim | 18558877 | 234 days ago | IN | 0 ETH | 0.00147487 | ||||
Play | 18558858 | 234 days ago | IN | 0.01 ETH | 0.0014133 | ||||
Play | 18558856 | 234 days ago | IN | 0.01 ETH | 0.00153658 | ||||
Play | 18558842 | 234 days ago | IN | 0.01 ETH | 0.00147333 | ||||
Join | 18558828 | 234 days ago | IN | 0.01 ETH | 0.00225823 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | Value | ||
---|---|---|---|---|---|---|
18850033 | 194 days ago | 0.026 ETH | ||||
18647397 | 222 days ago | 0.01 ETH | ||||
18617823 | 226 days ago | 0.01 ETH | ||||
18616102 | 226 days ago | 0.01 ETH | ||||
18588203 | 230 days ago | 0.01 ETH | ||||
18587596 | 230 days ago | 0.01 ETH | ||||
18566187 | 233 days ago | 0.01 ETH | ||||
18562767 | 234 days ago | 0.01 ETH | ||||
18561622 | 234 days ago | 0.01 ETH | ||||
18561456 | 234 days ago | 0.01 ETH | ||||
18561453 | 234 days ago | 0.05 ETH | ||||
18561451 | 234 days ago | 0.03 ETH | ||||
18561422 | 234 days ago | 0.01 ETH | ||||
18560517 | 234 days ago | 0.01 ETH | ||||
18560514 | 234 days ago | 0.01 ETH | ||||
18560128 | 234 days ago | 0.01 ETH | ||||
18560126 | 234 days ago | 0.01 ETH | ||||
18559368 | 234 days ago | 0.05 ETH | ||||
18559367 | 234 days ago | 0.03 ETH | ||||
18559361 | 234 days ago | 0.03 ETH | ||||
18558877 | 234 days ago | 0.057 ETH | ||||
18558767 | 234 days ago | 0.0665 ETH | ||||
18557812 | 235 days ago | 0.01 ETH | ||||
18552895 | 235 days ago | 0.057 ETH | ||||
18552759 | 235 days ago | 0.038 ETH |
Loading...
Loading
Contract Name:
Arbitrator
Compiler Version
v0.8.21+commit.d9974bed
Optimization Enabled:
Yes with 20000 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {Owned} from "solmate/auth/Owned.sol"; import {ERC20} from "solmate/tokens/ERC20.sol"; import {ECDSA} from "openzeppelin/utils/cryptography/ECDSA.sol"; import {EIP712} from "openzeppelin/utils/cryptography/EIP712.sol"; import {IArbitrator} from "../interfaces/IArbitrator.sol"; contract Arbitrator is Owned, IArbitrator, EIP712 { using ECDSA for bytes32; /// Minimum random value uint256 private constant RAND_MIN = 1; /// Maximum random value uint256 private constant RAND_MAX = 25; /// Ante percentage e.g 1000 / 10000 = .1 = 10% uint128 private constant ANTE = 1000; /// Denominator for percentage values e.g 1000 / 10000 = .1 = 10% uint128 private constant DENOMINATOR = 10000; /// Maximum allowed fee percentage uint128 private constant MAX_FEE = 1000; /// Number of blocks before a given game can begin uint64 private constant START_DELAY = 99 seconds; /// TODO ? Time between turns ? uint64 private constant DEFAULT_CADENCE = 99 seconds; /// Minimum number of players in a given game uint8 private constant MIN_SEATS = 2; /// Maximum number of players in a given game uint8 private constant MAX_SEATS = 100; /// Randomness function signature bytes32 private constant RANDOMNESS_TYPEHASH = keccak256("Randomness(uint256 randomness,uint64 counter,uint256 id)"); /// Fee receiver address address public feeController; /// Current fee percentage uint128 public fee = 500; /// Latest created game (array index) uint256 public currentId; /// Randomness supplier/signer address address public rngSource; /// Bitmasked of allowed game modes uint256 private modeAllowlist; /// Current game balances mapping(address => uint256) private balances; /// Arrays of participants based on tontine ID mapping(uint256 => address[]) private participants; /// Assets allowed for game use mapping(address => bool) private assetAllowlist; /// Tontines mapping(uint256 => Tontine) private tontines; /// Activity tracking mapping(bytes32 => bool) private activityLog; constructor( address _admin, address _feeController, address _rngSource ) Owned(_admin) EIP712("Tontine", "1") { feeController = _feeController; rngSource = _rngSource; } /// @notice Create a new Tontine /// @param _asset Game currency to be used /// @param _bet Starting bet amount /// @param _seats Number of players /// @param _betMode Lobby betting mode /// @param _rngMode Lobby RNG mode function create( address _asset, uint128 _bet, uint8 _seats, BetMode _betMode, RNGMode _rngMode ) external payable { if (tx.origin != msg.sender) revert NotEOA(); if (_seats < MIN_SEATS || _seats > MAX_SEATS) revert InvalidSeatCount(); if (_bet == 0) revert InvalidBet(); if (!getBetModeAllowed(_betMode) || !getRNGModeAllowed(_rngMode)) revert InvalidMode(); if (!assetAllowlist[_asset]) revert InvalidAsset(); Tontine storage tontine = tontines[currentId]; tontine.asset = _asset; tontine.seats = _seats; tontine.betMode = _betMode; tontine.rngMode = _rngMode; tontine.bet = _bet; tontine.balance = _bet; tontine.participantState = 1 << 127; participants[currentId].push(msg.sender); unchecked { balances[_asset] += _bet; currentId++; } activityLog[ _getParticipantIdentifier(msg.sender, currentId - 1) ] = true; if (_asset == address(0)) { if (msg.value != _bet) revert InvalidBet(); } else { if (msg.value > 0) revert InvalidBet(); ERC20(_asset).transferFrom(msg.sender, address(this), _bet); } emit Created(currentId - 1, _bet, _asset); emit Joined(currentId - 1, msg.sender); } /// @notice Join an existing Tontine /// @param _id Tontine ID function join(uint256 _id) external payable { Tontine storage tontine = tontines[_id]; address asset = tontine.asset; uint128 bet = tontine.bet; if (tx.origin != msg.sender) revert NotEOA(); if (tontine.lastBetTime != 0) revert AlreadyStarted(); // If the ID doesn't exist it will revert as "Ended" if (tontine.participantState == 0) revert Ended(); bytes32 participantId = _getParticipantIdentifier(msg.sender, _id); if (activityLog[participantId]) revert AlreadyJoined(); uint8 participantLength = uint8(participants[_id].length); unchecked { tontine.participantState |= uint128(1 << (127 - participantLength)); tontine.balance += bet; balances[asset] += bet; } participants[_id].push(msg.sender); activityLog[participantId] = true; // Start round if full if (++participantLength == tontine.seats) { // Schedule start time tontine.lastBetTime = uint64(block.timestamp) + START_DELAY; // Scramble order to keep odds uniform tontine.lastIndex = _scramble(tontine.seats); // Deduct fee on start such that participants are not charged fees when leaving uint128 feeDelta = tontine.balance - _getBetAfterFee(tontine.balance); unchecked { tontine.balance -= feeDelta; balances[asset] -= feeDelta; } emit Started(_id); } if (asset == address(0)) { if (msg.value != bet) revert InvalidBet(); } else { if (msg.value != 0) revert InvalidBet(); ERC20(asset).transferFrom(msg.sender, address(this), bet); } emit Joined(currentId, msg.sender); } /// @notice Leave a tontine lobby (that hasn't started yet) /// @param _id Tontine ID /// @param _index Participant array ID function leave(uint256 _id, uint8 _index) external { Tontine storage tontine = tontines[_id]; address[] storage participantArray = participants[_id]; if (tx.origin != msg.sender) revert NotEOA(); if (tontine.lastBetTime != 0) revert AlreadyStarted(); if (participantArray[_index] != msg.sender) revert NotJoined(); uint128 bet = tontine.bet; address asset = tontine.asset; unchecked { balances[tontine.asset] -= bet; tontine.balance -= bet; } // Clear state if (participantArray.length <= 1) { delete participants[_id]; delete tontines[_id]; emit Claimed(_id, address(0), address(0), 0); } else { participantArray[_index] = participantArray[ participantArray.length - 1 ]; participantArray.pop(); tontine.participantState ^= uint128( 1 << (127 - participantArray.length) ); } delete activityLog[_getParticipantIdentifier(msg.sender, _id)]; // Return funds if (asset == address(0)) { payable(msg.sender).transfer(bet); } else { ERC20(asset).transfer(msg.sender, bet); } emit Left(_id, msg.sender); } /// @notice Leave an already started game - funds will NOT be returned /// @param _id Tontine ID /// @param _index Participant array ID function fold(uint256 _id, uint8 _index) external { Tontine storage tontine = tontines[_id]; uint64 lastBetTime = tontine.lastBetTime; if (tx.origin != msg.sender) revert NotEOA(); if (lastBetTime == 0 || lastBetTime > block.timestamp) revert NotStarted(); if (participants[_id][_index] != msg.sender) revert NotJoined(); ( uint128 participantState, bool ended, uint256 currentIndex ) = _updateParticipantState( tontine.participantState, tontine.lastIndex, lastBetTime, tontine.seats ); if (currentIndex != _index) revert NotTurn(); if (ended || _isLastAlive(participantState, _index)) revert Ended(); if (!_isAlive(participantState, _index)) revert PlayerNotAlive(); tontine.participantState = _killPlayer(participantState, _index); tontine.lastIndex = _index; tontine.lastBetTime = uint64(block.timestamp); ++tontine.counter; emit Folded(_id, msg.sender); } /// Play your turn /// @param _id Tontine ID /// @param _index Participant array ID /// @param _bet Bet amount in wei /// @param _rng Randomness data /// @param _sig Signed randomness data function play( uint256 _id, uint8 _index, uint128 _bet, Randomness calldata _rng, bytes calldata _sig ) external payable { Tontine storage tontine = tontines[_id]; uint64 lastBetTime = tontine.lastBetTime; if (tx.origin != msg.sender) revert NotEOA(); if (lastBetTime == 0 || lastBetTime > block.timestamp) revert NotStarted(); if (participants[_id][_index] != msg.sender) revert NotJoined(); if (tontine.counter > 0 && tontine.rngMode == RNGMode.RANDOM) { uint32 counter = tontine.counter; if (_rng.id != _id) revert InvalidID(); if (_rng.counter != counter) revert InvalidCounter(); _validateRandomness(_rng, _sig); if ( _shouldKillLastPlayer( _id, counter, tontine.rngMode, _rng.randomness ) ) { tontine.participantState = _killPlayer( tontine.participantState, tontine.lastIndex ); } } ( uint128 participantState, bool ended, uint256 currentIndex ) = _updateParticipantState( tontine.participantState, tontine.lastIndex, lastBetTime, tontine.seats ); if (currentIndex != _index) revert NotTurn(); if (ended || _isLastAlive(participantState, _index)) revert Ended(); // Handling for alternate bet modes if (_bet >= tontine.bet && tontine.betMode == BetMode.VARIABLE) { tontine.bet = _bet; } else if (tontine.betMode == BetMode.ANTE) { tontine.bet = (tontine.bet * (DENOMINATOR + ANTE)) / DENOMINATOR; } uint128 betAfterFee = _getBetAfterFee(tontine.bet); tontine.balance += betAfterFee; balances[tontine.asset] += betAfterFee; tontine.lastBetTime = uint64(block.timestamp); tontine.lastIndex = _index; tontine.participantState = participantState; ++tontine.counter; if (tontine.asset == address(0)) { if (msg.value != tontine.bet) revert InvalidBet(); } else { if (msg.value > 0) revert InvalidBet(); ERC20(tontine.asset).transferFrom( msg.sender, address(this), tontine.bet ); } emit Played(_id, msg.sender, tontine.bet); } /// @notice Claim winnings when you're the last person standing /// @param _id Tontine ID /// @param _index Participant array ID /// @param _rng Randomness data /// @param _sig Signed randomness data function claim( uint256 _id, uint8 _index, Randomness calldata _rng, bytes calldata _sig ) external { Tontine storage tontine = tontines[_id]; uint64 lastBetTime = tontine.lastBetTime; if (tx.origin != msg.sender) revert NotEOA(); if (tontine.participantState == 0) revert AlreadyClaimed(); if (lastBetTime == 0 || lastBetTime > block.timestamp) revert NotStarted(); if (participants[_id][_index] != msg.sender) revert NotJoined(); if (tontine.counter > 0 && tontine.rngMode == RNGMode.RANDOM) { uint32 counter = tontine.counter; if (_rng.id != _id) revert InvalidID(); if (_rng.counter != counter) revert InvalidCounter(); _validateRandomness(_rng, _sig); if ( _shouldKillLastPlayer( _id, counter, tontine.rngMode, _rng.randomness ) ) { tontine.participantState = _killPlayer( tontine.participantState, tontine.lastIndex ); } } (uint128 participantState, bool ended, ) = _updateParticipantState( tontine.participantState, tontine.lastIndex, lastBetTime, tontine.seats ); if (!_isAlive(participantState, _index)) revert PlayerNotAlive(); if (!ended && !_isLastAlive(participantState, _index)) revert Running(); uint128 amount = tontine.balance; tontine.balance = 0; unchecked { balances[tontine.asset] -= amount; } address asset = tontine.asset; delete tontines[_id]; delete participants[_id]; // Return funds if (asset == address(0)) { payable(msg.sender).transfer(amount); } else { ERC20(asset).transfer(msg.sender, amount); } emit Claimed(_id, msg.sender, asset, amount); } /// @notice Collect and send held fees to controller /// @dev Use zero address for native currency /// @param _asset Asset to be collected function collectFees(address _asset) external { if (!assetAllowlist[_asset]) revert InvalidAsset(); if (_asset == address(0)) { payable(feeController).transfer( address(this).balance - balances[_asset] ); } else { ERC20(_asset).transfer( feeController, ERC20(_asset).balanceOf(address(this)) - balances[_asset] ); } } /// @notice Sets a new controller address /// @param _feeController New controller address function setFeeController(address _feeController) external { if (msg.sender != feeController) revert InvalidCaller(); feeController = _feeController; } /// @notice Sets a new fee /// @dev Fee is determined by division e.g 500 / 10000 = .05 = 5% /// @param _fee New fee percentage function setFee(uint128 _fee) external { if (msg.sender != feeController) revert InvalidCaller(); if (_fee > MAX_FEE) revert MaxFeeExceeded(); fee = _fee; } /// @notice White/blacklists a given asset /// @dev Use zero address for native currency /// @param _asset Asset to be allowed/disallowed /// @param _allowed Is this asset allowed? function setAssetAllowlist( address _asset, bool _allowed ) external onlyOwner { assetAllowlist[_asset] = _allowed; } /// @notice Sets a new bitmask of allowed game modes /// @param _allowlist New mode allow list value function setModeAllowlist(uint256 _allowlist) external onlyOwner { modeAllowlist = _allowlist; } /// @notice Sets the signer that is in charge of supplying randomness /// @param _rngSource New signer address function setRNGSource(address _rngSource) external onlyOwner { rngSource = _rngSource; } /// @notice Helper to more easily determine if a bet mode is allowed as opposed to shifting bitmask /// @param _mode Betmode enum value /// @return Is the supplied mode allowed? function getBetModeAllowed( BetMode _mode ) public view override returns (bool) { return ((modeAllowlist >> uint8(_mode)) & 1) == 1; } /// @notice Helper to more easily determine if a bet mode is allowed as opposed to shifting bitmask /// @param _mode RNG enum value /// @return Is the supplied mode allowed? function getRNGModeAllowed( RNGMode _mode ) public view override returns (bool) { return ((modeAllowlist >> (uint8(_mode) + 128)) & 1) == 1; } /// TODO: Is this needed? Appears unused. Document if needed function getRandomness( uint256 _id, uint64 _counter ) public pure override returns (uint256) { return (uint256(keccak256(abi.encodePacked(_id, _counter))) % RAND_MAX); } /// Participant state for a given lobby /// @param _id Tontine ID /// @param _rng Randomness data /// @return Participant state /// @return Last player index /// @return Seats in tontine function getParticipantState( uint256 _id, Randomness calldata _rng ) public view override returns (uint128, bool, uint256) { Tontine memory tontine = tontines[_id]; uint64 lastBetTime = tontine.lastBetTime; if (lastBetTime == 0) { return (tontine.participantState, false, 0); } if (tontine.counter > 0 && tontine.rngMode == RNGMode.RANDOM) { if ( _shouldKillLastPlayer( _id, tontine.counter, tontine.rngMode, _rng.randomness ) ) { tontine.participantState = _killPlayer( tontine.participantState, tontine.lastIndex ); } } return _updateParticipantState( tontine.participantState, tontine.lastIndex, lastBetTime, tontine.seats ); } /// TODO: Duplicate function, not exactly necessary. Change internal visibility on original (ln 600) function getParticipantIdentifier( address _participant, uint256 _id ) external pure override returns (bytes32) { return _getParticipantIdentifier(_participant, _id); } /// Gets amount after fees /// @dev Use WEI /// @param _amount Amount in /// @return Amount out function getAmountAfterFee( uint256 _amount ) external view override returns (uint256) { return (_amount * (DENOMINATOR - fee)) / DENOMINATOR; } /// Gets a tontine /// @param _id Tontine ID function getTontine( uint256 _id ) external view override returns (Tontine memory) { return (tontines[_id]); } /// Checks if a given address/participant is still active /// @param _participant Participant address /// @param _id Tontine ID /// @return Is participant active? function isActive( address _participant, uint256 _id ) external view override returns (bool) { return activityLog[_getParticipantIdentifier(_participant, _id)]; } /// Gets balance of supplied token address (contract accounting) /// @dev Amount returned in WEI /// @dev Use zero address for base currency /// @param _token Token address function getBalance( address _token ) external view override returns (uint256) { return balances[_token]; } /// Gets address for supplied IDs /// @param _id Tontine ID /// @param _index Participant array ID /// @return Participant address function getParticipant( uint256 _id, uint256 _index ) external view override returns (address) { return participants[_id][_index]; } /// Gets all participants in a given lobby /// @param _id Tontine ID /// @return Array of participants function getParticipants( uint256 _id ) external view override returns (address[] memory) { return participants[_id]; } /// Checks if an asset is allowed for game /// @dev Use zero address for base currency /// @param _asset Asset/token address /// @return Is asset allowed? function getAssetAllowed( address _asset ) external view override returns (bool) { return assetAllowlist[_asset]; } /// Hashes randomness data /// @param _rng Randomness data /// @return Hashed randomness data function randomnessHash( Randomness memory _rng ) public view returns (bytes32) { return _hashTypedDataV4( keccak256( abi.encode( RANDOMNESS_TYPEHASH, _rng.randomness, _rng.counter, _rng.id ) ) ); } /// Validates signed randomness data /// @param _rng Randomness data /// @param _sig Signed randomness data function _validateRandomness( Randomness memory _rng, bytes memory _sig ) internal view { bytes32 hash = randomnessHash(_rng); address signer = ECDSA.recover(hash, _sig); if (signer != rngSource) revert InvalidSigner(); } /// Shuffle index /// @param _range Number of seats/players /// @return Shuffled index within bounds function _scramble(uint8 _range) internal view returns (uint8) { return uint8( uint256( keccak256( abi.encodePacked(block.prevrandao, block.timestamp) ) ) ) % _range; } /// TODO: Same as ln 432. Remove? function _getBetAfterFee(uint128 _amount) internal view returns (uint128) { return (_amount * (DENOMINATOR - fee)) / DENOMINATOR; } /// Checks if player is alive /// @param _participantState Participant state bitmask /// @param _index Participant array ID /// @return Is player alive? function _isAlive( uint128 _participantState, uint8 _index ) internal pure returns (bool) { uint128 liveMask = uint128(1 << (127 - _index)); return (liveMask & _participantState) != 0; } /// Checks if player is last alive /// @param _participantState Participant state bitmask /// @param _index Participant array ID function _isLastAlive( uint128 _participantState, uint8 _index ) internal pure returns (bool) { return (_killPlayer(_participantState, _index) == 0); } /// Kills a designated player /// @param _participantState Participant state bitmask /// @param _index Participant array ID /// @return Updated state with designated player killed function _killPlayer( uint128 _participantState, uint8 _index ) internal pure returns (uint128) { uint128 deadMask = ~uint128(1 << (127 - _index)); return deadMask & _participantState; } /// Updates tontine participants state /// @param _participantState Participant state bitmask /// @param _lastIndex Last player index on participant state /// @param _lastBetTime Last time a bet was received, or when game started /// @param _seats Number of players/seats in lobby /// @return Participant state /// @return Is last alive? /// @return Next player index function _updateParticipantState( uint128 _participantState, uint64 _lastIndex, uint64 _lastBetTime, uint8 _seats ) internal view returns (uint128, bool, uint256) { if (_seats == 0) return (0, false, 0); if (_lastBetTime > block.timestamp) return (_participantState, false, (_lastIndex + 1) % _seats); uint256 iterations = (block.timestamp - _lastBetTime) / DEFAULT_CADENCE; for (uint256 i = 1; i <= iterations; i++) { uint8 index = uint8((_lastIndex + i) % _seats); if (_isAlive(_participantState, index)) { if (_isLastAlive(_participantState, index)) { return (_participantState, true, index); } else { _participantState = _killPlayer(_participantState, index); } } else { unchecked { ++iterations; } } } uint256 newIndex = (_lastIndex + iterations + 1) % _seats; return ( _participantState, _isLastAlive(_participantState, uint8(newIndex)), newIndex ); } /// Check if last player should be killed /// @param _id Participant array ID /// @param _counter RNG counter /// @param _rngMode RNG enum value /// @param randomness Randomness int /// @return Should last player be killed? function _shouldKillLastPlayer( uint256 _id, uint64 _counter, RNGMode _rngMode, uint256 randomness ) internal pure returns (bool) { if (_rngMode == RNGMode.RANDOM) { uint256 seed = uint256(keccak256(abi.encodePacked(randomness))); uint256 range = (uint256( keccak256(abi.encodePacked(_id, _counter)) ) % RAND_MAX); return (seed % 100) <= range; } return false; } /// Get hashed identifier /// @param _participant Participant/player address /// @param _id Participant array ID /// @return Participant identifier function _getParticipantIdentifier( address _participant, uint256 _id ) internal pure returns (bytes32) { return keccak256(abi.encode(_participant, _id)); } /// @dev Prevent direct sending of funds receive() external payable { revert(); } /// @dev default fallback() external { revert(); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Simple single owner authorization mixin. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Owned.sol) abstract contract Owned { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event OwnershipTransferred(address indexed user, address indexed newOwner); /*////////////////////////////////////////////////////////////// OWNERSHIP STORAGE //////////////////////////////////////////////////////////////*/ address public owner; modifier onlyOwner() virtual { require(msg.sender == owner, "UNAUTHORIZED"); _; } /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor(address _owner) { owner = _owner; emit OwnershipTransferred(address(0), _owner); } /*////////////////////////////////////////////////////////////// OWNERSHIP LOGIC //////////////////////////////////////////////////////////////*/ function transferOwnership(address newOwner) public virtual onlyOwner { owner = newOwner; emit OwnershipTransferred(msg.sender, newOwner); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol) /// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) /// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. abstract contract ERC20 { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event Transfer(address indexed from, address indexed to, uint256 amount); event Approval(address indexed owner, address indexed spender, uint256 amount); /*////////////////////////////////////////////////////////////// METADATA STORAGE //////////////////////////////////////////////////////////////*/ string public name; string public symbol; uint8 public immutable decimals; /*////////////////////////////////////////////////////////////// ERC20 STORAGE //////////////////////////////////////////////////////////////*/ uint256 public totalSupply; mapping(address => uint256) public balanceOf; mapping(address => mapping(address => uint256)) public allowance; /*////////////////////////////////////////////////////////////// EIP-2612 STORAGE //////////////////////////////////////////////////////////////*/ uint256 internal immutable INITIAL_CHAIN_ID; bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR; mapping(address => uint256) public nonces; /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor( string memory _name, string memory _symbol, uint8 _decimals ) { name = _name; symbol = _symbol; decimals = _decimals; INITIAL_CHAIN_ID = block.chainid; INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); } /*////////////////////////////////////////////////////////////// ERC20 LOGIC //////////////////////////////////////////////////////////////*/ function approve(address spender, uint256 amount) public virtual returns (bool) { allowance[msg.sender][spender] = amount; emit Approval(msg.sender, spender, amount); return true; } function transfer(address to, uint256 amount) public virtual returns (bool) { balanceOf[msg.sender] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(msg.sender, to, amount); return true; } function transferFrom( address from, address to, uint256 amount ) public virtual returns (bool) { uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount; balanceOf[from] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(from, to, amount); return true; } /*////////////////////////////////////////////////////////////// EIP-2612 LOGIC //////////////////////////////////////////////////////////////*/ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public virtual { require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); // Unchecked because the only math done is incrementing // the owner's nonce which cannot realistically overflow. unchecked { address recoveredAddress = ecrecover( keccak256( abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR(), keccak256( abi.encode( keccak256( "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" ), owner, spender, value, nonces[owner]++, deadline ) ) ) ), v, r, s ); require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); allowance[recoveredAddress][spender] = value; } emit Approval(owner, spender, value); } function DOMAIN_SEPARATOR() public view virtual returns (bytes32) { return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator(); } function computeDomainSeparator() internal view virtual returns (bytes32) { return keccak256( abi.encode( keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256(bytes(name)), keccak256("1"), block.chainid, address(this) ) ); } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint(address to, uint256 amount) internal virtual { totalSupply += amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(address(0), to, amount); } function _burn(address from, uint256 amount) internal virtual { balanceOf[from] -= amount; // Cannot underflow because a user's balance // will never be larger than the total supply. unchecked { totalSupply -= amount; } emit Transfer(from, address(0), amount); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.0; import "../Strings.sol"; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS, InvalidSignatureV // Deprecated in v4.8 } function _throwError(RecoverError error) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert("ECDSA: invalid signature"); } else if (error == RecoverError.InvalidSignatureLength) { revert("ECDSA: invalid signature length"); } else if (error == RecoverError.InvalidSignatureS) { revert("ECDSA: invalid signature 's' value"); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, signature); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. * * _Available since v4.2._ */ function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, r, vs); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature); } return (signer, RecoverError.NoError); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, v, r, s); _throwError(error); return recovered; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) { // 32 is the length in bytes of hash, // enforced by the type signature above /// @solidity memory-safe-assembly assembly { mstore(0x00, "\x19Ethereum Signed Message:\n32") mstore(0x1c, hash) message := keccak256(0x00, 0x3c) } } /** * @dev Returns an Ethereum Signed Message, created from `s`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) { /// @solidity memory-safe-assembly assembly { let ptr := mload(0x40) mstore(ptr, "\x19\x01") mstore(add(ptr, 0x02), domainSeparator) mstore(add(ptr, 0x22), structHash) data := keccak256(ptr, 0x42) } } /** * @dev Returns an Ethereum Signed Data with intended validator, created from a * `validator` and `data` according to the version 0 of EIP-191. * * See {recover}. */ function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x00", validator, data)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/EIP712.sol) pragma solidity ^0.8.8; import "./ECDSA.sol"; import "../ShortStrings.sol"; import "../../interfaces/IERC5267.sol"; /** * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. * * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible, * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding * they need in their contracts using a combination of `abi.encode` and `keccak256`. * * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA * ({_hashTypedDataV4}). * * The implementation of the domain separator was designed to be as efficient as possible while still properly updating * the chain id to protect against replay attacks on an eventual fork of the chain. * * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. * * NOTE: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain * separator of the implementation contract. This will cause the `_domainSeparatorV4` function to always rebuild the * separator from the immutable values, which is cheaper than accessing a cached version in cold storage. * * _Available since v3.4._ * * @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment */ abstract contract EIP712 is IERC5267 { using ShortStrings for *; bytes32 private constant _TYPE_HASH = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to // invalidate the cached domain separator if the chain id changes. bytes32 private immutable _cachedDomainSeparator; uint256 private immutable _cachedChainId; address private immutable _cachedThis; bytes32 private immutable _hashedName; bytes32 private immutable _hashedVersion; ShortString private immutable _name; ShortString private immutable _version; string private _nameFallback; string private _versionFallback; /** * @dev Initializes the domain separator and parameter caches. * * The meaning of `name` and `version` is specified in * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]: * * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol. * - `version`: the current major version of the signing domain. * * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart * contract upgrade]. */ constructor(string memory name, string memory version) { _name = name.toShortStringWithFallback(_nameFallback); _version = version.toShortStringWithFallback(_versionFallback); _hashedName = keccak256(bytes(name)); _hashedVersion = keccak256(bytes(version)); _cachedChainId = block.chainid; _cachedDomainSeparator = _buildDomainSeparator(); _cachedThis = address(this); } /** * @dev Returns the domain separator for the current chain. */ function _domainSeparatorV4() internal view returns (bytes32) { if (address(this) == _cachedThis && block.chainid == _cachedChainId) { return _cachedDomainSeparator; } else { return _buildDomainSeparator(); } } function _buildDomainSeparator() private view returns (bytes32) { return keccak256(abi.encode(_TYPE_HASH, _hashedName, _hashedVersion, block.chainid, address(this))); } /** * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this * function returns the hash of the fully encoded EIP712 message for this domain. * * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example: * * ```solidity * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode( * keccak256("Mail(address to,string contents)"), * mailTo, * keccak256(bytes(mailContents)) * ))); * address signer = ECDSA.recover(digest, signature); * ``` */ function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) { return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash); } /** * @dev See {EIP-5267}. * * _Available since v4.9._ */ function eip712Domain() public view virtual override returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ) { return ( hex"0f", // 01111 _name.toStringWithFallback(_nameFallback), _version.toStringWithFallback(_versionFallback), block.chainid, address(this), bytes32(0), new uint256[](0) ); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IArbitratorErrors} from "./IArbitratorErrors.sol"; import {IArbitratorEvents} from "./IArbitratorEvents.sol"; import {IArbitratorData} from "./IArbitratorData.sol"; interface IArbitrator is IArbitratorErrors, IArbitratorEvents, IArbitratorData { /*////////////////////////////////////////////////////////////// Core //////////////////////////////////////////////////////////////*/ function create( address _asset, uint128 _bet, uint8 _seats, BetMode _betMode, RNGMode _rngMode ) external payable; function join(uint256 _id) external payable; function leave(uint256 _id, uint8 _index) external; function fold(uint256 _id, uint8 _index) external; function play( uint256 _id, uint8 _index, uint128 _bet, Randomness calldata _rng, bytes calldata _sig ) external payable; function claim( uint256 _id, uint8 _index, Randomness calldata _rng, bytes calldata _sig ) external; function collectFees(address _asset) external; /*////////////////////////////////////////////////////////////// Views //////////////////////////////////////////////////////////////*/ function rngSource() external view returns (address); function fee() external view returns (uint128); function currentId() external view returns (uint256); function getBalance(address _token) external view returns (uint256); function getParticipant( uint256 _id, uint256 _index ) external view returns (address); function getParticipants( uint256 _id ) external view returns (address[] memory); function getAssetAllowed(address _asset) external view returns (bool); function getBetModeAllowed(BetMode _mode) external view returns (bool); function getRNGModeAllowed(RNGMode _mode) external view returns (bool); function getRandomness( uint256 _id, uint64 _counter ) external view returns (uint256); function getTontine(uint256 _id) external view returns (Tontine memory); function getAmountAfterFee(uint256 _amount) external view returns (uint256); function isActive( address _participant, uint256 _id ) external view returns (bool); function getParticipantState( uint256 _id, Randomness calldata _rng ) external view returns (uint128, bool, uint256); function getParticipantIdentifier( address _participant, uint256 _id ) external pure returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; import "./math/SignedMath.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toString(int256 value) internal pure returns (string memory) { return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value)))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return keccak256(bytes(a)) == keccak256(bytes(b)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/ShortStrings.sol) pragma solidity ^0.8.8; import "./StorageSlot.sol"; // | string | 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | // | length | 0x BB | type ShortString is bytes32; /** * @dev This library provides functions to convert short memory strings * into a `ShortString` type that can be used as an immutable variable. * * Strings of arbitrary length can be optimized using this library if * they are short enough (up to 31 bytes) by packing them with their * length (1 byte) in a single EVM word (32 bytes). Additionally, a * fallback mechanism can be used for every other case. * * Usage example: * * ```solidity * contract Named { * using ShortStrings for *; * * ShortString private immutable _name; * string private _nameFallback; * * constructor(string memory contractName) { * _name = contractName.toShortStringWithFallback(_nameFallback); * } * * function name() external view returns (string memory) { * return _name.toStringWithFallback(_nameFallback); * } * } * ``` */ library ShortStrings { // Used as an identifier for strings longer than 31 bytes. bytes32 private constant _FALLBACK_SENTINEL = 0x00000000000000000000000000000000000000000000000000000000000000FF; error StringTooLong(string str); error InvalidShortString(); /** * @dev Encode a string of at most 31 chars into a `ShortString`. * * This will trigger a `StringTooLong` error is the input string is too long. */ function toShortString(string memory str) internal pure returns (ShortString) { bytes memory bstr = bytes(str); if (bstr.length > 31) { revert StringTooLong(str); } return ShortString.wrap(bytes32(uint256(bytes32(bstr)) | bstr.length)); } /** * @dev Decode a `ShortString` back to a "normal" string. */ function toString(ShortString sstr) internal pure returns (string memory) { uint256 len = byteLength(sstr); // using `new string(len)` would work locally but is not memory safe. string memory str = new string(32); /// @solidity memory-safe-assembly assembly { mstore(str, len) mstore(add(str, 0x20), sstr) } return str; } /** * @dev Return the length of a `ShortString`. */ function byteLength(ShortString sstr) internal pure returns (uint256) { uint256 result = uint256(ShortString.unwrap(sstr)) & 0xFF; if (result > 31) { revert InvalidShortString(); } return result; } /** * @dev Encode a string into a `ShortString`, or write it to storage if it is too long. */ function toShortStringWithFallback(string memory value, string storage store) internal returns (ShortString) { if (bytes(value).length < 32) { return toShortString(value); } else { StorageSlot.getStringSlot(store).value = value; return ShortString.wrap(_FALLBACK_SENTINEL); } } /** * @dev Decode a string that was encoded to `ShortString` or written to storage using {setWithFallback}. */ function toStringWithFallback(ShortString value, string storage store) internal pure returns (string memory) { if (ShortString.unwrap(value) != _FALLBACK_SENTINEL) { return toString(value); } else { return store; } } /** * @dev Return the length of a string that was encoded to `ShortString` or written to storage using {setWithFallback}. * * WARNING: This will return the "byte length" of the string. This may not reflect the actual length in terms of * actual characters as the UTF-8 encoding of a single character can span over multiple bytes. */ function byteLengthWithFallback(ShortString value, string storage store) internal view returns (uint256) { if (ShortString.unwrap(value) != _FALLBACK_SENTINEL) { return byteLength(value); } else { return bytes(store).length; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC5267.sol) pragma solidity ^0.8.0; interface IERC5267 { /** * @dev MAY be emitted to signal that the domain could have changed. */ event EIP712DomainChanged(); /** * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712 * signature. */ function eip712Domain() external view returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IArbitratorErrors { /*////////////////////////////////////////////////////////////// Errors //////////////////////////////////////////////////////////////*/ /// @notice caller not EOA. error NotEOA(); /// @notice invalid asset. error InvalidAsset(); /// @notice invalid caller. error InvalidCaller(); /// @notice provided fee greater than maximum allowed. error MaxFeeExceeded(); /// @notice number of seats are invalid. error InvalidSeatCount(); /// @notice invalid bet size. error InvalidBet(); /// @notice invalid mode. error InvalidMode(); /// @notice game already started. error AlreadyStarted(); /// @notice game not started. error NotStarted(); /// @notice game already joined. error AlreadyJoined(); /// @notice game not joined. error NotJoined(); /// @notice not player's turn. error NotTurn(); /// @notice game ended. error Ended(); /// @notice game running. error Running(); /// @notice player no longer participating. error PlayerNotAlive(); /// @notice already claimed. error AlreadyClaimed(); /// @notice invalid signer. error InvalidSigner(); /// @notice invalid signer. error InvalidID(); /// @notice invalid signer. error InvalidCounter(); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IArbitratorEvents { /*////////////////////////////////////////////////////////////// Events //////////////////////////////////////////////////////////////*/ event Created( uint256 indexed id, uint256 indexed bet, address indexed asset ); event Joined(uint256 indexed id, address indexed participant); event Left(uint256 indexed id, address indexed participant); event Played(uint256 indexed id, address indexed participant, uint128 bet); event Folded(uint256 indexed id, address indexed participant); event Claimed( uint256 indexed id, address indexed participant, address indexed asset, uint128 amount ); event Started(uint256 indexed id); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IArbitratorData { /*////////////////////////////////////////////////////////////// Data Structures //////////////////////////////////////////////////////////////*/ enum BetMode { // Fixed bet size CLASSIC, // Bet size is strictly increasing and determined by the player VARIABLE, // Bet size is increasing linearly ANTE } enum RNGMode { // No odds of death ZERO, // Odds of death randomly selected between RAND_MIN and RAND_MAX RANDOM } struct Randomness { uint256 randomness; uint64 counter; uint256 id; } struct Tontine { // Asset used for Tontine address asset; // Available seats uint8 seats; // Bet Mode BetMode betMode; // RNG Mode RNGMode rngMode; // Balance uint128 balance; // Current bet amount uint128 bet; // State of all participants uint128 participantState; // Last time a bet was received, or game started uint64 lastBetTime; // Counter for rng uint32 counter; // Last player index on participant state uint8 lastIndex; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1, "Math: mulDiv overflow"); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.0; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol) // This file was procedurally generated from scripts/generate/templates/StorageSlot.js. pragma solidity ^0.8.0; /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC1967 implementation slot: * ```solidity * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` * * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._ * _Available since v4.9 for `string`, `bytes`._ */ library StorageSlot { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } struct StringSlot { string value; } struct BytesSlot { bytes value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` with member `value` located at `slot`. */ function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` representation of the string storage pointer `store`. */ function getStringSlot(string storage store) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } /** * @dev Returns an `BytesSlot` with member `value` located at `slot`. */ function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`. */ function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } }
{ "remappings": [ "ds-test/=lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "solmate/=lib/solmate/src/", "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "openzeppelin/=lib/openzeppelin-contracts/contracts/" ], "optimizer": { "enabled": true, "runs": 20000 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_admin","type":"address"},{"internalType":"address","name":"_feeController","type":"address"},{"internalType":"address","name":"_rngSource","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyClaimed","type":"error"},{"inputs":[],"name":"AlreadyJoined","type":"error"},{"inputs":[],"name":"AlreadyStarted","type":"error"},{"inputs":[],"name":"Ended","type":"error"},{"inputs":[],"name":"InvalidAsset","type":"error"},{"inputs":[],"name":"InvalidBet","type":"error"},{"inputs":[],"name":"InvalidCaller","type":"error"},{"inputs":[],"name":"InvalidCounter","type":"error"},{"inputs":[],"name":"InvalidID","type":"error"},{"inputs":[],"name":"InvalidMode","type":"error"},{"inputs":[],"name":"InvalidSeatCount","type":"error"},{"inputs":[],"name":"InvalidShortString","type":"error"},{"inputs":[],"name":"InvalidSigner","type":"error"},{"inputs":[],"name":"MaxFeeExceeded","type":"error"},{"inputs":[],"name":"NotEOA","type":"error"},{"inputs":[],"name":"NotJoined","type":"error"},{"inputs":[],"name":"NotStarted","type":"error"},{"inputs":[],"name":"NotTurn","type":"error"},{"inputs":[],"name":"PlayerNotAlive","type":"error"},{"inputs":[],"name":"Running","type":"error"},{"inputs":[{"internalType":"string","name":"str","type":"string"}],"name":"StringTooLong","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"participant","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint128","name":"amount","type":"uint128"}],"name":"Claimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"bet","type":"uint256"},{"indexed":true,"internalType":"address","name":"asset","type":"address"}],"name":"Created","type":"event"},{"anonymous":false,"inputs":[],"name":"EIP712DomainChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"participant","type":"address"}],"name":"Folded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"participant","type":"address"}],"name":"Joined","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"participant","type":"address"}],"name":"Left","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"participant","type":"address"},{"indexed":false,"internalType":"uint128","name":"bet","type":"uint128"}],"name":"Played","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Started","type":"event"},{"stateMutability":"nonpayable","type":"fallback"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"},{"internalType":"uint8","name":"_index","type":"uint8"},{"components":[{"internalType":"uint256","name":"randomness","type":"uint256"},{"internalType":"uint64","name":"counter","type":"uint64"},{"internalType":"uint256","name":"id","type":"uint256"}],"internalType":"struct IArbitratorData.Randomness","name":"_rng","type":"tuple"},{"internalType":"bytes","name":"_sig","type":"bytes"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_asset","type":"address"}],"name":"collectFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_asset","type":"address"},{"internalType":"uint128","name":"_bet","type":"uint128"},{"internalType":"uint8","name":"_seats","type":"uint8"},{"internalType":"enum IArbitratorData.BetMode","name":"_betMode","type":"uint8"},{"internalType":"enum IArbitratorData.RNGMode","name":"_rngMode","type":"uint8"}],"name":"create","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"currentId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields","type":"bytes1"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"verifyingContract","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"extensions","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fee","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeController","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"},{"internalType":"uint8","name":"_index","type":"uint8"}],"name":"fold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"getAmountAfterFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_asset","type":"address"}],"name":"getAssetAllowed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"getBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum IArbitratorData.BetMode","name":"_mode","type":"uint8"}],"name":"getBetModeAllowed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"},{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"getParticipant","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_participant","type":"address"},{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"getParticipantIdentifier","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"},{"components":[{"internalType":"uint256","name":"randomness","type":"uint256"},{"internalType":"uint64","name":"counter","type":"uint64"},{"internalType":"uint256","name":"id","type":"uint256"}],"internalType":"struct IArbitratorData.Randomness","name":"_rng","type":"tuple"}],"name":"getParticipantState","outputs":[{"internalType":"uint128","name":"","type":"uint128"},{"internalType":"bool","name":"","type":"bool"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"getParticipants","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum IArbitratorData.RNGMode","name":"_mode","type":"uint8"}],"name":"getRNGModeAllowed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"},{"internalType":"uint64","name":"_counter","type":"uint64"}],"name":"getRandomness","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"getTontine","outputs":[{"components":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint8","name":"seats","type":"uint8"},{"internalType":"enum IArbitratorData.BetMode","name":"betMode","type":"uint8"},{"internalType":"enum IArbitratorData.RNGMode","name":"rngMode","type":"uint8"},{"internalType":"uint128","name":"balance","type":"uint128"},{"internalType":"uint128","name":"bet","type":"uint128"},{"internalType":"uint128","name":"participantState","type":"uint128"},{"internalType":"uint64","name":"lastBetTime","type":"uint64"},{"internalType":"uint32","name":"counter","type":"uint32"},{"internalType":"uint8","name":"lastIndex","type":"uint8"}],"internalType":"struct IArbitratorData.Tontine","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_participant","type":"address"},{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"isActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"join","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"},{"internalType":"uint8","name":"_index","type":"uint8"}],"name":"leave","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"},{"internalType":"uint8","name":"_index","type":"uint8"},{"internalType":"uint128","name":"_bet","type":"uint128"},{"components":[{"internalType":"uint256","name":"randomness","type":"uint256"},{"internalType":"uint64","name":"counter","type":"uint64"},{"internalType":"uint256","name":"id","type":"uint256"}],"internalType":"struct IArbitratorData.Randomness","name":"_rng","type":"tuple"},{"internalType":"bytes","name":"_sig","type":"bytes"}],"name":"play","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"randomness","type":"uint256"},{"internalType":"uint64","name":"counter","type":"uint64"},{"internalType":"uint256","name":"id","type":"uint256"}],"internalType":"struct IArbitratorData.Randomness","name":"_rng","type":"tuple"}],"name":"randomnessHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rngSource","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_asset","type":"address"},{"internalType":"bool","name":"_allowed","type":"bool"}],"name":"setAssetAllowlist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"_fee","type":"uint128"}],"name":"setFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feeController","type":"address"}],"name":"setFeeController","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_allowlist","type":"uint256"}],"name":"setModeAllowlist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_rngSource","type":"address"}],"name":"setRNGSource","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
610160604052600480546001600160801b0319166101f41790553480156200002657600080fd5b506040516200554738038062005547833981016040819052620000499162000258565b6040805180820182526007815266546f6e74696e6560c81b6020808301919091528251808401845260018152603160f81b91810191909152600080546001600160a01b0319166001600160a01b0388169081178255935192939192879291907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a350620000db826001620001b6565b61012052620000ec816002620001b6565b61014052815160208084019190912060e052815190820120610100524660a0526200017a60e05161010051604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201529081019290925260608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b60805250503060c052600380546001600160a01b039384166001600160a01b031991821617909155600680549290931691161790555062000488565b6000602083511015620001d657620001ce83620001ef565b9050620001e9565b81620001e3848262000347565b5060ff90505b92915050565b600080829050601f8151111562000226578260405163305a27a960e01b81526004016200021d919062000413565b60405180910390fd5b8051620002338262000463565b179392505050565b80516001600160a01b03811681146200025357600080fd5b919050565b6000806000606084860312156200026e57600080fd5b62000279846200023b565b925062000289602085016200023b565b915062000299604085016200023b565b90509250925092565b634e487b7160e01b600052604160045260246000fd5b600181811c90821680620002cd57607f821691505b602082108103620002ee57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200034257600081815260208120601f850160051c810160208610156200031d5750805b601f850160051c820191505b818110156200033e5782815560010162000329565b5050505b505050565b81516001600160401b03811115620003635762000363620002a2565b6200037b81620003748454620002b8565b84620002f4565b602080601f831160018114620003b357600084156200039a5750858301515b600019600386901b1c1916600185901b1785556200033e565b600085815260208120601f198616915b82811015620003e457888601518255948401946001909101908401620003c3565b5085821015620004035787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b600060208083528351808285015260005b81811015620004425785810183015185820160400152820162000424565b506000604082860101526040601f19601f8301168501019250505092915050565b80516020808301519190811015620002ee5760001960209190910360031b1b16919050565b60805160a05160c05160e051610100516101205161014051615064620004e3600039600061225201526000612227015260006141ca015260006141a2015260006140fd015260006141270152600061415101526150646000f3fe6080604052600436106101e75760003560e01c806384b0196e11610102578063ddca3f4311610095578063f2fde38b11610064578063f2fde38b14610687578063f6927e7d146106a7578063f8b2cb4f146106c7578063feff17441461070a576101f1565b8063ddca3f43146105f4578063e00dd1611461063e578063e3d5c08c14610654578063ed64346214610674576101f1565b8063a480ca79116100d1578063a480ca7914610507578063c1e3bd3e14610527578063d266e83b14610554578063dc6f867c146105c7576101f1565b806384b0196e1461047f5780638da5cb5b146104a75780639738f87b146104d4578063a06412ac146104e7576101f1565b80633687f24a1161017a57806358db40d81161014957806358db40d8146103f2578063681b950d146104125780636999b3771461043257806379fa35071461045f576101f1565b80633687f24a146103655780633ed4c678146103855780634266580a146103a5578063450bde78146103d2576101f1565b80631aed59f0116101b65780631aed59f0146102775780631f6dc875146102c15780631fc6a5db1461031757806334fe228714610345576101f1565b806301fe1fdc14610202578063049878f3146102245780630ca522081461023757806314c9216a14610257576101f1565b366101f157600080fd5b3480156101fd57600080fd5b600080fd5b34801561020e57600080fd5b5061022261021d366004614590565b610758565b005b6102226102323660046145bc565b610cdd565b34801561024357600080fd5b506102226102523660046145bc565b611313565b34801561026357600080fd5b50610222610272366004614590565b61139e565b34801561028357600080fd5b506102976102923660046145d5565b611763565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102cd57600080fd5b506103076102dc36600461461b565b73ffffffffffffffffffffffffffffffffffffffff166000908152600a602052604090205460ff1690565b60405190151581526020016102b8565b34801561032357600080fd5b506103376103323660046145bc565b6117ae565b6040519081526020016102b8565b34801561035157600080fd5b50610307610360366004614645565b6117fa565b34801561037157600080fd5b50610222610380366004614680565b611823565b34801561039157600080fd5b506102226103a036600461461b565b611905565b3480156103b157600080fd5b506006546102979073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103de57600080fd5b506103376103ed3660046146b3565b61199d565b3480156103fe57600080fd5b5061022261040d36600461461b565b611a0c565b34801561041e57600080fd5b5061022261042d366004614730565b611ad4565b34801561043e57600080fd5b506003546102979073ffffffffffffffffffffffffffffffffffffffff1681565b34801561046b57600080fd5b5061030761047a3660046147af565b6121fa565b34801561048b57600080fd5b50610494612219565b6040516102b8979695949392919061482e565b3480156104b357600080fd5b506000546102979073ffffffffffffffffffffffffffffffffffffffff1681565b6102226104e23660046148ed565b6122be565b3480156104f357600080fd5b50610337610502366004614952565b6128df565b34801561051357600080fd5b5061022261052236600461461b565b612927565b34801561053357600080fd5b506105476105423660046145bc565b612b56565b6040516102b8919061497c565b34801561056057600080fd5b5061030761056f366004614952565b6040805173ffffffffffffffffffffffffffffffffffffffff9390931660208085019190915283820192909252805180840382018152606090930181528251928201929092206000908152600c909152205460ff1690565b3480156105d357600080fd5b506105e76105e23660046145bc565b612bcf565b6040516102b89190614a29565b34801561060057600080fd5b5060045461061d906fffffffffffffffffffffffffffffffff1681565b6040516fffffffffffffffffffffffffffffffff90911681526020016102b8565b34801561064a57600080fd5b5061033760055481565b34801561066057600080fd5b5061033761066f366004614b34565b612dbf565b610222610682366004614bbc565b612e42565b34801561069357600080fd5b506102226106a236600461461b565b6137aa565b3480156106b357600080fd5b506102226106c2366004614c4a565b61389b565b3480156106d357600080fd5b506103376106e236600461461b565b73ffffffffffffffffffffffffffffffffffffffff1660009081526008602052604090205490565b34801561071657600080fd5b5061072a610725366004614c81565b613972565b604080516fffffffffffffffffffffffffffffffff90941684529115156020840152908201526060016102b8565b6000828152600b6020908152604080832060099092529091203233146107aa576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002820154700100000000000000000000000000000000900467ffffffffffffffff1615610804576040517f1fbde44500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff16818460ff168154811061083057610830614ca5565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1614610889576040517fc394a43300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018281018054845473ffffffffffffffffffffffffffffffffffffffff16600081815260086020526040902080547001000000000000000000000000000000009093046fffffffffffffffffffffffffffffffff9081169384900390915583547fffffffffffffffffffffffffffffffff0000000000000000000000000000000081169082168490039091161790925583549092106109d957600086815260096020526040812061093a91614548565b6000868152600b6020908152604080832080547fffffffffffffffffff00000000000000000000000000000000000000000000001681556001810184905560020180547fffffff000000000000000000000000000000000000000000000000000000000016905551828152829189917f4fc9df21c274d2396432490df6fcda723ce987bc1b640015d34b26ca0ed98063910160405180910390a4610b41565b825483906109e990600190614d03565b815481106109f9576109f9614ca5565b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16838660ff1681548110610a3957610a39614ca5565b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082805480610a9157610a91614d16565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690550190558254610af690607f614d03565b6002850180547fffffffffffffffffffffffffffffffff000000000000000000000000000000008116600190931b6fffffffffffffffffffffffffffffffff91821618169190911790555b6040805133602080830191909152818301899052825180830384018152606090920183528151918101919091206000908152600c9091522080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905573ffffffffffffffffffffffffffffffffffffffff8116610bfe5760405133906fffffffffffffffffffffffffffffffff841680156108fc02916000818181858888f19350505050158015610bf8573d6000803e3d6000fd5b50610ca8565b6040517fa9059cbb0000000000000000000000000000000000000000000000000000000081523360048201526fffffffffffffffffffffffffffffffff8316602482015273ffffffffffffffffffffffffffffffffffffffff82169063a9059cbb906044016020604051808303816000875af1158015610c82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ca69190614d45565b505b604051339087907ff9b63d6ab6b86370bd291baf2443198e10294bc1a369e21ff12b34b904cb0fff90600090a3505050505050565b6000818152600b602052604090208054600182015473ffffffffffffffffffffffffffffffffffffffff9091169070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16333214610d6a576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002830154700100000000000000000000000000000000900467ffffffffffffffff1615610dc4576040517f1fbde44500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028301546fffffffffffffffffffffffffffffffff16600003610e14576040517f477383f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805133602080830191909152818301879052825180830384018152606090920183528151918101919091206000818152600c9092529190205460ff1615610e88576040517e3b268200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600085815260096020908152604080832080546002890180546fffffffffffffffffffffffffffffffff600160ff607f869003811682901b8316838516177fffffffffffffffffffffffffffffffff00000000000000000000000000000000948516179094558c810180548084168d01841694169390931790925573ffffffffffffffffffffffffffffffffffffffff8b168852600887528588208054918b169190910190558354808201855593875285872090930180547fffffffffffffffffffffffff00000000000000000000000000000000000000001633179055868652600c9094529190932080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016909317909255855474010000000000000000000000000000000000000000900416610fc082614d62565b91508160ff160361118957610fd6606342614d81565b60028601805467ffffffffffffffff92909216700100000000000000000000000000000000027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff909216919091179055845461104d9060ff7401000000000000000000000000000000000000000090910416613bde565b60028601805460ff929092167c0100000000000000000000000000000000000000000000000000000000027fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff90921691909117905560018501546000906110c5906fffffffffffffffffffffffffffffffff16613c20565b60018701546110e691906fffffffffffffffffffffffffffffffff16614da9565b6001870180547fffffffffffffffffffffffffffffffff0000000000000000000000000000000081166fffffffffffffffffffffffffffffffff91821684900382161790915573ffffffffffffffffffffffffffffffffffffffff87166000908152600860205260408082208054938516909303909255905191925088917e6e0c97de781a7389d44ba8fd35d1467cabb17ed04d038d166d34ab819213f39190a2505b73ffffffffffffffffffffffffffffffffffffffff84166111f457826fffffffffffffffffffffffffffffffff1634146111ef576040517faa82224900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6112dc565b341561122c576040517faa82224900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f23b872dd0000000000000000000000000000000000000000000000000000000081523360048201523060248201526fffffffffffffffffffffffffffffffff8416604482015273ffffffffffffffffffffffffffffffffffffffff8516906323b872dd906064016020604051808303816000875af11580156112b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112da9190614d45565b505b6005546040513391907fc0081eeafa0d002abcd7d58d84b6e688d1526b9c3d915a282212ba08c49a17a790600090a3505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611399576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b600755565b6000828152600b602052604090206002810154700100000000000000000000000000000000900467ffffffffffffffff16333214611408576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff811615806114285750428167ffffffffffffffff16115b1561145f576040517f6f312cbd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000848152600960205260409020805433919060ff861690811061148557611485614ca5565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16146114de576040517fc394a43300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600282015482546000918291829161154b916fffffffffffffffffffffffffffffffff82169160ff7c010000000000000000000000000000000000000000000000000000000090910481169188917401000000000000000000000000000000000000000090910416613c5a565b9250925092508560ff16811461158d576040517fc6e1dd1d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b818061159e575061159e8387613dbd565b156115d5576040517f477383f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6115df8387613de3565b611615576040517ff6fa148200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61161f8387613e1c565b6002860180546fffffffffffffffffffffffffffffffff929092167fffffff00ffffffffffffffffffffffff00000000000000000000000000000000909216919091177c010000000000000000000000000000000000000000000000000000000060ff891602177fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004267ffffffffffffffff1602178082556018906116f8907801000000000000000000000000000000000000000000000000900463ffffffff16614dd2565b91906101000a81548163ffffffff021916908363ffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff16877f537f4d0c896772cdfaaac608ab3c4705fe48cc44b3a2e63451b4a7eb9808ba1b60405160405180910390a350505050505050565b600082815260096020526040812080548390811061178357611783614ca5565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1690505b92915050565b600454600090612710906117d4906fffffffffffffffffffffffffffffffff1682614da9565b6117f0906fffffffffffffffffffffffffffffffff1684614df5565b6117a89190614e3b565b600081600281111561180e5761180e6149d6565b60ff16600754901c6001166001149050919050565b60035473ffffffffffffffffffffffffffffffffffffffff163314611874576040517f48f5c3ed00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e86fffffffffffffffffffffffffffffffff821611156118c2576040517ff4df6ae500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600480547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff92909216919091179055565b60035473ffffffffffffffffffffffffffffffffffffffff163314611956576040517f48f5c3ed00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6000601983836040516020016119e292919091825260c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016602082015260280190565b6040516020818303038152906040528051906020012060001c611a059190614e4f565b9392505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611a8d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401611390565b600680547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6000858152600b602052604090206002810154700100000000000000000000000000000000900467ffffffffffffffff16333214611b3e576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028201546fffffffffffffffffffffffffffffffff16600003611b8e576040517f646cf55800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff81161580611bae5750428167ffffffffffffffff16115b15611be5576040517f6f312cbd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000878152600960205260409020805433919060ff8916908110611c0b57611c0b614ca5565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1614611c64576040517fc394a43300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028201547801000000000000000000000000000000000000000000000000900463ffffffff1615801590611cc8575060018254760100000000000000000000000000000000000000000000900460ff166001811115611cc657611cc66149d6565b145b15611e9b5760028201547801000000000000000000000000000000000000000000000000900463ffffffff1660408601358814611d31576040517ff5d2101e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff8116611d486040880160208901614e63565b67ffffffffffffffff1614611d89576040517f63e0897a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611dd7611d9b36889003880188614b34565b86868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613e3f92505050565b8254611e0b90899063ffffffff841690760100000000000000000000000000000000000000000000900460ff168935613eb5565b15611e99576002830154611e55906fffffffffffffffffffffffffffffffff8116907c0100000000000000000000000000000000000000000000000000000000900460ff16613e1c565b6002840180547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff929092169190911790555b505b600282015482546000918291611f05916fffffffffffffffffffffffffffffffff81169160ff7c0100000000000000000000000000000000000000000000000000000000909204821691879174010000000000000000000000000000000000000000900416613c5a565b5091509150611f148289613de3565b611f4a576040517ff6fa148200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80158015611f5f5750611f5d8289613dbd565b155b15611f96576040517fa63065ca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180850180547fffffffffffffffffffffffffffffffff000000000000000000000000000000008116909155855473ffffffffffffffffffffffffffffffffffffffff908116600090815260086020908152604080832080546fffffffffffffffffffffffffffffffff90961695869003905589548f8452600b835281842080547fffffffffffffffffff0000000000000000000000000000000000000000000000168155968701849055600290960180547fffffff00000000000000000000000000000000000000000000000000000000001690556009909152812092939091169161208391614548565b73ffffffffffffffffffffffffffffffffffffffff81166120e25760405133906fffffffffffffffffffffffffffffffff841680156108fc02916000818181858888f193505050501580156120dc573d6000803e3d6000fd5b5061218c565b6040517fa9059cbb0000000000000000000000000000000000000000000000000000000081523360048201526fffffffffffffffffffffffffffffffff8316602482015273ffffffffffffffffffffffffffffffffffffffff82169063a9059cbb906044016020604051808303816000875af1158015612166573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218a9190614d45565b505b6040516fffffffffffffffffffffffffffffffff8316815273ffffffffffffffffffffffffffffffffffffffff82169033908d907f4fc9df21c274d2396432490df6fcda723ce987bc1b640015d34b26ca0ed980639060200160405180910390a45050505050505050505050565b600081600181111561220e5761220e6149d6565b61180e906080614e7e565b60006060808280808361224d7f00000000000000000000000000000000000000000000000000000000000000006001613f8d565b6122787f00000000000000000000000000000000000000000000000000000000000000006002613f8d565b604080516000808252602082019092527f0f000000000000000000000000000000000000000000000000000000000000009b939a50919850469750309650945092509050565b3233146122f7576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600260ff8416108061230c5750606460ff8416115b15612343576040517f59e59f3f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b836fffffffffffffffffffffffffffffffff1660000361238f576040517faa82224900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612398826117fa565b15806123aa57506123a8816121fa565b155b156123e1576040517fa0042b1700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff85166000908152600a602052604090205460ff16612440576040517fc891add200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6005546000908152600b60205260409020805460ff851674010000000000000000000000000000000000000000027fffffffffffffffffffffff00000000000000000000000000000000000000000090911673ffffffffffffffffffffffffffffffffffffffff88161717808255839082907fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000008360028111156124fd576124fd6149d6565b02179055508054829082907fffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffff16760100000000000000000000000000000000000000000000836001811115612554576125546149d6565b02179055506fffffffffffffffffffffffffffffffff851670010000000000000000000000000000000081027fffffffffffffffffffffffffffffffff0000000000000000000000000000000090811682176001808501919091556002840180549092166f8000000000000000000000000000000017909155600580546000908152600960209081526040808320805480870182559084528284200180547fffffffffffffffffffffffff0000000000000000000000000000000000000000163390811790915573ffffffffffffffffffffffffffffffffffffffff8d16845260089092528220805490950190945581548301918290559192600c92916126ab9190612661908690614d03565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602082015290810182905260009060600160405160208183030381529060405280519060200120905092915050565b8152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001691151591909117905573ffffffffffffffffffffffffffffffffffffffff861661275357846fffffffffffffffffffffffffffffffff16341461274e576040517faa82224900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61283b565b341561278b576040517faa82224900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f23b872dd0000000000000000000000000000000000000000000000000000000081523360048201523060248201526fffffffffffffffffffffffffffffffff8616604482015273ffffffffffffffffffffffffffffffffffffffff8716906323b872dd906064016020604051808303816000875af1158015612815573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128399190614d45565b505b8573ffffffffffffffffffffffffffffffffffffffff16856fffffffffffffffffffffffffffffffff1660016005546128749190614d03565b6040517f7bc3e781453a761be4ae9daaacb192000aff04f1c45c3bf9ca9e118b4c9e2e9c90600090a460055433906128ae90600190614d03565b6040517fc0081eeafa0d002abcd7d58d84b6e688d1526b9c3d915a282212ba08c49a17a790600090a3505050505050565b6040805173ffffffffffffffffffffffffffffffffffffffff841660208083019190915281830184905282518083038401815260609092019092528051910120600090611a05565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600a602052604090205460ff16612986576040517fc891add200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8116612a085760035473ffffffffffffffffffffffffffffffffffffffff8281166000908152600860205260409020549116906108fc906129dc9047614d03565b6040518115909202916000818181858888f19350505050158015612a04573d6000803e3d6000fd5b5050565b60035473ffffffffffffffffffffffffffffffffffffffff828116600081815260086020526040908190205490517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152919363a9059cbb93169184906370a0823190602401602060405180830381865afa158015612a91573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ab59190614e97565b612abf9190614d03565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff909216600483015260248201526044016020604051808303816000875af1158015612b2f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a049190614d45565b50565b600081815260096020908152604091829020805483518184028101840190945280845260609392830182828015612bc357602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311612b98575b50505050509050919050565b612c256040805161014081018252600080825260208201819052909182019081526020016000815260006020820181905260408201819052606082018190526080820181905260a0820181905260c09091015290565b6000828152600b6020908152604091829020825161014081018452815473ffffffffffffffffffffffffffffffffffffffff8116825260ff74010000000000000000000000000000000000000000820481169483019490945290939192918401917501000000000000000000000000000000000000000000909104166002811115612cb257612cb26149d6565b6002811115612cc357612cc36149d6565b81528154602090910190760100000000000000000000000000000000000000000000900460ff166001811115612cfb57612cfb6149d6565b6001811115612d0c57612d0c6149d6565b815260018201546fffffffffffffffffffffffffffffffff808216602084015270010000000000000000000000000000000091829004811660408401526002909301549283166060830152820467ffffffffffffffff1660808201527801000000000000000000000000000000000000000000000000820463ffffffff1660a08201527c010000000000000000000000000000000000000000000000000000000090910460ff1660c09091015292915050565b60006117a87fd133bbc7f95acfb85dec01a77edf5a7c3665782f8a05b72294c6bdf7fb8b115c836000015184602001518560400151604051602001612e279493929190938452602084019290925267ffffffffffffffff166040830152606082015260800190565b60405160208183030381529060405280519060200120614038565b6000868152600b602052604090206002810154700100000000000000000000000000000000900467ffffffffffffffff16333214612eac576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff81161580612ecc5750428167ffffffffffffffff16115b15612f03576040517f6f312cbd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000888152600960205260409020805433919060ff8a16908110612f2957612f29614ca5565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1614612f82576040517fc394a43300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028201547801000000000000000000000000000000000000000000000000900463ffffffff1615801590612fe6575060018254760100000000000000000000000000000000000000000000900460ff166001811115612fe457612fe46149d6565b145b1561317d5760028201547801000000000000000000000000000000000000000000000000900463ffffffff166040860135891461304f576040517ff5d2101e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff81166130666040880160208901614e63565b67ffffffffffffffff16146130a7576040517f63e0897a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6130b9611d9b36889003880188614b34565b82546130ed908a9063ffffffff841690760100000000000000000000000000000000000000000000900460ff168935613eb5565b1561317b576002830154613137906fffffffffffffffffffffffffffffffff8116907c0100000000000000000000000000000000000000000000000000000000900460ff16613e1c565b6002840180547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff929092169190911790555b505b60028201548254600091829182916131ea916fffffffffffffffffffffffffffffffff82169160ff7c010000000000000000000000000000000000000000000000000000000090910481169188917401000000000000000000000000000000000000000090910416613c5a565b9250925092508960ff16811461322c576040517fc6e1dd1d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b818061323d575061323d838b613dbd565b15613274576040517f477383f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018501546fffffffffffffffffffffffffffffffff7001000000000000000000000000000000009091048116908a16108015906132e05750600185547501000000000000000000000000000000000000000000900460ff1660028111156132de576132de6149d6565b145b1561331c576001850180546fffffffffffffffffffffffffffffffff808c167001000000000000000000000000000000000291161790556133d6565b600285547501000000000000000000000000000000000000000000900460ff16600281111561334d5761334d6149d6565b036133d6576127106133616103e882614eb0565b6001870154613396919070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16614ed9565b6133a09190614f05565b6001860180546fffffffffffffffffffffffffffffffff9283167001000000000000000000000000000000000292169190911790555b600185015460009061340d9070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16613c20565b60018701805491925082916000906134389084906fffffffffffffffffffffffffffffffff16614eb0565b82546101009290920a6fffffffffffffffffffffffffffffffff818102199093169183160217909155875473ffffffffffffffffffffffffffffffffffffffff166000908152600860205260408120805492851693509161349a908490614f34565b90915550506002860180547fffffff00ffffffff0000000000000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004267ffffffffffffffff16027fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff16177c010000000000000000000000000000000000000000000000000000000060ff8e1602177fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff861617808255601890613593907801000000000000000000000000000000000000000000000000900463ffffffff16614dd2565b825463ffffffff9182166101009390930a9283029190920219909116179055855473ffffffffffffffffffffffffffffffffffffffff1661363657600186015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff163414613631576040517faa82224900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61373a565b341561366e576040517faa82224900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b855460018701546040517f23b872dd0000000000000000000000000000000000000000000000000000000081523360048201523060248201527001000000000000000000000000000000009091046fffffffffffffffffffffffffffffffff16604482015273ffffffffffffffffffffffffffffffffffffffff909116906323b872dd906064016020604051808303816000875af1158015613714573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137389190614d45565b505b60018601546040517001000000000000000000000000000000009091046fffffffffffffffffffffffffffffffff16815233908d907f34e592c5d9452abe7b4df38f36795ed86fbcded8a266d5bdeeaaf5375a8cf0d39060200160405180910390a3505050505050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461382b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401611390565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a350565b60005473ffffffffffffffffffffffffffffffffffffffff16331461391c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401611390565b73ffffffffffffffffffffffffffffffffffffffff919091166000908152600a6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b6000828152600b60209081526040808320815161014081018352815473ffffffffffffffffffffffffffffffffffffffff8116825260ff74010000000000000000000000000000000000000000820481169583019590955285948594859492908401917501000000000000000000000000000000000000000000909104166002811115613a0157613a016149d6565b6002811115613a1257613a126149d6565b81528154602090910190760100000000000000000000000000000000000000000000900460ff166001811115613a4a57613a4a6149d6565b6001811115613a5b57613a5b6149d6565b815260018201546fffffffffffffffffffffffffffffffff808216602084015270010000000000000000000000000000000091829004811660408401526002909301549283166060830152820467ffffffffffffffff90811660808301527801000000000000000000000000000000000000000000000000830463ffffffff1660a08301527c010000000000000000000000000000000000000000000000000000000090920460ff1660c09091015260e08201519192508116600003613b2e575060c00151925060009150819050613bd7565b600082610100015163ffffffff16118015613b5e5750600182606001516001811115613b5c57613b5c6149d6565b145b15613bb257613b828783610100015163ffffffff1684606001518960000135613eb5565b15613bb257613b9a8260c00151836101200151613e1c565b6fffffffffffffffffffffffffffffffff1660c08301525b613bce8260c0015183610120015160ff16838560200151613c5a565b94509450945050505b9250925092565b6000814442604051602001613bfd929190918252602082015260400190565b6040516020818303038152906040528051906020012060001c6117a89190614f47565b60045460009061271090613c46906fffffffffffffffffffffffffffffffff1682614da9565b613c509084614ed9565b6117a89190614f05565b60008060008360ff16600003613c7857506000915081905080613db3565b428567ffffffffffffffff161115613cbc5786600060ff8616613c9c896001614d81565b613ca69190614f69565b919450925067ffffffffffffffff169050613db3565b60006063613cd467ffffffffffffffff881642614d03565b613cde9190614e3b565b905060015b818111613d6d57600060ff8716613d048367ffffffffffffffff8c16614f34565b613d0e9190614e4f565b9050613d1a8a82613de3565b15613d5357613d298a82613dbd565b15613d42578995506001945060ff169250613db3915050565b613d4c8a82613e1c565b9950613d5a565b8260010192505b5080613d6581614f90565b915050613ce3565b50600060ff8616613d888367ffffffffffffffff8b16614f34565b613d93906001614f34565b613d9d9190614e4f565b905088613daa8a83613dbd565b90955093509150505b9450945094915050565b6000613dc98383613e1c565b6fffffffffffffffffffffffffffffffff16159392505050565b600080613df183607f614fc8565b60ff166001901b90508381166fffffffffffffffffffffffffffffffff166000141591505092915050565b600080613e2a83607f614fc8565b600160ff919091161b19841691505092915050565b6000613e4a83612dbf565b90506000613e588284614080565b60065490915073ffffffffffffffffffffffffffffffffffffffff808316911614613eaf576040517f815e1d6400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b60006001836001811115613ecb57613ecb6149d6565b03613f8157600082604051602001613ee591815260200190565b6040516020818303038152906040528051906020012060001c9050600060198787604051602001613f4592919091825260c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016602082015260280190565b6040516020818303038152906040528051906020012060001c613f689190614e4f565b905080613f76606484614e4f565b111592505050613f85565b5060005b949350505050565b606060ff8314613fa757613fa0836140a4565b90506117a8565b818054613fb390614fe1565b80601f0160208091040260200160405190810160405280929190818152602001828054613fdf90614fe1565b801561402c5780601f106140015761010080835404028352916020019161402c565b820191906000526020600020905b81548152906001019060200180831161400f57829003601f168201915b505050505090506117a8565b60006117a86140456140e3565b836040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b600080600061408f8585614220565b9150915061409c81614265565b509392505050565b606060006140b183614418565b604080516020808252818301909252919250600091906020820181803683375050509182525060208101929092525090565b60003073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614801561414957507f000000000000000000000000000000000000000000000000000000000000000046145b1561417357507f000000000000000000000000000000000000000000000000000000000000000090565b61421b604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f0000000000000000000000000000000000000000000000000000000000000000918101919091527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b905090565b60008082516041036142565760208301516040840151606085015160001a61424a87828585614459565b9450945050505061425e565b506000905060025b9250929050565b6000816004811115614279576142796149d6565b036142815750565b6001816004811115614295576142956149d6565b036142fc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401611390565b6002816004811115614310576143106149d6565b03614377576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401611390565b600381600481111561438b5761438b6149d6565b03612b53576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152608401611390565b600060ff8216601f8111156117a8576040517fb3512b0c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115614490575060009050600361453f565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156144e4573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff81166145385760006001925092505061453f565b9150600090505b94509492505050565b5080546000825590600052602060002090810190612b5391905b808211156145765760008155600101614562565b5090565b803560ff8116811461458b57600080fd5b919050565b600080604083850312156145a357600080fd5b823591506145b36020840161457a565b90509250929050565b6000602082840312156145ce57600080fd5b5035919050565b600080604083850312156145e857600080fd5b50508035926020909101359150565b803573ffffffffffffffffffffffffffffffffffffffff8116811461458b57600080fd5b60006020828403121561462d57600080fd5b611a05826145f7565b80356003811061458b57600080fd5b60006020828403121561465757600080fd5b611a0582614636565b80356fffffffffffffffffffffffffffffffff8116811461458b57600080fd5b60006020828403121561469257600080fd5b611a0582614660565b803567ffffffffffffffff8116811461458b57600080fd5b600080604083850312156146c657600080fd5b823591506145b36020840161469b565b6000606082840312156146e857600080fd5b50919050565b60008083601f84011261470057600080fd5b50813567ffffffffffffffff81111561471857600080fd5b60208301915083602082850101111561425e57600080fd5b600080600080600060c0868803121561474857600080fd5b853594506147586020870161457a565b935061476787604088016146d6565b925060a086013567ffffffffffffffff81111561478357600080fd5b61478f888289016146ee565b969995985093965092949392505050565b80356002811061458b57600080fd5b6000602082840312156147c157600080fd5b611a05826147a0565b6000815180845260005b818110156147f0576020818501810151868301820152016147d4565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b7fff00000000000000000000000000000000000000000000000000000000000000881681526000602060e08184015261486a60e084018a6147ca565b838103604085015261487c818a6147ca565b6060850189905273ffffffffffffffffffffffffffffffffffffffff8816608086015260a0850187905284810360c0860152855180825283870192509083019060005b818110156148db578351835292840192918401916001016148bf565b50909c9b505050505050505050505050565b600080600080600060a0868803121561490557600080fd5b61490e866145f7565b945061491c60208701614660565b935061492a6040870161457a565b925061493860608701614636565b9150614946608087016147a0565b90509295509295909350565b6000806040838503121561496557600080fd5b61496e836145f7565b946020939093013593505050565b6020808252825182820181905260009190848201906040850190845b818110156149ca57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101614998565b50909695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60038110614a1557614a156149d6565b9052565b60028110614a1557614a156149d6565b815173ffffffffffffffffffffffffffffffffffffffff16815261014081016020830151614a5c602084018260ff169052565b506040830151614a6f6040840182614a05565b506060830151614a826060840182614a19565b506080830151614aa660808401826fffffffffffffffffffffffffffffffff169052565b5060a0830151614aca60a08401826fffffffffffffffffffffffffffffffff169052565b5060c0830151614aee60c08401826fffffffffffffffffffffffffffffffff169052565b5060e0830151614b0a60e084018267ffffffffffffffff169052565b506101008381015163ffffffff16908301526101208084015160ff8116828501525b505092915050565b600060608284031215614b4657600080fd5b6040516060810181811067ffffffffffffffff82111715614b90577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405282358152614ba36020840161469b565b6020820152604083013560408201528091505092915050565b60008060008060008060e08789031215614bd557600080fd5b86359550614be56020880161457a565b9450614bf360408801614660565b9350614c0288606089016146d6565b925060c087013567ffffffffffffffff811115614c1e57600080fd5b614c2a89828a016146ee565b979a9699509497509295939492505050565b8015158114612b5357600080fd5b60008060408385031215614c5d57600080fd5b614c66836145f7565b91506020830135614c7681614c3c565b809150509250929050565b60008060808385031215614c9457600080fd5b823591506145b384602085016146d6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156117a8576117a8614cd4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b600060208284031215614d5757600080fd5b8151611a0581614c3c565b600060ff821660ff8103614d7857614d78614cd4565b60010192915050565b67ffffffffffffffff818116838216019080821115614da257614da2614cd4565b5092915050565b6fffffffffffffffffffffffffffffffff828116828216039080821115614da257614da2614cd4565b600063ffffffff808316818103614deb57614deb614cd4565b6001019392505050565b80820281158282048414176117a8576117a8614cd4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082614e4a57614e4a614e0c565b500490565b600082614e5e57614e5e614e0c565b500690565b600060208284031215614e7557600080fd5b611a058261469b565b60ff81811683821601908111156117a8576117a8614cd4565b600060208284031215614ea957600080fd5b5051919050565b6fffffffffffffffffffffffffffffffff818116838216019080821115614da257614da2614cd4565b6fffffffffffffffffffffffffffffffff818116838216028082169190828114614b2c57614b2c614cd4565b60006fffffffffffffffffffffffffffffffff80841680614f2857614f28614e0c565b92169190910492915050565b808201808211156117a8576117a8614cd4565b600060ff831680614f5a57614f5a614e0c565b8060ff84160691505092915050565b600067ffffffffffffffff80841680614f8457614f84614e0c565b92169190910692915050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614fc157614fc1614cd4565b5060010190565b60ff82811682821603908111156117a8576117a8614cd4565b600181811c90821680614ff557607f821691505b6020821081036146e8577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fdfea26469706673582212201ede09760f66a31d17f5e2a9522175e60e0ca768cea14188a402a917d3a7a6c564736f6c63430008150033000000000000000000000000a92bfe11459e75c994dc612d4f64b7f2935a732d000000000000000000000000a92bfe11459e75c994dc612d4f64b7f2935a732d0000000000000000000000006b572731fd736a4e78f7307e27d8a2cba622ca02
Deployed Bytecode
0x6080604052600436106101e75760003560e01c806384b0196e11610102578063ddca3f4311610095578063f2fde38b11610064578063f2fde38b14610687578063f6927e7d146106a7578063f8b2cb4f146106c7578063feff17441461070a576101f1565b8063ddca3f43146105f4578063e00dd1611461063e578063e3d5c08c14610654578063ed64346214610674576101f1565b8063a480ca79116100d1578063a480ca7914610507578063c1e3bd3e14610527578063d266e83b14610554578063dc6f867c146105c7576101f1565b806384b0196e1461047f5780638da5cb5b146104a75780639738f87b146104d4578063a06412ac146104e7576101f1565b80633687f24a1161017a57806358db40d81161014957806358db40d8146103f2578063681b950d146104125780636999b3771461043257806379fa35071461045f576101f1565b80633687f24a146103655780633ed4c678146103855780634266580a146103a5578063450bde78146103d2576101f1565b80631aed59f0116101b65780631aed59f0146102775780631f6dc875146102c15780631fc6a5db1461031757806334fe228714610345576101f1565b806301fe1fdc14610202578063049878f3146102245780630ca522081461023757806314c9216a14610257576101f1565b366101f157600080fd5b3480156101fd57600080fd5b600080fd5b34801561020e57600080fd5b5061022261021d366004614590565b610758565b005b6102226102323660046145bc565b610cdd565b34801561024357600080fd5b506102226102523660046145bc565b611313565b34801561026357600080fd5b50610222610272366004614590565b61139e565b34801561028357600080fd5b506102976102923660046145d5565b611763565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102cd57600080fd5b506103076102dc36600461461b565b73ffffffffffffffffffffffffffffffffffffffff166000908152600a602052604090205460ff1690565b60405190151581526020016102b8565b34801561032357600080fd5b506103376103323660046145bc565b6117ae565b6040519081526020016102b8565b34801561035157600080fd5b50610307610360366004614645565b6117fa565b34801561037157600080fd5b50610222610380366004614680565b611823565b34801561039157600080fd5b506102226103a036600461461b565b611905565b3480156103b157600080fd5b506006546102979073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103de57600080fd5b506103376103ed3660046146b3565b61199d565b3480156103fe57600080fd5b5061022261040d36600461461b565b611a0c565b34801561041e57600080fd5b5061022261042d366004614730565b611ad4565b34801561043e57600080fd5b506003546102979073ffffffffffffffffffffffffffffffffffffffff1681565b34801561046b57600080fd5b5061030761047a3660046147af565b6121fa565b34801561048b57600080fd5b50610494612219565b6040516102b8979695949392919061482e565b3480156104b357600080fd5b506000546102979073ffffffffffffffffffffffffffffffffffffffff1681565b6102226104e23660046148ed565b6122be565b3480156104f357600080fd5b50610337610502366004614952565b6128df565b34801561051357600080fd5b5061022261052236600461461b565b612927565b34801561053357600080fd5b506105476105423660046145bc565b612b56565b6040516102b8919061497c565b34801561056057600080fd5b5061030761056f366004614952565b6040805173ffffffffffffffffffffffffffffffffffffffff9390931660208085019190915283820192909252805180840382018152606090930181528251928201929092206000908152600c909152205460ff1690565b3480156105d357600080fd5b506105e76105e23660046145bc565b612bcf565b6040516102b89190614a29565b34801561060057600080fd5b5060045461061d906fffffffffffffffffffffffffffffffff1681565b6040516fffffffffffffffffffffffffffffffff90911681526020016102b8565b34801561064a57600080fd5b5061033760055481565b34801561066057600080fd5b5061033761066f366004614b34565b612dbf565b610222610682366004614bbc565b612e42565b34801561069357600080fd5b506102226106a236600461461b565b6137aa565b3480156106b357600080fd5b506102226106c2366004614c4a565b61389b565b3480156106d357600080fd5b506103376106e236600461461b565b73ffffffffffffffffffffffffffffffffffffffff1660009081526008602052604090205490565b34801561071657600080fd5b5061072a610725366004614c81565b613972565b604080516fffffffffffffffffffffffffffffffff90941684529115156020840152908201526060016102b8565b6000828152600b6020908152604080832060099092529091203233146107aa576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002820154700100000000000000000000000000000000900467ffffffffffffffff1615610804576040517f1fbde44500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff16818460ff168154811061083057610830614ca5565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1614610889576040517fc394a43300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018281018054845473ffffffffffffffffffffffffffffffffffffffff16600081815260086020526040902080547001000000000000000000000000000000009093046fffffffffffffffffffffffffffffffff9081169384900390915583547fffffffffffffffffffffffffffffffff0000000000000000000000000000000081169082168490039091161790925583549092106109d957600086815260096020526040812061093a91614548565b6000868152600b6020908152604080832080547fffffffffffffffffff00000000000000000000000000000000000000000000001681556001810184905560020180547fffffff000000000000000000000000000000000000000000000000000000000016905551828152829189917f4fc9df21c274d2396432490df6fcda723ce987bc1b640015d34b26ca0ed98063910160405180910390a4610b41565b825483906109e990600190614d03565b815481106109f9576109f9614ca5565b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16838660ff1681548110610a3957610a39614ca5565b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082805480610a9157610a91614d16565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690550190558254610af690607f614d03565b6002850180547fffffffffffffffffffffffffffffffff000000000000000000000000000000008116600190931b6fffffffffffffffffffffffffffffffff91821618169190911790555b6040805133602080830191909152818301899052825180830384018152606090920183528151918101919091206000908152600c9091522080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905573ffffffffffffffffffffffffffffffffffffffff8116610bfe5760405133906fffffffffffffffffffffffffffffffff841680156108fc02916000818181858888f19350505050158015610bf8573d6000803e3d6000fd5b50610ca8565b6040517fa9059cbb0000000000000000000000000000000000000000000000000000000081523360048201526fffffffffffffffffffffffffffffffff8316602482015273ffffffffffffffffffffffffffffffffffffffff82169063a9059cbb906044016020604051808303816000875af1158015610c82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ca69190614d45565b505b604051339087907ff9b63d6ab6b86370bd291baf2443198e10294bc1a369e21ff12b34b904cb0fff90600090a3505050505050565b6000818152600b602052604090208054600182015473ffffffffffffffffffffffffffffffffffffffff9091169070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16333214610d6a576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002830154700100000000000000000000000000000000900467ffffffffffffffff1615610dc4576040517f1fbde44500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028301546fffffffffffffffffffffffffffffffff16600003610e14576040517f477383f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805133602080830191909152818301879052825180830384018152606090920183528151918101919091206000818152600c9092529190205460ff1615610e88576040517e3b268200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600085815260096020908152604080832080546002890180546fffffffffffffffffffffffffffffffff600160ff607f869003811682901b8316838516177fffffffffffffffffffffffffffffffff00000000000000000000000000000000948516179094558c810180548084168d01841694169390931790925573ffffffffffffffffffffffffffffffffffffffff8b168852600887528588208054918b169190910190558354808201855593875285872090930180547fffffffffffffffffffffffff00000000000000000000000000000000000000001633179055868652600c9094529190932080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016909317909255855474010000000000000000000000000000000000000000900416610fc082614d62565b91508160ff160361118957610fd6606342614d81565b60028601805467ffffffffffffffff92909216700100000000000000000000000000000000027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff909216919091179055845461104d9060ff7401000000000000000000000000000000000000000090910416613bde565b60028601805460ff929092167c0100000000000000000000000000000000000000000000000000000000027fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff90921691909117905560018501546000906110c5906fffffffffffffffffffffffffffffffff16613c20565b60018701546110e691906fffffffffffffffffffffffffffffffff16614da9565b6001870180547fffffffffffffffffffffffffffffffff0000000000000000000000000000000081166fffffffffffffffffffffffffffffffff91821684900382161790915573ffffffffffffffffffffffffffffffffffffffff87166000908152600860205260408082208054938516909303909255905191925088917e6e0c97de781a7389d44ba8fd35d1467cabb17ed04d038d166d34ab819213f39190a2505b73ffffffffffffffffffffffffffffffffffffffff84166111f457826fffffffffffffffffffffffffffffffff1634146111ef576040517faa82224900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6112dc565b341561122c576040517faa82224900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f23b872dd0000000000000000000000000000000000000000000000000000000081523360048201523060248201526fffffffffffffffffffffffffffffffff8416604482015273ffffffffffffffffffffffffffffffffffffffff8516906323b872dd906064016020604051808303816000875af11580156112b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112da9190614d45565b505b6005546040513391907fc0081eeafa0d002abcd7d58d84b6e688d1526b9c3d915a282212ba08c49a17a790600090a3505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611399576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b600755565b6000828152600b602052604090206002810154700100000000000000000000000000000000900467ffffffffffffffff16333214611408576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff811615806114285750428167ffffffffffffffff16115b1561145f576040517f6f312cbd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000848152600960205260409020805433919060ff861690811061148557611485614ca5565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16146114de576040517fc394a43300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600282015482546000918291829161154b916fffffffffffffffffffffffffffffffff82169160ff7c010000000000000000000000000000000000000000000000000000000090910481169188917401000000000000000000000000000000000000000090910416613c5a565b9250925092508560ff16811461158d576040517fc6e1dd1d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b818061159e575061159e8387613dbd565b156115d5576040517f477383f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6115df8387613de3565b611615576040517ff6fa148200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61161f8387613e1c565b6002860180546fffffffffffffffffffffffffffffffff929092167fffffff00ffffffffffffffffffffffff00000000000000000000000000000000909216919091177c010000000000000000000000000000000000000000000000000000000060ff891602177fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004267ffffffffffffffff1602178082556018906116f8907801000000000000000000000000000000000000000000000000900463ffffffff16614dd2565b91906101000a81548163ffffffff021916908363ffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff16877f537f4d0c896772cdfaaac608ab3c4705fe48cc44b3a2e63451b4a7eb9808ba1b60405160405180910390a350505050505050565b600082815260096020526040812080548390811061178357611783614ca5565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1690505b92915050565b600454600090612710906117d4906fffffffffffffffffffffffffffffffff1682614da9565b6117f0906fffffffffffffffffffffffffffffffff1684614df5565b6117a89190614e3b565b600081600281111561180e5761180e6149d6565b60ff16600754901c6001166001149050919050565b60035473ffffffffffffffffffffffffffffffffffffffff163314611874576040517f48f5c3ed00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e86fffffffffffffffffffffffffffffffff821611156118c2576040517ff4df6ae500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600480547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff92909216919091179055565b60035473ffffffffffffffffffffffffffffffffffffffff163314611956576040517f48f5c3ed00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6000601983836040516020016119e292919091825260c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016602082015260280190565b6040516020818303038152906040528051906020012060001c611a059190614e4f565b9392505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611a8d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401611390565b600680547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6000858152600b602052604090206002810154700100000000000000000000000000000000900467ffffffffffffffff16333214611b3e576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028201546fffffffffffffffffffffffffffffffff16600003611b8e576040517f646cf55800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff81161580611bae5750428167ffffffffffffffff16115b15611be5576040517f6f312cbd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000878152600960205260409020805433919060ff8916908110611c0b57611c0b614ca5565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1614611c64576040517fc394a43300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028201547801000000000000000000000000000000000000000000000000900463ffffffff1615801590611cc8575060018254760100000000000000000000000000000000000000000000900460ff166001811115611cc657611cc66149d6565b145b15611e9b5760028201547801000000000000000000000000000000000000000000000000900463ffffffff1660408601358814611d31576040517ff5d2101e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff8116611d486040880160208901614e63565b67ffffffffffffffff1614611d89576040517f63e0897a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611dd7611d9b36889003880188614b34565b86868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613e3f92505050565b8254611e0b90899063ffffffff841690760100000000000000000000000000000000000000000000900460ff168935613eb5565b15611e99576002830154611e55906fffffffffffffffffffffffffffffffff8116907c0100000000000000000000000000000000000000000000000000000000900460ff16613e1c565b6002840180547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff929092169190911790555b505b600282015482546000918291611f05916fffffffffffffffffffffffffffffffff81169160ff7c0100000000000000000000000000000000000000000000000000000000909204821691879174010000000000000000000000000000000000000000900416613c5a565b5091509150611f148289613de3565b611f4a576040517ff6fa148200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80158015611f5f5750611f5d8289613dbd565b155b15611f96576040517fa63065ca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180850180547fffffffffffffffffffffffffffffffff000000000000000000000000000000008116909155855473ffffffffffffffffffffffffffffffffffffffff908116600090815260086020908152604080832080546fffffffffffffffffffffffffffffffff90961695869003905589548f8452600b835281842080547fffffffffffffffffff0000000000000000000000000000000000000000000000168155968701849055600290960180547fffffff00000000000000000000000000000000000000000000000000000000001690556009909152812092939091169161208391614548565b73ffffffffffffffffffffffffffffffffffffffff81166120e25760405133906fffffffffffffffffffffffffffffffff841680156108fc02916000818181858888f193505050501580156120dc573d6000803e3d6000fd5b5061218c565b6040517fa9059cbb0000000000000000000000000000000000000000000000000000000081523360048201526fffffffffffffffffffffffffffffffff8316602482015273ffffffffffffffffffffffffffffffffffffffff82169063a9059cbb906044016020604051808303816000875af1158015612166573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218a9190614d45565b505b6040516fffffffffffffffffffffffffffffffff8316815273ffffffffffffffffffffffffffffffffffffffff82169033908d907f4fc9df21c274d2396432490df6fcda723ce987bc1b640015d34b26ca0ed980639060200160405180910390a45050505050505050505050565b600081600181111561220e5761220e6149d6565b61180e906080614e7e565b60006060808280808361224d7f546f6e74696e65000000000000000000000000000000000000000000000000076001613f8d565b6122787f31000000000000000000000000000000000000000000000000000000000000016002613f8d565b604080516000808252602082019092527f0f000000000000000000000000000000000000000000000000000000000000009b939a50919850469750309650945092509050565b3233146122f7576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600260ff8416108061230c5750606460ff8416115b15612343576040517f59e59f3f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b836fffffffffffffffffffffffffffffffff1660000361238f576040517faa82224900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612398826117fa565b15806123aa57506123a8816121fa565b155b156123e1576040517fa0042b1700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff85166000908152600a602052604090205460ff16612440576040517fc891add200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6005546000908152600b60205260409020805460ff851674010000000000000000000000000000000000000000027fffffffffffffffffffffff00000000000000000000000000000000000000000090911673ffffffffffffffffffffffffffffffffffffffff88161717808255839082907fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000008360028111156124fd576124fd6149d6565b02179055508054829082907fffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffff16760100000000000000000000000000000000000000000000836001811115612554576125546149d6565b02179055506fffffffffffffffffffffffffffffffff851670010000000000000000000000000000000081027fffffffffffffffffffffffffffffffff0000000000000000000000000000000090811682176001808501919091556002840180549092166f8000000000000000000000000000000017909155600580546000908152600960209081526040808320805480870182559084528284200180547fffffffffffffffffffffffff0000000000000000000000000000000000000000163390811790915573ffffffffffffffffffffffffffffffffffffffff8d16845260089092528220805490950190945581548301918290559192600c92916126ab9190612661908690614d03565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602082015290810182905260009060600160405160208183030381529060405280519060200120905092915050565b8152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001691151591909117905573ffffffffffffffffffffffffffffffffffffffff861661275357846fffffffffffffffffffffffffffffffff16341461274e576040517faa82224900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61283b565b341561278b576040517faa82224900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f23b872dd0000000000000000000000000000000000000000000000000000000081523360048201523060248201526fffffffffffffffffffffffffffffffff8616604482015273ffffffffffffffffffffffffffffffffffffffff8716906323b872dd906064016020604051808303816000875af1158015612815573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128399190614d45565b505b8573ffffffffffffffffffffffffffffffffffffffff16856fffffffffffffffffffffffffffffffff1660016005546128749190614d03565b6040517f7bc3e781453a761be4ae9daaacb192000aff04f1c45c3bf9ca9e118b4c9e2e9c90600090a460055433906128ae90600190614d03565b6040517fc0081eeafa0d002abcd7d58d84b6e688d1526b9c3d915a282212ba08c49a17a790600090a3505050505050565b6040805173ffffffffffffffffffffffffffffffffffffffff841660208083019190915281830184905282518083038401815260609092019092528051910120600090611a05565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600a602052604090205460ff16612986576040517fc891add200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8116612a085760035473ffffffffffffffffffffffffffffffffffffffff8281166000908152600860205260409020549116906108fc906129dc9047614d03565b6040518115909202916000818181858888f19350505050158015612a04573d6000803e3d6000fd5b5050565b60035473ffffffffffffffffffffffffffffffffffffffff828116600081815260086020526040908190205490517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152919363a9059cbb93169184906370a0823190602401602060405180830381865afa158015612a91573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ab59190614e97565b612abf9190614d03565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff909216600483015260248201526044016020604051808303816000875af1158015612b2f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a049190614d45565b50565b600081815260096020908152604091829020805483518184028101840190945280845260609392830182828015612bc357602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311612b98575b50505050509050919050565b612c256040805161014081018252600080825260208201819052909182019081526020016000815260006020820181905260408201819052606082018190526080820181905260a0820181905260c09091015290565b6000828152600b6020908152604091829020825161014081018452815473ffffffffffffffffffffffffffffffffffffffff8116825260ff74010000000000000000000000000000000000000000820481169483019490945290939192918401917501000000000000000000000000000000000000000000909104166002811115612cb257612cb26149d6565b6002811115612cc357612cc36149d6565b81528154602090910190760100000000000000000000000000000000000000000000900460ff166001811115612cfb57612cfb6149d6565b6001811115612d0c57612d0c6149d6565b815260018201546fffffffffffffffffffffffffffffffff808216602084015270010000000000000000000000000000000091829004811660408401526002909301549283166060830152820467ffffffffffffffff1660808201527801000000000000000000000000000000000000000000000000820463ffffffff1660a08201527c010000000000000000000000000000000000000000000000000000000090910460ff1660c09091015292915050565b60006117a87fd133bbc7f95acfb85dec01a77edf5a7c3665782f8a05b72294c6bdf7fb8b115c836000015184602001518560400151604051602001612e279493929190938452602084019290925267ffffffffffffffff166040830152606082015260800190565b60405160208183030381529060405280519060200120614038565b6000868152600b602052604090206002810154700100000000000000000000000000000000900467ffffffffffffffff16333214612eac576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff81161580612ecc5750428167ffffffffffffffff16115b15612f03576040517f6f312cbd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000888152600960205260409020805433919060ff8a16908110612f2957612f29614ca5565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1614612f82576040517fc394a43300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028201547801000000000000000000000000000000000000000000000000900463ffffffff1615801590612fe6575060018254760100000000000000000000000000000000000000000000900460ff166001811115612fe457612fe46149d6565b145b1561317d5760028201547801000000000000000000000000000000000000000000000000900463ffffffff166040860135891461304f576040517ff5d2101e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff81166130666040880160208901614e63565b67ffffffffffffffff16146130a7576040517f63e0897a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6130b9611d9b36889003880188614b34565b82546130ed908a9063ffffffff841690760100000000000000000000000000000000000000000000900460ff168935613eb5565b1561317b576002830154613137906fffffffffffffffffffffffffffffffff8116907c0100000000000000000000000000000000000000000000000000000000900460ff16613e1c565b6002840180547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff929092169190911790555b505b60028201548254600091829182916131ea916fffffffffffffffffffffffffffffffff82169160ff7c010000000000000000000000000000000000000000000000000000000090910481169188917401000000000000000000000000000000000000000090910416613c5a565b9250925092508960ff16811461322c576040517fc6e1dd1d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b818061323d575061323d838b613dbd565b15613274576040517f477383f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018501546fffffffffffffffffffffffffffffffff7001000000000000000000000000000000009091048116908a16108015906132e05750600185547501000000000000000000000000000000000000000000900460ff1660028111156132de576132de6149d6565b145b1561331c576001850180546fffffffffffffffffffffffffffffffff808c167001000000000000000000000000000000000291161790556133d6565b600285547501000000000000000000000000000000000000000000900460ff16600281111561334d5761334d6149d6565b036133d6576127106133616103e882614eb0565b6001870154613396919070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16614ed9565b6133a09190614f05565b6001860180546fffffffffffffffffffffffffffffffff9283167001000000000000000000000000000000000292169190911790555b600185015460009061340d9070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16613c20565b60018701805491925082916000906134389084906fffffffffffffffffffffffffffffffff16614eb0565b82546101009290920a6fffffffffffffffffffffffffffffffff818102199093169183160217909155875473ffffffffffffffffffffffffffffffffffffffff166000908152600860205260408120805492851693509161349a908490614f34565b90915550506002860180547fffffff00ffffffff0000000000000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004267ffffffffffffffff16027fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff16177c010000000000000000000000000000000000000000000000000000000060ff8e1602177fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff861617808255601890613593907801000000000000000000000000000000000000000000000000900463ffffffff16614dd2565b825463ffffffff9182166101009390930a9283029190920219909116179055855473ffffffffffffffffffffffffffffffffffffffff1661363657600186015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff163414613631576040517faa82224900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61373a565b341561366e576040517faa82224900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b855460018701546040517f23b872dd0000000000000000000000000000000000000000000000000000000081523360048201523060248201527001000000000000000000000000000000009091046fffffffffffffffffffffffffffffffff16604482015273ffffffffffffffffffffffffffffffffffffffff909116906323b872dd906064016020604051808303816000875af1158015613714573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137389190614d45565b505b60018601546040517001000000000000000000000000000000009091046fffffffffffffffffffffffffffffffff16815233908d907f34e592c5d9452abe7b4df38f36795ed86fbcded8a266d5bdeeaaf5375a8cf0d39060200160405180910390a3505050505050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461382b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401611390565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a350565b60005473ffffffffffffffffffffffffffffffffffffffff16331461391c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401611390565b73ffffffffffffffffffffffffffffffffffffffff919091166000908152600a6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b6000828152600b60209081526040808320815161014081018352815473ffffffffffffffffffffffffffffffffffffffff8116825260ff74010000000000000000000000000000000000000000820481169583019590955285948594859492908401917501000000000000000000000000000000000000000000909104166002811115613a0157613a016149d6565b6002811115613a1257613a126149d6565b81528154602090910190760100000000000000000000000000000000000000000000900460ff166001811115613a4a57613a4a6149d6565b6001811115613a5b57613a5b6149d6565b815260018201546fffffffffffffffffffffffffffffffff808216602084015270010000000000000000000000000000000091829004811660408401526002909301549283166060830152820467ffffffffffffffff90811660808301527801000000000000000000000000000000000000000000000000830463ffffffff1660a08301527c010000000000000000000000000000000000000000000000000000000090920460ff1660c09091015260e08201519192508116600003613b2e575060c00151925060009150819050613bd7565b600082610100015163ffffffff16118015613b5e5750600182606001516001811115613b5c57613b5c6149d6565b145b15613bb257613b828783610100015163ffffffff1684606001518960000135613eb5565b15613bb257613b9a8260c00151836101200151613e1c565b6fffffffffffffffffffffffffffffffff1660c08301525b613bce8260c0015183610120015160ff16838560200151613c5a565b94509450945050505b9250925092565b6000814442604051602001613bfd929190918252602082015260400190565b6040516020818303038152906040528051906020012060001c6117a89190614f47565b60045460009061271090613c46906fffffffffffffffffffffffffffffffff1682614da9565b613c509084614ed9565b6117a89190614f05565b60008060008360ff16600003613c7857506000915081905080613db3565b428567ffffffffffffffff161115613cbc5786600060ff8616613c9c896001614d81565b613ca69190614f69565b919450925067ffffffffffffffff169050613db3565b60006063613cd467ffffffffffffffff881642614d03565b613cde9190614e3b565b905060015b818111613d6d57600060ff8716613d048367ffffffffffffffff8c16614f34565b613d0e9190614e4f565b9050613d1a8a82613de3565b15613d5357613d298a82613dbd565b15613d42578995506001945060ff169250613db3915050565b613d4c8a82613e1c565b9950613d5a565b8260010192505b5080613d6581614f90565b915050613ce3565b50600060ff8616613d888367ffffffffffffffff8b16614f34565b613d93906001614f34565b613d9d9190614e4f565b905088613daa8a83613dbd565b90955093509150505b9450945094915050565b6000613dc98383613e1c565b6fffffffffffffffffffffffffffffffff16159392505050565b600080613df183607f614fc8565b60ff166001901b90508381166fffffffffffffffffffffffffffffffff166000141591505092915050565b600080613e2a83607f614fc8565b600160ff919091161b19841691505092915050565b6000613e4a83612dbf565b90506000613e588284614080565b60065490915073ffffffffffffffffffffffffffffffffffffffff808316911614613eaf576040517f815e1d6400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b60006001836001811115613ecb57613ecb6149d6565b03613f8157600082604051602001613ee591815260200190565b6040516020818303038152906040528051906020012060001c9050600060198787604051602001613f4592919091825260c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016602082015260280190565b6040516020818303038152906040528051906020012060001c613f689190614e4f565b905080613f76606484614e4f565b111592505050613f85565b5060005b949350505050565b606060ff8314613fa757613fa0836140a4565b90506117a8565b818054613fb390614fe1565b80601f0160208091040260200160405190810160405280929190818152602001828054613fdf90614fe1565b801561402c5780601f106140015761010080835404028352916020019161402c565b820191906000526020600020905b81548152906001019060200180831161400f57829003601f168201915b505050505090506117a8565b60006117a86140456140e3565b836040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b600080600061408f8585614220565b9150915061409c81614265565b509392505050565b606060006140b183614418565b604080516020808252818301909252919250600091906020820181803683375050509182525060208101929092525090565b60003073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000a9f25bac1e81d8558a1d738bbb275299333742b1614801561414957507f000000000000000000000000000000000000000000000000000000000000000146145b1561417357507f7ad6e81c91da69a1ef5c13b5ca89de3cab3f92d86b1a199e96b9b99cee30524590565b61421b604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f334e12643f9c85949b6ae031ea883c9b9d84f92aa0c86caecbc35f2fe550bf45918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b905090565b60008082516041036142565760208301516040840151606085015160001a61424a87828585614459565b9450945050505061425e565b506000905060025b9250929050565b6000816004811115614279576142796149d6565b036142815750565b6001816004811115614295576142956149d6565b036142fc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401611390565b6002816004811115614310576143106149d6565b03614377576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401611390565b600381600481111561438b5761438b6149d6565b03612b53576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152608401611390565b600060ff8216601f8111156117a8576040517fb3512b0c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115614490575060009050600361453f565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156144e4573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff81166145385760006001925092505061453f565b9150600090505b94509492505050565b5080546000825590600052602060002090810190612b5391905b808211156145765760008155600101614562565b5090565b803560ff8116811461458b57600080fd5b919050565b600080604083850312156145a357600080fd5b823591506145b36020840161457a565b90509250929050565b6000602082840312156145ce57600080fd5b5035919050565b600080604083850312156145e857600080fd5b50508035926020909101359150565b803573ffffffffffffffffffffffffffffffffffffffff8116811461458b57600080fd5b60006020828403121561462d57600080fd5b611a05826145f7565b80356003811061458b57600080fd5b60006020828403121561465757600080fd5b611a0582614636565b80356fffffffffffffffffffffffffffffffff8116811461458b57600080fd5b60006020828403121561469257600080fd5b611a0582614660565b803567ffffffffffffffff8116811461458b57600080fd5b600080604083850312156146c657600080fd5b823591506145b36020840161469b565b6000606082840312156146e857600080fd5b50919050565b60008083601f84011261470057600080fd5b50813567ffffffffffffffff81111561471857600080fd5b60208301915083602082850101111561425e57600080fd5b600080600080600060c0868803121561474857600080fd5b853594506147586020870161457a565b935061476787604088016146d6565b925060a086013567ffffffffffffffff81111561478357600080fd5b61478f888289016146ee565b969995985093965092949392505050565b80356002811061458b57600080fd5b6000602082840312156147c157600080fd5b611a05826147a0565b6000815180845260005b818110156147f0576020818501810151868301820152016147d4565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b7fff00000000000000000000000000000000000000000000000000000000000000881681526000602060e08184015261486a60e084018a6147ca565b838103604085015261487c818a6147ca565b6060850189905273ffffffffffffffffffffffffffffffffffffffff8816608086015260a0850187905284810360c0860152855180825283870192509083019060005b818110156148db578351835292840192918401916001016148bf565b50909c9b505050505050505050505050565b600080600080600060a0868803121561490557600080fd5b61490e866145f7565b945061491c60208701614660565b935061492a6040870161457a565b925061493860608701614636565b9150614946608087016147a0565b90509295509295909350565b6000806040838503121561496557600080fd5b61496e836145f7565b946020939093013593505050565b6020808252825182820181905260009190848201906040850190845b818110156149ca57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101614998565b50909695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60038110614a1557614a156149d6565b9052565b60028110614a1557614a156149d6565b815173ffffffffffffffffffffffffffffffffffffffff16815261014081016020830151614a5c602084018260ff169052565b506040830151614a6f6040840182614a05565b506060830151614a826060840182614a19565b506080830151614aa660808401826fffffffffffffffffffffffffffffffff169052565b5060a0830151614aca60a08401826fffffffffffffffffffffffffffffffff169052565b5060c0830151614aee60c08401826fffffffffffffffffffffffffffffffff169052565b5060e0830151614b0a60e084018267ffffffffffffffff169052565b506101008381015163ffffffff16908301526101208084015160ff8116828501525b505092915050565b600060608284031215614b4657600080fd5b6040516060810181811067ffffffffffffffff82111715614b90577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405282358152614ba36020840161469b565b6020820152604083013560408201528091505092915050565b60008060008060008060e08789031215614bd557600080fd5b86359550614be56020880161457a565b9450614bf360408801614660565b9350614c0288606089016146d6565b925060c087013567ffffffffffffffff811115614c1e57600080fd5b614c2a89828a016146ee565b979a9699509497509295939492505050565b8015158114612b5357600080fd5b60008060408385031215614c5d57600080fd5b614c66836145f7565b91506020830135614c7681614c3c565b809150509250929050565b60008060808385031215614c9457600080fd5b823591506145b384602085016146d6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156117a8576117a8614cd4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b600060208284031215614d5757600080fd5b8151611a0581614c3c565b600060ff821660ff8103614d7857614d78614cd4565b60010192915050565b67ffffffffffffffff818116838216019080821115614da257614da2614cd4565b5092915050565b6fffffffffffffffffffffffffffffffff828116828216039080821115614da257614da2614cd4565b600063ffffffff808316818103614deb57614deb614cd4565b6001019392505050565b80820281158282048414176117a8576117a8614cd4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082614e4a57614e4a614e0c565b500490565b600082614e5e57614e5e614e0c565b500690565b600060208284031215614e7557600080fd5b611a058261469b565b60ff81811683821601908111156117a8576117a8614cd4565b600060208284031215614ea957600080fd5b5051919050565b6fffffffffffffffffffffffffffffffff818116838216019080821115614da257614da2614cd4565b6fffffffffffffffffffffffffffffffff818116838216028082169190828114614b2c57614b2c614cd4565b60006fffffffffffffffffffffffffffffffff80841680614f2857614f28614e0c565b92169190910492915050565b808201808211156117a8576117a8614cd4565b600060ff831680614f5a57614f5a614e0c565b8060ff84160691505092915050565b600067ffffffffffffffff80841680614f8457614f84614e0c565b92169190910692915050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614fc157614fc1614cd4565b5060010190565b60ff82811682821603908111156117a8576117a8614cd4565b600181811c90821680614ff557607f821691505b6020821081036146e8577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fdfea26469706673582212201ede09760f66a31d17f5e2a9522175e60e0ca768cea14188a402a917d3a7a6c564736f6c63430008150033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000a92bfe11459e75c994dc612d4f64b7f2935a732d000000000000000000000000a92bfe11459e75c994dc612d4f64b7f2935a732d0000000000000000000000006b572731fd736a4e78f7307e27d8a2cba622ca02
-----Decoded View---------------
Arg [0] : _admin (address): 0xa92bFe11459e75c994dc612D4F64b7f2935a732D
Arg [1] : _feeController (address): 0xa92bFe11459e75c994dc612D4F64b7f2935a732D
Arg [2] : _rngSource (address): 0x6B572731fd736a4e78F7307e27d8a2CbA622cA02
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000a92bfe11459e75c994dc612d4f64b7f2935a732d
Arg [1] : 000000000000000000000000a92bfe11459e75c994dc612d4f64b7f2935a732d
Arg [2] : 0000000000000000000000006b572731fd736a4e78f7307e27d8a2cba622ca02
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | 100.00% | $3,155 | 0.8635 | $2,724.34 |
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.