Overview
POL Balance
0 POL
POL Value
$0.00Token Holdings
More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 1,906 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Withdraw House E... | 56276160 | 219 days ago | IN | 0 POL | 0.03649035 | ||||
Withdraw House E... | 48169657 | 428 days ago | IN | 0 POL | 0.00280936 | ||||
Withdraw House E... | 43887919 | 536 days ago | IN | 0 POL | 0.02093051 | ||||
Withdraw House E... | 40004996 | 636 days ago | IN | 0 POL | 0.00394735 | ||||
Withdraw House E... | 37096331 | 711 days ago | IN | 0 POL | 0.01316278 | ||||
Withdraw House E... | 36426685 | 728 days ago | IN | 0 POL | 0.00249093 | ||||
Withdraw House E... | 35326083 | 755 days ago | IN | 0 POL | 0.01207641 | ||||
Withdraw Referra... | 35326074 | 755 days ago | IN | 0 POL | 0.00877832 | ||||
Withdraw Partner... | 35325532 | 755 days ago | IN | 0 POL | 0.01668027 | ||||
Withdraw House E... | 34490022 | 775 days ago | IN | 0 POL | 0.01186642 | ||||
Withdraw House E... | 34182214 | 782 days ago | IN | 0 POL | 0.00272825 | ||||
Harvest Dividend... | 34181729 | 782 days ago | IN | 0 POL | 0.00272511 | ||||
Withdraw House E... | 34157877 | 783 days ago | IN | 0 POL | 0.00272091 | ||||
Withdraw House E... | 33911591 | 789 days ago | IN | 0 POL | 0.00272091 | ||||
Withdraw House E... | 33881500 | 790 days ago | IN | 0 POL | 0.00272091 | ||||
Withdraw House E... | 33384288 | 802 days ago | IN | 0 POL | 0.00196467 | ||||
Withdraw Referra... | 33004093 | 811 days ago | IN | 0 POL | 0.00364862 | ||||
Withdraw Referra... | 32998770 | 811 days ago | IN | 0 POL | 0.00283442 | ||||
Withdraw Referra... | 32996994 | 811 days ago | IN | 0 POL | 0.00303321 | ||||
Withdraw Referra... | 32991739 | 811 days ago | IN | 0 POL | 0.00350032 | ||||
Withdraw Referra... | 32988190 | 811 days ago | IN | 0 POL | 0.00412179 | ||||
Withdraw Referra... | 32986416 | 811 days ago | IN | 0 POL | 0.004292 | ||||
Withdraw Referra... | 32984640 | 811 days ago | IN | 0 POL | 0.00326671 | ||||
Withdraw Referra... | 32982866 | 811 days ago | IN | 0 POL | 0.00310222 | ||||
Withdraw Referra... | 32979321 | 812 days ago | IN | 0 POL | 0.00345484 |
Latest 25 internal transactions (View All)
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
32898447 | 814 days ago | 63.66160132 POL | ||||
32898447 | 814 days ago | 96.12815338 POL | ||||
32898414 | 814 days ago | 16,624.05404528 POL | ||||
32897088 | 814 days ago | 0.86674601 POL | ||||
32894160 | 814 days ago | 446.90965607 POL | ||||
32891972 | 814 days ago | 1.15 POL | ||||
32891907 | 814 days ago | 1 POL | ||||
32891867 | 814 days ago | 0.62357142 POL | ||||
32891867 | 814 days ago | 0.045 POL | ||||
32891819 | 814 days ago | 1.5 POL | ||||
32891761 | 814 days ago | 3 POL | ||||
32891726 | 814 days ago | 2 POL | ||||
32891683 | 814 days ago | 1.5 POL | ||||
32891651 | 814 days ago | 1.54058333 POL | ||||
32891651 | 814 days ago | 0.0405 POL | ||||
32891567 | 814 days ago | 2 POL | ||||
32891527 | 814 days ago | 1.02705555 POL | ||||
32891527 | 814 days ago | 0.027 POL | ||||
32891434 | 814 days ago | 0.582 POL | ||||
32891434 | 814 days ago | 0.054 POL | ||||
32891383 | 814 days ago | 2 POL | ||||
32891346 | 814 days ago | 0.97 POL | ||||
32891346 | 814 days ago | 0.03 POL | ||||
32891298 | 814 days ago | 2.91 POL | ||||
32891298 | 814 days ago | 0.09 POL |
Loading...
Loading
Contract Name:
Bank
Compiler Version
v0.8.14+commit.80d49f37
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; import "@openzeppelin/contracts/access/AccessControl.sol"; import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/utils/Address.sol"; import "@chainlink/contracts/src/v0.8/KeeperCompatible.sol"; import {IReferral} from "./IReferral.sol"; // import "hardhat/console.sol"; /// @title BetSwirl's Bank /// @author Romuald Hog /// @notice The Bank contract holds the casino's funds, /// whitelist the games betting tokens, /// define the max bet amount based on a risk, /// payout the bet profit to user and collect the loss bet amount from the game's contract, /// split and allocate the house edge taken from each bet (won or loss), /// manage the tokens balance overflow to dynamically send overflowed tokens to the treasury and team. /// The admin role is transfered to a Timelock that execute administrative tasks, /// only the Games could payout the bet profit from the bank, and send the loss bet amount to the bank. /// @dev All rates are in basis point. contract Bank is AccessControl, KeeperCompatibleInterface { using SafeERC20 for IERC20; /// @notice Enum to identify the Chainlink Upkeep registration. enum UpkeepActions { ManageBalanceOverflow, DistributePartnerHouseEdge, DistributeReferralHouseEdge } /// @notice Token's house edge allocations struct. /// The games house edge is split into several allocations. /// The allocated amounts stays in the bank until authorized parties withdraw. They are subtracted from the balance. /// @param dividend Rate to be allocated as staking rewards, on bet payout. /// @param referral Rate to be allocated to the referrers, on bet payout. /// @param partner Rate to be allocated to the partner, on bet payout. /// @param treasury Rate to be allocated to the treasury, on bet payout. /// @param team Rate to be allocated to the team, on bet payout. /// @param dividendAmount The number of tokens to be sent as staking rewards. /// @param partnerAmount The number of tokens to be sent to the partner. /// @param treasuryAmount The number of tokens to be sent to the treasury. /// @param teamAmount The number of tokens to be sent to the team. /// @param referralAmount The number of tokens to be sent to the referral program contract. /// @param minPartnerTransferAmount The minimum amount of token to distribute the partner house edge. struct HouseEdgeSplit { uint16 dividend; uint16 referral; uint16 partner; uint16 treasury; uint16 team; uint256 dividendAmount; uint256 partnerAmount; uint256 treasuryAmount; uint256 teamAmount; uint256 referralAmount; uint256 minPartnerTransferAmount; } /// @notice Token's balance overflow struct. /// @param thresholdRate Threshold rate for the token's balance reference. /// @param toTreasury Rate to be allocated to the treasury. /// @param toTeam Rate to be allocated to the team. struct BalanceOverflow { uint16 thresholdRate; uint16 toTreasury; uint16 toTeam; } /// @notice Token struct. /// List of tokens to bet on games. /// @param allowed Whether the token is allowed for bets. /// @param balanceRisk Defines the maximum bank payout, used to calculate the max bet amount. /// @param partner Address of the partner to manage the token and receive the house edge. /// @param houseEdgeSplit House edge allocations. /// @param balanceReference Balance reference used to manage the bank overflow. /// @param balanceOverflow Balance overflow management configuration. struct Token { bool allowed; uint16 balanceRisk; address partner; HouseEdgeSplit houseEdgeSplit; uint256 balanceReference; BalanceOverflow balanceOverflow; } /// @notice Token's metadata struct. It contains additional information from the ERC20 token. /// @dev Only used on the `getTokens` getter for the front-end. /// @param decimals Number of token's decimals. /// @param tokenAddress Contract address of the token. /// @param name Name of the token. /// @param symbol Symbol of the token. /// @param token Token data. struct TokenMetadata { uint8 decimals; address tokenAddress; string name; string symbol; Token token; } /// @notice Number of tokens added. uint16 public tokensCount; /// @notice Chainlink Keeper Registry address. address public keeperRegistry; /// @notice Treasury multi-sig wallet. address payable public immutable treasury; /// @notice Team wallet. address payable public teamWallet; /// @notice Referral program contract. IReferral public referralProgram; /// @notice Role associated to Games smart contracts. bytes32 public constant GAME_ROLE = keccak256("GAME_ROLE"); /// @notice Role associated to SwirlMaster smart contract. bytes32 public constant SWIRLMASTER_ROLE = keccak256("SWIRLMASTER_ROLE"); /// @notice Maps tokens addresses to token configuration. mapping(address => Token) public tokens; /// @notice Maps tokens indexes to token address. mapping(uint16 => address) public tokensList; /// @notice Emitted after the team wallet is set. /// @param teamWallet The team wallet address. event SetTeamWallet(address teamWallet); /// @notice Emitted after the referral program is set. /// @param referralProgram The referral program address. event SetReferralProgram(address referralProgram); /// @notice Emitted after a token is added. /// @param token Address of the token. event AddToken(address token); /// @notice Emitted after the balance risk is set. /// @param balanceRisk Rate defining the balance risk. event SetBalanceRisk(address indexed token, uint16 balanceRisk); /// @notice Emitted after a token is allowed. /// @param token Address of the token. /// @param allowed Whether the token is allowed for betting. event SetAllowedToken(address indexed token, bool allowed); /// @notice Emitted after the Upkeep minimum transfer amount is set. /// @param token Address of the token. /// @param minPartnerTransferAmount Minimum amount of token to allow transfer. event SetMinPartnerTransferAmount( address indexed token, uint256 minPartnerTransferAmount ); /// @notice Emitted after a token partner is set. /// @param token Address of the token. /// @param partner Address of the partner. event SetTokenPartner(address indexed token, address partner); /// @notice Emitted after a token deposit. /// @param token Address of the token. /// @param amount The number of token deposited. event Deposit(address indexed token, uint256 amount); /// @notice Emitted after a token withdrawal. /// @param token Address of the token. /// @param amount The number of token withdrawn. event Withdraw(address indexed token, uint256 amount); /// @notice Emitted after the Chainlink Keeper Registry is set. /// @param keeperRegistry Address of the Keeper Registry. event SetKeeperRegistry(address keeperRegistry); /// @notice Emitted after the token's house edge allocations for bet payout is set. /// @param token Address of the token. /// @param dividend Rate to be allocated as staking rewards, on bet payout. /// @param referral Rate to be allocated to the referrers, on bet payout. /// @param partner Rate to be allocated to the partner, on bet payout. /// @param treasury Rate to be allocated to the treasury, on bet payout. /// @param team Rate to be allocated to the team, on bet payout. event SetTokenHouseEdgeSplit( address indexed token, uint16 dividend, uint16 referral, uint16 partner, uint16 treasury, uint16 team ); /// @notice Emitted after the token's treasury and team allocations are distributed. /// @param token Address of the token. /// @param treasuryAmount The number of tokens sent to the treasury. /// @param teamAmount The number of tokens sent to the team. event HouseEdgeDistribution( address indexed token, uint256 treasuryAmount, uint256 teamAmount ); /// @notice Emitted after the token's partner allocation is distributed. /// @param token Address of the token. /// @param partnerAmount The number of tokens sent to the partner. event HouseEdgePartnerDistribution( address indexed token, uint256 partnerAmount ); /// @notice Emitted after the token's referral allocation is distributed. /// @param token Address of the token. /// @param referralProgram The address of the Referral Program contract. /// @param referralAmount The number of tokens sent. event DistributeReferralAmount( address indexed token, address referralProgram, uint256 referralAmount ); /// @notice Emitted after the token's dividend allocation is distributed. /// @param token Address of the token. /// @param amount The number of tokens sent to the SwirlMaster. event HarvestDividend(address indexed token, uint256 amount); /// @notice Emitted after the token's balance overflow management configuration is set. /// @param token Address of the token. /// @param thresholdRate Threshold rate for the token's balance reference. /// @param toTreasury Rate to be allocated to the treasury. /// @param toTeam Rate to be allocated to the team. event SetBalanceOverflow( address indexed token, uint16 thresholdRate, uint16 toTreasury, uint16 toTeam ); /// @notice Emitted after the token's bank overflow amount is distributed to the treasury and team. /// @param token Address of the token. /// @param amountToTreasury The number of tokens sent to the treasury. /// @param amountToTeam The number of tokens sent to the team. event BankOverflowTransfer( address indexed token, uint256 amountToTreasury, uint256 amountToTeam ); /// @notice Emitted after the token's balance reference is set. /// This happends on deposit, withdraw and when the bank overflow threashold is reached. /// @param token Address of the token. /// @param balanceReference New balance reference used to determine the bank overflow. event SetBalanceReference(address indexed token, uint256 balanceReference); /// @notice Emitted after the token's house edge is allocated. /// @param token Address of the token. /// @param dividend The number of tokens allocated as staking rewards. /// @param referral The number of tokens allocated to the referrers. /// @param partner The number of tokens allocated to the partner. /// @param treasury The number of tokens allocated to the treasury. /// @param team The number of tokens allocated to the team. event AllocateHouseEdgeAmount( address indexed token, uint256 dividend, uint256 referral, uint256 partner, uint256 treasury, uint256 team ); /// @notice Emitted after the bet profit amount is sent to the user. /// @param token Address of the token. /// @param newBalance New token balance. /// @param profit Bet profit amount sent. event Payout(address indexed token, uint256 newBalance, uint256 profit); /// @notice Emitted after the bet amount is collected from the game smart contract. /// @param token Address of the token. /// @param newBalance New token balance. /// @param amount Bet amount collected. event CashIn(address indexed token, uint256 newBalance, uint256 amount); /// @notice Reverting error when trying to add an existing token. /// @param token Address of the token. error TokenExists(address token); /// @notice Reverting error when setting the house edge allocations, but the sum isn't 100%. /// @param splitSum Sum of the house edge allocations rates. error WrongHouseEdgeSplit(uint16 splitSum); /// @notice Reverting error when setting wrong balance overflow management configuration. error WrongBalanceOverflow(); /// @notice Reverting error when sender isn't allowed. error AccessDenied(); /// @notice Reverting error when referral program or team wallet is the zero address. error WrongAddress(); /// @notice Modifier that checks that an account is allowed to interact. /// @param role The required role. /// @param token The token address. modifier onlyTokenOwner(bytes32 role, address token) { address partner = tokens[token].partner; if (partner == address(0)) { _checkRole(role, msg.sender); } else if (msg.sender != partner) { revert AccessDenied(); } _; } /// @notice Initialize the contract's admin role to the deployer, and state variables. /// @param treasuryAddress Treasury multi-sig wallet. /// @param teamWalletAddress Team wallet. /// @param referralProgramAddress The referral program. constructor( address payable treasuryAddress, address payable teamWalletAddress, IReferral referralProgramAddress ) { // The ownership should then be transfered to the Timelock. _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); treasury = treasuryAddress; setTeamWallet(teamWalletAddress); setReferralProgram(referralProgramAddress); } /// @notice Transfers a specific amount of token to an address. /// Uses native transfer or ERC20 transfer depending on the token. /// @dev The 0x address is considered the gas token. /// @param user Address of destination. /// @param token Address of the token. /// @param amount Number of tokens. function _safeTransfer( address payable user, address token, uint256 amount ) private { if (_isGasToken(token)) { Address.sendValue(user, amount); } else { IERC20(token).safeTransfer(user, amount); } } /// @notice Sets the new token's balance reference. /// @param token Address of the token. /// @param newReference Balance amount corresponding to the new reference. function _setBalanceReference(address token, uint256 newReference) private { tokens[token].balanceReference = newReference; emit SetBalanceReference(token, newReference); } /// @notice Check if the token has the 0x address. /// @param token Address of the token. /// @return Whether the token's address is the 0x address. function _isGasToken(address token) private pure returns (bool) { return token == address(0); } /// @notice Deposit funds in the bank to allow gamers to win more. /// It is also setting the new balance reference, used to manage the bank overflow. /// ERC20 token allowance should be given prior to deposit. /// @param token Address of the token. /// @param amount Number of tokens. function deposit(address token, uint256 amount) external payable onlyTokenOwner(DEFAULT_ADMIN_ROLE, token) { uint256 balance = getBalance(token); if (_isGasToken(token)) { _setBalanceReference(token, balance); amount = msg.value; } else { _setBalanceReference(token, balance + amount); IERC20(token).safeTransferFrom(msg.sender, address(this), amount); } emit Deposit(token, amount); } /// @notice Withdraw funds from the bank to migrate. /// It is also setting the new balance reference, used to manage the bank overflow. /// @param token Address of the token. /// @param amount Number of tokens. function withdraw(address token, uint256 amount) external onlyTokenOwner(DEFAULT_ADMIN_ROLE, token) { _setBalanceReference(token, getBalance(token) - amount); _safeTransfer(payable(msg.sender), token, amount); emit Withdraw(token, amount); } /// @notice Sets the keeper registry address /// @param keeperRegistryAddress Chainlink Keeper Registry. function setKeeperRegistry(address keeperRegistryAddress) external onlyRole(DEFAULT_ADMIN_ROLE) { if (keeperRegistryAddress != keeperRegistry) { keeperRegistry = keeperRegistryAddress; emit SetKeeperRegistry(keeperRegistryAddress); } } /// @notice Sets the new token balance risk. /// @param token Address of the token. /// @param balanceRisk Risk rate. function setBalanceRisk(address token, uint16 balanceRisk) external onlyTokenOwner(DEFAULT_ADMIN_ROLE, token) { tokens[token].balanceRisk = balanceRisk; emit SetBalanceRisk(token, balanceRisk); } /// @notice Adds a new token that'll be enabled for the games' betting. /// Token shouldn't exist yet. /// @param token Address of the token. function addToken(address token) external onlyRole(DEFAULT_ADMIN_ROLE) { if (tokensCount != 0) { for (uint16 i; i < tokensCount; i++) { if (tokensList[i] == token) { revert TokenExists(token); } } } tokensList[tokensCount] = token; tokensCount += 1; emit AddToken(token); } /// @notice Changes the token's bet permission on an already added token. /// @param token Address of the token. /// @param allowed Whether the token is enabled for bets. function setAllowedToken(address token, bool allowed) external onlyRole(DEFAULT_ADMIN_ROLE) { tokens[token].allowed = allowed; emit SetAllowedToken(token, allowed); } /// @notice Changes the token's Upkeep min transfer amount. /// @param token Address of the token. /// @param minPartnerTransferAmount Minimum amount of token to allow transfer. function setMinPartnerTransferAmount( address token, uint256 minPartnerTransferAmount ) external onlyTokenOwner(DEFAULT_ADMIN_ROLE, token) { tokens[token] .houseEdgeSplit .minPartnerTransferAmount = minPartnerTransferAmount; emit SetMinPartnerTransferAmount(token, minPartnerTransferAmount); } /// @notice Changes the token's partner address. /// @param token Address of the token. /// @param partner Address of the partner. function setTokenPartner(address token, address partner) external onlyTokenOwner(DEFAULT_ADMIN_ROLE, token) { tokens[token].partner = partner; emit SetTokenPartner(token, partner); } /// @notice Sets the token's house edge allocations for bet payout. /// @param token Address of the token. /// @param dividend Rate to be allocated as staking rewards, on bet payout. /// @param referral Rate to be allocated to the referrers, on bet payout. /// @param _treasury Rate to be allocated to the treasury, on bet payout. /// @param team Rate to be allocated to the team, on bet payout. /// @dev `dividend`, `referral`, `_treasury` and `team` rates sum must equals 10000. function setHouseEdgeSplit( address token, uint16 dividend, uint16 referral, uint16 partner, uint16 _treasury, uint16 team ) external onlyRole(DEFAULT_ADMIN_ROLE) { uint16 splitSum = dividend + team + partner + _treasury + referral; if (splitSum != 10000) { revert WrongHouseEdgeSplit(splitSum); } HouseEdgeSplit storage tokenHouseEdge = tokens[token].houseEdgeSplit; tokenHouseEdge.dividend = dividend; tokenHouseEdge.referral = referral; tokenHouseEdge.partner = partner; tokenHouseEdge.treasury = _treasury; tokenHouseEdge.team = team; emit SetTokenHouseEdgeSplit( token, dividend, referral, partner, _treasury, team ); } /// @notice Sets the token's balance overflow management configuration. /// The threshold shouldn't exceed 100% to be able to calculate the overflowed amount. /// The treasury and team rates sum shouldn't exceed 100% to allow the bank balance to grow organically. /// @param token Address of the token. /// @param thresholdRate Threshold rate for the token's balance reference. /// @param toTreasury Rate to be allocated to the treasury. /// @param toTeam Rate to be allocated to the team. function setBalanceOverflow( address token, uint16 thresholdRate, uint16 toTreasury, uint16 toTeam ) external onlyRole(DEFAULT_ADMIN_ROLE) { if (thresholdRate > 10000 || (toTreasury + toTeam) > 10000) { revert WrongBalanceOverflow(); } tokens[token].balanceOverflow = BalanceOverflow( thresholdRate, toTreasury, toTeam ); emit SetBalanceOverflow(token, thresholdRate, toTreasury, toTeam); } /// @notice Harvests tokens dividends. /// @return The list of tokens addresses. /// @return The list of tokens' amounts harvested. function harvestDividends() external onlyRole(SWIRLMASTER_ROLE) returns (address[] memory, uint256[] memory) { address[] memory _tokens = new address[](tokensCount); uint256[] memory _amounts = new uint256[](tokensCount); for (uint16 i; i < tokensCount; i++) { address tokenAddress = tokensList[i]; Token storage token = tokens[tokenAddress]; uint256 dividendAmount = token.houseEdgeSplit.dividendAmount; if (dividendAmount != 0) { token.houseEdgeSplit.dividendAmount = 0; _safeTransfer( payable(msg.sender), tokenAddress, dividendAmount ); emit HarvestDividend(tokenAddress, dividendAmount); _tokens[i] = tokenAddress; _amounts[i] = dividendAmount; } } return (_tokens, _amounts); } /// @notice Get the available tokens dividends amounts. /// @return The list of tokens addresses. /// @return The list of tokens' amounts harvested. function getDividends() external view returns (address[] memory, uint256[] memory) { address[] memory _tokens = new address[](tokensCount); uint256[] memory _amounts = new uint256[](tokensCount); for (uint16 i; i < tokensCount; i++) { address tokenAddress = tokensList[i]; Token storage token = tokens[tokenAddress]; uint256 dividendAmount = token.houseEdgeSplit.dividendAmount; if (dividendAmount > 0) { _tokens[i] = tokenAddress; _amounts[i] = dividendAmount; } } return (_tokens, _amounts); } /// @notice Payouts a winning bet, and allocate the house edge fee. /// @param user Address of the gamer. /// @param token Address of the token. /// @param profit Number of tokens to be sent to the gamer. /// @param fees Bet amount and bet profit fees amount. function payout( address payable user, address token, uint256 profit, uint256 fees ) external payable onlyRole(GAME_ROLE) { // Splits the house edge fees and allocates them as dividends, for referrers, to the partner, the treasury, and team. // If the user has no referrer, the referral allocation is allocated evenly among the other allocations. { HouseEdgeSplit storage tokenHouseEdge = tokens[token] .houseEdgeSplit; // Calculate the referral allocation uint256 referralAllocation = (fees * tokenHouseEdge.referral) / 10000; uint256 referralAmount; if (referralAllocation != 0) { referralAmount = referralProgram.payReferral( user, token, referralAllocation ); referralAllocation -= referralAmount; } uint256 dividendAmount = (fees * tokenHouseEdge.dividend) / 10000; uint256 partnerAmount = (fees * tokenHouseEdge.partner) / 10000; uint256 treasuryAmount = (fees * tokenHouseEdge.treasury) / 10000; uint256 teamAmount = (fees * tokenHouseEdge.team) / 10000; uint8 allocationsCount; if (dividendAmount != 0) { allocationsCount++; } if (partnerAmount != 0) { allocationsCount++; } if (treasuryAmount != 0) { allocationsCount++; } if (teamAmount != 0) { allocationsCount++; } uint256 referralAllocationRestPerSplit; if (allocationsCount != 0) { referralAllocationRestPerSplit = (referralAllocation - (referralAllocation % allocationsCount)) / allocationsCount; } if (dividendAmount != 0) { dividendAmount += referralAllocationRestPerSplit; tokenHouseEdge.dividendAmount += dividendAmount; } if (partnerAmount != 0) { partnerAmount += referralAllocationRestPerSplit; tokenHouseEdge.partnerAmount += partnerAmount; } if (treasuryAmount != 0) { treasuryAmount += referralAllocationRestPerSplit; tokenHouseEdge.treasuryAmount += treasuryAmount; } if (teamAmount != 0) { teamAmount += referralAllocationRestPerSplit; tokenHouseEdge.teamAmount += teamAmount; } if (referralAmount != 0) { // If no registered Chainlink Keepers, transfer to the referral program. if (keeperRegistry == address(0)) { _safeTransfer( payable(address(referralProgram)), token, referralAmount ); } else { tokenHouseEdge.referralAmount += referralAmount; } } emit AllocateHouseEdgeAmount( token, dividendAmount, referralAmount, partnerAmount, treasuryAmount, teamAmount ); } // Pay the user _safeTransfer(user, token, profit); emit Payout(token, getBalance(token), profit); } /// @notice Accounts a loss bet. /// @dev In case of an ERC20, the bet amount should be transfered prior to this tx. /// @dev In case of the gas token, the bet amount is sent along with this tx. /// @param tokenAddress Address of the token. /// @param amount Loss bet amount. function cashIn(address tokenAddress, uint256 amount) external payable onlyRole(GAME_ROLE) { emit CashIn( tokenAddress, getBalance(tokenAddress), _isGasToken(tokenAddress) ? msg.value : amount ); } /// @notice Executed by Chainlink Keepers when `upkeepNeeded` is true. /// @param performData Data which was passed back from `checkUpkeep`. function performUpkeep(bytes calldata performData) external override { if (msg.sender != keeperRegistry) { revert AccessDenied(); } (UpkeepActions upkeepAction, address tokenAddress) = abi.decode( performData, (UpkeepActions, address) ); HouseEdgeSplit memory houseEdgeSplit = tokens[tokenAddress] .houseEdgeSplit; if (upkeepAction == UpkeepActions.ManageBalanceOverflow) { manageBalanceOverflow(tokenAddress); } else if ( upkeepAction == UpkeepActions.DistributePartnerHouseEdge && houseEdgeSplit.partnerAmount > houseEdgeSplit.minPartnerTransferAmount ) { withdrawPartnerAmount(tokenAddress); } else if ( upkeepAction == UpkeepActions.DistributeReferralHouseEdge && houseEdgeSplit.referralAmount > 0 ) { withdrawReferralAmount(tokenAddress); } } /// @dev For the front-end function getTokens() external view returns (TokenMetadata[] memory) { TokenMetadata[] memory _tokens = new TokenMetadata[](tokensCount); for (uint16 i; i < tokensCount; i++) { address tokenAddress = tokensList[i]; Token memory token = tokens[tokenAddress]; if (_isGasToken(tokenAddress)) { _tokens[i] = TokenMetadata({ decimals: 18, tokenAddress: tokenAddress, name: "ETH", symbol: "ETH", token: token }); } else { IERC20Metadata erc20Metadata = IERC20Metadata(tokenAddress); _tokens[i] = TokenMetadata({ decimals: erc20Metadata.decimals(), tokenAddress: tokenAddress, name: erc20Metadata.name(), symbol: erc20Metadata.symbol(), token: token }); } } return _tokens; } /// @notice Calculates the max bet amount based on the token balance, the balance risk, and the game multiplier. /// @param token Address of the token. /// @param multiplier The bet amount leverage determines the user's profit amount. 10000 = 100% = no profit. /// @return Maximum bet amount for the token. /// @dev The multiplier should be at least 10000. function getMaxBetAmount(address token, uint256 multiplier) external view returns (uint256) { return (getBalance(token) * tokens[token].balanceRisk) / multiplier; } /// @notice Gets the token's allow status used on the games smart contracts. /// @param token Address of the token. /// @return Whether the token is enabled for bets. function isAllowedToken(address token) external view returns (bool) { return tokens[token].allowed; } /// @notice Runs by Chainlink Keepers at every block to determine if `performUpkeep` should be called. /// @param checkData Fixed and specified at Upkeep registration. /// @return upkeepNeeded Boolean that when True will trigger the on-chain performUpkeep call. /// @return performData Bytes that will be used as input parameter when calling performUpkeep. /// @dev `checkData` and `performData` are encoded with types (uint8, address). function checkUpkeep(bytes calldata checkData) external view override returns (bool upkeepNeeded, bytes memory performData) { (UpkeepActions upkeepAction, address tokenAddressData) = abi.decode( checkData, (UpkeepActions, address) ); if (upkeepAction == UpkeepActions.DistributePartnerHouseEdge) { HouseEdgeSplit memory houseEdgeSplit = tokens[tokenAddressData] .houseEdgeSplit; if ( houseEdgeSplit.partnerAmount > houseEdgeSplit.minPartnerTransferAmount ) { upkeepNeeded = true; performData = abi.encode(upkeepAction, tokenAddressData); } } else { for (uint16 i; i < tokensCount; i++) { address tokenAddress = tokensList[i]; Token memory token = tokens[tokenAddress]; HouseEdgeSplit memory houseEdgeSplit = token.houseEdgeSplit; if ( upkeepAction == UpkeepActions.ManageBalanceOverflow && token.partner == address(0) ) { uint256 tokenBalance = getBalance(tokenAddress); uint256 overflow = (token.balanceReference + ((tokenBalance * token.balanceOverflow.thresholdRate) / 10000)); if (tokenBalance > overflow) { upkeepNeeded = true; performData = abi.encode(upkeepAction, tokenAddress); break; } } else if ( upkeepAction == UpkeepActions.DistributeReferralHouseEdge && houseEdgeSplit.referralAmount > 0 ) { upkeepNeeded = true; performData = abi.encode(upkeepAction, tokenAddress); } } } } /// @notice Sets the new team wallet. /// @param _teamWallet The team wallet address. function setTeamWallet(address payable _teamWallet) public onlyRole(DEFAULT_ADMIN_ROLE) { if (_teamWallet == address(0)) { revert WrongAddress(); } teamWallet = _teamWallet; emit SetTeamWallet(teamWallet); } /// @notice Sets the new referral program. /// @param _referralProgram The referral program address. function setReferralProgram(IReferral _referralProgram) public onlyRole(DEFAULT_ADMIN_ROLE) { if (address(_referralProgram) == address(0)) { revert WrongAddress(); } referralProgram = _referralProgram; emit SetReferralProgram(address(referralProgram)); } /// @notice Manages the balance overflow. /// @notice When the bank overflow threshold amount is reached on a token balance, /// the bank sends a percentage to the treasury and team, and the new token's balance reference is set. /// @param tokenAddress Address of the token. function manageBalanceOverflow(address tokenAddress) public { Token storage token = tokens[tokenAddress]; uint256 tokenBalance = getBalance(tokenAddress); uint256 overflow = (token.balanceReference + ((tokenBalance * token.balanceOverflow.thresholdRate) / 10000)); if (token.partner == address(0) && tokenBalance > overflow) { uint256 diff = tokenBalance - token.balanceReference; uint256 overflowAmountToTreasury = ((diff * token.balanceOverflow.toTreasury) / 10000); uint256 overflowAmountToTeam = ((diff * token.balanceOverflow.toTeam) / 10000); _setBalanceReference( tokenAddress, tokenBalance - overflowAmountToTreasury - overflowAmountToTeam ); uint256 treasuryAmount = token.houseEdgeSplit.treasuryAmount; uint256 teamAmount = token.houseEdgeSplit.teamAmount; token.houseEdgeSplit.treasuryAmount = 0; token.houseEdgeSplit.teamAmount = 0; _safeTransfer( treasury, tokenAddress, treasuryAmount + overflowAmountToTreasury ); _safeTransfer( teamWallet, tokenAddress, teamAmount + overflowAmountToTeam ); emit BankOverflowTransfer( tokenAddress, treasuryAmount + overflowAmountToTreasury, teamAmount + overflowAmountToTeam ); } } /// @notice Distributes the token's treasury and team allocations amounts. /// @param tokenAddress Address of the token. function withdrawHouseEdgeAmount(address tokenAddress) public { HouseEdgeSplit storage tokenHouseEdge = tokens[tokenAddress] .houseEdgeSplit; uint256 treasuryAmount = tokenHouseEdge.treasuryAmount; uint256 teamAmount = tokenHouseEdge.teamAmount; if (treasuryAmount != 0) { tokenHouseEdge.treasuryAmount = 0; _safeTransfer(treasury, tokenAddress, treasuryAmount); } if (teamAmount != 0) { tokenHouseEdge.teamAmount = 0; _safeTransfer(teamWallet, tokenAddress, teamAmount); } if (treasuryAmount != 0 || teamAmount != 0) { emit HouseEdgeDistribution( tokenAddress, treasuryAmount, teamAmount ); } } /// @notice Distributes the token's partner amount. /// @param tokenAddress Address of the token. function withdrawPartnerAmount(address tokenAddress) public { Token storage token = tokens[tokenAddress]; uint256 partnerAmount = token.houseEdgeSplit.partnerAmount; if (partnerAmount != 0 && token.partner != address(0)) { token.houseEdgeSplit.partnerAmount = 0; _safeTransfer(payable(token.partner), tokenAddress, partnerAmount); emit HouseEdgePartnerDistribution(tokenAddress, partnerAmount); } } /// @notice Distributes the token's referral amount. /// @param tokenAddress Address of the token. function withdrawReferralAmount(address tokenAddress) public { HouseEdgeSplit storage tokenHouseEdge = tokens[tokenAddress] .houseEdgeSplit; uint256 referralAmount = tokenHouseEdge.referralAmount; if (referralAmount != 0) { address referralProgramAddress = address(referralProgram); tokenHouseEdge.referralAmount = 0; _safeTransfer( payable(referralProgramAddress), tokenAddress, referralAmount ); emit DistributeReferralAmount( tokenAddress, referralProgramAddress, referralAmount ); } } /// @notice Gets the token's balance. /// The token's house edge allocation amounts are subtracted from the balance. /// @param token Address of the token. /// @return The amount of token available for profits. function getBalance(address token) public view returns (uint256) { uint256 balance; if (_isGasToken(token)) { balance = address(this).balance; } else { balance = IERC20(token).balanceOf(address(this)); } HouseEdgeSplit memory tokenHouseEdgeSplit = tokens[token] .houseEdgeSplit; return balance - tokenHouseEdgeSplit.dividendAmount - tokenHouseEdgeSplit.partnerAmount - tokenHouseEdgeSplit.treasuryAmount - tokenHouseEdgeSplit.teamAmount - tokenHouseEdgeSplit.referralAmount; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract KeeperBase { error OnlySimulatedBackend(); /** * @notice method that allows it to be simulated via eth_call by checking that * the sender is the zero address. */ function preventExecution() internal view { if (tx.origin != address(0)) { revert OnlySimulatedBackend(); } } /** * @notice modifier that allows it to be simulated via eth_call by checking * that the sender is the zero address. */ modifier cannotExecute() { preventExecution(); _; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./KeeperBase.sol"; import "./interfaces/KeeperCompatibleInterface.sol"; abstract contract KeeperCompatible is KeeperBase, KeeperCompatibleInterface {}
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface KeeperCompatibleInterface { /** * @notice method that is simulated by the keepers to see if any work actually * needs to be performed. This method does does not actually need to be * executable, and since it is only ever simulated it can consume lots of gas. * @dev To ensure that it is never called, you may want to add the * cannotExecute modifier from KeeperBase to your implementation of this * method. * @param checkData specified in the upkeep registration so it is always the * same for a registered upkeep. This can easily be broken down into specific * arguments using `abi.decode`, so multiple upkeeps can be registered on the * same contract and easily differentiated by the contract. * @return upkeepNeeded boolean to indicate whether the keeper should call * performUpkeep or not. * @return performData bytes that the keeper should call performUpkeep with, if * upkeep is needed. If you would like to encode data to decode later, try * `abi.encode`. */ function checkUpkeep(bytes calldata checkData) external returns (bool upkeepNeeded, bytes memory performData); /** * @notice method that is actually executed by the keepers, via the registry. * The data returned by the checkUpkeep simulation will be passed into * this method to actually be executed. * @dev The input to this method should not be trusted, and the caller of the * method should not even be restricted to any single registry. Anyone should * be able call it, and the input should be validated, there is no guarantee * that the data passed in is the performData returned from checkUpkeep. This * could happen due to malicious keepers, racing keepers, or simply a state * change while the performUpkeep transaction is waiting for confirmation. * Always validate the data passed in. * @param performData is the data which was passed back from the checkData * simulation. If it is encoded, it can easily be decoded into other types by * calling `abi.decode`. This data should not be trusted, and should be * validated against the contract's current state. */ function performUpkeep(bytes calldata performData) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControl.sol) pragma solidity ^0.8.0; import "./IAccessControl.sol"; import "../utils/Context.sol"; import "../utils/Strings.sol"; import "../utils/introspection/ERC165.sol"; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ``` * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ``` * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. */ abstract contract AccessControl is Context, IAccessControl, ERC165 { struct RoleData { mapping(address => bool) members; bytes32 adminRole; } mapping(bytes32 => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with a standardized message including the required role. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ * * _Available since v4.1._ */ modifier onlyRole(bytes32 role) { _checkRole(role, _msgSender()); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view virtual override returns (bool) { return _roles[role].members[account]; } /** * @dev Revert with a standard message if `account` is missing `role`. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ */ function _checkRole(bytes32 role, address account) internal view virtual { if (!hasRole(role, account)) { revert( string( abi.encodePacked( "AccessControl: account ", Strings.toHexString(uint160(account), 20), " is missing role ", Strings.toHexString(uint256(role), 32) ) ) ); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) public virtual override { require(account == _msgSender(), "AccessControl: can only renounce roles for self"); _revokeRole(role, account); } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. Note that unlike {grantRole}, this function doesn't perform any * checks on the calling account. * * [WARNING] * ==== * This function should only be called from the constructor when setting * up the initial roles for the system. * * Using this function in any other way is effectively circumventing the admin * system imposed by {AccessControl}. * ==== * * NOTE: This function is deprecated in favor of {_grantRole}. */ function _setupRole(bytes32 role, address account) internal virtual { _grantRole(role, account); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Grants `role` to `account`. * * Internal function without access restriction. */ function _grantRole(bytes32 role, address account) internal virtual { if (!hasRole(role, account)) { _roles[role].members[account] = true; emit RoleGranted(role, account, _msgSender()); } } /** * @dev Revokes `role` from `account`. * * Internal function without access restriction. */ function _revokeRole(bytes32 role, address account) internal virtual { if (hasRole(role, account)) { _roles[role].members[account] = false; emit RoleRevoked(role, account, _msgSender()); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) pragma solidity ^0.8.0; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControl { /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. * * _Available since v3.1._ */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @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] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; /// @notice Referral interface /// @author Romuald Hog. interface IReferral { /// @notice Adds an address as referrer. /// @param user The address of the user. /// @param referrer The address would set as referrer of user. function addReferrer(address user, address referrer) external; /// @notice Updates referrer's last active timestamp. /// @param user The address would like to update active time. function updateReferrerActivity(address user) external; /// @notice Calculates and allocate referrer(s) credits to uplines. /// @param user Address of the gamer to find referrer(s). /// @param token The token to allocate. /// @param amount The number of tokens allocated for referrer(s). function payReferral( address user, address token, uint256 amount ) external returns (uint256); /// @notice Utils function for check whether an address has the referrer. /// @param user The address of the user. /// @return Whether user has a referrer. function hasReferrer(address user) external view returns (bool); }
{ "evmVersion": "london", "libraries": {}, "metadata": { "bytecodeHash": "ipfs", "useLiteralContent": true }, "optimizer": { "enabled": true, "runs": 8000 }, "remappings": [], "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address payable","name":"treasuryAddress","type":"address"},{"internalType":"address payable","name":"teamWalletAddress","type":"address"},{"internalType":"contract IReferral","name":"referralProgramAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessDenied","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"TokenExists","type":"error"},{"inputs":[],"name":"WrongAddress","type":"error"},{"inputs":[],"name":"WrongBalanceOverflow","type":"error"},{"inputs":[{"internalType":"uint16","name":"splitSum","type":"uint16"}],"name":"WrongHouseEdgeSplit","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"}],"name":"AddToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"dividend","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"referral","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"partner","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"treasury","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"team","type":"uint256"}],"name":"AllocateHouseEdgeAmount","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountToTreasury","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountToTeam","type":"uint256"}],"name":"BankOverflowTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"newBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"CashIn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"referralProgram","type":"address"},{"indexed":false,"internalType":"uint256","name":"referralAmount","type":"uint256"}],"name":"DistributeReferralAmount","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"HarvestDividend","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"treasuryAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"teamAmount","type":"uint256"}],"name":"HouseEdgeDistribution","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"partnerAmount","type":"uint256"}],"name":"HouseEdgePartnerDistribution","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"newBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"profit","type":"uint256"}],"name":"Payout","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"bool","name":"allowed","type":"bool"}],"name":"SetAllowedToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint16","name":"thresholdRate","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"toTreasury","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"toTeam","type":"uint16"}],"name":"SetBalanceOverflow","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"balanceReference","type":"uint256"}],"name":"SetBalanceReference","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint16","name":"balanceRisk","type":"uint16"}],"name":"SetBalanceRisk","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"keeperRegistry","type":"address"}],"name":"SetKeeperRegistry","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"minPartnerTransferAmount","type":"uint256"}],"name":"SetMinPartnerTransferAmount","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"referralProgram","type":"address"}],"name":"SetReferralProgram","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"teamWallet","type":"address"}],"name":"SetTeamWallet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint16","name":"dividend","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"referral","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"partner","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"treasury","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"team","type":"uint16"}],"name":"SetTokenHouseEdgeSplit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"partner","type":"address"}],"name":"SetTokenPartner","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GAME_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SWIRLMASTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"addToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"cashIn","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"checkData","type":"bytes"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"getBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDividends","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"multiplier","type":"uint256"}],"name":"getMaxBetAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTokens","outputs":[{"components":[{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"components":[{"internalType":"bool","name":"allowed","type":"bool"},{"internalType":"uint16","name":"balanceRisk","type":"uint16"},{"internalType":"address","name":"partner","type":"address"},{"components":[{"internalType":"uint16","name":"dividend","type":"uint16"},{"internalType":"uint16","name":"referral","type":"uint16"},{"internalType":"uint16","name":"partner","type":"uint16"},{"internalType":"uint16","name":"treasury","type":"uint16"},{"internalType":"uint16","name":"team","type":"uint16"},{"internalType":"uint256","name":"dividendAmount","type":"uint256"},{"internalType":"uint256","name":"partnerAmount","type":"uint256"},{"internalType":"uint256","name":"treasuryAmount","type":"uint256"},{"internalType":"uint256","name":"teamAmount","type":"uint256"},{"internalType":"uint256","name":"referralAmount","type":"uint256"},{"internalType":"uint256","name":"minPartnerTransferAmount","type":"uint256"}],"internalType":"struct Bank.HouseEdgeSplit","name":"houseEdgeSplit","type":"tuple"},{"internalType":"uint256","name":"balanceReference","type":"uint256"},{"components":[{"internalType":"uint16","name":"thresholdRate","type":"uint16"},{"internalType":"uint16","name":"toTreasury","type":"uint16"},{"internalType":"uint16","name":"toTeam","type":"uint16"}],"internalType":"struct Bank.BalanceOverflow","name":"balanceOverflow","type":"tuple"}],"internalType":"struct Bank.Token","name":"token","type":"tuple"}],"internalType":"struct Bank.TokenMetadata[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"harvestDividends","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"isAllowedToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"keeperRegistry","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"}],"name":"manageBalanceOverflow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"user","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"profit","type":"uint256"},{"internalType":"uint256","name":"fees","type":"uint256"}],"name":"payout","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"performData","type":"bytes"}],"name":"performUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"referralProgram","outputs":[{"internalType":"contract IReferral","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"bool","name":"allowed","type":"bool"}],"name":"setAllowedToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint16","name":"thresholdRate","type":"uint16"},{"internalType":"uint16","name":"toTreasury","type":"uint16"},{"internalType":"uint16","name":"toTeam","type":"uint16"}],"name":"setBalanceOverflow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint16","name":"balanceRisk","type":"uint16"}],"name":"setBalanceRisk","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint16","name":"dividend","type":"uint16"},{"internalType":"uint16","name":"referral","type":"uint16"},{"internalType":"uint16","name":"partner","type":"uint16"},{"internalType":"uint16","name":"_treasury","type":"uint16"},{"internalType":"uint16","name":"team","type":"uint16"}],"name":"setHouseEdgeSplit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"keeperRegistryAddress","type":"address"}],"name":"setKeeperRegistry","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"minPartnerTransferAmount","type":"uint256"}],"name":"setMinPartnerTransferAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IReferral","name":"_referralProgram","type":"address"}],"name":"setReferralProgram","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"_teamWallet","type":"address"}],"name":"setTeamWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"partner","type":"address"}],"name":"setTokenPartner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"teamWallet","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tokens","outputs":[{"internalType":"bool","name":"allowed","type":"bool"},{"internalType":"uint16","name":"balanceRisk","type":"uint16"},{"internalType":"address","name":"partner","type":"address"},{"components":[{"internalType":"uint16","name":"dividend","type":"uint16"},{"internalType":"uint16","name":"referral","type":"uint16"},{"internalType":"uint16","name":"partner","type":"uint16"},{"internalType":"uint16","name":"treasury","type":"uint16"},{"internalType":"uint16","name":"team","type":"uint16"},{"internalType":"uint256","name":"dividendAmount","type":"uint256"},{"internalType":"uint256","name":"partnerAmount","type":"uint256"},{"internalType":"uint256","name":"treasuryAmount","type":"uint256"},{"internalType":"uint256","name":"teamAmount","type":"uint256"},{"internalType":"uint256","name":"referralAmount","type":"uint256"},{"internalType":"uint256","name":"minPartnerTransferAmount","type":"uint256"}],"internalType":"struct Bank.HouseEdgeSplit","name":"houseEdgeSplit","type":"tuple"},{"internalType":"uint256","name":"balanceReference","type":"uint256"},{"components":[{"internalType":"uint16","name":"thresholdRate","type":"uint16"},{"internalType":"uint16","name":"toTreasury","type":"uint16"},{"internalType":"uint16","name":"toTeam","type":"uint16"}],"internalType":"struct Bank.BalanceOverflow","name":"balanceOverflow","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokensCount","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"tokensList","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"}],"name":"withdrawHouseEdgeAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"}],"name":"withdrawPartnerAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"}],"name":"withdrawReferralAmount","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60a06040523480156200001157600080fd5b50604051620049c3380380620049c38339810160408190526200003491620004ab565b620000416000336200006d565b6001600160a01b03831660805262000059826200007d565b620000648162000109565b50505062000679565b6200007982826200018e565b5050565b60006200008b81336200022e565b6001600160a01b038216620000b357604051630d23cf4160e11b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b0384169081179091556040519081527fc6a5dd316fe9d0339f2769deab7e31f64c8f5b101ffd85dfc9a83dbeaf2e69da906020015b60405180910390a15050565b60006200011781336200022e565b6001600160a01b0382166200013f57604051630d23cf4160e11b815260040160405180910390fd5b600380546001600160a01b0319166001600160a01b0384169081179091556040519081527f678edf136de423322d705b75c3157ecfde496e1ad82aef725aa6deb9d94d4de290602001620000fd565b6000828152602081815260408083206001600160a01b038516845290915290205460ff1662000079576000828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055620001ea3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16620000795762000278816001600160a01b03166014620002d260201b62002edc1760201c565b6200028e83602062002edc620002d2821b17811c565b604051602001620002a192919062000532565b60408051601f198184030181529082905262461bcd60e51b8252620002c991600401620005ab565b60405180910390fd5b60606000620002e3836002620005f6565b620002f090600262000618565b6001600160401b038111156200030a576200030a62000633565b6040519080825280601f01601f19166020018201604052801562000335576020820181803683370190505b509050600360fc1b8160008151811062000353576200035362000649565b60200101906001600160f81b031916908160001a905350600f60fb1b8160018151811062000385576200038562000649565b60200101906001600160f81b031916908160001a9053506000620003ab846002620005f6565b620003b890600162000618565b90505b60018111156200043a576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110620003f057620003f062000649565b1a60f81b82828151811062000409576200040962000649565b60200101906001600160f81b031916908160001a90535060049490941c9362000432816200065f565b9050620003bb565b5083156200048b5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401620002c9565b9392505050565b6001600160a01b0381168114620004a857600080fd5b50565b600080600060608486031215620004c157600080fd5b8351620004ce8162000492565b6020850151909350620004e18162000492565b6040850151909250620004f48162000492565b809150509250925092565b60005b838110156200051c57818101518382015260200162000502565b838111156200052c576000848401525b50505050565b7f416363657373436f6e74726f6c3a206163636f756e74200000000000000000008152600083516200056c816017850160208801620004ff565b7001034b99036b4b9b9b4b733903937b6329607d1b60179184019182015283516200059f816028840160208801620004ff565b01602801949350505050565b6020815260008251806020840152620005cc816040850160208701620004ff565b601f01601f19169190910160400192915050565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615620006135762000613620005e0565b500290565b600082198211156200062e576200062e620005e0565b500190565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b600081620006715762000671620005e0565b506000190190565b608051614320620006a36000396000818161054e01528181610ac301526127f601526143206000f3fe6080604052600436106102d15760003560e01c8063802ad8fb11610179578063bc3ec383116100d6578063d547741f1161008a578063f3fef3a311610064578063f3fef3a31461097a578063f6ae22041461099a578063f8b2cb4f146109ce57600080fd5b8063d547741f14610813578063e486033914610833578063ed442e141461096557600080fd5b8063cdc42344116100bb578063cdc423441461079d578063d1bf5768146107bd578063d48bfca7146107f357600080fd5b8063bc3ec38314610744578063cbe230c31461076457600080fd5b8063a217fddf1161012d578063aa6ca80811610112578063aa6ca808146106ce578063ab400706146106f0578063b291b8231461072457600080fd5b8063a217fddf1461068b578063a64ed8ba146106a057600080fd5b80638aaa22841161015e5780638aaa22841461060757806391d1485414610627578063a128c4d21461066b57600080fd5b8063802ad8fb146105be57806383e22774146105e157600080fd5b8063384feaac1161023257806350cacb9f116101e657806361d027b3116101c057806361d027b31461053c578063659bdfc6146105705780636e04ff0d1461059057600080fd5b806350cacb9f146104c457806356f0406d146104e4578063599270441461050457600080fd5b80633e32a381116102175780633e32a381146104715780634585e33b1461049157806347e7ef24146104b157600080fd5b8063384feaac1461043157806338c64d2f1461045157600080fd5b8063278b39de116102895780632f2ff15d1161026e5780632f2ff15d146103de5780633138809d146103fe57806336568abe1461041157600080fd5b8063278b39de1461039e5780632ee99d3e146103be57600080fd5b80631525ff7d116102ba5780631525ff7d1461032d5780631f6150231461034d578063248a9ca31461036057600080fd5b806301ffc9a7146102d65780630ae30cb01461030b575b600080fd5b3480156102e257600080fd5b506102f66102f1366004613826565b6109ee565b60405190151581526020015b60405180910390f35b34801561031757600080fd5b5061032b610326366004613880565b610a87565b005b34801561033957600080fd5b5061032b610348366004613880565b610b6b565b61032b61035b36600461389d565b610c25565b34801561036c57600080fd5b5061039061037b3660046138e3565b60009081526020819052604090206001015490565b604051908152602001610302565b3480156103aa57600080fd5b506103906103b93660046138fc565b611035565b3480156103ca57600080fd5b5061032b6103d936600461393f565b61107d565b3480156103ea57600080fd5b5061032b6103f93660046139b5565b611245565b61032b61040c3660046138fc565b611270565b34801561041d57600080fd5b5061032b61042c3660046139b5565b611304565b34801561043d57600080fd5b5061032b61044c3660046139e5565b6113aa565b34801561045d57600080fd5b5061032b61046c366004613880565b6114fa565b34801561047d57600080fd5b5061032b61048c366004613880565b61159a565b34801561049d57600080fd5b5061032b6104ac366004613a3b565b61164c565b61032b6104bf3660046138fc565b6117f6565b3480156104d057600080fd5b5061032b6104df366004613880565b611912565b3480156104f057600080fd5b5061032b6104ff366004613aad565b61199c565b34801561051057600080fd5b50600254610524906001600160a01b031681565b6040516001600160a01b039091168152602001610302565b34801561054857600080fd5b506105247f000000000000000000000000000000000000000000000000000000000000000081565b34801561057c57600080fd5b5061032b61058b3660046138fc565b611a97565b34801561059c57600080fd5b506105b06105ab366004613a3b565b611b63565b604051610302929190613b3a565b3480156105ca57600080fd5b506105d3611f04565b604051610302929190613b55565b3480156105ed57600080fd5b50600154610524906201000090046001600160a01b031681565b34801561061357600080fd5b5061032b610622366004613be7565b6120eb565b34801561063357600080fd5b506102f66106423660046139b5565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b34801561067757600080fd5b5061032b610686366004613880565b61216d565b34801561069757600080fd5b50610390600081565b3480156106ac57600080fd5b506001546106bb9061ffff1681565b60405161ffff9091168152602001610302565b3480156106da57600080fd5b506106e3612202565b6040516103029190613cb5565b3480156106fc57600080fd5b506103907f6a64baf327d646d1bca72653e2a075d15fd6ac6d8cbd7f6ee03fc55875e0fa8881565b34801561073057600080fd5b5061032b61073f366004613880565b6126d4565b34801561075057600080fd5b5061032b61075f366004613dfd565b612894565b34801561077057600080fd5b506102f661077f366004613880565b6001600160a01b031660009081526004602052604090205460ff1690565b3480156107a957600080fd5b50600354610524906001600160a01b031681565b3480156107c957600080fd5b506105246107d8366004613e2b565b6005602052600090815260409020546001600160a01b031681565b3480156107ff57600080fd5b5061032b61080e366004613880565b61298e565b34801561081f57600080fd5b5061032b61082e3660046139b5565b612ae3565b34801561083f57600080fd5b5061095361084e366004613880565b6004602081815260009283526040928390208054845161016081018652600183015461ffff8082168352620100008083048216848801526401000000008084048316858b01526601000000000000840483166060808701919091526801000000000000000090940483166080860152600287015460a0860152600387015460c08601529786015460e08501526005860154610100808601919091526006870154610120860152600787015461014086015260088701548a519485018b5260099097015480841685529182048316978401979097529690960486169681019690965260ff8216959382049094169363010000009091046001600160a01b03169290919086565b60405161030296959493929190613e46565b34801561097157600080fd5b506105d3612b09565b34801561098657600080fd5b5061032b6109953660046138fc565b612c71565b3480156109a657600080fd5b506103907f39780592ddb1e73f2a037f166ec57ba042082746f5c0b9fe56ea386e00369a9881565b3480156109da57600080fd5b506103906109e9366004613880565b612d41565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b000000000000000000000000000000000000000000000000000000001480610a8157507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b6001600160a01b03811660009081526004602081905260409091209081015460058201546001909201918115610ae95760006003840155610ae97f0000000000000000000000000000000000000000000000000000000000000000858461311f565b8015610b0d5760006004840155600254610b0d906001600160a01b0316858361311f565b81151580610b1a57508015155b15610b655760408051838152602081018390526001600160a01b038616917f0146f1701c23c89f761280798d36d6c4e3acb349438456f5da8f83a2f5dd8cdc91015b60405180910390a25b50505050565b6000610b77813361314b565b6001600160a01b038216610bb7576040517f1a479e8200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0384169081179091556040519081527fc6a5dd316fe9d0339f2769deab7e31f64c8f5b101ffd85dfc9a83dbeaf2e69da906020015b60405180910390a15050565b7f6a64baf327d646d1bca72653e2a075d15fd6ac6d8cbd7f6ee03fc55875e0fa88610c50813361314b565b6001600160a01b0384166000908152600460205260408120600101805490919061271090610c889062010000900461ffff1686613edf565b610c929190613f4b565b905060008115610d43576003546040517f7700f17b0000000000000000000000000000000000000000000000000000000081526001600160a01b038a8116600483015289811660248301526044820185905290911690637700f17b906064016020604051808303816000875af1158015610d10573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d349190613f5f565b9050610d408183613f78565b91505b825460009061271090610d5a9061ffff1688613edf565b610d649190613f4b565b845490915060009061271090610d8690640100000000900461ffff1689613edf565b610d909190613f4b565b855490915060009061271090610db4906601000000000000900461ffff168a613edf565b610dbe9190613f4b565b865490915060009061271090610de49068010000000000000000900461ffff168b613edf565b610dee9190613f4b565b905060008415610e065780610e0281613f8f565b9150505b8315610e1a5780610e1681613f8f565b9150505b8215610e2e5780610e2a81613f8f565b9150505b8115610e425780610e3e81613f8f565b9150505b600060ff821615610e725760ff8216610e5b818a613fae565b610e65908a613f78565b610e6f9190613f4b565b90505b8515610e9e57610e828187613fc2565b955085896001016000828254610e989190613fc2565b90915550505b8415610eca57610eae8186613fc2565b945084896002016000828254610ec49190613fc2565b90915550505b8315610ef657610eda8185613fc2565b935083896003016000828254610ef09190613fc2565b90915550505b8215610f2257610f068184613fc2565b925082896004016000828254610f1c9190613fc2565b90915550505b8615610f74576001546201000090046001600160a01b0316610f5a57600354610f55906001600160a01b03168e8961311f565b610f74565b86896005016000828254610f6e9190613fc2565b90915550505b604080518781526020810189905290810186905260608101859052608081018490526001600160a01b038e16907fc73e6f5bcd4395126567ead7e4c14b7c52a5f0b9eabd3335a05e631646a127e39060a00160405180910390a2505050505050505050610fe285858561311f565b836001600160a01b03167f634235fcf5af0adbca1a405ec65f6f6c08f55e1f379c2c45cd10f23cb29e0e3161101686612d41565b6040805191825260208201879052015b60405180910390a25050505050565b6001600160a01b0382166000908152600460205260408120548290610100900461ffff1661106285612d41565b61106c9190613edf565b6110769190613f4b565b9392505050565b6000611089813361314b565b6000858486611098868b613fda565b6110a29190613fda565b6110ac9190613fda565b6110b69190613fda565b90508061ffff1661271014611102576040517f6104384400000000000000000000000000000000000000000000000000000000815261ffff821660048201526024015b60405180910390fd5b6000600460008a6001600160a01b03166001600160a01b031681526020019081526020016000206001019050878160000160006101000a81548161ffff021916908361ffff160217905550868160000160026101000a81548161ffff021916908361ffff160217905550858160000160046101000a81548161ffff021916908361ffff160217905550848160000160066101000a81548161ffff021916908361ffff160217905550838160000160086101000a81548161ffff021916908361ffff160217905550886001600160a01b03167f87512489f5b5226512d8f1bfede20d9e809ff4042f028da79c833ed04baa8397898989898960405161123295949392919061ffff95861681529385166020850152918416604084015283166060830152909116608082015260a00190565b60405180910390a2505050505050505050565b600082815260208190526040902060010154611261813361314b565b61126b83836131e3565b505050565b7f6a64baf327d646d1bca72653e2a075d15fd6ac6d8cbd7f6ee03fc55875e0fa8861129b813361314b565b826001600160a01b03167f812b76b477469edc716929cbf7ed54e3d9c1a68d8b9f8290dbabcda54d96fcbe6112cf85612d41565b6001600160a01b038616156112e457846112e6565b345b604080519283526020830191909152015b60405180910390a2505050565b6001600160a01b038116331461139c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c66000000000000000000000000000000000060648201526084016110f9565b6113a6828261329f565b5050565b60006113b6813361314b565b6127108461ffff1611806113d857506127106113d28385613fda565b61ffff16115b1561140f576040517fa28c907300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516060808201835261ffff87811680845287821660208086018281528985168789018181526001600160a01b038f166000818152600486528b902099516009909a018054945192518916640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffffffff938a1662010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000009096169b9099169a909a1793909317169590951790965586519283528201529384015290917f4b481214fcdec41d9a7a06a45d5d931dada21892e48b04779c52d1c69d1e5f9f9101611026565b6001600160a01b03811660009081526004602052604090206003810154801580159061153657508154630100000090046001600160a01b031615155b1561126b5760006003830155815461155f90630100000090046001600160a01b0316848361311f565b826001600160a01b03167f1aa0fc6b9bc54a055d93b640b2c7313e0bd2944482e0b6b5fec7048bbdaacd81826040516112f791815260200190565b60006115a6813361314b565b6001600160a01b0382166115e6576040517f1a479e8200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0384169081179091556040519081527f678edf136de423322d705b75c3157ecfde496e1ad82aef725aa6deb9d94d4de290602001610c19565b6001546201000090046001600160a01b03163314611696576040517f4ca8886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000806116a583850185614000565b6001600160a01b0381166000908152600460208181526040808420815161016081018352600182015461ffff808216835262010000820481169583019590955264010000000081048516938201939093526601000000000000830484166060820152680100000000000000009092049092166080820152600282015460a0820152600382015460c08201529181015460e0830152600581015461010083015260068101546101208301526007015461014082015292945090925083600281111561177157611771614022565b036117845761177f826126d4565b6117ef565b600183600281111561179857611798614022565b1480156117ad57508061014001518160c00151115b156117bb5761177f826114fa565b60028360028111156117cf576117cf614022565b1480156117e157506000816101200151115b156117ef576117ef82611912565b5050505050565b6001600160a01b03808316600090815260046020526040812054909184916301000000900416806118305761182b833361314b565b611872565b336001600160a01b03821614611872576040517f4ca8886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061187d86612d41565b90506001600160a01b03861661189f57611897868261333c565b3494506118c7565b6118b2866118ad8784613fc2565b61333c565b6118c76001600160a01b038716333088613398565b856001600160a01b03167fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c8660405161190291815260200190565b60405180910390a2505050505050565b6001600160a01b03811660009081526004602052604090206006810154600190910190801561126b57600354600060058401556001600160a01b031661195981858461311f565b604080516001600160a01b038381168252602082018590528616917fbd79daf3f76bb7aff9e8c05f8b107f48127baea8584624bdc2c632bb16cd221e9101610b5c565b6001600160a01b03808316600090815260046020526040812054909184916301000000900416806119d6576119d1833361314b565b611a18565b336001600160a01b03821614611a18576040517f4ca8886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03851660008181526004602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ff1661010061ffff8a169081029190911790915591519182527f68288b0936dd994d19323ee940b2703e7bf46fae2552319d60dc1239ba52ec689101611026565b6001600160a01b0380831660009081526004602052604081205490918491630100000090041680611ad157611acc833361314b565b611b13565b336001600160a01b03821614611b13576040517f4ca8886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03851660008181526004602052604090819020600701869055517fc299d8f578e9777556514dc79b1c053fe9912dbc8424518c97262734a96e8095906110269087815260200190565b600060608180611b7585870187614000565b90925090506001826002811115611b8e57611b8e614022565b03611c81576001600160a01b038116600090815260046020818152604092839020835161016081018552600182015461ffff808216835262010000820481169483019490945264010000000081048416958201959095526601000000000000850483166060820152680100000000000000009094049091166080840152600281015460a0840152600381015460c084018190529181015460e0840152600581015461010084015260068101546101208401526007015461014083018190521015611c7b57600194508282604051602001611c69929190614051565b60405160208183030381529060405293505b50611efb565b60005b60015461ffff9081169082161015611ef95761ffff8082166000908152600560208181526040808420546001600160a01b039081168086526004808552838720845160c08082018752825460ff8116151583526101008082048d16848b01526301000000909104909616828801528651610160810188526001840154808d168252620100008082048e16838c01526401000000008083048f16848c0152660100000000000083048f16606085810191909152680100000000000000009093048f16608080860191909152600288015460a0808701919091526003890154968601969096529787015460e08501529b860154988301989098526006850154610120830152600785015461014083015280840191825260088501549584019590955287519485018852600990930154808c1685529586048b1697840197909752969093049097169287019290925291830194909452519091866002811115611dec57611dec614022565b148015611e04575060408201516001600160a01b0316155b15611e8f576000611e1484612d41565b905060006127108460a001516000015161ffff1683611e339190613edf565b611e3d9190613f4b565b8460800151611e4c9190613fc2565b905080821115611e8857600199508785604051602001611e6d929190614051565b60405160208183030381529060405298505050505050611ef9565b5050611ee3565b6002866002811115611ea357611ea3614022565b148015611eb557506000816101200151115b15611ee357600197508583604051602001611ed1929190614051565b60405160208183030381529060405296505b5050508080611ef1906140a4565b915050611c84565b505b50509250929050565b6060807f39780592ddb1e73f2a037f166ec57ba042082746f5c0b9fe56ea386e00369a98611f32813361314b565b60015460009061ffff1667ffffffffffffffff811115611f5457611f546140c5565b604051908082528060200260200182016040528015611f7d578160200160208202803683370190505b5060015490915060009061ffff1667ffffffffffffffff811115611fa357611fa36140c5565b604051908082528060200260200182016040528015611fcc578160200160208202803683370190505b50905060005b60015461ffff90811690821610156120e05761ffff81166000908152600560209081526040808320546001600160a01b03168084526004909252909120600281015480156120ca576000600283015561202c33848361311f565b826001600160a01b03167fca64dbcaf91abfb066e7a5163f1d135f8f48f2cbdb0395e3b35cc278ebbd340b8260405161206791815260200190565b60405180910390a282868561ffff1681518110612086576120866140f4565b60200260200101906001600160a01b031690816001600160a01b03168152505080858561ffff16815181106120bd576120bd6140f4565b6020026020010181815250505b50505080806120d8906140a4565b915050611fd2565b509093509150509091565b60006120f7813361314b565b6001600160a01b03831660008181526004602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915591519182527fe589eb036e62c07e307aa4d441bd39c81e8bd86f349eaacb0caa06b1477f7f9a91016112f7565b6000612179813361314b565b6001546001600160a01b038381166201000090920416146113a657600180547fffffffffffffffffffff0000000000000000000000000000000000000000ffff16620100006001600160a01b038516908102919091179091556040519081527f8bc03ae9a710727b3d59ae52c86167c6d2833076b076b23cbbcd5b381fef5d8890602001610c19565b60015460609060009061ffff1667ffffffffffffffff811115612227576122276140c5565b60405190808252806020026020018201604052801561231257816020015b6040805160a08082018352600080835260208084018290526060848601819052808501819052855160c08082018852848252818401859052818801859052875161016081018952858152808501869052808901869052808401869052608080820187905281880187905291810186905260e08101869052610100810186905261012081018690526101408101869052828401528082018590528751928301885284835292820184905295810192909252918401528101919091528152602001906001900390816122455790505b50905060005b60015461ffff90811690821610156126ce5761ffff8181166000908152600560208181526040808420546001600160a01b03908116808652600480855295839020835160c08082018652825460ff8116151583526101008082048c16848a01526301000000909104909516828701528551610160810187526001840154808c168252620100008082048d16838b01526401000000008083048e16848b0152660100000000000083048e16606080860191909152680100000000000000009093048e16608080860191909152600288015460a0808701919091526003890154968601969096529c87015460e08501529a86015497830197909752600685015461012083015260078501546101408301528084019190915260088401549983019990995285519889018652600990920154808a16895293840489169588019590955294909104909516908401529081019190915281612533576040518060a00160405280601260ff168152602001836001600160a01b031681526020016040518060400160405280600381526020017f455448000000000000000000000000000000000000000000000000000000000081525081526020016040518060400160405280600381526020017f4554480000000000000000000000000000000000000000000000000000000000815250815260200182815250848461ffff1681518110612523576125236140f4565b60200260200101819052506126b9565b60008290506040518060a00160405280826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612581573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125a59190614123565b60ff168152602001846001600160a01b03168152602001826001600160a01b03166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa1580156125fa573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526126229190810190614146565b8152602001826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015612665573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261268d9190810190614146565b815260200183815250858561ffff16815181106126ac576126ac6140f4565b6020026020010181905250505b505080806126c6906140a4565b915050612318565b50919050565b6001600160a01b0381166000908152600460205260408120906126f683612d41565b6009830154909150600090612710906127139061ffff1684613edf565b61271d9190613f4b565b836008015461272c9190613fc2565b8354909150630100000090046001600160a01b031615801561274d57508082115b15610b655760008360080154836127649190613f78565b6009850154909150600090612710906127879062010000900461ffff1684613edf565b6127919190613f4b565b6009860154909150600090612710906127b690640100000000900461ffff1685613edf565b6127c09190613f4b565b90506127db87826127d18589613f78565b6118ad9190613f78565b600486018054600588018054600093849055929055906128257f00000000000000000000000000000000000000000000000000000000000000008a6128208786613fc2565b61311f565b600254612840906001600160a01b03168a6128208685613fc2565b6001600160a01b0389167f6842359a4c3b5f98197bd29d5a317cd8c919e10ef467c746b9b256e99157b08e6128758685613fc2565b61287f8685613fc2565b60408051928352602083019190915201611232565b6001600160a01b03808316600090815260046020526040812054909184916301000000900416806128ce576128c9833361314b565b612910565b336001600160a01b03821614612910576040517f4ca8886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b0385811660008181526004602090815260409182902080547fffffffffffffffffff0000000000000000000000000000000000000000ffffff166301000000958a16958602179055905192835290917fc991529379552af6d0789cc899d5180a270a4bc3b1a3892adcac3d95f93dda1d9101611026565b600061299a813361314b565b60015461ffff1615612a325760005b60015461ffff9081169082161015612a305761ffff81166000908152600560205260409020546001600160a01b03808516911603612a1e576040517ff49f09990000000000000000000000000000000000000000000000000000000081526001600160a01b03841660048201526024016110f9565b80612a28816140a4565b9150506129a9565b505b6001805461ffff908116600090815260056020526040812080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03871617905582548392612a8b91849116613fda565b92506101000a81548161ffff021916908361ffff1602179055507fe473c74f34be27c1464d6624f14a0d7fd4e301cbfa29c3eba425d378c8a7ebe082604051610c1991906001600160a01b0391909116815260200190565b600082815260208190526040902060010154612aff813361314b565b61126b838361329f565b600154606090819060009061ffff1667ffffffffffffffff811115612b3057612b306140c5565b604051908082528060200260200182016040528015612b59578160200160208202803683370190505b5060015490915060009061ffff1667ffffffffffffffff811115612b7f57612b7f6140c5565b604051908082528060200260200182016040528015612ba8578160200160208202803683370190505b50905060005b60015461ffff9081169082161015612c675761ffff81166000908152600560209081526040808320546001600160a01b0316808452600490925290912060028101548015612c515782868561ffff1681518110612c0d57612c0d6140f4565b60200260200101906001600160a01b031690816001600160a01b03168152505080858561ffff1681518110612c4457612c446140f4565b6020026020010181815250505b5050508080612c5f906140a4565b915050612bae565b5090939092509050565b6001600160a01b0380831660009081526004602052604081205490918491630100000090041680612cab57612ca6833361314b565b612ced565b336001600160a01b03821614612ced576040517f4ca8886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612cfb85856127d188612d41565b612d0633868661311f565b846001600160a01b03167f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a94243648560405161102691815260200190565b6000806001600160a01b038316612d59575047612ddd565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b038416906370a0823190602401602060405180830381865afa158015612db6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dda9190613f5f565b90505b6001600160a01b038316600090815260046020818152604092839020835161016081018552600182015461ffff808216835262010000820481169483019490945264010000000081048416958201959095526601000000000000850483166060820152680100000000000000009094049091166080840152600281015460a08401819052600382015460c085018190529282015460e08501819052600583015461010086018190526006840154610120870181905260079094015461014087015292939091612eac9087613f78565b612eb69190613f78565b612ec09190613f78565b612eca9190613f78565b612ed49190613f78565b949350505050565b60606000612eeb836002613edf565b612ef6906002613fc2565b67ffffffffffffffff811115612f0e57612f0e6140c5565b6040519080825280601f01601f191660200182016040528015612f38576020820181803683370190505b5090507f300000000000000000000000000000000000000000000000000000000000000081600081518110612f6f57612f6f6140f4565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110612fd257612fd26140f4565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600061300e846002613edf565b613019906001613fc2565b90505b60018111156130b6577f303132333435363738396162636465660000000000000000000000000000000085600f166010811061305a5761305a6140f4565b1a60f81b828281518110613070576130706140f4565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c936130af816141e8565b905061301c565b508315611076576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016110f9565b6001600160a01b0382166131375761126b8382613449565b61126b6001600160a01b0383168483613596565b6000828152602081815260408083206001600160a01b038516845290915290205460ff166113a657613187816001600160a01b03166014612edc565b613192836020612edc565b6040516020016131a392919061421d565b60408051601f19818403018152908290527f08c379a00000000000000000000000000000000000000000000000000000000082526110f99160040161429e565b6000828152602081815260408083206001600160a01b038516845290915290205460ff166113a6576000828152602081815260408083206001600160a01b0385168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905561325b3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16156113a6576000828152602081815260408083206001600160a01b038516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6001600160a01b03821660008181526004602052604090819020600801839055517f492a63a7d96d749f455133f12ab1ea15a7dd0a5d5f6ae04694244a2761df3f8c9061338c9084815260200190565b60405180910390a25050565b6040516001600160a01b0380851660248301528316604482015260648101829052610b659085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526135df565b804710156134b3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e636500000060448201526064016110f9565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114613500576040519150601f19603f3d011682016040523d82523d6000602084013e613505565b606091505b505090508061126b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d6179206861766520726576657274656400000000000060648201526084016110f9565b6040516001600160a01b03831660248201526044810182905261126b9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064016133e5565b6000613634826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166136de9092919063ffffffff16565b80519091501561126b578080602001905181019061365291906142b1565b61126b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016110f9565b6060612ed48484600085856001600160a01b0385163b61375a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016110f9565b600080866001600160a01b0316858760405161377691906142ce565b60006040518083038185875af1925050503d80600081146137b3576040519150601f19603f3d011682016040523d82523d6000602084013e6137b8565b606091505b50915091506137c88282866137d3565b979650505050505050565b606083156137e2575081611076565b8251156137f25782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110f9919061429e565b60006020828403121561383857600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461107657600080fd5b6001600160a01b038116811461387d57600080fd5b50565b60006020828403121561389257600080fd5b813561107681613868565b600080600080608085870312156138b357600080fd5b84356138be81613868565b935060208501356138ce81613868565b93969395505050506040820135916060013590565b6000602082840312156138f557600080fd5b5035919050565b6000806040838503121561390f57600080fd5b823561391a81613868565b946020939093013593505050565b803561ffff8116811461393a57600080fd5b919050565b60008060008060008060c0878903121561395857600080fd5b863561396381613868565b955061397160208801613928565b945061397f60408801613928565b935061398d60608801613928565b925061399b60808801613928565b91506139a960a08801613928565b90509295509295509295565b600080604083850312156139c857600080fd5b8235915060208301356139da81613868565b809150509250929050565b600080600080608085870312156139fb57600080fd5b8435613a0681613868565b9350613a1460208601613928565b9250613a2260408601613928565b9150613a3060608601613928565b905092959194509250565b60008060208385031215613a4e57600080fd5b823567ffffffffffffffff80821115613a6657600080fd5b818501915085601f830112613a7a57600080fd5b813581811115613a8957600080fd5b866020828501011115613a9b57600080fd5b60209290920196919550909350505050565b60008060408385031215613ac057600080fd5b8235613acb81613868565b9150613ad960208401613928565b90509250929050565b60005b83811015613afd578181015183820152602001613ae5565b83811115610b655750506000910152565b60008151808452613b26816020860160208601613ae2565b601f01601f19169290920160200192915050565b8215158152604060208201526000612ed46040830184613b0e565b604080825283519082018190526000906020906060840190828701845b82811015613b975781516001600160a01b031684529284019290840190600101613b72565b5050508381038285015284518082528583019183019060005b81811015613bcc57835183529284019291840191600101613bb0565b5090979650505050505050565b801515811461387d57600080fd5b60008060408385031215613bfa57600080fd5b8235613c0581613868565b915060208301356139da81613bd9565b805161ffff1682526020810151613c32602084018261ffff169052565b506040810151613c48604084018261ffff169052565b506060810151613c5e606084018261ffff169052565b506080810151613c74608084018261ffff169052565b5060a0818101519083015260c0808201519083015260e080820151908301526101008082015190830152610120808201519083015261014090810151910152565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b83811015613def577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc089840301855281516102c060ff8251168552888201516001600160a01b038082168b880152898401519150828a880152613d4183880183613b0e565b9250606091508184015187840383890152613d5c8482613b0e565b935050608080850151945084511515818901528b85015160a061ffff8216818b0152838d8801511660c08b0152848701519450613d9c60e08b0186613c15565b918601516102408a0152509390930151805161ffff908116610260890152602082015181166102808901526040820151166102a08801529250613ddc9050565b9588019593505090860190600101613cdc565b509098975050505050505050565b60008060408385031215613e1057600080fd5b8235613e1b81613868565b915060208301356139da81613868565b600060208284031215613e3d57600080fd5b61107682613928565b861515815261ffff861660208201526001600160a01b03851660408201526102408101613e766060830186613c15565b6101c08201849052825161ffff9081166101e084015260208401518116610200840152604084015116610220830152979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613f1757613f17613eb0565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082613f5a57613f5a613f1c565b500490565b600060208284031215613f7157600080fd5b5051919050565b600082821015613f8a57613f8a613eb0565b500390565b600060ff821660ff8103613fa557613fa5613eb0565b60010192915050565b600082613fbd57613fbd613f1c565b500690565b60008219821115613fd557613fd5613eb0565b500190565b600061ffff808316818516808303821115613ff757613ff7613eb0565b01949350505050565b6000806040838503121561401357600080fd5b823560038110613e1b57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b604081016003841061408c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9281526001600160a01b039190911660209091015290565b600061ffff8083168181036140bb576140bb613eb0565b6001019392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561413557600080fd5b815160ff8116811461107657600080fd5b60006020828403121561415857600080fd5b815167ffffffffffffffff8082111561417057600080fd5b818401915084601f83011261418457600080fd5b815181811115614196576141966140c5565b604051601f8201601f19908116603f011681019083821181831017156141be576141be6140c5565b816040528281528760208487010111156141d757600080fd5b6137c8836020830160208801613ae2565b6000816141f7576141f7613eb0565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351614255816017850160208801613ae2565b7f206973206d697373696e6720726f6c65200000000000000000000000000000006017918401918201528351614292816028840160208801613ae2565b01602801949350505050565b6020815260006110766020830184613b0e565b6000602082840312156142c357600080fd5b815161107681613bd9565b600082516142e0818460208701613ae2565b919091019291505056fea26469706673582212202ffe9dcdcaa4ecc8b053496841d7fe6006bd33f4361a848cb8886f8aae56ccf064736f6c634300080e0033000000000000000000000000fa695010bf9e757a1abcd2703259f419217aa756000000000000000000000000cb013622cfc0ea0b02e0db352be7883f2e84e3fe000000000000000000000000d0b6d4503207588b677f79876cf12724baff70f8
Deployed Bytecode
0x6080604052600436106102d15760003560e01c8063802ad8fb11610179578063bc3ec383116100d6578063d547741f1161008a578063f3fef3a311610064578063f3fef3a31461097a578063f6ae22041461099a578063f8b2cb4f146109ce57600080fd5b8063d547741f14610813578063e486033914610833578063ed442e141461096557600080fd5b8063cdc42344116100bb578063cdc423441461079d578063d1bf5768146107bd578063d48bfca7146107f357600080fd5b8063bc3ec38314610744578063cbe230c31461076457600080fd5b8063a217fddf1161012d578063aa6ca80811610112578063aa6ca808146106ce578063ab400706146106f0578063b291b8231461072457600080fd5b8063a217fddf1461068b578063a64ed8ba146106a057600080fd5b80638aaa22841161015e5780638aaa22841461060757806391d1485414610627578063a128c4d21461066b57600080fd5b8063802ad8fb146105be57806383e22774146105e157600080fd5b8063384feaac1161023257806350cacb9f116101e657806361d027b3116101c057806361d027b31461053c578063659bdfc6146105705780636e04ff0d1461059057600080fd5b806350cacb9f146104c457806356f0406d146104e4578063599270441461050457600080fd5b80633e32a381116102175780633e32a381146104715780634585e33b1461049157806347e7ef24146104b157600080fd5b8063384feaac1461043157806338c64d2f1461045157600080fd5b8063278b39de116102895780632f2ff15d1161026e5780632f2ff15d146103de5780633138809d146103fe57806336568abe1461041157600080fd5b8063278b39de1461039e5780632ee99d3e146103be57600080fd5b80631525ff7d116102ba5780631525ff7d1461032d5780631f6150231461034d578063248a9ca31461036057600080fd5b806301ffc9a7146102d65780630ae30cb01461030b575b600080fd5b3480156102e257600080fd5b506102f66102f1366004613826565b6109ee565b60405190151581526020015b60405180910390f35b34801561031757600080fd5b5061032b610326366004613880565b610a87565b005b34801561033957600080fd5b5061032b610348366004613880565b610b6b565b61032b61035b36600461389d565b610c25565b34801561036c57600080fd5b5061039061037b3660046138e3565b60009081526020819052604090206001015490565b604051908152602001610302565b3480156103aa57600080fd5b506103906103b93660046138fc565b611035565b3480156103ca57600080fd5b5061032b6103d936600461393f565b61107d565b3480156103ea57600080fd5b5061032b6103f93660046139b5565b611245565b61032b61040c3660046138fc565b611270565b34801561041d57600080fd5b5061032b61042c3660046139b5565b611304565b34801561043d57600080fd5b5061032b61044c3660046139e5565b6113aa565b34801561045d57600080fd5b5061032b61046c366004613880565b6114fa565b34801561047d57600080fd5b5061032b61048c366004613880565b61159a565b34801561049d57600080fd5b5061032b6104ac366004613a3b565b61164c565b61032b6104bf3660046138fc565b6117f6565b3480156104d057600080fd5b5061032b6104df366004613880565b611912565b3480156104f057600080fd5b5061032b6104ff366004613aad565b61199c565b34801561051057600080fd5b50600254610524906001600160a01b031681565b6040516001600160a01b039091168152602001610302565b34801561054857600080fd5b506105247f000000000000000000000000fa695010bf9e757a1abcd2703259f419217aa75681565b34801561057c57600080fd5b5061032b61058b3660046138fc565b611a97565b34801561059c57600080fd5b506105b06105ab366004613a3b565b611b63565b604051610302929190613b3a565b3480156105ca57600080fd5b506105d3611f04565b604051610302929190613b55565b3480156105ed57600080fd5b50600154610524906201000090046001600160a01b031681565b34801561061357600080fd5b5061032b610622366004613be7565b6120eb565b34801561063357600080fd5b506102f66106423660046139b5565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b34801561067757600080fd5b5061032b610686366004613880565b61216d565b34801561069757600080fd5b50610390600081565b3480156106ac57600080fd5b506001546106bb9061ffff1681565b60405161ffff9091168152602001610302565b3480156106da57600080fd5b506106e3612202565b6040516103029190613cb5565b3480156106fc57600080fd5b506103907f6a64baf327d646d1bca72653e2a075d15fd6ac6d8cbd7f6ee03fc55875e0fa8881565b34801561073057600080fd5b5061032b61073f366004613880565b6126d4565b34801561075057600080fd5b5061032b61075f366004613dfd565b612894565b34801561077057600080fd5b506102f661077f366004613880565b6001600160a01b031660009081526004602052604090205460ff1690565b3480156107a957600080fd5b50600354610524906001600160a01b031681565b3480156107c957600080fd5b506105246107d8366004613e2b565b6005602052600090815260409020546001600160a01b031681565b3480156107ff57600080fd5b5061032b61080e366004613880565b61298e565b34801561081f57600080fd5b5061032b61082e3660046139b5565b612ae3565b34801561083f57600080fd5b5061095361084e366004613880565b6004602081815260009283526040928390208054845161016081018652600183015461ffff8082168352620100008083048216848801526401000000008084048316858b01526601000000000000840483166060808701919091526801000000000000000090940483166080860152600287015460a0860152600387015460c08601529786015460e08501526005860154610100808601919091526006870154610120860152600787015461014086015260088701548a519485018b5260099097015480841685529182048316978401979097529690960486169681019690965260ff8216959382049094169363010000009091046001600160a01b03169290919086565b60405161030296959493929190613e46565b34801561097157600080fd5b506105d3612b09565b34801561098657600080fd5b5061032b6109953660046138fc565b612c71565b3480156109a657600080fd5b506103907f39780592ddb1e73f2a037f166ec57ba042082746f5c0b9fe56ea386e00369a9881565b3480156109da57600080fd5b506103906109e9366004613880565b612d41565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b000000000000000000000000000000000000000000000000000000001480610a8157507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b6001600160a01b03811660009081526004602081905260409091209081015460058201546001909201918115610ae95760006003840155610ae97f000000000000000000000000fa695010bf9e757a1abcd2703259f419217aa756858461311f565b8015610b0d5760006004840155600254610b0d906001600160a01b0316858361311f565b81151580610b1a57508015155b15610b655760408051838152602081018390526001600160a01b038616917f0146f1701c23c89f761280798d36d6c4e3acb349438456f5da8f83a2f5dd8cdc91015b60405180910390a25b50505050565b6000610b77813361314b565b6001600160a01b038216610bb7576040517f1a479e8200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0384169081179091556040519081527fc6a5dd316fe9d0339f2769deab7e31f64c8f5b101ffd85dfc9a83dbeaf2e69da906020015b60405180910390a15050565b7f6a64baf327d646d1bca72653e2a075d15fd6ac6d8cbd7f6ee03fc55875e0fa88610c50813361314b565b6001600160a01b0384166000908152600460205260408120600101805490919061271090610c889062010000900461ffff1686613edf565b610c929190613f4b565b905060008115610d43576003546040517f7700f17b0000000000000000000000000000000000000000000000000000000081526001600160a01b038a8116600483015289811660248301526044820185905290911690637700f17b906064016020604051808303816000875af1158015610d10573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d349190613f5f565b9050610d408183613f78565b91505b825460009061271090610d5a9061ffff1688613edf565b610d649190613f4b565b845490915060009061271090610d8690640100000000900461ffff1689613edf565b610d909190613f4b565b855490915060009061271090610db4906601000000000000900461ffff168a613edf565b610dbe9190613f4b565b865490915060009061271090610de49068010000000000000000900461ffff168b613edf565b610dee9190613f4b565b905060008415610e065780610e0281613f8f565b9150505b8315610e1a5780610e1681613f8f565b9150505b8215610e2e5780610e2a81613f8f565b9150505b8115610e425780610e3e81613f8f565b9150505b600060ff821615610e725760ff8216610e5b818a613fae565b610e65908a613f78565b610e6f9190613f4b565b90505b8515610e9e57610e828187613fc2565b955085896001016000828254610e989190613fc2565b90915550505b8415610eca57610eae8186613fc2565b945084896002016000828254610ec49190613fc2565b90915550505b8315610ef657610eda8185613fc2565b935083896003016000828254610ef09190613fc2565b90915550505b8215610f2257610f068184613fc2565b925082896004016000828254610f1c9190613fc2565b90915550505b8615610f74576001546201000090046001600160a01b0316610f5a57600354610f55906001600160a01b03168e8961311f565b610f74565b86896005016000828254610f6e9190613fc2565b90915550505b604080518781526020810189905290810186905260608101859052608081018490526001600160a01b038e16907fc73e6f5bcd4395126567ead7e4c14b7c52a5f0b9eabd3335a05e631646a127e39060a00160405180910390a2505050505050505050610fe285858561311f565b836001600160a01b03167f634235fcf5af0adbca1a405ec65f6f6c08f55e1f379c2c45cd10f23cb29e0e3161101686612d41565b6040805191825260208201879052015b60405180910390a25050505050565b6001600160a01b0382166000908152600460205260408120548290610100900461ffff1661106285612d41565b61106c9190613edf565b6110769190613f4b565b9392505050565b6000611089813361314b565b6000858486611098868b613fda565b6110a29190613fda565b6110ac9190613fda565b6110b69190613fda565b90508061ffff1661271014611102576040517f6104384400000000000000000000000000000000000000000000000000000000815261ffff821660048201526024015b60405180910390fd5b6000600460008a6001600160a01b03166001600160a01b031681526020019081526020016000206001019050878160000160006101000a81548161ffff021916908361ffff160217905550868160000160026101000a81548161ffff021916908361ffff160217905550858160000160046101000a81548161ffff021916908361ffff160217905550848160000160066101000a81548161ffff021916908361ffff160217905550838160000160086101000a81548161ffff021916908361ffff160217905550886001600160a01b03167f87512489f5b5226512d8f1bfede20d9e809ff4042f028da79c833ed04baa8397898989898960405161123295949392919061ffff95861681529385166020850152918416604084015283166060830152909116608082015260a00190565b60405180910390a2505050505050505050565b600082815260208190526040902060010154611261813361314b565b61126b83836131e3565b505050565b7f6a64baf327d646d1bca72653e2a075d15fd6ac6d8cbd7f6ee03fc55875e0fa8861129b813361314b565b826001600160a01b03167f812b76b477469edc716929cbf7ed54e3d9c1a68d8b9f8290dbabcda54d96fcbe6112cf85612d41565b6001600160a01b038616156112e457846112e6565b345b604080519283526020830191909152015b60405180910390a2505050565b6001600160a01b038116331461139c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c66000000000000000000000000000000000060648201526084016110f9565b6113a6828261329f565b5050565b60006113b6813361314b565b6127108461ffff1611806113d857506127106113d28385613fda565b61ffff16115b1561140f576040517fa28c907300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516060808201835261ffff87811680845287821660208086018281528985168789018181526001600160a01b038f166000818152600486528b902099516009909a018054945192518916640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffffffff938a1662010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000009096169b9099169a909a1793909317169590951790965586519283528201529384015290917f4b481214fcdec41d9a7a06a45d5d931dada21892e48b04779c52d1c69d1e5f9f9101611026565b6001600160a01b03811660009081526004602052604090206003810154801580159061153657508154630100000090046001600160a01b031615155b1561126b5760006003830155815461155f90630100000090046001600160a01b0316848361311f565b826001600160a01b03167f1aa0fc6b9bc54a055d93b640b2c7313e0bd2944482e0b6b5fec7048bbdaacd81826040516112f791815260200190565b60006115a6813361314b565b6001600160a01b0382166115e6576040517f1a479e8200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0384169081179091556040519081527f678edf136de423322d705b75c3157ecfde496e1ad82aef725aa6deb9d94d4de290602001610c19565b6001546201000090046001600160a01b03163314611696576040517f4ca8886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000806116a583850185614000565b6001600160a01b0381166000908152600460208181526040808420815161016081018352600182015461ffff808216835262010000820481169583019590955264010000000081048516938201939093526601000000000000830484166060820152680100000000000000009092049092166080820152600282015460a0820152600382015460c08201529181015460e0830152600581015461010083015260068101546101208301526007015461014082015292945090925083600281111561177157611771614022565b036117845761177f826126d4565b6117ef565b600183600281111561179857611798614022565b1480156117ad57508061014001518160c00151115b156117bb5761177f826114fa565b60028360028111156117cf576117cf614022565b1480156117e157506000816101200151115b156117ef576117ef82611912565b5050505050565b6001600160a01b03808316600090815260046020526040812054909184916301000000900416806118305761182b833361314b565b611872565b336001600160a01b03821614611872576040517f4ca8886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061187d86612d41565b90506001600160a01b03861661189f57611897868261333c565b3494506118c7565b6118b2866118ad8784613fc2565b61333c565b6118c76001600160a01b038716333088613398565b856001600160a01b03167fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c8660405161190291815260200190565b60405180910390a2505050505050565b6001600160a01b03811660009081526004602052604090206006810154600190910190801561126b57600354600060058401556001600160a01b031661195981858461311f565b604080516001600160a01b038381168252602082018590528616917fbd79daf3f76bb7aff9e8c05f8b107f48127baea8584624bdc2c632bb16cd221e9101610b5c565b6001600160a01b03808316600090815260046020526040812054909184916301000000900416806119d6576119d1833361314b565b611a18565b336001600160a01b03821614611a18576040517f4ca8886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03851660008181526004602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ff1661010061ffff8a169081029190911790915591519182527f68288b0936dd994d19323ee940b2703e7bf46fae2552319d60dc1239ba52ec689101611026565b6001600160a01b0380831660009081526004602052604081205490918491630100000090041680611ad157611acc833361314b565b611b13565b336001600160a01b03821614611b13576040517f4ca8886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03851660008181526004602052604090819020600701869055517fc299d8f578e9777556514dc79b1c053fe9912dbc8424518c97262734a96e8095906110269087815260200190565b600060608180611b7585870187614000565b90925090506001826002811115611b8e57611b8e614022565b03611c81576001600160a01b038116600090815260046020818152604092839020835161016081018552600182015461ffff808216835262010000820481169483019490945264010000000081048416958201959095526601000000000000850483166060820152680100000000000000009094049091166080840152600281015460a0840152600381015460c084018190529181015460e0840152600581015461010084015260068101546101208401526007015461014083018190521015611c7b57600194508282604051602001611c69929190614051565b60405160208183030381529060405293505b50611efb565b60005b60015461ffff9081169082161015611ef95761ffff8082166000908152600560208181526040808420546001600160a01b039081168086526004808552838720845160c08082018752825460ff8116151583526101008082048d16848b01526301000000909104909616828801528651610160810188526001840154808d168252620100008082048e16838c01526401000000008083048f16848c0152660100000000000083048f16606085810191909152680100000000000000009093048f16608080860191909152600288015460a0808701919091526003890154968601969096529787015460e08501529b860154988301989098526006850154610120830152600785015461014083015280840191825260088501549584019590955287519485018852600990930154808c1685529586048b1697840197909752969093049097169287019290925291830194909452519091866002811115611dec57611dec614022565b148015611e04575060408201516001600160a01b0316155b15611e8f576000611e1484612d41565b905060006127108460a001516000015161ffff1683611e339190613edf565b611e3d9190613f4b565b8460800151611e4c9190613fc2565b905080821115611e8857600199508785604051602001611e6d929190614051565b60405160208183030381529060405298505050505050611ef9565b5050611ee3565b6002866002811115611ea357611ea3614022565b148015611eb557506000816101200151115b15611ee357600197508583604051602001611ed1929190614051565b60405160208183030381529060405296505b5050508080611ef1906140a4565b915050611c84565b505b50509250929050565b6060807f39780592ddb1e73f2a037f166ec57ba042082746f5c0b9fe56ea386e00369a98611f32813361314b565b60015460009061ffff1667ffffffffffffffff811115611f5457611f546140c5565b604051908082528060200260200182016040528015611f7d578160200160208202803683370190505b5060015490915060009061ffff1667ffffffffffffffff811115611fa357611fa36140c5565b604051908082528060200260200182016040528015611fcc578160200160208202803683370190505b50905060005b60015461ffff90811690821610156120e05761ffff81166000908152600560209081526040808320546001600160a01b03168084526004909252909120600281015480156120ca576000600283015561202c33848361311f565b826001600160a01b03167fca64dbcaf91abfb066e7a5163f1d135f8f48f2cbdb0395e3b35cc278ebbd340b8260405161206791815260200190565b60405180910390a282868561ffff1681518110612086576120866140f4565b60200260200101906001600160a01b031690816001600160a01b03168152505080858561ffff16815181106120bd576120bd6140f4565b6020026020010181815250505b50505080806120d8906140a4565b915050611fd2565b509093509150509091565b60006120f7813361314b565b6001600160a01b03831660008181526004602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915591519182527fe589eb036e62c07e307aa4d441bd39c81e8bd86f349eaacb0caa06b1477f7f9a91016112f7565b6000612179813361314b565b6001546001600160a01b038381166201000090920416146113a657600180547fffffffffffffffffffff0000000000000000000000000000000000000000ffff16620100006001600160a01b038516908102919091179091556040519081527f8bc03ae9a710727b3d59ae52c86167c6d2833076b076b23cbbcd5b381fef5d8890602001610c19565b60015460609060009061ffff1667ffffffffffffffff811115612227576122276140c5565b60405190808252806020026020018201604052801561231257816020015b6040805160a08082018352600080835260208084018290526060848601819052808501819052855160c08082018852848252818401859052818801859052875161016081018952858152808501869052808901869052808401869052608080820187905281880187905291810186905260e08101869052610100810186905261012081018690526101408101869052828401528082018590528751928301885284835292820184905295810192909252918401528101919091528152602001906001900390816122455790505b50905060005b60015461ffff90811690821610156126ce5761ffff8181166000908152600560208181526040808420546001600160a01b03908116808652600480855295839020835160c08082018652825460ff8116151583526101008082048c16848a01526301000000909104909516828701528551610160810187526001840154808c168252620100008082048d16838b01526401000000008083048e16848b0152660100000000000083048e16606080860191909152680100000000000000009093048e16608080860191909152600288015460a0808701919091526003890154968601969096529c87015460e08501529a86015497830197909752600685015461012083015260078501546101408301528084019190915260088401549983019990995285519889018652600990920154808a16895293840489169588019590955294909104909516908401529081019190915281612533576040518060a00160405280601260ff168152602001836001600160a01b031681526020016040518060400160405280600381526020017f455448000000000000000000000000000000000000000000000000000000000081525081526020016040518060400160405280600381526020017f4554480000000000000000000000000000000000000000000000000000000000815250815260200182815250848461ffff1681518110612523576125236140f4565b60200260200101819052506126b9565b60008290506040518060a00160405280826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612581573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125a59190614123565b60ff168152602001846001600160a01b03168152602001826001600160a01b03166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa1580156125fa573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526126229190810190614146565b8152602001826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015612665573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261268d9190810190614146565b815260200183815250858561ffff16815181106126ac576126ac6140f4565b6020026020010181905250505b505080806126c6906140a4565b915050612318565b50919050565b6001600160a01b0381166000908152600460205260408120906126f683612d41565b6009830154909150600090612710906127139061ffff1684613edf565b61271d9190613f4b565b836008015461272c9190613fc2565b8354909150630100000090046001600160a01b031615801561274d57508082115b15610b655760008360080154836127649190613f78565b6009850154909150600090612710906127879062010000900461ffff1684613edf565b6127919190613f4b565b6009860154909150600090612710906127b690640100000000900461ffff1685613edf565b6127c09190613f4b565b90506127db87826127d18589613f78565b6118ad9190613f78565b600486018054600588018054600093849055929055906128257f000000000000000000000000fa695010bf9e757a1abcd2703259f419217aa7568a6128208786613fc2565b61311f565b600254612840906001600160a01b03168a6128208685613fc2565b6001600160a01b0389167f6842359a4c3b5f98197bd29d5a317cd8c919e10ef467c746b9b256e99157b08e6128758685613fc2565b61287f8685613fc2565b60408051928352602083019190915201611232565b6001600160a01b03808316600090815260046020526040812054909184916301000000900416806128ce576128c9833361314b565b612910565b336001600160a01b03821614612910576040517f4ca8886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b0385811660008181526004602090815260409182902080547fffffffffffffffffff0000000000000000000000000000000000000000ffffff166301000000958a16958602179055905192835290917fc991529379552af6d0789cc899d5180a270a4bc3b1a3892adcac3d95f93dda1d9101611026565b600061299a813361314b565b60015461ffff1615612a325760005b60015461ffff9081169082161015612a305761ffff81166000908152600560205260409020546001600160a01b03808516911603612a1e576040517ff49f09990000000000000000000000000000000000000000000000000000000081526001600160a01b03841660048201526024016110f9565b80612a28816140a4565b9150506129a9565b505b6001805461ffff908116600090815260056020526040812080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03871617905582548392612a8b91849116613fda565b92506101000a81548161ffff021916908361ffff1602179055507fe473c74f34be27c1464d6624f14a0d7fd4e301cbfa29c3eba425d378c8a7ebe082604051610c1991906001600160a01b0391909116815260200190565b600082815260208190526040902060010154612aff813361314b565b61126b838361329f565b600154606090819060009061ffff1667ffffffffffffffff811115612b3057612b306140c5565b604051908082528060200260200182016040528015612b59578160200160208202803683370190505b5060015490915060009061ffff1667ffffffffffffffff811115612b7f57612b7f6140c5565b604051908082528060200260200182016040528015612ba8578160200160208202803683370190505b50905060005b60015461ffff9081169082161015612c675761ffff81166000908152600560209081526040808320546001600160a01b0316808452600490925290912060028101548015612c515782868561ffff1681518110612c0d57612c0d6140f4565b60200260200101906001600160a01b031690816001600160a01b03168152505080858561ffff1681518110612c4457612c446140f4565b6020026020010181815250505b5050508080612c5f906140a4565b915050612bae565b5090939092509050565b6001600160a01b0380831660009081526004602052604081205490918491630100000090041680612cab57612ca6833361314b565b612ced565b336001600160a01b03821614612ced576040517f4ca8886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612cfb85856127d188612d41565b612d0633868661311f565b846001600160a01b03167f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a94243648560405161102691815260200190565b6000806001600160a01b038316612d59575047612ddd565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b038416906370a0823190602401602060405180830381865afa158015612db6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dda9190613f5f565b90505b6001600160a01b038316600090815260046020818152604092839020835161016081018552600182015461ffff808216835262010000820481169483019490945264010000000081048416958201959095526601000000000000850483166060820152680100000000000000009094049091166080840152600281015460a08401819052600382015460c085018190529282015460e08501819052600583015461010086018190526006840154610120870181905260079094015461014087015292939091612eac9087613f78565b612eb69190613f78565b612ec09190613f78565b612eca9190613f78565b612ed49190613f78565b949350505050565b60606000612eeb836002613edf565b612ef6906002613fc2565b67ffffffffffffffff811115612f0e57612f0e6140c5565b6040519080825280601f01601f191660200182016040528015612f38576020820181803683370190505b5090507f300000000000000000000000000000000000000000000000000000000000000081600081518110612f6f57612f6f6140f4565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110612fd257612fd26140f4565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600061300e846002613edf565b613019906001613fc2565b90505b60018111156130b6577f303132333435363738396162636465660000000000000000000000000000000085600f166010811061305a5761305a6140f4565b1a60f81b828281518110613070576130706140f4565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c936130af816141e8565b905061301c565b508315611076576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016110f9565b6001600160a01b0382166131375761126b8382613449565b61126b6001600160a01b0383168483613596565b6000828152602081815260408083206001600160a01b038516845290915290205460ff166113a657613187816001600160a01b03166014612edc565b613192836020612edc565b6040516020016131a392919061421d565b60408051601f19818403018152908290527f08c379a00000000000000000000000000000000000000000000000000000000082526110f99160040161429e565b6000828152602081815260408083206001600160a01b038516845290915290205460ff166113a6576000828152602081815260408083206001600160a01b0385168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905561325b3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16156113a6576000828152602081815260408083206001600160a01b038516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6001600160a01b03821660008181526004602052604090819020600801839055517f492a63a7d96d749f455133f12ab1ea15a7dd0a5d5f6ae04694244a2761df3f8c9061338c9084815260200190565b60405180910390a25050565b6040516001600160a01b0380851660248301528316604482015260648101829052610b659085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526135df565b804710156134b3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e636500000060448201526064016110f9565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114613500576040519150601f19603f3d011682016040523d82523d6000602084013e613505565b606091505b505090508061126b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d6179206861766520726576657274656400000000000060648201526084016110f9565b6040516001600160a01b03831660248201526044810182905261126b9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064016133e5565b6000613634826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166136de9092919063ffffffff16565b80519091501561126b578080602001905181019061365291906142b1565b61126b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016110f9565b6060612ed48484600085856001600160a01b0385163b61375a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016110f9565b600080866001600160a01b0316858760405161377691906142ce565b60006040518083038185875af1925050503d80600081146137b3576040519150601f19603f3d011682016040523d82523d6000602084013e6137b8565b606091505b50915091506137c88282866137d3565b979650505050505050565b606083156137e2575081611076565b8251156137f25782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110f9919061429e565b60006020828403121561383857600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461107657600080fd5b6001600160a01b038116811461387d57600080fd5b50565b60006020828403121561389257600080fd5b813561107681613868565b600080600080608085870312156138b357600080fd5b84356138be81613868565b935060208501356138ce81613868565b93969395505050506040820135916060013590565b6000602082840312156138f557600080fd5b5035919050565b6000806040838503121561390f57600080fd5b823561391a81613868565b946020939093013593505050565b803561ffff8116811461393a57600080fd5b919050565b60008060008060008060c0878903121561395857600080fd5b863561396381613868565b955061397160208801613928565b945061397f60408801613928565b935061398d60608801613928565b925061399b60808801613928565b91506139a960a08801613928565b90509295509295509295565b600080604083850312156139c857600080fd5b8235915060208301356139da81613868565b809150509250929050565b600080600080608085870312156139fb57600080fd5b8435613a0681613868565b9350613a1460208601613928565b9250613a2260408601613928565b9150613a3060608601613928565b905092959194509250565b60008060208385031215613a4e57600080fd5b823567ffffffffffffffff80821115613a6657600080fd5b818501915085601f830112613a7a57600080fd5b813581811115613a8957600080fd5b866020828501011115613a9b57600080fd5b60209290920196919550909350505050565b60008060408385031215613ac057600080fd5b8235613acb81613868565b9150613ad960208401613928565b90509250929050565b60005b83811015613afd578181015183820152602001613ae5565b83811115610b655750506000910152565b60008151808452613b26816020860160208601613ae2565b601f01601f19169290920160200192915050565b8215158152604060208201526000612ed46040830184613b0e565b604080825283519082018190526000906020906060840190828701845b82811015613b975781516001600160a01b031684529284019290840190600101613b72565b5050508381038285015284518082528583019183019060005b81811015613bcc57835183529284019291840191600101613bb0565b5090979650505050505050565b801515811461387d57600080fd5b60008060408385031215613bfa57600080fd5b8235613c0581613868565b915060208301356139da81613bd9565b805161ffff1682526020810151613c32602084018261ffff169052565b506040810151613c48604084018261ffff169052565b506060810151613c5e606084018261ffff169052565b506080810151613c74608084018261ffff169052565b5060a0818101519083015260c0808201519083015260e080820151908301526101008082015190830152610120808201519083015261014090810151910152565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b83811015613def577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc089840301855281516102c060ff8251168552888201516001600160a01b038082168b880152898401519150828a880152613d4183880183613b0e565b9250606091508184015187840383890152613d5c8482613b0e565b935050608080850151945084511515818901528b85015160a061ffff8216818b0152838d8801511660c08b0152848701519450613d9c60e08b0186613c15565b918601516102408a0152509390930151805161ffff908116610260890152602082015181166102808901526040820151166102a08801529250613ddc9050565b9588019593505090860190600101613cdc565b509098975050505050505050565b60008060408385031215613e1057600080fd5b8235613e1b81613868565b915060208301356139da81613868565b600060208284031215613e3d57600080fd5b61107682613928565b861515815261ffff861660208201526001600160a01b03851660408201526102408101613e766060830186613c15565b6101c08201849052825161ffff9081166101e084015260208401518116610200840152604084015116610220830152979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613f1757613f17613eb0565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082613f5a57613f5a613f1c565b500490565b600060208284031215613f7157600080fd5b5051919050565b600082821015613f8a57613f8a613eb0565b500390565b600060ff821660ff8103613fa557613fa5613eb0565b60010192915050565b600082613fbd57613fbd613f1c565b500690565b60008219821115613fd557613fd5613eb0565b500190565b600061ffff808316818516808303821115613ff757613ff7613eb0565b01949350505050565b6000806040838503121561401357600080fd5b823560038110613e1b57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b604081016003841061408c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9281526001600160a01b039190911660209091015290565b600061ffff8083168181036140bb576140bb613eb0565b6001019392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561413557600080fd5b815160ff8116811461107657600080fd5b60006020828403121561415857600080fd5b815167ffffffffffffffff8082111561417057600080fd5b818401915084601f83011261418457600080fd5b815181811115614196576141966140c5565b604051601f8201601f19908116603f011681019083821181831017156141be576141be6140c5565b816040528281528760208487010111156141d757600080fd5b6137c8836020830160208801613ae2565b6000816141f7576141f7613eb0565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351614255816017850160208801613ae2565b7f206973206d697373696e6720726f6c65200000000000000000000000000000006017918401918201528351614292816028840160208801613ae2565b01602801949350505050565b6020815260006110766020830184613b0e565b6000602082840312156142c357600080fd5b815161107681613bd9565b600082516142e0818460208701613ae2565b919091019291505056fea26469706673582212202ffe9dcdcaa4ecc8b053496841d7fe6006bd33f4361a848cb8886f8aae56ccf064736f6c634300080e0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000fa695010bf9e757a1abcd2703259f419217aa756000000000000000000000000cb013622cfc0ea0b02e0db352be7883f2e84e3fe000000000000000000000000d0b6d4503207588b677f79876cf12724baff70f8
-----Decoded View---------------
Arg [0] : treasuryAddress (address): 0xfA695010bF9e757a1abCd2703259F419217aa756
Arg [1] : teamWalletAddress (address): 0xCb013622CfC0EA0b02e0db352Be7883F2E84E3FE
Arg [2] : referralProgramAddress (address): 0xd0B6D4503207588B677F79876cf12724bAFF70f8
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000fa695010bf9e757a1abcd2703259f419217aa756
Arg [1] : 000000000000000000000000cb013622cfc0ea0b02e0db352be7883f2e84e3fe
Arg [2] : 000000000000000000000000d0b6d4503207588b677f79876cf12724baff70f8
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
POL | 100.00% | $0.000507 | 1,678,230.4249 | $850.88 |
[ 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.