Overview
ETH Balance
5 wei
Eth Value
Less Than $0.01 (@ $3,112.28/ETH)More Info
Private Name Tags
ContractCreator
Latest 6 from a total of 6 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Renounce Ownersh... | 19745265 | 205 days ago | IN | 0 ETH | 0.0001202 | ||||
Set Render Contr... | 19744038 | 205 days ago | IN | 0 ETH | 0.00015569 | ||||
Transfer Ownersh... | 19714026 | 209 days ago | IN | 0 ETH | 0.00018935 | ||||
Set Render Contr... | 19712634 | 209 days ago | IN | 0 ETH | 0.00062265 | ||||
Set Token Contra... | 19712633 | 209 days ago | IN | 0 ETH | 0.00063052 | ||||
0x60806040 | 19712630 | 209 days ago | IN | 0 ETH | 0.06441293 |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
HonestWorkLogic
Compiler Version
v0.8.25+commit.b61c2a91
Optimization Enabled:
Yes with 2000000 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: UNLICENSE pragma solidity 0.8.25; import "solady/src/utils/DateTimeLib.sol"; import "./IHonestWorkRender.sol"; import "./TodoVariables.sol"; import "./3rd/Ownable.sol"; uint256 constant SEED = 0xbeef; contract HonestWorkLogic is Ownable { event TodoCompleted(uint256 tokenId, uint256 todoId, address from, address to); event TodoCreated(uint256 tokenId, uint256 todoIndex, uint256 todoId); address public tokenContract; address public renderContract; struct Token { uint8 open; // how many todos are open uint8 max; // how many todos can be open at the same time bool repeater; // if the token is a repeater uint24 todoCount; // total number of todos (including active) uint24[3] activeTodosIndices; // indices of active todos uint16[3] activeTodos; // ids of active todos uint48 lastTransferTime; // last transfer block.timestamp, uint48 ~= 8.9 million years } mapping(uint256 => Token) public tokenData; // token data mapping(uint256 => uint256[]) public tokenTodos; // all todos; we push the newest todos into this array struct TransferTracker { uint8 left; uint8 right; bytes4[7] data; } mapping(uint256 => mapping(uint256 => TransferTracker)) transferTrackers; mapping(uint256 => mapping(uint256 => uint32)) public todoCounters; // counter trackers constructor() { _initializeOwner(msg.sender); } function setRenderContract(address _contract) external onlyOwner { renderContract = _contract; } function setTokenContract(address _contract) external onlyOwner { tokenContract = _contract; } modifier onlyTokenContract() { require(msg.sender == tokenContract); _; } /*////////////////////////////////////////////////////////////// VIEW //////////////////////////////////////////////////////////////*/ function getTodoState( uint256 tokenId ) external view returns ( uint8 open, uint8 max, bool repeater, uint24 todoCount, uint24[3] memory activeTodosIndices, uint16[3] memory activeTodos, uint48 lastTransferTime, uint256[] memory todos ) { Token memory token = tokenData[tokenId]; uint256[] memory todosMem = tokenTodos[tokenId]; return ( token.open, token.max, token.repeater, token.todoCount, token.activeTodosIndices, token.activeTodos, token.lastTransferTime, todosMem ); } function resolveTask(uint256 taskId) external view returns (string memory) { return IHonestWorkRender(renderContract).resolveTask(taskId); } /*////////////////////////////////////////////////////////////// HOOK //////////////////////////////////////////////////////////////*/ function beforeTokenTransfer( address from, address to, address sender, uint256 tokenId, uint256 balanceOfFrom, bytes calldata data ) external payable onlyTokenContract { Token memory token = tokenData[tokenId]; uint256 fullfilledTodos = 0; // iterate over active todos for (uint256 index = token.open; index > 0; index--) { uint256 todo = token.activeTodos[index - 1]; // attempt to fullfill the todo if ( _fulfillTodo( tokenId, todo, token.activeTodosIndices[index - 1], // todoIndex from, to, sender, balanceOfFrom, data ) ) { emit TodoCompleted(tokenId, todo, from, to); // shift the last "open" todo to the current position if (index - 1 < token.open - 1) { token.activeTodosIndices[index - 1] = token.activeTodosIndices[token.open - 1]; token.activeTodos[index - 1] = token.activeTodos[token.open - 1]; } token.open--; fullfilledTodos++; } } // add new todos if we have completed some if (fullfilledTodos > 0) { token = _addTodos(tokenId, token, fullfilledTodos); // save token data to storage if we have new todos token.lastTransferTime = uint48(block.timestamp); tokenData[tokenId] = token; } else { // if we have no new todos, we update the transfer time tokenData[tokenId].lastTransferTime = uint48(block.timestamp); } } function _addTodos(uint256 tokenId, Token memory token, uint256 todosToReplace) internal returns (Token memory) { uint256 todosToCreate = todosToReplace > 0 ? todosToReplace : 1; // Decision: Replace n todos or add n+1 for multi-taskers 1 in 3 times if ( token.open + todosToReplace < token.max && uint256(keccak256(abi.encodePacked(tokenId, SEED, token.max))) % 3 == 0 ) { todosToCreate += 1; } uint256 seed = uint256(keccak256(abi.encodePacked(tokenId, SEED))); // Here be scary nested loops (but max n is 3) for (uint256 i = 0; i < todosToCreate; i++) { uint16 cut = 0; uint16 offset = 0; for (uint256 j = 0; j < token.open; j++) { // Rule 1: Only ever 1 passive (cut END range) if (token.activeTodos[j] >= DO_WHAT_YOU_WANT && token.activeTodos[j] <= DONT_THINK) { cut = uint16(DONT_THINK - DO_WHAT_YOU_WANT + 1); } // Rule 2: Only ever 1 of GET X THINGS done (cut start range) // AND never show if max todos is 1 // AND never show if list can still grow if (token.max == 1 || token.activeTodos[j] <= GET_10_DONE || (token.open + 1) < token.max) { offset = uint16(GET_10_DONE); } } // Rule 3: Only ever 1 of the same todo (within reason: try to avoid duplicates ~e.g. 5 iterations) uint16 todoId; bool doContinue; for (uint256 j = 0; j < 5; j++) { todoId = uint16( uint256(keccak256(abi.encodePacked(seed, token.todoCount + j * type(uint16).max))) % (TOTAL_TODO_COUNT - cut - offset) ) + offset + 1; // 1-indexed for (uint256 k = 0; j < 5 - 1 && k < token.open; k++) { if (token.activeTodos[k] == todoId) { doContinue = true; } } if (!doContinue) break; } token.activeTodosIndices[token.open] = uint24(token.todoCount); token.activeTodos[token.open] = todoId; token.todoCount++; token.open++; tokenTodos[tokenId].push(todoId); emit TodoCreated(tokenId, token.todoCount - 1, todoId); } return token; } /*////////////////////////////////////////////////////////////// MINT //////////////////////////////////////////////////////////////*/ function createTodo(uint256 tokenId) external onlyTokenContract { // Generate the token with initial todo (1 - 3) uint256 seed = uint256(keccak256(abi.encodePacked(tokenId, SEED))); bool repeater = tokenId == 1 || tokenId == 25 || tokenId == 50 || tokenId == 100; uint8 max = repeater ? 1 : uint8(uint256(seed) % 3) + 1; uint16 cut = 0; uint16 offset = uint16(GET_10_DONE); uint16 todoId; if (!repeater) { todoId = uint16( uint256(keccak256(abi.encodePacked(seed, uint32(0 /*first*/)))) % (TOTAL_TODO_COUNT - offset - cut) ) + offset + 1; // 1-indexed } else if (tokenId == 1) { todoId = uint16(DO_NOTHING_FOR_A_YEAR); } else if (tokenId == 25) { todoId = uint16(DO_NOTHING_FOR_A_MONTH); } else if (tokenId == 50) { todoId = uint16(DO_NOTHING_FOR_A_WEEK); } else { todoId = uint16(DO_NOTHING_FOR_A_DAY); } tokenTodos[tokenId].push(todoId); Token memory token = Token({ open: 1, max: max, repeater: repeater, todoCount: 1, activeTodosIndices: [uint24(0 /*first*/), 0, 0], activeTodos: [todoId, 0, 0], lastTransferTime: uint48(block.timestamp) }); // save to storage tokenData[tokenId] = token; emit TodoCreated(tokenId, 0, todoId); } /*////////////////////////////////////////////////////////////// TODO //////////////////////////////////////////////////////////////*/ function _fulfillTodo( uint256 tokenId, uint256 todo, // id uint256 todoIndex, // id address from, address to, address sender, uint256 balanceOfFrom, bytes calldata data ) internal returns (bool) { // Just transfer: Do what you want / Don't think / etc if (DO_WHAT_YOU_WANT <= todo && todo <= DONT_THINK) { return true; } // Low Gas if (todo == LOW_GAS) { return tx.gasprice < 20 gwei; } // Origin is not the sender if (todo == ORIGIN_NOT_SENDER || todo == ORIGIN_NOT_SENDER_2) { return tx.origin != sender; } // Send to beef if (todo == BEEF || todo == BEEF_2 || todo == BEEF_ONLY) { bytes20 addr = bytes20(to); return (addr[0] == 0xbe && addr[1] == 0xef) || (addr[18] == 0xbe && addr[19] == 0xef); } // Avoid the beef if (todo == AVOID_THE_BEEF) { bytes20 addr = bytes20(to); return !(addr[0] == 0xbe && addr[1] == 0xef) || (addr[18] == 0xbe && addr[19] == 0xef); } // Send to dead if (todo == DEAD || todo == DEAD_2) { bytes20 addr = bytes20(to); return (addr[0] == 0xde && addr[1] == 0xad) || (addr[18] == 0xde && addr[19] == 0xad); } // Send to babe if (todo == BABE || todo == BABE_2) { bytes20 addr = bytes20(to); return (addr[0] == 0xba && addr[1] == 0xbe) || (addr[18] == 0xba && addr[19] == 0xbe); } // Send to deaf if (todo == DEAF) { bytes20 addr = bytes20(to); return (addr[0] == 0xde && addr[1] == 0xaf) || (addr[18] == 0xde && addr[19] == 0xaf); } // Send to feed if (todo == FEED) { bytes20 addr = bytes20(to); return (addr[0] == 0xfe && addr[1] == 0xed) || (addr[18] == 0xfe && addr[19] == 0xed); } // Send to fed if (todo == FED) { bytes20 addr = bytes20(to); return (addr[0] == 0xfe && addr[1] & hex"f0" == hex"d0") || (addr[18] & hex"0f" == hex"0f" && addr[19] == 0xed); } // Send to face if (todo == FACE || todo == FACE_2) { bytes20 addr = bytes20(to); return (addr[0] == 0xfa && addr[1] == 0xce) || (addr[18] == 0xfa && addr[19] == 0xce); } // Send to bad if (todo == BAD || todo == BAD_2 || todo == BAD_3) { bytes20 addr = bytes20(to); return (addr[0] == 0xba && addr[1] & hex"f0" == hex"d0") || (addr[18] & hex"0f" == hex"0b" && addr[19] == 0xad); } // Pay 1 wei if (todo == PAY_1_WEI) { return msg.value == 1 wei; } // Send to an empty address if (todo == TO_ZERO_ETH) { return to.balance == 0; } // Have 0 ETH when sending it if (todo == ZERO_ETH) { return from.balance == 0; } // Have 1 ETH when sending it if (todo == ONE_ETH) { return from.balance >= 1 ether; } // Have an even balance if (todo == EVEN_BALANCE) { return from.balance % 2 == 0; } // Have an odd balance if (todo == ODD_BALANCE) { return from.balance % 2 == 1; } // Make me jealous if (todo == MAKE_ME_JEALOUS) { return from.balance < to.balance; } // Happy New Year if (todo == HAPPY_NEW_YEAR) { (, uint month, uint day) = DateTimeLib.timestampToDate(block.timestamp); return month == 1 && day == 1; } // At midnight if (todo == AT_MIDNIGHT) { // +/- 5 minute around midnight return block.timestamp % 1 days < 5 minutes || block.timestamp % 1 days > 1 days - 5 minutes; } // Opening Hours if (todo == OPENING_HOURS) { uint hour = (block.timestamp / 1 hours) % 24; return hour >= 9 && hour < 17; } // Outside Opening Hours if (todo == OUTSIDE_OPENING_HOURS) { uint hour = (block.timestamp / 1 hours) % 24; return hour < 9 || hour >= 17; } // 7/11 if (todo == SEVEN_ELEVEN) { uint hour = (block.timestamp / 1 hours) % 24; return hour >= 7 && hour < 23; } // Send to yourself if ( todo == TO_SELF || todo == TREAT_YOURSELF || todo == A_A || todo == YOU_ARE_HERE || todo == YOU_ARE_ENOUGH ) { return from == to; } // Send to someone else if (todo == TO_SOMEONE_ELSE || todo == AWAY || todo == OFF_YOU_GO) { return from != to; } // Transfer on a Monday if (todo == MONDAY) { return DateTimeLib.weekday(block.timestamp) == 1; } // Transfer on a Tuesday if (todo == TUESDAY) { return DateTimeLib.weekday(block.timestamp) == 2; } // Transfer on a Wednesday if (todo == WEDNESDAY) { return DateTimeLib.weekday(block.timestamp) == 3; } // Transfer on a Thursday if (todo == THURSDAY) { return DateTimeLib.weekday(block.timestamp) == 4; } // Transfer on a Friday if (todo == FRIDAY) { return DateTimeLib.weekday(block.timestamp) == 5; } // Transfer on a Saturday if (todo == SATURDAY) { return DateTimeLib.weekday(block.timestamp) == 6; } // Transfer on a Sunday if (todo == SUNDAY) { return DateTimeLib.weekday(block.timestamp) == 7; } // Do nothing for 5 minutes if (todo == DO_NOTHING_FOR_5_MINUTES || todo == TAKE_A_MOMENT || todo == NOT_NOW) { return tokenData[tokenId].lastTransferTime + 5 minutes <= block.timestamp; } // Do nothing for 10 minutes (aka snooze) if (todo == SNOOZE) { return tokenData[tokenId].lastTransferTime + 10 minutes <= block.timestamp; } // Do nothing for an hour if (todo == DO_NOTHING_FOR_AN_HOUR || todo == TIME_FOR_LUNCH || todo == GO_LOOK_AT_THE_SKY) { return tokenData[tokenId].lastTransferTime + 1 hours <= block.timestamp; } // Do nothing for twelve hours if (todo == DO_NOTHING_FOR_TWELVE_HOURS) { return tokenData[tokenId].lastTransferTime + 12 hours <= block.timestamp; } // Do nothing for a day if ( todo == DO_NOTHING_FOR_A_DAY || todo == TOMORROW_IS_ANOTHER_DAY || todo == SLEEP_ON_IT || todo == TAKE_TODAY_OFF || todo == COME_BACK_TOMORROW || todo == TOUCH_GRASS || todo == PROCRASTINATE ) { return tokenData[tokenId].lastTransferTime + 1 days <= block.timestamp; } // Do nothing for 48 hours if (todo == DO_NOTHING_FOR_48_HOURS) { return tokenData[tokenId].lastTransferTime + 2 days <= block.timestamp; } // Do nothing for a week if (todo == DO_NOTHING_FOR_A_WEEK || todo == TAKE_A_WEEK_OFF || todo == HOLIDAY_TIME) { return tokenData[tokenId].lastTransferTime + 1 weeks <= block.timestamp; } // Do nothing for 1 month if (todo == DO_NOTHING_FOR_A_MONTH || todo == WAIT_A_MONTH) { return tokenData[tokenId].lastTransferTime + 4 weeks <= block.timestamp; } // Do nothing for 1 year if (todo == DO_NOTHING_FOR_A_YEAR || todo == NEXT_YEAR_WILL_BE_GREAT) { return tokenData[tokenId].lastTransferTime + 52 weeks <= block.timestamp; } // Send ETH with it if (todo == SEND_ETH_WITH_IT) { return msg.value > 0; } // Don't send ETH with it if (todo == DONT_SEND_ETH_WITH_IT) { return msg.value == 0; } // 50 percent chance if (todo == FIFTY_FIFTY || todo == TRY_IT_USUALLY_WORKS) { return succeedWithProbability(50); } // 33 percent chance if (todo == ITS_ABOUT_THE_JOURNEY || todo == TRUST_THE_PROCESS || todo == KEEP_TRYING) { return succeedWithProbability(33); } // 60 percent chance if (todo == TAKE_A_CHANCE || todo == TRY_IT_USUALLY_WORKS) { return succeedWithProbability(60); } // 10 percent chance if (todo == BE_PERSISTENT || todo == BE_LUCKY) { return succeedWithProbability(10); } // 20 percent chance if (todo == HARD_WORK || todo == KEEP_ON_KEEPING_ON) { return succeedWithProbability(20); } // 75 percent chance if (todo == EASY_WORK) { return succeedWithProbability(75); } // Have multiple lists if (todo == HAVE_MULTIPLE_LISTS) { return balanceOfFrom > 1; } // Transfer to a contract if (todo == TO_CONTRACT) { return to.code.length > 0; } // To someone foreign if (todo == TO_SOMEONE_FOREIGN) { // We iterate over the address and make sure we have no matching digits bytes20 fromAddr = bytes20(from); bytes20 toAddr = bytes20(to); for (uint i = 0; i < 20; i++) { if (fromAddr[i] & hex"f0" == toAddr[i] & hex"f0" || fromAddr[i] & hex"0f" == toAddr[i] & hex"0f") { return false; } } return true; } // Summer if (todo == SUMMER) { (, uint month, ) = DateTimeLib.timestampToDate(block.timestamp); return month >= 6 && month <= 8; } // Not Summer if (todo == NOT_SUMMER) { (, uint month, ) = DateTimeLib.timestampToDate(block.timestamp); return month < 6 || month > 8; } // Winter if (todo == WINTER) { (, uint month, ) = DateTimeLib.timestampToDate(block.timestamp); return month >= 12 || month <= 2; } // Not Winter if (todo == NOT_WINTER) { (, uint month, ) = DateTimeLib.timestampToDate(block.timestamp); return month > 2 && month < 12; } // Spring if (todo == SPRING) { (, uint month, ) = DateTimeLib.timestampToDate(block.timestamp); return month >= 3 && month <= 5; } // Not Spring if (todo == NOT_SPRING) { (, uint month, ) = DateTimeLib.timestampToDate(block.timestamp); return month < 3 || month > 5; } // Autumn if (todo == AUTUMN) { (, uint month, ) = DateTimeLib.timestampToDate(block.timestamp); return month >= 9 && month <= 11; } // Not Autumn if (todo == NOT_AUTUMN) { (, uint month, ) = DateTimeLib.timestampToDate(block.timestamp); return month < 9 || month > 11; } // In any season if (todo == IN_ANY_SEASON) { return true; } // Weekend, Not week if (todo == WEEKEND || todo == NOT_WEEK) { uint weekday = DateTimeLib.weekday(block.timestamp); return weekday == 6 || weekday == 7; } // Week, Not weekend if (todo == WEEK || todo == NOT_WEEKEND) { uint weekday = DateTimeLib.weekday(block.timestamp); return weekday >= 1 && weekday <= 5; } // Not Monday if (todo == NOT_MONDAY) { return DateTimeLib.weekday(block.timestamp) != 1; } // Not Tuesday if (todo == NOT_TUESDAY) { return DateTimeLib.weekday(block.timestamp) != 2; } // Not Wednesday if (todo == NOT_WEDNESDAY) { return DateTimeLib.weekday(block.timestamp) != 3; } // Not Thursday if (todo == NOT_THURSDAY) { return DateTimeLib.weekday(block.timestamp) != 4; } // Not Friday if (todo == NOT_FRIDAY) { return DateTimeLib.weekday(block.timestamp) != 5; } // Not Saturday if (todo == NOT_SATURDAY) { return DateTimeLib.weekday(block.timestamp) != 6; } // Not Sunday if (todo == NOT_SUNDAY) { return DateTimeLib.weekday(block.timestamp) != 7; } // Visit 7 addresses, A B C D E F G A if (todo == RING_OF_7) { // here we need to track 7 distinct addresses/transfers return trackDistinctAddressesInARow({todo: todo, tokenId: tokenId, from: from, to: to, length: 7}); } // Visit 5 addresses, A B C D E A if (todo == RING_OF_5) { // here we need to track 5 distinct addresses/transfers return trackDistinctAddressesInARow({todo: todo, tokenId: tokenId, from: from, to: to, length: 5}); } // Visit 3 addresses, Love triangle, A B C if (todo == LOVE_TRIANGLE || todo == RING_OF_3 || todo == ALICE_BOB_AND_EVE || todo == A_B_C) { return trackDistinctAddressesInARow({todo: todo, tokenId: tokenId, from: from, to: to, length: 3}); } // Visit 2 addresses, A B A if (todo == ALICE_AND_BOB || todo == RETURN_TO_SENDER || todo == ASK_FOR_HELP || todo == A_B_A) { return trackDistinctAddressesInARow({todo: todo, tokenId: tokenId, from: from, to: to, length: 2}); } // Two in two if (todo == TWO_IN_TWO) { // Checking if the last two transfers were within 2 minutes return trackLastNTransfersWithinTimeWindow({todo: todo, tokenId: tokenId, length: 2, timeWindow: 2 minutes}); } // Three in three if (todo == THREE_IN_THREE) { // Checking if the last three transfers were within 3 minutes return trackLastNTransfersWithinTimeWindow({todo: todo, tokenId: tokenId, length: 3, timeWindow: 3 minutes}); } // Five in five if (todo == FIVE_IN_FIVE) { // Checking if the last five transfers were within 5 minutes return trackLastNTransfersWithinTimeWindow({todo: todo, tokenId: tokenId, length: 5, timeWindow: 5 minutes}); } // Every 10 minutes for an hour if (todo == EVERY_10_MINUTES_FOR_AN_HOUR) { // We are only tracking the last time the token was transferred and check if it's within 10 and 11 if ( tokenData[tokenId].lastTransferTime + 10 minutes <= block.timestamp && tokenData[tokenId].lastTransferTime + 11 minutes > block.timestamp ) { tokenData[tokenId].lastTransferTime = uint48(block.timestamp); todoCounters[tokenId][todo]++; if (todoCounters[tokenId][todo] == 5) { todoCounters[tokenId][todo] = 0; return true; } } else { tokenData[tokenId].lastTransferTime = uint48(block.timestamp); todoCounters[tokenId][todo] = 0; } return false; } // Every day for a week if (todo == EVERY_DAY_FOR_A_WEEK) { return trackEveryDay({todo: todo, tokenId: tokenId, period: 7}); } // Steady job (transfer every day monday to friday) if (todo == STEADY_JOB) { if (DateTimeLib.weekday(block.timestamp) == 1) { // We always start counting on a Monday todoCounters[tokenId][todo] = 1; } else if (block.timestamp / 1 days == tokenData[tokenId].lastTransferTime / 1 days + 1) { // If the previous transfer was yesterday, we increment the counter todoCounters[tokenId][todo]++; } else { // If there was a gap in the transfers, we reset the counter todoCounters[tokenId][todo] = 0; } return todoCounters[tokenId][todo] == 5; } // Every week for a month if (todo == EVERY_WEEK_FOR_A_MONTH) { return trackEveryWeek({todo: todo, tokenId: tokenId, period: 4}); } // Every month for a year if (todo == EVERY_MONTH_FOR_A_YEAR) { // We need to check if the previous transfer was last month uint256 currMonth = calculateMonthsSinceEpoch(block.timestamp); uint256 prevMonth = calculateMonthsSinceEpoch(tokenData[tokenId].lastTransferTime); if (prevMonth + 1 == currMonth) { todoCounters[tokenId][todo]++; } else { // If we have a gap of not one month, we reset the counter todoCounters[tokenId][todo] = 0; return false; } if (todoCounters[tokenId][todo] == 11) { todoCounters[tokenId][todo] = 0; return true; } return false; } // Every season if (todo == EVERY_SEASON) { return trackEverySeason({todo: todo, tokenId: tokenId}); } // Twice within the same block if (todo == TWICE_WITHIN_A_BLOCK) { return tokenData[tokenId].lastTransferTime == block.timestamp; } // Transfer 3 times if (todo == TRANSFER_3_TIMES) { return trackLastNTransfers(todo, tokenId, 3); } // Transfer 5 times if (todo == TRANSFER_5_TIMES) { return trackLastNTransfers(todo, tokenId, 5); } // Transfer 7 times if (todo == TRANSFER_7_TIMES) { return trackLastNTransfers(todo, tokenId, 7); } // Transfer 10 times if (todo == TRANSFER_10_TIMES) { return trackLastNTransfers(todo, tokenId, 10); } // Get 1 things done if (todo == GET_1_DONE) { return tokenData[tokenId].todoCount - (todoIndex + 1) >= 1; } // Get 5 things done if (todo == GET_5_DONE) { return tokenData[tokenId].todoCount - (todoIndex + 1) >= 5; } // Get 10 things done if (todo == GET_10_DONE) { return tokenData[tokenId].todoCount - (todoIndex + 1) >= 10; } // Even blocks if (todo == EVEN_BLOCKS) { return block.number % 2 == 0; } // Odd blocks if (todo == ODD_BLOCKS) { return block.number % 2 == 1; } // Password if (todo == WITH_PASSWORD) { return keccak256(data) == keccak256(abi.encodePacked("password")); } // Safty first if (todo == SAFETY_FIRST) { return data.length > 0; } // Fuck safety if (todo == FCK_SAFETY) { return data.length == 0; } // Stay the weekend if (todo == STAY_THE_WEEKEND) { TransferTracker memory tracker = transferTrackers[tokenId][todo]; // Check if previous holder was the same as the "to" address. // Check if the previous transfer was on a Friday and the current transfer is on the following Monday. if ( tracker.data[0] == bytes4(bytes20(to)) && DateTimeLib.weekday(tokenData[tokenId].lastTransferTime) == 5 && DateTimeLib.weekday(block.timestamp) == 1 && block.timestamp - tokenData[tokenId].lastTransferTime < 7 days ) { delete transferTrackers[tokenId][todo]; return true; } // Update tracker with the new 'from' address only if needed if (tracker.data[0] != bytes4(bytes20(from))) { tracker.data[0] = bytes4(bytes20(from)); // save to storage transferTrackers[tokenId][todo] = tracker; } return false; } // Stay the night if (todo == STAY_THE_NIGHT || todo == WHERE_WHERE_YOU) { TransferTracker memory tracker = transferTrackers[tokenId][todo]; // Normalize to epoch days (Days since 1970-01-01) uint curDay = block.timestamp / 1 days; uint prevDay = tokenData[tokenId].lastTransferTime / 1 days; // Check if previous holder was the same as the "to" address. // Check if the first transfer was on a previous day and if this transfer is after 6 am. if ( tracker.data[0] == bytes4(bytes20(to)) && prevDay + 1 == curDay && block.timestamp % 1 days >= 6 hours ) { delete transferTrackers[tokenId][todo]; return true; } // Update tracker with the new 'from' address only if needed if (tracker.data[0] != bytes4(bytes20(from))) { tracker.data[0] = bytes4(bytes20(from)); // save to storage transferTrackers[tokenId][todo] = tracker; } return false; } // Stay on a contract for 2 days if (todo == ON_A_CONTRACT_2_DAYS) { TransferTracker memory tracker = transferTrackers[tokenId][todo]; // Normalize to epoch days (Days since 1970-01-01) uint curDay = block.timestamp / 1 days; uint prevDay = tokenData[tokenId].lastTransferTime / 1 days; // Check if previous holder was the same as the "to" address. // Check if the first transfer was two days ago and if this // transfer is coming from a contract. if (tracker.data[0] == bytes4(bytes20(to)) && prevDay + 2 == curDay && from.code.length > 0) { delete transferTrackers[tokenId][todo]; return true; } // Update tracker with the new 'from' address only if needed if (tracker.data[0] != bytes4(bytes20(from))) { tracker.data[0] = bytes4(bytes20(from)); // save to storage transferTrackers[tokenId][todo] = tracker; } return false; } if (todo == VISIT_A_NEW_PLACE_TOMORROW) { // Check if the previous transfer was yesterday and the "to" address is different. return tokenData[tokenId].lastTransferTime + 1 days <= block.timestamp && from != to; } if (todo == TAKE_A_SABBATICAL) { // Stay 3 months on another address, then come back TransferTracker memory tracker = transferTrackers[tokenId][todo]; // Normalize to epoch months uint256 currMonth = calculateMonthsSinceEpoch(block.timestamp); uint256 prevMonth = calculateMonthsSinceEpoch(tokenData[tokenId].lastTransferTime); // Check if the 'to' address is the same as the previously recorded address // and check if the difference in months is exactly three. if (tracker.data[0] == bytes4(bytes20(to)) && (prevMonth + 3 == currMonth)) { delete transferTrackers[tokenId][todo]; return true; } // Update tracker with the new 'from' address only if needed if (tracker.data[0] != bytes4(bytes20(from))) { tracker.data[0] = bytes4(bytes20(from)); // save to storage transferTrackers[tokenId][todo] = tracker; } return false; } // Be bad for a week if (todo == BE_BAD_FOR_A_WEEK) { // Get this weeks Monday 00:00:00 in epoch days uint curWeekStart = block.timestamp / 1 days - DateTimeLib.weekday(block.timestamp) + 1; // Get the previous weeks Monday 00:00:00 in epoch days uint prevTimestamp = tokenData[tokenId].lastTransferTime; uint prevWeekStart = prevTimestamp / 1 days - DateTimeLib.weekday(prevTimestamp) + 1; bytes20 addr = bytes20(from); // Check if the previous transfer was a week ago and the "from" address is bad. return prevWeekStart + 7 == curWeekStart && ((addr[0] == 0xba && addr[1] & hex"f0" == hex"d0") || (addr[18] & hex"0f" == hex"0b" && addr[19] == 0xad)); } // Play dead for a week if (todo == PLAY_DEAD_FOR_A_WEEK) { // Get this weeks Monday 00:00:00 in epoch days uint curWeekStart = block.timestamp / 1 days - DateTimeLib.weekday(block.timestamp) + 1; // Get the previous weeks Monday 00:00:00 in epoch days uint prevTimestamp = tokenData[tokenId].lastTransferTime; uint prevWeekStart = prevTimestamp / 1 days - DateTimeLib.weekday(prevTimestamp) + 1; bytes20 addr = bytes20(from); // Check if the previous transfer was a week ago and the "from" address is dead. return (prevWeekStart + 7 == curWeekStart && (addr[0] == 0xde && addr[1] == 0xad)) || (addr[18] == 0xde && addr[19] == 0xad); } // A new place every day, Road trip if (todo == A_NEW_PLACE_EVERY_DAY || todo == ROAD_TRIP) { return trackLastNTransfersWithInterval({ todo: todo, tokenId: tokenId, length: 7, from: from, to: to, interval: 1 days }); } // Go sightseeing if (todo == GO_SIGHTSEEING) { return trackLastNTransfersWithInterval({ todo: todo, tokenId: tokenId, length: 4, from: from, to: to, interval: 1 hours }); } // Do 3 in a row, Do 3 if (todo == DO_3) { return trackLastNTransfers(todo, tokenId, 3); } // Do 5 if (todo == DO_5) { return trackLastNTransfers(todo, tokenId, 5); } // Do 5 if (todo == DO_5 || todo == GIVE_ME_5) { return trackLastNTransfers(todo, tokenId, 5); } // Do 7 if (todo == DO_7) { return trackLastNTransfers(todo, tokenId, 7); } // Do 10 if (todo == DO_10) { return trackLastNTransfers(todo, tokenId, 10); } // Date if (todo == A_DATE) { uint256 detRand = uint256(keccak256(abi.encodePacked(tokenId, todoIndex))); (, uint month, uint day) = DateTimeLib.epochDayToDate((detRand % 365) + 1); (, uint curMonth, uint curDay) = DateTimeLib.timestampToDate(block.timestamp); return (month == curMonth && day == curDay); } // If we don't know the todo, we can't fullfill it return false; } /*////////////////////////////////////////////////////////////// LOGIC HELPERS //////////////////////////////////////////////////////////////*/ function succeedWithProbability(uint256 probability) internal view returns (bool) { return uint256(keccak256(abi.encodePacked(block.timestamp, block.prevrandao))) % 100 <= probability; } function trackEveryDay(uint todo, uint tokenId, uint period) internal returns (bool) { // Normalize to epoch days (Days since 1970-01-01) uint curDay = block.timestamp / 1 days; uint prevDay = tokenData[tokenId].lastTransferTime / 1 days; // We check if the previous day was yesterday if (prevDay + 1 == curDay) { todoCounters[tokenId][todo]++; } else if (prevDay + 1 < curDay) { // If we have a gap of more than one day, we reset the counter todoCounters[tokenId][todo] = 0; } // Period - 1 because we start counting from 0 (this is how the todoCounter is initialized) if (todoCounters[tokenId][todo] == period - 1) { todoCounters[tokenId][todo] = 0; return true; } return false; } function calculateMonthsSinceEpoch(uint timestamp) internal pure returns (uint) { (uint year, uint month, ) = DateTimeLib.timestampToDate(timestamp); return year * 12 + month; } function trackEveryWeek(uint todo, uint tokenId, uint period) internal returns (bool) { // Get this weeks Monday 00:00:00 in epoch days uint curWeekStart = block.timestamp / 1 days - DateTimeLib.weekday(block.timestamp) + 1; // Get the previous weeks Monday 00:00:00 in epoch days uint prevTimestamp = tokenData[tokenId].lastTransferTime; uint prevWeekStart = prevTimestamp / 1 days - DateTimeLib.weekday(prevTimestamp) + 1; // We check if the transactions were in continuous weeks if (prevWeekStart + 7 == curWeekStart) { todoCounters[tokenId][todo]++; } else if (prevWeekStart + 1 < curWeekStart) { // If we have a gap of more than one week, we reset the counter todoCounters[tokenId][todo] = 0; } // Period - 1 because we start counting from 0 (this is how the todoCounter is initialized) if (todoCounters[tokenId][todo] == period - 1) { todoCounters[tokenId][todo] = 0; return true; } return false; } function trackEverySeason(uint todo, uint tokenId) internal returns (bool) { // Track the last transfers and check if they were in consecutive seasons. // Winter: Dec-Feb, Spring: Mar-May, Summer: Jun-Aug, Autumn: Sep-Nov // Transfers can start in any season to be valid. (, uint curMonth, ) = DateTimeLib.timestampToDate(block.timestamp); (, uint prevMonth, ) = DateTimeLib.timestampToDate(tokenData[tokenId].lastTransferTime); // Normalize to season uint curSeason = (curMonth % 12) / 3; uint prevSeason = (prevMonth % 12) / 3; if ((prevSeason + 1) % 4 == curSeason) { todoCounters[tokenId][todo]++; } else { // If we have a gap of not exactly one season, we reset the counter todoCounters[tokenId][todo] = 0; return false; } if (todoCounters[tokenId][todo] == 3) { todoCounters[tokenId][todo] = 0; return true; } return false; } function trackLastNTransfersWithinTimeWindow( uint todo, uint tokenId, uint8 length, uint timeWindow ) internal returns (bool) { TransferTracker memory tracker = transferTrackers[tokenId][todo]; // typecast timestamp to bytes4 , this results in a resolution of 136 years bytes4 currentTimeStamp = bytes4(uint32(block.timestamp % type(uint32).max)); bytes4 earliestTime = bytes4(uint32((block.timestamp - timeWindow) % type(uint32).max)); // add the new timestamp to the tracker on the right tracker.data[tracker.right] = currentTimeStamp; // increment right pointer tracker.right = (tracker.right + 1) % length; // end condition: left pointer is equal to right (but we also need to exclude the initial state) if (tracker.left == tracker.right && tracker.data[0] != 0x0) { // Check if left timestamp is within the timeWindow if (tracker.data[tracker.left] >= earliestTime) { delete transferTrackers[tokenId][todo]; return true; } } // if left timestamp is not within timeWindow, we pop-left (adjust the left pointer) // we loop from the left pointer to the right pointer while (tracker.left != tracker.right) { if (tracker.data[tracker.left] < earliestTime) { tracker.left = (tracker.left + 1) % length; } else { break; } } // save to storage transferTrackers[tokenId][todo] = tracker; return false; } function trackLastNTransfersWithInterval( uint todo, uint tokenId, uint8 length, address from, address to, uint interval ) internal returns (bool) { TransferTracker memory tracker = transferTrackers[tokenId][todo]; // normalize time to interval uint curTime = block.timestamp / interval; uint prevTime = tokenData[tokenId].lastTransferTime / interval; // if the previous transfer was not within the interval, we reset the tracker if (prevTime + 1 != curTime) { tracker.left = tracker.right; } // add the new address to the tracker tracker.data[tracker.right] = bytes4(bytes20(from)); // increment right pointer tracker.right = (tracker.right + 1) % length; // end condition: left pointer is equal to right (but we also need to exclude the initial state) if (tracker.left == tracker.right && tracker.data[0] != 0x0) { if (tracker.data[tracker.left] == bytes4(bytes20(to))) { delete transferTrackers[tokenId][todo]; return true; } } // If new address is a duplicate, we adjust the left pointer. // We loop from the left pointer to the right pointer. uint8 left = tracker.left; while (left != tracker.right) { if (tracker.data[left] == bytes4(bytes20(to))) { tracker.left = (left + 1) % length; break; } left = (left + 1) % length; } // save to storage transferTrackers[tokenId][todo] = tracker; return false; } function trackLastNTransfers(uint todo, uint tokenId, uint8 n) internal returns (bool) { todoCounters[tokenId][todo]++; if (todoCounters[tokenId][todo] == n) { delete todoCounters[tokenId][todo]; return true; } return false; } function trackDistinctAddressesInARow( uint todo, uint tokenId, address from, address to, uint8 length ) internal returns (bool) { TransferTracker memory tracker = transferTrackers[tokenId][todo]; // add the new address to the tracker tracker.data[tracker.right] = bytes4(bytes20(from)); // adjust right pointer tracker.right = (tracker.right + 1) % length; // end condition: left pointer is equal to right (but we also need exclude the initial state) if (tracker.left == tracker.right && tracker.data[0] != 0x0) { if (tracker.data[tracker.left] == bytes4(bytes20(to))) { delete transferTrackers[tokenId][todo]; return true; } } // If new address is a duplicate, we adjust the left pointer. // We loop from the left pointer to the right pointer. uint8 left = tracker.left; while (left != tracker.right) { if (tracker.data[left] == bytes4(bytes20(to))) { tracker.left = (left + 1) % length; break; } left = (left + 1) % length; } // save to storage transferTrackers[tokenId][todo] = tracker; return false; } /*////////////////////////////////////////////////////////////// tokenURI //////////////////////////////////////////////////////////////*/ function tokenURI(uint256 tokenId) external view returns (string memory) { Token memory token = tokenData[tokenId]; return IHonestWorkRender(renderContract).tokenURI( tokenId, tokenTodos[tokenId], token.activeTodosIndices, token.open, token.max, token.repeater ); } function renderSVG(uint256 tokenId) external view returns (string memory) { Token memory token = tokenData[tokenId]; return IHonestWorkRender(renderContract).renderSVG( tokenId, tokenTodos[tokenId], token.activeTodosIndices, token.open ); } function renderSVGBase64(uint256 tokenId) external view returns (string memory) { Token memory token = tokenData[tokenId]; return IHonestWorkRender(renderContract).renderSVGBase64( tokenId, tokenTodos[tokenId], token.activeTodosIndices, token.open ); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Library for date time operations. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/DateTimeLib.sol) /// @author Modified from BokkyPooBahsDateTimeLibrary (https://github.com/bokkypoobah/BokkyPooBahsDateTimeLibrary) /// @dev /// Conventions: /// --------------------------------------------------------------------+ /// Unit | Range | Notes | /// --------------------------------------------------------------------| /// timestamp | 0..0x1e18549868c76ff | Unix timestamp. | /// epochDay | 0..0x16d3e098039 | Days since 1970-01-01. | /// year | 1970..0xffffffff | Gregorian calendar year. | /// month | 1..12 | Gregorian calendar month. | /// day | 1..31 | Gregorian calendar day of month. | /// weekday | 1..7 | The day of the week (1-indexed). | /// --------------------------------------------------------------------+ /// All timestamps of days are rounded down to 00:00:00 UTC. library DateTimeLib { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTANTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ // Weekdays are 1-indexed, adhering to ISO 8601. uint256 internal constant MON = 1; uint256 internal constant TUE = 2; uint256 internal constant WED = 3; uint256 internal constant THU = 4; uint256 internal constant FRI = 5; uint256 internal constant SAT = 6; uint256 internal constant SUN = 7; // Months and days of months are 1-indexed, adhering to ISO 8601. uint256 internal constant JAN = 1; uint256 internal constant FEB = 2; uint256 internal constant MAR = 3; uint256 internal constant APR = 4; uint256 internal constant MAY = 5; uint256 internal constant JUN = 6; uint256 internal constant JUL = 7; uint256 internal constant AUG = 8; uint256 internal constant SEP = 9; uint256 internal constant OCT = 10; uint256 internal constant NOV = 11; uint256 internal constant DEC = 12; // These limits are large enough for most practical purposes. // Inputs that exceed these limits result in undefined behavior. uint256 internal constant MAX_SUPPORTED_YEAR = 0xffffffff; uint256 internal constant MAX_SUPPORTED_EPOCH_DAY = 0x16d3e098039; uint256 internal constant MAX_SUPPORTED_TIMESTAMP = 0x1e18549868c76ff; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* DATE TIME OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the number of days since 1970-01-01 from (`year`,`month`,`day`). /// See: https://howardhinnant.github.io/date_algorithms.html /// Note: Inputs outside the supported ranges result in undefined behavior. /// Use {isSupportedDate} to check if the inputs are supported. function dateToEpochDay(uint256 year, uint256 month, uint256 day) internal pure returns (uint256 epochDay) { /// @solidity memory-safe-assembly assembly { year := sub(year, lt(month, 3)) let doy := add(shr(11, add(mul(62719, mod(add(month, 9), 12)), 769)), day) let yoe := mod(year, 400) let doe := sub(add(add(mul(yoe, 365), shr(2, yoe)), doy), div(yoe, 100)) epochDay := sub(add(mul(div(year, 400), 146097), doe), 719469) } } /// @dev Returns (`year`,`month`,`day`) from the number of days since 1970-01-01. /// Note: Inputs outside the supported ranges result in undefined behavior. /// Use {isSupportedDays} to check if the inputs is supported. function epochDayToDate(uint256 epochDay) internal pure returns (uint256 year, uint256 month, uint256 day) { /// @solidity memory-safe-assembly assembly { epochDay := add(epochDay, 719468) let doe := mod(epochDay, 146097) let yoe := div(sub(sub(add(doe, div(doe, 36524)), div(doe, 1460)), eq(doe, 146096)), 365) let doy := sub(doe, sub(add(mul(365, yoe), shr(2, yoe)), div(yoe, 100))) let mp := div(add(mul(5, doy), 2), 153) day := add(sub(doy, shr(11, add(mul(mp, 62719), 769))), 1) month := byte(mp, shl(160, 0x030405060708090a0b0c0102)) year := add(add(yoe, mul(div(epochDay, 146097), 400)), lt(month, 3)) } } /// @dev Returns the unix timestamp from (`year`,`month`,`day`). /// Note: Inputs outside the supported ranges result in undefined behavior. /// Use {isSupportedDate} to check if the inputs are supported. function dateToTimestamp(uint256 year, uint256 month, uint256 day) internal pure returns (uint256 result) { unchecked { result = dateToEpochDay(year, month, day) * 86400; } } /// @dev Returns (`year`,`month`,`day`) from the given unix timestamp. /// Note: Inputs outside the supported ranges result in undefined behavior. /// Use {isSupportedTimestamp} to check if the inputs are supported. function timestampToDate(uint256 timestamp) internal pure returns (uint256 year, uint256 month, uint256 day) { (year, month, day) = epochDayToDate(timestamp / 86400); } /// @dev Returns the unix timestamp from /// (`year`,`month`,`day`,`hour`,`minute`,`second`). /// Note: Inputs outside the supported ranges result in undefined behavior. /// Use {isSupportedDateTime} to check if the inputs are supported. function dateTimeToTimestamp( uint256 year, uint256 month, uint256 day, uint256 hour, uint256 minute, uint256 second ) internal pure returns (uint256 result) { unchecked { result = dateToEpochDay(year, month, day) * 86400 + hour * 3600 + minute * 60 + second; } } /// @dev Returns (`year`,`month`,`day`,`hour`,`minute`,`second`) /// from the given unix timestamp. /// Note: Inputs outside the supported ranges result in undefined behavior. /// Use {isSupportedTimestamp} to check if the inputs are supported. function timestampToDateTime(uint256 timestamp) internal pure returns ( uint256 year, uint256 month, uint256 day, uint256 hour, uint256 minute, uint256 second ) { unchecked { (year, month, day) = epochDayToDate(timestamp / 86400); uint256 secs = timestamp % 86400; hour = secs / 3600; secs = secs % 3600; minute = secs / 60; second = secs % 60; } } /// @dev Returns if the `year` is leap. function isLeapYear(uint256 year) internal pure returns (bool leap) { /// @solidity memory-safe-assembly assembly { leap := iszero(and(add(mul(iszero(mod(year, 25)), 12), 3), year)) } } /// @dev Returns number of days in given `month` of `year`. function daysInMonth(uint256 year, uint256 month) internal pure returns (uint256 result) { bool flag = isLeapYear(year); /// @solidity memory-safe-assembly assembly { // `daysInMonths = [31,28,31,30,31,30,31,31,30,31,30,31]`. // `result = daysInMonths[month - 1] + isLeapYear(year)`. result := add(byte(month, shl(152, 0x1f1c1f1e1f1e1f1f1e1f1e1f)), and(eq(month, 2), flag)) } } /// @dev Returns the weekday from the unix timestamp. /// Monday: 1, Tuesday: 2, ....., Sunday: 7. function weekday(uint256 timestamp) internal pure returns (uint256 result) { unchecked { result = ((timestamp / 86400 + 3) % 7) + 1; } } /// @dev Returns if (`year`,`month`,`day`) is a supported date. /// - `1970 <= year <= MAX_SUPPORTED_YEAR`. /// - `1 <= month <= 12`. /// - `1 <= day <= daysInMonth(year, month)`. function isSupportedDate(uint256 year, uint256 month, uint256 day) internal pure returns (bool result) { uint256 md = daysInMonth(year, month); /// @solidity memory-safe-assembly assembly { result := and( lt(sub(year, 1970), sub(MAX_SUPPORTED_YEAR, 1969)), and(lt(sub(month, 1), 12), lt(sub(day, 1), md)) ) } } /// @dev Returns if (`year`,`month`,`day`,`hour`,`minute`,`second`) is a supported date time. /// - `1970 <= year <= MAX_SUPPORTED_YEAR`. /// - `1 <= month <= 12`. /// - `1 <= day <= daysInMonth(year, month)`. /// - `hour < 24`. /// - `minute < 60`. /// - `second < 60`. function isSupportedDateTime( uint256 year, uint256 month, uint256 day, uint256 hour, uint256 minute, uint256 second ) internal pure returns (bool result) { if (isSupportedDate(year, month, day)) { /// @solidity memory-safe-assembly assembly { result := and(lt(hour, 24), and(lt(minute, 60), lt(second, 60))) } } } /// @dev Returns if `epochDay` is a supported unix epoch day. function isSupportedEpochDay(uint256 epochDay) internal pure returns (bool result) { unchecked { result = epochDay < MAX_SUPPORTED_EPOCH_DAY + 1; } } /// @dev Returns if `timestamp` is a supported unix timestamp. function isSupportedTimestamp(uint256 timestamp) internal pure returns (bool result) { unchecked { result = timestamp < MAX_SUPPORTED_TIMESTAMP + 1; } } /// @dev Returns the unix timestamp of the given `n`th weekday `wd`, in `month` of `year`. /// Example: 3rd Friday of Feb 2022 is `nthWeekdayInMonthOfYearTimestamp(2022, 2, 3, 5)` /// Note: `n` is 1-indexed for traditional consistency. /// Invalid weekdays (i.e. `wd == 0 || wd > 7`) result in undefined behavior. function nthWeekdayInMonthOfYearTimestamp(uint256 year, uint256 month, uint256 n, uint256 wd) internal pure returns (uint256 result) { uint256 d = dateToEpochDay(year, month, 1); uint256 md = daysInMonth(year, month); /// @solidity memory-safe-assembly assembly { let diff := sub(wd, add(mod(add(d, 3), 7), 1)) let date := add(mul(sub(n, 1), 7), add(mul(gt(diff, 6), 7), diff)) result := mul(mul(86400, add(date, d)), and(lt(date, md), iszero(iszero(n)))) } } /// @dev Returns the unix timestamp of the most recent Monday. function mondayTimestamp(uint256 timestamp) internal pure returns (uint256 result) { uint256 t = timestamp; /// @solidity memory-safe-assembly assembly { let day := div(t, 86400) result := mul(mul(sub(day, mod(add(day, 3), 7)), 86400), gt(t, 345599)) } } /// @dev Returns whether the unix timestamp falls on a Saturday or Sunday. /// To check whether it is a week day, just take the negation of the result. function isWeekEnd(uint256 timestamp) internal pure returns (bool result) { result = weekday(timestamp) > FRI; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* DATE TIME ARITHMETIC OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Adds `numYears` to the unix timestamp, and returns the result. /// Note: The result will share the same Gregorian calendar month, /// but different Gregorian calendar years for non-zero `numYears`. /// If the Gregorian calendar month of the result has less days /// than the Gregorian calendar month day of the `timestamp`, /// the result's month day will be the maximum possible value for the month. /// (e.g. from 29th Feb to 28th Feb) function addYears(uint256 timestamp, uint256 numYears) internal pure returns (uint256 result) { (uint256 year, uint256 month, uint256 day) = epochDayToDate(timestamp / 86400); result = _offsetted(year + numYears, month, day, timestamp); } /// @dev Adds `numMonths` to the unix timestamp, and returns the result. /// Note: If the Gregorian calendar month of the result has less days /// than the Gregorian calendar month day of the `timestamp`, /// the result's month day will be the maximum possible value for the month. /// (e.g. from 29th Feb to 28th Feb) function addMonths(uint256 timestamp, uint256 numMonths) internal pure returns (uint256 result) { (uint256 year, uint256 month, uint256 day) = epochDayToDate(timestamp / 86400); month = _sub(month + numMonths, 1); result = _offsetted(year + month / 12, _add(month % 12, 1), day, timestamp); } /// @dev Adds `numDays` to the unix timestamp, and returns the result. function addDays(uint256 timestamp, uint256 numDays) internal pure returns (uint256 result) { result = timestamp + numDays * 86400; } /// @dev Adds `numHours` to the unix timestamp, and returns the result. function addHours(uint256 timestamp, uint256 numHours) internal pure returns (uint256 result) { result = timestamp + numHours * 3600; } /// @dev Adds `numMinutes` to the unix timestamp, and returns the result. function addMinutes(uint256 timestamp, uint256 numMinutes) internal pure returns (uint256 result) { result = timestamp + numMinutes * 60; } /// @dev Adds `numSeconds` to the unix timestamp, and returns the result. function addSeconds(uint256 timestamp, uint256 numSeconds) internal pure returns (uint256 result) { result = timestamp + numSeconds; } /// @dev Subtracts `numYears` from the unix timestamp, and returns the result. /// Note: The result will share the same Gregorian calendar month, /// but different Gregorian calendar years for non-zero `numYears`. /// If the Gregorian calendar month of the result has less days /// than the Gregorian calendar month day of the `timestamp`, /// the result's month day will be the maximum possible value for the month. /// (e.g. from 29th Feb to 28th Feb) function subYears(uint256 timestamp, uint256 numYears) internal pure returns (uint256 result) { (uint256 year, uint256 month, uint256 day) = epochDayToDate(timestamp / 86400); result = _offsetted(year - numYears, month, day, timestamp); } /// @dev Subtracts `numYears` from the unix timestamp, and returns the result. /// Note: If the Gregorian calendar month of the result has less days /// than the Gregorian calendar month day of the `timestamp`, /// the result's month day will be the maximum possible value for the month. /// (e.g. from 29th Feb to 28th Feb) function subMonths(uint256 timestamp, uint256 numMonths) internal pure returns (uint256 result) { (uint256 year, uint256 month, uint256 day) = epochDayToDate(timestamp / 86400); uint256 yearMonth = _totalMonths(year, month) - _add(numMonths, 1); result = _offsetted(yearMonth / 12, _add(yearMonth % 12, 1), day, timestamp); } /// @dev Subtracts `numDays` from the unix timestamp, and returns the result. function subDays(uint256 timestamp, uint256 numDays) internal pure returns (uint256 result) { result = timestamp - numDays * 86400; } /// @dev Subtracts `numHours` from the unix timestamp, and returns the result. function subHours(uint256 timestamp, uint256 numHours) internal pure returns (uint256 result) { result = timestamp - numHours * 3600; } /// @dev Subtracts `numMinutes` from the unix timestamp, and returns the result. function subMinutes(uint256 timestamp, uint256 numMinutes) internal pure returns (uint256 result) { result = timestamp - numMinutes * 60; } /// @dev Subtracts `numSeconds` from the unix timestamp, and returns the result. function subSeconds(uint256 timestamp, uint256 numSeconds) internal pure returns (uint256 result) { result = timestamp - numSeconds; } /// @dev Returns the difference in Gregorian calendar years /// between `fromTimestamp` and `toTimestamp`. /// Note: Even if the true time difference is less than a year, /// the difference can be non-zero is the timestamps are /// from different Gregorian calendar years function diffYears(uint256 fromTimestamp, uint256 toTimestamp) internal pure returns (uint256 result) { toTimestamp - fromTimestamp; (uint256 fromYear,,) = epochDayToDate(fromTimestamp / 86400); (uint256 toYear,,) = epochDayToDate(toTimestamp / 86400); result = _sub(toYear, fromYear); } /// @dev Returns the difference in Gregorian calendar months /// between `fromTimestamp` and `toTimestamp`. /// Note: Even if the true time difference is less than a month, /// the difference can be non-zero is the timestamps are /// from different Gregorian calendar months. function diffMonths(uint256 fromTimestamp, uint256 toTimestamp) internal pure returns (uint256 result) { toTimestamp - fromTimestamp; (uint256 fromYear, uint256 fromMonth,) = epochDayToDate(fromTimestamp / 86400); (uint256 toYear, uint256 toMonth,) = epochDayToDate(toTimestamp / 86400); result = _sub(_totalMonths(toYear, toMonth), _totalMonths(fromYear, fromMonth)); } /// @dev Returns the difference in days between `fromTimestamp` and `toTimestamp`. function diffDays(uint256 fromTimestamp, uint256 toTimestamp) internal pure returns (uint256 result) { result = (toTimestamp - fromTimestamp) / 86400; } /// @dev Returns the difference in hours between `fromTimestamp` and `toTimestamp`. function diffHours(uint256 fromTimestamp, uint256 toTimestamp) internal pure returns (uint256 result) { result = (toTimestamp - fromTimestamp) / 3600; } /// @dev Returns the difference in minutes between `fromTimestamp` and `toTimestamp`. function diffMinutes(uint256 fromTimestamp, uint256 toTimestamp) internal pure returns (uint256 result) { result = (toTimestamp - fromTimestamp) / 60; } /// @dev Returns the difference in seconds between `fromTimestamp` and `toTimestamp`. function diffSeconds(uint256 fromTimestamp, uint256 toTimestamp) internal pure returns (uint256 result) { result = toTimestamp - fromTimestamp; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PRIVATE HELPERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Unchecked arithmetic for computing the total number of months. function _totalMonths(uint256 numYears, uint256 numMonths) private pure returns (uint256 total) { unchecked { total = numYears * 12 + numMonths; } } /// @dev Unchecked arithmetic for adding two numbers. function _add(uint256 a, uint256 b) private pure returns (uint256 c) { unchecked { c = a + b; } } /// @dev Unchecked arithmetic for subtracting two numbers. function _sub(uint256 a, uint256 b) private pure returns (uint256 c) { unchecked { c = a - b; } } /// @dev Returns the offsetted timestamp. function _offsetted(uint256 year, uint256 month, uint256 day, uint256 timestamp) private pure returns (uint256 result) { uint256 dm = daysInMonth(year, month); if (day >= dm) { day = dm; } result = dateToEpochDay(year, month, day) * 86400 + (timestamp % 86400); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Simple single owner authorization mixin. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol) /// @dev While the ownable portion follows /// [EIP-173](https://eips.ethereum.org/EIPS/eip-173) for compatibility, abstract contract Ownable { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The caller is not authorized to call the function. error Unauthorized(); /// @dev The `newOwner` cannot be the zero address. error NewOwnerIsZeroAddress(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EVENTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The ownership is transferred from `oldOwner` to `newOwner`. /// This event is intentionally kept the same as OpenZeppelin's Ownable to be /// compatible with indexers and [EIP-173](https://eips.ethereum.org/EIPS/eip-173), /// despite it not being as lightweight as a single argument event. event OwnershipTransferred(address indexed oldOwner, address indexed newOwner); /// @dev `keccak256(bytes("OwnershipTransferred(address,address)"))`. uint256 private constant _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE = 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STORAGE */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The owner slot is given by: `not(_OWNER_SLOT_NOT)`. /// It is intentionally chosen to be a high value /// to avoid collision with lower slots. /// The choice of manual storage layout is to enable compatibility /// with both regular and upgradeable contracts. uint256 private constant _OWNER_SLOT_NOT = 0x8b78c6d8; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Initializes the owner directly without authorization guard. /// This function must be called upon initialization, /// regardless of whether the contract is upgradeable or not. /// This is to enable generalization to both regular and upgradeable contracts, /// and to save gas in case the initial owner is not the caller. /// For performance reasons, this function will not check if there /// is an existing owner. function _initializeOwner(address newOwner) internal virtual { /// @solidity memory-safe-assembly assembly { // Clean the upper 96 bits. newOwner := shr(96, shl(96, newOwner)) // Store the new value. sstore(not(_OWNER_SLOT_NOT), newOwner) // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner) } } /// @dev Sets the owner directly without authorization guard. function _setOwner(address newOwner) internal virtual { /// @solidity memory-safe-assembly assembly { let ownerSlot := not(_OWNER_SLOT_NOT) // Clean the upper 96 bits. newOwner := shr(96, shl(96, newOwner)) // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner) // Store the new value. sstore(ownerSlot, newOwner) } } /// @dev Throws if the sender is not the owner. function _checkOwner() internal view virtual { /// @solidity memory-safe-assembly assembly { // If the caller is not the stored owner, revert. if iszero(eq(caller(), sload(not(_OWNER_SLOT_NOT)))) { mstore(0x00, 0x82b42900) // `Unauthorized()`. revert(0x1c, 0x04) } } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PUBLIC UPDATE FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Allows the owner to transfer the ownership to `newOwner`. function transferOwnership(address newOwner) public payable virtual onlyOwner { /// @solidity memory-safe-assembly assembly { if iszero(shl(96, newOwner)) { mstore(0x00, 0x7448fbae) // `NewOwnerIsZeroAddress()`. revert(0x1c, 0x04) } } _setOwner(newOwner); } /// @dev Allows the owner to renounce their ownership. function renounceOwnership() public payable virtual onlyOwner { _setOwner(address(0)); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PUBLIC READ FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the owner of the contract. function owner() public view virtual returns (address result) { /// @solidity memory-safe-assembly assembly { result := sload(not(_OWNER_SLOT_NOT)) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* MODIFIERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Marks a function as only callable by the owner. modifier onlyOwner() virtual { _checkOwner(); _; } }
// SPDX-License-Identifier: UNLICENSE pragma solidity 0.8.25; interface IHonestWorkRender { function tokenURI( uint256 tokenId, uint256[] calldata tokenTodos, uint24[3] calldata activeTodoIndices, uint8 open, uint8 max, bool repeater ) external view returns (string memory); function renderSVG( uint256 tokenId, uint256[] calldata tokenTodos, uint24[3] calldata activeTodoIndices, uint8 open ) external view returns (string memory); function renderSVGBase64( uint256 tokenId, uint256[] calldata tokenTodos, uint24[3] calldata activeTodoIndices, uint8 open ) external view returns (string memory); function resolveTask(uint256 taskId) external view returns (string memory); }
// SPDX-License-Identifier: UNLICENSE pragma solidity 0.8.25; uint256 constant GET_1_DONE = 1; uint256 constant GET_5_DONE = 2; uint256 constant GET_10_DONE = 3; uint256 constant LOW_GAS = 4; uint256 constant EVEN_BLOCKS = 5; uint256 constant ODD_BLOCKS = 6; uint256 constant SEND_ETH_WITH_IT = 7; uint256 constant DONT_SEND_ETH_WITH_IT = 8; uint256 constant PAY_1_WEI = 9; uint256 constant SAFETY_FIRST = 10; uint256 constant FCK_SAFETY = 11; uint256 constant WITH_PASSWORD = 12; uint256 constant BE_LUCKY = 13; uint256 constant ITS_ABOUT_THE_JOURNEY = 14; uint256 constant TAKE_A_CHANCE = 15; uint256 constant TRUST_THE_PROCESS = 16; uint256 constant BE_PERSISTENT = 17; uint256 constant KEEP_TRYING = 18; uint256 constant KEEP_ON_KEEPING_ON = 19; uint256 constant FIFTY_FIFTY = 20; uint256 constant TRY_IT_USUALLY_WORKS = 21; uint256 constant EASY_WORK = 22; uint256 constant HARD_WORK = 23; uint256 constant YOU_ARE_HERE = 24; uint256 constant YOU_ARE_ENOUGH = 25; uint256 constant BEEF = 26; uint256 constant BEEF_2 = 27; uint256 constant BEEF_ONLY = 28; uint256 constant AVOID_THE_BEEF = 29; uint256 constant DEAD = 30; uint256 constant DEAD_2 = 31; uint256 constant BABE = 32; uint256 constant BABE_2 = 33; uint256 constant DEAF = 34; uint256 constant FEED = 35; uint256 constant FED = 36; uint256 constant BAD = 37; uint256 constant BAD_2 = 38; uint256 constant BAD_3 = 39; uint256 constant FACE = 40; uint256 constant FACE_2 = 41; uint256 constant TO_SELF = 42; uint256 constant TREAT_YOURSELF = 43; uint256 constant A_A = 44; uint256 constant TO_SOMEONE_ELSE = 45; uint256 constant AWAY = 46; uint256 constant OFF_YOU_GO = 47; uint256 constant TO_SOMEONE_FOREIGN = 48; uint256 constant TO_CONTRACT = 49; uint256 constant ORIGIN_NOT_SENDER = 50; uint256 constant ORIGIN_NOT_SENDER_2 = 51; uint256 constant TO_ZERO_ETH = 52; uint256 constant ZERO_ETH = 53; uint256 constant ONE_ETH = 54; uint256 constant MAKE_ME_JEALOUS = 55; uint256 constant EVEN_BALANCE = 56; uint256 constant ODD_BALANCE = 57; uint256 constant HAVE_MULTIPLE_LISTS = 58; uint256 constant OPENING_HOURS = 59; uint256 constant OUTSIDE_OPENING_HOURS = 60; uint256 constant MONDAY = 61; uint256 constant NOT_MONDAY = 62; uint256 constant TUESDAY = 63; uint256 constant NOT_TUESDAY = 64; uint256 constant WEDNESDAY = 65; uint256 constant NOT_WEDNESDAY = 66; uint256 constant THURSDAY = 67; uint256 constant NOT_THURSDAY = 68; uint256 constant FRIDAY = 69; uint256 constant NOT_FRIDAY = 70; uint256 constant SATURDAY = 71; uint256 constant NOT_SATURDAY = 72; uint256 constant SUNDAY = 73; uint256 constant NOT_SUNDAY = 74; uint256 constant WEEKEND = 75; uint256 constant NOT_WEEKEND = 76; uint256 constant WEEK = 77; uint256 constant NOT_WEEK = 78; uint256 constant SUMMER = 79; uint256 constant NOT_SUMMER = 80; uint256 constant WINTER = 81; uint256 constant NOT_WINTER = 82; uint256 constant SPRING = 83; uint256 constant NOT_SPRING = 84; uint256 constant AUTUMN = 85; uint256 constant NOT_AUTUMN = 86; uint256 constant IN_ANY_SEASON = 87; uint256 constant SEVEN_ELEVEN = 88; uint256 constant AT_MIDNIGHT = 89; uint256 constant HAPPY_NEW_YEAR = 90; uint256 constant A_DATE = 91; uint256 constant DO_NOTHING_FOR_5_MINUTES = 92; uint256 constant TAKE_A_MOMENT = 93; uint256 constant NOT_NOW = 94; uint256 constant SNOOZE = 95; uint256 constant DO_NOTHING_FOR_AN_HOUR = 96; uint256 constant GO_LOOK_AT_THE_SKY = 97; uint256 constant TIME_FOR_LUNCH = 98; uint256 constant DO_NOTHING_FOR_TWELVE_HOURS = 99; uint256 constant DO_NOTHING_FOR_A_DAY = 100; uint256 constant TOMORROW_IS_ANOTHER_DAY = 101; uint256 constant SLEEP_ON_IT = 102; uint256 constant TAKE_TODAY_OFF = 103; uint256 constant COME_BACK_TOMORROW = 104; uint256 constant TOUCH_GRASS = 105; uint256 constant PROCRASTINATE = 106; uint256 constant DO_NOTHING_FOR_48_HOURS = 107; uint256 constant DO_NOTHING_FOR_A_WEEK = 108; uint256 constant TAKE_A_WEEK_OFF = 109; uint256 constant HOLIDAY_TIME = 110; uint256 constant DO_NOTHING_FOR_A_MONTH = 111; uint256 constant WAIT_A_MONTH = 112; uint256 constant DO_NOTHING_FOR_A_YEAR = 113; uint256 constant NEXT_YEAR_WILL_BE_GREAT = 114; uint256 constant TWO_IN_TWO = 115; uint256 constant THREE_IN_THREE = 116; uint256 constant FIVE_IN_FIVE = 117; uint256 constant EVERY_10_MINUTES_FOR_AN_HOUR = 118; uint256 constant EVERY_DAY_FOR_A_WEEK = 119; uint256 constant STEADY_JOB = 120; uint256 constant EVERY_WEEK_FOR_A_MONTH = 121; uint256 constant EVERY_MONTH_FOR_A_YEAR = 122; uint256 constant EVERY_SEASON = 123; uint256 constant TWICE_WITHIN_A_BLOCK = 124; uint256 constant STAY_THE_WEEKEND = 125; uint256 constant STAY_THE_NIGHT = 126; uint256 constant ON_A_CONTRACT_2_DAYS = 127; uint256 constant VISIT_A_NEW_PLACE_TOMORROW = 128; uint256 constant TAKE_A_SABBATICAL = 129; uint256 constant BE_BAD_FOR_A_WEEK = 130; uint256 constant PLAY_DEAD_FOR_A_WEEK = 131; uint256 constant A_NEW_PLACE_EVERY_DAY = 132; uint256 constant ROAD_TRIP = 133; uint256 constant GO_SIGHTSEEING = 134; uint256 constant WHERE_WHERE_YOU = 135; uint256 constant TRANSFER_3_TIMES = 136; uint256 constant TRANSFER_5_TIMES = 137; uint256 constant TRANSFER_7_TIMES = 138; uint256 constant TRANSFER_10_TIMES = 139; uint256 constant DO_3 = 140; uint256 constant DO_5 = 141; uint256 constant DO_7 = 142; uint256 constant DO_10 = 143; uint256 constant GIVE_ME_5 = 144; uint256 constant RING_OF_3 = 145; uint256 constant RING_OF_5 = 146; uint256 constant RING_OF_7 = 147; uint256 constant LOVE_TRIANGLE = 148; uint256 constant ALICE_AND_BOB = 149; uint256 constant ALICE_BOB_AND_EVE = 150; uint256 constant A_B_C = 151; uint256 constant A_B_A = 152; uint256 constant ASK_FOR_HELP = 153; uint256 constant RETURN_TO_SENDER = 154; uint256 constant DO_WHAT_YOU_WANT = 155; uint256 constant ITS_NOT_MUCH = 156; uint256 constant HONEST_WORK = 157; uint256 constant ALL_PLAY_AND_NO_WORK = 158; uint256 constant SEND_IT = 159; uint256 constant JUST_TRANSFER = 160; uint256 constant TRANSFER = 161; uint256 constant DO_WHAT_YOU_LOVE = 162; uint256 constant TRANSFER_AND_MAKE_A_WISH = 163; uint256 constant TRANSFER_AND_CALL_YOUR_MOM = 164; uint256 constant TAKE_A_DEEP_BREATH = 165; uint256 constant WITH_YOUR_EYES_CLOSED = 166; uint256 constant SUCCESS = 167; uint256 constant YES = 168; uint256 constant TO_YOUR_CRUSH = 169; uint256 constant TO_SOMEONE_YOU_LIKE = 170; uint256 constant TO_SOMEONE_YOU_DONT_LIKE = 171; uint256 constant TO_SOMEONE_YOU_LOVE = 172; uint256 constant TO_SOMEONE_YOU_HATE = 173; uint256 constant SMILE = 174; uint256 constant BE_CALM = 175; uint256 constant GO_FOR_IT = 176; uint256 constant ACT_NOW = 177; uint256 constant DO_IT = 178; uint256 constant START_A_RUMOR = 179; uint256 constant DONT_DO_IT = 180; uint256 constant REFUSE = 181; uint256 constant FEELS_GOOD_TO = 182; uint256 constant DONT_THINK = 183; uint256 constant TOTAL_TODO_COUNT = 183;
{ "optimizer": { "enabled": true, "runs": 2000000 }, "evmVersion": "cancun", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"NewOwnerIsZeroAddress","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"todoId","type":"uint256"},{"indexed":false,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"address","name":"to","type":"address"}],"name":"TodoCompleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"todoIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"todoId","type":"uint256"}],"name":"TodoCreated","type":"event"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"balanceOfFrom","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"beforeTokenTransfer","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"createTodo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getTodoState","outputs":[{"internalType":"uint8","name":"open","type":"uint8"},{"internalType":"uint8","name":"max","type":"uint8"},{"internalType":"bool","name":"repeater","type":"bool"},{"internalType":"uint24","name":"todoCount","type":"uint24"},{"internalType":"uint24[3]","name":"activeTodosIndices","type":"uint24[3]"},{"internalType":"uint16[3]","name":"activeTodos","type":"uint16[3]"},{"internalType":"uint48","name":"lastTransferTime","type":"uint48"},{"internalType":"uint256[]","name":"todos","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renderContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"renderSVG","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"renderSVGBase64","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"taskId","type":"uint256"}],"name":"resolveTask","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_contract","type":"address"}],"name":"setRenderContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_contract","type":"address"}],"name":"setTokenContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"todoCounters","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokenData","outputs":[{"internalType":"uint8","name":"open","type":"uint8"},{"internalType":"uint8","name":"max","type":"uint8"},{"internalType":"bool","name":"repeater","type":"bool"},{"internalType":"uint24","name":"todoCount","type":"uint24"},{"internalType":"uint48","name":"lastTransferTime","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokenTodos","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"payable","type":"function"}]
Contract Creation Code
6080604052348015600e575f80fd5b50601633601a565b6055565b6001600160a01b0316638b78c6d819819055805f7f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08180a350565b615fad806100625f395ff3fe608060405260043610610109575f3560e01c80638da5cb5b116100a1578063c321f9b411610071578063c87b56dd11610057578063c87b56dd146103d6578063d12a4c98146103f5578063f2fde38b14610414575f80fd5b8063c321f9b414610372578063c3c3a2f0146103c3575f80fd5b80638da5cb5b14610254578063adb3ca6714610287578063b4b5b48f146102b4578063bbcd5bbe14610353575f80fd5b80635ca2ddf1116100dc5780635ca2ddf1146101db578063715018a6146101fa57806372efa29f146102025780638415d21314610235575f80fd5b8063173db2e51461010d578063456d908e1461016357806348d8afd51461018f57806355a373d6146101b0575b5f80fd5b348015610118575f80fd5b506001546101399073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561016e575f80fd5b5061018261017d36600461588c565b610427565b60405161015a91906158a3565b34801561019a575f80fd5b506101ae6101a936600461588c565b6104df565b005b3480156101bb575f80fd5b505f546101399073ffffffffffffffffffffffffffffffffffffffff1681565b3480156101e6575f80fd5b506101826101f536600461588c565b610860565b6101ae610a5d565b34801561020d575f80fd5b5061022161021c36600461588c565b610a70565b60405161015a98979695949392919061595d565b348015610240575f80fd5b506101ae61024f366004615a17565b610c45565b34801561025f575f80fd5b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffff7487392754610139565b348015610292575f80fd5b506102a66102a1366004615a30565b610c94565b60405190815260200161015a565b3480156102bf575f80fd5b506103146102ce36600461588c565b60026020525f90815260409020805460039091015460ff80831692610100810482169262010000820490921691630100000090910462ffffff169065ffffffffffff1685565b6040805160ff96871681529590941660208601529115159284019290925262ffffff909116606083015265ffffffffffff16608082015260a00161015a565b34801561035e575f80fd5b506101ae61036d366004615a17565b610cbf565b34801561037d575f80fd5b506103ae61038c366004615a30565b600560209081525f928352604080842090915290825290205463ffffffff1681565b60405163ffffffff909116815260200161015a565b6101ae6103d1366004615a50565b610d0d565b3480156103e1575f80fd5b506101826103f036600461588c565b6111d7565b348015610400575f80fd5b5061018261040f36600461588c565b611376565b6101ae610422366004615a17565b61150d565b6001546040517f456d908e0000000000000000000000000000000000000000000000000000000081526004810183905260609173ffffffffffffffffffffffffffffffffffffffff169063456d908e906024015f60405180830381865afa158015610494573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526104d99190810190615b2c565b92915050565b5f5473ffffffffffffffffffffffffffffffffffffffff163314610501575f80fd5b5f8161beef604051602001610520929190918252602082015260400190565b604051602081830303815290604052805190602001205f1c90505f826001148061054a5750826019145b806105555750826032145b806105605750826064145b90505f8161058357610573600384615c22565b61057e906001615c62565b610586565b60015b90505f6003818461060057818361ffff168361ffff1660b76105a89190615c7b565b6105b29190615c7b565b6040805160208082018b90525f8284015282516024818403018152604490920190925280519101206105e49190615c22565b6105ee9190615c8e565b6105f9906001615c8e565b9050610634565b8660010361061057506071610634565b866019036106205750606f610634565b866032036106305750606c610634565b5060645b60035f8881526020019081526020015f2081908060018154018082558091505060019003905f5260205f20015f909161ffff169091909150555f6040518060e00160405280600160ff1681526020018660ff1681526020018715158152602001600162ffffff16815260200160405180606001604052805f62ffffff1662ffffff1681526020015f62ffffff1681526020015f62ffffff16815250815260200160405180606001604052808561ffff1661ffff1681526020015f61ffff1681526020015f61ffff1681525081526020014265ffffffffffff1681525090508060025f8a81526020019081526020015f205f820151815f015f6101000a81548160ff021916908360ff1602179055506020820151815f0160016101000a81548160ff021916908360ff1602179055506040820151815f0160026101000a81548160ff0219169083151502179055506060820151815f0160036101000a81548162ffffff021916908362ffffff1602179055506080820151816001019060036107bc929190615671565b5060a08201516107d29060028301906003615709565b5060c09190910151600390910180547fffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000001665ffffffffffff909216919091179055604080518981525f602082015261ffff84168183015290517fa2c76bc2f53d218db7b73da5593a6f3b09c71e0d92aca376720d10369814f0d5916060908290030190a15050505050505050565b5f818152600260209081526040808320815160e081018352815460ff80821683526101008204811695830195909552620100008104909416151581840152630100000090930462ffffff166060808501919091528251808201938490529094939260808401919060018401906003908288855b82829054906101000a900462ffffff1662ffffff16815260200190600301906020826002010492830192600103820291508084116108d357505050928452505060408051606081019182905260209093019291506002840190600390825f855b82829054906101000a900461ffff1661ffff16815260200190600201906020826001010492830192600103820291508084116109335750505092845250505060039182015465ffffffffffff166020918201526001545f878152929091526040918290206080840151845193517f9416c65a00000000000000000000000000000000000000000000000000000000815294955073ffffffffffffffffffffffffffffffffffffffff90921693639416c65a936109f793899392909190600401615ce2565b5f60405180830381865afa158015610a11573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610a569190810190615b2c565b9392505050565b610a65611536565b610a6e5f61156b565b565b5f805f80610a7c61578c565b610a8461578c565b5f878152600260209081526040808320815160e081018352815460ff80821683526101008204811695830195909552620100008104909416151581840152630100000090930462ffffff1660608085019190915282518082019384905290938593909291608084019160018401906003908288855b82829054906101000a900462ffffff1662ffffff1681526020019060030190602082600201049283019260010382029150808411610af957505050928452505060408051606081019182905260209093019291506002840190600390825f855b82829054906101000a900461ffff1661ffff1681526020019060020190602082600101049283019260010382029150808411610b595750505092845250505060039182015465ffffffffffff166020918201525f8d8152918152604080832080548251818502810185019093528083529495509293909291830182828015610bfe57602002820191905f5260205f20905b815481526020019060010190808311610bea575b50505050509050815f015182602001518360400151846060015185608001518660a001518760c0015187995099509950995099509950995099505050919395975091939597565b610c4d611536565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6003602052815f5260405f208181548110610cad575f80fd5b905f5260205f20015f91509150505481565b610cc7611536565b5f80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b5f5473ffffffffffffffffffffffffffffffffffffffff163314610d2f575f80fd5b5f848152600260209081526040808320815160e081018352815460ff80821683526101008204811695830195909552620100008104909416151581840152630100000090930462ffffff16606080850191909152825190810192839052909160808401919060018401906003908288855b82829054906101000a900462ffffff1662ffffff1681526020019060030190602082600201049283019260010382029150808411610da057505050928452505060408051606081019182905260209093019291506002840190600390825f855b82829054906101000a900461ffff1661ffff1681526020019060020190602082600101049283019260010382029150808411610e00575050509284525050506003919091015465ffffffffffff1660209091015280519091505f9060ff165b80156110395760a08301515f90610e77600184615c7b565b60038110610e8757610e87615d1b565b602002015161ffff169050610ece88828660800151600186610ea99190615c7b565b60038110610eb957610eb9615d1b565b602002015162ffffff168e8e8e8d8d8d6115d0565b1561102657604080518981526020810183905273ffffffffffffffffffffffffffffffffffffffff8d8116828401528c16606082015290517f573c13d5af72038238ea235fec819de220e307e6ee81ca9a7d9ad8de329f938f9181900360800190a18351610f3e90600190615d48565b60ff16610f4c600184615c7b565b10156110065760808401518451610f6590600190615d48565b60ff1660038110610f7857610f78615d1b565b60200201516080850151610f8d600185615c7b565b60038110610f9d57610f9d615d1b565b62ffffff909216602092909202015260a08401518451610fbf90600190615d48565b60ff1660038110610fd257610fd2615d1b565b602002015160a0850151610fe7600185615c7b565b60038110610ff757610ff7615d1b565b61ffff90921660209290920201525b83518461101282615d61565b60ff169052508261102281615d9b565b9350505b508061103181615dd2565b915050610e5f565b50801561118b5761104b8683836141e0565b65ffffffffffff421660c08201525f87815260026020908152604091829020835181549285015193850151606086015162ffffff166301000000027fffffffffffffffffffffffffffffffffffffffffffffffffffff000000ffffff9115156201000002919091167fffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ffff60ff968716610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000090961696909316959095179390931716929092171781556080820151919350839161112f9060018301906003615671565b5060a08201516111459060028301906003615709565b5060c09190910151600390910180547fffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000001665ffffffffffff9092169190911790556111cc565b5f86815260026020526040902060030180547fffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000164265ffffffffffff161790555b505050505050505050565b5f818152600260209081526040808320815160e081018352815460ff80821683526101008204811695830195909552620100008104909416151581840152630100000090930462ffffff166060808501919091528251808201938490529094939260808401919060018401906003908288855b82829054906101000a900462ffffff1662ffffff168152602001906003019060208260020104928301926001038202915080841161124a57505050928452505060408051606081019182905260209093019291506002840190600390825f855b82829054906101000a900461ffff1661ffff16815260200190600201906020826001010492830192600103820291508084116112aa5750505092845250505060039182015465ffffffffffff166020918201526001545f87815292825260409283902060808501518551938601518686015195517ff78cd33900000000000000000000000000000000000000000000000000000000815296975073ffffffffffffffffffffffffffffffffffffffff9093169563f78cd339956109f7958b959092909190600401615e06565b5f818152600260209081526040808320815160e081018352815460ff80821683526101008204811695830195909552620100008104909416151581840152630100000090930462ffffff166060808501919091528251808201938490529094939260808401919060018401906003908288855b82829054906101000a900462ffffff1662ffffff16815260200190600301906020826002010492830192600103820291508084116113e957505050928452505060408051606081019182905260209093019291506002840190600390825f855b82829054906101000a900461ffff1661ffff16815260200190600201906020826001010492830192600103820291508084116114495750505092845250505060039182015465ffffffffffff166020918201526001545f878152929091526040918290206080840151845193517fd099110e00000000000000000000000000000000000000000000000000000000815294955073ffffffffffffffffffffffffffffffffffffffff9092169363d099110e936109f793899392909190600401615ce2565b611515611536565b8060601b61152a57637448fbae5f526004601cfd5b6115338161156b565b50565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927543314610a6e576382b429005f526004601cfd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927805473ffffffffffffffffffffffffffffffffffffffff9092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a355565b5f88609b111580156115e3575060b78911155b156115f0575060016141d3565b6004890361160657506404a817c8003a106141d3565b60328914806116155750603389145b1561163a57503273ffffffffffffffffffffffffffffffffffffffff851614156141d3565b601a8914806116495750601b89145b806116545750601c89145b1561179057606086901b7fbe000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000600c89901a60f81b161480156116fe57507fef000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000600183901a60f81b16145b8061178857508060125b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191660be60f81b14801561178857507fef000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000601383901a60f81b16145b9150506141d3565b601d890361184c57606086901b7fbe000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000600c89901a60f81b1614801561183d57507fef000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000600183901a60f81b16145b15806117885750806012611708565b601e89148061185b5750601f89145b1561199657606086901b7fde000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000600c89901a60f81b1614801561190557507fad000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000600183901a60f81b16145b8061178857507fde000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000601283901a60f81b1614801561178857508060135b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191660ad60f81b149150506141d3565b60208914806119a55750602189145b15611adf57606086901b7fba000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000600c89901a60f81b16148015611a4f57507fbe000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000600183901a60f81b16145b8061178857507fba000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000601283901a60f81b1614801561178857508060131a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191660be60f81b149150506141d3565b60228903611c1c57606086901b7fde000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000600c89901a60f81b16148015611b8c57507faf000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000600183901a60f81b16145b8061178857507fde000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000601283901a60f81b1614801561178857508060131a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191660af60f81b149150506141d3565b60238903611d5a57606086901b7ffe000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000600c89901a60f81b16148015611cc957507fed000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000600183901a60f81b16145b8061178857507ffe000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000601283901a60f81b1614801561178857508060135b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191660ed60f81b149150506141d3565b60248903611e4857606086901b7ffe000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000600c89901a60f81b16148015611e0757507fd0000000000000000000000000000000000000000000000000000000000000007ff000000000000000000000000000000000000000000000000000000000000000600183901a60f81b16145b8061178857508060121a60f81b7f0f000000000000000000000000000000000000000000000000000000000000009081161480156117885750806013611d26565b6028891480611e575750602989145b15611f9157606086901b7ffa000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000600c89901a60f81b16148015611f0157507fce000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000600183901a60f81b16145b8061178857507ffa000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000601283901a60f81b1614801561178857508060131a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191660ce60f81b149150506141d3565b6025891480611fa05750602689145b80611fab5750602789145b156120b657606086901b7fba000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000600c89901a60f81b1614801561205557507fd0000000000000000000000000000000000000000000000000000000000000007ff000000000000000000000000000000000000000000000000000000000000000600183901a60f81b16145b8061178857507f0b000000000000000000000000000000000000000000000000000000000000007f0f00000000000000000000000000000000000000000000000000000000000000601283901a60f81b161480156117885750806013611962565b600989036120c85750600134146141d3565b603489036120ef575073ffffffffffffffffffffffffffffffffffffffff851631156141d3565b60358903612116575073ffffffffffffffffffffffffffffffffffffffff861631156141d3565b603689036121475750670de0b6b3a764000073ffffffffffffffffffffffffffffffffffffffff87163110156141d3565b6038890361217957612171600273ffffffffffffffffffffffffffffffffffffffff891631615c22565b1590506141d3565b603989036121ad576121a3600273ffffffffffffffffffffffffffffffffffffffff891631615c22565b60011490506141d3565b603789036121ed578573ffffffffffffffffffffffffffffffffffffffff16318773ffffffffffffffffffffffffffffffffffffffff16311090506141d3565b605a890361221e575f80612200426145e9565b92509250508160011480156122155750806001145b925050506141d3565b605989036122575761012c6122366201518042615c22565b108061225057506201505461224e6201518042615c22565b115b90506141d3565b603b8903612290575f601861226e610e1042615e54565b6122789190615c22565b905060098110158015611788575060111190506141d3565b603c89036122c8575f60186122a7610e1042615e54565b6122b19190615c22565b9050600981108061178857506011111590506141d3565b60588903612301575f60186122df610e1042615e54565b6122e99190615c22565b905060078110158015611788575060171190506141d3565b602a8914806123105750602b89145b8061231b5750602c89145b806123265750601889145b806123315750601989145b1561236c578573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161490506141d3565b602d89148061237b5750602e89145b806123865750602f89145b156123c2578573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff16141590506141d3565b603d89036123de576007600362015180420401066001016121a3565b603f89036123fe57506002600160076201518042046003010601146141d3565b6041890361241f5760076003620151804204010660010160031490506141d3565b6043890361243f57506004600160076201518042046003010601146141d3565b6045890361245f57506005600160076201518042046003010601146141d3565b6047890361247f57506006600160076201518042046003010601146141d3565b604989036124a05760076003620151804204010660010160071490506141d3565b605c8914806124af5750605d89145b806124ba5750605e89145b156124f7575f8a81526002602052604090206003015442906124e69065ffffffffffff1661012c615e67565b65ffffffffffff16111590506141d3565b605f8903612526575f8a81526002602052604090206003015442906124e69065ffffffffffff16610258615e67565b60608914806125355750606289145b806125405750606189145b1561256c575f8a81526002602052604090206003015442906124e69065ffffffffffff16610e10615e67565b6063890361259b575f8a81526002602052604090206003015442906124e69065ffffffffffff1661a8c0615e67565b60648914806125aa5750606589145b806125b55750606689145b806125c05750606789145b806125cb5750606889145b806125d65750606989145b806125e15750606a89145b1561260e575f8a81526002602052604090206003015442906124e69065ffffffffffff1662015180615e67565b606b890361263e575f8a81526002602052604090206003015442906124e69065ffffffffffff166202a300615e67565b606c89148061264d5750606d89145b806126585750606e89145b15612685575f8a81526002602052604090206003015442906124e69065ffffffffffff1662093a80615e67565b606f8914806126945750607089145b156126c1575f8a81526002602052604090206003015442906124e69065ffffffffffff166224ea00615e67565b60718914806126d05750607289145b156126fe575f8a81526002602052604090206003015442906124e69065ffffffffffff166301dfe200615e67565b6007890361270f57503415156141d3565b6008890361271f575034156141d3565b601489148061272e5750601589145b1561273d576122506032614609565b600e89148061274c5750601089145b806127575750601289145b15612766576122506021614609565b600f8914806127755750601589145b1561278457612250603c614609565b60118914806127935750600d89145b156127a257612250600a614609565b60178914806127b15750601389145b156127c0576122506014614609565b601689036127d257612250604b614609565b603a89036127e45750600183116141d3565b6031890361280c575073ffffffffffffffffffffffffffffffffffffffff85163b15156141d3565b6030890361293557606087811b9087901b5f5b60148110156129295781816014811061283a5761283a615d1b565b1a60f81b7ff0000000000000000000000000000000000000000000000000000000000000001683826014811061287257612872615d1b565b1a60f81b7ff00000000000000000000000000000000000000000000000000000000000000016148061291157508181601481106128b1576128b1615d1b565b1a60f81b7f0f00000000000000000000000000000000000000000000000000000000000000168382601481106128e9576128e9615d1b565b1a60f81b7f0f0000000000000000000000000000000000000000000000000000000000000016145b15612921575f93505050506141d3565b60010161281f565b506001925050506141d3565b604f8903612962575f612947426145e9565b509150506006811015801561178857506008101590506141d3565b6050890361298c575f612974426145e9565b509150506006811080611788575060081090506141d3565b605189036129b8575f61299e426145e9565b50915050600c8110158061178857506002101590506141d3565b605289036129e3575f6129ca426145e9565b509150506002811180156117885750600c1190506141d3565b60538903612a10575f6129f5426145e9565b509150506003811015801561178857506005101590506141d3565b60548903612a3a575f612a22426145e9565b509150506003811080611788575060051090506141d3565b60558903612a67575f612a4c426145e9565b50915050600981101580156117885750600b101590506141d3565b60568903612a91575f612a79426145e9565b5091505060098110806117885750600b1090506141d3565b60578903612aa1575060016141d3565b604b891480612ab05750604e89145b15612ad8576001600762015180420460030106016006811480611788575060071490506141d3565b604d891480612ae75750604c89145b15612b12576001600762015180420460030106810190811080159061178857506005101590506141d3565b603e8903612b3257506001600762015180420460030106810114156141d3565b60408903612b535750600260016007620151804204600301060114156141d3565b60428903612b75576007600362015180420401066001016003141590506141d3565b60448903612b965750600460016007620151804204600301060114156141d3565b60468903612bb75750600560016007620151804204600301060114156141d3565b60488903612bd85750600660016007620151804204600301060114156141d3565b604a8903612bfa576007600362015180420401066001016007141590506141d3565b60938903612c1057612250898b89896007614653565b60928903612c2657612250898b89896005614653565b6094891480612c355750609189145b80612c405750609689145b80612c4b5750609789145b15612c5e57612250898b89896003614653565b6095891480612c6d5750609a89145b80612c785750609989145b80612c835750609889145b15612c9657612250898b89896002614653565b60738903612cac57612250898b600260786149a7565b60748903612cc257612250898b600360b46149a7565b60758903612cd957612250898b600561012c6149a7565b60768903612ec0575f8a8152600260205260409020600301544290612d089065ffffffffffff16610258615e67565b65ffffffffffff1611158015612d4a57505f8a8152600260205260409020600301544290612d409065ffffffffffff16610294615e67565b65ffffffffffff16115b15612e40575f8a815260026020908152604080832060030180547fffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000164265ffffffffffff16179055600582528083208c84529091528120805463ffffffff1691612db383615e86565b82546101009290920a63ffffffff8181021990931691831602179091555f8c81526005602081815260408084208f85529091529091205490911690039050612e3b57505f8981526005602090815260408083208b8452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000016905560016141d3565b612eb9565b5f8a815260026020908152604080832060030180547fffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000164265ffffffffffff16179055600582528083208c8452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001690555b505f6141d3565b60778903612ed457612250898b6007614d1c565b6078890361303857600760036201518042040106600101600103612f38575f8a81526005602090815260408083208c8452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000166001179055613011565b5f8a815260026020526040902060030154612f5f90620151809065ffffffffffff16615ea8565b612f6a906001615e67565b65ffffffffffff16612f7f6201518042615e54565b03612fd2575f8a81526005602090815260408083208c84529091528120805463ffffffff1691612fae83615e86565b91906101000a81548163ffffffff021916908363ffffffff16021790555050613011565b5f8a81526005602090815260408083208c8452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001690555b505f8981526005602081815260408084208c85529091529091205463ffffffff16146141d3565b6079890361304c57612250898b6004614e92565b607a89036131a3575f61305e4261504d565b5f8c815260026020526040812060030154919250906130849065ffffffffffff1661504d565b905081613092826001615ecc565b036130e5575f8c81526005602090815260408083208e84529091528120805463ffffffff16916130c183615e86565b91906101000a81548163ffffffff021916908363ffffffff1602179055505061312b565b5050505f8981526005602090815260408083208b8452909152812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001690556141d3565b5f8c81526005602090815260408083208e845290915290205463ffffffff16600b03613199575050505f8981526005602090815260408083208b8452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000016905560016141d3565b5f925050506141d3565b607b89036131b557612250898b615075565b607c89036131de57505f8981526002602052604090206003015465ffffffffffff1642146141d3565b608889036131f257612250898b6003615207565b6089890361320657612250898b6005615207565b608a890361321a57612250898b6007615207565b608b890361322e57612250898b600a615207565b6001890361326f5760016132428982615ecc565b5f8c81526002602052604090205461326691906301000000900462ffffff16615c7b565b101590506141d3565b60028903613284576005613242896001615ecc565b6003890361329957600a613242896001615ecc565b600589036132ac57612171600243615c22565b600689036132bf576121a3600243615c22565b600c8903613329576040517f70617373776f72640000000000000000000000000000000000000000000000006020820152602801604051602081830303815290604052805190602001208383604051613319929190615edf565b60405180910390201490506141d3565b600a890361333a57508015156141d3565b600b890361334a575080156141d3565b607d89036135ea575f8a81526004602090815260408083208c845282528083208151606081018352815460ff80821683526101009091041693810193909352815160e08101808452919284019160018401906007908288855b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190600401906020826003010492830192600103820291508084116133a3575050509290935250505050604081015151909150606088901b7fffffffff00000000000000000000000000000000000000000000000000000000908116911614801561347157505f8b81526002602052604090206003015461346d9065ffffffffffff166001600762015180909204600301919091060190565b6005145b801561348b57506007600362015180420401066001016001145b80156134bc57505f8b81526002602052604090206003015462093a80906134ba9065ffffffffffff1642615c7b565b105b1561350f5750505f8981526004602090815260408083208b8452909152812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001681556001908101919091556141d3565b604081015151606089901b7fffffffff000000000000000000000000000000000000000000000000000000009081169116146135e1576040818101805160608b901b7fffffffff000000000000000000000000000000000000000000000000000000001690525f8d8152600460209081528382208e83528152929020835181549385015160ff908116610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909516911617929092178255518291906135dd90600183019060076157aa565b5050505b5f9150506141d3565b607e8914806135f95750608789145b156138c4575f8a81526004602090815260408083208c845282528083208151606081018352815460ff80821683526101009091041693810193909352815160e08101808452919284019160018401906007908288855b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001906004019060208260030104928301926001038202915080841161364f57905050505050508152505090505f62015180426136bc9190615e54565b5f8d815260026020526040812060030154919250906136e790620151809065ffffffffffff16615ea8565b65ffffffffffff1690508860601b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191683604001515f6007811061372a5761372a615d1b565b60200201517fffffffff0000000000000000000000000000000000000000000000000000000016148015613767575081613765826001615ecc565b145b8015613781575061546061377e6201518042615c22565b10155b156137db575f8d81526004602090815260408083208f8452909152812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016815560018101829055905b5050600193505050506141d3565b60408301515160608b901b7fffffffff000000000000000000000000000000000000000000000000000000009081169116146138b957604083015160608b901b905f7fffffffff00000000000000000000000000000000000000000000000000000000909216602092830291909101525f8e81526004825260408082208f8352835290819020855181549387015160ff908116610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00009095169116179290921782558401518491906138b590600183019060076157aa565b5050505b5f93505050506141d3565b607f8903613aa4575f8a81526004602090815260408083208c845282528083208151606081018352815460ff80821683526101009091041693810193909352815160e08101808452919284019160018401906007908288855b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001906004019060208260030104928301926001038202915080841161391d57905050505050508152505090505f620151804261398a9190615e54565b5f8d815260026020526040812060030154919250906139b590620151809065ffffffffffff16615ea8565b65ffffffffffff1690508860601b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191683604001515f600781106139f8576139f8615d1b565b60200201517fffffffff0000000000000000000000000000000000000000000000000000000016148015613a35575081613a33826002615ecc565b145b8015613781575073ffffffffffffffffffffffffffffffffffffffff8a163b156137db575f8d81526004602090815260408083208f8452909152812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016815560018101829055906137cd565b60808903613b1c575f8a8152600260205260409020600301544290613ad49065ffffffffffff1662015180615e67565b65ffffffffffff161115801561225057508573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff16141590506141d3565b60818903613c9a575f8a81526004602090815260408083208c845282528083208151606081018352815460ff80821683526101009091041693810193909352815160e08101808452919284019160018401906007908288855b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019060040190602082600301049283019260010382029150808411613b7557905050505050508152505090505f613bdc4261504d565b5f8d81526002602052604081206003015491925090613c029065ffffffffffff1661504d565b60408401515190915060608a901b7fffffffff000000000000000000000000000000000000000000000000000000009081169116148015613781575081613c4a826003615ecc565b036137db575f8d81526004602090815260408083208f8452909152812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016815560018101829055906137cd565b60828903613e75575f600760036201518042040106600101613cbf6201518042615e54565b613cc99190615c7b565b613cd4906001615ecc565b5f8c815260026020526040812060039081015492935065ffffffffffff90921691600762015180840490910106600101613d116201518084615e54565b613d1b9190615c7b565b613d26906001615ecc565b905060608a901b83613d39836007615ecc565b148015613e6a57507fba000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000005f83901a60f81b16148015613de057507fd0000000000000000000000000000000000000000000000000000000000000007ff000000000000000000000000000000000000000000000000000000000000000600183901a60f81b16145b80613e6a57507f0b000000000000000000000000000000000000000000000000000000000000007f0f00000000000000000000000000000000000000000000000000000000000000601283901a60f81b16148015613e6a57508060135b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191660ad60f81b145b9450505050506141d3565b6083890361401c575f600760036201518042040106600101613e9a6201518042615e54565b613ea49190615c7b565b613eaf906001615ecc565b5f8c815260026020526040812060039081015492935065ffffffffffff90921691600762015180840490910106600101613eec6201518084615e54565b613ef69190615c7b565b613f01906001615ecc565b905060608a901b83613f14836007615ecc565b148015613fbb57507fde000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000005f83901a60f81b16148015613fbb57507fad000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000600183901a60f81b16145b80613e6a57507fde000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000601283901a60f81b16148015613e6a5750806013613e3d565b608489148061402b5750608589145b1561404257612250898b60078a8a620151806152c4565b6086890361405b57612250898b60048a8a610e106152c4565b608c890361406f57612250898b6003615207565b608d890361408357612250898b6005615207565b608d8914806140925750609089145b156140a357612250898b6005615207565b608e89036140b757612250898b6007615207565b608f89036140cb57612250898b600a615207565b605b89036141d0576040805160208082018d90528183018b9052825180830384018152606090920190925280519101205f806141a161410c61016d85615c22565b614117906001615ecc565b5f805f620afa6c8401935062023ab1840661016d62023ab082146105b48304618eac84048401030304606481048160021c8261016d0201038203915060996002836005020104600161030161f4ff830201600b1c84030193506b030405060708090a0b0c010260a01b811a9450506003841061019062023ab1880402820101945050509193909250565b92509250505f806141b1426145e9565b925092505081841480156141c457508083145b955050505050506141d3565b505f5b9998505050505050505050565b6141e8615830565b5f8083116141f75760016141f9565b825b9050836020015160ff1683855f015160ff166142159190615ecc565b10801561428857506020848101516040805192830188905261beef9083015260f81b7fff00000000000000000000000000000000000000000000000000000000000000166060820152600390606101604051602081830303815290604052805190602001205f1c6142869190615c22565b155b1561429b57614298600182615ecc565b90505b5f8561beef6040516020016142ba929190918252602082015260400190565b604051602081830303815290604052805190602001205f1c90505f5b828110156145de575f805f5b885160ff168110156143c557609b8960a00151826003811061430657614306615d1b565b602002015161ffff161015801561433c575060b78960a00151826003811061433057614330615d1b565b602002015161ffff1611155b1561435b5761434d609b60b7615c7b565b614358906001615ecc565b92505b886020015160ff1660011480614390575060038960a00151826003811061438457614384615d1b565b602002015161ffff1611155b806143b35750886020015160ff16895f015160016143ae9190615c62565b60ff16105b156143bd57600391505b6001016142e2565b505f805f5b60058110156144c957838461ffff168661ffff1660b76143ea9190615c7b565b6143f49190615c7b565b8861440161ffff85615eee565b8e6060015162ffffff166144159190615ecc565b604080516020810193909352820152606001604051602081830303815290604052805190602001205f1c6144499190615c22565b6144539190615c8e565b61445e906001615c8e565b92505f5b60048210801561447557508b5160ff1681105b156144ba578361ffff168c60a00151826003811061449557614495615d1b565b602002015161ffff16036144a857600192505b806144b281615d9b565b915050614462565b5081156144c9576001016143ca565b5060608a015160808b01518b5160ff16600381106144e9576144e9615d1b565b62ffffff909216602092909202015260a08a01518a5183919060ff166003811061451557614515615d1b565b61ffff909216602092909202015260608a0180519061453382615f05565b62ffffff1690525089518a61454782615f1c565b60ff169052505f8b815260036020908152604082208054600181810183559184529190922061ffff851691015560608b01517fa2c76bc2f53d218db7b73da5593a6f3b09c71e0d92aca376720d10369814f0d5918d916145a79190615f3a565b6040805192835262ffffff909116602083015261ffff85169082015260600160405180910390a15050600190920191506142d69050565b509395945050505050565b5f80806145fc6141176201518086615e54565b9196909550909350915050565b5f8160644244604051602001614629929190918252602082015260400190565b604051602081830303815290604052805190602001205f1c61464b9190615c22565b111592915050565b5f84815260046020908152604080832088845282528083208151606081018352815460ff80821683526101009091041693810193909352815160e081018084528594938401919060018401906007908288855b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190600401906020826003010492830192600103820291508084116146a657905050505050508152505090508460601b8160400151826020015160ff166007811061472457614724615d1b565b7fffffffff00000000000000000000000000000000000000000000000000000000909216602092830291909101528101518390614762906001615c62565b61476c9190615f56565b60ff9081166020830181905282519091161480156147b057506040810151517fffffffff000000000000000000000000000000000000000000000000000000001615155b1561486e578360601b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168160400151825f015160ff16600781106147f4576147f4615d1b565b60200201517fffffffff00000000000000000000000000000000000000000000000000000000160361486e5750505f848152600460209081526040808320888452909152812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016815560019081019190915561499e565b80515b816020015160ff168160ff1614614927578460601b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191682604001518260ff16600781106148be576148be615d1b565b60200201517fffffffff00000000000000000000000000000000000000000000000000000000160361490a57836148f6826001615c62565b6149009190615f56565b60ff168252614927565b83614916826001615c62565b6149209190615f56565b9050614871565b5f8781526004602090815260408083208b8452825291829020845181549286015160ff908116610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00009094169116179190911781559083015183919061499590600183019060076157aa565b505f9450505050505b95945050505050565b5f83815260046020908152604080832087845282528083208151606081018352815460ff80821683526101009091041693810193909352815160e081018084528594938401919060018401906007908288855b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190600401906020826003010492830192600103820291508084116149fa57905050505050508152505090505f63ffffffff801642614a6a9190615c22565b60e01b90505f63ffffffff614a7f8642615c7b565b614a899190615c22565b60e01b9050818360400151846020015160ff1660078110614aac57614aac615d1b565b7fffffffff00000000000000000000000000000000000000000000000000000000909216602092830291909101528301518690614aea906001615c62565b614af49190615f56565b60ff908116602085018190528451909116148015614b3857506040830151517fffffffff000000000000000000000000000000000000000000000000000000001615155b15614bf957604083015183517fffffffff000000000000000000000000000000000000000000000000000000008316919060ff1660078110614b7c57614b7c615d1b565b60200201517fffffffff000000000000000000000000000000000000000000000000000000001610614bf9575050505f848152600460209081526040808320888452909152812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001681556001908101919091559050614d14565b826020015160ff16835f015160ff1614614c9c57604083015183517fffffffff000000000000000000000000000000000000000000000000000000008316919060ff1660078110614c4c57614c4c615d1b565b60200201517fffffffff00000000000000000000000000000000000000000000000000000000161015614c9c5782518690614c88906001615c62565b614c929190615f56565b60ff168352614bf9565b5f8781526004602090815260408083208b8452825291829020855181549287015160ff908116610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000090941691161791909117815590840151849190614d0a90600183019060076157aa565b505f955050505050505b949350505050565b5f80614d2b6201518042615e54565b5f8581526002602052604081206003015491925090614d5690620151809065ffffffffffff16615ea8565b65ffffffffffff16905081614d6c826001615ecc565b03614dbf575f8581526005602090815260408083208984529091528120805463ffffffff1691614d9b83615e86565b91906101000a81548163ffffffff021916908363ffffffff16021790555050614e10565b81614dcb826001615ecc565b1015614e10575f858152600560209081526040808320898452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001690555b614e1b600185615c7b565b5f8681526005602090815260408083208a845290915290205463ffffffff1603614e87575050505f828152600560209081526040808320868452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001690556001610a56565b505f95945050505050565b5f80600760036201518042040106600101614eb06201518042615e54565b614eba9190615c7b565b614ec5906001615ecc565b5f85815260026020526040812060039081015492935065ffffffffffff90921691600762015180840490910106600101614f026201518084615e54565b614f0c9190615c7b565b614f17906001615ecc565b905082614f25826007615ecc565b03614f78575f8681526005602090815260408083208a84529091528120805463ffffffff1691614f5483615e86565b91906101000a81548163ffffffff021916908363ffffffff16021790555050614fc9565b82614f84826001615ecc565b1015614fc9575f8681526005602090815260408083208a8452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001690555b614fd4600186615c7b565b5f8781526005602090815260408083208b845290915290205463ffffffff1603615041575050505f838152600560209081526040808320878452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000169055506001610a56565b505f9695505050505050565b5f805f615059846145e9565b5090925090508061506b83600c615eee565b614d149190615ecc565b5f80615080426145e9565b505f8581526002602052604081206003015491935091506150a89065ffffffffffff166145e9565b5091505f905060036150bb600c85615c22565b6150c59190615e54565b90505f60036150d5600c85615c22565b6150df9190615e54565b90508160046150ef836001615ecc565b6150f99190615c22565b0361514c575f8681526005602090815260408083208a84529091528120805463ffffffff169161512883615e86565b91906101000a81548163ffffffff021916908363ffffffff16021790555050615196565b5050505f838152600560209081526040808320878452909152812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000016905591506104d99050565b5f8681526005602090815260408083208a845290915290205463ffffffff16600303615041575050505f838152600560209081526040808320878452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000016905550600190506104d9565b5f8281526005602090815260408083208684529091528120805463ffffffff16908261523283615e86565b82546101009290920a63ffffffff8181021990931691831602179091555f85815260056020908152604080832089845290915290205460ff851691160390506152bb57505f828152600560209081526040808320868452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001690556001610a56565b505f9392505050565b5f85815260046020908152604080832089845282528083208151606081018352815460ff80821683526101009091041693810193909352815160e081018084528594938401919060018401906007908288855b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001906004019060208260030104928301926001038202915080841161531757905050505050508152505090505f83426153819190615e54565b5f89815260026020526040812060030154919250906153a990869065ffffffffffff16615e54565b9050816153b7826001615ecc565b146153c757602083015160ff1683525b8660601b8360400151846020015160ff16600781106153e8576153e8615d1b565b7fffffffff00000000000000000000000000000000000000000000000000000000909216602092830291909101528301518890615426906001615c62565b6154309190615f56565b60ff90811660208501819052845190911614801561547457506040830151517fffffffff000000000000000000000000000000000000000000000000000000001615155b15615535578560601b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168360400151845f015160ff16600781106154b8576154b8615d1b565b60200201517fffffffff000000000000000000000000000000000000000000000000000000001603615535575050505f8681526004602090815260408083208a8452909152812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001681556001908101919091559050615667565b82515b836020015160ff168160ff16146155ee578660601b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191684604001518260ff166007811061558557615585615d1b565b60200201517fffffffff0000000000000000000000000000000000000000000000000000000016036155d157886155bd826001615c62565b6155c79190615f56565b60ff1684526155ee565b886155dd826001615c62565b6155e79190615f56565b9050615538565b5f8a81526004602090815260408083208e8452825291829020865181549288015160ff908116610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00009094169116179190911781559085015185919061565c90600183019060076157aa565b505f96505050505050505b9695505050505050565b6001830191839082156156f9579160200282015f5b838211156156c857835183826101000a81548162ffffff021916908362ffffff1602179055509260200192600301602081600201049283019260010302615686565b80156156f75782816101000a81549062ffffff02191690556003016020816002010492830192600103026156c8565b505b50615705929150615878565b5090565b6001830191839082156156f9579160200282015f5b8382111561575e57835183826101000a81548161ffff021916908361ffff160217905550926020019260020160208160010104928301926001030261571e565b80156156f75782816101000a81549061ffff021916905560020160208160010104928301926001030261575e565b60405180606001604052806003906020820280368337509192915050565b6001830191839082156156f9579160200282015f5b8382111561580057835183826101000a81548163ffffffff021916908360e01c021790555092602001926004016020816003010492830192600103026157bf565b80156156f75782816101000a81549063ffffffff0219169055600401602081600301049283019260010302615800565b6040805160e0810182525f8082526020820181905291810182905260608101919091526080810161585f61578c565b815260200161586c61578c565b81525f60209091015290565b5b80821115615705575f8155600101615879565b5f6020828403121561589c575f80fd5b5035919050565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b805f5b600381101561591d57815162ffffff168452602093840193909101906001016158f9565b50505050565b5f815180845260208085019450602084015f5b8381101561595257815187529582019590820190600101615936565b509495945050505050565b5f61018060ff8b168352602060ff8b166020850152891515604085015262ffffff8916606085015261599260808501896158f6565b60e08401875f5b60038110156159ba57815161ffff1683529183019190830190600101615999565b50505065ffffffffffff861661014085015250806101608401526159e081840185615923565b9b9a5050505050505050505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114615a12575f80fd5b919050565b5f60208284031215615a27575f80fd5b610a56826159ef565b5f8060408385031215615a41575f80fd5b50508035926020909101359150565b5f805f805f805f60c0888a031215615a66575f80fd5b615a6f886159ef565b9650615a7d602089016159ef565b9550615a8b604089016159ef565b9450606088013593506080880135925060a088013567ffffffffffffffff80821115615ab5575f80fd5b818a0191508a601f830112615ac8575f80fd5b813581811115615ad6575f80fd5b8b6020828501011115615ae7575f80fd5b60208301945080935050505092959891949750929550565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f60208284031215615b3c575f80fd5b815167ffffffffffffffff80821115615b53575f80fd5b818401915084601f830112615b66575f80fd5b815181811115615b7857615b78615aff565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715615bbe57615bbe615aff565b81604052828152876020848701011115615bd6575f80fd5b8260208601602083015e5f928101602001929092525095945050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f82615c3057615c30615bf5565b500690565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b60ff81811683821601908111156104d9576104d9615c35565b818103818111156104d9576104d9615c35565b61ffff818116838216019080821115615ca957615ca9615c35565b5092915050565b5f815480845260208085019450835f5260205f205f5b8381101561595257815487529582019560019182019101615cc6565b84815260c060208201525f615cfa60c0830186615cb0565b9050615d0960408301856158f6565b60ff831660a083015295945050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b60ff82811682821603908111156104d9576104d9615c35565b5f60ff821680615d7357615d73615c35565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0192915050565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615dcb57615dcb615c35565b5060010190565b5f81615de057615de0615c35565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b5f610100888352806020840152615e1f81840189615cb0565b915050615e2f60408301876158f6565b60ff851660a083015260ff841660c083015282151560e0830152979650505050505050565b5f82615e6257615e62615bf5565b500490565b65ffffffffffff818116838216019080821115615ca957615ca9615c35565b5f63ffffffff808316818103615e9e57615e9e615c35565b6001019392505050565b5f65ffffffffffff80841680615ec057615ec0615bf5565b92169190910492915050565b808201808211156104d9576104d9615c35565b818382375f9101908152919050565b80820281158282048414176104d9576104d9615c35565b5f62ffffff808316818103615e9e57615e9e615c35565b5f60ff821660ff8103615f3157615f31615c35565b60010192915050565b62ffffff828116828216039080821115615ca957615ca9615c35565b5f60ff831680615f6857615f68615bf5565b8060ff8416069150509291505056fea26469706673582212205740219e7c6d6df2e30f8644dc6b5e1005c5f0a4d53c0784dc4795042801ff7864736f6c63430008190033
Deployed Bytecode
0x608060405260043610610109575f3560e01c80638da5cb5b116100a1578063c321f9b411610071578063c87b56dd11610057578063c87b56dd146103d6578063d12a4c98146103f5578063f2fde38b14610414575f80fd5b8063c321f9b414610372578063c3c3a2f0146103c3575f80fd5b80638da5cb5b14610254578063adb3ca6714610287578063b4b5b48f146102b4578063bbcd5bbe14610353575f80fd5b80635ca2ddf1116100dc5780635ca2ddf1146101db578063715018a6146101fa57806372efa29f146102025780638415d21314610235575f80fd5b8063173db2e51461010d578063456d908e1461016357806348d8afd51461018f57806355a373d6146101b0575b5f80fd5b348015610118575f80fd5b506001546101399073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561016e575f80fd5b5061018261017d36600461588c565b610427565b60405161015a91906158a3565b34801561019a575f80fd5b506101ae6101a936600461588c565b6104df565b005b3480156101bb575f80fd5b505f546101399073ffffffffffffffffffffffffffffffffffffffff1681565b3480156101e6575f80fd5b506101826101f536600461588c565b610860565b6101ae610a5d565b34801561020d575f80fd5b5061022161021c36600461588c565b610a70565b60405161015a98979695949392919061595d565b348015610240575f80fd5b506101ae61024f366004615a17565b610c45565b34801561025f575f80fd5b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffff7487392754610139565b348015610292575f80fd5b506102a66102a1366004615a30565b610c94565b60405190815260200161015a565b3480156102bf575f80fd5b506103146102ce36600461588c565b60026020525f90815260409020805460039091015460ff80831692610100810482169262010000820490921691630100000090910462ffffff169065ffffffffffff1685565b6040805160ff96871681529590941660208601529115159284019290925262ffffff909116606083015265ffffffffffff16608082015260a00161015a565b34801561035e575f80fd5b506101ae61036d366004615a17565b610cbf565b34801561037d575f80fd5b506103ae61038c366004615a30565b600560209081525f928352604080842090915290825290205463ffffffff1681565b60405163ffffffff909116815260200161015a565b6101ae6103d1366004615a50565b610d0d565b3480156103e1575f80fd5b506101826103f036600461588c565b6111d7565b348015610400575f80fd5b5061018261040f36600461588c565b611376565b6101ae610422366004615a17565b61150d565b6001546040517f456d908e0000000000000000000000000000000000000000000000000000000081526004810183905260609173ffffffffffffffffffffffffffffffffffffffff169063456d908e906024015f60405180830381865afa158015610494573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526104d99190810190615b2c565b92915050565b5f5473ffffffffffffffffffffffffffffffffffffffff163314610501575f80fd5b5f8161beef604051602001610520929190918252602082015260400190565b604051602081830303815290604052805190602001205f1c90505f826001148061054a5750826019145b806105555750826032145b806105605750826064145b90505f8161058357610573600384615c22565b61057e906001615c62565b610586565b60015b90505f6003818461060057818361ffff168361ffff1660b76105a89190615c7b565b6105b29190615c7b565b6040805160208082018b90525f8284015282516024818403018152604490920190925280519101206105e49190615c22565b6105ee9190615c8e565b6105f9906001615c8e565b9050610634565b8660010361061057506071610634565b866019036106205750606f610634565b866032036106305750606c610634565b5060645b60035f8881526020019081526020015f2081908060018154018082558091505060019003905f5260205f20015f909161ffff169091909150555f6040518060e00160405280600160ff1681526020018660ff1681526020018715158152602001600162ffffff16815260200160405180606001604052805f62ffffff1662ffffff1681526020015f62ffffff1681526020015f62ffffff16815250815260200160405180606001604052808561ffff1661ffff1681526020015f61ffff1681526020015f61ffff1681525081526020014265ffffffffffff1681525090508060025f8a81526020019081526020015f205f820151815f015f6101000a81548160ff021916908360ff1602179055506020820151815f0160016101000a81548160ff021916908360ff1602179055506040820151815f0160026101000a81548160ff0219169083151502179055506060820151815f0160036101000a81548162ffffff021916908362ffffff1602179055506080820151816001019060036107bc929190615671565b5060a08201516107d29060028301906003615709565b5060c09190910151600390910180547fffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000001665ffffffffffff909216919091179055604080518981525f602082015261ffff84168183015290517fa2c76bc2f53d218db7b73da5593a6f3b09c71e0d92aca376720d10369814f0d5916060908290030190a15050505050505050565b5f818152600260209081526040808320815160e081018352815460ff80821683526101008204811695830195909552620100008104909416151581840152630100000090930462ffffff166060808501919091528251808201938490529094939260808401919060018401906003908288855b82829054906101000a900462ffffff1662ffffff16815260200190600301906020826002010492830192600103820291508084116108d357505050928452505060408051606081019182905260209093019291506002840190600390825f855b82829054906101000a900461ffff1661ffff16815260200190600201906020826001010492830192600103820291508084116109335750505092845250505060039182015465ffffffffffff166020918201526001545f878152929091526040918290206080840151845193517f9416c65a00000000000000000000000000000000000000000000000000000000815294955073ffffffffffffffffffffffffffffffffffffffff90921693639416c65a936109f793899392909190600401615ce2565b5f60405180830381865afa158015610a11573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610a569190810190615b2c565b9392505050565b610a65611536565b610a6e5f61156b565b565b5f805f80610a7c61578c565b610a8461578c565b5f878152600260209081526040808320815160e081018352815460ff80821683526101008204811695830195909552620100008104909416151581840152630100000090930462ffffff1660608085019190915282518082019384905290938593909291608084019160018401906003908288855b82829054906101000a900462ffffff1662ffffff1681526020019060030190602082600201049283019260010382029150808411610af957505050928452505060408051606081019182905260209093019291506002840190600390825f855b82829054906101000a900461ffff1661ffff1681526020019060020190602082600101049283019260010382029150808411610b595750505092845250505060039182015465ffffffffffff166020918201525f8d8152918152604080832080548251818502810185019093528083529495509293909291830182828015610bfe57602002820191905f5260205f20905b815481526020019060010190808311610bea575b50505050509050815f015182602001518360400151846060015185608001518660a001518760c0015187995099509950995099509950995099505050919395975091939597565b610c4d611536565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6003602052815f5260405f208181548110610cad575f80fd5b905f5260205f20015f91509150505481565b610cc7611536565b5f80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b5f5473ffffffffffffffffffffffffffffffffffffffff163314610d2f575f80fd5b5f848152600260209081526040808320815160e081018352815460ff80821683526101008204811695830195909552620100008104909416151581840152630100000090930462ffffff16606080850191909152825190810192839052909160808401919060018401906003908288855b82829054906101000a900462ffffff1662ffffff1681526020019060030190602082600201049283019260010382029150808411610da057505050928452505060408051606081019182905260209093019291506002840190600390825f855b82829054906101000a900461ffff1661ffff1681526020019060020190602082600101049283019260010382029150808411610e00575050509284525050506003919091015465ffffffffffff1660209091015280519091505f9060ff165b80156110395760a08301515f90610e77600184615c7b565b60038110610e8757610e87615d1b565b602002015161ffff169050610ece88828660800151600186610ea99190615c7b565b60038110610eb957610eb9615d1b565b602002015162ffffff168e8e8e8d8d8d6115d0565b1561102657604080518981526020810183905273ffffffffffffffffffffffffffffffffffffffff8d8116828401528c16606082015290517f573c13d5af72038238ea235fec819de220e307e6ee81ca9a7d9ad8de329f938f9181900360800190a18351610f3e90600190615d48565b60ff16610f4c600184615c7b565b10156110065760808401518451610f6590600190615d48565b60ff1660038110610f7857610f78615d1b565b60200201516080850151610f8d600185615c7b565b60038110610f9d57610f9d615d1b565b62ffffff909216602092909202015260a08401518451610fbf90600190615d48565b60ff1660038110610fd257610fd2615d1b565b602002015160a0850151610fe7600185615c7b565b60038110610ff757610ff7615d1b565b61ffff90921660209290920201525b83518461101282615d61565b60ff169052508261102281615d9b565b9350505b508061103181615dd2565b915050610e5f565b50801561118b5761104b8683836141e0565b65ffffffffffff421660c08201525f87815260026020908152604091829020835181549285015193850151606086015162ffffff166301000000027fffffffffffffffffffffffffffffffffffffffffffffffffffff000000ffffff9115156201000002919091167fffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ffff60ff968716610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000090961696909316959095179390931716929092171781556080820151919350839161112f9060018301906003615671565b5060a08201516111459060028301906003615709565b5060c09190910151600390910180547fffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000001665ffffffffffff9092169190911790556111cc565b5f86815260026020526040902060030180547fffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000164265ffffffffffff161790555b505050505050505050565b5f818152600260209081526040808320815160e081018352815460ff80821683526101008204811695830195909552620100008104909416151581840152630100000090930462ffffff166060808501919091528251808201938490529094939260808401919060018401906003908288855b82829054906101000a900462ffffff1662ffffff168152602001906003019060208260020104928301926001038202915080841161124a57505050928452505060408051606081019182905260209093019291506002840190600390825f855b82829054906101000a900461ffff1661ffff16815260200190600201906020826001010492830192600103820291508084116112aa5750505092845250505060039182015465ffffffffffff166020918201526001545f87815292825260409283902060808501518551938601518686015195517ff78cd33900000000000000000000000000000000000000000000000000000000815296975073ffffffffffffffffffffffffffffffffffffffff9093169563f78cd339956109f7958b959092909190600401615e06565b5f818152600260209081526040808320815160e081018352815460ff80821683526101008204811695830195909552620100008104909416151581840152630100000090930462ffffff166060808501919091528251808201938490529094939260808401919060018401906003908288855b82829054906101000a900462ffffff1662ffffff16815260200190600301906020826002010492830192600103820291508084116113e957505050928452505060408051606081019182905260209093019291506002840190600390825f855b82829054906101000a900461ffff1661ffff16815260200190600201906020826001010492830192600103820291508084116114495750505092845250505060039182015465ffffffffffff166020918201526001545f878152929091526040918290206080840151845193517fd099110e00000000000000000000000000000000000000000000000000000000815294955073ffffffffffffffffffffffffffffffffffffffff9092169363d099110e936109f793899392909190600401615ce2565b611515611536565b8060601b61152a57637448fbae5f526004601cfd5b6115338161156b565b50565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927543314610a6e576382b429005f526004601cfd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927805473ffffffffffffffffffffffffffffffffffffffff9092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a355565b5f88609b111580156115e3575060b78911155b156115f0575060016141d3565b6004890361160657506404a817c8003a106141d3565b60328914806116155750603389145b1561163a57503273ffffffffffffffffffffffffffffffffffffffff851614156141d3565b601a8914806116495750601b89145b806116545750601c89145b1561179057606086901b7fbe000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000600c89901a60f81b161480156116fe57507fef000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000600183901a60f81b16145b8061178857508060125b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191660be60f81b14801561178857507fef000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000601383901a60f81b16145b9150506141d3565b601d890361184c57606086901b7fbe000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000600c89901a60f81b1614801561183d57507fef000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000600183901a60f81b16145b15806117885750806012611708565b601e89148061185b5750601f89145b1561199657606086901b7fde000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000600c89901a60f81b1614801561190557507fad000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000600183901a60f81b16145b8061178857507fde000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000601283901a60f81b1614801561178857508060135b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191660ad60f81b149150506141d3565b60208914806119a55750602189145b15611adf57606086901b7fba000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000600c89901a60f81b16148015611a4f57507fbe000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000600183901a60f81b16145b8061178857507fba000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000601283901a60f81b1614801561178857508060131a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191660be60f81b149150506141d3565b60228903611c1c57606086901b7fde000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000600c89901a60f81b16148015611b8c57507faf000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000600183901a60f81b16145b8061178857507fde000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000601283901a60f81b1614801561178857508060131a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191660af60f81b149150506141d3565b60238903611d5a57606086901b7ffe000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000600c89901a60f81b16148015611cc957507fed000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000600183901a60f81b16145b8061178857507ffe000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000601283901a60f81b1614801561178857508060135b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191660ed60f81b149150506141d3565b60248903611e4857606086901b7ffe000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000600c89901a60f81b16148015611e0757507fd0000000000000000000000000000000000000000000000000000000000000007ff000000000000000000000000000000000000000000000000000000000000000600183901a60f81b16145b8061178857508060121a60f81b7f0f000000000000000000000000000000000000000000000000000000000000009081161480156117885750806013611d26565b6028891480611e575750602989145b15611f9157606086901b7ffa000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000600c89901a60f81b16148015611f0157507fce000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000600183901a60f81b16145b8061178857507ffa000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000601283901a60f81b1614801561178857508060131a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191660ce60f81b149150506141d3565b6025891480611fa05750602689145b80611fab5750602789145b156120b657606086901b7fba000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000600c89901a60f81b1614801561205557507fd0000000000000000000000000000000000000000000000000000000000000007ff000000000000000000000000000000000000000000000000000000000000000600183901a60f81b16145b8061178857507f0b000000000000000000000000000000000000000000000000000000000000007f0f00000000000000000000000000000000000000000000000000000000000000601283901a60f81b161480156117885750806013611962565b600989036120c85750600134146141d3565b603489036120ef575073ffffffffffffffffffffffffffffffffffffffff851631156141d3565b60358903612116575073ffffffffffffffffffffffffffffffffffffffff861631156141d3565b603689036121475750670de0b6b3a764000073ffffffffffffffffffffffffffffffffffffffff87163110156141d3565b6038890361217957612171600273ffffffffffffffffffffffffffffffffffffffff891631615c22565b1590506141d3565b603989036121ad576121a3600273ffffffffffffffffffffffffffffffffffffffff891631615c22565b60011490506141d3565b603789036121ed578573ffffffffffffffffffffffffffffffffffffffff16318773ffffffffffffffffffffffffffffffffffffffff16311090506141d3565b605a890361221e575f80612200426145e9565b92509250508160011480156122155750806001145b925050506141d3565b605989036122575761012c6122366201518042615c22565b108061225057506201505461224e6201518042615c22565b115b90506141d3565b603b8903612290575f601861226e610e1042615e54565b6122789190615c22565b905060098110158015611788575060111190506141d3565b603c89036122c8575f60186122a7610e1042615e54565b6122b19190615c22565b9050600981108061178857506011111590506141d3565b60588903612301575f60186122df610e1042615e54565b6122e99190615c22565b905060078110158015611788575060171190506141d3565b602a8914806123105750602b89145b8061231b5750602c89145b806123265750601889145b806123315750601989145b1561236c578573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161490506141d3565b602d89148061237b5750602e89145b806123865750602f89145b156123c2578573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff16141590506141d3565b603d89036123de576007600362015180420401066001016121a3565b603f89036123fe57506002600160076201518042046003010601146141d3565b6041890361241f5760076003620151804204010660010160031490506141d3565b6043890361243f57506004600160076201518042046003010601146141d3565b6045890361245f57506005600160076201518042046003010601146141d3565b6047890361247f57506006600160076201518042046003010601146141d3565b604989036124a05760076003620151804204010660010160071490506141d3565b605c8914806124af5750605d89145b806124ba5750605e89145b156124f7575f8a81526002602052604090206003015442906124e69065ffffffffffff1661012c615e67565b65ffffffffffff16111590506141d3565b605f8903612526575f8a81526002602052604090206003015442906124e69065ffffffffffff16610258615e67565b60608914806125355750606289145b806125405750606189145b1561256c575f8a81526002602052604090206003015442906124e69065ffffffffffff16610e10615e67565b6063890361259b575f8a81526002602052604090206003015442906124e69065ffffffffffff1661a8c0615e67565b60648914806125aa5750606589145b806125b55750606689145b806125c05750606789145b806125cb5750606889145b806125d65750606989145b806125e15750606a89145b1561260e575f8a81526002602052604090206003015442906124e69065ffffffffffff1662015180615e67565b606b890361263e575f8a81526002602052604090206003015442906124e69065ffffffffffff166202a300615e67565b606c89148061264d5750606d89145b806126585750606e89145b15612685575f8a81526002602052604090206003015442906124e69065ffffffffffff1662093a80615e67565b606f8914806126945750607089145b156126c1575f8a81526002602052604090206003015442906124e69065ffffffffffff166224ea00615e67565b60718914806126d05750607289145b156126fe575f8a81526002602052604090206003015442906124e69065ffffffffffff166301dfe200615e67565b6007890361270f57503415156141d3565b6008890361271f575034156141d3565b601489148061272e5750601589145b1561273d576122506032614609565b600e89148061274c5750601089145b806127575750601289145b15612766576122506021614609565b600f8914806127755750601589145b1561278457612250603c614609565b60118914806127935750600d89145b156127a257612250600a614609565b60178914806127b15750601389145b156127c0576122506014614609565b601689036127d257612250604b614609565b603a89036127e45750600183116141d3565b6031890361280c575073ffffffffffffffffffffffffffffffffffffffff85163b15156141d3565b6030890361293557606087811b9087901b5f5b60148110156129295781816014811061283a5761283a615d1b565b1a60f81b7ff0000000000000000000000000000000000000000000000000000000000000001683826014811061287257612872615d1b565b1a60f81b7ff00000000000000000000000000000000000000000000000000000000000000016148061291157508181601481106128b1576128b1615d1b565b1a60f81b7f0f00000000000000000000000000000000000000000000000000000000000000168382601481106128e9576128e9615d1b565b1a60f81b7f0f0000000000000000000000000000000000000000000000000000000000000016145b15612921575f93505050506141d3565b60010161281f565b506001925050506141d3565b604f8903612962575f612947426145e9565b509150506006811015801561178857506008101590506141d3565b6050890361298c575f612974426145e9565b509150506006811080611788575060081090506141d3565b605189036129b8575f61299e426145e9565b50915050600c8110158061178857506002101590506141d3565b605289036129e3575f6129ca426145e9565b509150506002811180156117885750600c1190506141d3565b60538903612a10575f6129f5426145e9565b509150506003811015801561178857506005101590506141d3565b60548903612a3a575f612a22426145e9565b509150506003811080611788575060051090506141d3565b60558903612a67575f612a4c426145e9565b50915050600981101580156117885750600b101590506141d3565b60568903612a91575f612a79426145e9565b5091505060098110806117885750600b1090506141d3565b60578903612aa1575060016141d3565b604b891480612ab05750604e89145b15612ad8576001600762015180420460030106016006811480611788575060071490506141d3565b604d891480612ae75750604c89145b15612b12576001600762015180420460030106810190811080159061178857506005101590506141d3565b603e8903612b3257506001600762015180420460030106810114156141d3565b60408903612b535750600260016007620151804204600301060114156141d3565b60428903612b75576007600362015180420401066001016003141590506141d3565b60448903612b965750600460016007620151804204600301060114156141d3565b60468903612bb75750600560016007620151804204600301060114156141d3565b60488903612bd85750600660016007620151804204600301060114156141d3565b604a8903612bfa576007600362015180420401066001016007141590506141d3565b60938903612c1057612250898b89896007614653565b60928903612c2657612250898b89896005614653565b6094891480612c355750609189145b80612c405750609689145b80612c4b5750609789145b15612c5e57612250898b89896003614653565b6095891480612c6d5750609a89145b80612c785750609989145b80612c835750609889145b15612c9657612250898b89896002614653565b60738903612cac57612250898b600260786149a7565b60748903612cc257612250898b600360b46149a7565b60758903612cd957612250898b600561012c6149a7565b60768903612ec0575f8a8152600260205260409020600301544290612d089065ffffffffffff16610258615e67565b65ffffffffffff1611158015612d4a57505f8a8152600260205260409020600301544290612d409065ffffffffffff16610294615e67565b65ffffffffffff16115b15612e40575f8a815260026020908152604080832060030180547fffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000164265ffffffffffff16179055600582528083208c84529091528120805463ffffffff1691612db383615e86565b82546101009290920a63ffffffff8181021990931691831602179091555f8c81526005602081815260408084208f85529091529091205490911690039050612e3b57505f8981526005602090815260408083208b8452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000016905560016141d3565b612eb9565b5f8a815260026020908152604080832060030180547fffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000164265ffffffffffff16179055600582528083208c8452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001690555b505f6141d3565b60778903612ed457612250898b6007614d1c565b6078890361303857600760036201518042040106600101600103612f38575f8a81526005602090815260408083208c8452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000166001179055613011565b5f8a815260026020526040902060030154612f5f90620151809065ffffffffffff16615ea8565b612f6a906001615e67565b65ffffffffffff16612f7f6201518042615e54565b03612fd2575f8a81526005602090815260408083208c84529091528120805463ffffffff1691612fae83615e86565b91906101000a81548163ffffffff021916908363ffffffff16021790555050613011565b5f8a81526005602090815260408083208c8452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001690555b505f8981526005602081815260408084208c85529091529091205463ffffffff16146141d3565b6079890361304c57612250898b6004614e92565b607a89036131a3575f61305e4261504d565b5f8c815260026020526040812060030154919250906130849065ffffffffffff1661504d565b905081613092826001615ecc565b036130e5575f8c81526005602090815260408083208e84529091528120805463ffffffff16916130c183615e86565b91906101000a81548163ffffffff021916908363ffffffff1602179055505061312b565b5050505f8981526005602090815260408083208b8452909152812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001690556141d3565b5f8c81526005602090815260408083208e845290915290205463ffffffff16600b03613199575050505f8981526005602090815260408083208b8452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000016905560016141d3565b5f925050506141d3565b607b89036131b557612250898b615075565b607c89036131de57505f8981526002602052604090206003015465ffffffffffff1642146141d3565b608889036131f257612250898b6003615207565b6089890361320657612250898b6005615207565b608a890361321a57612250898b6007615207565b608b890361322e57612250898b600a615207565b6001890361326f5760016132428982615ecc565b5f8c81526002602052604090205461326691906301000000900462ffffff16615c7b565b101590506141d3565b60028903613284576005613242896001615ecc565b6003890361329957600a613242896001615ecc565b600589036132ac57612171600243615c22565b600689036132bf576121a3600243615c22565b600c8903613329576040517f70617373776f72640000000000000000000000000000000000000000000000006020820152602801604051602081830303815290604052805190602001208383604051613319929190615edf565b60405180910390201490506141d3565b600a890361333a57508015156141d3565b600b890361334a575080156141d3565b607d89036135ea575f8a81526004602090815260408083208c845282528083208151606081018352815460ff80821683526101009091041693810193909352815160e08101808452919284019160018401906007908288855b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190600401906020826003010492830192600103820291508084116133a3575050509290935250505050604081015151909150606088901b7fffffffff00000000000000000000000000000000000000000000000000000000908116911614801561347157505f8b81526002602052604090206003015461346d9065ffffffffffff166001600762015180909204600301919091060190565b6005145b801561348b57506007600362015180420401066001016001145b80156134bc57505f8b81526002602052604090206003015462093a80906134ba9065ffffffffffff1642615c7b565b105b1561350f5750505f8981526004602090815260408083208b8452909152812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001681556001908101919091556141d3565b604081015151606089901b7fffffffff000000000000000000000000000000000000000000000000000000009081169116146135e1576040818101805160608b901b7fffffffff000000000000000000000000000000000000000000000000000000001690525f8d8152600460209081528382208e83528152929020835181549385015160ff908116610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909516911617929092178255518291906135dd90600183019060076157aa565b5050505b5f9150506141d3565b607e8914806135f95750608789145b156138c4575f8a81526004602090815260408083208c845282528083208151606081018352815460ff80821683526101009091041693810193909352815160e08101808452919284019160018401906007908288855b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001906004019060208260030104928301926001038202915080841161364f57905050505050508152505090505f62015180426136bc9190615e54565b5f8d815260026020526040812060030154919250906136e790620151809065ffffffffffff16615ea8565b65ffffffffffff1690508860601b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191683604001515f6007811061372a5761372a615d1b565b60200201517fffffffff0000000000000000000000000000000000000000000000000000000016148015613767575081613765826001615ecc565b145b8015613781575061546061377e6201518042615c22565b10155b156137db575f8d81526004602090815260408083208f8452909152812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016815560018101829055905b5050600193505050506141d3565b60408301515160608b901b7fffffffff000000000000000000000000000000000000000000000000000000009081169116146138b957604083015160608b901b905f7fffffffff00000000000000000000000000000000000000000000000000000000909216602092830291909101525f8e81526004825260408082208f8352835290819020855181549387015160ff908116610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00009095169116179290921782558401518491906138b590600183019060076157aa565b5050505b5f93505050506141d3565b607f8903613aa4575f8a81526004602090815260408083208c845282528083208151606081018352815460ff80821683526101009091041693810193909352815160e08101808452919284019160018401906007908288855b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001906004019060208260030104928301926001038202915080841161391d57905050505050508152505090505f620151804261398a9190615e54565b5f8d815260026020526040812060030154919250906139b590620151809065ffffffffffff16615ea8565b65ffffffffffff1690508860601b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191683604001515f600781106139f8576139f8615d1b565b60200201517fffffffff0000000000000000000000000000000000000000000000000000000016148015613a35575081613a33826002615ecc565b145b8015613781575073ffffffffffffffffffffffffffffffffffffffff8a163b156137db575f8d81526004602090815260408083208f8452909152812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016815560018101829055906137cd565b60808903613b1c575f8a8152600260205260409020600301544290613ad49065ffffffffffff1662015180615e67565b65ffffffffffff161115801561225057508573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff16141590506141d3565b60818903613c9a575f8a81526004602090815260408083208c845282528083208151606081018352815460ff80821683526101009091041693810193909352815160e08101808452919284019160018401906007908288855b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019060040190602082600301049283019260010382029150808411613b7557905050505050508152505090505f613bdc4261504d565b5f8d81526002602052604081206003015491925090613c029065ffffffffffff1661504d565b60408401515190915060608a901b7fffffffff000000000000000000000000000000000000000000000000000000009081169116148015613781575081613c4a826003615ecc565b036137db575f8d81526004602090815260408083208f8452909152812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016815560018101829055906137cd565b60828903613e75575f600760036201518042040106600101613cbf6201518042615e54565b613cc99190615c7b565b613cd4906001615ecc565b5f8c815260026020526040812060039081015492935065ffffffffffff90921691600762015180840490910106600101613d116201518084615e54565b613d1b9190615c7b565b613d26906001615ecc565b905060608a901b83613d39836007615ecc565b148015613e6a57507fba000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000005f83901a60f81b16148015613de057507fd0000000000000000000000000000000000000000000000000000000000000007ff000000000000000000000000000000000000000000000000000000000000000600183901a60f81b16145b80613e6a57507f0b000000000000000000000000000000000000000000000000000000000000007f0f00000000000000000000000000000000000000000000000000000000000000601283901a60f81b16148015613e6a57508060135b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191660ad60f81b145b9450505050506141d3565b6083890361401c575f600760036201518042040106600101613e9a6201518042615e54565b613ea49190615c7b565b613eaf906001615ecc565b5f8c815260026020526040812060039081015492935065ffffffffffff90921691600762015180840490910106600101613eec6201518084615e54565b613ef69190615c7b565b613f01906001615ecc565b905060608a901b83613f14836007615ecc565b148015613fbb57507fde000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000005f83901a60f81b16148015613fbb57507fad000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000600183901a60f81b16145b80613e6a57507fde000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000601283901a60f81b16148015613e6a5750806013613e3d565b608489148061402b5750608589145b1561404257612250898b60078a8a620151806152c4565b6086890361405b57612250898b60048a8a610e106152c4565b608c890361406f57612250898b6003615207565b608d890361408357612250898b6005615207565b608d8914806140925750609089145b156140a357612250898b6005615207565b608e89036140b757612250898b6007615207565b608f89036140cb57612250898b600a615207565b605b89036141d0576040805160208082018d90528183018b9052825180830384018152606090920190925280519101205f806141a161410c61016d85615c22565b614117906001615ecc565b5f805f620afa6c8401935062023ab1840661016d62023ab082146105b48304618eac84048401030304606481048160021c8261016d0201038203915060996002836005020104600161030161f4ff830201600b1c84030193506b030405060708090a0b0c010260a01b811a9450506003841061019062023ab1880402820101945050509193909250565b92509250505f806141b1426145e9565b925092505081841480156141c457508083145b955050505050506141d3565b505f5b9998505050505050505050565b6141e8615830565b5f8083116141f75760016141f9565b825b9050836020015160ff1683855f015160ff166142159190615ecc565b10801561428857506020848101516040805192830188905261beef9083015260f81b7fff00000000000000000000000000000000000000000000000000000000000000166060820152600390606101604051602081830303815290604052805190602001205f1c6142869190615c22565b155b1561429b57614298600182615ecc565b90505b5f8561beef6040516020016142ba929190918252602082015260400190565b604051602081830303815290604052805190602001205f1c90505f5b828110156145de575f805f5b885160ff168110156143c557609b8960a00151826003811061430657614306615d1b565b602002015161ffff161015801561433c575060b78960a00151826003811061433057614330615d1b565b602002015161ffff1611155b1561435b5761434d609b60b7615c7b565b614358906001615ecc565b92505b886020015160ff1660011480614390575060038960a00151826003811061438457614384615d1b565b602002015161ffff1611155b806143b35750886020015160ff16895f015160016143ae9190615c62565b60ff16105b156143bd57600391505b6001016142e2565b505f805f5b60058110156144c957838461ffff168661ffff1660b76143ea9190615c7b565b6143f49190615c7b565b8861440161ffff85615eee565b8e6060015162ffffff166144159190615ecc565b604080516020810193909352820152606001604051602081830303815290604052805190602001205f1c6144499190615c22565b6144539190615c8e565b61445e906001615c8e565b92505f5b60048210801561447557508b5160ff1681105b156144ba578361ffff168c60a00151826003811061449557614495615d1b565b602002015161ffff16036144a857600192505b806144b281615d9b565b915050614462565b5081156144c9576001016143ca565b5060608a015160808b01518b5160ff16600381106144e9576144e9615d1b565b62ffffff909216602092909202015260a08a01518a5183919060ff166003811061451557614515615d1b565b61ffff909216602092909202015260608a0180519061453382615f05565b62ffffff1690525089518a61454782615f1c565b60ff169052505f8b815260036020908152604082208054600181810183559184529190922061ffff851691015560608b01517fa2c76bc2f53d218db7b73da5593a6f3b09c71e0d92aca376720d10369814f0d5918d916145a79190615f3a565b6040805192835262ffffff909116602083015261ffff85169082015260600160405180910390a15050600190920191506142d69050565b509395945050505050565b5f80806145fc6141176201518086615e54565b9196909550909350915050565b5f8160644244604051602001614629929190918252602082015260400190565b604051602081830303815290604052805190602001205f1c61464b9190615c22565b111592915050565b5f84815260046020908152604080832088845282528083208151606081018352815460ff80821683526101009091041693810193909352815160e081018084528594938401919060018401906007908288855b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190600401906020826003010492830192600103820291508084116146a657905050505050508152505090508460601b8160400151826020015160ff166007811061472457614724615d1b565b7fffffffff00000000000000000000000000000000000000000000000000000000909216602092830291909101528101518390614762906001615c62565b61476c9190615f56565b60ff9081166020830181905282519091161480156147b057506040810151517fffffffff000000000000000000000000000000000000000000000000000000001615155b1561486e578360601b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168160400151825f015160ff16600781106147f4576147f4615d1b565b60200201517fffffffff00000000000000000000000000000000000000000000000000000000160361486e5750505f848152600460209081526040808320888452909152812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016815560019081019190915561499e565b80515b816020015160ff168160ff1614614927578460601b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191682604001518260ff16600781106148be576148be615d1b565b60200201517fffffffff00000000000000000000000000000000000000000000000000000000160361490a57836148f6826001615c62565b6149009190615f56565b60ff168252614927565b83614916826001615c62565b6149209190615f56565b9050614871565b5f8781526004602090815260408083208b8452825291829020845181549286015160ff908116610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00009094169116179190911781559083015183919061499590600183019060076157aa565b505f9450505050505b95945050505050565b5f83815260046020908152604080832087845282528083208151606081018352815460ff80821683526101009091041693810193909352815160e081018084528594938401919060018401906007908288855b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190600401906020826003010492830192600103820291508084116149fa57905050505050508152505090505f63ffffffff801642614a6a9190615c22565b60e01b90505f63ffffffff614a7f8642615c7b565b614a899190615c22565b60e01b9050818360400151846020015160ff1660078110614aac57614aac615d1b565b7fffffffff00000000000000000000000000000000000000000000000000000000909216602092830291909101528301518690614aea906001615c62565b614af49190615f56565b60ff908116602085018190528451909116148015614b3857506040830151517fffffffff000000000000000000000000000000000000000000000000000000001615155b15614bf957604083015183517fffffffff000000000000000000000000000000000000000000000000000000008316919060ff1660078110614b7c57614b7c615d1b565b60200201517fffffffff000000000000000000000000000000000000000000000000000000001610614bf9575050505f848152600460209081526040808320888452909152812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001681556001908101919091559050614d14565b826020015160ff16835f015160ff1614614c9c57604083015183517fffffffff000000000000000000000000000000000000000000000000000000008316919060ff1660078110614c4c57614c4c615d1b565b60200201517fffffffff00000000000000000000000000000000000000000000000000000000161015614c9c5782518690614c88906001615c62565b614c929190615f56565b60ff168352614bf9565b5f8781526004602090815260408083208b8452825291829020855181549287015160ff908116610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000090941691161791909117815590840151849190614d0a90600183019060076157aa565b505f955050505050505b949350505050565b5f80614d2b6201518042615e54565b5f8581526002602052604081206003015491925090614d5690620151809065ffffffffffff16615ea8565b65ffffffffffff16905081614d6c826001615ecc565b03614dbf575f8581526005602090815260408083208984529091528120805463ffffffff1691614d9b83615e86565b91906101000a81548163ffffffff021916908363ffffffff16021790555050614e10565b81614dcb826001615ecc565b1015614e10575f858152600560209081526040808320898452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001690555b614e1b600185615c7b565b5f8681526005602090815260408083208a845290915290205463ffffffff1603614e87575050505f828152600560209081526040808320868452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001690556001610a56565b505f95945050505050565b5f80600760036201518042040106600101614eb06201518042615e54565b614eba9190615c7b565b614ec5906001615ecc565b5f85815260026020526040812060039081015492935065ffffffffffff90921691600762015180840490910106600101614f026201518084615e54565b614f0c9190615c7b565b614f17906001615ecc565b905082614f25826007615ecc565b03614f78575f8681526005602090815260408083208a84529091528120805463ffffffff1691614f5483615e86565b91906101000a81548163ffffffff021916908363ffffffff16021790555050614fc9565b82614f84826001615ecc565b1015614fc9575f8681526005602090815260408083208a8452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001690555b614fd4600186615c7b565b5f8781526005602090815260408083208b845290915290205463ffffffff1603615041575050505f838152600560209081526040808320878452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000169055506001610a56565b505f9695505050505050565b5f805f615059846145e9565b5090925090508061506b83600c615eee565b614d149190615ecc565b5f80615080426145e9565b505f8581526002602052604081206003015491935091506150a89065ffffffffffff166145e9565b5091505f905060036150bb600c85615c22565b6150c59190615e54565b90505f60036150d5600c85615c22565b6150df9190615e54565b90508160046150ef836001615ecc565b6150f99190615c22565b0361514c575f8681526005602090815260408083208a84529091528120805463ffffffff169161512883615e86565b91906101000a81548163ffffffff021916908363ffffffff16021790555050615196565b5050505f838152600560209081526040808320878452909152812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000016905591506104d99050565b5f8681526005602090815260408083208a845290915290205463ffffffff16600303615041575050505f838152600560209081526040808320878452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000016905550600190506104d9565b5f8281526005602090815260408083208684529091528120805463ffffffff16908261523283615e86565b82546101009290920a63ffffffff8181021990931691831602179091555f85815260056020908152604080832089845290915290205460ff851691160390506152bb57505f828152600560209081526040808320868452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001690556001610a56565b505f9392505050565b5f85815260046020908152604080832089845282528083208151606081018352815460ff80821683526101009091041693810193909352815160e081018084528594938401919060018401906007908288855b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001906004019060208260030104928301926001038202915080841161531757905050505050508152505090505f83426153819190615e54565b5f89815260026020526040812060030154919250906153a990869065ffffffffffff16615e54565b9050816153b7826001615ecc565b146153c757602083015160ff1683525b8660601b8360400151846020015160ff16600781106153e8576153e8615d1b565b7fffffffff00000000000000000000000000000000000000000000000000000000909216602092830291909101528301518890615426906001615c62565b6154309190615f56565b60ff90811660208501819052845190911614801561547457506040830151517fffffffff000000000000000000000000000000000000000000000000000000001615155b15615535578560601b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168360400151845f015160ff16600781106154b8576154b8615d1b565b60200201517fffffffff000000000000000000000000000000000000000000000000000000001603615535575050505f8681526004602090815260408083208a8452909152812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001681556001908101919091559050615667565b82515b836020015160ff168160ff16146155ee578660601b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191684604001518260ff166007811061558557615585615d1b565b60200201517fffffffff0000000000000000000000000000000000000000000000000000000016036155d157886155bd826001615c62565b6155c79190615f56565b60ff1684526155ee565b886155dd826001615c62565b6155e79190615f56565b9050615538565b5f8a81526004602090815260408083208e8452825291829020865181549288015160ff908116610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00009094169116179190911781559085015185919061565c90600183019060076157aa565b505f96505050505050505b9695505050505050565b6001830191839082156156f9579160200282015f5b838211156156c857835183826101000a81548162ffffff021916908362ffffff1602179055509260200192600301602081600201049283019260010302615686565b80156156f75782816101000a81549062ffffff02191690556003016020816002010492830192600103026156c8565b505b50615705929150615878565b5090565b6001830191839082156156f9579160200282015f5b8382111561575e57835183826101000a81548161ffff021916908361ffff160217905550926020019260020160208160010104928301926001030261571e565b80156156f75782816101000a81549061ffff021916905560020160208160010104928301926001030261575e565b60405180606001604052806003906020820280368337509192915050565b6001830191839082156156f9579160200282015f5b8382111561580057835183826101000a81548163ffffffff021916908360e01c021790555092602001926004016020816003010492830192600103026157bf565b80156156f75782816101000a81549063ffffffff0219169055600401602081600301049283019260010302615800565b6040805160e0810182525f8082526020820181905291810182905260608101919091526080810161585f61578c565b815260200161586c61578c565b81525f60209091015290565b5b80821115615705575f8155600101615879565b5f6020828403121561589c575f80fd5b5035919050565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b805f5b600381101561591d57815162ffffff168452602093840193909101906001016158f9565b50505050565b5f815180845260208085019450602084015f5b8381101561595257815187529582019590820190600101615936565b509495945050505050565b5f61018060ff8b168352602060ff8b166020850152891515604085015262ffffff8916606085015261599260808501896158f6565b60e08401875f5b60038110156159ba57815161ffff1683529183019190830190600101615999565b50505065ffffffffffff861661014085015250806101608401526159e081840185615923565b9b9a5050505050505050505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114615a12575f80fd5b919050565b5f60208284031215615a27575f80fd5b610a56826159ef565b5f8060408385031215615a41575f80fd5b50508035926020909101359150565b5f805f805f805f60c0888a031215615a66575f80fd5b615a6f886159ef565b9650615a7d602089016159ef565b9550615a8b604089016159ef565b9450606088013593506080880135925060a088013567ffffffffffffffff80821115615ab5575f80fd5b818a0191508a601f830112615ac8575f80fd5b813581811115615ad6575f80fd5b8b6020828501011115615ae7575f80fd5b60208301945080935050505092959891949750929550565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f60208284031215615b3c575f80fd5b815167ffffffffffffffff80821115615b53575f80fd5b818401915084601f830112615b66575f80fd5b815181811115615b7857615b78615aff565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715615bbe57615bbe615aff565b81604052828152876020848701011115615bd6575f80fd5b8260208601602083015e5f928101602001929092525095945050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f82615c3057615c30615bf5565b500690565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b60ff81811683821601908111156104d9576104d9615c35565b818103818111156104d9576104d9615c35565b61ffff818116838216019080821115615ca957615ca9615c35565b5092915050565b5f815480845260208085019450835f5260205f205f5b8381101561595257815487529582019560019182019101615cc6565b84815260c060208201525f615cfa60c0830186615cb0565b9050615d0960408301856158f6565b60ff831660a083015295945050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b60ff82811682821603908111156104d9576104d9615c35565b5f60ff821680615d7357615d73615c35565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0192915050565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615dcb57615dcb615c35565b5060010190565b5f81615de057615de0615c35565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b5f610100888352806020840152615e1f81840189615cb0565b915050615e2f60408301876158f6565b60ff851660a083015260ff841660c083015282151560e0830152979650505050505050565b5f82615e6257615e62615bf5565b500490565b65ffffffffffff818116838216019080821115615ca957615ca9615c35565b5f63ffffffff808316818103615e9e57615e9e615c35565b6001019392505050565b5f65ffffffffffff80841680615ec057615ec0615bf5565b92169190910492915050565b808201808211156104d9576104d9615c35565b818382375f9101908152919050565b80820281158282048414176104d9576104d9615c35565b5f62ffffff808316818103615e9e57615e9e615c35565b5f60ff821660ff8103615f3157615f31615c35565b60010192915050565b62ffffff828116828216039080821115615ca957615ca9615c35565b5f60ff831680615f6857615f68615bf5565b8060ff8416069150509291505056fea26469706673582212205740219e7c6d6df2e30f8644dc6b5e1005c5f0a4d53c0784dc4795042801ff7864736f6c63430008190033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | Ether (ETH) | 100.00% | $3,114.21 | 0.000000000000000005 | <$0.000001 |
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.