Overview
S Balance
S Value
$0.00More Info
Private Name Tags
ContractCreator
Loading...
Loading
Contract Name:
SRTickets
Compiler Version
v0.8.15+commit.e14f2714
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT //vedb25sonic2 pragma solidity 0.8.15; import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import "@openzeppelin/contracts/utils/Counters.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol"; contract NFTRemote { function mintItem( address attendee, string memory ticketName, string memory social ) public returns (uint256) {} function setCancelled(uint256 itemId) public {} } contract SRTicketsDiscountsRemote { struct DiscountResponse { bool hasDiscountCode; bool hasDiscountAddress; bool hasTokenDiscount; uint256 discountAmount; } address public SRTicketsAddress; struct SenderAndTokenDiscountBuyer { address sender; bool tokenDiscountBuyer; } function getAttendee( address sender, uint256 index ) public view returns (SRTickets.Attendee memory) {} function getDiscountView( SenderAndTokenDiscountBuyer memory stdb, bool discountCodeTicketAttendee, SRTickets.DiscountCode memory, bool discountAddressTicketAttendee, SRTickets.DiscountAddress memory, bool tokenDiscountTicketAttendee, SRTickets.TokenDiscount memory, address tokenDiscountAttendee ) public view returns (DiscountResponse memory) {} function setAttendee( uint256 attendeeIndex, SRTickets.Attendee memory newAttendee, SRTickets.Attendee memory attendee, address sender, bool resell, bool refund ) public {} } contract SRTickets is ReentrancyGuard { using Counters for Counters.Counter; using SafeERC20 for IERC20; /********** * Events **********/ event LMint( address indexed attendeeAddress, Attendee attendee, string message ); event LogBuy( address indexed attendee, uint256 amount, uint256 amountUSD, address token ); event LogRefund( address indexed attendee, uint256 amount, uint256 attendeesIndex, address buyToken ); event LogSetOwner(address indexed sender, address newOwner); /*********** * Variables ***********/ // an address of the owner address public owner; // an address of the to be confirmed owner address public tbcOwner; // when true, people can call the selfRefund function to get a refund bool public allowSelfRefund; // when true, people can buy resellable tickets bool public allowBuyResellable; // amount by which self-refund decrease every x second uint256 public refundIncFee; // time lapse between each self-refund amount decrease uint256 public refundIncLapse; // refund fee uint256 public refundFee; // fee charged when reselling ticket uint256 public resellFee; // ticket struct details struct Ticket { uint256 qty; Counters.Counter used; uint256 price; uint256 endDate; uint256 startDate; } // discount code details struct DiscountCode { uint256 qty; Counters.Counter used; uint256 amount; string code; uint256 endDate; uint256 startDate; } // discount address details, discount based on buyer address struct DiscountAddress { address buyer; uint256 qty; Counters.Counter used; uint256 amount; string code; uint256 endDate; uint256 startDate; } // discount token details, discount based on a buyer's token balance // can be used once only per buyer struct TokenDiscount { address token; uint256 minAmount; uint256 qty; Counters.Counter used; uint256 amount; uint256 endDate; uint256 startDate; } // attendee details, fields are encrypted on the frontend struct Attendee { string email; string fname; string lname; string bio; string job; string company; string social; string ticket; string discountCode; address tokenDiscount; address sender; address buyToken; uint256 pricePaid; uint256 pricePaidInToken; bool cancelled; uint256 refunded; bool allowResell; uint256 resellPrice; string code; uint256 boughtOn; bool resold; uint256 nftId; } /********** * Mappings **********/ /// @notice keeps track of list of tickets mapping(string => Ticket) public tickets; /// @notice keeps track of list of discount codes mapping(string => DiscountCode) public discountCodes; /// @notice keeps track of list of discount addresses mapping(address => DiscountAddress) public discountAddresses; /// @notice keeps track of list of token discounts mapping(address => TokenDiscount) public tokenDiscounts; /// @notice keeps track of list of token discounts for each ticket /// @dev mapping(token address => mapping(ticket => bool)) mapping(address => mapping(string => bool)) public tokenDiscountTickets; /// @notice keeps track of list of token discounts for each buyer. Can be used once only per buyer. /// @dev mapping(token address => mapping(buyer address => bool)) mapping(address => mapping(address => bool)) public tokenDiscountBuyer; /// @notice keeps track of list of discounts code for each ticket /// @dev mapping(discount code => mapping(ticket => bool)) mapping(string => mapping(string => bool)) public discountCodeTickets; /// @notice keeps track of list of address discounts for each ticket /// @dev mapping(discount address => mapping(ticket => bool)) mapping(address => mapping(string => bool)) public discountAddressTickets; /// @notice keeps track of list of chainlink price feeds mapping(address => address) public priceFeeds; /// @notice stores address of discount contract address private discountContract; /// @notice stores address of nft contract address private nftContract; /// @notice store total number of tickets per attendee mapping(address => Counters.Counter) public attendeesCount; constructor(address _discountContract, address _nftContract) { discountContract = _discountContract; nftContract = _nftContract; owner = address(msg.sender); allowSelfRefund = true; refundFee = 15; resellFee = 15; refundIncFee = 3; refundIncLapse = 1 days; //remove for prod //setTicket(100, 100 * 10**8, 9949326229, 1, "conference-only"); //setTicket(25, 50, 9949326229, 1, "iftar-meetup"); //priceFeeds[address(0)] = 0x7f8847242a530E809E17bF2DA5D2f9d2c4A43261; //kovan optimism //priceFeeds[address(0)] = 0x13e3Ee699D1909E989722E753853AE30b17e08c5; //mainnet optimism //priceFeeds[address(0)] = 0x639Fe6ab55C921f74e7fac1ee960C0B6293ba612; //mainnet arbitrum /* setTicket(100, 28750 * 10**6, 9949326229, 1, "modular-blockchain-conf"); setTicket( 100, 46000 * 10**6, 9949326229, 1, "modular-blockchain-conf-party" ); setTicket( 100, 138000 * 10**6, 9949326229, 1, "modular-blockchain-vc-conf-party" ); setTicket( 100, 149500 * 10**6, 9949326229, 1, "modular-blockchain-conf-hotel" ); setTicket( 100, 207000 * 10**6, 9949326229, 1, "modular-blockchain-conf-party-hotel" ); setTicket( 100, 287500 * 10**6, 9949326229, 1, "modular-blockchain-vc-conf-party-hotel" ); setTicket(100, 28750 * 10**6, 9949326229, 1, "metamask-conf"); setTicket(100, 46000 * 10**6, 9949326229, 1, "metamask-conf-party"); setTicket(100, 138000 * 10**6, 9949326229, 1, "metamask-vc-conf-party"); setTicket(100, 149500 * 10**6, 9949326229, 1, "metamask-conf-hotel"); setTicket( 100, 207000 * 10**6, 9949326229, 1, "metamask-conf-party-hotel" ); setTicket( 100, 287500 * 10**6, 9949326229, 1, "metamask-vc-conf-party-hotel" ); setTicket(100, 28750 * 10**6, 9949326229, 1, "verilog-conf"); setTicket(100, 46000 * 10**6, 9949326229, 1, "verilog-conf-party"); setTicket(100, 138000 * 10**6, 9949326229, 1, "verilog-vc-conf-party"); setTicket(100, 149500 * 10**6, 9949326229, 1, "verilog-conf-hotel"); setTicket( 100, 207000 * 10**6, 9949326229, 1, "verilog-conf-party-hotel" ); setTicket( 100, 287500 * 10**6, 9949326229, 1, "verilog-vc-conf-party-hotel" ); setTicket( 100, 28750 * 10**6, 9949326229, 1, "build-fuelvm-exchange-conf" ); setTicket( 100, 46000 * 10**6, 9949326229, 1, "build-fuelvm-exchange-conf-party" ); setTicket( 100, 138000 * 10**6, 9949326229, 1, "build-fuelvm-exchange-vc-conf-party" ); setTicket( 100, 149500 * 10**6, 9949326229, 1, "build-fuelvm-exchange-conf-hotel" ); setTicket( 100, 207000 * 10**6, 9949326229, 1, "build-fuelvm-exchange-conf-party-hotel" ); setTicket( 100, 287500 * 10**6, 9949326229, 1, "build-fuelvm-exchange-vc-conf-party-hotel" ); */ /* setTicket(100, 28750 * 10**6, 9949326229, 1, "web3-intro-conf"); setTicket(100, 46000 * 10**6, 9949326229, 1, "web3-intro-conf-party"); setTicket( 100, 138000 * 10**6, 9949326229, 1, "web3-intro-vc-conf-party" ); setTicket(100, 149500 * 10**6, 9949326229, 1, "web3-intro-conf-hotel"); setTicket( 100, 207000 * 10**6, 9949326229, 1, "web3-intro-conf-party-hotel" ); setTicket( 100, 287500 * 10**6, 9949326229, 1, "web3-intro-vc-conf-party-hotel" ); setTicket(100, 28750 * 10**6, 9949326229, 1, "moralis-conf"); setTicket(100, 46000 * 10**6, 9949326229, 1, "moralis-conf-party"); setTicket(100, 138000 * 10**6, 9949326229, 1, "moralis-vc-conf-party"); setTicket(100, 149500 * 10**6, 9949326229, 1, "moralis-conf-hotel"); setTicket( 100, 207000 * 10**6, 9949326229, 1, "moralis-conf-party-hotel" ); setTicket( 100, 287500 * 10**6, 9949326229, 1, "moralis-vc-conf-party-hotel" ); setTicket( 100, 0x1010b87200, 9949326229, 1, "modular-blockchain-vc-conf" ); setTicket(100, 0x1010b87200, 9949326229, 1, "verilog-vc-conf"); setTicket(100, 0x1010b87200, 9949326229, 1, "web3-intro-vc-conf"); setTicket( 100, 0x1010b87200, 9949326229, 1, "build-fuelvm-exchange-vc-conf" ); setTicket( 100, 28750 * 10**6, 9949326229, 1, "partnering-with-giants-conf" ); setTicket( 100, 138000 * 10**6, 9949326229, 1, "partnering-with-giants-vc-conf-party" ); setTicket( 100, 149500 * 10**6, 9949326229, 1, "partnering-with-giants-conf-hotel" ); setTicket( 100, 207000 * 10**6, 9949326229, 1, "partnering-with-giants-conf-party-hotel" ); setTicket( 100, 287500 * 10**6, 9949326229, 1, "partnering-with-giants-vc-conf-party-hotel" ); */ ////mainnet /* priceFeeds[address(0)] = 0x4BAD96DD1C7D541270a0C92e1D4e5f12EEEA7a57; //mainnet //WETH priceFeeds[ 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 ] = 0x4BAD96DD1C7D541270a0C92e1D4e5f12EEEA7a57; //WETH mainnet //usdt priceFeeds[ 0xdAC17F958D2ee523a2206206994597C13D831ec7 ] = 0x3E7d1eAB13ad0104d2750B8863b489D65364e32D; //dai priceFeeds[ 0x6B175474E89094C44Da98b954EedeAC495271d0F ] = 0xAed0c38402a5d19df6E4c03F4E2DceD6e29c1ee9; //usdc priceFeeds[ 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 ] = 0x986b5E1e1755e3C2440e960477f25201B0a8bbD4; //rai priceFeeds[ 0x03ab458634910AaD20eF5f1C8ee96F1D6ac54919 ] = 0x483d36F6a1d063d580c7a24F9A42B346f3a69fbb; //sushi priceFeeds[ 0x6B3595068778DD592e39A122f4f5a5cF09C90fE2 ] = 0xCc70F09A6CC17553b2E31954cD36E4A2d89501f7; //LUSD priceFeeds[ 0x5f98805A4E8be255a32880FDeC7F6728C6568bA0 ] = 0x3D7aE7E594f2f2091Ad8798313450130d0Aba3a0; //MIM priceFeeds[ 0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3 ] = 0x7A364e8770418566e3eb2001A96116E6138Eb32F; //xsushi priceFeeds[ 0x8798249c2E607446EfB7Ad49eC89dD1865Ff4272 ] = 0xCC1f5d9e6956447630d703C8e93b2345c2DE3D13; //mkr priceFeeds[ 0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2 ] = 0xec1D1B3b0443256cc3860e24a46F108e699484Aa; //yfi priceFeeds[ 0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e ] = 0xA027702dbb89fbd58938e4324ac03B58d812b0E1; //comp priceFeeds[ 0xc00e94Cb662C3520282E6f5717214004A7f26888 ] = 0xdbd020CAeF83eFd542f4De03e3cF0C28A4428bd5; //matic priceFeeds[ 0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0 ] = 0x7bAC85A8a13A4BcD8abb3eB7d6b4d632c5a57676; //1inch priceFeeds[ 0x111111111117dC0aa78b770fA6A738034120C302 ] = 0xc929ad75B72593967DE83E7F7Cda0493458261D9; //busd priceFeeds[ 0x4Fabb145d64652a948d72533023f6E7A623C7C53 ] = 0x833D8Eb16D306ed1FbB5D7A2E019e106B960965A; OPTIMISM priceFeeds[address(0)] = 0x13e3Ee699D1909E989722E753853AE30b17e08c5; //mainnet //WETH priceFeeds[ 0x4200000000000000000000000000000000000006 ] = 0x13e3Ee699D1909E989722E753853AE30b17e08c5; //WETH mainnet //usdt priceFeeds[ 0x94b008aA00579c1307B0EF2c499aD98a8ce58e58 ] = 0xECef79E109e997bCA29c1c0897ec9d7b03647F5E; //dai priceFeeds[ 0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1 ] = 0x8dBa75e83DA73cc766A7e5a0ee71F656BAb470d6; //usdc priceFeeds[ 0x7F5c764cBc14f9669B88837ca1490cCa17c31607 ] = 0x16a9FA2FDa030272Ce99B29CF780dFA30361E0f3; /*ARBITRUM* priceFeeds[address(0)] = 0x639Fe6ab55C921f74e7fac1ee960C0B6293ba612; //WETH priceFeeds[ 0x82aF49447D8a07e3bd95BD0d56f35241523fBab1 ] = 0x639Fe6ab55C921f74e7fac1ee960C0B6293ba612; //WETH mainnet //usdt priceFeeds[ 0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9 ] = 0x3f3f5dF88dC9F13eac63DF89EC16ef6e7E25DdE7; //dai priceFeeds[ 0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1 ] = 0xc5C8E77B397E531B8EC06BFb0048328B30E9eCfB; //usdc priceFeeds[ 0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8 ] = 0x50834F3163758fcC1Df9973b6e91f0F0F0434aD3; //sushi priceFeeds[ 0xd4d42F0b6DEF4CE0383636770eF773390d85c61A ] = 0xb2A8BA74cbca38508BA1632761b56C897060147C; //MIM priceFeeds[ 0xFEa7a6a0B346362BF88A9e4A88416B77a57D6c2A ] = 0x87121F6c9A9F6E90E59591E4Cf4804873f54A95b; arbitrum*/ /****polygon priceFeeds[address(0)] = 0xAB594600376Ec9fD91F8e885dADF0CE036862dE0; //mainnet //WETH priceFeeds[ 0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619 ] = 0xF9680D99D6C9589e2a93a78A04A279e509205945; //WETH mainnet //usdt priceFeeds[ 0xc2132D05D31c914a87C6611C10748AEb04B58e8F ] = 0x0A6513e40db6EB1b165753AD52E80663aeA50545; //dai priceFeeds[ 0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063 ] = 0x4746DeC9e833A82EC7C2C1356372CcF2cfcD2F3D; //usdc priceFeeds[ 0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174 ] = 0xfE4A8cc5b5B2366C1B58Bea3858e81843581b2F7; //rai priceFeeds[ 0x00e5646f60AC6Fb446f621d146B6E1886f002905 ] = 0x7f45273fD7C644714825345670414Ea649b50b16; //sushi priceFeeds[ 0x0b3F868E0BE5597D5DB7fEB59E1CADBb0fdDa50a ] = 0x49B0c695039243BBfEb8EcD054EB70061fd54aa0; polygon */ /******bsc priceFeeds[address(0)] = 0x0567F2323251f0Aab15c8dFb1967E4e8A7D42aeE; //mainnet //WETH priceFeeds[ 0x2170Ed0880ac9A755fd29B2688956BD959F933F8 ] = 0x9ef1B8c0E4F7dc8bF5719Ea496883DC6401d5b2e; //WETH mainnet //usdt priceFeeds[ 0x55d398326f99059fF775485246999027B3197955 ] = 0xB97Ad0E74fa7d920791E90258A6E2085088b4320; //dai priceFeeds[ 0x1AF3F329e8BE154074D8769D1FFa4eE058B1DBc3 ] = 0x132d3C0B1D2cEa0BC552588063bdBb210FDeecfA; //usdc priceFeeds[ 0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d ] = 0x51597f405303C4377E36123cBc172b13269EA163; //sushi priceFeeds[ 0x947950BcC74888a40Ffa2593C5798F11Fc9124C4 ] = 0x49B0c695039243BBfEb8EcD054EB70061fd54aa0; //MIM priceFeeds[ 0xfE19F0B51438fd612f6FD59C1dbB3eA319f433Ba ] = 0xc9D267542B23B41fB93397a93e5a1D7B80Ea5A01; bsc*/ /******ftm priceFeeds[address(0)] = 0xf4766552D15AE4d256Ad41B6cf2933482B0680dc; //mainnet //WETH priceFeeds[ 0xA59982c7A272839cBd93e02Bd8978E9a78189AB5 ] = 0x11DdD3d147E5b83D01cee7070027092397d63658; //WETH mainnet //usdt priceFeeds[ 0x049d68029688eAbF473097a2fC38ef61633A3C7A ] = 0xF64b636c5dFe1d3555A847341cDC449f612307d0; //dai priceFeeds[ 0x8D11eC38a3EB5E956B052f67Da8Bdc9bef8Abf3E ] = 0x91d5DEFAFfE2854C7D02F50c80FA1fdc8A721e52; //usdc priceFeeds[ 0x04068DA6C83AFCFA0e13ba15A6696662335D5B75 ] = 0x2553f4eeb82d5A26427b8d1106C51499CBa5D99c; //MIM priceFeeds[ 0x82f0B8B456c1A451378467398982d4834b6829c1 ] = 0x28de48D3291F31F839274B8d82691c77DF1c5ceD; ftm*/ /***avax priceFeeds[address(0)] = 0x0A77230d17318075983913bC2145DB16C7366156; //mainnet //WETH priceFeeds[ 0x49D5c2BdFfac6CE2BFdB6640F4F80f226bc10bAB ] = 0x976B3D034E162d8bD72D6b9C989d545b839003b0; //WETH mainnet //usdt priceFeeds[ 0xde3A24028580884448a5397872046a019649b084 ] = 0xEBE676ee90Fe1112671f19b6B7459bC678B67e8a; //dai priceFeeds[ 0xbA7dEebBFC5fA1100Fb055a87773e1E99Cd3507a ] = 0x51D7180edA2260cc4F6e4EebB82FEF5c3c2B8300; //usdc priceFeeds[ 0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E ] = 0xF096872672F44d6EBA71458D74fe67F9a77a23B9; //sushi priceFeeds[ 0x39cf1BD5f15fb22eC3D9Ff86b0727aFc203427cc ] = 0x449A373A090d8A1e5F74c63Ef831Ceff39E94563; //MIM priceFeeds[ 0x130966628846BFd36ff31a822705796e8cb8C18D ] = 0x54EdAB30a7134A16a54218AE64C73e1DAf48a8Fb; /* //btc priceFeeds[ 0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599 ] = 0xF4030086522a5bEEa4988F8cA5B36dbC97BeE88c; //usdt priceFeeds[ 0xdAC17F958D2ee523a2206206994597C13D831ec7 ] = 0x3E7d1eAB13ad0104d2750B8863b489D65364e32D; //dai priceFeeds[ 0x6B175474E89094C44Da98b954EedeAC495271d0F ] = 0xAed0c38402a5d19df6E4c03F4E2DceD6e29c1ee9; //bnb priceFeeds[ 0xB8c77482e45F1F44dE1745F52C74426C631bDD52 ] = 0x14e613AC84a31f709eadbdF89C6CC390fDc9540A; //usdc priceFeeds[ 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 ] = 0x986b5E1e1755e3C2440e960477f25201B0a8bbD4; //link priceFeeds[ 0x514910771AF9Ca656af840dff83E8264EcF986CA ] = 0x2c1d072e956AFFC0D435Cb7AC38EF18d24d9127c; //aave priceFeeds[ 0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9 ] = 0x547a514d5e3769680Ce22B2361c10Ea13619e8a9; //tusd priceFeeds[ 0x0000000000085d4780B73119b644AE5ecd22b376 ] = 0xec746eCF986E2927Abd291a2A1716c940100f8Ba; //mim priceFeeds[ 0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3 ] = 0x7A364e8770418566e3eb2001A96116E6138Eb32F; //rai priceFeeds[ 0x03ab458634910AaD20eF5f1C8ee96F1D6ac54919 ] = 0x483d36F6a1d063d580c7a24F9A42B346f3a69fbb; //fei priceFeeds[ 0x956F47F50A910163D8BF957Cf5846D573E7f87CA ] = 0x31e0a88fecB6eC0a411DBe0e9E76391498296EE9; //uni priceFeeds[ 0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984 ] = 0x553303d460EE0afB37EdFf9bE42922D8FF63220e; //sushi priceFeeds[ 0x6B3595068778DD592e39A122f4f5a5cF09C90fE2 ] = 0xCc70F09A6CC17553b2E31954cD36E4A2d89501f7; //xsushi priceFeeds[ 0x8798249c2E607446EfB7Ad49eC89dD1865Ff4272 ] = 0xCC1f5d9e6956447630d703C8e93b2345c2DE3D13; //mkr priceFeeds[ 0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2 ] = 0xec1D1B3b0443256cc3860e24a46F108e699484Aa; //yfi priceFeeds[ 0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e ] = 0xA027702dbb89fbd58938e4324ac03B58d812b0E1; //comp priceFeeds[ 0xc00e94Cb662C3520282E6f5717214004A7f26888 ] = 0xdbd020CAeF83eFd542f4De03e3cF0C28A4428bd5; //matic priceFeeds[ 0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0 ] = 0x7bAC85A8a13A4BcD8abb3eB7d6b4d632c5a57676; //1inch priceFeeds[ 0x111111111117dC0aa78b770fA6A738034120C302 ] = 0xc929ad75B72593967DE83E7F7Cda0493458261D9; //busd priceFeeds[ 0x4Fabb145d64652a948d72533023f6E7A623C7C53 ] = 0x833D8Eb16D306ed1FbB5D7A2E019e106B960965A; */ } /*********** * Modifiers ***********/ modifier validNameSlug(string memory _slug) { bytes memory tmpSlug = bytes(_slug); // Uses memory require(tmpSlug.length > 0, "Not valid slug"); _; } modifier onlyOwner() { require(address(msg.sender) == owner, "!owner"); _; } /*********** * Functions ***********/ /*** * @notice Allow to set the chainlink feed address of a token * This function will be called by owner to add support for new tokens to buy tickets * @param _token The address of the ERC20 token to be used to pay for a ticket * @param _feed The address of the chainlink feed of the token **/ function setPriceFeed(address _token, address _feed) public onlyOwner { priceFeeds[_token] = _feed; } /*** * @notice Allow to set refund settings * This function will be called by owner to set refunds parameters * @param _allow Sets whether self refunds are enabled or not * @param _refundFee Percentage of the refunds fee * @param _resellFee Percentage of resell fee * @param _refundIncFee Amount by which refund fee gets incremented for self refunds * @param _refundIncLapse Time lapse between each self refund fee increment for self refunds **/ function setRefund( bool _allow, uint256 _refundFee, uint256 _resellFee, uint256 _refundIncFee, uint256 _refundIncLapse ) public onlyOwner { allowSelfRefund = _allow; refundFee = _refundFee; resellFee = _resellFee; refundIncFee = _refundIncFee; refundIncLapse = _refundIncLapse; } /*** * @notice Allow to enable or disable reselling globally * This function will be called by owner to set allowBuyResellable * @param _allow Sets whether buying resellable is enabled or not **/ function setResellable(bool _allow) public onlyOwner { allowBuyResellable = _allow; } /*** * @notice Allow to set tickets * This function will be called by owner to set new or update tickets * @param _qty Amount of tickets available (eg. 1000 tickets) * @param _price Price of ticket in USD (eg 100) * @param _endDate Timestamp of date at which tickets won't be available anymore * @param _startDate Timestamp of date at which tickets can start being bought * @param _slug Name of ticket (eg. early_bird) **/ function setTicket( uint256 _qty, uint256 _price, uint256 _endDate, uint256 _startDate, string memory slug ) public validNameSlug(slug) onlyOwner { Ticket memory t; t.qty = _qty; t.price = _price; t.endDate = _endDate; t.startDate = _startDate; tickets[slug] = t; } /*** * @notice Allow to set discounts based on buyer's token balance * This function will be called by owner to set token balance based discounts * @param _discountToken Address of the token address that will be used (eg. address of $YFI) * @param _minAmount Minimum amount of tokens buyer must have to get discount (eg. 1 $YFI) * @param _qty How many times can this discount be used (eg. 10 transactions only) * @param _amount Amount of the discount in percentage (eg. 5 for a 5% discount) * @param _endDate Timestamp of date at which discount won't be available anymore * @param _startDate Timestamp of date at which discount can start being used * @param _ticketsToAdd Tickets the discount will apply to * @param _ticketsToRemove Tickets the discount will not apply to anymore **/ function setTokenDiscount( address _discountToken, uint256 _minAmount, uint256 _qty, uint256 _amount, uint256 _endDate, uint256 _startDate, string[] memory ticketsToAdd, string[] memory ticketsToRemove ) public onlyOwner { TokenDiscount memory td; td.token = _discountToken; td.minAmount = _minAmount; td.qty = _qty; td.amount = _amount; td.endDate = _endDate; td.startDate = _startDate; tokenDiscounts[_discountToken] = td; for (uint256 i = 0; i < ticketsToAdd.length; i++) { tokenDiscountTickets[_discountToken][ticketsToAdd[i]] = true; } for (uint256 i = 0; i < ticketsToRemove.length; i++) { tokenDiscountTickets[_discountToken][ticketsToRemove[i]] = false; } } /*** * @notice Allow to set discounts codes * This function will be called by owner to set a discount code * @param _code Value of code that can be used * @param _qty How many times can this discount be used (eg. 10 transactions only) * @param _amount Amount of the discount in percentage (eg. 5 for a 5% discount) * @param _endDate Timestamp of date at which discount won't be available anymore * @param _startDate Timestamp of date at which discount can start being used * @param _ticketsToAdd Tickets the discount will apply to * @param _ticketsToRemote Tickets the discount will not apply to anymore **/ function setDiscountCodes( string memory _code, uint256 _qty, uint256 _amount, uint256 _endDate, uint256 _startDate, string[] memory _ticketsToAdd, string[] memory _ticketsToRemove ) public onlyOwner { DiscountCode memory td; td.qty = _qty; td.amount = _amount; td.endDate = _endDate; td.startDate = _startDate; discountCodes[_code] = td; for (uint256 i = 0; i < _ticketsToAdd.length; i++) { discountCodeTickets[_code][_ticketsToAdd[i]] = true; } for (uint256 i = 0; i < _ticketsToRemove.length; i++) { discountCodeTickets[_code][_ticketsToRemove[i]] = false; } } /*** * @notice Allow to set discounts based on buyer address * This function will be called by owner to set address based discounts * @param _buyer Address of buyer that can use the code * @param _qty How many times can this discount be used (eg. 10 transactions only) * @param _amount Amount of the discount in percentage (eg. 5 for a 5% discount) * @param _endDate Timestamp of date at which discount won't be available anymore * @param _startDate Timestamp of date at which discount can start being used * @param _ticketsToAdd Tickets the discount will apply to * @param _ticketsToRemote Tickets the discount will not apply to anymore **/ function setDiscountAddresses( address buyer, uint256 qty, uint256 amount, uint256 endDate, uint256 startDate, string[] memory ticketsToAdd, string[] memory ticketsToRemove ) public onlyOwner { DiscountAddress memory td; td.qty = qty; td.amount = amount; td.endDate = endDate; td.startDate = startDate; discountAddresses[buyer] = td; for (uint256 i = 0; i < ticketsToAdd.length; i++) { discountAddressTickets[buyer][ticketsToAdd[i]] = true; } for (uint256 i = 0; i < ticketsToRemove.length; i++) { discountAddressTickets[buyer][ticketsToRemove[i]] = false; } } /*** * @notice Buy ticket function * This function will be called by tickets buyers to buy tickets * @param _buyAttendees mapping of Attendee details * @param _buyToken address of token being used to buy tickets (eg DAI, USDC, if ETH use 0x0) **/ function mintTicket( Attendee[] memory _buyAttendees, address _buyToken ) public payable nonReentrant { uint256 total = 0; uint256 discount = 0; //AggregatorV3Interface priceFeed; uint256 valueToken = 0; require(priceFeeds[_buyToken] != address(0), "token not supported"); for (uint256 i = 0; i < _buyAttendees.length; i++) { require( tickets[_buyAttendees[i].ticket].used.current() < tickets[_buyAttendees[i].ticket].qty, "sold out" ); require( tickets[_buyAttendees[i].ticket].startDate < block.timestamp, "not available yet" ); require( tickets[_buyAttendees[i].ticket].endDate > block.timestamp, "not available anymore" ); discount = getDiscount(msg.sender, _buyAttendees[i]); uint256 priceToPay = getPrice(discount, _buyAttendees[i].ticket); total += priceToPay; _buyAttendees[i].sender = msg.sender; _buyAttendees[i].pricePaid = priceToPay; _buyAttendees[i].pricePaidInToken = getPriceFromUSD( priceToPay, _buyToken ); _buyAttendees[i].boughtOn = block.timestamp; _buyAttendees[i].buyToken = _buyToken; NFTRemote nc = NFTRemote(nftContract); uint256 nftId = nc.mintItem( msg.sender, _buyAttendees[i].ticket, _buyAttendees[i].social ); _buyAttendees[i].nftId = nftId; setAttendee( attendeesCount[msg.sender].current(), _buyAttendees[i], _buyAttendees[i], msg.sender, false, false ); tickets[_buyAttendees[i].ticket].used.increment(); attendeesCount[msg.sender].increment(); emit LMint(msg.sender, _buyAttendees[i], "buy"); } valueToken = getPriceFromUSD(total, _buyToken); require(valueToken > 0 || total == 0, "total 0"); if (_buyToken == address(0)) { require(msg.value >= valueToken, "price too low"); if (msg.value > valueToken) { (bool ok, ) = msg.sender.call{value: msg.value - valueToken}( "" ); require(ok, "Failed"); } } else { require( IERC20(_buyToken).transferFrom( address(msg.sender), address(this), uint256(valueToken) ), "transfer failed" ); } emit LogBuy(msg.sender, msg.value, valueToken, _buyToken); } /*** * @notice get pricing in USD for a given token * This function gets pricing from chainlink in USD for a token * @param _priceUSD amount in USD * @param _token token address **/ function getPriceFromUSD( uint256 _priceUSD, address _token ) private view returns (uint256) { AggregatorV3Interface priceFeed; priceFeed = AggregatorV3Interface(priceFeeds[_token]); (, int256 latestPrice, , , ) = priceFeed.latestRoundData(); //int256 latestPrice = 326393000000; uint256 decimals = 18; if (_token != 0x0000000000000000000000000000000000000000) { IERC20Metadata ercToken = IERC20Metadata(_token); decimals = ercToken.decimals(); } uint256 price = uint256( (int256(_priceUSD) * int256(10 ** decimals)) / latestPrice ); return price; } /*** * @notice get price minus discount * This function caluculates price minus discount * @param _discount discount amount * @param _ticket ticket slug name **/ function getPrice( uint256 _discount, string memory _ticket ) public view returns (uint256) { uint256 price = tickets[_ticket].price; return price - (price * _discount) / 100; } /*** * @notice retrieve attendee details * This function gets Attendee details by address and index * @param _sender Address of attendee * @param _index Attendee ticket index (each attendee can have more than one ticket) **/ function getAttendee( address _sender, uint256 _index ) private view returns (Attendee memory attendee) { SRTicketsDiscountsRemote dc = SRTicketsDiscountsRemote( discountContract ); attendee = dc.getAttendee(_sender, _index); } /*** * @notice set attendee details * This function sets Attendee details by address and index * @param _attendeeIndex index of attendee * @param _newAttendee new attendee struct * @param _attendee current attendee struct * @param _sender Address of attendee * @param _resell true if this operation is a resell of the attendee's ticket * @param _isRefund true if this operation is a refund of the attendee's ticket **/ function setAttendee( uint256 _attendeeIndex, Attendee memory _newAttendee, Attendee memory _attendee, address _sender, bool _resell, bool _isRefund ) private { SRTicketsDiscountsRemote dc = SRTicketsDiscountsRemote( discountContract ); dc.setAttendee( _attendeeIndex, _newAttendee, _attendee, _sender, _resell, _isRefund ); } /*** * @notice get discount for an attendee * This view function checks if an attendee gets a discount * @param _sender Address of attendee * @param _attendee current attendee struct **/ function getDiscountView( address _sender, Attendee memory _attendee ) public view returns (uint256) { SRTicketsDiscountsRemote.DiscountResponse memory dr = getDiscountAmount( _sender, _attendee ); return dr.discountAmount; //discountCodeTickets["50pc-discount"]["conference-only"]; } /*** * @notice get discount for all attendees * This view function checks if each attendee gets a discount * @param _sender Address of buyer * @param _attendees attendees array **/ function getDiscountsView( address _sender, Attendee[] memory _attendees ) public view returns (uint256) { uint256 total = 0; for (uint256 i = 0; i < _attendees.length; i++) { SRTicketsDiscountsRemote.DiscountResponse memory dr = getDiscountAmount(_sender, _attendees[i]); total = total + dr.discountAmount; //discountCodeTickets["50pc-discount"]["conference-only"]; } return total; } /*** * @notice get discount amount for an attendee * This function checks if an attendee gets a discount and apllies it if true * @param _sender Address of attendee * @param _attendee current attendee struct **/ function getDiscount( address _sender, Attendee memory _attendee ) private returns (uint256) { SRTicketsDiscountsRemote.DiscountResponse memory dr = getDiscountAmount( _sender, _attendee ); if (dr.hasDiscountCode) { discountCodes[_attendee.discountCode].used.increment(); } if (dr.hasDiscountAddress) { discountAddresses[_sender].used.increment(); } if (dr.hasTokenDiscount) { tokenDiscounts[_attendee.tokenDiscount].used.increment(); tokenDiscountBuyer[_attendee.tokenDiscount][_sender] = true; } return dr.discountAmount; } /*** * @notice get discount amount for an attendee * This function computes discount amount for an attendee if any * @param _sender Address of attendee * @param _attendee current attendee struct **/ function getDiscountAmount( address _sender, Attendee memory _attendee ) private view returns (SRTicketsDiscountsRemote.DiscountResponse memory) { //check sender Discount code SRTicketsDiscountsRemote dc = SRTicketsDiscountsRemote( discountContract ); SRTicketsDiscountsRemote.SenderAndTokenDiscountBuyer memory stdb; stdb.sender = _sender; stdb.tokenDiscountBuyer = tokenDiscountBuyer[_attendee.tokenDiscount][ _sender ]; SRTicketsDiscountsRemote.DiscountResponse memory dr = dc .getDiscountView( stdb, discountCodeTickets[_attendee.discountCode][_attendee.ticket], discountCodes[_attendee.discountCode], discountAddressTickets[_attendee.sender][_attendee.ticket], discountAddresses[_attendee.sender], tokenDiscountTickets[_attendee.tokenDiscount][_attendee.ticket], tokenDiscounts[_attendee.tokenDiscount], _attendee.tokenDiscount ); return dr; } /*** * @notice update attendee details * This function allows an attendee to update their own ticket * if new ticket is more expensive, attendee needs to pay the difference * @param _attendeeIndex attendee index * @param _newAttendee new attendee details **/ function updateAttendee( uint256 _attendeeIndex, address _attendeeAddress, Attendee memory _newAttendee ) public payable nonReentrant { Attendee memory oldAttendee = getAttendee( _attendeeAddress, _attendeeIndex ); require( oldAttendee.sender == msg.sender || msg.sender == owner, "not allowed to update" ); require(!oldAttendee.cancelled, "already cancelled"); //if attendee is just updating eg. their name but same ticket, skip even if ticket has gone up in price if ( (oldAttendee.sender == msg.sender || msg.sender == owner) && !stringsEquals(_newAttendee.ticket, oldAttendee.ticket) ) { require( tickets[_newAttendee.ticket].used.current() < tickets[_newAttendee.ticket].qty, "sold out" ); require( tickets[_newAttendee.ticket].startDate < block.timestamp, "not available yet" ); require( tickets[_newAttendee.ticket].endDate > block.timestamp, "not available anymore" ); //only charge more if attendee is updating to a different more expensive ticket if (tickets[_newAttendee.ticket].price > oldAttendee.pricePaid) { uint256 newAmountPaidInToken = getPriceFromUSD( tickets[_newAttendee.ticket].price - oldAttendee.pricePaid, oldAttendee.buyToken ); if (oldAttendee.buyToken == address(0)) { require( msg.value >= newAmountPaidInToken, "new ticket more expensive" ); } else { require( IERC20(oldAttendee.buyToken).transferFrom( address(msg.sender), address(this), newAmountPaidInToken ), "transfer failed" ); } //increase number of tickets used with this update tickets[_newAttendee.ticket].used.increment(); //decrease number of tickets used for attendee ticket pre-update tickets[oldAttendee.ticket].used.decrement(); oldAttendee.pricePaid = tickets[_newAttendee.ticket].price; oldAttendee.pricePaidInToken = oldAttendee.pricePaidInToken + newAmountPaidInToken; } } setAttendee( _attendeeIndex, _newAttendee, oldAttendee, _attendeeAddress, false, false ); } /*** * @notice refund attendee * This function allows owner to refund attendee * @param _buyer buyer's address * @param _attendeeIndex attendee index * @param _amount amount to refund **/ function refund( address _buyer, uint256 _attendeeIndex, uint256 _amount ) public onlyOwner nonReentrant { Attendee memory attendee = getAttendee(_buyer, _attendeeIndex); require( attendee.pricePaidInToken >= _amount, "refund higher than paid price" ); require(!attendee.cancelled, "already cancelled"); //set attendee nft as cancelled NFTRemote nc = NFTRemote(nftContract); nc.setCancelled(attendee.nftId); tickets[attendee.ticket].used.decrement(); if (attendee.buyToken != address(0)) { IERC20(attendee.buyToken).safeTransfer( address(attendee.sender), _amount ); attendee.refunded = _amount; attendee.cancelled = true; setAttendee( _attendeeIndex, attendee, attendee, attendee.sender, false, true ); } else { (bool ok, ) = address(_buyer).call{value: _amount}(""); require(ok, "Failed"); attendee.refunded = _amount; attendee.cancelled = true; setAttendee( _attendeeIndex, attendee, attendee, attendee.sender, false, true ); } emit LogRefund(_buyer, _amount, _attendeeIndex, attendee.buyToken); } /*** * @notice self-refund attendee * This function allows attendee to get a refund automatically * as time passes by, every x seconds the refundable amount decreases by y * x is refundIncLapse and y refundIncFee * @param _attendeeIndex attendee index **/ function selfRefund(uint256 _attendeeIndex) public nonReentrant { Attendee memory attendee = getAttendee(msg.sender, _attendeeIndex); require(attendee.sender == msg.sender, "sender is not buyer"); require(allowSelfRefund, "refund not possible"); require(!attendee.cancelled, "already cancelled"); require(!attendee.resold, "resold, see refund with reseller"); require( tickets[attendee.ticket].endDate > block.timestamp, "refund not possible anymore" ); uint256 feePercentage = (refundIncFee * (block.timestamp - attendee.boughtOn)) / refundIncLapse; require(feePercentage < 100, "refund not possible"); uint256 amount = attendee.pricePaidInToken - ((feePercentage * attendee.pricePaidInToken) / 100); //set attendee nft as cancelled NFTRemote nc = NFTRemote(nftContract); nc.setCancelled(attendee.nftId); tickets[attendee.ticket].used.decrement(); if (attendee.buyToken != address(0)) { IERC20(attendee.buyToken).safeTransfer( address(attendee.sender), amount ); attendee.refunded = amount; attendee.cancelled = true; setAttendee( _attendeeIndex, attendee, attendee, attendee.sender, false, true ); } else { (bool ok, ) = address(attendee.sender).call{value: amount}(""); require(ok, "Failed"); attendee.refunded = amount; attendee.cancelled = true; setAttendee( _attendeeIndex, attendee, attendee, attendee.sender, false, true ); } } /*** * @notice buy a resellable ticket * This function allows anyone to buy someone's else ticket as long as allowResell is true * @param _attendeeIndex attendee index * @param _newAttendee newAttendee details **/ function buyResellable( uint256 _attendeeIndex, Attendee memory _newAttendee ) public payable nonReentrant { Attendee memory attendee = getAttendee( _newAttendee.sender, _attendeeIndex ); bool canUpdate = false; require(attendee.allowResell, "not for sell"); require(allowBuyResellable, "reselling desabled"); require(!attendee.cancelled, "already cancelled"); require( stringsEquals(_newAttendee.ticket, attendee.ticket), "different ticket" ); if (attendee.buyToken != address(0)) { require( IERC20(attendee.buyToken).transferFrom( address(msg.sender), address(this), uint256((attendee.resellPrice * resellFee) / 100) ), "transfer failed" ); require( IERC20(attendee.buyToken).transferFrom( address(msg.sender), address(attendee.sender), uint256( attendee.resellPrice - (attendee.resellPrice * resellFee) / 100 ) ), "transfer failed" ); canUpdate = true; } else { require(msg.value == attendee.resellPrice, "not enough fund"); (bool ok, ) = attendee.sender.call{ value: attendee.resellPrice - (attendee.resellPrice * resellFee) / 100 }(""); require(ok, "Failed"); canUpdate = true; } if (canUpdate) { setAttendee( attendeesCount[msg.sender].current(), _newAttendee, attendee, msg.sender, true, false ); attendeesCount[msg.sender].increment(); } } /*** * @notice withdraw funds * This function allows owner to withdraw funds from contracts * @param _token address of token to withdraw * @param _amount amount to withdraw **/ function withdraw(address _token, uint256 _amount) external onlyOwner { if (_token != address(0)) { IERC20(_token).safeTransfer(address(owner), _amount); } else { (bool ok, ) = owner.call{value: _amount}(""); require(ok, "Failed"); } } function setOwner(address _newOwner) public onlyOwner { tbcOwner = _newOwner; emit LogSetOwner(msg.sender, _newOwner); } function confirmOwner(address _newOwner) public onlyOwner { require(_newOwner == tbcOwner, "not confirmed"); require( _newOwner != 0x0000000000000000000000000000000000000000, "address cant be 0" ); owner = _newOwner; } /* function getThing() public view returns (uint256) { // return discountAddressTickets[attendee.sender][attendee.ticket]; //return discountAddresses[0x70997970C51812dc3A010C7d01b50e0d17dc79C8]; AggregatorV3Interface priceFeed; priceFeed = AggregatorV3Interface( priceFeeds[0x0000000000000000000000000000000000000000] ); (, int256 latestPrice, , , ) = priceFeed.latestRoundData(); //int256 latestPrice = 326393000000; //uint256 price = uint256((int256(100 * 10**8) * 10**18) / latestPrice); return uint256(latestPrice); } */ } function stringsEquals(string memory s1, string memory s2) pure returns (bool) { bytes memory b1 = bytes(s1); bytes memory b2 = bytes(s2); uint256 l1 = b1.length; if (l1 != b2.length) return false; for (uint256 i = 0; i < l1; i++) { if (b1[i] != b2[i]) return false; } return true; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.15; import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import "@openzeppelin/contracts/utils/Counters.sol"; import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import "@openzeppelin/contracts/finance/PaymentSplitter.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; contract JobBoard is ReentrancyGuard { // The amount of ETH to be paid per block for a job ad uint256 public amountPerBlock; using EnumerableSet for EnumerableSet.AddressSet; using SafeERC20 for IERC20; address public owner; // The struct for a job ad struct JobAd { // The ID of the job ad uint256 id; // The title of the job ad string title; // The description of the job ad string description; // The URL where users can apply for the job string apply_url; // The expiring date of the job ad uint256 expiring_date; // Whether the job ad has been validated or not bool validated; //address of ad owner address owner; string tags; } struct Application { uint256 id; string github; string linkedin; uint256 jobId; bool validated; address owner; } // The mapping from job ad IDs to job ads mapping(uint256 => JobAd) public jobAds; mapping(uint256 => Application) public applications; //trustedAddresses are allowed to validate ads //and applications EnumerableSet.AddressSet trustedAddresses; // The counter for generating unique job ad IDs uint256 public jobAdCounter; uint256 public applicationCounter; // The constructor function constructor() { // Set the amountPerBlock to a default value of 1 ETH per block amountPerBlock = 1 ether; } modifier onlyOwner() { require(address(msg.sender) == owner, "!owner"); _; } // The function to create a new job ad function createApplication( //this info (github and linkedin) will be encrypted in the frontend using //the public key of the ad owner and the the public key //of each validator string memory _github, string memory _linkedin, uint _jobId ) public payable { // Generate a unique ID for the job ad uint256 applicationId = applicationCounter++; // Create a new job ad with the specified parameters Application memory application = Application({ id: applicationId, github: _github, linkedin: _linkedin, jobId: _jobId, validated: false, owner: msg.sender }); applications[applicationId] = application; } // The function to create a new job ad function createAd( string memory _title, string memory _description, string memory _apply_url, uint256 _expiring_date, string memory _tags ) public payable { // Generate a unique ID for the job ad uint256 adId = jobAdCounter++; // Create a new job ad with the specified parameters JobAd memory ad = JobAd({ id: adId, title: _title, description: _description, apply_url: _apply_url, expiring_date: _expiring_date, validated: true, tags: _tags, owner: msg.sender }); // Save the new job ad jobAds[adId] = ad; // Calculate the fee to be paid for the job ad uint256 fee = amountPerBlock * (ad.expiring_date - block.number); // Require the user to pay the fee in ETH require(msg.value >= fee, "Insufficient ETH"); } // The function to bump the expiring date of a job ad function bumpExpiringDate( uint256 _ad_id, uint256 _new_expiring_date ) public payable { // Get the job ad to bump the expiring date for JobAd storage ad = jobAds[_ad_id]; // Update the expiring date of the job ad ad.expiring_date = _new_expiring_date; // Calculate the fee to be paid for extending the expiring date uint256 fee = amountPerBlock * (ad.expiring_date - block.number); // Require the user to pay the fee in ETH require(msg.value >= fee, "Insufficient ETH"); } // The function to check if a job ad has expired function isExpired(uint256 _ad_id) public view returns (bool) { // Get the job ad to check JobAd storage ad = jobAds[_ad_id]; // Return whether the job ad has expired or not return (ad.expiring_date <= block.number); } // The function to check if a job ad has been validated function isValidatedAd(uint256 _ad_id) public view returns (bool) { // Get the job ad to check JobAd storage ad = jobAds[_ad_id]; return ad.validated; } // The function to check if an application has been validated function isValidatedApplication( uint256 _application_id ) public view returns (bool) { // Get the job ad to check Application storage application = applications[_application_id]; return application.validated; } function validateAd(uint256 _ad_id) public { if (trustedAddresses.contains(msg.sender)) { JobAd storage ad = jobAds[_ad_id]; } } function validateApplication(uint256 _application_id) public { if (trustedAddresses.contains(msg.sender)) { Application storage application = applications[_application_id]; // application.confirmations += application.confirmations; } } function distributeGains() public {} /*** * @notice withdraw funds * This function allows owner to withdraw funds from contracts * @param _token address of token to withdraw * @param _amount amount to withdraw **/ function withdraw(address _token, uint256 _amount) external onlyOwner { if (_token != address(0)) { IERC20(_token).safeTransfer(address(owner), _amount); } else { (bool ok, ) = owner.call{value: _amount}(""); require(ok, "Failed"); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Counters.sol) pragma solidity ^0.8.0; /** * @title Counters * @author Matt Condon (@shrugs) * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number * of elements in a mapping, issuing ERC721 ids, or counting request ids. * * Include with `using Counters for Counters.Counter;` */ library Counters { struct Counter { // This variable should never be directly accessed by users of the library: interactions must be restricted to // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add // this feature: see https://github.com/ethereum/solidity/issues/4637 uint256 _value; // default: 0 } function current(Counter storage counter) internal view returns (uint256) { return counter._value; } function increment(Counter storage counter) internal { unchecked { counter._value += 1; } } function decrement(Counter storage counter) internal { uint256 value = counter._value; require(value > 0, "Counter: decrement overflow"); unchecked { counter._value = value - 1; } } function reset(Counter storage counter) internal { counter._value = 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/structs/EnumerableSet.sol) pragma solidity ^0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; if (lastIndex != toDeleteIndex) { bytes32 lastvalue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastvalue; // Update the index for the moved value set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex } // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { return _values(set._inner); } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values on the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; assembly { result := store } return result; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (finance/PaymentSplitter.sol) pragma solidity ^0.8.0; import "../token/ERC20/utils/SafeERC20.sol"; import "../utils/Address.sol"; import "../utils/Context.sol"; /** * @title PaymentSplitter * @dev This contract allows to split Ether payments among a group of accounts. The sender does not need to be aware * that the Ether will be split in this way, since it is handled transparently by the contract. * * The split can be in equal parts or in any other arbitrary proportion. The way this is specified is by assigning each * account to a number of shares. Of all the Ether that this contract receives, each account will then be able to claim * an amount proportional to the percentage of total shares they were assigned. * * `PaymentSplitter` follows a _pull payment_ model. This means that payments are not automatically forwarded to the * accounts but kept in this contract, and the actual transfer is triggered as a separate step by calling the {release} * function. * * NOTE: This contract assumes that ERC20 tokens will behave similarly to native tokens (Ether). Rebasing tokens, and * tokens that apply fees during transfers, are likely to not be supported as expected. If in doubt, we encourage you * to run tests before sending real value to this contract. */ contract PaymentSplitter is Context { event PayeeAdded(address account, uint256 shares); event PaymentReleased(address to, uint256 amount); event ERC20PaymentReleased(IERC20 indexed token, address to, uint256 amount); event PaymentReceived(address from, uint256 amount); uint256 private _totalShares; uint256 private _totalReleased; mapping(address => uint256) private _shares; mapping(address => uint256) private _released; address[] private _payees; mapping(IERC20 => uint256) private _erc20TotalReleased; mapping(IERC20 => mapping(address => uint256)) private _erc20Released; /** * @dev Creates an instance of `PaymentSplitter` where each account in `payees` is assigned the number of shares at * the matching position in the `shares` array. * * All addresses in `payees` must be non-zero. Both arrays must have the same non-zero length, and there must be no * duplicates in `payees`. */ constructor(address[] memory payees, uint256[] memory shares_) payable { require(payees.length == shares_.length, "PaymentSplitter: payees and shares length mismatch"); require(payees.length > 0, "PaymentSplitter: no payees"); for (uint256 i = 0; i < payees.length; i++) { _addPayee(payees[i], shares_[i]); } } /** * @dev The Ether received will be logged with {PaymentReceived} events. Note that these events are not fully * reliable: it's possible for a contract to receive Ether without triggering this function. This only affects the * reliability of the events, and not the actual splitting of Ether. * * To learn more about this see the Solidity documentation for * https://solidity.readthedocs.io/en/latest/contracts.html#fallback-function[fallback * functions]. */ receive() external payable virtual { emit PaymentReceived(_msgSender(), msg.value); } /** * @dev Getter for the total shares held by payees. */ function totalShares() public view returns (uint256) { return _totalShares; } /** * @dev Getter for the total amount of Ether already released. */ function totalReleased() public view returns (uint256) { return _totalReleased; } /** * @dev Getter for the total amount of `token` already released. `token` should be the address of an IERC20 * contract. */ function totalReleased(IERC20 token) public view returns (uint256) { return _erc20TotalReleased[token]; } /** * @dev Getter for the amount of shares held by an account. */ function shares(address account) public view returns (uint256) { return _shares[account]; } /** * @dev Getter for the amount of Ether already released to a payee. */ function released(address account) public view returns (uint256) { return _released[account]; } /** * @dev Getter for the amount of `token` tokens already released to a payee. `token` should be the address of an * IERC20 contract. */ function released(IERC20 token, address account) public view returns (uint256) { return _erc20Released[token][account]; } /** * @dev Getter for the address of the payee number `index`. */ function payee(uint256 index) public view returns (address) { return _payees[index]; } /** * @dev Triggers a transfer to `account` of the amount of Ether they are owed, according to their percentage of the * total shares and their previous withdrawals. */ function release(address payable account) public virtual { require(_shares[account] > 0, "PaymentSplitter: account has no shares"); uint256 totalReceived = address(this).balance + totalReleased(); uint256 payment = _pendingPayment(account, totalReceived, released(account)); require(payment != 0, "PaymentSplitter: account is not due payment"); _released[account] += payment; _totalReleased += payment; Address.sendValue(account, payment); emit PaymentReleased(account, payment); } /** * @dev Triggers a transfer to `account` of the amount of `token` tokens they are owed, according to their * percentage of the total shares and their previous withdrawals. `token` must be the address of an IERC20 * contract. */ function release(IERC20 token, address account) public virtual { require(_shares[account] > 0, "PaymentSplitter: account has no shares"); uint256 totalReceived = token.balanceOf(address(this)) + totalReleased(token); uint256 payment = _pendingPayment(account, totalReceived, released(token, account)); require(payment != 0, "PaymentSplitter: account is not due payment"); _erc20Released[token][account] += payment; _erc20TotalReleased[token] += payment; SafeERC20.safeTransfer(token, account, payment); emit ERC20PaymentReleased(token, account, payment); } /** * @dev internal logic for computing the pending payment of an `account` given the token historical balances and * already released amounts. */ function _pendingPayment( address account, uint256 totalReceived, uint256 alreadyReleased ) private view returns (uint256) { return (totalReceived * _shares[account]) / _totalShares - alreadyReleased; } /** * @dev Add a new payee to the contract. * @param account The address of the payee to add. * @param shares_ The number of shares owned by the payee. */ function _addPayee(address account, uint256 shares_) private { require(account != address(0), "PaymentSplitter: account is the zero address"); require(shares_ > 0, "PaymentSplitter: shares are 0"); require(_shares[account] == 0, "PaymentSplitter: account already has shares"); _payees.push(account); _shares[account] = shares_; _totalShares = _totalShares + shares_; emit PayeeAdded(account, shares_); } }
// 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 (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 //vedb25b pragma solidity 0.8.15; import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import "@openzeppelin/contracts/utils/Counters.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol"; import "@openzeppelin/contracts/utils/Strings.sol"; contract ISRTickets { mapping(address => Counters.Counter) public attendeesCount; } contract NFTRemote { function mintItem( address attendee, string memory ticketName, string memory social ) public returns (uint256) {} function setCancelled(uint256 itemId) public {} function setSRTicketsDiscountsAddress(address _srtdiscount) public {} function setSocialTicket( string memory ticketName, string memory social, uint256 itemId ) public {} } contract SRTicketsDiscounts { using Counters for Counters.Counter; struct DiscountResponse { bool hasDiscountCode; bool hasDiscountAddress; bool hasTokenDiscount; uint256 discountAmount; } struct SenderAndTokenDiscountBuyer { address sender; bool tokenDiscountBuyer; } mapping(address => mapping(uint256 => Attendee)) private attendees; mapping(address => Counters.Counter) public attendeesCount; // attendee details, fields are encrypted on the frontend struct Attendee { string email; string fname; string lname; string bio; string job; string company; string social; string ticket; string discountCode; address tokenDiscount; address sender; address buyToken; uint256 pricePaid; uint256 pricePaidInToken; bool cancelled; uint256 refunded; bool allowResell; uint256 resellPrice; string code; uint256 boughtOn; bool resold; uint256 nftId; } // discount code details struct DiscountCode { uint256 qty; Counters.Counter used; uint256 amount; string code; uint256 endDate; uint256 startDate; } // discount address details, discount based on buyer address struct DiscountAddress { address buyer; uint256 qty; Counters.Counter used; uint256 amount; string code; uint256 endDate; uint256 startDate; } // discount token details, discount based on a buyer's token balance // can be used once only per buyer struct TokenDiscount { address token; uint256 minAmount; uint256 qty; Counters.Counter used; uint256 amount; uint256 endDate; uint256 startDate; } // @notice store address of ticket contract address public SRTicketsAddress; // @notice store address of contract owner address public owner; /// @notice stores address of nft contract address private nftContract; constructor() { owner = msg.sender; } event LogAttendee( address indexed attendeeAddress, uint256 attendeeIndex, string message ); event LogResell( address indexed buyerAddress, address sellerAddress, uint256 buyerIndex, uint256 sellerIndex, string message ); /*** * @notice set ticket contract address * This function allows owner to set contract ticket address * @param _newAddr contract address **/ function setSRTicketsAddress(address _newAddr) public { require(msg.sender == owner, "not owner"); SRTicketsAddress = _newAddr; } /*** * @notice set nft contract address * This function allows owner to set nft contract address * @param _newAddr contract address **/ function setNFTContract(address _newAddr) public { require(msg.sender == owner, "not owner"); nftContract = _newAddr; } /*** * @notice set attendee details * This function sets Attendee details by address and index * @param _attendeeIndex index of attendee * @param _newAttendee new attendee struct * @param _attendee current attendee struct * @param _sender Address of attendee * @param _resell true if this operation is a resell of the attendee's ticket * @param _isRefund true if this operation is a refund of the attendee's ticket **/ function setAttendee( uint256 attendeeIndex, Attendee memory newAttendee, Attendee memory attendee, address sender, bool resell, bool refund ) public { require( msg.sender == SRTicketsAddress, string.concat( Strings.toHexString(uint160(msg.sender), 20), " not allowed, required ", Strings.toHexString(uint160(SRTicketsAddress), 20) ) ); Attendee memory exAttendee = attendee; bool updateSocialTicket = false; if ( !stringsEquals(exAttendee.social, newAttendee.social) || !stringsEquals(exAttendee.ticket, newAttendee.ticket) ) { updateSocialTicket = true; } attendee.email = newAttendee.email; attendee.fname = newAttendee.fname; attendee.lname = newAttendee.lname; attendee.social = newAttendee.social; attendee.bio = newAttendee.bio; attendee.job = newAttendee.job; attendee.company = newAttendee.company; attendee.allowResell = newAttendee.allowResell; attendee.resellPrice = newAttendee.resellPrice; attendee.ticket = newAttendee.ticket; if (refund) { attendee.refunded = newAttendee.refunded; attendee.cancelled = newAttendee.cancelled; } if (resell) { attendees[exAttendee.sender][attendeeIndex].cancelled = true; attendees[exAttendee.sender][attendeeIndex].allowResell = false; //set old attendee nft as cancelled NFTRemote nc = NFTRemote(nftContract); nc.setCancelled(attendees[exAttendee.sender][attendeeIndex].nftId); uint256 oldAttendeeIndex = attendeeIndex; attendee.code = newAttendee.code; attendee.sender = sender; attendee.cancelled = false; attendee.allowResell = false; attendee.resellPrice = 0; attendee.resold = true; // mint new nft for new owner uint256 nftId = nc.mintItem( attendee.sender, attendee.ticket, attendee.social ); attendee.nftId = nftId; emit LogResell( sender, exAttendee.sender, attendeeIndex, oldAttendeeIndex, "resell" ); } if (updateSocialTicket) { NFTRemote ncupdated = NFTRemote(nftContract); ncupdated.setSocialTicket( attendee.ticket, attendee.social, attendee.nftId ); } attendees[sender][attendeeIndex] = attendee; emit LogAttendee(sender, attendeeIndex, "setAttendee"); } /*** * @notice get discount code amount for an attendee * This function checks discount code amount * @params _discountCodeTicketAttendee defines whether attendee has a discount code * @params _dcQty how many discount in total * @params _dcStartDate Timestamp of date at which discount can start being used * @params _dcEndDate Timestamp of date at which discount won't be available anymore * @params _dcUsed Amount of discount used * @params _dcAmount Amount of the discount in percentage (eg. 5 for a 5% discount) **/ function getDiscountCodeAmount( bool _discountCodeTicketAttendee, uint256 _dcQty, uint256 _dcStartDate, uint256 _dcEndDate, uint256 _dcUsed, uint256 _dcAmount ) public view returns (uint256, bool found) { uint256 discountAmount = 0; if (_discountCodeTicketAttendee) { if ( _dcUsed < _dcQty && _dcStartDate < block.timestamp && _dcEndDate > block.timestamp ) { discountAmount = _dcAmount; found = true; } } return (discountAmount, found); } /*** * @notice get discount address amount for an attendee * This function checks discount address amount (discount based on sender address) * @params _discountAddressTicketAttendee true if attendee has a discount based on address * @params _dcQty how many discount in total * @params _dcStartDate Timestamp of date at which discount can start being used * @params _dcEndDate Timestamp of date at which discount won't be available anymore * @params _dcUsed Amount of discount used * @params _dcAmount Amount of the discount in percentage (eg. 5 for a 5% discount) **/ function getDiscountAddressAmount( bool _discountAddressTicketAttendee, uint256 _daQty, uint256 _daStartDate, uint256 _daEndDate, uint256 _daUsed, uint256 _daAmount, uint256 _discountAmount ) public view returns (uint256, bool found) { if (_discountAddressTicketAttendee) { if ( _daQty > _daUsed && _daStartDate < block.timestamp && _daEndDate > block.timestamp && _daAmount > _discountAmount && _daAmount > 0 ) { return (_daAmount, true); } } return (_discountAmount, found); } /*** * @notice get token discount amount for an attendee * This function checks token discount amount (discount based on sender token balance) * @params _stdb struct with attendee address and whether it has a token discount * @params _discountAmount Amount of the discount in percentage (eg. 5 for a 5% discount) * @params _tokenDiscountTicketAttendee checks if a ticket has a token discount associated * @params _ts token discount struct * @params _tokenDiscountAttendee address of the token used for discount **/ function getTokenDiscountAmount( SenderAndTokenDiscountBuyer memory _stdb, uint256 _discountAmount, bool _tokenDiscountTicketAttendee, TokenDiscount memory _ts, address _tokenDiscountAttendee ) public view returns (uint256, bool found) { if ( _tokenDiscountAttendee != address(0) && _tokenDiscountTicketAttendee ) { //check sender balance IERC20 tokenDiscount = IERC20(_tokenDiscountAttendee); uint256 balance = tokenDiscount.balanceOf(_stdb.sender); if ( (balance > _ts.minAmount && _ts.used._value < _ts.qty && _ts.startDate < block.timestamp && _ts.endDate > block.timestamp && _ts.amount > _discountAmount && !_stdb.tokenDiscountBuyer) ) { return (_ts.amount, true); } } return (_discountAmount, found); } /*** * @notice get discount amount for an attendee * This function checks each kind of discount and returns total discount amount * @params _stdb struct with attendee address and whether it has a token discount * @params _discountCodeTicketAttendee true if a discount code applies to a given ticket * @params _dc discount code * @params _discountAddressTicketAttendee true if attendee has a discount based on address * @params _da discount address * @params _tokenDiscountTicketAttendee address of the token used for discount * @params _ts token discount struct * @params _tokenDiscountAttendee address of the token used for discount **/ function getDiscountView( SenderAndTokenDiscountBuyer memory _stdb, bool _discountCodeTicketAttendee, DiscountCode memory _dc, bool _discountAddressTicketAttendee, DiscountAddress memory _da, bool _tokenDiscountTicketAttendee, TokenDiscount memory _ts, address _tokenDiscountAttendee ) public view returns (DiscountResponse memory) { //check sender Discount code uint256 discountAmount = 0; DiscountResponse memory dr; (discountAmount, dr.hasDiscountCode) = getDiscountCodeAmount( _discountCodeTicketAttendee, _dc.qty, _dc.startDate, _dc.endDate, _dc.used._value, _dc.amount ); (discountAmount, dr.hasDiscountAddress) = getDiscountAddressAmount( _discountAddressTicketAttendee, _da.qty, _da.startDate, _da.endDate, _da.used._value, _da.amount, discountAmount ); if (dr.hasDiscountAddress) { dr.hasDiscountCode = false; } (discountAmount, dr.hasTokenDiscount) = getTokenDiscountAmount( _stdb, discountAmount, _tokenDiscountTicketAttendee, _ts, _tokenDiscountAttendee ); if (dr.hasTokenDiscount) { dr.hasDiscountAddress = false; dr.hasDiscountCode = false; } dr.discountAmount = discountAmount; return dr; } /*** * @notice retrieve attendee details * This function gets Attendee details by address and index * @param _sender Address of attendee * @param _index Attendee ticket index (each attendee can have more than one ticket) **/ function getAttendee( address sender, uint256 index ) public view returns (Attendee memory) { //SRTicketsRemote str = SRTicketsRemote(sender); //Attendee memory x = str.attendees(sender, index); return attendees[sender][index]; } /*** * @notice retrieve attendee's total spent * This function gets Attendee total spent on tickets * @param _sender Address of attendee **/ function getAttendeeSpent(address sender) public view returns (uint256) { ISRTickets sr = ISRTickets(SRTicketsAddress); uint256 count = sr.attendeesCount(sender); uint256 totalPaidInToken = 0; for (uint256 i = 0; i < count; i++) { totalPaidInToken += attendees[sender][i].pricePaidInToken; } return totalPaidInToken; } } function stringsEquals(string memory s1, string memory s2) pure returns (bool) { bytes memory b1 = bytes(s1); bytes memory b2 = bytes(s2); uint256 l1 = b1.length; if (l1 != b2.length) return false; for (uint256 i = 0; i < l1; i++) { if (b1[i] != b2[i]) return false; } return true; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface AggregatorV3Interface { function decimals() external view returns (uint8); function description() external view returns (string memory); function version() external view returns (uint256); // getRoundData and latestRoundData should both raise "No data present" // if they do not have data to report, instead of returning unset values // which could be misinterpreted as actual reported values. function getRoundData(uint80 _roundId) external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); function latestRoundData() external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); }
// 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 (last updated v4.5.0) (token/ERC721/ERC721.sol) pragma solidity ^0.8.0; import "./IERC721.sol"; import "./IERC721Receiver.sol"; import "./extensions/IERC721Metadata.sol"; import "../../utils/Address.sol"; import "../../utils/Context.sol"; import "../../utils/Strings.sol"; import "../../utils/introspection/ERC165.sol"; /** * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including * the Metadata extension, but not including the Enumerable extension, which is available separately as * {ERC721Enumerable}. */ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata { using Address for address; using Strings for uint256; // Token name string private _name; // Token symbol string private _symbol; // Mapping from token ID to owner address mapping(uint256 => address) private _owners; // Mapping owner address to token count mapping(address => uint256) private _balances; // Mapping from token ID to approved address mapping(uint256 => address) private _tokenApprovals; // Mapping from owner to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; /** * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC721).interfaceId || interfaceId == type(IERC721Metadata).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721-balanceOf}. */ function balanceOf(address owner) public view virtual override returns (uint256) { require(owner != address(0), "ERC721: balance query for the zero address"); return _balances[owner]; } /** * @dev See {IERC721-ownerOf}. */ function ownerOf(uint256 tokenId) public view virtual override returns (address) { address owner = _owners[tokenId]; require(owner != address(0), "ERC721: owner query for nonexistent token"); return owner; } /** * @dev See {IERC721Metadata-name}. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev See {IERC721Metadata-symbol}. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev See {IERC721Metadata-tokenURI}. */ function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token"); string memory baseURI = _baseURI(); return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : ""; } /** * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each * token will be the concatenation of the `baseURI` and the `tokenId`. Empty * by default, can be overriden in child contracts. */ function _baseURI() internal view virtual returns (string memory) { return ""; } /** * @dev See {IERC721-approve}. */ function approve(address to, uint256 tokenId) public virtual override { address owner = ERC721.ownerOf(tokenId); require(to != owner, "ERC721: approval to current owner"); require( _msgSender() == owner || isApprovedForAll(owner, _msgSender()), "ERC721: approve caller is not owner nor approved for all" ); _approve(to, tokenId); } /** * @dev See {IERC721-getApproved}. */ function getApproved(uint256 tokenId) public view virtual override returns (address) { require(_exists(tokenId), "ERC721: approved query for nonexistent token"); return _tokenApprovals[tokenId]; } /** * @dev See {IERC721-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual override { _setApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC721-isApprovedForAll}. */ function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev See {IERC721-transferFrom}. */ function transferFrom( address from, address to, uint256 tokenId ) public virtual override { //solhint-disable-next-line max-line-length require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved"); _transfer(from, to, tokenId); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 tokenId ) public virtual override { safeTransferFrom(from, to, tokenId, ""); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes memory _data ) public virtual override { require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved"); _safeTransfer(from, to, tokenId, _data); } /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * `_data` is additional data, it has no specified format and it is sent in call to `to`. * * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g. * implement alternative mechanisms to perform token transfer, such as signature-based. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeTransfer( address from, address to, uint256 tokenId, bytes memory _data ) internal virtual { _transfer(from, to, tokenId); require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer"); } /** * @dev Returns whether `tokenId` exists. * * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}. * * Tokens start existing when they are minted (`_mint`), * and stop existing when they are burned (`_burn`). */ function _exists(uint256 tokenId) internal view virtual returns (bool) { return _owners[tokenId] != address(0); } /** * @dev Returns whether `spender` is allowed to manage `tokenId`. * * Requirements: * * - `tokenId` must exist. */ function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) { require(_exists(tokenId), "ERC721: operator query for nonexistent token"); address owner = ERC721.ownerOf(tokenId); return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender)); } /** * @dev Safely mints `tokenId` and transfers it to `to`. * * Requirements: * * - `tokenId` must not exist. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeMint(address to, uint256 tokenId) internal virtual { _safeMint(to, tokenId, ""); } /** * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is * forwarded in {IERC721Receiver-onERC721Received} to contract recipients. */ function _safeMint( address to, uint256 tokenId, bytes memory _data ) internal virtual { _mint(to, tokenId); require( _checkOnERC721Received(address(0), to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer" ); } /** * @dev Mints `tokenId` and transfers it to `to`. * * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible * * Requirements: * * - `tokenId` must not exist. * - `to` cannot be the zero address. * * Emits a {Transfer} event. */ function _mint(address to, uint256 tokenId) internal virtual { require(to != address(0), "ERC721: mint to the zero address"); require(!_exists(tokenId), "ERC721: token already minted"); _beforeTokenTransfer(address(0), to, tokenId); _balances[to] += 1; _owners[tokenId] = to; emit Transfer(address(0), to, tokenId); _afterTokenTransfer(address(0), to, tokenId); } /** * @dev Destroys `tokenId`. * The approval is cleared when the token is burned. * * Requirements: * * - `tokenId` must exist. * * Emits a {Transfer} event. */ function _burn(uint256 tokenId) internal virtual { address owner = ERC721.ownerOf(tokenId); _beforeTokenTransfer(owner, address(0), tokenId); // Clear approvals _approve(address(0), tokenId); _balances[owner] -= 1; delete _owners[tokenId]; emit Transfer(owner, address(0), tokenId); _afterTokenTransfer(owner, address(0), tokenId); } /** * @dev Transfers `tokenId` from `from` to `to`. * As opposed to {transferFrom}, this imposes no restrictions on msg.sender. * * Requirements: * * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * * Emits a {Transfer} event. */ function _transfer( address from, address to, uint256 tokenId ) internal virtual { require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner"); require(to != address(0), "ERC721: transfer to the zero address"); _beforeTokenTransfer(from, to, tokenId); // Clear approvals from the previous owner _approve(address(0), tokenId); _balances[from] -= 1; _balances[to] += 1; _owners[tokenId] = to; emit Transfer(from, to, tokenId); _afterTokenTransfer(from, to, tokenId); } /** * @dev Approve `to` to operate on `tokenId` * * Emits a {Approval} event. */ function _approve(address to, uint256 tokenId) internal virtual { _tokenApprovals[tokenId] = to; emit Approval(ERC721.ownerOf(tokenId), to, tokenId); } /** * @dev Approve `operator` to operate on all of `owner` tokens * * Emits a {ApprovalForAll} event. */ function _setApprovalForAll( address owner, address operator, bool approved ) internal virtual { require(owner != operator, "ERC721: approve to caller"); _operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } /** * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address. * The call is not executed if the target address is not a contract. * * @param from address representing the previous owner of the given token ID * @param to target address that will receive the tokens * @param tokenId uint256 ID of the token to be transferred * @param _data bytes optional data to send along with the call * @return bool whether the call correctly returned the expected magic value */ function _checkOnERC721Received( address from, address to, uint256 tokenId, bytes memory _data ) private returns (bool) { if (to.isContract()) { try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) { return retval == IERC721Receiver.onERC721Received.selector; } catch (bytes memory reason) { if (reason.length == 0) { revert("ERC721: transfer to non ERC721Receiver implementer"); } else { assembly { revert(add(32, reason), mload(reason)) } } } } else { return true; } } /** * @dev Hook that is called before any token transfer. This includes minting * and burning. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be * transferred to `to`. * - When `from` is zero, `tokenId` will be minted for `to`. * - When `to` is zero, ``from``'s `tokenId` will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 tokenId ) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 tokenId ) internal virtual {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.0; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol) pragma solidity ^0.8.0; import "../IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Metadata is IERC721 { /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); }
// 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 // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/ERC721Enumerable.sol) pragma solidity ^0.8.0; import "../ERC721.sol"; import "./IERC721Enumerable.sol"; /** * @dev This implements an optional extension of {ERC721} defined in the EIP that adds * enumerability of all the token ids in the contract as well as all token ids owned by each * account. */ abstract contract ERC721Enumerable is ERC721, IERC721Enumerable { // Mapping from owner to list of owned token IDs mapping(address => mapping(uint256 => uint256)) private _ownedTokens; // Mapping from token ID to index of the owner tokens list mapping(uint256 => uint256) private _ownedTokensIndex; // Array with all token ids, used for enumeration uint256[] private _allTokens; // Mapping from token id to position in the allTokens array mapping(uint256 => uint256) private _allTokensIndex; /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) { return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}. */ function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) { require(index < ERC721.balanceOf(owner), "ERC721Enumerable: owner index out of bounds"); return _ownedTokens[owner][index]; } /** * @dev See {IERC721Enumerable-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _allTokens.length; } /** * @dev See {IERC721Enumerable-tokenByIndex}. */ function tokenByIndex(uint256 index) public view virtual override returns (uint256) { require(index < ERC721Enumerable.totalSupply(), "ERC721Enumerable: global index out of bounds"); return _allTokens[index]; } /** * @dev Hook that is called before any token transfer. This includes minting * and burning. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be * transferred to `to`. * - When `from` is zero, `tokenId` will be minted for `to`. * - When `to` is zero, ``from``'s `tokenId` will be burned. * - `from` cannot be the zero address. * - `to` cannot be the zero address. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 tokenId ) internal virtual override { super._beforeTokenTransfer(from, to, tokenId); if (from == address(0)) { _addTokenToAllTokensEnumeration(tokenId); } else if (from != to) { _removeTokenFromOwnerEnumeration(from, tokenId); } if (to == address(0)) { _removeTokenFromAllTokensEnumeration(tokenId); } else if (to != from) { _addTokenToOwnerEnumeration(to, tokenId); } } /** * @dev Private function to add a token to this extension's ownership-tracking data structures. * @param to address representing the new owner of the given token ID * @param tokenId uint256 ID of the token to be added to the tokens list of the given address */ function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private { uint256 length = ERC721.balanceOf(to); _ownedTokens[to][length] = tokenId; _ownedTokensIndex[tokenId] = length; } /** * @dev Private function to add a token to this extension's token tracking data structures. * @param tokenId uint256 ID of the token to be added to the tokens list */ function _addTokenToAllTokensEnumeration(uint256 tokenId) private { _allTokensIndex[tokenId] = _allTokens.length; _allTokens.push(tokenId); } /** * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for * gas optimizations e.g. when performing a transfer operation (avoiding double writes). * This has O(1) time complexity, but alters the order of the _ownedTokens array. * @param from address representing the previous owner of the given token ID * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address */ function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private { // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and // then delete the last slot (swap and pop). uint256 lastTokenIndex = ERC721.balanceOf(from) - 1; uint256 tokenIndex = _ownedTokensIndex[tokenId]; // When the token to delete is the last token, the swap operation is unnecessary if (tokenIndex != lastTokenIndex) { uint256 lastTokenId = _ownedTokens[from][lastTokenIndex]; _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index } // This also deletes the contents at the last position of the array delete _ownedTokensIndex[tokenId]; delete _ownedTokens[from][lastTokenIndex]; } /** * @dev Private function to remove a token from this extension's token tracking data structures. * This has O(1) time complexity, but alters the order of the _allTokens array. * @param tokenId uint256 ID of the token to be removed from the tokens list */ function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private { // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and // then delete the last slot (swap and pop). uint256 lastTokenIndex = _allTokens.length - 1; uint256 tokenIndex = _allTokensIndex[tokenId]; // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding // an 'if' statement (like in _removeTokenFromOwnerEnumeration) uint256 lastTokenId = _allTokens[lastTokenIndex]; _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index // This also deletes the contents at the last position of the array delete _allTokensIndex[tokenId]; _allTokens.pop(); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol) pragma solidity ^0.8.0; import "../IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Enumerable is IERC721 { /** * @dev Returns the total amount of tokens stored by the contract. */ function totalSupply() external view returns (uint256); /** * @dev Returns a token ID owned by `owner` at a given `index` of its token list. * Use along with {balanceOf} to enumerate all of ``owner``'s tokens. */ function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256); /** * @dev Returns a token ID at a given `index` of all the tokens stored by the contract. * Use along with {totalSupply} to enumerate all tokens. */ function tokenByIndex(uint256 index) external view returns (uint256); }
// SPDX-License-Identifier: MIT //vedb52 pragma solidity 0.8.15; import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol"; import "@openzeppelin/contracts/utils/Counters.sol"; import "@openzeppelin/contracts/utils/Strings.sol"; contract SRTicketsNFT is ERC721Enumerable { using Counters for Counters.Counter; Counters.Counter private _tokenIds; mapping(uint256 => string) public socials; mapping(uint256 => string) public cancelled; mapping(uint256 => string) public ticketNames; mapping(uint256 => address) public owners; string public baseURI; string public chainName; address public coowner; address public owner; // @notice store address of ticket contract address public SRTicketsDiscountsAddress; constructor(string memory _chainName) ERC721("ETHDubai 2025", "EDB25") { baseURI = "https://ed2025.vercel.app/nftimage.svg"; chainName = _chainName; owner = msg.sender; } function addressToString( address _addr ) public pure returns (string memory) { bytes memory buffer = new bytes(40); for (uint256 i = 0; i < 20; i++) { bytes1 b = bytes1(uint8(uint160(_addr) / (2 ** (8 * (19 - i))))); bytes1 hi = bytes1(uint8(b) / 16); bytes1 lo = bytes1(uint8(b) - 16 * uint8(hi)); buffer[2 * i] = char(hi); buffer[2 * i + 1] = char(lo); } return string(abi.encodePacked("0x", buffer)); } function char(bytes1 b) internal pure returns (bytes1) { if (uint8(b) < 10) return bytes1(uint8(b) + 0x30); else return bytes1(uint8(b) + 0x57); } function setOwner(address _owner) public { require(msg.sender == coowner || msg.sender == owner, "not allowed1"); owner = _owner; } function setCoOwner(address _coowner) public { require(msg.sender == coowner || msg.sender == owner, "not allowed2"); coowner = _coowner; } function setSRTicketsDiscountsAddress(address _srtdiscount) public { require(msg.sender == coowner || msg.sender == owner, "not allowed3"); SRTicketsDiscountsAddress = _srtdiscount; } function setChain(string memory _chainName) public { require(msg.sender == coowner || msg.sender == owner, "not allowed4"); chainName = _chainName; } function setBaseURI(string memory _baseURI) public { require(msg.sender == coowner || msg.sender == owner, "not allowed5"); baseURI = _baseURI; } function setCancelled(uint256 itemId) public { require( msg.sender == coowner || msg.sender == owner || msg.sender == SRTicketsDiscountsAddress, "not allowed6" ); cancelled[itemId] = "true"; } function setSocialTicket( string memory ticketName, string memory social, uint256 itemId ) public { require( msg.sender == coowner || msg.sender == owner || msg.sender == SRTicketsDiscountsAddress, "not allowed7" ); ticketNames[itemId] = ticketName; socials[itemId] = social; } function mintItem( address _attendee, string memory _ticketName, string memory _social ) public returns (uint256) { require( msg.sender == coowner || msg.sender == owner || msg.sender == SRTicketsDiscountsAddress, addressToString(msg.sender) ); _tokenIds.increment(); uint256 newItemId = _tokenIds.current(); _mint(_attendee, newItemId); socials[newItemId] = _social; owners[newItemId] = _attendee; ticketNames[newItemId] = _ticketName; cancelled[newItemId] = "false"; return newItemId; } function tokenURI( uint256 tokenId ) public view virtual override returns (string memory) { require( tokenId <= _tokenIds.current(), "ERC721Metadata: URI query for nonexistent token" ); string memory uri = string.concat( baseURI, "?c=", chainName, "&id=", Strings.toString(tokenId), "&s=", socials[tokenId], "&t=", ticketNames[tokenId], "&cl=", cancelled[tokenId] ); return uri; } }
// 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 (last updated v4.5.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.0; import "./IERC20.sol"; import "./extensions/IERC20Metadata.sol"; import "../../utils/Context.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20, IERC20Metadata { mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * The default value of {decimals} is 18. To select a different value for * {decimals} you should overload it. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the value {ERC20} uses, unless this function is * overridden; * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual override returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address to, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _transfer(owner, to, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _approve(owner, spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. * - the caller must have allowance for ``from``'s tokens of at least * `amount`. */ function transferFrom( address from, address to, uint256 amount ) public virtual override returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, amount); _transfer(from, to, amount); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, _allowances[owner][spender] + addedValue); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { address owner = _msgSender(); uint256 currentAllowance = _allowances[owner][spender]; require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); unchecked { _approve(owner, spender, currentAllowance - subtractedValue); } return true; } /** * @dev Moves `amount` of tokens from `sender` to `recipient`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. */ function _transfer( address from, address to, uint256 amount ) internal virtual { require(from != address(0), "ERC20: transfer from the zero address"); require(to != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(from, to, amount); uint256 fromBalance = _balances[from]; require(fromBalance >= amount, "ERC20: transfer amount exceeds balance"); unchecked { _balances[from] = fromBalance - amount; } _balances[to] += amount; emit Transfer(from, to, amount); _afterTokenTransfer(from, to, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply += amount; _balances[account] += amount; emit Transfer(address(0), account, amount); _afterTokenTransfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); unchecked { _balances[account] = accountBalance - amount; } _totalSupply -= amount; emit Transfer(account, address(0), amount); _afterTokenTransfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve( address owner, address spender, uint256 amount ) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Spend `amount` form the allowance of `owner` toward `spender`. * * Does not update the allowance amount in case of infinite allowance. * Revert if not enough allowance is available. * * Might emit an {Approval} event. */ function _spendAllowance( address owner, address spender, uint256 amount ) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { require(currentAllowance >= amount, "ERC20: insufficient allowance"); unchecked { _approve(owner, spender, currentAllowance - amount); } } } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 amount ) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * has been transferred to `to`. * - when `from` is zero, `amount` tokens have been minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens have been burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 amount ) internal virtual {} }
pragma solidity ^0.8.15; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; contract TestToken is ERC20 { constructor() ERC20("TestToken", "TT") { mintTokens(); } function mintTokens() public { _mint(msg.sender, 100000000000000000000000); } function mintTokensTo(address beneficiary) public { _mint(beneficiary, 100000000000000000000000); } }
{ "optimizer": { "enabled": true, "runs": 2000 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "metadata": { "useLiteralContent": true } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_discountContract","type":"address"},{"internalType":"address","name":"_nftContract","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"attendeeAddress","type":"address"},{"components":[{"internalType":"string","name":"email","type":"string"},{"internalType":"string","name":"fname","type":"string"},{"internalType":"string","name":"lname","type":"string"},{"internalType":"string","name":"bio","type":"string"},{"internalType":"string","name":"job","type":"string"},{"internalType":"string","name":"company","type":"string"},{"internalType":"string","name":"social","type":"string"},{"internalType":"string","name":"ticket","type":"string"},{"internalType":"string","name":"discountCode","type":"string"},{"internalType":"address","name":"tokenDiscount","type":"address"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"buyToken","type":"address"},{"internalType":"uint256","name":"pricePaid","type":"uint256"},{"internalType":"uint256","name":"pricePaidInToken","type":"uint256"},{"internalType":"bool","name":"cancelled","type":"bool"},{"internalType":"uint256","name":"refunded","type":"uint256"},{"internalType":"bool","name":"allowResell","type":"bool"},{"internalType":"uint256","name":"resellPrice","type":"uint256"},{"internalType":"string","name":"code","type":"string"},{"internalType":"uint256","name":"boughtOn","type":"uint256"},{"internalType":"bool","name":"resold","type":"bool"},{"internalType":"uint256","name":"nftId","type":"uint256"}],"indexed":false,"internalType":"struct SRTickets.Attendee","name":"attendee","type":"tuple"},{"indexed":false,"internalType":"string","name":"message","type":"string"}],"name":"LMint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"attendee","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountUSD","type":"uint256"},{"indexed":false,"internalType":"address","name":"token","type":"address"}],"name":"LogBuy","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"attendee","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"attendeesIndex","type":"uint256"},{"indexed":false,"internalType":"address","name":"buyToken","type":"address"}],"name":"LogRefund","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"LogSetOwner","type":"event"},{"inputs":[],"name":"allowBuyResellable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"allowSelfRefund","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"attendeesCount","outputs":[{"internalType":"uint256","name":"_value","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_attendeeIndex","type":"uint256"},{"components":[{"internalType":"string","name":"email","type":"string"},{"internalType":"string","name":"fname","type":"string"},{"internalType":"string","name":"lname","type":"string"},{"internalType":"string","name":"bio","type":"string"},{"internalType":"string","name":"job","type":"string"},{"internalType":"string","name":"company","type":"string"},{"internalType":"string","name":"social","type":"string"},{"internalType":"string","name":"ticket","type":"string"},{"internalType":"string","name":"discountCode","type":"string"},{"internalType":"address","name":"tokenDiscount","type":"address"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"buyToken","type":"address"},{"internalType":"uint256","name":"pricePaid","type":"uint256"},{"internalType":"uint256","name":"pricePaidInToken","type":"uint256"},{"internalType":"bool","name":"cancelled","type":"bool"},{"internalType":"uint256","name":"refunded","type":"uint256"},{"internalType":"bool","name":"allowResell","type":"bool"},{"internalType":"uint256","name":"resellPrice","type":"uint256"},{"internalType":"string","name":"code","type":"string"},{"internalType":"uint256","name":"boughtOn","type":"uint256"},{"internalType":"bool","name":"resold","type":"bool"},{"internalType":"uint256","name":"nftId","type":"uint256"}],"internalType":"struct SRTickets.Attendee","name":"_newAttendee","type":"tuple"}],"name":"buyResellable","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"confirmOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"string","name":"","type":"string"}],"name":"discountAddressTickets","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"discountAddresses","outputs":[{"internalType":"address","name":"buyer","type":"address"},{"internalType":"uint256","name":"qty","type":"uint256"},{"components":[{"internalType":"uint256","name":"_value","type":"uint256"}],"internalType":"struct Counters.Counter","name":"used","type":"tuple"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"string","name":"code","type":"string"},{"internalType":"uint256","name":"endDate","type":"uint256"},{"internalType":"uint256","name":"startDate","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"","type":"string"},{"internalType":"string","name":"","type":"string"}],"name":"discountCodeTickets","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"","type":"string"}],"name":"discountCodes","outputs":[{"internalType":"uint256","name":"qty","type":"uint256"},{"components":[{"internalType":"uint256","name":"_value","type":"uint256"}],"internalType":"struct Counters.Counter","name":"used","type":"tuple"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"string","name":"code","type":"string"},{"internalType":"uint256","name":"endDate","type":"uint256"},{"internalType":"uint256","name":"startDate","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_sender","type":"address"},{"components":[{"internalType":"string","name":"email","type":"string"},{"internalType":"string","name":"fname","type":"string"},{"internalType":"string","name":"lname","type":"string"},{"internalType":"string","name":"bio","type":"string"},{"internalType":"string","name":"job","type":"string"},{"internalType":"string","name":"company","type":"string"},{"internalType":"string","name":"social","type":"string"},{"internalType":"string","name":"ticket","type":"string"},{"internalType":"string","name":"discountCode","type":"string"},{"internalType":"address","name":"tokenDiscount","type":"address"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"buyToken","type":"address"},{"internalType":"uint256","name":"pricePaid","type":"uint256"},{"internalType":"uint256","name":"pricePaidInToken","type":"uint256"},{"internalType":"bool","name":"cancelled","type":"bool"},{"internalType":"uint256","name":"refunded","type":"uint256"},{"internalType":"bool","name":"allowResell","type":"bool"},{"internalType":"uint256","name":"resellPrice","type":"uint256"},{"internalType":"string","name":"code","type":"string"},{"internalType":"uint256","name":"boughtOn","type":"uint256"},{"internalType":"bool","name":"resold","type":"bool"},{"internalType":"uint256","name":"nftId","type":"uint256"}],"internalType":"struct SRTickets.Attendee","name":"_attendee","type":"tuple"}],"name":"getDiscountView","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_sender","type":"address"},{"components":[{"internalType":"string","name":"email","type":"string"},{"internalType":"string","name":"fname","type":"string"},{"internalType":"string","name":"lname","type":"string"},{"internalType":"string","name":"bio","type":"string"},{"internalType":"string","name":"job","type":"string"},{"internalType":"string","name":"company","type":"string"},{"internalType":"string","name":"social","type":"string"},{"internalType":"string","name":"ticket","type":"string"},{"internalType":"string","name":"discountCode","type":"string"},{"internalType":"address","name":"tokenDiscount","type":"address"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"buyToken","type":"address"},{"internalType":"uint256","name":"pricePaid","type":"uint256"},{"internalType":"uint256","name":"pricePaidInToken","type":"uint256"},{"internalType":"bool","name":"cancelled","type":"bool"},{"internalType":"uint256","name":"refunded","type":"uint256"},{"internalType":"bool","name":"allowResell","type":"bool"},{"internalType":"uint256","name":"resellPrice","type":"uint256"},{"internalType":"string","name":"code","type":"string"},{"internalType":"uint256","name":"boughtOn","type":"uint256"},{"internalType":"bool","name":"resold","type":"bool"},{"internalType":"uint256","name":"nftId","type":"uint256"}],"internalType":"struct SRTickets.Attendee[]","name":"_attendees","type":"tuple[]"}],"name":"getDiscountsView","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_discount","type":"uint256"},{"internalType":"string","name":"_ticket","type":"string"}],"name":"getPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"email","type":"string"},{"internalType":"string","name":"fname","type":"string"},{"internalType":"string","name":"lname","type":"string"},{"internalType":"string","name":"bio","type":"string"},{"internalType":"string","name":"job","type":"string"},{"internalType":"string","name":"company","type":"string"},{"internalType":"string","name":"social","type":"string"},{"internalType":"string","name":"ticket","type":"string"},{"internalType":"string","name":"discountCode","type":"string"},{"internalType":"address","name":"tokenDiscount","type":"address"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"buyToken","type":"address"},{"internalType":"uint256","name":"pricePaid","type":"uint256"},{"internalType":"uint256","name":"pricePaidInToken","type":"uint256"},{"internalType":"bool","name":"cancelled","type":"bool"},{"internalType":"uint256","name":"refunded","type":"uint256"},{"internalType":"bool","name":"allowResell","type":"bool"},{"internalType":"uint256","name":"resellPrice","type":"uint256"},{"internalType":"string","name":"code","type":"string"},{"internalType":"uint256","name":"boughtOn","type":"uint256"},{"internalType":"bool","name":"resold","type":"bool"},{"internalType":"uint256","name":"nftId","type":"uint256"}],"internalType":"struct SRTickets.Attendee[]","name":"_buyAttendees","type":"tuple[]"},{"internalType":"address","name":"_buyToken","type":"address"}],"name":"mintTicket","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"priceFeeds","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_buyer","type":"address"},{"internalType":"uint256","name":"_attendeeIndex","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"refund","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"refundFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"refundIncFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"refundIncLapse","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"resellFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_attendeeIndex","type":"uint256"}],"name":"selfRefund","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"buyer","type":"address"},{"internalType":"uint256","name":"qty","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"endDate","type":"uint256"},{"internalType":"uint256","name":"startDate","type":"uint256"},{"internalType":"string[]","name":"ticketsToAdd","type":"string[]"},{"internalType":"string[]","name":"ticketsToRemove","type":"string[]"}],"name":"setDiscountAddresses","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_code","type":"string"},{"internalType":"uint256","name":"_qty","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_endDate","type":"uint256"},{"internalType":"uint256","name":"_startDate","type":"uint256"},{"internalType":"string[]","name":"_ticketsToAdd","type":"string[]"},{"internalType":"string[]","name":"_ticketsToRemove","type":"string[]"}],"name":"setDiscountCodes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_feed","type":"address"}],"name":"setPriceFeed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_allow","type":"bool"},{"internalType":"uint256","name":"_refundFee","type":"uint256"},{"internalType":"uint256","name":"_resellFee","type":"uint256"},{"internalType":"uint256","name":"_refundIncFee","type":"uint256"},{"internalType":"uint256","name":"_refundIncLapse","type":"uint256"}],"name":"setRefund","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_allow","type":"bool"}],"name":"setResellable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_qty","type":"uint256"},{"internalType":"uint256","name":"_price","type":"uint256"},{"internalType":"uint256","name":"_endDate","type":"uint256"},{"internalType":"uint256","name":"_startDate","type":"uint256"},{"internalType":"string","name":"slug","type":"string"}],"name":"setTicket","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_discountToken","type":"address"},{"internalType":"uint256","name":"_minAmount","type":"uint256"},{"internalType":"uint256","name":"_qty","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_endDate","type":"uint256"},{"internalType":"uint256","name":"_startDate","type":"uint256"},{"internalType":"string[]","name":"ticketsToAdd","type":"string[]"},{"internalType":"string[]","name":"ticketsToRemove","type":"string[]"}],"name":"setTokenDiscount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"tbcOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"","type":"string"}],"name":"tickets","outputs":[{"internalType":"uint256","name":"qty","type":"uint256"},{"components":[{"internalType":"uint256","name":"_value","type":"uint256"}],"internalType":"struct Counters.Counter","name":"used","type":"tuple"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"endDate","type":"uint256"},{"internalType":"uint256","name":"startDate","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"tokenDiscountBuyer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"string","name":"","type":"string"}],"name":"tokenDiscountTickets","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tokenDiscounts","outputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"minAmount","type":"uint256"},{"internalType":"uint256","name":"qty","type":"uint256"},{"components":[{"internalType":"uint256","name":"_value","type":"uint256"}],"internalType":"struct Counters.Counter","name":"used","type":"tuple"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"endDate","type":"uint256"},{"internalType":"uint256","name":"startDate","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_attendeeIndex","type":"uint256"},{"internalType":"address","name":"_attendeeAddress","type":"address"},{"components":[{"internalType":"string","name":"email","type":"string"},{"internalType":"string","name":"fname","type":"string"},{"internalType":"string","name":"lname","type":"string"},{"internalType":"string","name":"bio","type":"string"},{"internalType":"string","name":"job","type":"string"},{"internalType":"string","name":"company","type":"string"},{"internalType":"string","name":"social","type":"string"},{"internalType":"string","name":"ticket","type":"string"},{"internalType":"string","name":"discountCode","type":"string"},{"internalType":"address","name":"tokenDiscount","type":"address"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"buyToken","type":"address"},{"internalType":"uint256","name":"pricePaid","type":"uint256"},{"internalType":"uint256","name":"pricePaidInToken","type":"uint256"},{"internalType":"bool","name":"cancelled","type":"bool"},{"internalType":"uint256","name":"refunded","type":"uint256"},{"internalType":"bool","name":"allowResell","type":"bool"},{"internalType":"uint256","name":"resellPrice","type":"uint256"},{"internalType":"string","name":"code","type":"string"},{"internalType":"uint256","name":"boughtOn","type":"uint256"},{"internalType":"bool","name":"resold","type":"bool"},{"internalType":"uint256","name":"nftId","type":"uint256"}],"internalType":"struct SRTickets.Attendee","name":"_newAttendee","type":"tuple"}],"name":"updateAttendee","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b50604051620056f1380380620056f18339810160408190526200003491620000be565b60016000819055601080546001600160a01b039485166001600160a01b031991821617909155601180549390941692811692909217909255815416331790556002805460ff60a01b1916600160a01b179055600f60058190556006556003805562015180600455620000f6565b80516001600160a01b0381168114620000b957600080fd5b919050565b60008060408385031215620000d257600080fd5b620000dd83620000a1565b9150620000ed60208401620000a1565b90509250929050565b6155eb80620001066000396000f3fe60806040526004361061024f5760003560e01c80638da5cb5b11610138578063b2d4cb23116100b0578063d0223fb11161007f578063e94cefc811610064578063e94cefc814610868578063f3fef3a31461089b578063f52b832f146108bb57600080fd5b8063d0223fb114610828578063d1c9fc5f1461084857600080fd5b8063b2d4cb23146107a5578063b4b1d5d8146107c5578063c1165ded146107f2578063cad39e161461080857600080fd5b8063955f21df116101075780639a322361116100ec5780639a322361146107045780639dcb511a14610717578063a1be9cb11461074d57600080fd5b8063955f21df146106b157806396517faf146106e457600080fd5b80638da5cb5b1461064857806390cb68b31461066857806390fe6ddb1461068857806394dff5c91461069e57600080fd5b80633c542c81116101cb5780636cd5b5b91161019a5780637ac974a91161017f5780637ac974a9146105c55780637da044191461060057806383a765dd1461063257600080fd5b80636cd5b5b91461055957806376e11286146105a557600080fd5b80633c542c811461044a5780634da98607146104f8578063549859c51461050b578063698d2d761461052b57600080fd5b806318fd890311610222578063290e351511610207578063290e35151461036957806329ae0b7f146103895780633bd3dad81461041257600080fd5b806318fd8903146103175780631a3764d21461033757600080fd5b8063076beddd146102545780630b7f8118146102b55780631058471b146102d757806313af4035146102f7575b600080fd5b34801561026057600080fd5b506102a061026f366004613ea9565b600e602090815260009283526040909220815180830184018051928152908401929093019190912091525460ff1681565b60405190151581526020015b60405180910390f35b3480156102c157600080fd5b506102d56102d0366004613fa8565b6108d1565b005b3480156102e357600080fd5b506102d56102f2366004614045565b610ad0565b34801561030357600080fd5b506102d56103123660046140b6565b610ca2565b34801561032357600080fd5b506102d56103323660046140d3565b610d48565b34801561034357600080fd5b50610357610352366004614108565b6110da565b6040516102ac96959493929190614199565b34801561037557600080fd5b506102d56103843660046141d4565b6111b1565b34801561039557600080fd5b506103eb6103a4366004614108565b805160208183018101805160078252928201938201939093209190925280546040805193840190526001820154835260028201546003830154600490930154919392909185565b6040805195865293516020860152928401919091526060830152608082015260a0016102ac565b34801561041e57600080fd5b50600254610432906001600160a01b031681565b6040516001600160a01b0390911681526020016102ac565b34801561045657600080fd5b506104ba6104653660046140b6565b600a60209081526000918252604091829020805460018201546002830154855194850190955260038301548452600483015460058401546006909401546001600160a01b039093169591949193919290919087565b604080516001600160a01b03909816885260208801969096529486019390935290516060850152608084015260a083015260c082015260e0016102ac565b6102d56105063660046144f1565b61139b565b34801561051757600080fd5b506102d56105263660046140b6565b611901565b34801561053757600080fd5b5061054b61054636600461454a565b611a29565b6040519081526020016102ac565b34801561056557600080fd5b506102a0610574366004613ea9565b600b602090815260009283526040909220815180830184018051928152908401929093019190912091525460ff1681565b3480156105b157600080fd5b506102d56105c036600461457b565b611a7b565b3480156105d157600080fd5b506102a06105e036600461457b565b600c60209081526000928352604080842090915290825290205460ff1681565b34801561060c57600080fd5b506002546102a09074010000000000000000000000000000000000000000900460ff1681565b34801561063e57600080fd5b5061054b60035481565b34801561065457600080fd5b50600154610432906001600160a01b031681565b34801561067457600080fd5b506102d56106833660046145b4565b611af9565b34801561069457600080fd5b5061054b60055481565b6102d56106ac3660046145cd565b611fbc565b3480156106bd57600080fd5b506002546102a0907501000000000000000000000000000000000000000000900460ff1681565b3480156106f057600080fd5b506102d56106ff36600461460a565b612540565b6102d56107123660046146ee565b61264e565b34801561072357600080fd5b506104326107323660046140b6565b600f602052600090815260409020546001600160a01b031681565b34801561075957600080fd5b506102a0610768366004614735565b8151602081840181018051600d82529282019482019490942091909352815180830184018051928152908401929093019190912091525460ff1681565b3480156107b157600080fd5b506102d56107c036600461478f565b612e8e565b3480156107d157600080fd5b5061054b6107e03660046140b6565b60126020526000908152604090205481565b3480156107fe57600080fd5b5061054b60065481565b34801561081457600080fd5b5061054b6108233660046147ac565b612f1c565b34801561083457600080fd5b506102d56108433660046147e6565b612f35565b34801561085457600080fd5b5061054b61086336600461482a565b612fd2565b34801561087457600080fd5b506108886108833660046140b6565b613035565b6040516102ac9796959493929190614870565b3480156108a757600080fd5b506102d56108b63660046148bb565b613110565b3480156108c757600080fd5b5061054b60045481565b6001546001600160a01b031633146109195760405162461bcd60e51b815260206004820152600660248201526510b7bbb732b960d11b60448201526064015b60405180910390fd5b610921613c8e565b60208181018881526060830188815260a0840188905260c084018790526001600160a01b038b8116600090815260099094526040938490208551815473ffffffffffffffffffffffffffffffffffffffff19169216919091178155915160018301559183015151600282015590516003820155608082015182919060048201906109ab908261496f565b5060a0820151600582015560c09091015160069091015560005b8351811015610a45576001600160a01b0389166000908152600e602052604090208451600191908690849081106109fe576109fe614a2f565b6020026020010151604051610a139190614a45565b908152604051908190036020019020805491151560ff1990921691909117905580610a3d81614a77565b9150506109c5565b5060005b8251811015610ac5576001600160a01b0389166000908152600e602052604081208451859084908110610a7e57610a7e614a2f565b6020026020010151604051610a939190614a45565b908152604051908190036020019020805491151560ff1990921691909117905580610abd81614a77565b915050610a49565b505050505050505050565b6001546001600160a01b03163314610b135760405162461bcd60e51b815260206004820152600660248201526510b7bbb732b960d11b6044820152606401610910565b610b1b613ce8565b86815260408082018790526080820186905260a08201859052518190600890610b45908b90614a45565b90815260408051602092819003830190208351815591830151516001830155820151600282015560608201516003820190610b80908261496f565b506080820151600482015560a09091015160059091015560005b8351811015610c1c576001600d8a604051610bb59190614a45565b9081526020016040518091039020858381518110610bd557610bd5614a2f565b6020026020010151604051610bea9190614a45565b908152604051908190036020019020805491151560ff1990921691909117905580610c1481614a77565b915050610b9a565b5060005b8251811015610ac5576000600d8a604051610c3b9190614a45565b9081526020016040518091039020848381518110610c5b57610c5b614a2f565b6020026020010151604051610c709190614a45565b908152604051908190036020019020805491151560ff1990921691909117905580610c9a81614a77565b915050610c20565b6001546001600160a01b03163314610ce55760405162461bcd60e51b815260206004820152600660248201526510b7bbb732b960d11b6044820152606401610910565b6002805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03831690811790915560405190815233907fc66d1d23a5b7baf1f496bb19f580d7b12070ad5a08a758c990db97d961fa33a69060200160405180910390a250565b6001546001600160a01b03163314610d8b5760405162461bcd60e51b815260206004820152600660248201526510b7bbb732b960d11b6044820152606401610910565b600260005403610ddd5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610910565b60026000908155610dee8484613211565b905081816101a001511015610e455760405162461bcd60e51b815260206004820152601d60248201527f726566756e6420686967686572207468616e20706169642070726963650000006044820152606401610910565b806101c0015115610e985760405162461bcd60e51b815260206004820152601160248201527f616c72656164792063616e63656c6c65640000000000000000000000000000006044820152606401610910565b6011546102a08201516040517fe452351b00000000000000000000000000000000000000000000000000000000815260048101919091526001600160a01b0390911690819063e452351b90602401600060405180830381600087803b158015610f0057600080fd5b505af1158015610f14573d6000803e3d6000fd5b50505050610f4560078360e00151604051610f2f9190614a45565b9081526020016040518091039020600101613370565b6101608201516001600160a01b031615610fb157610f81826101400151848461016001516001600160a01b03166133c79092919063ffffffff16565b6101e0820183905260016101c08301819052610140830151610fac9186918591829190600090613447565b61106a565b6000856001600160a01b03168460405160006040518083038185875af1925050503d8060008114610ffe576040519150601f19603f3d011682016040523d82523d6000602084013e611003565b606091505b505090508061103d5760405162461bcd60e51b815260206004820152600660248201526511985a5b195960d21b6044820152606401610910565b6101e0830184905260016101c084018190526101408401516110689187918691829190600090613447565b505b846001600160a01b03167f1bd82af1a69358f33a6adf465c79404ca8dd30dbf4f7049eca78b5627018fc0a84868561016001516040516110c69392919092835260208301919091526001600160a01b0316604082015260600190565b60405180910390a250506001600055505050565b805160208183018101805160088252928201938201939093209190925280546040805193840190526001820154835260028201546003830180549294939192611122906148e7565b80601f016020809104026020016040519081016040528092919081815260200182805461114e906148e7565b801561119b5780601f106111705761010080835404028352916020019161119b565b820191906000526020600020905b81548152906001019060200180831161117e57829003601f168201915b5050505050908060040154908060050154905086565b6001546001600160a01b031633146111f45760405162461bcd60e51b815260206004820152600660248201526510b7bbb732b960d11b6044820152606401610910565b6111fc613d10565b6001600160a01b0389811680835260208084018b815260408086018c8152608087018c815260a088018c815260c089018c81526000978852600a9096529286208851815473ffffffffffffffffffffffffffffffffffffffff1916981697909717875592516001870155516002860155606086015151600386015590516004850155516005840155516006909201919091555b835181101561130f576001600160a01b038a166000908152600b602052604090208451600191908690849081106112c8576112c8614a2f565b60200260200101516040516112dd9190614a45565b908152604051908190036020019020805491151560ff199092169190911790558061130781614a77565b91505061128f565b5060005b825181101561138f576001600160a01b038a166000908152600b60205260408120845185908490811061134857611348614a2f565b602002602001015160405161135d9190614a45565b908152604051908190036020019020805491151560ff199092169190911790558061138781614a77565b915050611313565b50505050505050505050565b6002600054036113ed5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610910565b600260009081556113fe8385613211565b6101408101519091506001600160a01b031633148061142757506001546001600160a01b031633145b6114735760405162461bcd60e51b815260206004820152601560248201527f6e6f7420616c6c6f77656420746f2075706461746500000000000000000000006044820152606401610910565b806101c00151156114c65760405162461bcd60e51b815260206004820152601160248201527f616c72656164792063616e63656c6c65640000000000000000000000000000006044820152606401610910565b6101408101516001600160a01b03163314806114ec57506001546001600160a01b031633145b801561150757506115058260e001518260e001516134d7565b155b156118e75760078260e001516040516115209190614a45565b90815260200160405180910390206000015461155e60078460e001516040516115499190614a45565b90815260200160405180910390206001015490565b106115ab5760405162461bcd60e51b815260206004820152600860248201527f736f6c64206f75740000000000000000000000000000000000000000000000006044820152606401610910565b4260078360e001516040516115c09190614a45565b9081526020016040518091039020600401541061161f5760405162461bcd60e51b815260206004820152601160248201527f6e6f7420617661696c61626c65207965740000000000000000000000000000006044820152606401610910565b4260078360e001516040516116349190614a45565b908152602001604051809103902060030154116116935760405162461bcd60e51b815260206004820152601560248201527f6e6f7420617661696c61626c6520616e796d6f726500000000000000000000006044820152606401610910565b80610180015160078360e001516040516116ad9190614a45565b90815260200160405180910390206002015411156118e757600061170b82610180015160078560e001516040516116e49190614a45565b9081526020016040518091039020600201546117009190614a91565b8361016001516135a9565b6101608301519091506001600160a01b031661177657803410156117715760405162461bcd60e51b815260206004820152601960248201527f6e6577207469636b6574206d6f726520657870656e73697665000000000000006044820152606401610910565b611859565b6101608201516040517f23b872dd000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018390526001600160a01b03909116906323b872dd906064016020604051808303816000875af11580156117e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061180d9190614ab3565b6118595760405162461bcd60e51b815260206004820152600f60248201527f7472616e73666572206661696c656400000000000000000000000000000000006044820152606401610910565b61188a60078460e001516040516118709190614a45565b908152602001604051809103902060010180546001019055565b6118a160078360e00151604051610f2f9190614a45565b60078360e001516040516118b59190614a45565b908152604051908190036020019020600201546101808301526101a08201516118df908290614ad0565b6101a0830152505b6118f684838386600080613447565b505060016000555050565b6001546001600160a01b031633146119445760405162461bcd60e51b815260206004820152600660248201526510b7bbb732b960d11b6044820152606401610910565b6002546001600160a01b038281169116146119a15760405162461bcd60e51b815260206004820152600d60248201527f6e6f7420636f6e6669726d6564000000000000000000000000000000000000006044820152606401610910565b6001600160a01b0381166000036119fa5760405162461bcd60e51b815260206004820152601160248201527f616464726573732063616e7420626520300000000000000000000000000000006044820152606401610910565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b600080600783604051611a3c9190614a45565b9081526040519081900360200190206002015490506064611a5d8583614ae8565b611a679190614b1d565b611a719082614a91565b9150505b92915050565b6001546001600160a01b03163314611abe5760405162461bcd60e51b815260206004820152600660248201526510b7bbb732b960d11b6044820152606401610910565b6001600160a01b039182166000908152600f60205260409020805473ffffffffffffffffffffffffffffffffffffffff191691909216179055565b600260005403611b4b5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610910565b60026000908155611b5c3383613211565b6101408101519091506001600160a01b03163314611bbc5760405162461bcd60e51b815260206004820152601360248201527f73656e646572206973206e6f74206275796572000000000000000000000000006044820152606401610910565b60025474010000000000000000000000000000000000000000900460ff16611c265760405162461bcd60e51b815260206004820152601360248201527f726566756e64206e6f7420706f737369626c65000000000000000000000000006044820152606401610910565b806101c0015115611c795760405162461bcd60e51b815260206004820152601160248201527f616c72656164792063616e63656c6c65640000000000000000000000000000006044820152606401610910565b80610280015115611ccc5760405162461bcd60e51b815260206004820181905260248201527f7265736f6c642c2073656520726566756e64207769746820726573656c6c65726044820152606401610910565b4260078260e00151604051611ce19190614a45565b90815260200160405180910390206003015411611d405760405162461bcd60e51b815260206004820152601b60248201527f726566756e64206e6f7420706f737369626c6520616e796d6f726500000000006044820152606401610910565b600060045482610260015142611d569190614a91565b600354611d639190614ae8565b611d6d9190614b1d565b905060648110611dbf5760405162461bcd60e51b815260206004820152601360248201527f726566756e64206e6f7420706f737369626c65000000000000000000000000006044820152606401610910565b60006064836101a0015183611dd49190614ae8565b611dde9190614b1d565b836101a00151611dee9190614a91565b6011546102a08501516040517fe452351b00000000000000000000000000000000000000000000000000000000815260048101919091529192506001600160a01b031690819063e452351b90602401600060405180830381600087803b158015611e5757600080fd5b505af1158015611e6b573d6000803e3d6000fd5b50505050611e8660078560e00151604051610f2f9190614a45565b6101608401516001600160a01b031615611ef257611ec2846101400151838661016001516001600160a01b03166133c79092919063ffffffff16565b6101e0840182905260016101c08501819052610140850151611eed9187918791829190600090613447565b611fb0565b60008461014001516001600160a01b03168360405160006040518083038185875af1925050503d8060008114611f44576040519150601f19603f3d011682016040523d82523d6000602084013e611f49565b606091505b5050905080611f835760405162461bcd60e51b815260206004820152600660248201526511985a5b195960d21b6044820152606401610910565b6101e0850183905260016101c08601819052610140860151611fae9188918891829190600090613447565b505b50506001600055505050565b60026000540361200e5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610910565b600260009081556101408201516120259084613211565b9050600081610200015161207b5760405162461bcd60e51b815260206004820152600c60248201527f6e6f7420666f722073656c6c00000000000000000000000000000000000000006044820152606401610910565b6002547501000000000000000000000000000000000000000000900460ff166120e65760405162461bcd60e51b815260206004820152601260248201527f726573656c6c696e672064657361626c656400000000000000000000000000006044820152606401610910565b816101c00151156121395760405162461bcd60e51b815260206004820152601160248201527f616c72656164792063616e63656c6c65640000000000000000000000000000006044820152606401610910565b61214b8360e001518360e001516134d7565b6121975760405162461bcd60e51b815260206004820152601060248201527f646966666572656e74207469636b6574000000000000000000000000000000006044820152606401610910565b6101608201516001600160a01b0316156123ea578161016001516001600160a01b03166323b872dd333060646006548761022001516121d69190614ae8565b6121e09190614b1d565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b1681526001600160a01b03938416600482015292909116602483015260448201526064016020604051808303816000875af115801561224c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122709190614ab3565b6122bc5760405162461bcd60e51b815260206004820152600f60248201527f7472616e73666572206661696c656400000000000000000000000000000000006044820152606401610910565b8161016001516001600160a01b03166323b872dd3384610140015160646006548761022001516122ec9190614ae8565b6122f69190614b1d565b8661022001516123069190614a91565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b1681526001600160a01b03938416600482015292909116602483015260448201526064016020604051808303816000875af1158015612372573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123969190614ab3565b6123e25760405162461bcd60e51b815260206004820152600f60248201527f7472616e73666572206661696c656400000000000000000000000000000000006044820152606401610910565b5060016124ff565b816102200151341461243e5760405162461bcd60e51b815260206004820152600f60248201527f6e6f7420656e6f7567682066756e6400000000000000000000000000000000006044820152606401610910565b60008261014001516001600160a01b031660646006548561022001516124649190614ae8565b61246e9190614b1d565b84610220015161247e9190614a91565b604051600081818185875af1925050503d80600081146124ba576040519150601f19603f3d011682016040523d82523d6000602084013e6124bf565b606091505b50509050806124f95760405162461bcd60e51b815260206004820152600660248201526511985a5b195960d21b6044820152606401610910565b60019150505b80156118f657336000908152601260205260409020546125259084843360016000613447565b336000908152601260205260409020805460010190556118f6565b8051819081906125925760405162461bcd60e51b815260206004820152600e60248201527f4e6f742076616c696420736c75670000000000000000000000000000000000006044820152606401610910565b6001546001600160a01b031633146125d55760405162461bcd60e51b815260206004820152600660248201526510b7bbb732b960d11b6044820152606401610910565b6125dd613d6a565b87815260408082018890526060820187905260808201869052518190600790612607908790614a45565b908152604080516020928190038301902083518155918301515160018301558201516002820155606082015160038201556080909101516004909101555050505050505050565b6002600054036126a05760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610910565b600260009081556001600160a01b038281168252600f6020526040822054829182911661270f5760405162461bcd60e51b815260206004820152601360248201527f746f6b656e206e6f7420737570706f72746564000000000000000000000000006044820152606401610910565b60005b8551811015612c0c57600786828151811061272f5761272f614a2f565b602002602001015160e001516040516127489190614a45565b90815260200160405180910390206000015461278a600788848151811061277157612771614a2f565b602002602001015160e001516040516115499190614a45565b106127d75760405162461bcd60e51b815260206004820152600860248201527f736f6c64206f75740000000000000000000000000000000000000000000000006044820152606401610910565b4260078783815181106127ec576127ec614a2f565b602002602001015160e001516040516128059190614a45565b908152602001604051809103902060040154106128645760405162461bcd60e51b815260206004820152601160248201527f6e6f7420617661696c61626c65207965740000000000000000000000000000006044820152606401610910565b42600787838151811061287957612879614a2f565b602002602001015160e001516040516128929190614a45565b908152602001604051809103902060030154116128f15760405162461bcd60e51b815260206004820152601560248201527f6e6f7420617661696c61626c6520616e796d6f726500000000000000000000006044820152606401610910565b6129143387838151811061290757612907614a2f565b60200260200101516136f6565b9250600061293f8488848151811061292e5761292e614a2f565b602002602001015160e00151611a29565b905061294b8186614ad0565b94503387838151811061296057612960614a2f565b602002602001015161014001906001600160a01b031690816001600160a01b0316815250508087838151811061299857612998614a2f565b60200260200101516101800181815250506129b381876135a9565b8783815181106129c5576129c5614a2f565b60200260200101516101a0018181525050428783815181106129e9576129e9614a2f565b602002602001015161026001818152505085878381518110612a0d57612a0d614a2f565b60209081029190910101516001600160a01b039182166101609091015260115488519116906000908290639ada37979033908c9088908110612a5157612a51614a2f565b602002602001015160e001518c8881518110612a6f57612a6f614a2f565b602002602001015160c001516040518463ffffffff1660e01b8152600401612a9993929190614b31565b6020604051808303816000875af1158015612ab8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612adc9190614b65565b905080898581518110612af157612af1614a2f565b6020908102919091018101516102a0019190915233600090815260129091526040902054612b56908a8681518110612b2b57612b2b614a2f565b60200260200101518b8781518110612b4557612b45614a2f565b602002602001015133600080613447565b612b8660078a8681518110612b6d57612b6d614a2f565b602002602001015160e001516040516118709190614a45565b33600090815260126020526040902080546001019055336001600160a01b03167f37f6bb16b0bdb959756bdf092a280a41bc3d9bc945cb9400324cc46fcc21ef058a8681518110612bd957612bd9614a2f565b6020026020010151604051612bee9190614d45565b60405180910390a25050508080612c0490614a77565b915050612712565b50612c1783856135a9565b90506000811180612c26575082155b612c725760405162461bcd60e51b815260206004820152600760248201527f746f74616c2030000000000000000000000000000000000000000000000000006044820152606401610910565b6001600160a01b038416612d675780341015612cd05760405162461bcd60e51b815260206004820152600d60248201527f707269636520746f6f206c6f77000000000000000000000000000000000000006044820152606401610910565b80341115612d6257600033612ce58334614a91565b604051600081818185875af1925050503d8060008114612d21576040519150601f19603f3d011682016040523d82523d6000602084013e612d26565b606091505b5050905080612d605760405162461bcd60e51b815260206004820152600660248201526511985a5b195960d21b6044820152606401610910565b505b612e43565b6040517f23b872dd000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018290526001600160a01b038516906323b872dd906064016020604051808303816000875af1158015612dd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612df79190614ab3565b612e435760405162461bcd60e51b815260206004820152600f60248201527f7472616e73666572206661696c656400000000000000000000000000000000006044820152606401610910565b60408051348152602081018390526001600160a01b0386169181019190915233907f3c5dbc8b06dedabbc2e368e4c4b130d6034cb47f80ff25b31d24d51c72adee85906060016110c6565b6001546001600160a01b03163314612ed15760405162461bcd60e51b815260206004820152600660248201526510b7bbb732b960d11b6044820152606401610910565b600280549115157501000000000000000000000000000000000000000000027fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff909216919091179055565b600080612f2984846137c5565b60600151949350505050565b6001546001600160a01b03163314612f785760405162461bcd60e51b815260206004820152600660248201526510b7bbb732b960d11b6044820152606401610910565b6002805495151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff90961695909517909455600592909255600655600355600455565b600080805b835181101561302d57600061300586868481518110612ff857612ff8614a2f565b60200260200101516137c5565b90508060600151836130179190614ad0565b925050808061302590614a77565b915050612fd7565b509392505050565b6009602090815260009182526040918290208054600182015484519384019094526002820154835260038201546004830180546001600160a01b039093169594939192613081906148e7565b80601f01602080910402602001604051908101604052809291908181526020018280546130ad906148e7565b80156130fa5780601f106130cf576101008083540402835291602001916130fa565b820191906000526020600020905b8154815290600101906020018083116130dd57829003601f168201915b5050505050908060050154908060060154905087565b6001546001600160a01b031633146131535760405162461bcd60e51b815260206004820152600660248201526510b7bbb732b960d11b6044820152606401610910565b6001600160a01b038216156131805760015461317c906001600160a01b038481169116836133c7565b5050565b6001546040516000916001600160a01b03169083908381818185875af1925050503d80600081146131cd576040519150601f19603f3d011682016040523d82523d6000602084013e6131d2565b606091505b505090508061320c5760405162461bcd60e51b815260206004820152600660248201526511985a5b195960d21b6044820152606401610910565b505050565b6132dc604051806102c0016040528060608152602001606081526020016060815260200160608152602001606081526020016060815260200160608152602001606081526020016060815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160001515815260200160008152602001600015158152602001600081526020016060815260200160008152602001600015158152602001600081525090565b6010546040517f1ebfefab0000000000000000000000000000000000000000000000000000000081526001600160a01b03858116600483015260248201859052909116908190631ebfefab90604401600060405180830381865afa158015613348573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611a719190810190614def565b8054806133bf5760405162461bcd60e51b815260206004820152601b60248201527f436f756e7465723a2064656372656d656e74206f766572666c6f7700000000006044820152606401610910565b600019019055565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905261320c908490613a1f565b6010546040517f7071a8250000000000000000000000000000000000000000000000000000000081526001600160a01b03909116908190637071a8259061349c908a908a908a908a908a908a9060040161505b565b600060405180830381600087803b1580156134b657600080fd5b505af11580156134ca573d6000803e3d6000fd5b5050505050505050505050565b81518151600091849184919081146134f55760009350505050611a75565b60005b8181101561359c5782818151811061351257613512614a2f565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191684828151811061355157613551614a2f565b01602001517fff00000000000000000000000000000000000000000000000000000000000000161461358a576000945050505050611a75565b8061359481614a77565b9150506134f8565b5060019695505050505050565b6001600160a01b038082166000908152600f60205260408082205481517ffeaf968c0000000000000000000000000000000000000000000000000000000081529151929316918391839163feaf968c9160048082019260a0929091908290030181865afa15801561361e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061364291906150ca565b509193506012925050506001600160a01b038516156136c9576000859050806001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561369e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136c2919061511a565b60ff169150505b6000826136d783600a615221565b6136e1908961522d565b6136eb91906152e9565b979650505050505050565b60008061370384846137c5565b8051909150156137255761372560088461010001516040516118709190614a45565b806020015115613752576001600160a01b0384166000908152600960205260409020600201805460010190555b8060400151156137ba576101208301516001600160a01b03166000908152600a60205260409020600301805460010190556101208301516001600160a01b039081166000908152600c60209081526040808320938816835292905220805460ff191660011790555b606001519392505050565b604080516080810182526000808252602080830182905282840182905260608301829052601054845180860186528083018481526001600160a01b038981168084526101208a015182168752600c86528887209087529094528685205460ff1615159052610100870151955194959290911693909291849163e1a3195d918591600d9161385191614a45565b90815260200160405180910390208860e001516040516138719190614a45565b908152604051908190036020018120546101008a015160ff9091169160089161389991614a45565b9081526020016040518091039020600e60008b61014001516001600160a01b03166001600160a01b031681526020019081526020016000208a60e001516040516138e39190614a45565b908152602001604051809103902060009054906101000a900460ff16600960008c61014001516001600160a01b03166001600160a01b03168152602001908152602001600020600b60008d61012001516001600160a01b03166001600160a01b031681526020019081526020016000208c60e001516040516139659190614a45565b908152602001604051809103902060009054906101000a900460ff16600a60008e61012001516001600160a01b03166001600160a01b031681526020019081526020016000208d61012001516040518963ffffffff1660e01b81526004016139d4989796959493929190615412565b608060405180830381865afa1580156139f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a159190615524565b9695505050505050565b6000613a74826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316613b049092919063ffffffff16565b80519091501561320c5780806020019051810190613a929190614ab3565b61320c5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610910565b6060613b138484600085613b1d565b90505b9392505050565b606082471015613b955760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610910565b6001600160a01b0385163b613bec5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610910565b600080866001600160a01b03168587604051613c089190614a45565b60006040518083038185875af1925050503d8060008114613c45576040519150601f19603f3d011682016040523d82523d6000602084013e613c4a565b606091505b50915091506136eb82828660608315613c64575081613b16565b825115613c745782518084602001fd5b8160405162461bcd60e51b815260040161091091906155a2565b6040518060e0016040528060006001600160a01b0316815260200160008152602001613cc66040518060200160405280600081525090565b8152602001600081526020016060815260200160008152602001600081525090565b6040518060c0016040528060008152602001613cc66040518060200160405280600081525090565b6040518060e0016040528060006001600160a01b031681526020016000815260200160008152602001613d4f6040518060200160405280600081525090565b81526020016000815260200160008152602001600081525090565b6040518060a0016040528060008152602001613d4f6040518060200160405280600081525090565b6001600160a01b0381168114613da757600080fd5b50565b8035613db581613d92565b919050565b634e487b7160e01b600052604160045260246000fd5b6040516102c0810167ffffffffffffffff81118282101715613df457613df4613dba565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715613e2357613e23613dba565b604052919050565b600067ffffffffffffffff821115613e4557613e45613dba565b50601f01601f191660200190565b600082601f830112613e6457600080fd5b8135613e77613e7282613e2b565b613dfa565b818152846020838601011115613e8c57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215613ebc57600080fd5b8235613ec781613d92565b9150602083013567ffffffffffffffff811115613ee357600080fd5b613eef85828601613e53565b9150509250929050565b600067ffffffffffffffff821115613f1357613f13613dba565b5060051b60200190565b600082601f830112613f2e57600080fd5b81356020613f3e613e7283613ef9565b82815260059290921b84018101918181019086841115613f5d57600080fd5b8286015b84811015613f9d57803567ffffffffffffffff811115613f815760008081fd5b613f8f8986838b0101613e53565b845250918301918301613f61565b509695505050505050565b600080600080600080600060e0888a031215613fc357600080fd5b8735613fce81613d92565b96506020880135955060408801359450606088013593506080880135925060a088013567ffffffffffffffff8082111561400757600080fd5b6140138b838c01613f1d565b935060c08a013591508082111561402957600080fd5b506140368a828b01613f1d565b91505092959891949750929550565b600080600080600080600060e0888a03121561406057600080fd5b873567ffffffffffffffff8082111561407857600080fd5b6140848b838c01613e53565b985060208a0135975060408a0135965060608a0135955060808a0135945060a08a013591508082111561400757600080fd5b6000602082840312156140c857600080fd5b8135613b1681613d92565b6000806000606084860312156140e857600080fd5b83356140f381613d92565b95602085013595506040909401359392505050565b60006020828403121561411a57600080fd5b813567ffffffffffffffff81111561413157600080fd5b611a7184828501613e53565b60005b83811015614158578181015183820152602001614140565b83811115614167576000848401525b50505050565b6000815180845261418581602086016020860161413d565b601f01601f19169290920160200192915050565b8681528551602082015284604082015260c0606082015260006141bf60c083018661416d565b60808301949094525060a00152949350505050565b600080600080600080600080610100898b0312156141f157600080fd5b88356141fc81613d92565b97506020890135965060408901359550606089013594506080890135935060a0890135925060c089013567ffffffffffffffff8082111561423c57600080fd5b6142488c838d01613f1d565b935060e08b013591508082111561425e57600080fd5b5061426b8b828c01613f1d565b9150509295985092959890939650565b8015158114613da757600080fd5b8035613db58161427b565b60006102c082840312156142a757600080fd5b6142af613dd0565b9050813567ffffffffffffffff808211156142c957600080fd5b6142d585838601613e53565b835260208401359150808211156142eb57600080fd5b6142f785838601613e53565b6020840152604084013591508082111561431057600080fd5b61431c85838601613e53565b6040840152606084013591508082111561433557600080fd5b61434185838601613e53565b6060840152608084013591508082111561435a57600080fd5b61436685838601613e53565b608084015260a084013591508082111561437f57600080fd5b61438b85838601613e53565b60a084015260c08401359150808211156143a457600080fd5b6143b085838601613e53565b60c084015260e08401359150808211156143c957600080fd5b6143d585838601613e53565b60e0840152610100915081840135818111156143f057600080fd5b6143fc86828701613e53565b83850152506101209150614411828501613daa565b828401526101409150614425828501613daa565b828401526101609150614439828501613daa565b9183019190915261018083810135908301526101a080840135908301526101c090614465828501614289565b828401526101e0915081840135828401526102009150614486828501614289565b8284015261022091508184013582840152610240915081840135818111156144ad57600080fd5b6144b986828701613e53565b838501525050506102608083013581830152506102806144da818401614289565b81830152506102a080830135818301525092915050565b60008060006060848603121561450657600080fd5b83359250602084013561451881613d92565b9150604084013567ffffffffffffffff81111561453457600080fd5b61454086828701614294565b9150509250925092565b6000806040838503121561455d57600080fd5b82359150602083013567ffffffffffffffff811115613ee357600080fd5b6000806040838503121561458e57600080fd5b823561459981613d92565b915060208301356145a981613d92565b809150509250929050565b6000602082840312156145c657600080fd5b5035919050565b600080604083850312156145e057600080fd5b82359150602083013567ffffffffffffffff8111156145fe57600080fd5b613eef85828601614294565b600080600080600060a0868803121561462257600080fd5b85359450602086013593506040860135925060608601359150608086013567ffffffffffffffff81111561465557600080fd5b61466188828901613e53565b9150509295509295909350565b600082601f83011261467f57600080fd5b8135602061468f613e7283613ef9565b82815260059290921b840181019181810190868411156146ae57600080fd5b8286015b84811015613f9d57803567ffffffffffffffff8111156146d25760008081fd5b6146e08986838b0101614294565b8452509183019183016146b2565b6000806040838503121561470157600080fd5b823567ffffffffffffffff81111561471857600080fd5b6147248582860161466e565b92505060208301356145a981613d92565b6000806040838503121561474857600080fd5b823567ffffffffffffffff8082111561476057600080fd5b61476c86838701613e53565b9350602085013591508082111561478257600080fd5b50613eef85828601613e53565b6000602082840312156147a157600080fd5b8135613b168161427b565b600080604083850312156147bf57600080fd5b82356147ca81613d92565b9150602083013567ffffffffffffffff8111156145fe57600080fd5b600080600080600060a086880312156147fe57600080fd5b85356148098161427b565b97602087013597506040870135966060810135965060800135945092505050565b6000806040838503121561483d57600080fd5b823561484881613d92565b9150602083013567ffffffffffffffff81111561486457600080fd5b613eef8582860161466e565b6001600160a01b03881681528660208201528551604082015284606082015260e0608082015260006148a560e083018661416d565b60a08301949094525060c0015295945050505050565b600080604083850312156148ce57600080fd5b82356148d981613d92565b946020939093013593505050565b600181811c908216806148fb57607f821691505b60208210810361491b57634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111561320c57600081815260208120601f850160051c810160208610156149485750805b601f850160051c820191505b8181101561496757828155600101614954565b505050505050565b815167ffffffffffffffff81111561498957614989613dba565b61499d8161499784546148e7565b84614921565b602080601f8311600181146149d257600084156149ba5750858301515b600019600386901b1c1916600185901b178555614967565b600085815260208120601f198616915b82811015614a01578886015182559484019460019091019084016149e2565b5085821015614a1f5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052603260045260246000fd5b60008251614a5781846020870161413d565b9190910192915050565b634e487b7160e01b600052601160045260246000fd5b60006000198203614a8a57614a8a614a61565b5060010190565b600082821015614aa357614aa3614a61565b500390565b8051613db58161427b565b600060208284031215614ac557600080fd5b8151613b168161427b565b60008219821115614ae357614ae3614a61565b500190565b6000816000190483118215151615614b0257614b02614a61565b500290565b634e487b7160e01b600052601260045260246000fd5b600082614b2c57614b2c614b07565b500490565b6001600160a01b0384168152606060208201526000614b53606083018561416d565b8281036040840152613a15818561416d565b600060208284031215614b7757600080fd5b5051919050565b60006102c08251818552614b948286018261416d565b91505060208301518482036020860152614bae828261416d565b91505060408301518482036040860152614bc8828261416d565b91505060608301518482036060860152614be2828261416d565b91505060808301518482036080860152614bfc828261416d565b91505060a083015184820360a0860152614c16828261416d565b91505060c083015184820360c0860152614c30828261416d565b91505060e083015184820360e0860152614c4a828261416d565b9150506101008084015185830382870152614c65838261416d565b9250505061012080840151614c84828701826001600160a01b03169052565b5050610140838101516001600160a01b0390811691860191909152610160808501519091169085015261018080840151908501526101a080840151908501526101c0808401511515908501526101e080840151908501526102008084015115159085015261022080840151908501526102408084015185830382870152614d0b838261416d565b9250505061026080840151818601525061028080840151614d2f8287018215159052565b50506102a0928301519390920192909252919050565b604081526000614d586040830184614b7e565b8281036020840152600381527f627579000000000000000000000000000000000000000000000000000000000060208201526040810191505092915050565b600082601f830112614da857600080fd5b8151614db6613e7282613e2b565b818152846020838601011115614dcb57600080fd5b614ddc82602083016020870161413d565b949350505050565b8051613db581613d92565b600060208284031215614e0157600080fd5b815167ffffffffffffffff80821115614e1957600080fd5b908301906102c08286031215614e2e57600080fd5b614e36613dd0565b825182811115614e4557600080fd5b614e5187828601614d97565b825250602083015182811115614e6657600080fd5b614e7287828601614d97565b602083015250604083015182811115614e8a57600080fd5b614e9687828601614d97565b604083015250606083015182811115614eae57600080fd5b614eba87828601614d97565b606083015250608083015182811115614ed257600080fd5b614ede87828601614d97565b60808301525060a083015182811115614ef657600080fd5b614f0287828601614d97565b60a08301525060c083015182811115614f1a57600080fd5b614f2687828601614d97565b60c08301525060e083015182811115614f3e57600080fd5b614f4a87828601614d97565b60e0830152506101008084015183811115614f6457600080fd5b614f7088828701614d97565b828401525050610120614f84818501614de4565b90820152610140614f96848201614de4565b90820152610160614fa8848201614de4565b9082015261018083810151908201526101a080840151908201526101c0614fd0818501614aa8565b908201526101e08381015190820152610200614fed818501614aa8565b908201526102208381015190820152610240808401518381111561501057600080fd5b61501c88828701614d97565b82840152505061026091508183015182820152610280915061503f828401614aa8565b918101919091526102a091820151918101919091529392505050565b86815260c06020820152600061507460c0830188614b7e565b82810360408401526150868188614b7e565b6001600160a01b0396909616606084015250509115156080830152151560a0909101529392505050565b805169ffffffffffffffffffff81168114613db557600080fd5b600080600080600060a086880312156150e257600080fd5b6150eb866150b0565b945060208601519350604086015192506060860151915061510e608087016150b0565b90509295509295909350565b60006020828403121561512c57600080fd5b815160ff81168114613b1657600080fd5b600181815b8085111561517857816000190482111561515e5761515e614a61565b8085161561516b57918102915b93841c9390800290615142565b509250929050565b60008261518f57506001611a75565b8161519c57506000611a75565b81600181146151b257600281146151bc576151d8565b6001915050611a75565b60ff8411156151cd576151cd614a61565b50506001821b611a75565b5060208310610133831016604e8410600b84101617156151fb575081810a611a75565b615205838361513d565b806000190482111561521957615219614a61565b029392505050565b6000613b168383615180565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60008413600084138583048511828216161561526e5761526e614a61565b7f800000000000000000000000000000000000000000000000000000000000000060008712868205881281841616156152a9576152a9614a61565b600087129250878205871284841616156152c5576152c5614a61565b878505871281841616156152db576152db614a61565b505050929093029392505050565b6000826152f8576152f8614b07565b60001983147f80000000000000000000000000000000000000000000000000000000000000008314161561532e5761532e614a61565b500590565b60008154615340816148e7565b80855260206001838116801561535d5760018114615377576153a5565b60ff198516838901528284151560051b89010195506153a5565b866000528260002060005b8581101561539d5781548a8201860152908301908401615382565b890184019650505b505050505092915050565b6001600160a01b03815416825260018101546020830152600281015460408301526003810154606083015260e0608083015260006153f460e0840160048401615333565b600583015460a0850152600683015460c08501528091505092915050565b60006101e06001600160a01b038b5116835260208b0151151560208401528915156040840152806060840152885481840152506001880154610200830152600288015461022083015260c06102408301526154746102a0830160038a01615333565b60048901546102608401526005890154610280840152871515608084015282810360a08401526154a481886153b0565b9150506154b560c083018615159052565b83546001600160a01b031660e08301526001840154610100830152600284015461012083015260038401546101408301526004840154610160830152600584015461018083015260068401546101a08301526001600160a01b0383166101c08301529998505050505050505050565b60006080828403121561553657600080fd5b6040516080810181811067ffffffffffffffff8211171561555957615559613dba565b60405282516155678161427b565b815260208301516155778161427b565b6020820152604083015161558a8161427b565b60408201526060928301519281019290925250919050565b602081526000613b16602083018461416d56fea2646970667358221220e1ab597239476fd8612cb204f5f85da048993e44148882d3796f5d53d76817b164736f6c634300080f0033000000000000000000000000d5d2e66f96a167c15610f637d67e6392f5a0df36000000000000000000000000160f5ffdde509aaf271e93a9b675c09e27580330
Deployed Bytecode
0x60806040526004361061024f5760003560e01c80638da5cb5b11610138578063b2d4cb23116100b0578063d0223fb11161007f578063e94cefc811610064578063e94cefc814610868578063f3fef3a31461089b578063f52b832f146108bb57600080fd5b8063d0223fb114610828578063d1c9fc5f1461084857600080fd5b8063b2d4cb23146107a5578063b4b1d5d8146107c5578063c1165ded146107f2578063cad39e161461080857600080fd5b8063955f21df116101075780639a322361116100ec5780639a322361146107045780639dcb511a14610717578063a1be9cb11461074d57600080fd5b8063955f21df146106b157806396517faf146106e457600080fd5b80638da5cb5b1461064857806390cb68b31461066857806390fe6ddb1461068857806394dff5c91461069e57600080fd5b80633c542c81116101cb5780636cd5b5b91161019a5780637ac974a91161017f5780637ac974a9146105c55780637da044191461060057806383a765dd1461063257600080fd5b80636cd5b5b91461055957806376e11286146105a557600080fd5b80633c542c811461044a5780634da98607146104f8578063549859c51461050b578063698d2d761461052b57600080fd5b806318fd890311610222578063290e351511610207578063290e35151461036957806329ae0b7f146103895780633bd3dad81461041257600080fd5b806318fd8903146103175780631a3764d21461033757600080fd5b8063076beddd146102545780630b7f8118146102b55780631058471b146102d757806313af4035146102f7575b600080fd5b34801561026057600080fd5b506102a061026f366004613ea9565b600e602090815260009283526040909220815180830184018051928152908401929093019190912091525460ff1681565b60405190151581526020015b60405180910390f35b3480156102c157600080fd5b506102d56102d0366004613fa8565b6108d1565b005b3480156102e357600080fd5b506102d56102f2366004614045565b610ad0565b34801561030357600080fd5b506102d56103123660046140b6565b610ca2565b34801561032357600080fd5b506102d56103323660046140d3565b610d48565b34801561034357600080fd5b50610357610352366004614108565b6110da565b6040516102ac96959493929190614199565b34801561037557600080fd5b506102d56103843660046141d4565b6111b1565b34801561039557600080fd5b506103eb6103a4366004614108565b805160208183018101805160078252928201938201939093209190925280546040805193840190526001820154835260028201546003830154600490930154919392909185565b6040805195865293516020860152928401919091526060830152608082015260a0016102ac565b34801561041e57600080fd5b50600254610432906001600160a01b031681565b6040516001600160a01b0390911681526020016102ac565b34801561045657600080fd5b506104ba6104653660046140b6565b600a60209081526000918252604091829020805460018201546002830154855194850190955260038301548452600483015460058401546006909401546001600160a01b039093169591949193919290919087565b604080516001600160a01b03909816885260208801969096529486019390935290516060850152608084015260a083015260c082015260e0016102ac565b6102d56105063660046144f1565b61139b565b34801561051757600080fd5b506102d56105263660046140b6565b611901565b34801561053757600080fd5b5061054b61054636600461454a565b611a29565b6040519081526020016102ac565b34801561056557600080fd5b506102a0610574366004613ea9565b600b602090815260009283526040909220815180830184018051928152908401929093019190912091525460ff1681565b3480156105b157600080fd5b506102d56105c036600461457b565b611a7b565b3480156105d157600080fd5b506102a06105e036600461457b565b600c60209081526000928352604080842090915290825290205460ff1681565b34801561060c57600080fd5b506002546102a09074010000000000000000000000000000000000000000900460ff1681565b34801561063e57600080fd5b5061054b60035481565b34801561065457600080fd5b50600154610432906001600160a01b031681565b34801561067457600080fd5b506102d56106833660046145b4565b611af9565b34801561069457600080fd5b5061054b60055481565b6102d56106ac3660046145cd565b611fbc565b3480156106bd57600080fd5b506002546102a0907501000000000000000000000000000000000000000000900460ff1681565b3480156106f057600080fd5b506102d56106ff36600461460a565b612540565b6102d56107123660046146ee565b61264e565b34801561072357600080fd5b506104326107323660046140b6565b600f602052600090815260409020546001600160a01b031681565b34801561075957600080fd5b506102a0610768366004614735565b8151602081840181018051600d82529282019482019490942091909352815180830184018051928152908401929093019190912091525460ff1681565b3480156107b157600080fd5b506102d56107c036600461478f565b612e8e565b3480156107d157600080fd5b5061054b6107e03660046140b6565b60126020526000908152604090205481565b3480156107fe57600080fd5b5061054b60065481565b34801561081457600080fd5b5061054b6108233660046147ac565b612f1c565b34801561083457600080fd5b506102d56108433660046147e6565b612f35565b34801561085457600080fd5b5061054b61086336600461482a565b612fd2565b34801561087457600080fd5b506108886108833660046140b6565b613035565b6040516102ac9796959493929190614870565b3480156108a757600080fd5b506102d56108b63660046148bb565b613110565b3480156108c757600080fd5b5061054b60045481565b6001546001600160a01b031633146109195760405162461bcd60e51b815260206004820152600660248201526510b7bbb732b960d11b60448201526064015b60405180910390fd5b610921613c8e565b60208181018881526060830188815260a0840188905260c084018790526001600160a01b038b8116600090815260099094526040938490208551815473ffffffffffffffffffffffffffffffffffffffff19169216919091178155915160018301559183015151600282015590516003820155608082015182919060048201906109ab908261496f565b5060a0820151600582015560c09091015160069091015560005b8351811015610a45576001600160a01b0389166000908152600e602052604090208451600191908690849081106109fe576109fe614a2f565b6020026020010151604051610a139190614a45565b908152604051908190036020019020805491151560ff1990921691909117905580610a3d81614a77565b9150506109c5565b5060005b8251811015610ac5576001600160a01b0389166000908152600e602052604081208451859084908110610a7e57610a7e614a2f565b6020026020010151604051610a939190614a45565b908152604051908190036020019020805491151560ff1990921691909117905580610abd81614a77565b915050610a49565b505050505050505050565b6001546001600160a01b03163314610b135760405162461bcd60e51b815260206004820152600660248201526510b7bbb732b960d11b6044820152606401610910565b610b1b613ce8565b86815260408082018790526080820186905260a08201859052518190600890610b45908b90614a45565b90815260408051602092819003830190208351815591830151516001830155820151600282015560608201516003820190610b80908261496f565b506080820151600482015560a09091015160059091015560005b8351811015610c1c576001600d8a604051610bb59190614a45565b9081526020016040518091039020858381518110610bd557610bd5614a2f565b6020026020010151604051610bea9190614a45565b908152604051908190036020019020805491151560ff1990921691909117905580610c1481614a77565b915050610b9a565b5060005b8251811015610ac5576000600d8a604051610c3b9190614a45565b9081526020016040518091039020848381518110610c5b57610c5b614a2f565b6020026020010151604051610c709190614a45565b908152604051908190036020019020805491151560ff1990921691909117905580610c9a81614a77565b915050610c20565b6001546001600160a01b03163314610ce55760405162461bcd60e51b815260206004820152600660248201526510b7bbb732b960d11b6044820152606401610910565b6002805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03831690811790915560405190815233907fc66d1d23a5b7baf1f496bb19f580d7b12070ad5a08a758c990db97d961fa33a69060200160405180910390a250565b6001546001600160a01b03163314610d8b5760405162461bcd60e51b815260206004820152600660248201526510b7bbb732b960d11b6044820152606401610910565b600260005403610ddd5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610910565b60026000908155610dee8484613211565b905081816101a001511015610e455760405162461bcd60e51b815260206004820152601d60248201527f726566756e6420686967686572207468616e20706169642070726963650000006044820152606401610910565b806101c0015115610e985760405162461bcd60e51b815260206004820152601160248201527f616c72656164792063616e63656c6c65640000000000000000000000000000006044820152606401610910565b6011546102a08201516040517fe452351b00000000000000000000000000000000000000000000000000000000815260048101919091526001600160a01b0390911690819063e452351b90602401600060405180830381600087803b158015610f0057600080fd5b505af1158015610f14573d6000803e3d6000fd5b50505050610f4560078360e00151604051610f2f9190614a45565b9081526020016040518091039020600101613370565b6101608201516001600160a01b031615610fb157610f81826101400151848461016001516001600160a01b03166133c79092919063ffffffff16565b6101e0820183905260016101c08301819052610140830151610fac9186918591829190600090613447565b61106a565b6000856001600160a01b03168460405160006040518083038185875af1925050503d8060008114610ffe576040519150601f19603f3d011682016040523d82523d6000602084013e611003565b606091505b505090508061103d5760405162461bcd60e51b815260206004820152600660248201526511985a5b195960d21b6044820152606401610910565b6101e0830184905260016101c084018190526101408401516110689187918691829190600090613447565b505b846001600160a01b03167f1bd82af1a69358f33a6adf465c79404ca8dd30dbf4f7049eca78b5627018fc0a84868561016001516040516110c69392919092835260208301919091526001600160a01b0316604082015260600190565b60405180910390a250506001600055505050565b805160208183018101805160088252928201938201939093209190925280546040805193840190526001820154835260028201546003830180549294939192611122906148e7565b80601f016020809104026020016040519081016040528092919081815260200182805461114e906148e7565b801561119b5780601f106111705761010080835404028352916020019161119b565b820191906000526020600020905b81548152906001019060200180831161117e57829003601f168201915b5050505050908060040154908060050154905086565b6001546001600160a01b031633146111f45760405162461bcd60e51b815260206004820152600660248201526510b7bbb732b960d11b6044820152606401610910565b6111fc613d10565b6001600160a01b0389811680835260208084018b815260408086018c8152608087018c815260a088018c815260c089018c81526000978852600a9096529286208851815473ffffffffffffffffffffffffffffffffffffffff1916981697909717875592516001870155516002860155606086015151600386015590516004850155516005840155516006909201919091555b835181101561130f576001600160a01b038a166000908152600b602052604090208451600191908690849081106112c8576112c8614a2f565b60200260200101516040516112dd9190614a45565b908152604051908190036020019020805491151560ff199092169190911790558061130781614a77565b91505061128f565b5060005b825181101561138f576001600160a01b038a166000908152600b60205260408120845185908490811061134857611348614a2f565b602002602001015160405161135d9190614a45565b908152604051908190036020019020805491151560ff199092169190911790558061138781614a77565b915050611313565b50505050505050505050565b6002600054036113ed5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610910565b600260009081556113fe8385613211565b6101408101519091506001600160a01b031633148061142757506001546001600160a01b031633145b6114735760405162461bcd60e51b815260206004820152601560248201527f6e6f7420616c6c6f77656420746f2075706461746500000000000000000000006044820152606401610910565b806101c00151156114c65760405162461bcd60e51b815260206004820152601160248201527f616c72656164792063616e63656c6c65640000000000000000000000000000006044820152606401610910565b6101408101516001600160a01b03163314806114ec57506001546001600160a01b031633145b801561150757506115058260e001518260e001516134d7565b155b156118e75760078260e001516040516115209190614a45565b90815260200160405180910390206000015461155e60078460e001516040516115499190614a45565b90815260200160405180910390206001015490565b106115ab5760405162461bcd60e51b815260206004820152600860248201527f736f6c64206f75740000000000000000000000000000000000000000000000006044820152606401610910565b4260078360e001516040516115c09190614a45565b9081526020016040518091039020600401541061161f5760405162461bcd60e51b815260206004820152601160248201527f6e6f7420617661696c61626c65207965740000000000000000000000000000006044820152606401610910565b4260078360e001516040516116349190614a45565b908152602001604051809103902060030154116116935760405162461bcd60e51b815260206004820152601560248201527f6e6f7420617661696c61626c6520616e796d6f726500000000000000000000006044820152606401610910565b80610180015160078360e001516040516116ad9190614a45565b90815260200160405180910390206002015411156118e757600061170b82610180015160078560e001516040516116e49190614a45565b9081526020016040518091039020600201546117009190614a91565b8361016001516135a9565b6101608301519091506001600160a01b031661177657803410156117715760405162461bcd60e51b815260206004820152601960248201527f6e6577207469636b6574206d6f726520657870656e73697665000000000000006044820152606401610910565b611859565b6101608201516040517f23b872dd000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018390526001600160a01b03909116906323b872dd906064016020604051808303816000875af11580156117e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061180d9190614ab3565b6118595760405162461bcd60e51b815260206004820152600f60248201527f7472616e73666572206661696c656400000000000000000000000000000000006044820152606401610910565b61188a60078460e001516040516118709190614a45565b908152602001604051809103902060010180546001019055565b6118a160078360e00151604051610f2f9190614a45565b60078360e001516040516118b59190614a45565b908152604051908190036020019020600201546101808301526101a08201516118df908290614ad0565b6101a0830152505b6118f684838386600080613447565b505060016000555050565b6001546001600160a01b031633146119445760405162461bcd60e51b815260206004820152600660248201526510b7bbb732b960d11b6044820152606401610910565b6002546001600160a01b038281169116146119a15760405162461bcd60e51b815260206004820152600d60248201527f6e6f7420636f6e6669726d6564000000000000000000000000000000000000006044820152606401610910565b6001600160a01b0381166000036119fa5760405162461bcd60e51b815260206004820152601160248201527f616464726573732063616e7420626520300000000000000000000000000000006044820152606401610910565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b600080600783604051611a3c9190614a45565b9081526040519081900360200190206002015490506064611a5d8583614ae8565b611a679190614b1d565b611a719082614a91565b9150505b92915050565b6001546001600160a01b03163314611abe5760405162461bcd60e51b815260206004820152600660248201526510b7bbb732b960d11b6044820152606401610910565b6001600160a01b039182166000908152600f60205260409020805473ffffffffffffffffffffffffffffffffffffffff191691909216179055565b600260005403611b4b5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610910565b60026000908155611b5c3383613211565b6101408101519091506001600160a01b03163314611bbc5760405162461bcd60e51b815260206004820152601360248201527f73656e646572206973206e6f74206275796572000000000000000000000000006044820152606401610910565b60025474010000000000000000000000000000000000000000900460ff16611c265760405162461bcd60e51b815260206004820152601360248201527f726566756e64206e6f7420706f737369626c65000000000000000000000000006044820152606401610910565b806101c0015115611c795760405162461bcd60e51b815260206004820152601160248201527f616c72656164792063616e63656c6c65640000000000000000000000000000006044820152606401610910565b80610280015115611ccc5760405162461bcd60e51b815260206004820181905260248201527f7265736f6c642c2073656520726566756e64207769746820726573656c6c65726044820152606401610910565b4260078260e00151604051611ce19190614a45565b90815260200160405180910390206003015411611d405760405162461bcd60e51b815260206004820152601b60248201527f726566756e64206e6f7420706f737369626c6520616e796d6f726500000000006044820152606401610910565b600060045482610260015142611d569190614a91565b600354611d639190614ae8565b611d6d9190614b1d565b905060648110611dbf5760405162461bcd60e51b815260206004820152601360248201527f726566756e64206e6f7420706f737369626c65000000000000000000000000006044820152606401610910565b60006064836101a0015183611dd49190614ae8565b611dde9190614b1d565b836101a00151611dee9190614a91565b6011546102a08501516040517fe452351b00000000000000000000000000000000000000000000000000000000815260048101919091529192506001600160a01b031690819063e452351b90602401600060405180830381600087803b158015611e5757600080fd5b505af1158015611e6b573d6000803e3d6000fd5b50505050611e8660078560e00151604051610f2f9190614a45565b6101608401516001600160a01b031615611ef257611ec2846101400151838661016001516001600160a01b03166133c79092919063ffffffff16565b6101e0840182905260016101c08501819052610140850151611eed9187918791829190600090613447565b611fb0565b60008461014001516001600160a01b03168360405160006040518083038185875af1925050503d8060008114611f44576040519150601f19603f3d011682016040523d82523d6000602084013e611f49565b606091505b5050905080611f835760405162461bcd60e51b815260206004820152600660248201526511985a5b195960d21b6044820152606401610910565b6101e0850183905260016101c08601819052610140860151611fae9188918891829190600090613447565b505b50506001600055505050565b60026000540361200e5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610910565b600260009081556101408201516120259084613211565b9050600081610200015161207b5760405162461bcd60e51b815260206004820152600c60248201527f6e6f7420666f722073656c6c00000000000000000000000000000000000000006044820152606401610910565b6002547501000000000000000000000000000000000000000000900460ff166120e65760405162461bcd60e51b815260206004820152601260248201527f726573656c6c696e672064657361626c656400000000000000000000000000006044820152606401610910565b816101c00151156121395760405162461bcd60e51b815260206004820152601160248201527f616c72656164792063616e63656c6c65640000000000000000000000000000006044820152606401610910565b61214b8360e001518360e001516134d7565b6121975760405162461bcd60e51b815260206004820152601060248201527f646966666572656e74207469636b6574000000000000000000000000000000006044820152606401610910565b6101608201516001600160a01b0316156123ea578161016001516001600160a01b03166323b872dd333060646006548761022001516121d69190614ae8565b6121e09190614b1d565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b1681526001600160a01b03938416600482015292909116602483015260448201526064016020604051808303816000875af115801561224c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122709190614ab3565b6122bc5760405162461bcd60e51b815260206004820152600f60248201527f7472616e73666572206661696c656400000000000000000000000000000000006044820152606401610910565b8161016001516001600160a01b03166323b872dd3384610140015160646006548761022001516122ec9190614ae8565b6122f69190614b1d565b8661022001516123069190614a91565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b1681526001600160a01b03938416600482015292909116602483015260448201526064016020604051808303816000875af1158015612372573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123969190614ab3565b6123e25760405162461bcd60e51b815260206004820152600f60248201527f7472616e73666572206661696c656400000000000000000000000000000000006044820152606401610910565b5060016124ff565b816102200151341461243e5760405162461bcd60e51b815260206004820152600f60248201527f6e6f7420656e6f7567682066756e6400000000000000000000000000000000006044820152606401610910565b60008261014001516001600160a01b031660646006548561022001516124649190614ae8565b61246e9190614b1d565b84610220015161247e9190614a91565b604051600081818185875af1925050503d80600081146124ba576040519150601f19603f3d011682016040523d82523d6000602084013e6124bf565b606091505b50509050806124f95760405162461bcd60e51b815260206004820152600660248201526511985a5b195960d21b6044820152606401610910565b60019150505b80156118f657336000908152601260205260409020546125259084843360016000613447565b336000908152601260205260409020805460010190556118f6565b8051819081906125925760405162461bcd60e51b815260206004820152600e60248201527f4e6f742076616c696420736c75670000000000000000000000000000000000006044820152606401610910565b6001546001600160a01b031633146125d55760405162461bcd60e51b815260206004820152600660248201526510b7bbb732b960d11b6044820152606401610910565b6125dd613d6a565b87815260408082018890526060820187905260808201869052518190600790612607908790614a45565b908152604080516020928190038301902083518155918301515160018301558201516002820155606082015160038201556080909101516004909101555050505050505050565b6002600054036126a05760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610910565b600260009081556001600160a01b038281168252600f6020526040822054829182911661270f5760405162461bcd60e51b815260206004820152601360248201527f746f6b656e206e6f7420737570706f72746564000000000000000000000000006044820152606401610910565b60005b8551811015612c0c57600786828151811061272f5761272f614a2f565b602002602001015160e001516040516127489190614a45565b90815260200160405180910390206000015461278a600788848151811061277157612771614a2f565b602002602001015160e001516040516115499190614a45565b106127d75760405162461bcd60e51b815260206004820152600860248201527f736f6c64206f75740000000000000000000000000000000000000000000000006044820152606401610910565b4260078783815181106127ec576127ec614a2f565b602002602001015160e001516040516128059190614a45565b908152602001604051809103902060040154106128645760405162461bcd60e51b815260206004820152601160248201527f6e6f7420617661696c61626c65207965740000000000000000000000000000006044820152606401610910565b42600787838151811061287957612879614a2f565b602002602001015160e001516040516128929190614a45565b908152602001604051809103902060030154116128f15760405162461bcd60e51b815260206004820152601560248201527f6e6f7420617661696c61626c6520616e796d6f726500000000000000000000006044820152606401610910565b6129143387838151811061290757612907614a2f565b60200260200101516136f6565b9250600061293f8488848151811061292e5761292e614a2f565b602002602001015160e00151611a29565b905061294b8186614ad0565b94503387838151811061296057612960614a2f565b602002602001015161014001906001600160a01b031690816001600160a01b0316815250508087838151811061299857612998614a2f565b60200260200101516101800181815250506129b381876135a9565b8783815181106129c5576129c5614a2f565b60200260200101516101a0018181525050428783815181106129e9576129e9614a2f565b602002602001015161026001818152505085878381518110612a0d57612a0d614a2f565b60209081029190910101516001600160a01b039182166101609091015260115488519116906000908290639ada37979033908c9088908110612a5157612a51614a2f565b602002602001015160e001518c8881518110612a6f57612a6f614a2f565b602002602001015160c001516040518463ffffffff1660e01b8152600401612a9993929190614b31565b6020604051808303816000875af1158015612ab8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612adc9190614b65565b905080898581518110612af157612af1614a2f565b6020908102919091018101516102a0019190915233600090815260129091526040902054612b56908a8681518110612b2b57612b2b614a2f565b60200260200101518b8781518110612b4557612b45614a2f565b602002602001015133600080613447565b612b8660078a8681518110612b6d57612b6d614a2f565b602002602001015160e001516040516118709190614a45565b33600090815260126020526040902080546001019055336001600160a01b03167f37f6bb16b0bdb959756bdf092a280a41bc3d9bc945cb9400324cc46fcc21ef058a8681518110612bd957612bd9614a2f565b6020026020010151604051612bee9190614d45565b60405180910390a25050508080612c0490614a77565b915050612712565b50612c1783856135a9565b90506000811180612c26575082155b612c725760405162461bcd60e51b815260206004820152600760248201527f746f74616c2030000000000000000000000000000000000000000000000000006044820152606401610910565b6001600160a01b038416612d675780341015612cd05760405162461bcd60e51b815260206004820152600d60248201527f707269636520746f6f206c6f77000000000000000000000000000000000000006044820152606401610910565b80341115612d6257600033612ce58334614a91565b604051600081818185875af1925050503d8060008114612d21576040519150601f19603f3d011682016040523d82523d6000602084013e612d26565b606091505b5050905080612d605760405162461bcd60e51b815260206004820152600660248201526511985a5b195960d21b6044820152606401610910565b505b612e43565b6040517f23b872dd000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018290526001600160a01b038516906323b872dd906064016020604051808303816000875af1158015612dd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612df79190614ab3565b612e435760405162461bcd60e51b815260206004820152600f60248201527f7472616e73666572206661696c656400000000000000000000000000000000006044820152606401610910565b60408051348152602081018390526001600160a01b0386169181019190915233907f3c5dbc8b06dedabbc2e368e4c4b130d6034cb47f80ff25b31d24d51c72adee85906060016110c6565b6001546001600160a01b03163314612ed15760405162461bcd60e51b815260206004820152600660248201526510b7bbb732b960d11b6044820152606401610910565b600280549115157501000000000000000000000000000000000000000000027fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff909216919091179055565b600080612f2984846137c5565b60600151949350505050565b6001546001600160a01b03163314612f785760405162461bcd60e51b815260206004820152600660248201526510b7bbb732b960d11b6044820152606401610910565b6002805495151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff90961695909517909455600592909255600655600355600455565b600080805b835181101561302d57600061300586868481518110612ff857612ff8614a2f565b60200260200101516137c5565b90508060600151836130179190614ad0565b925050808061302590614a77565b915050612fd7565b509392505050565b6009602090815260009182526040918290208054600182015484519384019094526002820154835260038201546004830180546001600160a01b039093169594939192613081906148e7565b80601f01602080910402602001604051908101604052809291908181526020018280546130ad906148e7565b80156130fa5780601f106130cf576101008083540402835291602001916130fa565b820191906000526020600020905b8154815290600101906020018083116130dd57829003601f168201915b5050505050908060050154908060060154905087565b6001546001600160a01b031633146131535760405162461bcd60e51b815260206004820152600660248201526510b7bbb732b960d11b6044820152606401610910565b6001600160a01b038216156131805760015461317c906001600160a01b038481169116836133c7565b5050565b6001546040516000916001600160a01b03169083908381818185875af1925050503d80600081146131cd576040519150601f19603f3d011682016040523d82523d6000602084013e6131d2565b606091505b505090508061320c5760405162461bcd60e51b815260206004820152600660248201526511985a5b195960d21b6044820152606401610910565b505050565b6132dc604051806102c0016040528060608152602001606081526020016060815260200160608152602001606081526020016060815260200160608152602001606081526020016060815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160001515815260200160008152602001600015158152602001600081526020016060815260200160008152602001600015158152602001600081525090565b6010546040517f1ebfefab0000000000000000000000000000000000000000000000000000000081526001600160a01b03858116600483015260248201859052909116908190631ebfefab90604401600060405180830381865afa158015613348573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611a719190810190614def565b8054806133bf5760405162461bcd60e51b815260206004820152601b60248201527f436f756e7465723a2064656372656d656e74206f766572666c6f7700000000006044820152606401610910565b600019019055565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905261320c908490613a1f565b6010546040517f7071a8250000000000000000000000000000000000000000000000000000000081526001600160a01b03909116908190637071a8259061349c908a908a908a908a908a908a9060040161505b565b600060405180830381600087803b1580156134b657600080fd5b505af11580156134ca573d6000803e3d6000fd5b5050505050505050505050565b81518151600091849184919081146134f55760009350505050611a75565b60005b8181101561359c5782818151811061351257613512614a2f565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191684828151811061355157613551614a2f565b01602001517fff00000000000000000000000000000000000000000000000000000000000000161461358a576000945050505050611a75565b8061359481614a77565b9150506134f8565b5060019695505050505050565b6001600160a01b038082166000908152600f60205260408082205481517ffeaf968c0000000000000000000000000000000000000000000000000000000081529151929316918391839163feaf968c9160048082019260a0929091908290030181865afa15801561361e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061364291906150ca565b509193506012925050506001600160a01b038516156136c9576000859050806001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561369e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136c2919061511a565b60ff169150505b6000826136d783600a615221565b6136e1908961522d565b6136eb91906152e9565b979650505050505050565b60008061370384846137c5565b8051909150156137255761372560088461010001516040516118709190614a45565b806020015115613752576001600160a01b0384166000908152600960205260409020600201805460010190555b8060400151156137ba576101208301516001600160a01b03166000908152600a60205260409020600301805460010190556101208301516001600160a01b039081166000908152600c60209081526040808320938816835292905220805460ff191660011790555b606001519392505050565b604080516080810182526000808252602080830182905282840182905260608301829052601054845180860186528083018481526001600160a01b038981168084526101208a015182168752600c86528887209087529094528685205460ff1615159052610100870151955194959290911693909291849163e1a3195d918591600d9161385191614a45565b90815260200160405180910390208860e001516040516138719190614a45565b908152604051908190036020018120546101008a015160ff9091169160089161389991614a45565b9081526020016040518091039020600e60008b61014001516001600160a01b03166001600160a01b031681526020019081526020016000208a60e001516040516138e39190614a45565b908152602001604051809103902060009054906101000a900460ff16600960008c61014001516001600160a01b03166001600160a01b03168152602001908152602001600020600b60008d61012001516001600160a01b03166001600160a01b031681526020019081526020016000208c60e001516040516139659190614a45565b908152602001604051809103902060009054906101000a900460ff16600a60008e61012001516001600160a01b03166001600160a01b031681526020019081526020016000208d61012001516040518963ffffffff1660e01b81526004016139d4989796959493929190615412565b608060405180830381865afa1580156139f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a159190615524565b9695505050505050565b6000613a74826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316613b049092919063ffffffff16565b80519091501561320c5780806020019051810190613a929190614ab3565b61320c5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610910565b6060613b138484600085613b1d565b90505b9392505050565b606082471015613b955760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610910565b6001600160a01b0385163b613bec5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610910565b600080866001600160a01b03168587604051613c089190614a45565b60006040518083038185875af1925050503d8060008114613c45576040519150601f19603f3d011682016040523d82523d6000602084013e613c4a565b606091505b50915091506136eb82828660608315613c64575081613b16565b825115613c745782518084602001fd5b8160405162461bcd60e51b815260040161091091906155a2565b6040518060e0016040528060006001600160a01b0316815260200160008152602001613cc66040518060200160405280600081525090565b8152602001600081526020016060815260200160008152602001600081525090565b6040518060c0016040528060008152602001613cc66040518060200160405280600081525090565b6040518060e0016040528060006001600160a01b031681526020016000815260200160008152602001613d4f6040518060200160405280600081525090565b81526020016000815260200160008152602001600081525090565b6040518060a0016040528060008152602001613d4f6040518060200160405280600081525090565b6001600160a01b0381168114613da757600080fd5b50565b8035613db581613d92565b919050565b634e487b7160e01b600052604160045260246000fd5b6040516102c0810167ffffffffffffffff81118282101715613df457613df4613dba565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715613e2357613e23613dba565b604052919050565b600067ffffffffffffffff821115613e4557613e45613dba565b50601f01601f191660200190565b600082601f830112613e6457600080fd5b8135613e77613e7282613e2b565b613dfa565b818152846020838601011115613e8c57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215613ebc57600080fd5b8235613ec781613d92565b9150602083013567ffffffffffffffff811115613ee357600080fd5b613eef85828601613e53565b9150509250929050565b600067ffffffffffffffff821115613f1357613f13613dba565b5060051b60200190565b600082601f830112613f2e57600080fd5b81356020613f3e613e7283613ef9565b82815260059290921b84018101918181019086841115613f5d57600080fd5b8286015b84811015613f9d57803567ffffffffffffffff811115613f815760008081fd5b613f8f8986838b0101613e53565b845250918301918301613f61565b509695505050505050565b600080600080600080600060e0888a031215613fc357600080fd5b8735613fce81613d92565b96506020880135955060408801359450606088013593506080880135925060a088013567ffffffffffffffff8082111561400757600080fd5b6140138b838c01613f1d565b935060c08a013591508082111561402957600080fd5b506140368a828b01613f1d565b91505092959891949750929550565b600080600080600080600060e0888a03121561406057600080fd5b873567ffffffffffffffff8082111561407857600080fd5b6140848b838c01613e53565b985060208a0135975060408a0135965060608a0135955060808a0135945060a08a013591508082111561400757600080fd5b6000602082840312156140c857600080fd5b8135613b1681613d92565b6000806000606084860312156140e857600080fd5b83356140f381613d92565b95602085013595506040909401359392505050565b60006020828403121561411a57600080fd5b813567ffffffffffffffff81111561413157600080fd5b611a7184828501613e53565b60005b83811015614158578181015183820152602001614140565b83811115614167576000848401525b50505050565b6000815180845261418581602086016020860161413d565b601f01601f19169290920160200192915050565b8681528551602082015284604082015260c0606082015260006141bf60c083018661416d565b60808301949094525060a00152949350505050565b600080600080600080600080610100898b0312156141f157600080fd5b88356141fc81613d92565b97506020890135965060408901359550606089013594506080890135935060a0890135925060c089013567ffffffffffffffff8082111561423c57600080fd5b6142488c838d01613f1d565b935060e08b013591508082111561425e57600080fd5b5061426b8b828c01613f1d565b9150509295985092959890939650565b8015158114613da757600080fd5b8035613db58161427b565b60006102c082840312156142a757600080fd5b6142af613dd0565b9050813567ffffffffffffffff808211156142c957600080fd5b6142d585838601613e53565b835260208401359150808211156142eb57600080fd5b6142f785838601613e53565b6020840152604084013591508082111561431057600080fd5b61431c85838601613e53565b6040840152606084013591508082111561433557600080fd5b61434185838601613e53565b6060840152608084013591508082111561435a57600080fd5b61436685838601613e53565b608084015260a084013591508082111561437f57600080fd5b61438b85838601613e53565b60a084015260c08401359150808211156143a457600080fd5b6143b085838601613e53565b60c084015260e08401359150808211156143c957600080fd5b6143d585838601613e53565b60e0840152610100915081840135818111156143f057600080fd5b6143fc86828701613e53565b83850152506101209150614411828501613daa565b828401526101409150614425828501613daa565b828401526101609150614439828501613daa565b9183019190915261018083810135908301526101a080840135908301526101c090614465828501614289565b828401526101e0915081840135828401526102009150614486828501614289565b8284015261022091508184013582840152610240915081840135818111156144ad57600080fd5b6144b986828701613e53565b838501525050506102608083013581830152506102806144da818401614289565b81830152506102a080830135818301525092915050565b60008060006060848603121561450657600080fd5b83359250602084013561451881613d92565b9150604084013567ffffffffffffffff81111561453457600080fd5b61454086828701614294565b9150509250925092565b6000806040838503121561455d57600080fd5b82359150602083013567ffffffffffffffff811115613ee357600080fd5b6000806040838503121561458e57600080fd5b823561459981613d92565b915060208301356145a981613d92565b809150509250929050565b6000602082840312156145c657600080fd5b5035919050565b600080604083850312156145e057600080fd5b82359150602083013567ffffffffffffffff8111156145fe57600080fd5b613eef85828601614294565b600080600080600060a0868803121561462257600080fd5b85359450602086013593506040860135925060608601359150608086013567ffffffffffffffff81111561465557600080fd5b61466188828901613e53565b9150509295509295909350565b600082601f83011261467f57600080fd5b8135602061468f613e7283613ef9565b82815260059290921b840181019181810190868411156146ae57600080fd5b8286015b84811015613f9d57803567ffffffffffffffff8111156146d25760008081fd5b6146e08986838b0101614294565b8452509183019183016146b2565b6000806040838503121561470157600080fd5b823567ffffffffffffffff81111561471857600080fd5b6147248582860161466e565b92505060208301356145a981613d92565b6000806040838503121561474857600080fd5b823567ffffffffffffffff8082111561476057600080fd5b61476c86838701613e53565b9350602085013591508082111561478257600080fd5b50613eef85828601613e53565b6000602082840312156147a157600080fd5b8135613b168161427b565b600080604083850312156147bf57600080fd5b82356147ca81613d92565b9150602083013567ffffffffffffffff8111156145fe57600080fd5b600080600080600060a086880312156147fe57600080fd5b85356148098161427b565b97602087013597506040870135966060810135965060800135945092505050565b6000806040838503121561483d57600080fd5b823561484881613d92565b9150602083013567ffffffffffffffff81111561486457600080fd5b613eef8582860161466e565b6001600160a01b03881681528660208201528551604082015284606082015260e0608082015260006148a560e083018661416d565b60a08301949094525060c0015295945050505050565b600080604083850312156148ce57600080fd5b82356148d981613d92565b946020939093013593505050565b600181811c908216806148fb57607f821691505b60208210810361491b57634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111561320c57600081815260208120601f850160051c810160208610156149485750805b601f850160051c820191505b8181101561496757828155600101614954565b505050505050565b815167ffffffffffffffff81111561498957614989613dba565b61499d8161499784546148e7565b84614921565b602080601f8311600181146149d257600084156149ba5750858301515b600019600386901b1c1916600185901b178555614967565b600085815260208120601f198616915b82811015614a01578886015182559484019460019091019084016149e2565b5085821015614a1f5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052603260045260246000fd5b60008251614a5781846020870161413d565b9190910192915050565b634e487b7160e01b600052601160045260246000fd5b60006000198203614a8a57614a8a614a61565b5060010190565b600082821015614aa357614aa3614a61565b500390565b8051613db58161427b565b600060208284031215614ac557600080fd5b8151613b168161427b565b60008219821115614ae357614ae3614a61565b500190565b6000816000190483118215151615614b0257614b02614a61565b500290565b634e487b7160e01b600052601260045260246000fd5b600082614b2c57614b2c614b07565b500490565b6001600160a01b0384168152606060208201526000614b53606083018561416d565b8281036040840152613a15818561416d565b600060208284031215614b7757600080fd5b5051919050565b60006102c08251818552614b948286018261416d565b91505060208301518482036020860152614bae828261416d565b91505060408301518482036040860152614bc8828261416d565b91505060608301518482036060860152614be2828261416d565b91505060808301518482036080860152614bfc828261416d565b91505060a083015184820360a0860152614c16828261416d565b91505060c083015184820360c0860152614c30828261416d565b91505060e083015184820360e0860152614c4a828261416d565b9150506101008084015185830382870152614c65838261416d565b9250505061012080840151614c84828701826001600160a01b03169052565b5050610140838101516001600160a01b0390811691860191909152610160808501519091169085015261018080840151908501526101a080840151908501526101c0808401511515908501526101e080840151908501526102008084015115159085015261022080840151908501526102408084015185830382870152614d0b838261416d565b9250505061026080840151818601525061028080840151614d2f8287018215159052565b50506102a0928301519390920192909252919050565b604081526000614d586040830184614b7e565b8281036020840152600381527f627579000000000000000000000000000000000000000000000000000000000060208201526040810191505092915050565b600082601f830112614da857600080fd5b8151614db6613e7282613e2b565b818152846020838601011115614dcb57600080fd5b614ddc82602083016020870161413d565b949350505050565b8051613db581613d92565b600060208284031215614e0157600080fd5b815167ffffffffffffffff80821115614e1957600080fd5b908301906102c08286031215614e2e57600080fd5b614e36613dd0565b825182811115614e4557600080fd5b614e5187828601614d97565b825250602083015182811115614e6657600080fd5b614e7287828601614d97565b602083015250604083015182811115614e8a57600080fd5b614e9687828601614d97565b604083015250606083015182811115614eae57600080fd5b614eba87828601614d97565b606083015250608083015182811115614ed257600080fd5b614ede87828601614d97565b60808301525060a083015182811115614ef657600080fd5b614f0287828601614d97565b60a08301525060c083015182811115614f1a57600080fd5b614f2687828601614d97565b60c08301525060e083015182811115614f3e57600080fd5b614f4a87828601614d97565b60e0830152506101008084015183811115614f6457600080fd5b614f7088828701614d97565b828401525050610120614f84818501614de4565b90820152610140614f96848201614de4565b90820152610160614fa8848201614de4565b9082015261018083810151908201526101a080840151908201526101c0614fd0818501614aa8565b908201526101e08381015190820152610200614fed818501614aa8565b908201526102208381015190820152610240808401518381111561501057600080fd5b61501c88828701614d97565b82840152505061026091508183015182820152610280915061503f828401614aa8565b918101919091526102a091820151918101919091529392505050565b86815260c06020820152600061507460c0830188614b7e565b82810360408401526150868188614b7e565b6001600160a01b0396909616606084015250509115156080830152151560a0909101529392505050565b805169ffffffffffffffffffff81168114613db557600080fd5b600080600080600060a086880312156150e257600080fd5b6150eb866150b0565b945060208601519350604086015192506060860151915061510e608087016150b0565b90509295509295909350565b60006020828403121561512c57600080fd5b815160ff81168114613b1657600080fd5b600181815b8085111561517857816000190482111561515e5761515e614a61565b8085161561516b57918102915b93841c9390800290615142565b509250929050565b60008261518f57506001611a75565b8161519c57506000611a75565b81600181146151b257600281146151bc576151d8565b6001915050611a75565b60ff8411156151cd576151cd614a61565b50506001821b611a75565b5060208310610133831016604e8410600b84101617156151fb575081810a611a75565b615205838361513d565b806000190482111561521957615219614a61565b029392505050565b6000613b168383615180565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60008413600084138583048511828216161561526e5761526e614a61565b7f800000000000000000000000000000000000000000000000000000000000000060008712868205881281841616156152a9576152a9614a61565b600087129250878205871284841616156152c5576152c5614a61565b878505871281841616156152db576152db614a61565b505050929093029392505050565b6000826152f8576152f8614b07565b60001983147f80000000000000000000000000000000000000000000000000000000000000008314161561532e5761532e614a61565b500590565b60008154615340816148e7565b80855260206001838116801561535d5760018114615377576153a5565b60ff198516838901528284151560051b89010195506153a5565b866000528260002060005b8581101561539d5781548a8201860152908301908401615382565b890184019650505b505050505092915050565b6001600160a01b03815416825260018101546020830152600281015460408301526003810154606083015260e0608083015260006153f460e0840160048401615333565b600583015460a0850152600683015460c08501528091505092915050565b60006101e06001600160a01b038b5116835260208b0151151560208401528915156040840152806060840152885481840152506001880154610200830152600288015461022083015260c06102408301526154746102a0830160038a01615333565b60048901546102608401526005890154610280840152871515608084015282810360a08401526154a481886153b0565b9150506154b560c083018615159052565b83546001600160a01b031660e08301526001840154610100830152600284015461012083015260038401546101408301526004840154610160830152600584015461018083015260068401546101a08301526001600160a01b0383166101c08301529998505050505050505050565b60006080828403121561553657600080fd5b6040516080810181811067ffffffffffffffff8211171561555957615559613dba565b60405282516155678161427b565b815260208301516155778161427b565b6020820152604083015161558a8161427b565b60408201526060928301519281019290925250919050565b602081526000613b16602083018461416d56fea2646970667358221220e1ab597239476fd8612cb204f5f85da048993e44148882d3796f5d53d76817b164736f6c634300080f0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000d5d2e66f96a167c15610f637d67e6392f5a0df36000000000000000000000000160f5ffdde509aaf271e93a9b675c09e27580330
-----Decoded View---------------
Arg [0] : _discountContract (address): 0xd5d2E66F96A167c15610f637D67e6392f5A0DF36
Arg [1] : _nftContract (address): 0x160f5fFDDe509aAF271E93a9B675c09E27580330
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000d5d2e66f96a167c15610f637d67e6392f5a0df36
Arg [1] : 000000000000000000000000160f5ffdde509aaf271e93a9b675c09e27580330
Deployed Bytecode Sourcemap
1755:50055:21:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6005:73;;;;;;;;;;-1:-1:-1;6005:73:21;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2543:14:25;;2536:22;2518:41;;2506:2;2491:18;6005:73:21;;;;;;;;30513:730;;;;;;;;;;-1:-1:-1;30513:730:21;;;;;:::i;:::-;;:::i;:::-;;29079:732;;;;;;;;;;-1:-1:-1;29079:732:21;;;;;:::i;:::-;;:::i;50752:140::-;;;;;;;;;;-1:-1:-1;50752:140:21;;;;;:::i;:::-;;:::i;44228:1521::-;;;;;;;;;;-1:-1:-1;44228:1521:21;;;;;:::i;:::-;;:::i;4893:52::-;;;;;;;;;;-1:-1:-1;4893:52:21;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;:::i;27553:858::-;;;;;;;;;;-1:-1:-1;27553:858:21;;;;;:::i;:::-;;:::i;4792:40::-;;;;;;;;;;-1:-1:-1;4792:40:21;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9372:25:25;;;9433:13;;9428:2;9413:18;;9406:41;9463:18;;;9456:34;;;;9521:2;9506:18;;9499:34;9564:3;9549:19;;9542:35;9359:3;9344:19;4792:40:21;9063:520:25;2535:23:21;;;;;;;;;;-1:-1:-1;2535:23:21;;;;-1:-1:-1;;;;;2535:23:21;;;;;;-1:-1:-1;;;;;9884:55:25;;;9866:74;;9854:2;9839:18;2535:23:21;9720:226:25;5132:55:21;;;;;;;;;;-1:-1:-1;5132:55:21;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;5132:55:21;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;10334:55:25;;;10316:74;;10421:2;10406:18;;10399:34;;;;10449:18;;;10442:34;;;;10512:13;;10507:2;10492:18;;10485:41;10557:3;10542:19;;10535:35;10601:3;10586:19;;10579:35;10645:3;10630:19;;10623:35;10303:3;10288:19;5132:55:21;9951:713:25;41106:2894:21;;;;;;:::i;:::-;;:::i;50898:278::-;;;;;;;;;;-1:-1:-1;50898:278:21;;;;;:::i;:::-;;:::i;35503:217::-;;;;;;;;;;-1:-1:-1;35503:217:21;;;;;:::i;:::-;;:::i;:::-;;;15183:25:25;;;15171:2;15156:18;35503:217:21;15037:177:25;5328:71:21;;;;;;;;;;-1:-1:-1;5328:71:21;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;24570:113;;;;;;;;;;-1:-1:-1;24570:113:21;;;;;:::i;:::-;;:::i;5580:70::-;;;;;;;;;;-1:-1:-1;5580:70:21;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;2639:27;;;;;;;;;;-1:-1:-1;2639:27:21;;;;;;;;;;;2821;;;;;;;;;;;;;;;;2461:20;;;;;;;;;;-1:-1:-1;2461:20:21;;;;-1:-1:-1;;;;;2461:20:21;;;46046:1892;;;;;;;;;;-1:-1:-1;46046:1892:21;;;;;:::i;:::-;;:::i;2968:24::-;;;;;;;;;;;;;;;;48187:2048;;;;;;:::i;:::-;;:::i;2725:30::-;;;;;;;;;;-1:-1:-1;2725:30:21;;;;;;;;;;;26343:361;;;;;;;;;;-1:-1:-1;26343:361:21;;;;;:::i;:::-;;:::i;31525:2875::-;;;;;;:::i;:::-;;:::i;6146:45::-;;;;;;;;;;-1:-1:-1;6146:45:21;;;;;:::i;:::-;;;;;;;;;;;;-1:-1:-1;;;;;6146:45:21;;;5790:69;;;;;;;;;;-1:-1:-1;5790:69:21;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;25773:97;;;;;;;;;;-1:-1:-1;25773:97:21;;;;;:::i;:::-;;:::i;6429:58::-;;;;;;;;;;-1:-1:-1;6429:58:21;;;;;:::i;:::-;;;;;;;;;;;;;;3040:24;;;;;;;;;;;;;;;;37461:356;;;;;;;;;;-1:-1:-1;37461:356:21;;;;;:::i;:::-;;:::i;25179:368::-;;;;;;;;;;-1:-1:-1;25179:368:21;;;;;:::i;:::-;;:::i;38033:480::-;;;;;;;;;;-1:-1:-1;38033:480:21;;;;;:::i;:::-;;:::i;5010:60::-;;;;;;;;;;-1:-1:-1;5010:60:21;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;;:::i;50447:299::-;;;;;;;;;;-1:-1:-1;50447:299:21;;;;;:::i;:::-;;:::i;2914:29::-;;;;;;;;;;;;;;;;30513:730;24153:5;;-1:-1:-1;;;;;24153:5:21;24138:10;24130:28;24122:47;;;;-1:-1:-1;;;24122:47:21;;21857:2:25;24122:47:21;;;21839:21:25;21896:1;21876:18;;;21869:29;-1:-1:-1;;;21914:18:25;;;21907:36;21960:18;;24122:47:21;;;;;;;;;30775:25:::1;;:::i;:::-;30810:6;::::0;;::::1;:12:::0;;;30832:9:::1;::::0;::::1;:18:::0;;;30860:10:::1;::::0;::::1;:20:::0;;;30890:12:::1;::::0;::::1;:24:::0;;;-1:-1:-1;;;;;30924:24:21;;::::1;-1:-1:-1::0;30924:24:21;;;:17:::1;:24:::0;;;;;;;;:29;;;;-1:-1:-1;;30924:29:21::1;::::0;::::1;::::0;;;::::1;::::0;;;;-1:-1:-1;30924:29:21;::::1;::::0;;;::::1;::::0;;::::1;::::0;::::1;::::0;;;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;30810:6;;30924:24;:29:::1;::::0;::::1;::::0;::::1;::::0;;::::1;:::i;:::-;-1:-1:-1::0;30924:29:21::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;;::::1;::::0;-1:-1:-1;30964:128:21::1;30988:12;:19;30984:1;:23;30964:128;;;-1:-1:-1::0;;;;;31028:29:21;::::1;;::::0;;;:22:::1;:29;::::0;;;;31058:15;;31077:4:::1;::::0;31028:29;31058:12;;31071:1;;31058:15;::::1;;;;;:::i;:::-;;;;;;;31028:46;;;;;;:::i;:::-;::::0;;;::::1;::::0;;;;;::::1;::::0;;;:53;;;::::1;;-1:-1:-1::0;;31028:53:21;;::::1;::::0;;;::::1;::::0;;31009:3;::::1;::::0;::::1;:::i;:::-;;;;30964:128;;;;31107:9;31102:135;31126:15;:22;31122:1;:26;31102:135;;;-1:-1:-1::0;;;;;31169:29:21;::::1;31221:5;31169:29:::0;;;:22:::1;:29;::::0;;;;31199:18;;:15;;31215:1;;31199:18;::::1;;;;;:::i;:::-;;;;;;;31169:49;;;;;;:::i;:::-;::::0;;;::::1;::::0;;;;;::::1;::::0;;;:57;;;::::1;;-1:-1:-1::0;;31169:57:21;;::::1;::::0;;;::::1;::::0;;31150:3;::::1;::::0;::::1;:::i;:::-;;;;31102:135;;;;30765:478;30513:730:::0;;;;;;;:::o;29079:732::-;24153:5;;-1:-1:-1;;;;;24153:5:21;24138:10;24130:28;24122:47;;;;-1:-1:-1;;;24122:47:21;;21857:2:25;24122:47:21;;;21839:21:25;21896:1;21876:18;;;21869:29;-1:-1:-1;;;21914:18:25;;;21907:36;21960:18;;24122:47:21;21655:329:25;24122:47:21;29349:22:::1;;:::i;:::-;29381:13:::0;;;29404:9:::1;::::0;;::::1;:19:::0;;;29433:10:::1;::::0;::::1;:21:::0;;;29464:12:::1;::::0;::::1;:25:::0;;;29499:20;29381:2;;29499:13:::1;::::0;:20:::1;::::0;29513:5;;29499:20:::1;:::i;:::-;::::0;;;::::1;::::0;;::::1;::::0;;;;;;;;:25;;;;;;::::1;::::0;;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;:::i;:::-;-1:-1:-1::0;29499:25:21::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;;::::1;::::0;-1:-1:-1;29535:127:21::1;29559:13;:20;29555:1;:24;29535:127;;;29647:4;29600:19;29620:5;29600:26;;;;;;:::i;:::-;;;;;;;;;;;;;29627:13;29641:1;29627:16;;;;;;;;:::i;:::-;;;;;;;29600:44;;;;;;:::i;:::-;::::0;;;::::1;::::0;;;;;::::1;::::0;;;:51;;;::::1;;-1:-1:-1::0;;29600:51:21;;::::1;::::0;;;::::1;::::0;;29581:3;::::1;::::0;::::1;:::i;:::-;;;;29535:127;;;;29676:9;29671:134;29695:16;:23;29691:1;:27;29671:134;;;29789:5;29739:19;29759:5;29739:26;;;;;;:::i;:::-;;;;;;;;;;;;;29766:16;29783:1;29766:19;;;;;;;;:::i;:::-;;;;;;;29739:47;;;;;;:::i;:::-;::::0;;;::::1;::::0;;;;;::::1;::::0;;;:55;;;::::1;;-1:-1:-1::0;;29739:55:21;;::::1;::::0;;;::::1;::::0;;29720:3;::::1;::::0;::::1;:::i;:::-;;;;29671:134;;50752:140:::0;24153:5;;-1:-1:-1;;;;;24153:5:21;24138:10;24130:28;24122:47;;;;-1:-1:-1;;;24122:47:21;;21857:2:25;24122:47:21;;;21839:21:25;21896:1;21876:18;;;21869:29;-1:-1:-1;;;21914:18:25;;;21907:36;21960:18;;24122:47:21;21655:329:25;24122:47:21;50816:8:::1;:20:::0;;-1:-1:-1;;50816:20:21::1;-1:-1:-1::0;;;;;50816:20:21;::::1;::::0;;::::1;::::0;;;50851:34:::1;::::0;9866:74:25;;;50863:10:21::1;::::0;50851:34:::1;::::0;9854:2:25;9839:18;50851:34:21::1;;;;;;;50752:140:::0;:::o;44228:1521::-;24153:5;;-1:-1:-1;;;;;24153:5:21;24138:10;24130:28;24122:47;;;;-1:-1:-1;;;24122:47:21;;21857:2:25;24122:47:21;;;21839:21:25;21896:1;21876:18;;;21869:29;-1:-1:-1;;;21914:18:25;;;21907:36;21960:18;;24122:47:21;21655:329:25;24122:47:21;1744:1:2::1;2325:7;;:19:::0;2317:63:::1;;;::::0;-1:-1:-1;;;2317:63:2;;25875:2:25;2317:63:2::1;::::0;::::1;25857:21:25::0;25914:2;25894:18;;;25887:30;25953:33;25933:18;;;25926:61;26004:18;;2317:63:2::1;25673:355:25::0;2317:63:2::1;1744:1;2455:7;:18:::0;;;44398:35:21::2;44410:6:::0;44418:14;44398:11:::2;:35::i;:::-;44371:62;;44493:7;44464:8;:25;;;:36;;44443:112;;;::::0;-1:-1:-1;;;44443:112:21;;26235:2:25;44443:112:21::2;::::0;::::2;26217:21:25::0;26274:2;26254:18;;;26247:30;26313:31;26293:18;;;26286:59;26362:18;;44443:112:21::2;26033:353:25::0;44443:112:21::2;44574:8;:18;;;44573:19;44565:49;;;::::0;-1:-1:-1;;;44565:49:21;;26593:2:25;44565:49:21::2;::::0;::::2;26575:21:25::0;26632:2;26612:18;;;26605:30;26671:19;26651:18;;;26644:47;26708:18;;44565:49:21::2;26391:341:25::0;44565:49:21::2;44689:11;::::0;44727:14:::2;::::0;::::2;::::0;44711:31:::2;::::0;;;;::::2;::::0;::::2;15183:25:25::0;;;;-1:-1:-1;;;;;44689:11:21;;::::2;::::0;;;44711:15:::2;::::0;15156:18:25;;44711:31:21::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;44752:41;:7;44760:8;:15;;;44752:24;;;;;;:::i;:::-;;;;;;;;;;;;;:29;;:39;:41::i;:::-;44808:17;::::0;::::2;::::0;-1:-1:-1;;;;;44808:31:21::2;::::0;44804:863:::2;;44855:119;44919:8;:15;;;44953:7;44862:8;:17;;;-1:-1:-1::0;;;;;44855:38:21::2;;;:119;;;;;:::i;:::-;44988:17;::::0;::::2;:27:::0;;;45050:4:::2;45029:18;::::0;::::2;:25:::0;;;45181:15:::2;::::0;::::2;::::0;45068:187:::2;::::0;45097:14;;44988:8;;;;45181:15;45029:25;;45068:11:::2;:187::i;:::-;44804:863;;;45287:7;45308:6;-1:-1:-1::0;;;;;45300:20:21::2;45328:7;45300:40;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;45286:54;;;45362:2;45354:21;;;::::0;-1:-1:-1;;;45354:21:21;;27149:2:25;45354:21:21::2;::::0;::::2;27131::25::0;27188:1;27168:18;;;27161:29;-1:-1:-1;;;27206:18:25;;;27199:36;27252:18;;45354:21:21::2;26947:329:25::0;45354:21:21::2;45389:17;::::0;::::2;:27:::0;;;45451:4:::2;45430:18;::::0;::::2;:25:::0;;;45582:15:::2;::::0;::::2;::::0;45469:187:::2;::::0;45498:14;;45389:8;;;;45582:15;45430:25;;45469:11:::2;:187::i;:::-;45272:395;44804:863;45691:6;-1:-1:-1::0;;;;;45681:61:21::2;;45699:7;45708:14;45724:8;:17;;;45681:61;;;;;;;27483:25:25::0;;;27539:2;27524:18;;27517:34;;;;-1:-1:-1;;;;;27587:55:25;27582:2;27567:18;;27560:83;27471:2;27456:18;;27281:368;45681:61:21::2;;;;;;;;-1:-1:-1::0;;1701:1:2::1;2628:7;:22:::0;-1:-1:-1;;;44228:1521:21:o;4893:52::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;27553:858::-;24153:5;;-1:-1:-1;;;;;24153:5:21;24138:10;24130:28;24122:47;;;;-1:-1:-1;;;24122:47:21;;21857:2:25;24122:47:21;;;21839:21:25;21896:1;21876:18;;;21869:29;-1:-1:-1;;;21914:18:25;;;21907:36;21960:18;;24122:47:21;21655:329:25;24122:47:21;27852:23:::1;;:::i;:::-;-1:-1:-1::0;;;;;27885:25:21;;::::1;::::0;;;27920:12:::1;::::0;;::::1;:25:::0;;;27955:6:::1;::::0;;::::1;:13:::0;;;27978:9:::1;::::0;::::1;:19:::0;;;28007:10:::1;::::0;::::1;:21:::0;;;28038:12:::1;::::0;::::1;:25:::0;;;-1:-1:-1;28073:30:21;;;:14:::1;:30:::0;;;;;;:35;;;;-1:-1:-1;;28073:35:21::1;::::0;::::1;::::0;;;::::1;::::0;;;;-1:-1:-1;28073:35:21;::::1;::::0;;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;;;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;;::::1;::::0;;::::1;::::0;;;;28119:135:::1;28143:12;:19;28139:1;:23;28119:135;;;-1:-1:-1::0;;;;;28183:36:21;::::1;;::::0;;;:20:::1;:36;::::0;;;;28220:15;;28239:4:::1;::::0;28183:36;28220:12;;28233:1;;28220:15;::::1;;;;;:::i;:::-;;;;;;;28183:53;;;;;;:::i;:::-;::::0;;;::::1;::::0;;;;;::::1;::::0;;;:60;;;::::1;;-1:-1:-1::0;;28183:60:21;;::::1;::::0;;;::::1;::::0;;28164:3;::::1;::::0;::::1;:::i;:::-;;;;28119:135;;;;28268:9;28263:142;28287:15;:22;28283:1;:26;28263:142;;;-1:-1:-1::0;;;;;28330:36:21;::::1;28389:5;28330:36:::0;;;:20:::1;:36;::::0;;;;28367:18;;:15;;28383:1;;28367:18;::::1;;;;;:::i;:::-;;;;;;;28330:56;;;;;;:::i;:::-;::::0;;;::::1;::::0;;;;;::::1;::::0;;;:64;;;::::1;;-1:-1:-1::0;;28330:64:21;;::::1;::::0;;;::::1;::::0;;28311:3;::::1;::::0;::::1;:::i;:::-;;;;28263:142;;;;27842:569;27553:858:::0;;;;;;;;:::o;41106:2894::-;1744:1:2;2325:7;;:19;2317:63;;;;-1:-1:-1;;;2317:63:2;;25875:2:25;2317:63:2;;;25857:21:25;25914:2;25894:18;;;25887:30;25953:33;25933:18;;;25926:61;26004:18;;2317:63:2;25673:355:25;2317:63:2;1744:1;2455:7;:18;;;41308:79:21::1;41333:16:::0;41363:14;41308:11:::1;:79::i;:::-;41419:18;::::0;::::1;::::0;41278:109;;-1:-1:-1;;;;;;41419:32:21::1;41441:10;41419:32;::::0;:55:::1;;-1:-1:-1::0;41469:5:21::1;::::0;-1:-1:-1;;;;;41469:5:21::1;41455:10;:19;41419:55;41398:123;;;::::0;-1:-1:-1;;;41398:123:21;;27856:2:25;41398:123:21::1;::::0;::::1;27838:21:25::0;27895:2;27875:18;;;27868:30;27934:23;27914:18;;;27907:51;27975:18;;41398:123:21::1;27654:345:25::0;41398:123:21::1;41540:11;:21;;;41539:22;41531:52;;;::::0;-1:-1:-1;;;41531:52:21;;26593:2:25;41531:52:21::1;::::0;::::1;26575:21:25::0;26632:2;26612:18;;;26605:30;26671:19;26651:18;;;26644:47;26708:18;;41531:52:21::1;26391:341:25::0;41531:52:21::1;41724:18;::::0;::::1;::::0;-1:-1:-1;;;;;41724:32:21::1;41746:10;41724:32;::::0;:55:::1;;-1:-1:-1::0;41774:5:21::1;::::0;-1:-1:-1;;;;;41774:5:21::1;41760:10;:19;41724:55;41723:128;;;;;41797:54;41811:12;:19;;;41832:11;:18;;;41797:13;:54::i;:::-;41796:55;41723:128;41706:2110;;;41967:7;41975:12;:19;;;41967:28;;;;;;:::i;:::-;;;;;;;;;;;;;:32;;;41901:43;:7;41909:12;:19;;;41901:28;;;;;;:::i;:::-;;;;;;;;;;;;;:33;;918:14:15::0;;827:112;41901:43:21::1;:98;41876:165;;;::::0;-1:-1:-1;;;41876:165:21;;28206:2:25;41876:165:21::1;::::0;::::1;28188:21:25::0;28245:1;28225:18;;;28218:29;28283:10;28263:18;;;28256:38;28311:18;;41876:165:21::1;28004:331:25::0;41876:165:21::1;42121:15;42080:7;42088:12;:19;;;42080:28;;;;;;:::i;:::-;;;;;;;;;;;;;:38;;;:56;42055:132;;;::::0;-1:-1:-1;;;42055:132:21;;28542:2:25;42055:132:21::1;::::0;::::1;28524:21:25::0;28581:2;28561:18;;;28554:30;28620:19;28600:18;;;28593:47;28657:18;;42055:132:21::1;28340:341:25::0;42055:132:21::1;42265:15;42226:7;42234:12;:19;;;42226:28;;;;;;:::i;:::-;;;;;;;;;;;;;:36;;;:54;42201:134;;;::::0;-1:-1:-1;;;42201:134:21;;28888:2:25;42201:134:21::1;::::0;::::1;28870:21:25::0;28927:2;28907:18;;;28900:30;28966:23;28946:18;;;28939:51;29007:18;;42201:134:21::1;28686:345:25::0;42201:134:21::1;42482:11;:21;;;42445:7;42453:12;:19;;;42445:28;;;;;;:::i;:::-;;;;;;;;;;;;;:34;;;:58;42441:1365;;;42523:28;42554:155;42628:11;:21;;;42591:7;42599:12;:19;;;42591:28;;;;;;:::i;:::-;;;;;;;;;;;;;:34;;;:58;;;;:::i;:::-;42671:11;:20;;;42554:15;:155::i;:::-;42731:20;::::0;::::1;::::0;42523:186;;-1:-1:-1;;;;;;42731:34:21::1;42727:576;;42835:20;42822:9;:33;;42789:141;;;::::0;-1:-1:-1;;;42789:141:21;;29368:2:25;42789:141:21::1;::::0;::::1;29350:21:25::0;29407:2;29387:18;;;29380:30;29446:27;29426:18;;;29419:55;29491:18;;42789:141:21::1;29166:349:25::0;42789:141:21::1;42727:576;;;43017:20;::::0;::::1;::::0;43010:209:::1;::::0;;;;43089:10:::1;43010:209;::::0;::::1;29783:34:25::0;43138:4:21::1;29833:18:25::0;;;29826:43;29885:18;;;29878:34;;;-1:-1:-1;;;;;43010:41:21;;::::1;::::0;::::1;::::0;29695:18:25;;43010:209:21::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;42977:307;;;::::0;-1:-1:-1;;;42977:307:21;;30512:2:25;42977:307:21::1;::::0;::::1;30494:21:25::0;30551:2;30531:18;;;30524:30;30590:17;30570:18;;;30563:45;30625:18;;42977:307:21::1;30310:339:25::0;42977:307:21::1;43387:45;:7;43395:12;:19;;;43387:28;;;;;;:::i;:::-;;;;;;;;;;;;;:33;;1032:19:15::0;;1050:1;1032:19;;;945:123;43387:45:21::1;43531:44;:7;43539:11;:18;;;43531:27;;;;;;:::i;:44::-;43617:7;43625:12;:19;;;43617:28;;;;;;:::i;:::-;::::0;;;::::1;::::0;;;;;::::1;::::0;;;:34:::1;;::::0;43593:21:::1;::::0;::::1;:58:::0;43720:28:::1;::::0;::::1;::::0;:71:::1;::::0;43771:20;;43720:71:::1;:::i;:::-;43669:28;::::0;::::1;:122:::0;-1:-1:-1;42441:1365:21::1;43825:168;43850:14;43878:12;43904:11;43929:16;43959:5;43978::::0;43825:11:::1;:168::i;:::-;-1:-1:-1::0;;1701:1:2;2628:7;:22;-1:-1:-1;;41106:2894:21:o;50898:278::-;24153:5;;-1:-1:-1;;;;;24153:5:21;24138:10;24130:28;24122:47;;;;-1:-1:-1;;;24122:47:21;;21857:2:25;24122:47:21;;;21839:21:25;21896:1;21876:18;;;21869:29;-1:-1:-1;;;21914:18:25;;;21907:36;21960:18;;24122:47:21;21655:329:25;24122:47:21;50987:8:::1;::::0;-1:-1:-1;;;;;50974:21:21;;::::1;50987:8:::0;::::1;50974:21;50966:47;;;::::0;-1:-1:-1;;;50966:47:21;;30989:2:25;50966:47:21::1;::::0;::::1;30971:21:25::0;31028:2;31008:18;;;31001:30;31067:15;31047:18;;;31040:43;31100:18;;50966:47:21::1;30787:337:25::0;50966:47:21::1;-1:-1:-1::0;;;;;51044:55:21;::::1;51057:42;51044:55:::0;51023:119:::1;;;::::0;-1:-1:-1;;;51023:119:21;;31331:2:25;51023:119:21::1;::::0;::::1;31313:21:25::0;31370:2;31350:18;;;31343:30;31409:19;31389:18;;;31382:47;31446:18;;51023:119:21::1;31129:341:25::0;51023:119:21::1;51152:5;:17:::0;;-1:-1:-1;;51152:17:21::1;-1:-1:-1::0;;;;;51152:17:21;;;::::1;::::0;;;::::1;::::0;;50898:278::o;35503:217::-;35606:7;35625:13;35641:7;35649;35641:16;;;;;;:::i;:::-;;;;;;;;;;;;;;:22;;;;-1:-1:-1;35710:3:21;35689:17;35697:9;35641:22;35689:17;:::i;:::-;35688:25;;;;:::i;:::-;35680:33;;:5;:33;:::i;:::-;35673:40;;;35503:217;;;;;:::o;24570:113::-;24153:5;;-1:-1:-1;;;;;24153:5:21;24138:10;24130:28;24122:47;;;;-1:-1:-1;;;24122:47:21;;21857:2:25;24122:47:21;;;21839:21:25;21896:1;21876:18;;;21869:29;-1:-1:-1;;;21914:18:25;;;21907:36;21960:18;;24122:47:21;21655:329:25;24122:47:21;-1:-1:-1;;;;;24650:18:21;;::::1;;::::0;;;:10:::1;:18;::::0;;;;:26;;-1:-1:-1;;24650:26:21::1;::::0;;;::::1;;::::0;;24570:113::o;46046:1892::-;1744:1:2;2325:7;;:19;2317:63;;;;-1:-1:-1;;;2317:63:2;;25875:2:25;2317:63:2;;;25857:21:25;25914:2;25894:18;;;25887:30;25953:33;25933:18;;;25926:61;26004:18;;2317:63:2;25673:355:25;2317:63:2;1744:1;2455:7;:18;;;46147:39:21::1;46159:10;46171:14:::0;46147:11:::1;:39::i;:::-;46204:15;::::0;::::1;::::0;46120:66;;-1:-1:-1;;;;;;46204:29:21::1;46223:10;46204:29;46196:61;;;::::0;-1:-1:-1;;;46196:61:21;;32224:2:25;46196:61:21::1;::::0;::::1;32206:21:25::0;32263:2;32243:18;;;32236:30;32302:21;32282:18;;;32275:49;32341:18;;46196:61:21::1;32022:343:25::0;46196:61:21::1;46275:15;::::0;;;::::1;;;46267:47;;;::::0;-1:-1:-1;;;46267:47:21;;32572:2:25;46267:47:21::1;::::0;::::1;32554:21:25::0;32611:2;32591:18;;;32584:30;32650:21;32630:18;;;32623:49;32689:18;;46267:47:21::1;32370:343:25::0;46267:47:21::1;46333:8;:18;;;46332:19;46324:49;;;::::0;-1:-1:-1;;;46324:49:21;;26593:2:25;46324:49:21::1;::::0;::::1;26575:21:25::0;26632:2;26612:18;;;26605:30;26671:19;26651:18;;;26644:47;26708:18;;46324:49:21::1;26391:341:25::0;46324:49:21::1;46392:8;:15;;;46391:16;46383:61;;;::::0;-1:-1:-1;;;46383:61:21;;32920:2:25;46383:61:21::1;::::0;::::1;32902:21:25::0;;;32939:18;;;32932:30;32998:34;32978:18;;;32971:62;33050:18;;46383:61:21::1;32718:356:25::0;46383:61:21::1;46510:15;46475:7;46483:8;:15;;;46475:24;;;;;;:::i;:::-;;;;;;;;;;;;;:32;;;:50;46454:124;;;::::0;-1:-1:-1;;;46454:124:21;;33281:2:25;46454:124:21::1;::::0;::::1;33263:21:25::0;33320:2;33300:18;;;33293:30;33359:29;33339:18;;;33332:57;33406:18;;46454:124:21::1;33079:351:25::0;46454:124:21::1;46588:21;46681:14;;46659:8;:17;;;46641:15;:35;;;;:::i;:::-;46613:12;;:64;;;;:::i;:::-;46612:83;;;;:::i;:::-;46588:107;;46729:3;46713:13;:19;46705:51;;;::::0;-1:-1:-1;;;46705:51:21;;32572:2:25;46705:51:21::1;::::0;::::1;32554:21:25::0;32611:2;32591:18;;;32584:30;32650:21;32630:18;;;32623:49;32689:18;;46705:51:21::1;32370:343:25::0;46705:51:21::1;46767:14;46871:3;46842:8;:25;;;46826:13;:41;;;;:::i;:::-;46825:49;;;;:::i;:::-;46784:8;:25;;;:91;;;;:::i;:::-;46950:11;::::0;46988:14:::1;::::0;::::1;::::0;46972:31:::1;::::0;;;;::::1;::::0;::::1;15183:25:25::0;;;;46767:108:21;;-1:-1:-1;;;;;;46950:11:21::1;::::0;;;46972:15:::1;::::0;15156:18:25;;46972:31:21::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;47013:41;:7;47021:8;:15;;;47013:24;;;;;;:::i;:41::-;47068:17;::::0;::::1;::::0;-1:-1:-1;;;;;47068:31:21::1;::::0;47064:868:::1;;47115:118;47179:8;:15;;;47213:6;47122:8;:17;;;-1:-1:-1::0;;;;;47115:38:21::1;;;:118;;;;;:::i;:::-;47247:17;::::0;::::1;:26:::0;;;47308:4:::1;47287:18;::::0;::::1;:25:::0;;;47439:15:::1;::::0;::::1;::::0;47326:187:::1;::::0;47355:14;;47247:8;;;;47439:15;47287:25;;47326:11:::1;:187::i;:::-;47064:868;;;47545:7;47566:8;:15;;;-1:-1:-1::0;;;;;47558:29:21::1;47595:6;47558:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;47544:62;;;47628:2;47620:21;;;::::0;-1:-1:-1;;;47620:21:21;;27149:2:25;47620:21:21::1;::::0;::::1;27131::25::0;27188:1;27168:18;;;27161:29;-1:-1:-1;;;27206:18:25;;;27199:36;27252:18;;47620:21:21::1;26947:329:25::0;47620:21:21::1;47655:17;::::0;::::1;:26:::0;;;47716:4:::1;47695:18;::::0;::::1;:25:::0;;;47847:15:::1;::::0;::::1;::::0;47734:187:::1;::::0;47763:14;;47655:8;;;;47847:15;47695:25;;47734:11:::1;:187::i;:::-;47530:402;47064:868;-1:-1:-1::0;;1701:1:2;2628:7;:22;-1:-1:-1;;;46046:1892:21:o;48187:2048::-;1744:1:2;2325:7;;:19;2317:63;;;;-1:-1:-1;;;2317:63:2;;25875:2:25;2317:63:2;;;25857:21:25;25914:2;25894:18;;;25887:30;25953:33;25933:18;;;25926:61;26004:18;;2317:63:2;25673:355:25;2317:63:2;1744:1;2455:7;:18;;;48376:19:21::1;::::0;::::1;::::0;48351:82:::1;::::0;48409:14;48351:11:::1;:82::i;:::-;48324:109;;48443:14;48483:8;:20;;;48475:45;;;::::0;-1:-1:-1;;;48475:45:21;;33637:2:25;48475:45:21::1;::::0;::::1;33619:21:25::0;33676:2;33656:18;;;33649:30;33715:14;33695:18;;;33688:42;33747:18;;48475:45:21::1;33435:336:25::0;48475:45:21::1;48538:18;::::0;;;::::1;;;48530:49;;;::::0;-1:-1:-1;;;48530:49:21;;33978:2:25;48530:49:21::1;::::0;::::1;33960:21:25::0;34017:2;33997:18;;;33990:30;34056:20;34036:18;;;34029:48;34094:18;;48530:49:21::1;33776:342:25::0;48530:49:21::1;48598:8;:18;;;48597:19;48589:49;;;::::0;-1:-1:-1;;;48589:49:21;;26593:2:25;48589:49:21::1;::::0;::::1;26575:21:25::0;26632:2;26612:18;;;26605:30;26671:19;26651:18;;;26644:47;26708:18;;48589:49:21::1;26391:341:25::0;48589:49:21::1;48669:51;48683:12;:19;;;48704:8;:15;;;48669:13;:51::i;:::-;48648:114;;;::::0;-1:-1:-1;;;48648:114:21;;34325:2:25;48648:114:21::1;::::0;::::1;34307:21:25::0;34364:2;34344:18;;;34337:30;34403:18;34383;;;34376:46;34439:18;;48648:114:21::1;34123:340:25::0;48648:114:21::1;48776:17;::::0;::::1;::::0;-1:-1:-1;;;;;48776:31:21::1;::::0;48772:1147:::1;;48855:8;:17;;;-1:-1:-1::0;;;;;48848:38:21::1;;48916:10;48957:4;49029:3;49016:9;;48993:8;:20;;;:32;;;;:::i;:::-;48992:40;;;;:::i;:::-;48848:203;::::0;;::::1;::::0;;;;;;-1:-1:-1;;;;;29801:15:25;;;48848:203:21::1;::::0;::::1;29783:34:25::0;29853:15;;;;29833:18;;;29826:43;29885:18;;;29878:34;29695:18;;48848:203:21::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;48823:277;;;::::0;-1:-1:-1;;;48823:277:21;;30512:2:25;48823:277:21::1;::::0;::::1;30494:21:25::0;30551:2;30531:18;;;30524:30;30590:17;30570:18;;;30563:45;30625:18;;48823:277:21::1;30310:339:25::0;48823:277:21::1;49146:8;:17;;;-1:-1:-1::0;;;;;49139:38:21::1;;49207:10;49248:8;:15;;;49435:3;49394:9;;49371:8;:20;;;:32;;;;:::i;:::-;49370:68;;;;:::i;:::-;49319:8;:20;;;:119;;;;:::i;:::-;49139:339;::::0;;::::1;::::0;;;;;;-1:-1:-1;;;;;29801:15:25;;;49139:339:21::1;::::0;::::1;29783:34:25::0;29853:15;;;;29833:18;;;29826:43;29885:18;;;29878:34;29695:18;;49139:339:21::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;49114:413;;;::::0;-1:-1:-1;;;49114:413:21;;30512:2:25;49114:413:21::1;::::0;::::1;30494:21:25::0;30551:2;30531:18;;;30524:30;30590:17;30570:18;;;30563:45;30625:18;;49114:413:21::1;30310:339:25::0;49114:413:21::1;-1:-1:-1::0;49553:4:21::1;48772:1147;;;49609:8;:20;;;49596:9;:33;49588:61;;;::::0;-1:-1:-1;;;49588:61:21;;34670:2:25;49588:61:21::1;::::0;::::1;34652:21:25::0;34709:2;34689:18;;;34682:30;34748:17;34728:18;;;34721:45;34783:18;;49588:61:21::1;34468:339:25::0;49588:61:21::1;49664:7;49677:8;:15;;;-1:-1:-1::0;;;;;49677:20:21::1;49822:3;49789:9;;49766:8;:20;;;:32;;;;:::i;:::-;49765:60;;;;:::i;:::-;49722:8;:20;;;:103;;;;:::i;:::-;49677:166;::::0;::::1;::::0;;;;;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;49663:180;;;49865:2;49857:21;;;::::0;-1:-1:-1;;;49857:21:21;;27149:2:25;49857:21:21::1;::::0;::::1;27131::25::0;27188:1;27168:18;;;27161:29;-1:-1:-1;;;27206:18:25;;;27199:36;27252:18;;49857:21:21::1;26947:329:25::0;49857:21:21::1;49904:4;49892:16;;49574:345;48772:1147;49932:9;49928:301;;;50001:10;49986:26;::::0;;;:14:::1;:26;::::0;;;;918:14:15;49957:208:21::1;::::0;50040:12:::1;50070:8;50096:10;50124:4;50146:5;49957:11;:208::i;:::-;50195:10;50180:26;::::0;;;:14:::1;:26;::::0;;;;1032:19:15;;1050:1;1032:19;;;50180:38:21::1;945:123:15::0;26343:361:21;24031:14;;26517:4;;;;24023:45;;;;-1:-1:-1;;;24023:45:21;;35014:2:25;24023:45:21;;;34996:21:25;35053:2;35033:18;;;35026:30;35092:16;35072:18;;;35065:44;35126:18;;24023:45:21;34812:338:25;24023:45:21;24153:5:::1;::::0;-1:-1:-1;;;;;24153:5:21::1;24138:10;24130:28;24122:47;;;::::0;-1:-1:-1;;;24122:47:21;;21857:2:25;24122:47:21::1;::::0;::::1;21839:21:25::0;21896:1;21876:18;;;21869:29;-1:-1:-1;;;21914:18:25;;;21907:36;21960:18;;24122:47:21::1;21655:329:25::0;24122:47:21::1;26543:15:::2;;:::i;:::-;26568:12:::0;;;26590:7:::2;::::0;;::::2;:16:::0;;;26616:9:::2;::::0;::::2;:20:::0;;;26646:11:::2;::::0;::::2;:24:::0;;;26680:13;26568:1;;26680:7:::2;::::0;:13:::2;::::0;26688:4;;26680:13:::2;:::i;:::-;::::0;;;::::2;::::0;;::::2;::::0;;;;;;;;:17;;;;;;::::2;::::0;;::::2;::::0;::::2;::::0;;::::2;::::0;::::2;::::0;::::2;::::0;::::2;::::0;::::2;::::0;::::2;::::0;::::2;::::0;::::2;::::0;;::::2;::::0;::::2;::::0;;::::2;::::0;-1:-1:-1;;;;;;;;26343:361:21:o;31525:2875::-;1744:1:2;2325:7;;:19;2317:63;;;;-1:-1:-1;;;2317:63:2;;25875:2:25;2317:63:2;;;25857:21:25;25914:2;25894:18;;;25887:30;25953:33;25933:18;;;25926:61;26004:18;;2317:63:2;25673:355:25;2317:63:2;1744:1;2455:7;:18;;;-1:-1:-1;;;;;31797:21:21;;::::1;::::0;;:10:::1;:21;::::0;;;;;2455:7:2;;;;31797:21:21::1;31789:67;;;::::0;-1:-1:-1;;;31789:67:21;;35357:2:25;31789:67:21::1;::::0;::::1;35339:21:25::0;35396:2;35376:18;;;35369:30;35435:21;35415:18;;;35408:49;35474:18;;31789:67:21::1;35155:343:25::0;31789:67:21::1;31872:9;31867:1746;31891:13;:20;31887:1;:24;31867:1746;;;32027:7;32035:13;32049:1;32035:16;;;;;;;;:::i;:::-;;;;;;;:23;;;32027:32;;;;;;:::i;:::-;;;;;;;;;;;;;:36;;;31957:47;:7;31965:13;31979:1;31965:16;;;;;;;;:::i;:::-;;;;;;;:23;;;31957:32;;;;;;:::i;:47::-;:106;31932:173;;;::::0;-1:-1:-1;;;31932:173:21;;28206:2:25;31932:173:21::1;::::0;::::1;28188:21:25::0;28245:1;28225:18;;;28218:29;28283:10;28263:18;;;28256:38;28311:18;;31932:173:21::1;28004:331:25::0;31932:173:21::1;32189:15;32144:7;32152:13;32166:1;32152:16;;;;;;;;:::i;:::-;;;;;;;:23;;;32144:32;;;;;;:::i;:::-;;;;;;;;;;;;;:42;;;:60;32119:136;;;::::0;-1:-1:-1;;;32119:136:21;;28542:2:25;32119:136:21::1;::::0;::::1;28524:21:25::0;28581:2;28561:18;;;28554:30;28620:19;28600:18;;;28593:47;28657:18;;32119:136:21::1;28340:341:25::0;32119:136:21::1;32337:15;32294:7;32302:13;32316:1;32302:16;;;;;;;;:::i;:::-;;;;;;;:23;;;32294:32;;;;;;:::i;:::-;;;;;;;;;;;;;:40;;;:58;32269:138;;;::::0;-1:-1:-1;;;32269:138:21;;28888:2:25;32269:138:21::1;::::0;::::1;28870:21:25::0;28927:2;28907:18;;;28900:30;28966:23;28946:18;;;28939:51;29007:18;;32269:138:21::1;28686:345:25::0;32269:138:21::1;32432:41;32444:10;32456:13;32470:1;32456:16;;;;;;;;:::i;:::-;;;;;;;32432:11;:41::i;:::-;32421:52;;32488:18;32509:43;32518:8;32528:13;32542:1;32528:16;;;;;;;;:::i;:::-;;;;;;;:23;;;32509:8;:43::i;:::-;32488:64:::0;-1:-1:-1;32566:19:21::1;32488:64:::0;32566:19;::::1;:::i;:::-;;;32625:10;32599:13;32613:1;32599:16;;;;;;;;:::i;:::-;;;;;;;:23;;:36;-1:-1:-1::0;;;;;32599:36:21::1;;;-1:-1:-1::0;;;;;32599:36:21::1;;;::::0;::::1;32678:10;32649:13;32663:1;32649:16;;;;;;;;:::i;:::-;;;;;;;:26;;:39;;;::::0;::::1;32738:84;32771:10;32799:9;32738:15;:84::i;:::-;32702:13;32716:1;32702:16;;;;;;;;:::i;:::-;;;;;;;:33;;:120;;;::::0;::::1;32864:15;32836:13;32850:1;32836:16;;;;;;;;:::i;:::-;;;;;;;:25;;:43;;;::::0;::::1;32921:9;32893:13;32907:1;32893:16;;;;;;;;:::i;:::-;;::::0;;::::1;::::0;;;;;;-1:-1:-1;;;;;32893:37:21;;::::1;:25;::::0;;::::1;:37:::0;32969:11:::1;::::0;33068:16;;32969:11;::::1;::::0;32944:12:::1;::::0;32969:11;;33011::::1;::::0;33040:10:::1;::::0;33068:13;;33082:1;;33068:16;::::1;;;;;:::i;:::-;;;;;;;:23;;;33109:13;33123:1;33109:16;;;;;;;;:::i;:::-;;;;;;;:23;;;33011:135;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;32995:151;;33185:5;33160:13;33174:1;33160:16;;;;;;;;:::i;:::-;;::::0;;::::1;::::0;;;;;;;:22:::1;;:30:::0;;;;33249:10:::1;33234:26;::::0;;;:14:::1;:26:::0;;;;;;918:14:15;33205:221:21::1;::::0;33288:13:::1;33302:1;33288:16;;;;;;;;:::i;:::-;;;;;;;33322:13;33336:1;33322:16;;;;;;;;:::i;:::-;;;;;;;33356:10;33384:5;33407::::0;33205:11:::1;:221::i;:::-;33440:49;:7;33448:13;33462:1;33448:16;;;;;;;;:::i;:::-;;;;;;;:23;;;33440:32;;;;;;:::i;:49::-;33518:10;33503:26;::::0;;;:14:::1;:26;::::0;;;;1032:19:15;;1050:1;1032:19;;;33566:10:21::1;-1:-1:-1::0;;;;;33560:42:21::1;;33578:13;33592:1;33578:16;;;;;;;;:::i;:::-;;;;;;;33560:42;;;;;;:::i;:::-;;;;;;;;31918:1695;;;31913:3;;;;;:::i;:::-;;;;31867:1746;;;;33636:33;33652:5;33659:9;33636:15;:33::i;:::-;33623:46;;33701:1;33688:10;:14;:28;;;-1:-1:-1::0;33706:10:21;;33688:28:::1;33680:48;;;::::0;-1:-1:-1;;;33680:48:21;;40008:2:25;33680:48:21::1;::::0;::::1;39990:21:25::0;40047:1;40027:18;;;40020:29;40085:9;40065:18;;;40058:37;40112:18;;33680:48:21::1;39806:330:25::0;33680:48:21::1;-1:-1:-1::0;;;;;33743:23:21;::::1;33739:588;;33803:10;33790:9;:23;;33782:49;;;::::0;-1:-1:-1;;;33782:49:21;;40343:2:25;33782:49:21::1;::::0;::::1;40325:21:25::0;40382:2;40362:18;;;40355:30;40421:15;40401:18;;;40394:43;40454:18;;33782:49:21::1;40141:337:25::0;33782:49:21::1;33861:10;33849:9;:22;33845:202;;;33892:7;33905:10;33928:22;33940:10:::0;33928:9:::1;:22;:::i;:::-;33905:88;::::0;::::1;::::0;;;;;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;33891:102;;;34019:2;34011:21;;;::::0;-1:-1:-1;;;34011:21:21;;27149:2:25;34011:21:21::1;::::0;::::1;27131::25::0;27188:1;27168:18;;;27161:29;-1:-1:-1;;;27206:18:25;;;27199:36;27252:18;;34011:21:21::1;26947:329:25::0;34011:21:21::1;33873:174;33845:202;33739:588;;;34102:165;::::0;;;;34162:10:::1;34102:165;::::0;::::1;29783:34:25::0;34203:4:21::1;29833:18:25::0;;;29826:43;29885:18;;;29878:34;;;-1:-1:-1;;;;;34102:30:21;::::1;::::0;::::1;::::0;29695:18:25;;34102:165:21::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;34077:239;;;::::0;-1:-1:-1;;;34077:239:21;;30512:2:25;34077:239:21::1;::::0;::::1;30494:21:25::0;30551:2;30531:18;;;30524:30;30590:17;30570:18;;;30563:45;30625:18;;34077:239:21::1;30310:339:25::0;34077:239:21::1;34341:52;::::0;;34360:9:::1;27483:25:25::0;;27539:2;27524:18;;27517:34;;;-1:-1:-1;;;;;27587:55:25;;27567:18;;;27560:83;;;;34348:10:21::1;::::0;34341:52:::1;::::0;27471:2:25;27456:18;34341:52:21::1;27281:368:25::0;25773:97:21;24153:5;;-1:-1:-1;;;;;24153:5:21;24138:10;24130:28;24122:47;;;;-1:-1:-1;;;24122:47:21;;21857:2:25;24122:47:21;;;21839:21:25;21896:1;21876:18;;;21869:29;-1:-1:-1;;;21914:18:25;;;21907:36;21960:18;;24122:47:21;21655:329:25;24122:47:21;25836:18:::1;:27:::0;;;::::1;;::::0;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;25773:97::o;37461:356::-;37573:7;37592:51;37646:71;37677:7;37698:9;37646:17;:71::i;:::-;37734:17;;;;37461:356;-1:-1:-1;;;;37461:356:21:o;25179:368::-;24153:5;;-1:-1:-1;;;;;24153:5:21;24138:10;24130:28;24122:47;;;;-1:-1:-1;;;24122:47:21;;21857:2:25;24122:47:21;;;21839:21:25;21896:1;21876:18;;;21869:29;-1:-1:-1;;;21914:18:25;;;21907:36;21960:18;;24122:47:21;21655:329:25;24122:47:21;25372:15:::1;:24:::0;;;::::1;;::::0;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;;25406:9:::1;:22:::0;;;;25438:9:::1;:22:::0;25470:12:::1;:28:::0;25508:14:::1;:32:::0;25179:368::o;38033:480::-;38149:7;;;38195:290;38219:10;:17;38215:1;:21;38195:290;;;38257:67;38327:41;38345:7;38354:10;38365:1;38354:13;;;;;;;;:::i;:::-;;;;;;;38327:17;:41::i;:::-;38257:111;;38398:2;:17;;;38390:5;:25;;;;:::i;:::-;38382:33;;38243:242;38238:3;;;;;:::i;:::-;;;;38195:290;;;-1:-1:-1;38501:5:21;38033:480;-1:-1:-1;;;38033:480:21:o;5010:60::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;5010:60:21;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;50447:299::-;24153:5;;-1:-1:-1;;;;;24153:5:21;24138:10;24130:28;24122:47;;;;-1:-1:-1;;;24122:47:21;;21857:2:25;24122:47:21;;;21839:21:25;21896:1;21876:18;;;21869:29;-1:-1:-1;;;21914:18:25;;;21907:36;21960:18;;24122:47:21;21655:329:25;24122:47:21;-1:-1:-1;;;;;50531:20:21;::::1;::::0;50527:213:::1;;50603:5;::::0;50567:52:::1;::::0;-1:-1:-1;;;;;50567:27:21;;::::1;::::0;50603:5:::1;50611:7:::0;50567:27:::1;:52::i;:::-;50447:299:::0;;:::o;50527:213::-:1;50664:5;::::0;:30:::1;::::0;50651:7:::1;::::0;-1:-1:-1;;;;;50664:5:21::1;::::0;50682:7;;50651;50664:30;50651:7;50664:30;50682:7;50664:5;:30:::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;50650:44;;;50716:2;50708:21;;;::::0;-1:-1:-1;;;50708:21:21;;27149:2:25;50708:21:21::1;::::0;::::1;27131::25::0;27188:1;27168:18;;;27161:29;-1:-1:-1;;;27206:18:25;;;27199:36;27252:18;;50708:21:21::1;26947:329:25::0;50708:21:21::1;50636:104;50447:299:::0;;:::o;35980:287::-;36078:24;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;36078:24:21;36182:16;;36229:31;;;;;-1:-1:-1;;;;;40675:55:25;;;36229:31:21;;;40657:74:25;40747:18;;;40740:34;;;36182:16:21;;;;;;36229:14;;40630:18:25;;36229:31:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;36229:31:21;;;;;;;;;;;;:::i;1074:229:15:-;1153:14;;1185:9;1177:49;;;;-1:-1:-1;;;1177:49:15;;44870:2:25;1177:49:15;;;44852:21:25;44909:2;44889:18;;;44882:30;44948:29;44928:18;;;44921:57;44995:18;;1177:49:15;44668:351:25;1177:49:15;-1:-1:-1;;1277:9:15;1260:26;;1074:229::o;701:205:6:-;840:58;;;-1:-1:-1;;;;;40675:55:25;;840:58:6;;;40657:74:25;40747:18;;;;40740:34;;;840:58:6;;;;;;;;;;40630:18:25;;;;840:58:6;;;;;;;;;;863:23;840:58;;;813:86;;833:5;;813:19;:86::i;36741:498:21:-;37030:16;;37066:166;;;;;-1:-1:-1;;;;;37030:16:21;;;;;;37066:14;;:166;;37094:14;;37122:12;;37148:9;;37171:7;;37192;;37213:9;;37066:166;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;36952:287;36741:498;;;;;;:::o;51812:319::-;51976:9;;52001;;51885:4;;51921:2;;51954;;51976:9;51995:15;;51991:33;;52019:5;52012:12;;;;;;;51991:33;52035:9;52030:82;52054:2;52050:1;:6;52030:82;;;52086:2;52089:1;52086:5;;;;;;;;:::i;:::-;;;;;;;;;52077:14;;;:2;52080:1;52077:5;;;;;;;;:::i;:::-;;;;;;;:14;52073:32;;52100:5;52093:12;;;;;;;;52073:32;52058:3;;;;:::i;:::-;;;;52030:82;;;-1:-1:-1;52124:4:21;;51812:319;-1:-1:-1;;;;;;51812:319:21:o;34617:689::-;-1:-1:-1;;;;;34815:18:21;;;34721:7;34815:18;;;:10;:18;;;;;;;34875:27;;;;;;;34721:7;;34815:18;;34721:7;;34815:18;;34875:25;;:27;;;;;;;;;;;;;;;34815:18;34875:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;34844:58:21;;-1:-1:-1;34976:2:21;;-1:-1:-1;;;;;;;;34992:52:21;;;34988:175;;35060:23;35101:6;35060:48;;35133:8;-1:-1:-1;;;;;35133:17:21;;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;35122:30;;;;35046:117;34988:175;35172:13;35256:11;35237:14;35243:8;35237:2;:14;:::i;:::-;35210:42;;35217:9;35210:42;:::i;:::-;35209:58;;;;:::i;:::-;35172:105;34617:689;-1:-1:-1;;;;;;;34617:689:21:o;38760:693::-;38864:7;38883:51;38937:71;38968:7;38989:9;38937:17;:71::i;:::-;39022:18;;38883:125;;-1:-1:-1;39018:103:21;;;39056:54;:13;39070:9;:22;;;39056:37;;;;;;:::i;:54::-;39134:2;:21;;;39130:95;;;-1:-1:-1;;;;;39171:26:21;;;;;;:17;:26;;;;;:31;;1032:19:15;;1050:1;1032:19;;;39171:43:21;39238:2;:19;;;39234:179;;;39288:23;;;;-1:-1:-1;;;;;39273:39:21;;;;;:14;:39;;;;;:44;;1032:19:15;;1050:1;1032:19;;;39362:23:21;;;;-1:-1:-1;;;;;39343:43:21;;;;;;;:18;:43;;;;;;;;:52;;;;;;;;;:59;;-1:-1:-1;;39343:59:21;39398:4;39343:59;;;39234:179;39429:17;;;;38760:693;-1:-1:-1;;;38760:693:21:o;39687:1120::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;39967:16:21;;-1:-1:-1;;;;;;;;;;;;;;;;;;40077:21:21;;;;;;40153:23;;;;40134:43;;;;:18;:43;;;;;:74;;;;;;;;;;;;40108:100;;;;40134:74;40363:22;;;40343:43;;-1:-1:-1;;39967:16:21;;;;;-1:-1:-1;;;39967:16:21;;40272:31;;-1:-1:-1;;40343:19:21;;:43;;;:::i;:::-;;;;;;;;;;;;;40387:9;:16;;;40343:61;;;;;;:::i;:::-;;;;;;;;;;;;;;;;40436:22;;;40343:61;;;;;40422:13;;:37;;;:::i;:::-;;;;;;;;;;;;;40477:22;:40;40500:9;:16;;;-1:-1:-1;;;;;40477:40:21;-1:-1:-1;;;;;40477:40:21;;;;;;;;;;;;40518:9;:16;;;40477:58;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;40553:17;:35;40571:9;:16;;;-1:-1:-1;;;;;40553:35:21;-1:-1:-1;;;;;40553:35:21;;;;;;;;;;;;40606:20;:45;40627:9;:23;;;-1:-1:-1;;;;;40606:45:21;-1:-1:-1;;;;;40606:45:21;;;;;;;;;;;;40652:9;:16;;;40606:63;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;40687:14;:39;40702:9;:23;;;-1:-1:-1;;;;;40687:39:21;-1:-1:-1;;;;;40687:39:21;;;;;;;;;;;;40744:9;:23;;;40272:509;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;40218:563;39687:1120;-1:-1:-1;;;;;;39687:1120:21:o;3207:706:6:-;3626:23;3652:69;3680:4;3652:69;;;;;;;;;;;;;;;;;3660:5;-1:-1:-1;;;;;3652:27:6;;;:69;;;;;:::i;:::-;3735:17;;3626:95;;-1:-1:-1;3735:21:6;3731:176;;3830:10;3819:30;;;;;;;;;;;;:::i;:::-;3811:85;;;;-1:-1:-1;;;3811:85:6;;53869:2:25;3811:85:6;;;53851:21:25;53908:2;53888:18;;;53881:30;53947:34;53927:18;;;53920:62;54018:12;53998:18;;;53991:40;54048:19;;3811:85:6;53667:406:25;3861:223:13;3994:12;4025:52;4047:6;4055:4;4061:1;4064:12;4025:21;:52::i;:::-;4018:59;;3861:223;;;;;;:::o;4948:499::-;5113:12;5170:5;5145:21;:30;;5137:81;;;;-1:-1:-1;;;5137:81:13;;54280:2:25;5137:81:13;;;54262:21:25;54319:2;54299:18;;;54292:30;54358:34;54338:18;;;54331:62;54429:8;54409:18;;;54402:36;54455:19;;5137:81:13;54078:402:25;5137:81:13;-1:-1:-1;;;;;1465:19:13;;;5228:60;;;;-1:-1:-1;;;5228:60:13;;54687:2:25;5228:60:13;;;54669:21:25;54726:2;54706:18;;;54699:30;54765:31;54745:18;;;54738:59;54814:18;;5228:60:13;54485:353:25;5228:60:13;5300:12;5314:23;5341:6;-1:-1:-1;;;;;5341:11:13;5360:5;5367:4;5341:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5299:73;;;;5389:51;5406:7;5415:10;5427:12;7707;7735:7;7731:516;;;-1:-1:-1;7765:10:13;7758:17;;7731:516;7876:17;;:21;7872:365;;8070:10;8064:17;8130:15;8117:10;8113:2;8109:19;8102:44;7872:365;8209:12;8202:20;;-1:-1:-1;;;8202:20:13;;;;;;;;:::i;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14:154:25;-1:-1:-1;;;;;93:5:25;89:54;82:5;79:65;69:93;;158:1;155;148:12;69:93;14:154;:::o;173:134::-;241:20;;270:31;241:20;270:31;:::i;:::-;173:134;;;:::o;312:184::-;-1:-1:-1;;;361:1:25;354:88;461:4;458:1;451:15;485:4;482:1;475:15;501:255;573:2;567:9;615:6;603:19;;652:18;637:34;;673:22;;;634:62;631:88;;;699:18;;:::i;:::-;735:2;728:22;501:255;:::o;761:334::-;832:2;826:9;888:2;878:13;;-1:-1:-1;;874:86:25;862:99;;991:18;976:34;;1012:22;;;973:62;970:88;;;1038:18;;:::i;:::-;1074:2;1067:22;761:334;;-1:-1:-1;761:334:25:o;1100:246::-;1149:4;1182:18;1174:6;1171:30;1168:56;;;1204:18;;:::i;:::-;-1:-1:-1;1261:2:25;1249:15;-1:-1:-1;;1245:88:25;1335:4;1241:99;;1100:246::o;1351:464::-;1394:5;1447:3;1440:4;1432:6;1428:17;1424:27;1414:55;;1465:1;1462;1455:12;1414:55;1501:6;1488:20;1532:49;1548:32;1577:2;1548:32;:::i;:::-;1532:49;:::i;:::-;1606:2;1597:7;1590:19;1652:3;1645:4;1640:2;1632:6;1628:15;1624:26;1621:35;1618:55;;;1669:1;1666;1659:12;1618:55;1734:2;1727:4;1719:6;1715:17;1708:4;1699:7;1695:18;1682:55;1782:1;1757:16;;;1775:4;1753:27;1746:38;;;;1761:7;1351:464;-1:-1:-1;;;1351:464:25:o;1820:457::-;1898:6;1906;1959:2;1947:9;1938:7;1934:23;1930:32;1927:52;;;1975:1;1972;1965:12;1927:52;2014:9;2001:23;2033:31;2058:5;2033:31;:::i;:::-;2083:5;-1:-1:-1;2139:2:25;2124:18;;2111:32;2166:18;2155:30;;2152:50;;;2198:1;2195;2188:12;2152:50;2221;2263:7;2254:6;2243:9;2239:22;2221:50;:::i;:::-;2211:60;;;1820:457;;;;;:::o;2570:182::-;2629:4;2662:18;2654:6;2651:30;2648:56;;;2684:18;;:::i;:::-;-1:-1:-1;2729:1:25;2725:14;2741:4;2721:25;;2570:182::o;2757:887::-;2810:5;2863:3;2856:4;2848:6;2844:17;2840:27;2830:55;;2881:1;2878;2871:12;2830:55;2917:6;2904:20;2943:4;2967:59;2983:42;3022:2;2983:42;:::i;2967:59::-;3060:15;;;3146:1;3142:10;;;;3130:23;;3126:32;;;3091:12;;;;3170:15;;;3167:35;;;3198:1;3195;3188:12;3167:35;3234:2;3226:6;3222:15;3246:369;3262:6;3257:3;3254:15;3246:369;;;3348:3;3335:17;3384:18;3371:11;3368:35;3365:125;;;3444:1;3473:2;3469;3462:14;3365:125;3515:57;3568:3;3563:2;3549:11;3541:6;3537:24;3533:33;3515:57;:::i;:::-;3503:70;;-1:-1:-1;3593:12:25;;;;3279;;3246:369;;;-1:-1:-1;3633:5:25;2757:887;-1:-1:-1;;;;;;2757:887:25:o;3649:1024::-;3832:6;3840;3848;3856;3864;3872;3880;3933:3;3921:9;3912:7;3908:23;3904:33;3901:53;;;3950:1;3947;3940:12;3901:53;3989:9;3976:23;4008:31;4033:5;4008:31;:::i;:::-;4058:5;-1:-1:-1;4110:2:25;4095:18;;4082:32;;-1:-1:-1;4161:2:25;4146:18;;4133:32;;-1:-1:-1;4212:2:25;4197:18;;4184:32;;-1:-1:-1;4263:3:25;4248:19;;4235:33;;-1:-1:-1;4319:3:25;4304:19;;4291:33;4343:18;4373:14;;;4370:34;;;4400:1;4397;4390:12;4370:34;4423:60;4475:7;4466:6;4455:9;4451:22;4423:60;:::i;:::-;4413:70;;4536:3;4525:9;4521:19;4508:33;4492:49;;4566:2;4556:8;4553:16;4550:36;;;4582:1;4579;4572:12;4550:36;;4605:62;4659:7;4648:8;4637:9;4633:24;4605:62;:::i;:::-;4595:72;;;3649:1024;;;;;;;;;;:::o;4678:1089::-;4871:6;4879;4887;4895;4903;4911;4919;4972:3;4960:9;4951:7;4947:23;4943:33;4940:53;;;4989:1;4986;4979:12;4940:53;5029:9;5016:23;5058:18;5099:2;5091:6;5088:14;5085:34;;;5115:1;5112;5105:12;5085:34;5138:50;5180:7;5171:6;5160:9;5156:22;5138:50;:::i;:::-;5128:60;;5235:2;5224:9;5220:18;5207:32;5197:42;;5286:2;5275:9;5271:18;5258:32;5248:42;;5337:2;5326:9;5322:18;5309:32;5299:42;;5388:3;5377:9;5373:19;5360:33;5350:43;;5446:3;5435:9;5431:19;5418:33;5402:49;;5476:2;5466:8;5463:16;5460:36;;;5492:1;5489;5482:12;5772:247;5831:6;5884:2;5872:9;5863:7;5859:23;5855:32;5852:52;;;5900:1;5897;5890:12;5852:52;5939:9;5926:23;5958:31;5983:5;5958:31;:::i;6024:383::-;6101:6;6109;6117;6170:2;6158:9;6149:7;6145:23;6141:32;6138:52;;;6186:1;6183;6176:12;6138:52;6225:9;6212:23;6244:31;6269:5;6244:31;:::i;:::-;6294:5;6346:2;6331:18;;6318:32;;-1:-1:-1;6397:2:25;6382:18;;;6369:32;;6024:383;-1:-1:-1;;;6024:383:25:o;6412:322::-;6481:6;6534:2;6522:9;6513:7;6509:23;6505:32;6502:52;;;6550:1;6547;6540:12;6502:52;6590:9;6577:23;6623:18;6615:6;6612:30;6609:50;;;6655:1;6652;6645:12;6609:50;6678;6720:7;6711:6;6700:9;6696:22;6678:50;:::i;6739:258::-;6811:1;6821:113;6835:6;6832:1;6829:13;6821:113;;;6911:11;;;6905:18;6892:11;;;6885:39;6857:2;6850:10;6821:113;;;6952:6;6949:1;6946:13;6943:48;;;6987:1;6978:6;6973:3;6969:16;6962:27;6943:48;;6739:258;;;:::o;7002:317::-;7044:3;7082:5;7076:12;7109:6;7104:3;7097:19;7125:63;7181:6;7174:4;7169:3;7165:14;7158:4;7151:5;7147:16;7125:63;:::i;:::-;7233:2;7221:15;-1:-1:-1;;7217:88:25;7208:98;;;;7308:4;7204:109;;7002:317;-1:-1:-1;;7002:317:25:o;7324:636::-;7663:6;7652:9;7645:25;7712:6;7706:13;7701:2;7690:9;7686:18;7679:41;7756:6;7751:2;7740:9;7736:18;7729:34;7799:3;7794:2;7783:9;7779:18;7772:31;7626:4;7820:46;7861:3;7850:9;7846:19;7838:6;7820:46;:::i;:::-;7897:3;7882:19;;7875:35;;;;-1:-1:-1;7941:3:25;7926:19;7919:35;7812:54;7324:636;-1:-1:-1;;;;7324:636:25:o;7965:1093::-;8157:6;8165;8173;8181;8189;8197;8205;8213;8266:3;8254:9;8245:7;8241:23;8237:33;8234:53;;;8283:1;8280;8273:12;8234:53;8322:9;8309:23;8341:31;8366:5;8341:31;:::i;:::-;8391:5;-1:-1:-1;8443:2:25;8428:18;;8415:32;;-1:-1:-1;8494:2:25;8479:18;;8466:32;;-1:-1:-1;8545:2:25;8530:18;;8517:32;;-1:-1:-1;8596:3:25;8581:19;;8568:33;;-1:-1:-1;8648:3:25;8633:19;;8620:33;;-1:-1:-1;8704:3:25;8689:19;;8676:33;8728:18;8758:14;;;8755:34;;;8785:1;8782;8775:12;8755:34;8808:60;8860:7;8851:6;8840:9;8836:22;8808:60;:::i;:::-;8798:70;;8921:3;8910:9;8906:19;8893:33;8877:49;;8951:2;8941:8;8938:16;8935:36;;;8967:1;8964;8957:12;8935:36;;8990:62;9044:7;9033:8;9022:9;9018:24;8990:62;:::i;:::-;8980:72;;;7965:1093;;;;;;;;;;;:::o;10669:118::-;10755:5;10748:13;10741:21;10734:5;10731:32;10721:60;;10777:1;10774;10767:12;10792:128;10857:20;;10886:28;10857:20;10886:28;:::i;10925:3157::-;10980:5;11028:6;11016:9;11011:3;11007:19;11003:32;11000:52;;;11048:1;11045;11038:12;11000:52;11070:22;;:::i;:::-;11061:31;;11128:9;11115:23;11157:18;11198:2;11190:6;11187:14;11184:34;;;11214:1;11211;11204:12;11184:34;11241:46;11283:3;11274:6;11263:9;11259:22;11241:46;:::i;:::-;11234:5;11227:61;11341:2;11330:9;11326:18;11313:32;11297:48;;11370:2;11360:8;11357:16;11354:36;;;11386:1;11383;11376:12;11354:36;11422:48;11466:3;11455:8;11444:9;11440:24;11422:48;:::i;:::-;11417:2;11410:5;11406:14;11399:72;11524:2;11513:9;11509:18;11496:32;11480:48;;11553:2;11543:8;11540:16;11537:36;;;11569:1;11566;11559:12;11537:36;11605:48;11649:3;11638:8;11627:9;11623:24;11605:48;:::i;:::-;11600:2;11593:5;11589:14;11582:72;11707:2;11696:9;11692:18;11679:32;11663:48;;11736:2;11726:8;11723:16;11720:36;;;11752:1;11749;11742:12;11720:36;11788:48;11832:3;11821:8;11810:9;11806:24;11788:48;:::i;:::-;11783:2;11776:5;11772:14;11765:72;11890:3;11879:9;11875:19;11862:33;11846:49;;11920:2;11910:8;11907:16;11904:36;;;11936:1;11933;11926:12;11904:36;11973:48;12017:3;12006:8;11995:9;11991:24;11973:48;:::i;:::-;11967:3;11960:5;11956:15;11949:73;12075:3;12064:9;12060:19;12047:33;12031:49;;12105:2;12095:8;12092:16;12089:36;;;12121:1;12118;12111:12;12089:36;12158:48;12202:3;12191:8;12180:9;12176:24;12158:48;:::i;:::-;12152:3;12145:5;12141:15;12134:73;12260:3;12249:9;12245:19;12232:33;12216:49;;12290:2;12280:8;12277:16;12274:36;;;12306:1;12303;12296:12;12274:36;12343:48;12387:3;12376:8;12365:9;12361:24;12343:48;:::i;:::-;12337:3;12330:5;12326:15;12319:73;12445:3;12434:9;12430:19;12417:33;12401:49;;12475:2;12465:8;12462:16;12459:36;;;12491:1;12488;12481:12;12459:36;12528:48;12572:3;12561:8;12550:9;12546:24;12528:48;:::i;:::-;12522:3;12515:5;12511:15;12504:73;12596:3;12586:13;;12652:2;12641:9;12637:18;12624:32;12681:2;12671:8;12668:16;12665:36;;;12697:1;12694;12687:12;12665:36;12733:48;12777:3;12766:8;12755:9;12751:24;12733:48;:::i;:::-;12728:2;12721:5;12717:14;12710:72;;12801:3;12791:13;;12836:38;12870:2;12859:9;12855:18;12836:38;:::i;:::-;12831:2;12824:5;12820:14;12813:62;12894:3;12884:13;;12929:38;12963:2;12952:9;12948:18;12929:38;:::i;:::-;12924:2;12917:5;12913:14;12906:62;12987:3;12977:13;;13022:38;13056:2;13045:9;13041:18;13022:38;:::i;:::-;13006:14;;;12999:62;;;;13080:3;13128:18;;;13115:32;13099:14;;;13092:56;13167:3;13215:18;;;13202:32;13186:14;;;13179:56;13254:3;;13289:35;13305:18;;;13289:35;:::i;:::-;13284:2;13277:5;13273:14;13266:59;13344:3;13334:13;;13407:2;13396:9;13392:18;13379:32;13374:2;13367:5;13363:14;13356:56;13432:3;13421:14;;13468:36;13499:3;13488:9;13484:19;13468:36;:::i;:::-;13462:3;13455:5;13451:15;13444:61;13525:3;13514:14;;13589:3;13578:9;13574:19;13561:33;13555:3;13548:5;13544:15;13537:58;13615:3;13604:14;;13671:3;13660:9;13656:19;13643:33;13701:2;13691:8;13688:16;13685:36;;;13717:1;13714;13707:12;13685:36;13754:48;13798:3;13787:8;13776:9;13772:24;13754:48;:::i;:::-;13748:3;13741:5;13737:15;13730:73;;;;13823:3;13887;13876:9;13872:19;13859:33;13853:3;13846:5;13842:15;13835:58;;13913:3;13949:36;13980:3;13969:9;13965:19;13949:36;:::i;:::-;13943:3;13936:5;13932:15;13925:61;;14006:3;14070;14059:9;14055:19;14042:33;14036:3;14029:5;14025:15;14018:58;;10925:3157;;;;:::o;14087:550::-;14190:6;14198;14206;14259:2;14247:9;14238:7;14234:23;14230:32;14227:52;;;14275:1;14272;14265:12;14227:52;14311:9;14298:23;14288:33;;14371:2;14360:9;14356:18;14343:32;14384:31;14409:5;14384:31;:::i;:::-;14434:5;-1:-1:-1;14490:2:25;14475:18;;14462:32;14517:18;14506:30;;14503:50;;;14549:1;14546;14539:12;14503:50;14572:59;14623:7;14614:6;14603:9;14599:22;14572:59;:::i;:::-;14562:69;;;14087:550;;;;;:::o;14642:390::-;14720:6;14728;14781:2;14769:9;14760:7;14756:23;14752:32;14749:52;;;14797:1;14794;14787:12;14749:52;14833:9;14820:23;14810:33;;14894:2;14883:9;14879:18;14866:32;14921:18;14913:6;14910:30;14907:50;;;14953:1;14950;14943:12;15219:388;15287:6;15295;15348:2;15336:9;15327:7;15323:23;15319:32;15316:52;;;15364:1;15361;15354:12;15316:52;15403:9;15390:23;15422:31;15447:5;15422:31;:::i;:::-;15472:5;-1:-1:-1;15529:2:25;15514:18;;15501:32;15542:33;15501:32;15542:33;:::i;:::-;15594:7;15584:17;;;15219:388;;;;;:::o;15612:180::-;15671:6;15724:2;15712:9;15703:7;15699:23;15695:32;15692:52;;;15740:1;15737;15730:12;15692:52;-1:-1:-1;15763:23:25;;15612:180;-1:-1:-1;15612:180:25:o;15797:415::-;15891:6;15899;15952:2;15940:9;15931:7;15927:23;15923:32;15920:52;;;15968:1;15965;15958:12;15920:52;16004:9;15991:23;15981:33;;16065:2;16054:9;16050:18;16037:32;16092:18;16084:6;16081:30;16078:50;;;16124:1;16121;16114:12;16078:50;16147:59;16198:7;16189:6;16178:9;16174:22;16147:59;:::i;16217:596::-;16322:6;16330;16338;16346;16354;16407:3;16395:9;16386:7;16382:23;16378:33;16375:53;;;16424:1;16421;16414:12;16375:53;16460:9;16447:23;16437:33;;16517:2;16506:9;16502:18;16489:32;16479:42;;16568:2;16557:9;16553:18;16540:32;16530:42;;16619:2;16608:9;16604:18;16591:32;16581:42;;16674:3;16663:9;16659:19;16646:33;16702:18;16694:6;16691:30;16688:50;;;16734:1;16731;16724:12;16688:50;16757;16799:7;16790:6;16779:9;16775:22;16757:50;:::i;:::-;16747:60;;;16217:596;;;;;;;;:::o;16818:905::-;16880:5;16933:3;16926:4;16918:6;16914:17;16910:27;16900:55;;16951:1;16948;16941:12;16900:55;16987:6;16974:20;17013:4;17037:59;17053:42;17092:2;17053:42;:::i;17037:59::-;17130:15;;;17216:1;17212:10;;;;17200:23;;17196:32;;;17161:12;;;;17240:15;;;17237:35;;;17268:1;17265;17258:12;17237:35;17304:2;17296:6;17292:15;17316:378;17332:6;17327:3;17324:15;17316:378;;;17418:3;17405:17;17454:18;17441:11;17438:35;17435:125;;;17514:1;17543:2;17539;17532:14;17435:125;17585:66;17647:3;17642:2;17628:11;17620:6;17616:24;17612:33;17585:66;:::i;:::-;17573:79;;-1:-1:-1;17672:12:25;;;;17349;;17316:378;;17728:517;17847:6;17855;17908:2;17896:9;17887:7;17883:23;17879:32;17876:52;;;17924:1;17921;17914:12;17876:52;17964:9;17951:23;17997:18;17989:6;17986:30;17983:50;;;18029:1;18026;18019:12;17983:50;18052:69;18113:7;18104:6;18093:9;18089:22;18052:69;:::i;:::-;18042:79;;;18171:2;18160:9;18156:18;18143:32;18184:31;18209:5;18184:31;:::i;18250:543::-;18338:6;18346;18399:2;18387:9;18378:7;18374:23;18370:32;18367:52;;;18415:1;18412;18405:12;18367:52;18455:9;18442:23;18484:18;18525:2;18517:6;18514:14;18511:34;;;18541:1;18538;18531:12;18511:34;18564:50;18606:7;18597:6;18586:9;18582:22;18564:50;:::i;:::-;18554:60;;18667:2;18656:9;18652:18;18639:32;18623:48;;18696:2;18686:8;18683:16;18680:36;;;18712:1;18709;18702:12;18680:36;;18735:52;18779:7;18768:8;18757:9;18753:24;18735:52;:::i;18798:241::-;18854:6;18907:2;18895:9;18886:7;18882:23;18878:32;18875:52;;;18923:1;18920;18913:12;18875:52;18962:9;18949:23;18981:28;19003:5;18981:28;:::i;19044:482::-;19138:6;19146;19199:2;19187:9;19178:7;19174:23;19170:32;19167:52;;;19215:1;19212;19205:12;19167:52;19254:9;19241:23;19273:31;19298:5;19273:31;:::i;:::-;19323:5;-1:-1:-1;19379:2:25;19364:18;;19351:32;19406:18;19395:30;;19392:50;;;19438:1;19435;19428:12;19531:515;19623:6;19631;19639;19647;19655;19708:3;19696:9;19687:7;19683:23;19679:33;19676:53;;;19725:1;19722;19715:12;19676:53;19764:9;19751:23;19783:28;19805:5;19783:28;:::i;:::-;19830:5;19882:2;19867:18;;19854:32;;-1:-1:-1;19933:2:25;19918:18;;19905:32;;19984:2;19969:18;;19956:32;;-1:-1:-1;20035:3:25;20020:19;20007:33;;-1:-1:-1;19531:515:25;-1:-1:-1;;;19531:515:25:o;20051:517::-;20170:6;20178;20231:2;20219:9;20210:7;20206:23;20202:32;20199:52;;;20247:1;20244;20237:12;20199:52;20286:9;20273:23;20305:31;20330:5;20305:31;:::i;:::-;20355:5;-1:-1:-1;20411:2:25;20396:18;;20383:32;20438:18;20427:30;;20424:50;;;20470:1;20467;20460:12;20424:50;20493:69;20554:7;20545:6;20534:9;20530:22;20493:69;:::i;20573:757::-;-1:-1:-1;;;;;20944:6:25;20940:55;20929:9;20922:74;21032:6;21027:2;21016:9;21012:18;21005:34;21081:6;21075:13;21070:2;21059:9;21055:18;21048:41;21125:6;21120:2;21109:9;21105:18;21098:34;21169:3;21163;21152:9;21148:19;21141:32;20903:4;21190:46;21231:3;21220:9;21216:19;21208:6;21190:46;:::i;:::-;21267:3;21252:19;;21245:35;;;;-1:-1:-1;21311:3:25;21296:19;21289:35;21182:54;20573:757;-1:-1:-1;;;;;20573:757:25:o;21335:315::-;21403:6;21411;21464:2;21452:9;21443:7;21439:23;21435:32;21432:52;;;21480:1;21477;21470:12;21432:52;21519:9;21506:23;21538:31;21563:5;21538:31;:::i;:::-;21588:5;21640:2;21625:18;;;;21612:32;;-1:-1:-1;;;21335:315:25:o;21989:437::-;22068:1;22064:12;;;;22111;;;22132:61;;22186:4;22178:6;22174:17;22164:27;;22132:61;22239:2;22231:6;22228:14;22208:18;22205:38;22202:218;;-1:-1:-1;;;22273:1:25;22266:88;22377:4;22374:1;22367:15;22405:4;22402:1;22395:15;22202:218;;21989:437;;;:::o;22557:545::-;22659:2;22654:3;22651:11;22648:448;;;22695:1;22720:5;22716:2;22709:17;22765:4;22761:2;22751:19;22835:2;22823:10;22819:19;22816:1;22812:27;22806:4;22802:38;22871:4;22859:10;22856:20;22853:47;;;-1:-1:-1;22894:4:25;22853:47;22949:2;22944:3;22940:12;22937:1;22933:20;22927:4;22923:31;22913:41;;23004:82;23022:2;23015:5;23012:13;23004:82;;;23067:17;;;23048:1;23037:13;23004:82;;;23008:3;;;22557:545;;;:::o;23338:1471::-;23464:3;23458:10;23491:18;23483:6;23480:30;23477:56;;;23513:18;;:::i;:::-;23542:97;23632:6;23592:38;23624:4;23618:11;23592:38;:::i;:::-;23586:4;23542:97;:::i;:::-;23694:4;;23758:2;23747:14;;23775:1;23770:782;;;;24596:1;24613:6;24610:89;;;-1:-1:-1;24665:19:25;;;24659:26;24610:89;-1:-1:-1;;23235:1:25;23231:11;;;23227:84;23223:89;23213:100;23319:1;23315:11;;;23210:117;24712:81;;23740:1063;;23770:782;22504:1;22497:14;;;22541:4;22528:18;;-1:-1:-1;;23806:79:25;;;23983:236;23997:7;23994:1;23991:14;23983:236;;;24086:19;;;24080:26;24065:42;;24178:27;;;;24146:1;24134:14;;;;24013:19;;23983:236;;;23987:3;24247:6;24238:7;24235:19;24232:261;;;24308:19;;;24302:26;-1:-1:-1;;24391:1:25;24387:14;;;24403:3;24383:24;24379:97;24375:102;24360:118;24345:134;;24232:261;-1:-1:-1;;;;;24539:1:25;24523:14;;;24519:22;24506:36;;-1:-1:-1;23338:1471:25:o;24814:184::-;-1:-1:-1;;;24863:1:25;24856:88;24963:4;24960:1;24953:15;24987:4;24984:1;24977:15;25003:276;25134:3;25172:6;25166:13;25188:53;25234:6;25229:3;25222:4;25214:6;25210:17;25188:53;:::i;:::-;25257:16;;;;;25003:276;-1:-1:-1;;25003:276:25:o;25284:184::-;-1:-1:-1;;;25333:1:25;25326:88;25433:4;25430:1;25423:15;25457:4;25454:1;25447:15;25473:195;25512:3;-1:-1:-1;;25536:5:25;25533:77;25530:103;;25613:18;;:::i;:::-;-1:-1:-1;25660:1:25;25649:13;;25473:195::o;29036:125::-;29076:4;29104:1;29101;29098:8;29095:34;;;29109:18;;:::i;:::-;-1:-1:-1;29146:9:25;;29036:125::o;29923:132::-;29999:13;;30021:28;29999:13;30021:28;:::i;30060:245::-;30127:6;30180:2;30168:9;30159:7;30155:23;30151:32;30148:52;;;30196:1;30193;30186:12;30148:52;30228:9;30222:16;30247:28;30269:5;30247:28;:::i;30654:128::-;30694:3;30725:1;30721:6;30718:1;30715:13;30712:39;;;30731:18;;:::i;:::-;-1:-1:-1;30767:9:25;;30654:128::o;31475:228::-;31515:7;31641:1;-1:-1:-1;;31569:74:25;31566:1;31563:81;31558:1;31551:9;31544:17;31540:105;31537:131;;;31648:18;;:::i;:::-;-1:-1:-1;31688:9:25;;31475:228::o;31708:184::-;-1:-1:-1;;;31757:1:25;31750:88;31857:4;31854:1;31847:15;31881:4;31878:1;31871:15;31897:120;31937:1;31963;31953:35;;31968:18;;:::i;:::-;-1:-1:-1;32002:9:25;;31897:120::o;35503:503::-;-1:-1:-1;;;;;35732:6:25;35728:55;35717:9;35710:74;35820:2;35815;35804:9;35800:18;35793:30;35691:4;35846:45;35887:2;35876:9;35872:18;35864:6;35846:45;:::i;:::-;35939:9;35931:6;35927:22;35922:2;35911:9;35907:18;35900:50;35967:33;35993:6;35985;35967:33;:::i;36011:184::-;36081:6;36134:2;36122:9;36113:7;36109:23;36105:32;36102:52;;;36150:1;36147;36140:12;36102:52;-1:-1:-1;36173:16:25;;36011:184;-1:-1:-1;36011:184:25:o;36200:3072::-;36251:3;36279:6;36320:5;36314:12;36347:2;36342:3;36335:15;36371:45;36412:2;36407:3;36403:12;36389;36371:45;:::i;:::-;36359:57;;;36464:4;36457:5;36453:16;36447:23;36512:3;36506:4;36502:14;36495:4;36490:3;36486:14;36479:38;36540:39;36574:4;36558:14;36540:39;:::i;:::-;36526:53;;;36627:4;36620:5;36616:16;36610:23;36677:3;36669:6;36665:16;36658:4;36653:3;36649:14;36642:40;36705:41;36739:6;36723:14;36705:41;:::i;:::-;36691:55;;;36794:4;36787:5;36783:16;36777:23;36844:3;36836:6;36832:16;36825:4;36820:3;36816:14;36809:40;36872:41;36906:6;36890:14;36872:41;:::i;:::-;36858:55;;;36961:4;36954:5;36950:16;36944:23;37011:3;37003:6;36999:16;36992:4;36987:3;36983:14;36976:40;37039:41;37073:6;37057:14;37039:41;:::i;:::-;37025:55;;;37128:4;37121:5;37117:16;37111:23;37178:3;37170:6;37166:16;37159:4;37154:3;37150:14;37143:40;37206:41;37240:6;37224:14;37206:41;:::i;:::-;37192:55;;;37295:4;37288:5;37284:16;37278:23;37345:3;37337:6;37333:16;37326:4;37321:3;37317:14;37310:40;37373:41;37407:6;37391:14;37373:41;:::i;:::-;37359:55;;;37462:4;37455:5;37451:16;37445:23;37512:3;37504:6;37500:16;37493:4;37488:3;37484:14;37477:40;37540:41;37574:6;37558:14;37540:41;:::i;:::-;37526:55;;;37600:6;37654:2;37647:5;37643:14;37637:21;37700:3;37692:6;37688:16;37683:2;37678:3;37674:12;37667:38;37728:41;37762:6;37746:14;37728:41;:::i;:::-;37714:55;;;;37788:6;37842:2;37835:5;37831:14;37825:21;37855:48;37899:2;37894:3;37890:12;37874:14;-1:-1:-1;;;;;9654:54:25;9642:67;;9588:127;37855:48;-1:-1:-1;;37922:6:25;37966:14;;;37960:21;-1:-1:-1;;;;;9654:54:25;;;38026:12;;;9642:67;;;;38058:6;38102:14;;;38096:21;9654:54;;;38162:12;;;9642:67;38194:6;38236:14;;;38230:21;38216:12;;;38209:43;38271:6;38313:14;;;38307:21;38293:12;;;38286:43;38348:6;38392:14;;;38386:21;2352:13;2345:21;38449:12;;;2333:34;38481:6;38523:14;;;38517:21;38503:12;;;38496:43;38559:6;38603:15;;;38597:22;2352:13;2345:21;38661:13;;;2333:34;38695:6;38738:15;;;38732:22;38717:13;;;38710:45;38775:6;38819:15;;;38813:22;38866:16;;;38851:13;;;38844:39;38906:42;38866:16;38813:22;38906:42;:::i;:::-;38892:56;;;;38968:6;39022:3;39015:5;39011:15;39005:22;38999:3;38994;38990:13;38983:45;;39048:6;39103:3;39096:5;39092:15;39086:22;39117:47;39159:3;39154;39150:13;39133:15;2352:13;2345:21;2333:34;;2282:91;39117:47;-1:-1:-1;;39184:6:25;39227:15;;;39221:22;39206:13;;;;39199:45;;;;39260:6;36200:3072;-1:-1:-1;36200:3072:25:o;39277:524::-;39559:2;39548:9;39541:21;39522:4;39585:54;39635:2;39624:9;39620:18;39612:6;39585:54;:::i;:::-;39687:9;39679:6;39675:22;39670:2;39659:9;39655:18;39648:50;39722:1;39714:6;39707:17;39757:5;39752:2;39744:6;39740:15;39733:30;39792:2;39784:6;39780:15;39772:23;;;39277:524;;;;:::o;40785:430::-;40839:5;40892:3;40885:4;40877:6;40873:17;40869:27;40859:55;;40910:1;40907;40900:12;40859:55;40939:6;40933:13;40970:49;40986:32;41015:2;40986:32;:::i;40970:49::-;41044:2;41035:7;41028:19;41090:3;41083:4;41078:2;41070:6;41066:15;41062:26;41059:35;41056:55;;;41107:1;41104;41097:12;41056:55;41120:64;41181:2;41174:4;41165:7;41161:18;41154:4;41146:6;41142:17;41120:64;:::i;:::-;41202:7;40785:430;-1:-1:-1;;;;40785:430:25:o;41220:138::-;41299:13;;41321:31;41299:13;41321:31;:::i;41363:3300::-;41459:6;41512:2;41500:9;41491:7;41487:23;41483:32;41480:52;;;41528:1;41525;41518:12;41480:52;41561:9;41555:16;41590:18;41631:2;41623:6;41620:14;41617:34;;;41647:1;41644;41637:12;41617:34;41670:22;;;;41726:6;41708:16;;;41704:29;41701:49;;;41746:1;41743;41736:12;41701:49;41772:22;;:::i;:::-;41825:2;41819:9;41853:2;41843:8;41840:16;41837:36;;;41869:1;41866;41859:12;41837:36;41896:56;41944:7;41933:8;41929:2;41925:17;41896:56;:::i;:::-;41889:5;41882:71;;41992:2;41988;41984:11;41978:18;42021:2;42011:8;42008:16;42005:36;;;42037:1;42034;42027:12;42005:36;42073:56;42121:7;42110:8;42106:2;42102:17;42073:56;:::i;:::-;42068:2;42061:5;42057:14;42050:80;;42169:2;42165;42161:11;42155:18;42198:2;42188:8;42185:16;42182:36;;;42214:1;42211;42204:12;42182:36;42250:56;42298:7;42287:8;42283:2;42279:17;42250:56;:::i;:::-;42245:2;42238:5;42234:14;42227:80;;42346:2;42342;42338:11;42332:18;42375:2;42365:8;42362:16;42359:36;;;42391:1;42388;42381:12;42359:36;42427:56;42475:7;42464:8;42460:2;42456:17;42427:56;:::i;:::-;42422:2;42415:5;42411:14;42404:80;;42523:3;42519:2;42515:12;42509:19;42553:2;42543:8;42540:16;42537:36;;;42569:1;42566;42559:12;42537:36;42606:56;42654:7;42643:8;42639:2;42635:17;42606:56;:::i;:::-;42600:3;42593:5;42589:15;42582:81;;42702:3;42698:2;42694:12;42688:19;42732:2;42722:8;42719:16;42716:36;;;42748:1;42745;42738:12;42716:36;42785:56;42833:7;42822:8;42818:2;42814:17;42785:56;:::i;:::-;42779:3;42772:5;42768:15;42761:81;;42881:3;42877:2;42873:12;42867:19;42911:2;42901:8;42898:16;42895:36;;;42927:1;42924;42917:12;42895:36;42964:56;43012:7;43001:8;42997:2;42993:17;42964:56;:::i;:::-;42958:3;42951:5;42947:15;42940:81;;43060:3;43056:2;43052:12;43046:19;43090:2;43080:8;43077:16;43074:36;;;43106:1;43103;43096:12;43074:36;43143:56;43191:7;43180:8;43176:2;43172:17;43143:56;:::i;:::-;43137:3;43130:5;43126:15;43119:81;;43219:3;43261:2;43257;43253:11;43247:18;43290:2;43280:8;43277:16;43274:36;;;43306:1;43303;43296:12;43274:36;43342:56;43390:7;43379:8;43375:2;43371:17;43342:56;:::i;:::-;43337:2;43330:5;43326:14;43319:80;;;43418:3;43453:42;43491:2;43487;43483:11;43453:42;:::i;:::-;43437:14;;;43430:66;43515:3;43550:42;43580:11;;;43550:42;:::i;:::-;43534:14;;;43527:66;43612:3;43647:42;43677:11;;;43647:42;:::i;:::-;43631:14;;;43624:66;43709:3;43750:11;;;43744:18;43728:14;;;43721:42;43782:3;43823:11;;;43817:18;43801:14;;;43794:42;43855:3;43890:39;43917:11;;;43890:39;:::i;:::-;43874:14;;;43867:63;43950:3;43992:12;;;43986:19;43969:15;;;43962:44;44026:3;44062:40;44089:12;;;44062:40;:::i;:::-;44045:15;;;44038:65;44123:3;44165:12;;;44159:19;44142:15;;;44135:44;44199:3;44234:12;;;44228:19;44259:17;;;44256:37;;;44289:1;44286;44279:12;44256:37;44326:57;44375:7;44363:9;44359:2;44355:18;44326:57;:::i;:::-;44320:3;44313:5;44309:15;44302:82;;;44404:3;44393:14;;44454:3;44450:2;44446:12;44440:19;44434:3;44427:5;44423:15;44416:44;44480:3;44469:14;;44516:40;44551:3;44547:2;44543:12;44516:40;:::i;:::-;44499:15;;;44492:65;;;;44577:3;44619:12;;;44613:19;44596:15;;;44589:44;;;;44503:5;41363:3300;-1:-1:-1;;;41363:3300:25:o;45024:822::-;45385:6;45374:9;45367:25;45428:3;45423:2;45412:9;45408:18;45401:31;45348:4;45455:55;45505:3;45494:9;45490:19;45482:6;45455:55;:::i;:::-;45558:9;45550:6;45546:22;45541:2;45530:9;45526:18;45519:50;45586:42;45621:6;45613;45586:42;:::i;:::-;-1:-1:-1;;;;;45664:55:25;;;;45659:2;45644:18;;45637:83;-1:-1:-1;;45764:14:25;;45757:22;45751:3;45736:19;;45729:51;45824:14;45817:22;45811:3;45796:19;;;45789:51;45578:50;45024:822;-1:-1:-1;;;45024:822:25:o;45851:179::-;45929:13;;45982:22;45971:34;;45961:45;;45951:73;;46020:1;46017;46010:12;46035:473;46138:6;46146;46154;46162;46170;46223:3;46211:9;46202:7;46198:23;46194:33;46191:53;;;46240:1;46237;46230:12;46191:53;46263:39;46292:9;46263:39;:::i;:::-;46253:49;;46342:2;46331:9;46327:18;46321:25;46311:35;;46386:2;46375:9;46371:18;46365:25;46355:35;;46430:2;46419:9;46415:18;46409:25;46399:35;;46453:49;46497:3;46486:9;46482:19;46453:49;:::i;:::-;46443:59;;46035:473;;;;;;;;:::o;46513:273::-;46581:6;46634:2;46622:9;46613:7;46609:23;46605:32;46602:52;;;46650:1;46647;46640:12;46602:52;46682:9;46676:16;46732:4;46725:5;46721:16;46714:5;46711:27;46701:55;;46752:1;46749;46742:12;46791:482;46880:1;46923:5;46880:1;46937:330;46958:7;46948:8;46945:21;46937:330;;;47077:4;-1:-1:-1;;47005:77:25;46999:4;46996:87;46993:113;;;47086:18;;:::i;:::-;47136:7;47126:8;47122:22;47119:55;;;47156:16;;;;47119:55;47235:22;;;;47195:15;;;;46937:330;;;46941:3;46791:482;;;;;:::o;47278:866::-;47327:5;47357:8;47347:80;;-1:-1:-1;47398:1:25;47412:5;;47347:80;47446:4;47436:76;;-1:-1:-1;47483:1:25;47497:5;;47436:76;47528:4;47546:1;47541:59;;;;47614:1;47609:130;;;;47521:218;;47541:59;47571:1;47562:10;;47585:5;;;47609:130;47646:3;47636:8;47633:17;47630:43;;;47653:18;;:::i;:::-;-1:-1:-1;;47709:1:25;47695:16;;47724:5;;47521:218;;47823:2;47813:8;47810:16;47804:3;47798:4;47795:13;47791:36;47785:2;47775:8;47772:16;47767:2;47761:4;47758:12;47754:35;47751:77;47748:159;;;-1:-1:-1;47860:19:25;;;47892:5;;47748:159;47939:34;47964:8;47958:4;47939:34;:::i;:::-;48069:6;-1:-1:-1;;47997:79:25;47988:7;47985:92;47982:118;;;48080:18;;:::i;:::-;48118:20;;47278:866;-1:-1:-1;;;47278:866:25:o;48149:131::-;48209:5;48238:36;48265:8;48259:4;48238:36;:::i;48285:655::-;48324:7;48356:66;48448:1;48445;48441:9;48476:1;48473;48469:9;48521:1;48517:2;48513:10;48510:1;48507:17;48502:2;48498;48494:11;48490:35;48487:61;;;48528:18;;:::i;:::-;48567:66;48659:1;48656;48652:9;48706:1;48702:2;48697:11;48694:1;48690:19;48685:2;48681;48677:11;48673:37;48670:63;;;48713:18;;:::i;:::-;48759:1;48756;48752:9;48742:19;;48806:1;48802:2;48797:11;48794:1;48790:19;48785:2;48781;48777:11;48773:37;48770:63;;;48813:18;;:::i;:::-;48878:1;48874:2;48869:11;48866:1;48862:19;48857:2;48853;48849:11;48845:37;48842:63;;;48885:18;;:::i;:::-;-1:-1:-1;;;48925:9:25;;;;;48285:655;-1:-1:-1;;;48285:655:25:o;48945:308::-;48984:1;49010;49000:35;;49015:18;;:::i;:::-;-1:-1:-1;;49129:1:25;49126:73;49057:66;49054:1;49051:73;49047:153;49044:179;;;49203:18;;:::i;:::-;-1:-1:-1;49237:10:25;;48945:308::o;49258:830::-;49308:3;49349:5;49343:12;49378:36;49404:9;49378:36;:::i;:::-;49423:19;;;49461:4;49484:1;49501:18;;;49528:204;;;;49746:1;49741:341;;;;49494:588;;49528:204;-1:-1:-1;;49574:9:25;49570:82;49565:2;49560:3;49556:12;49549:104;49719:2;49707:6;49700:14;49693:22;49690:1;49686:30;49681:3;49677:40;49673:49;49666:56;;49528:204;;49741:341;49772:5;49769:1;49762:16;49819:2;49816:1;49806:16;49844:1;49858:174;49872:6;49869:1;49866:13;49858:174;;;49959:14;;49941:11;;;49937:20;;49930:44;50002:16;;;;49887:10;;49858:174;;;50056:11;;50052:20;;;-1:-1:-1;;49494:588:25;;;;;;49258:830;;;;:::o;50093:581::-;-1:-1:-1;;;;;50199:5:25;50193:12;50189:61;50184:3;50177:74;50300:4;50293:5;50289:16;50283:23;50276:4;50271:3;50267:14;50260:47;50356:4;50349:5;50345:16;50339:23;50332:4;50327:3;50323:14;50316:47;50412:4;50405:5;50401:16;50395:23;50388:4;50383:3;50379:14;50372:47;50451:4;50444;50439:3;50435:14;50428:28;50159:3;50477:59;50530:4;50525:3;50521:14;50514:4;50507:5;50503:16;50477:59;:::i;:::-;50585:4;50578:5;50574:16;50568:23;50561:4;50556:3;50552:14;50545:47;50641:4;50634:5;50630:16;50624:23;50617:4;50612:3;50608:14;50601:47;50664:4;50657:11;;;50093:581;;;;:::o;51175:1648::-;51714:4;51743:3;-1:-1:-1;;;;;51783:6:25;51777:13;51773:62;51762:9;51755:81;51906:4;51898:6;51894:17;51888:24;51881:32;51874:40;51867:4;51856:9;51852:20;51845:70;51965:6;51958:14;51951:22;51946:2;51935:9;51931:18;51924:50;52010:2;52005;51994:9;51990:18;51983:30;52055:6;52049:13;52044:2;52033:9;52029:18;52022:41;;52118:4;52110:6;52106:17;52100:24;52094:3;52083:9;52079:19;52072:53;52180:4;52172:6;52168:17;52162:24;52156:3;52145:9;52141:19;52134:53;52224:4;52218:3;52207:9;52203:19;52196:33;52252:65;52312:3;52301:9;52297:19;52290:4;52282:6;52278:17;52252:65;:::i;:::-;52372:4;52360:17;;52354:24;52348:3;52333:19;;52326:53;52434:4;52422:17;;52416:24;52410:3;52395:19;;52388:53;2352:13;;2345:21;52489:4;52474:20;;2333:34;52545:9;52537:6;52533:22;52526:4;52515:9;52511:20;52504:52;52573:57;52623:6;52615;52573:57;:::i;:::-;52565:65;;;52639:45;52678:4;52667:9;52663:20;52655:6;2352:13;2345:21;2333:34;;2282:91;52639:45;50770:12;;-1:-1:-1;;;;;50766:61:25;52756:3;52741:19;;50754:74;50877:4;50866:16;;50860:23;50844:14;;;50837:47;50933:4;50922:16;;50916:23;50900:14;;;50893:47;50989:4;50978:16;;50972:23;50956:14;;;50949:47;51045:4;51034:16;;51028:23;51012:14;;;51005:47;51101:4;51090:16;;51084:23;51068:14;;;51061:47;51157:4;51146:16;;51140:23;51124:14;;;51117:47;-1:-1:-1;;;;;9654:54:25;;52812:3;52797:19;;9642:67;51175:1648;;;;;;;;;;;:::o;52828:834::-;52932:6;52985:3;52973:9;52964:7;52960:23;52956:33;52953:53;;;53002:1;52999;52992:12;52953:53;53035:2;53029:9;53077:3;53069:6;53065:16;53147:6;53135:10;53132:22;53111:18;53099:10;53096:34;53093:62;53090:88;;;53158:18;;:::i;:::-;53194:2;53187:22;53231:16;;53256:28;53231:16;53256:28;:::i;:::-;53293:21;;53359:2;53344:18;;53338:25;53372:30;53338:25;53372:30;:::i;:::-;53430:2;53418:15;;53411:32;53488:2;53473:18;;53467:25;53501:30;53467:25;53501:30;:::i;:::-;53559:2;53547:15;;53540:32;53626:2;53611:18;;;53605:25;53588:15;;;53581:50;;;;-1:-1:-1;53551:6:25;52828:834;-1:-1:-1;52828:834:25:o;55122:220::-;55271:2;55260:9;55253:21;55234:4;55291:45;55332:2;55321:9;55317:18;55309:6;55291:45;:::i
Swarm Source
ipfs://e1ab597239476fd8612cb204f5f85da048993e44148882d3796f5d53d76817b1
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ 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.