Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 18 from a total of 18 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
Value | ||||
---|---|---|---|---|---|---|---|---|---|
Vote For Gauge W... | 20188506 | 2 days ago | IN | 0 ETH | 0.00069863 | ||||
Vote For Many Ga... | 20174195 | 4 days ago | IN | 0 ETH | 0.00121426 | ||||
Vote For Many Ga... | 20124348 | 11 days ago | IN | 0 ETH | 0.0036935 | ||||
Vote For Many Ga... | 20074864 | 18 days ago | IN | 0 ETH | 0.00817816 | ||||
Vote For Many Ga... | 20072835 | 18 days ago | IN | 0 ETH | 0.00334831 | ||||
Vote For Many Ga... | 20009678 | 27 days ago | IN | 0 ETH | 0.00673412 | ||||
Vote For Many Ga... | 20008703 | 27 days ago | IN | 0 ETH | 0.00623828 | ||||
Vote For Many Ga... | 20007412 | 27 days ago | IN | 0 ETH | 0.00643196 | ||||
Vote For Many Ga... | 20003165 | 28 days ago | IN | 0 ETH | 0.00604282 | ||||
Vote For Gauge W... | 19996033 | 29 days ago | IN | 0 ETH | 0.00141622 | ||||
Vote For Gauge W... | 19995639 | 29 days ago | IN | 0 ETH | 0.00140861 | ||||
Vote For Gauge W... | 19987536 | 30 days ago | IN | 0 ETH | 0.00236768 | ||||
Transfer Ownersh... | 19933017 | 38 days ago | IN | 0 ETH | 0.00141487 | ||||
Add New Board | 19922730 | 39 days ago | IN | 0 ETH | 0.00107221 | ||||
Add New Board | 19922729 | 39 days ago | IN | 0 ETH | 0.00106354 | ||||
Add New Board | 19922728 | 39 days ago | IN | 0 ETH | 0.00106111 | ||||
Add New Board | 19922727 | 39 days ago | IN | 0 ETH | 0.00103805 | ||||
0x60a03462 | 19922650 | 39 days ago | IN | Create: LootVoteController | 0 ETH | 0.02679246 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
LootVoteController
Compiler Version
v0.8.20+commit.a1b79de6
Optimization Enabled:
Yes with 999999 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
//██████╗ █████╗ ██╗ █████╗ ██████╗ ██╗███╗ ██╗ //██╔══██╗██╔══██╗██║ ██╔══██╗██╔══██╗██║████╗ ██║ //██████╔╝███████║██║ ███████║██║ ██║██║██╔██╗ ██║ //██╔═══╝ ██╔══██║██║ ██╔══██║██║ ██║██║██║╚██╗██║ //██║ ██║ ██║███████╗██║ ██║██████╔╝██║██║ ╚████║ //╚═╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚═════╝ ╚═╝╚═╝ ╚═══╝ //SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.20; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {ILootVoteController} from "./interfaces/ILootVoteController.sol"; import {IHolyPalPower} from "./interfaces/IHolyPalPower.sol"; import "./libraries/Errors.sol"; import "./utils/Owner.sol"; /** @title Loot Vote Controller contract */ /// @author Paladin /* Contract handling the vote logic for repartition of the global Loot budget between all the listed gauges for the Quest system */ contract LootVoteController is Owner, ILootVoteController { using SafeERC20 for IERC20; // Constants /** @notice Seconds in a Week */ uint256 private constant WEEK = 604800; /** @notice Unit scale for wei calculations */ uint256 private constant UNIT = 1e18; /** @notice Max BPS value */ uint256 private constant MAX_BPS = 10000; /** @notice Cooldown between 2 votes */ uint256 private constant VOTE_COOLDOWN = 864000; // 10 days /** @notice Max number of votes an user can vote at once */ uint256 private constant MAX_VOTE_LENGTH = 10; /** @notice Max number of proxies an user can have at once */ uint256 private constant MAX_PROXY_LENGTH = 50; uint256 private constant MIN_GAUGE_CAP = 0.001 * 1e18; // 0.1% uint256 private constant MAX_GAUGE_CAP = 1 * 1e18; // 100% // Structs /** @notice Quest Board & distributor struct */ struct QuestBoard { address board; address distributor; } /** @notice Point struct */ struct Point { uint256 bias; uint256 slope; } /** @notice Voted Slope struct */ struct VotedSlope { uint256 slope; uint256 power; uint256 end; address caller; } /** @notice Struct used for the vote method */ struct VoteVars { uint256 currentPeriod; uint256 nextPeriod; int128 userSlope; uint256 userLockEnd; uint256 oldBias; uint256 newBias; uint256 totalPowerUsed; uint256 oldUsedPower; uint256 oldWeightBias; uint256 oldWeightSlope; uint256 oldTotalBias; uint256 oldTotalSlope; } /** @notice Proxy Voter struct */ struct ProxyVoter { uint256 maxPower; uint256 usedPower; uint256 endTimestamp; } // Storage /** @notice Address of the hPalPower contract */ address public immutable hPalPower; /** @notice Next ID to list Boards */ uint256 public nextBoardId; // ID 0 == no ID/not set /** @notice Listed Quest Boards */ mapping(uint256 => QuestBoard) public questBoards; /** @notice Match Board address to ID */ mapping(address => uint256) public boardToId; /** @notice Match Distributor address to ID */ mapping(address => uint256) public distributorToId; /** @notice Match a Gauge to a Board ID */ mapping(address => uint256) public gaugeToBoardId; /** @notice Default weight cap for gauges */ uint256 public defaultCap = 0.1 * 1e18; // 10% /** @notice Custom caps for gauges */ mapping(address => uint256) public gaugeCaps; /** @notice Flag for killed gauges */ mapping(address => bool) public isGaugeKilled; /** @notice User VotedSlopes for each gauge */ // user -> gauge -> VotedSlope mapping(address => mapping(address => VotedSlope)) public voteUserSlopes; /** @notice Total vote power used by user */ mapping(address => uint256) public voteUserPower; /** @notice Last user vote's timestamp for each gauge address */ mapping(address => mapping(address => uint256)) public lastUserVote; /** @notice Point weight for each gauge */ // gauge -> time -> Point mapping(address => mapping(uint256 => Point)) public pointsWeight; /** @notice Slope changes for each gauge */ // gauge -> time -> slope mapping(address => mapping(uint256 => uint256)) public changesWeight; /** @notice Last scheduled time for gauge weight update */ // gauge -> last scheduled time (next week) mapping(address => uint256) public timeWeight; /** @notice Total Point weights */ // time -> Point mapping(uint256 => Point) public pointsWeightTotal; /** @notice Total weight slope changes */ // time -> slope mapping(uint256 => uint256) public changesWeightTotal; /** @notice Last scheduled time for weight update */ uint256 public timeTotal; /** @notice Proxy Managers set for each user */ // user -> proxy manager -> bool mapping(address => mapping(address => bool)) public isProxyManager; /** @notice Max Proxy duration allowed for Manager */ // user -> proxy manager -> uint256 mapping(address => mapping(address => uint256)) public maxProxyDuration; /** @notice State of Proxy Managers for each user */ // user -> proxy voter -> state mapping(address => mapping(address => ProxyVoter)) public proxyVoterState; /** @notice List of current proxy for each user */ mapping(address => address[]) public currentUserProxyVoters; /** @notice Blocked (for Proxies) voting power for each user */ mapping(address => uint256) public blockedProxyPower; /** @notice Used free voting power for each user */ mapping(address => uint256) public usedFreePower; // Events /** @notice Event emitted when a vote is casted for a gauge */ event VoteForGauge( uint256 time, address user, address gauge_addr, uint256 weight ); /** @notice Event emitted when a new Board is listed */ event NewBoardListed(uint256 id, address indexed board, address indexed distributor); /** @notice Event emitted when a Board is udpated */ event BoardUpdated(uint256 id, address indexed newDistributor); /** @notice Event emitted when a new Gauge is listed */ event NewGaugeAdded(address indexed gauge, uint256 indexed boardId, uint256 cap); /** @notice Event emitted when a Gauge is updated */ event GaugeCapUpdated(address indexed gauge, uint256 indexed boardId, uint256 newCap); /** @notice Event emitted when a Gauge is updated */ event GaugeBoardUpdated(address indexed gauge, uint256 indexed newBoardId); /** @notice Event emitted when a Gauge is killed */ event GaugeKilled(address indexed gauge, uint256 indexed boardId); /** @notice Event emitted when a Gauge is unkilled */ event GaugeUnkilled(address indexed gauge, uint256 indexed boardId); /** @notice Event emitted when a Proxy Manager is set */ event SetProxyManager(address indexed user, address indexed manager); /** @notice Event emitted when a Proxy Manager is removed */ event RemoveProxyManager(address indexed user, address indexed manager); /** @notice Event emitted when a Proxy Voter is set */ event SetNewProxyVoter(address indexed user, address indexed proxyVoter, uint256 maxPower, uint256 endTimestamp); /** @notice Event emitted when the default gauge cap is updated */ event DefaultCapUpdated(uint256 newCap); // Constructor constructor(address _hPalPower) { if(_hPalPower == address(0)) revert Errors.AddressZero(); hPalPower = _hPalPower; nextBoardId = 1; timeTotal = (block.timestamp) / WEEK * WEEK; } // View functions /** * @notice Is the gauge listed * @param gauge Address of the gauge * @return bool : Is the gauge listed */ function isListedGauge(address gauge) external view returns(bool) { return _isGaugeListed(gauge); } /** * @notice Returns the Quest Board assocatied to a gauge * @param gauge Address of the gauge * @return address : Address of the Quest Board */ function getBoardForGauge(address gauge) external view returns(address) { return questBoards[gaugeToBoardId[gauge]].board; } /** * @notice Returns the Distributor assocatied to a gauge * @param gauge Address of the gauge * @return address : Address of the Distributor */ function getDistributorForGauge(address gauge) external view returns(address) { return questBoards[gaugeToBoardId[gauge]].distributor; } /** * @notice Returns the current gauge weight * @param gauge Address of the gauge * @return uint256 : Current gauge weight */ function getGaugeWeight(address gauge) external view returns(uint256) { return pointsWeight[gauge][timeWeight[gauge]].bias; } /** * @notice Returns the gauge weight at a specific timestamp * @param gauge Address of the gauge * @param ts Timestamp * @return uint256 : Gauge weight at the timestamp */ function getGaugeWeightAt(address gauge, uint256 ts) external view returns(uint256) { ts = ts / WEEK * WEEK; return pointsWeight[gauge][ts].bias; } /** * @notice Returns the current total weight * @return uint256 : Total weight */ function getTotalWeight() external view returns(uint256) { return pointsWeightTotal[timeTotal].bias; } /** * @notice Returns a gauge relative weight * @param gauge Address of the gauge * @return uint256 : Gauge relative weight */ function getGaugeRelativeWeight(address gauge) external view returns(uint256) { return _getGaugeRelativeWeight(gauge, block.timestamp); } /** * @notice Returns a gauge relative weight at a specific timestamp * @param gauge Address of the gauge * @param ts Timestamp * @return uint256 : Gauge relative weight at the timestamp */ function getGaugeRelativeWeight(address gauge, uint256 ts) external view returns(uint256) { return _getGaugeRelativeWeight(gauge, ts); } /** * @notice Returns the cap relative weight for a gauge * @param gauge Address of the gauge * @return uint256 : Gauge cap */ function getGaugeCap(address gauge) external view returns(uint256) { return gaugeCaps[gauge] != 0 ? gaugeCaps[gauge] : defaultCap; } /** * @notice Returns the list of current proxies for a user * @param user Address of the user * @return address[] : List of proxy addresses */ function getUserProxyVoters(address user) external view returns(address[] memory) { return currentUserProxyVoters[user]; } // State-changing functions /** * @notice Votes for a gauge weight * @dev Votes for a gauge weight based on the given user power * @param gauge Address of the gauge * @param userPower Power used for this gauge */ function voteForGaugeWeights(address gauge, uint256 userPower) external { // Clear any expired past Proxy _clearExpiredProxies(msg.sender); _voteForGauge(msg.sender, gauge, userPower, msg.sender); } /** * @notice Votes for multiple gauge weights * @dev Votes for multiple gauge weights based on the given user powers * @param gauge Address of the gauges * @param userPower Power used for each gauge */ function voteForManyGaugeWeights(address[] calldata gauge, uint256[] calldata userPower) external { // Clear any expired past Proxy _clearExpiredProxies(msg.sender); uint256 length = gauge.length; if(length > MAX_VOTE_LENGTH) revert Errors.MaxVoteListExceeded(); if(length != userPower.length) revert Errors.ArraySizeMismatch(); for(uint256 i; i < length; i++) { _voteForGauge(msg.sender, gauge[i], userPower[i], msg.sender); } } /** * @notice Votes for a gauge weight as another user * @dev Votes for a gauge weight based on the given user power as another user (need to have a proxy set) * @param user Address of the user * @param gauge Address of the gauge * @param userPower Power used for this gauge */ function voteForGaugeWeightsFor(address user, address gauge, uint256 userPower) external { // Clear any expired past Proxy _clearExpiredProxies(user); ProxyVoter memory proxyState = proxyVoterState[user][msg.sender]; if(proxyState.maxPower == 0) revert Errors.NotAllowedProxyVoter(); if(proxyState.endTimestamp < block.timestamp) revert Errors.ExpiredProxy(); if(userPower > proxyState.maxPower) revert Errors.VotingPowerProxyExceeded(); _voteForGauge(user, gauge, userPower, msg.sender); } /** * @notice Votes for multiple gauge weights as another user * @dev Votes for multiple gauge weights based on the given user powers as another user (need to have a proxy set) * @param user Address of the user * @param gauge Address of the gauges * @param userPower Power used for each gauge */ function voteForManyGaugeWeightsFor(address user, address[] calldata gauge, uint256[] calldata userPower) external { // Clear any expired past Proxy _clearExpiredProxies(user); ProxyVoter memory proxyState = proxyVoterState[user][msg.sender]; if(proxyState.maxPower == 0) revert Errors.NotAllowedProxyVoter(); if(proxyState.endTimestamp < block.timestamp) revert Errors.ExpiredProxy(); uint256 totalPower; uint256 length = gauge.length; if(length > MAX_VOTE_LENGTH) revert Errors.MaxVoteListExceeded(); if(length != userPower.length) revert Errors.ArraySizeMismatch(); for(uint256 i; i < length;) { totalPower += userPower[i]; _voteForGauge(user, gauge[i], userPower[i], msg.sender); unchecked { i++; } } if(totalPower > proxyState.maxPower) revert Errors.VotingPowerProxyExceeded(); } /** * @notice Returns the updated gauge relative weight * @dev Updates the gauge weight & returns the new relative weight * @param gauge Address of the gauge * @return uint256 : Updated gauge relative weight */ function getGaugeRelativeWeightWrite(address gauge) external returns(uint256) { _updateGaugeWeight(gauge); _updateTotalWeight(); return _getGaugeRelativeWeight(gauge, block.timestamp); } /** * @notice Returns the updated gauge relative weight at a given timestamp * @dev Updates the gauge weight & returns the relative weight at a given timestamp * @param gauge Address of the gauge * @param ts Timestamp * @return uint256 : Updated gauge relative weight at the timestamp */ function getGaugeRelativeWeightWrite(address gauge, uint256 ts) external returns(uint256) { _updateGaugeWeight(gauge); _updateTotalWeight(); return _getGaugeRelativeWeight(gauge, ts); } /** * @notice Updates the gauge weight * @dev Updates a gauge current weight for all past non-updated periods * @param gauge Address of the gauge */ function updateGaugeWeight(address gauge) external { _updateGaugeWeight(gauge); } /** * @notice Updates the total weight * @dev Updates the total wieght for all past non-updated periods */ function updateTotalWeight() external { _updateTotalWeight(); } /** * @notice Approves a Proxy Manager for the caller * @dev Approves a Proxy Manager for the caller allowed to create Proxy on his voting power * @param manager Address of the Proxy Manager * @param maxDuration Maximum Proxy duration allowed to be created by the Manager (can be set to 0 for no limit) */ function approveProxyManager(address manager, uint256 maxDuration) external { if(manager == address(0)) revert Errors.AddressZero(); isProxyManager[msg.sender][manager] = true; maxProxyDuration[msg.sender][manager] = maxDuration; emit SetProxyManager(msg.sender, manager); } /** * @notice Updates the max duration allowed for a Proxy Manager * @dev Updates the max duration allowed for a Proxy Manager * @param manager Address of the Proxy Manager * @param newMaxDuration Maximum Proxy duration allowed to be created by the Manager (can be set to 0 for no limit) */ function updateProxyManagerDuration(address manager, uint256 newMaxDuration) external { if(manager == address(0)) revert Errors.AddressZero(); if(!isProxyManager[msg.sender][manager]) revert Errors.NotAllowedManager(); maxProxyDuration[msg.sender][manager] = newMaxDuration; } /** * @notice Approves a Proxy Manager for the caller * @dev Approves a Proxy Manager for the caller allowed to create Proxy on his voting power * @param manager Address of the Proxy Manager */ function removeProxyManager(address manager) external { if(manager == address(0)) revert Errors.AddressZero(); isProxyManager[msg.sender][manager] = false; emit RemoveProxyManager(msg.sender, manager); } /** * @notice Sets a Proxy Voter for the user * @dev Sets a Proxy Voter for the user allowed to vote on his behalf * @param user Address of the user * @param proxy Address of the Proxy Voter * @param maxPower Max voting power allowed for the Proxy * @param endTimestamp Timestamp of the Proxy expiry */ function setVoterProxy(address user, address proxy, uint256 maxPower, uint256 endTimestamp) external { if(!isProxyManager[user][msg.sender] && msg.sender != user) revert Errors.NotAllowedManager(); if(maxPower == 0 || maxPower > MAX_BPS) revert Errors.VotingPowerInvalid(); if(currentUserProxyVoters[user].length + 1 > MAX_PROXY_LENGTH) revert Errors.MaxProxyListExceeded(); // Round down the end timestamp to weeks & check the user Lock is not expired then endTimestamp = endTimestamp / WEEK * WEEK; uint256 userLockEnd = IHolyPalPower(hPalPower).locked__end(user); if(endTimestamp < block.timestamp || endTimestamp > userLockEnd) revert Errors.InvalidTimestamp(); uint256 maxDuration = maxProxyDuration[user][msg.sender]; if(maxDuration > 0 && endTimestamp > block.timestamp + maxDuration) revert Errors.ProxyDurationExceeded(); // Clear any expired past Proxy _clearExpiredProxies(user); // Revert if the user already has a Proxy with the same address ProxyVoter memory prevProxyState = proxyVoterState[user][proxy]; if(prevProxyState.maxPower != 0) revert Errors.ProxyAlreadyActive(); // Block the user's power for the Proxy & revert if the user execeed's its voting power uint256 userBlockedPower = blockedProxyPower[user]; if(userBlockedPower + maxPower > MAX_BPS) revert Errors.ProxyPowerExceeded(); blockedProxyPower[user] = userBlockedPower + maxPower; // Set up the Proxy proxyVoterState[user][proxy] = ProxyVoter({ maxPower: maxPower, usedPower: 0, endTimestamp: endTimestamp }); // Add the Proxy to the user's list currentUserProxyVoters[user].push(proxy); emit SetNewProxyVoter(user, proxy, maxPower, endTimestamp); } /** * @notice Clears expired Proxies for a user * @dev Clears all expired Proxies for a user & frees the blocked voting power * @param user Address of the user */ function clearUserExpiredProxies(address user) external { _clearExpiredProxies(user); } // Internal functions /** * @dev Checks if a gauge is listed * @param gauge Address of the gauge * @return bool : Is the gauge listed */ function _isGaugeListed(address gauge) internal view returns(bool) { return gaugeToBoardId[gauge] != 0; } /** * @dev Clears expired Proxies for a user & frees the blocked voting power * @param user Address of the user */ function _clearExpiredProxies(address user) internal { uint256 length = currentUserProxyVoters[user].length; if(length == 0) return; for(uint256 i; i < length;) { address proxyVoter = currentUserProxyVoters[user][i]; if(proxyVoterState[user][proxyVoter].endTimestamp < block.timestamp) { // Free the user blocked voting power blockedProxyPower[user] -= proxyVoterState[user][proxyVoter].maxPower; // Delete the Proxy delete proxyVoterState[user][proxyVoter]; // Remove the Proxy from the user's list uint256 lastIndex = length - 1; if(i != lastIndex) { currentUserProxyVoters[user][i] = currentUserProxyVoters[user][length-1]; } currentUserProxyVoters[user].pop(); length--; } else { unchecked{ i++; } } } } /** * @dev Vote for a gauge weight based on the given user power * @param user Address of the user * @param gauge Address of the gauge * @param userPower Power used for this gauge * @param caller Address of the caller */ function _voteForGauge(address user, address gauge, uint256 userPower, address caller) internal { VoteVars memory vars; // Get the periods timestamps & user lock state vars.currentPeriod = (block.timestamp) / WEEK * WEEK; vars.nextPeriod = vars.currentPeriod + WEEK; vars.userSlope = IHolyPalPower(hPalPower).getUserPoint(user).slope; vars.userLockEnd = IHolyPalPower(hPalPower).locked__end(user); // Check the gauge is listed & the user lock is not expired if(!_isGaugeListed(gauge)) revert Errors.NotListed(); if(vars.userLockEnd <= vars.nextPeriod) revert Errors.LockExpired(); // Check the user has enough voting power & the cooldown is respected if(userPower > MAX_BPS) revert Errors.VotingPowerInvalid(); if(block.timestamp < lastUserVote[user][gauge] + VOTE_COOLDOWN) revert Errors.VotingCooldown(); // Load the user past vote state VotedSlope memory oldSlope = voteUserSlopes[user][gauge]; if(oldSlope.end > vars.nextPeriod) { vars.oldBias = oldSlope.slope * (oldSlope.end - vars.nextPeriod); } // No vote to cast & no previous vote to remove == useless action if(userPower == 0 && oldSlope.power == 0) return; // Calculate the new vote state VotedSlope memory newSlope = VotedSlope({ slope: (convertInt128ToUint128(vars.userSlope) * userPower) / MAX_BPS, power: userPower, end: vars.userLockEnd, caller: caller }); vars.newBias = newSlope.slope * (vars.userLockEnd - vars.nextPeriod); // Check if the caller is allowed to change this vote if( oldSlope.caller != caller && proxyVoterState[user][oldSlope.caller].endTimestamp > block.timestamp ) revert Errors.NotAllowedVoteChange(); // Update the voter used voting power & the proxy one if needed vars.totalPowerUsed = voteUserPower[user]; vars.totalPowerUsed = vars.totalPowerUsed + newSlope.power - oldSlope.power; if(user == caller) { uint256 usedPower = usedFreePower[user]; vars.oldUsedPower = oldSlope.caller != user ? 0 : oldSlope.power; usedPower = usedPower + newSlope.power - vars.oldUsedPower; if(usedPower > (MAX_BPS - blockedProxyPower[user])) revert Errors.VotingPowerExceeded(); usedFreePower[user] = usedPower; } else { uint256 proxyPower = proxyVoterState[user][caller].usedPower; vars.oldUsedPower = oldSlope.caller == caller ? oldSlope.power : 0; proxyPower = proxyPower + newSlope.power - vars.oldUsedPower; if(oldSlope.caller == user) { usedFreePower[user] -= oldSlope.power; } if(proxyPower > proxyVoterState[user][caller].maxPower) revert Errors.VotingPowerProxyExceeded(); proxyVoterState[user][caller].usedPower = proxyPower; } if(vars.totalPowerUsed > MAX_BPS) revert Errors.VotingPowerExceeded(); voteUserPower[user] = vars.totalPowerUsed; // Update the gauge weight vars.oldWeightBias = _updateGaugeWeight(gauge); vars.oldWeightSlope = pointsWeight[gauge][vars.nextPeriod].slope; // Update the total weight vars.oldTotalBias = _updateTotalWeight(); vars.oldTotalSlope = pointsWeightTotal[vars.nextPeriod].slope; // Update the new gauge bias & total bias pointsWeight[gauge][vars.nextPeriod].bias = max(vars.oldWeightBias + vars.newBias, vars.oldBias) - vars.oldBias; pointsWeightTotal[vars.nextPeriod].bias = max(vars.oldTotalBias + vars.newBias, vars.oldBias) - vars.oldBias; // Update the new gauge slope & total slope if(oldSlope.end > vars.nextPeriod) { pointsWeight[gauge][vars.nextPeriod].slope = max(vars.oldWeightSlope + newSlope.slope, oldSlope.slope) - oldSlope.slope; pointsWeightTotal[vars.nextPeriod].slope = max(vars.oldTotalSlope + newSlope.slope, oldSlope.slope) - oldSlope.slope; } else { pointsWeight[gauge][vars.nextPeriod].slope += newSlope.slope; pointsWeightTotal[vars.nextPeriod].slope += newSlope.slope; } // Update the gauge slope changes & total slope changes if(oldSlope.end > block.timestamp) { changesWeight[gauge][oldSlope.end] -= oldSlope.slope; changesWeightTotal[oldSlope.end] -= oldSlope.slope; } changesWeight[gauge][newSlope.end] += newSlope.slope; changesWeightTotal[newSlope.end] += newSlope.slope; // Store the user vote state voteUserSlopes[user][gauge] = newSlope; lastUserVote[user][gauge] = block.timestamp; emit VoteForGauge(block.timestamp, user, gauge, userPower); } /** * @dev Returns a gauge relative weight based on its weight and the total weight at a given period * @param gauge Address of the gauge * @param ts Timestamp * @return uint256 : Gauge relative weight */ function _getGaugeRelativeWeight(address gauge, uint256 ts) internal view returns(uint256) { if(isGaugeKilled[gauge]) return 0; ts = ts / WEEK * WEEK; uint256 _totalWeight = pointsWeightTotal[ts].bias; if(_totalWeight == 0) return 0; return (pointsWeight[gauge][ts].bias * UNIT) / _totalWeight; } /** * @dev Updates the gauge weight for all past non-updated periods & returns the current gauge weight * @param gauge Address of the gauge * @return uint256 : Current gauge weight */ function _updateGaugeWeight(address gauge) internal returns(uint256) { uint256 ts = timeWeight[gauge]; if(ts == 0) return 0; Point memory _point = pointsWeight[gauge][ts]; for(uint256 i; i < 500; i++) { if(ts > block.timestamp) break; ts += WEEK; uint256 decreaseBias = _point.slope * WEEK; if(decreaseBias >= _point.bias) { _point.bias = 0; _point.slope = 0; } else { _point.bias -= decreaseBias; uint256 decreaseSlope = changesWeight[gauge][ts]; _point.slope -= decreaseSlope; } pointsWeight[gauge][ts] = _point; if(ts > block.timestamp) { timeWeight[gauge] = ts; } } return _point.bias; } /** * @dev Updates the total weight for all past non-updated periods & returns the current total weight * @return uint256 : Current total weight */ function _updateTotalWeight() internal returns(uint256) { uint256 ts = timeTotal; if(ts == 0) return 0; Point memory _point = pointsWeightTotal[ts]; for(uint256 i; i < 500; i++) { if(ts > block.timestamp) break; ts += WEEK; uint256 decreaseBias = _point.slope * WEEK; if(decreaseBias >= _point.bias) { _point.bias = 0; _point.slope = 0; } else { _point.bias -= decreaseBias; uint256 decreaseSlope = changesWeightTotal[ts]; _point.slope -= decreaseSlope; } pointsWeightTotal[ts] = _point; if(ts > block.timestamp) { timeTotal = ts; } } return _point.bias; } // Admin functions /** * @notice Adds a new Quest Board & its Distributor * @dev Adds a new Quest Board & its Distributor * @param board Address of the Quest Board * @param distributor Address of the Distributor */ function addNewBoard(address board, address distributor) external onlyOwner { if(board == address(0) || distributor == address(0)) revert Errors.AddressZero(); if(boardToId[board] != 0 || distributorToId[distributor] != 0) revert Errors.AlreadyListed(); uint256 boardId = nextBoardId; nextBoardId++; questBoards[boardId] = QuestBoard(board, distributor); boardToId[board] = boardId; distributorToId[distributor] = boardId; emit NewBoardListed(boardId, board, distributor); } /** * @notice Updates the Distributor for a Quest Board * @dev Updates the Distributor for a Quest Board * @param board Address of the Quest Board * @param newDistributor Address of the new Distributor */ function updateDistributor(address board, address newDistributor) external onlyOwner { if(board == address(0) || newDistributor == address(0)) revert Errors.AddressZero(); if(distributorToId[newDistributor] != 0) revert Errors.AlreadyListed(); uint256 boardId = boardToId[board]; if(boardId == 0) revert Errors.InvalidParameter(); questBoards[boardId].distributor = newDistributor; distributorToId[newDistributor] = boardId; emit BoardUpdated(boardId, newDistributor); } /** * @notice Adds a new Gauge (with a cap) * @dev Adds a new Gauge linked to a listed Quest Board & sets a weight cap * @param gauge Address of the gauge * @param boardId ID of the Quest Board * @param cap Weight cap for the gauge */ function addNewGauge(address gauge, uint256 boardId, uint256 cap) external onlyOwner { if(gauge == address(0)) revert Errors.AddressZero(); if(boardId == 0) revert Errors.InvalidParameter(); if(_isGaugeListed(gauge)) revert Errors.AlreadyListed(); if((cap < MIN_GAUGE_CAP && cap != 0) || cap > MAX_GAUGE_CAP) revert Errors.InvalidGaugeCap(); gaugeToBoardId[gauge] = boardId; gaugeCaps[gauge] = cap; timeWeight[gauge] = (block.timestamp + WEEK) / WEEK * WEEK; emit NewGaugeAdded(gauge, boardId, cap); } /** * @notice Updates the Board ID for a gauge * @dev Updates the Board ID for a gauge * @param gauge Address of the gauge * @param newBoardId New Board ID for the gauge */ function updateGaugeBoard(address gauge, uint256 newBoardId) external onlyOwner { if(gauge == address(0)) revert Errors.AddressZero(); if(gaugeToBoardId[gauge] == 0) revert Errors.InvalidParameter(); if(isGaugeKilled[gauge]) revert Errors.KilledGauge(); gaugeToBoardId[gauge] = newBoardId; emit GaugeBoardUpdated(gauge, newBoardId); } /** * @notice Updates the weight cap for a gauge * @dev Updates the weight cap for a gauge * @param gauge Address of the gauge * @param newCap New weight cap for the gauge */ function updateGaugeCap(address gauge, uint256 newCap) external onlyOwner { if(gauge == address(0)) revert Errors.AddressZero(); if(gaugeToBoardId[gauge] == 0) revert Errors.InvalidParameter(); if(isGaugeKilled[gauge]) revert Errors.KilledGauge(); if((newCap < MIN_GAUGE_CAP && newCap != 0) || newCap > MAX_GAUGE_CAP) revert Errors.InvalidGaugeCap(); gaugeCaps[gauge] = newCap; emit GaugeCapUpdated(gauge, gaugeToBoardId[gauge], newCap); } /** * @notice Updates the default weight cap * @dev Updates the default weight cap * @param newCap New default weight cap */ function updateDefaultGaugeCap(uint256 newCap) external onlyOwner { if(newCap < MIN_GAUGE_CAP || newCap > MAX_GAUGE_CAP) revert Errors.InvalidGaugeCap(); defaultCap = newCap; emit DefaultCapUpdated(newCap); } /** * @notice Kills a gauge * @dev Kills a gauge, blocking the votes & weight updates * @param gauge Address of the gauge */ function killGauge(address gauge) external onlyOwner { if(gauge == address(0)) revert Errors.AddressZero(); if(!_isGaugeListed(gauge)) revert Errors.NotListed(); if(isGaugeKilled[gauge]) revert Errors.KilledGauge(); isGaugeKilled[gauge] = true; emit GaugeKilled(gauge, gaugeToBoardId[gauge]); } /** * @notice Unkills a gauge * @dev Unkills a gauge, unblocking the votes & weight updates * @param gauge Address of the gauge */ function unkillGauge(address gauge) external onlyOwner { if(gauge == address(0)) revert Errors.AddressZero(); if(!isGaugeKilled[gauge]) revert Errors.NotKilledGauge(); isGaugeKilled[gauge] = false; emit GaugeUnkilled(gauge, gaugeToBoardId[gauge]); } // Maths function convertInt128ToUint128(int128 value) internal pure returns(uint128) { if (value < 0) revert Errors.ConversionOverflow(); return uint128(value); } function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {Context} from "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ constructor(address initialOwner) { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; import {IERC20Permit} from "../extensions/IERC20Permit.sol"; import {Address} from "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev An operation with an ERC20 token failed. */ error SafeERC20FailedOperation(address token); /** * @dev Indicates a failed `decreaseAllowance` request. */ error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease); /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value))); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value))); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); forceApprove(token, spender, oldAllowance + value); } /** * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no * value, non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal { unchecked { uint256 currentAllowance = token.allowance(address(this), spender); if (currentAllowance < requestedDecrease) { revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease); } forceApprove(token, spender, currentAllowance - requestedDecrease); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value)); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0))); _callOptionalReturn(token, approvalCall); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data); if (returndata.length != 0 && !abi.decode(returndata, (bool))) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol) pragma solidity ^0.8.20; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error AddressInsufficientBalance(address account); /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedInnerCall(); /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert AddressInsufficientBalance(address(this)); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert FailedInnerCall(); } } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {FailedInnerCall} error. * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert AddressInsufficientBalance(address(this)); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an * unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {FailedInnerCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}. */ function _revert(bytes memory returndata) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert FailedInnerCall(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: Unlicensed pragma solidity 0.8.20; interface IHolyPalPower { // Structs struct Point { int128 bias; int128 slope; uint256 endTimestamp; uint256 blockNumber; } // Functions function balanceOf(address user) external view returns(uint256); function balanceOfAt(address user, uint256 timestamp) external view returns(uint256); function getUserPoint(address user) external view returns(Point memory); function getUserPointAt(address user, uint256 timestamp) external view returns(Point memory); // to match with veToken interface // solhint-disable-next-line function locked__end(address user) external view returns(uint256); function totalSupply() external view returns(uint256); function totalLocked() external view returns(uint256); function totalLockedAt(uint256 blockNumber) external view returns(uint256); function findTotalLockedAt(uint256 timestamp) external view returns(uint256); }
// SPDX-License-Identifier: Unlicensed pragma solidity 0.8.20; interface ILootVoteController { function isListedGauge(address gauge) external view returns(bool); function getBoardForGauge(address gauge) external view returns(address); function getDistributorForGauge(address gauge) external view returns(address); function getGaugeWeight(address gauge) external view returns(uint256); function getGaugeWeightAt(address gauge, uint256 ts) external view returns(uint256); function getTotalWeight() external view returns(uint256); function getGaugeRelativeWeight(address gauge) external view returns(uint256); function getGaugeRelativeWeight(address gauge, uint256 ts) external view returns(uint256); function getGaugeRelativeWeightWrite(address gauge) external returns(uint256); function getGaugeRelativeWeightWrite(address gauge, uint256 ts) external returns(uint256); function getGaugeCap(address gauge) external view returns(uint256); function getUserProxyVoters(address user) external view returns(address[] memory); function voteForGaugeWeights(address gauge, uint256 userPower) external; function voteForManyGaugeWeights(address[] memory gauge, uint256[] memory userPower) external; function voteForGaugeWeightsFor(address user, address gauge, uint256 userPower) external; function voteForManyGaugeWeightsFor(address user, address[] memory gauge, uint256[] memory userPower) external; function updateGaugeWeight(address gauge) external; function updateTotalWeight() external; function approveProxyManager(address manager, uint256 maxDuration) external; function removeProxyManager(address manager) external; function setVoterProxy(address user, address proxy, uint256 maxPower, uint256 endTimestamp) external; function clearUserExpiredProxies(address user) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.20; library Errors { // Commons error AddressZero(); error NullAmount(); error InvalidParameter(); error SameAddress(); error ArraySizeMismatch(); error AlreadyInitialized(); // Access Control error CannotBeOwner(); error CallerNotPendingOwner(); error CallerNotAllowed(); // Merkle Distributor error EmptyParameters(); error InvalidProof(); error AlreadyClaimed(); error MerkleRootNotUpdated(); error EmptyMerkleRoot(); error IncorrectQuestID(); error QuestAlreadyListed(); error QuestNotListed(); error PeriodAlreadyUpdated(); error PeriodNotClosed(); error IncorrectPeriod(); error PeriodNotListed(); error TokenNotWhitelisted(); error IncorrectRewardAmount(); error CannotRecoverToken(); // HolyPalPower error InvalidTimestamp(); // Vote Controller error AlreadyListed(); error LockExpired(); error VotingPowerInvalid(); error VotingPowerExceeded(); error VotingPowerProxyExceeded(); error VotingCooldown(); error KilledGauge(); error NotKilledGauge(); error NotAllowedManager(); error NotAllowedProxyVoter(); error ExpiredProxy(); error ProxyAlreadyActive(); error ProxyPowerExceeded(); error ProxyDurationExceeded(); error NotAllowedVoteChange(); error MaxVoteListExceeded(); error MaxProxyListExceeded(); error InvalidGaugeCap(); // Loot error CreatorAlreadySet(); error InvalidId(uint256 id); error VestingNotStarted(uint256 id); // Loot Creator error NotListed(); // Loot Buget error LootBudgetExceedLimit(); //Maths error ConversionOverflow(); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.20; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import "../libraries/Errors.sol"; /** @title 2-step Ownership */ /// @author Paladin /* Extends OZ Ownable contract to add 2-step ownership transfer */ contract Owner is Ownable { address public pendingOwner; event NewPendingOwner(address indexed previousPendingOwner, address indexed newPendingOwner); constructor() Ownable(msg.sender) {} function transferOwnership(address newOwner) public override virtual onlyOwner { if(newOwner == address(0)) revert Errors.AddressZero(); if(newOwner == owner()) revert Errors.CannotBeOwner(); address oldPendingOwner = pendingOwner; pendingOwner = newOwner; emit NewPendingOwner(oldPendingOwner, newOwner); } function acceptOwnership() public virtual { if(msg.sender != pendingOwner) revert Errors.CallerNotPendingOwner(); address newOwner = pendingOwner; _transferOwnership(pendingOwner); pendingOwner = address(0); emit NewPendingOwner(newOwner, address(0)); } }
{ "optimizer": { "enabled": true, "runs": 999999 }, "viaIR": true, "evmVersion": "paris", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_hPalPower","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AddressZero","type":"error"},{"inputs":[],"name":"AlreadyListed","type":"error"},{"inputs":[],"name":"ArraySizeMismatch","type":"error"},{"inputs":[],"name":"CallerNotPendingOwner","type":"error"},{"inputs":[],"name":"CannotBeOwner","type":"error"},{"inputs":[],"name":"ConversionOverflow","type":"error"},{"inputs":[],"name":"ExpiredProxy","type":"error"},{"inputs":[],"name":"InvalidGaugeCap","type":"error"},{"inputs":[],"name":"InvalidParameter","type":"error"},{"inputs":[],"name":"InvalidTimestamp","type":"error"},{"inputs":[],"name":"KilledGauge","type":"error"},{"inputs":[],"name":"LockExpired","type":"error"},{"inputs":[],"name":"MaxProxyListExceeded","type":"error"},{"inputs":[],"name":"MaxVoteListExceeded","type":"error"},{"inputs":[],"name":"NotAllowedManager","type":"error"},{"inputs":[],"name":"NotAllowedProxyVoter","type":"error"},{"inputs":[],"name":"NotAllowedVoteChange","type":"error"},{"inputs":[],"name":"NotKilledGauge","type":"error"},{"inputs":[],"name":"NotListed","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ProxyAlreadyActive","type":"error"},{"inputs":[],"name":"ProxyDurationExceeded","type":"error"},{"inputs":[],"name":"ProxyPowerExceeded","type":"error"},{"inputs":[],"name":"VotingCooldown","type":"error"},{"inputs":[],"name":"VotingPowerExceeded","type":"error"},{"inputs":[],"name":"VotingPowerInvalid","type":"error"},{"inputs":[],"name":"VotingPowerProxyExceeded","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"newDistributor","type":"address"}],"name":"BoardUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newCap","type":"uint256"}],"name":"DefaultCapUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"gauge","type":"address"},{"indexed":true,"internalType":"uint256","name":"newBoardId","type":"uint256"}],"name":"GaugeBoardUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"gauge","type":"address"},{"indexed":true,"internalType":"uint256","name":"boardId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newCap","type":"uint256"}],"name":"GaugeCapUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"gauge","type":"address"},{"indexed":true,"internalType":"uint256","name":"boardId","type":"uint256"}],"name":"GaugeKilled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"gauge","type":"address"},{"indexed":true,"internalType":"uint256","name":"boardId","type":"uint256"}],"name":"GaugeUnkilled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"board","type":"address"},{"indexed":true,"internalType":"address","name":"distributor","type":"address"}],"name":"NewBoardListed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"gauge","type":"address"},{"indexed":true,"internalType":"uint256","name":"boardId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"cap","type":"uint256"}],"name":"NewGaugeAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousPendingOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newPendingOwner","type":"address"}],"name":"NewPendingOwner","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"manager","type":"address"}],"name":"RemoveProxyManager","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"proxyVoter","type":"address"},{"indexed":false,"internalType":"uint256","name":"maxPower","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endTimestamp","type":"uint256"}],"name":"SetNewProxyVoter","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"manager","type":"address"}],"name":"SetProxyManager","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"},{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"address","name":"gauge_addr","type":"address"},{"indexed":false,"internalType":"uint256","name":"weight","type":"uint256"}],"name":"VoteForGauge","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"board","type":"address"},{"internalType":"address","name":"distributor","type":"address"}],"name":"addNewBoard","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"gauge","type":"address"},{"internalType":"uint256","name":"boardId","type":"uint256"},{"internalType":"uint256","name":"cap","type":"uint256"}],"name":"addNewGauge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"manager","type":"address"},{"internalType":"uint256","name":"maxDuration","type":"uint256"}],"name":"approveProxyManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"blockedProxyPower","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"boardToId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"changesWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"changesWeightTotal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"clearUserExpiredProxies","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"currentUserProxyVoters","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"defaultCap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"distributorToId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"gaugeCaps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"gaugeToBoardId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"gauge","type":"address"}],"name":"getBoardForGauge","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"gauge","type":"address"}],"name":"getDistributorForGauge","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"gauge","type":"address"}],"name":"getGaugeCap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"gauge","type":"address"}],"name":"getGaugeRelativeWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"gauge","type":"address"},{"internalType":"uint256","name":"ts","type":"uint256"}],"name":"getGaugeRelativeWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"gauge","type":"address"},{"internalType":"uint256","name":"ts","type":"uint256"}],"name":"getGaugeRelativeWeightWrite","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"gauge","type":"address"}],"name":"getGaugeRelativeWeightWrite","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"gauge","type":"address"}],"name":"getGaugeWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"gauge","type":"address"},{"internalType":"uint256","name":"ts","type":"uint256"}],"name":"getGaugeWeightAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getUserProxyVoters","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hPalPower","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isGaugeKilled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"gauge","type":"address"}],"name":"isListedGauge","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isProxyManager","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"gauge","type":"address"}],"name":"killGauge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"lastUserVote","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"maxProxyDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextBoardId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"pointsWeight","outputs":[{"internalType":"uint256","name":"bias","type":"uint256"},{"internalType":"uint256","name":"slope","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"pointsWeightTotal","outputs":[{"internalType":"uint256","name":"bias","type":"uint256"},{"internalType":"uint256","name":"slope","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"proxyVoterState","outputs":[{"internalType":"uint256","name":"maxPower","type":"uint256"},{"internalType":"uint256","name":"usedPower","type":"uint256"},{"internalType":"uint256","name":"endTimestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"questBoards","outputs":[{"internalType":"address","name":"board","type":"address"},{"internalType":"address","name":"distributor","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"manager","type":"address"}],"name":"removeProxyManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"proxy","type":"address"},{"internalType":"uint256","name":"maxPower","type":"uint256"},{"internalType":"uint256","name":"endTimestamp","type":"uint256"}],"name":"setVoterProxy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"timeTotal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"timeWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"gauge","type":"address"}],"name":"unkillGauge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newCap","type":"uint256"}],"name":"updateDefaultGaugeCap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"board","type":"address"},{"internalType":"address","name":"newDistributor","type":"address"}],"name":"updateDistributor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"gauge","type":"address"},{"internalType":"uint256","name":"newBoardId","type":"uint256"}],"name":"updateGaugeBoard","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"gauge","type":"address"},{"internalType":"uint256","name":"newCap","type":"uint256"}],"name":"updateGaugeCap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"gauge","type":"address"}],"name":"updateGaugeWeight","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"manager","type":"address"},{"internalType":"uint256","name":"newMaxDuration","type":"uint256"}],"name":"updateProxyManagerDuration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updateTotalWeight","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"usedFreePower","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"gauge","type":"address"},{"internalType":"uint256","name":"userPower","type":"uint256"}],"name":"voteForGaugeWeights","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"gauge","type":"address"},{"internalType":"uint256","name":"userPower","type":"uint256"}],"name":"voteForGaugeWeightsFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"gauge","type":"address[]"},{"internalType":"uint256[]","name":"userPower","type":"uint256[]"}],"name":"voteForManyGaugeWeights","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address[]","name":"gauge","type":"address[]"},{"internalType":"uint256[]","name":"userPower","type":"uint256[]"}],"name":"voteForManyGaugeWeightsFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"voteUserPower","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"voteUserSlopes","outputs":[{"internalType":"uint256","name":"slope","type":"uint256"},{"internalType":"uint256","name":"power","type":"uint256"},{"internalType":"uint256","name":"end","type":"uint256"},{"internalType":"address","name":"caller","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60a0346200014357601f6200432538819003918201601f19168301916001600160401b0383118484101762000148578084926020946040528339810103126200014357516001600160a01b038082169190828203620001435733156200012a5760008054336001600160a01b0319821681178355604051929592939091167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08680a367016345785d8a0000600755156200011b5750608052600160025562093a80908142048281029281840414901517156200010757506012556040516141c690816200015f823960805181818161186401528181612606015281816131ec01526132890152f35b634e487b7160e01b81526011600452602490fd5b639fabe1c160e01b8152600490fd5b604051631e4fbdf760e01b815260006004820152602490fd5b600080fd5b634e487b7160e01b600052604160045260246000fdfe6080604081815260048036101561001557600080fd5b600092833560e01c90816302346a2114612b84575080630291df2c14612b2257806306aba0e114612adc5780630fd2757514612a7a57806310f28c8d14612a0957806311d96230146129a257806313ed73d8146127f85780631776d6ee146127845780631fac13791461262a57806323bf2982146125bb57806324202739146124245780632445e76d1461234f57806326f4ed51146122db578063276723f6146121a1578063289f338f1461213f5780632c2a002e146120f95780633ae75360146120415780634db28ab6146120015780635bc652a214611dd957806360fc305d14611d7f57806363a9e58e14611d1d57806367fec84d14611ca9578063688f3f1f14611c6c578063689df56e14611c2f5780636ca32ae714611be85780636fa9bbf414611769578063715018a6146116cd5780637244d9601461167b57806372be52761461160a578063730ca21e14611529578063744c8b41146114b757806374a213241461140557806379ba5097146113075780637b71a6cc146112c2578063817135e0146112855780638abf8d7c146111b25780638b7f310d1461114b5780638da5cb5b146110fa57806390bddd0914610fd8578063921e86c714610f44578063992a793314610dec5780639a548bdf14610d8a578063afef3a3614610d06578063b4fcceb014610ccf578063c3a6ca1314610c59578063c424616614610bf7578063c745210414610b88578063c82a462714610b41578063cee308bf14610ac8578063cf4729d614610a68578063d65f66a31461098d578063d93c6ede14610922578063e048f33b146108c2578063e30c39781461086f578063e3699ba314610633578063e75ec6991461059a578063e83418d41461047a578063e8c8d7501461042b578063ec73d906146103c55763f2fde38b146102b757600080fd5b346103c15760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103c1576102ee612c0f565b906102f7612cd2565b73ffffffffffffffffffffffffffffffffffffffff80921692831561039b57828554168414610375575050600154827fffffffffffffffffffffffff0000000000000000000000000000000000000000821617600155167fb3d55174552271a4f1aaf36b72f50381e892171636b3fb5447fe00e995e7a37b8380a380f35b517fd5e889bf000000000000000000000000000000000000000000000000000000008152fd5b517f9fabe1c1000000000000000000000000000000000000000000000000000000008152fd5b8280fd5b5050346104275760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610427578060209273ffffffffffffffffffffffffffffffffffffffff610417612c0f565b168152600b845220549051908152f35b5080fd5b50346103c15760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103c1579181923581526010602052206001815491015482519182526020820152f35b5090346103c157807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103c15767ffffffffffffffff918035838111610596576104ca9036908301612c5a565b9093602435908111610592576104e39036908401612c5a565b9290936104ef33612ea1565b600a831161056c57838303610546575050845b81811061050d578580f35b8061053c61052761052261054194868a612e56565b612e66565b339061053484888a612e56565b3590336130d3565b612e29565b610502565b517fcc6e40b3000000000000000000000000000000000000000000000000000000008152fd5b517f53d79f6a000000000000000000000000000000000000000000000000000000008152fd5b8580fd5b8480fd5b50503461042757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261042757608091816105d6612c0f565b916105df612c37565b73ffffffffffffffffffffffffffffffffffffffff8094168252600a602052838383209116825260205220805492600182015492600360028401549301541692815194855260208501528301526060820152f35b50346103c15760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103c15761066b612c0f565b90602435926044359161067c612cd2565b73ffffffffffffffffffffffffffffffffffffffff841693841561084757851561081f576106cd9073ffffffffffffffffffffffffffffffffffffffff166000526006602052604060002054151590565b6107f85766038d7ea4c680008310806107ef575b80156107de575b6107b757838652600660205284828720556008602052828287205562093a809081420180421161078b5782900482810292818404149015171561075f5750916020917f99bd8149a7afcb4739659acb009a1a66648727f3cd1da7500198717dfecdccb393858852600f84528188205551908152a380f35b8660116024927f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b6024886011847f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b90517f94463346000000000000000000000000000000000000000000000000000000008152fd5b50670de0b6b3a764000083116106e8565b508215156106e1565b90517fa3d582ec000000000000000000000000000000000000000000000000000000008152fd5b5090517f613970e0000000000000000000000000000000000000000000000000000000008152fd5b5090517f9fabe1c1000000000000000000000000000000000000000000000000000000008152fd5b50503461042757817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104275760209073ffffffffffffffffffffffffffffffffffffffff600154169051908152f35b50346103c15760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103c157602092829173ffffffffffffffffffffffffffffffffffffffff610914612c0f565b168252845220549051908152f35b50503461042757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610427578060209273ffffffffffffffffffffffffffffffffffffffff610973612c0f565b168152600e84528181206024358252845220549051908152f35b50346103c157817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103c15773ffffffffffffffffffffffffffffffffffffffff6109d9612c0f565b16908115610a4157338452601360205282842082855260205260ff838520541615610a1a575033835260146020528183209083526020526024359082205580f35b82517f2648c268000000000000000000000000000000000000000000000000000000008152fd5b82517f9fabe1c1000000000000000000000000000000000000000000000000000000008152fd5b5050346104275760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261042757602090610ac1610aa7612c0f565b610ab081613ed9565b50610ab961403d565b504290613de3565b9051908152f35b50503461042757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104275760ff81602093610b06612c0f565b610b0e612c37565b73ffffffffffffffffffffffffffffffffffffffff91821683526013875283832091168252855220549151911615158152f35b8334610b855760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610b8557610b81610b7c612c0f565b613ed9565b5080f35b80fd5b5050346104275760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610427576020918173ffffffffffffffffffffffffffffffffffffffff9182610bdc612c0f565b16815260068552818120548152600385522054169051908152f35b5050346104275760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610427578060209273ffffffffffffffffffffffffffffffffffffffff610c49612c0f565b1681526008845220549051908152f35b50503461042757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261042757809173ffffffffffffffffffffffffffffffffffffffff610ca8612c0f565b168152600d6020528181206024358252602052206001815491015482519182526020820152f35b8334610b8557807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610b8557610b8161403d565b50503461042757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261042757610d3e612c0f565b6024359273ffffffffffffffffffffffffffffffffffffffff80921681526016602052828120908154851015610b855750602093610d7b91612c8b565b92905490519260031b1c168152f35b5050346104275760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610427578060209273ffffffffffffffffffffffffffffffffffffffff610ddc612c0f565b1681526005845220549051908152f35b5090346103c15760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103c157610e25612c0f565b91610e2e612cd2565b73ffffffffffffffffffffffffffffffffffffffff831692831561084757610e799073ffffffffffffffffffffffffffffffffffffffff166000526006602052604060002054151590565b15610f1d57828452600960205260ff8285205416610ef65750818352600960205280832060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008254161790556006602052822054907f37045eded4ae85a16f55cfa4394328cc3531cd6ab3aa97c0a5d1ced6a2b9aae58380a380f35b90517f6cd7ad06000000000000000000000000000000000000000000000000000000008152fd5b90517f665c1c57000000000000000000000000000000000000000000000000000000008152fd5b5090346103c15760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103c157813591610f80612cd2565b66038d7ea4c6800083108015610fc7575b6107b75750816020917f9b8d46d5ada9050fa0320d285f24811d709bba8d11887134fda797788740d0dc9360075551908152a180f35b50670de0b6b3a76400008311610f91565b5090346103c15760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103c15773ffffffffffffffffffffffffffffffffffffffff611026612c0f565b61102e612cd2565b169182156110d357828452600960205260ff8285205416156110ac575081835260096020528083207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0081541690556006602052822054907f3a59461de410bac93671a77196d74419de5bd66391c8c13015cb6c75188a285a8380a380f35b90517f5f128a7a000000000000000000000000000000000000000000000000000000008152fd5b90517f9fabe1c1000000000000000000000000000000000000000000000000000000008152fd5b50503461042757817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104275773ffffffffffffffffffffffffffffffffffffffff60209254169051908152f35b5050346104275760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104275760ff8160209373ffffffffffffffffffffffffffffffffffffffff61119f612c0f565b1681526009855220541690519015158152f35b5090346103c157807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103c15773ffffffffffffffffffffffffffffffffffffffff6111ff612c0f565b169182156110d35750338352601360205280832082845260205280832060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055338352601460205280832082845260205260243590832055337f5f2994004a6cb848619098988e3fd740b8121835cc529569a87fcbb6d301f50d8380a380f35b50503461042757817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610427576020906002549051908152f35b50346103c15760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103c15760209282913581526011845220549051908152f35b5091903461042757817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104275760015473ffffffffffffffffffffffffffffffffffffffff90818116928333036113dd5750839450828454927fffffffffffffffffffffffff00000000000000000000000000000000000000009382858216178755167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08680a3166001557fb3d55174552271a4f1aaf36b72f50381e892171636b3fb5447fe00e995e7a37b8280a380f35b8590517f2f02da58000000000000000000000000000000000000000000000000000000008152fd5b509134610b8557817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610b855761143d612c0f565b62093a8090816024350482810292818404149015171561148b57602092849273ffffffffffffffffffffffffffffffffffffffff8493168252600d8552828220908252845220549051908152f35b6024836011877f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b5050346104275760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104275760209160018273ffffffffffffffffffffffffffffffffffffffff928361150d612c0f565b1681526006865281812054815260038652200154169051908152f35b50346103c157817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103c157611560612c0f565b9173ffffffffffffffffffffffffffffffffffffffff60243593611582612cd2565b169182156110d357828552600660205281852054156115e357828552600960205260ff8286205416610ef65750829082855260066020528420557fa286662a57d383b7aa8efe5ed8dceea19a94848a8189fe24f860b9423aaa779b8380a380f35b90517f613970e0000000000000000000000000000000000000000000000000000000008152fd5b5050346104275760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610427578060209273ffffffffffffffffffffffffffffffffffffffff61165c612c0f565b168152600d8452818120600f8552828220548252845220549051908152f35b505034610427577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610b85576116ca6116b5612c0f565b6116be33612ea1565b339060243590336130d3565b80f35b8334610b8557807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610b8557611704612cd2565b8073ffffffffffffffffffffffffffffffffffffffff81547fffffffffffffffffffffffff000000000000000000000000000000000000000081168355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b509190346104275760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610427576117a3612c0f565b906117ac612c37565b9060443573ffffffffffffffffffffffffffffffffffffffff938481169384875260209060138252848820338952825260ff85892054161580611bde575b611bb65783158015611bab575b611b8357858852601682528488205460018101809111611b2f57603210611b5b5762093a80928360643504848102948186041490151715611b2f5785517fadc63589000000000000000000000000000000000000000000000000000000008152878b82015283816024818c7f0000000000000000000000000000000000000000000000000000000000000000165afa908115611b25578a91611af4575b50428510908115611aea575b50611ac25786895260148352858920338a528352858920548015159081611aaf575b50611a87576118d090612ea1565b8588526015825284882096811696878952825284882085516118f181612db0565b8660028354938484526001810154878501520154910152611a5f5785885260178252848820546127106119248683612e87565b11611a37578461193391612e87565b8689526017835285892055845161194981612db0565b84815260028382018a815287830190868252898c5260158652888c208b8d528652888c2093518455516001840155519101558588526016825284882080549068010000000000000000821015611a0b57916119d2827fba0729e0f4fe0826a8bfe066da36c2b21bc12084a29dd3a41b796b673c4ad6be989796959460016119ff95018155612c8b565b90919082549060031b9173ffffffffffffffffffffffffffffffffffffffff809116831b921b1916179055565b8351928352820152a380f35b60248a60418d7f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b8986517f38bcb619000000000000000000000000000000000000000000000000000000008152fd5b8885517fe3cbac45000000000000000000000000000000000000000000000000000000008152fd5b8986517f75720d70000000000000000000000000000000000000000000000000000000008152fd5b611aba915042612e87565b8411386118c2565b8986517fb7d09497000000000000000000000000000000000000000000000000000000008152fd5b90508411386118a0565b90508381813d8311611b1e575b611b0b8183612de8565b81010312611b1a575138611894565b8980fd5b503d611b01565b87513d8c823e3d90fd5b60248960118c7f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b8885517f79b9b3a3000000000000000000000000000000000000000000000000000000008152fd5b8885517f2fe2ca10000000000000000000000000000000000000000000000000000000008152fd5b5061271084116117f7565b8885517f2648c268000000000000000000000000000000000000000000000000000000008152fd5b50853314156117ea565b50503461042757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261042757602090610ac1611c26612c0f565b60243590613de3565b50503461042757817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610427576020906007549051908152f35b50503461042757817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610427576020906012549051908152f35b5050346104275760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104275760209173ffffffffffffffffffffffffffffffffffffffff611cfa612c0f565b16815260088352819020548015611d1357905b51908152f35b5060075490611d0d565b5050346104275760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610427578060209273ffffffffffffffffffffffffffffffffffffffff611d6f612c0f565b1681526017845220549051908152f35b50503461042757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261042757602090610ac1611dbd612c0f565b611dc681613ed9565b50611dcf61403d565b5060243590613de3565b5090346103c15760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103c157611e12612c0f565b67ffffffffffffffff60243581811161059257611e329036908601612c5a565b929091604435908111611ffd57611e4c9036908701612c5a565b9290611e5783612ea1565b73ffffffffffffffffffffffffffffffffffffffff83168852601560205285882033895260205285882092865194611e8e86612db0565b845480875260026001968781015460208a015201549089880191825215611fd557514211611fad578996600a8111611f8557818103611f5d5794939291908a955b808710611f0d57505050505050505110611ee7578280f35b517f1dc41441000000000000000000000000000000000000000000000000000000008152fd5b9091929394611f2a8799611f2383998689612e56565b3590612e87565b98611f51611f3c61052283868b612e56565b3390611f4984888b612e56565b3590886130d3565b01959493929190611ecf565b8989517fcc6e40b3000000000000000000000000000000000000000000000000000000008152fd5b8989517f53d79f6a000000000000000000000000000000000000000000000000000000008152fd5b8888517fddb7f867000000000000000000000000000000000000000000000000000000008152fd5b8989517f8ec70231000000000000000000000000000000000000000000000000000000008152fd5b8680fd5b8334610b855760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610b85576116ca61203c612c0f565b612ea1565b5090346103c15760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103c15773ffffffffffffffffffffffffffffffffffffffff61208f612c0f565b169182156110d35750338352601360205280832082845260205282207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008154169055337f50d314463c3d92f422a6a898054175d82c3482b9594ef1431ed666f9da59e1a98380a380f35b5050346104275760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261042757602090610ac1612138612c0f565b4290613de3565b5050346104275760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610427578060209273ffffffffffffffffffffffffffffffffffffffff612191612c0f565b168152600f845220549051908152f35b509190346104275760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610427576121db612c0f565b906121e4612c37565b604435916121f184612ea1565b73ffffffffffffffffffffffffffffffffffffffff84168552601560205280852033865260205280852081519061222782612db0565b600281549182845260018101546020850152015490838301918252156122b35751421161228b5751831161226357506116ca93945033926130d3565b8590517f1dc41441000000000000000000000000000000000000000000000000000000008152fd5b8682517fddb7f867000000000000000000000000000000000000000000000000000000008152fd5b8783517f8ec70231000000000000000000000000000000000000000000000000000000008152fd5b50503461042757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104275780602092612317612c0f565b61231f612c37565b73ffffffffffffffffffffffffffffffffffffffff9182168352600c865283832091168252845220549051908152f35b505034610427576020807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103c15773ffffffffffffffffffffffffffffffffffffffff92836123a0612c0f565b1681526016825282812091835190818185549182815201908195855282852090855b81811061240e57505050826123d8910383612de8565b8451948186019282875251809352850193925b8281106123f85785850386f35b83518716855293810193928101926001016123eb565b82548a16845292840192600192830192016123c2565b50346103c157817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103c15761245b612c0f565b73ffffffffffffffffffffffffffffffffffffffff6024359161247c612cd2565b16918215612594578285526006602052838520541561256d57828552600960205260ff84862054166125465766038d7ea4c6800082108061253d575b801561252c575b612505575060207f849877e3a920a233bd1dadf1bfcdd066f09c852b05378ad093af9c745b327bb39183865260088252808587205560068252848620549451908152a380f35b83517f94463346000000000000000000000000000000000000000000000000000000008152fd5b50670de0b6b3a764000082116124bf565b508115156124b8565b83517f6cd7ad06000000000000000000000000000000000000000000000000000000008152fd5b83517f613970e0000000000000000000000000000000000000000000000000000000008152fd5b83517f9fabe1c1000000000000000000000000000000000000000000000000000000008152fd5b50503461042757817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610427576020905173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346103c157817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103c157612661612c0f565b9161266a612c37565b92612673612cd2565b73ffffffffffffffffffffffffffffffffffffffff809116938415801561277a575b61275257169283855260056020528185205461272b57845281602052808420549182156115e35750816020917f6f1094cad3fd96620239637ccce6fa95cc123710b81f399069bb5b047ec232ea93865260038352600181872001857fffffffffffffffffffffffff000000000000000000000000000000000000000082541617905584865260058352818187205551908152a280f35b50517fa3d582ec000000000000000000000000000000000000000000000000000000008152fd5b5050517f9fabe1c1000000000000000000000000000000000000000000000000000000008152fd5b5081811615612695565b50503461042757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261042757806020926127c0612c0f565b6127c8612c37565b73ffffffffffffffffffffffffffffffffffffffff91821683526014865283832091168252845220549051908152f35b5091903461042757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261042757612831612c0f565b9061283a612c37565b90612843612cd2565b73ffffffffffffffffffffffffffffffffffffffff8093169182158015612998575b61297057828552602091868352808620541580159061295b575b612933577f1005b8f1174594df83bf60033ed95f2a1503df5a39a7315b66d662617144719f93949596600254926128b584612e29565b60025582516128c381612d65565b87815288868201921698898352858b5260038752600181868d20935116927fffffffffffffffffffffffff0000000000000000000000000000000000000000938482541617815501925116908254161790558588528352818188205585875260058352818188205551908152a380f35b8690517fa3d582ec000000000000000000000000000000000000000000000000000000008152fd5b5084821686526005835280862054151561287f565b8582517f9fabe1c1000000000000000000000000000000000000000000000000000000008152fd5b5083811615612865565b50346103c15760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103c15791819235815260036020522073ffffffffffffffffffffffffffffffffffffffff6001818354169201541682519182526020820152f35b5050346104275760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261042757602090612a71612a48612c0f565b73ffffffffffffffffffffffffffffffffffffffff166000526006602052604060002054151590565b90519015158152f35b5050346104275760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610427578060209273ffffffffffffffffffffffffffffffffffffffff612acc612c0f565b1681526006845220549051908152f35b50503461042757817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610427578060209260125481526010845220549051908152f35b5050346104275760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610427578060209273ffffffffffffffffffffffffffffffffffffffff612b74612c0f565b1681526018845220549051908152f35b849084346103c157807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103c15780606093612bc1612c0f565b612bc9612c37565b9073ffffffffffffffffffffffffffffffffffffffff80911683526015602052838320911682526020522090815491600260018201549101549284526020840152820152f35b6004359073ffffffffffffffffffffffffffffffffffffffff82168203612c3257565b600080fd5b6024359073ffffffffffffffffffffffffffffffffffffffff82168203612c3257565b9181601f84011215612c325782359167ffffffffffffffff8311612c32576020808501948460051b010111612c3257565b8054821015612ca35760005260206000200190600090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b73ffffffffffffffffffffffffffffffffffffffff600054163303612cf357565b60246040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152fd5b81810292918115918404141715612d3657565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6040810190811067ffffffffffffffff821117612d8157604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6060810190811067ffffffffffffffff821117612d8157604052565b6080810190811067ffffffffffffffff821117612d8157604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117612d8157604052565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114612d365760010190565b9190811015612ca35760051b0190565b3573ffffffffffffffffffffffffffffffffffffffff81168103612c325790565b91908201809211612d3657565b91908203918211612d3657565b73ffffffffffffffffffffffffffffffffffffffff809116906000908282526016906020938285526040808520549384156130bc578596945b808810612eeb575050505050505050565b8490848852828752612eff89858a20612c8b565b929054600393841b1c16858952601590818952858a20818b5289526002914283888d200154106000146130ac57908a9291888452808b528784208285528b528784205489855260178c52612f57898620918254612e94565b90558884528a52868320908352895285822082815582600182015501557fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff918282019282841161307f578887898d898e8a8a8403613048575b5093945050505052848952858a20908154801561301b5701918890612fd58484612c8b565b81939154921b1b191690555515612fee57945b94612eda565b6024877f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b60248c7f4e487b710000000000000000000000000000000000000000000000000000000081526031600452fd5b613073966119d2958784528282526130628d868620612c8b565b9054908c1b1c169683525220612c8b565b8887898d898e8a612fb0565b60248a7f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b5050509597600191500196612fe8565b50505050505050565b519081600f0b8203612c3257565b9091604051610180810181811067ffffffffffffffff821117612d81576040526000815260006020820152600060408201526000606082015260006080820152600060a0820152600060c0820152600060e0820152600061010082015260006101208201526000610140820152600061016082015262093a80420462093a80804204020462093a801462093a804204151715612d365762093a8042819004810280835290810110612d365762093a8080804204020160208201526040517f71628bfd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416600482015260808160248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa8015613d6b57600090613d77575b602091500151600f0b60408201526040517fadc6358900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416600482015260208160248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa908115613d6b57600091613d39575b5060608201526132ed8473ffffffffffffffffffffffffffffffffffffffff166000526006602052604060002054151590565b15613d0f57606081015160208201511015613ce5576127108211613cbb5773ffffffffffffffffffffffffffffffffffffffff8316600052600c602052604060002073ffffffffffffffffffffffffffffffffffffffff8516600052602052604060002054620d2f008101809111612d36574210613c915773ffffffffffffffffffffffffffffffffffffffff8316600052600a602052604060002073ffffffffffffffffffffffffffffffffffffffff8516600052602052604060002093604051946133b986612dcc565b80548087526001820154602088015273ffffffffffffffffffffffffffffffffffffffff60036002840154938460408b01520154166060880152602084015191828111613c77575b505050821580613c6b575b613c63576040820151600081600f0b12613c395761343f846fffffffffffffffffffffffffffffffff6127109316612d23565b049561349a606084015197604051986134578a612dcc565b818a528660208b015260408a015273ffffffffffffffffffffffffffffffffffffffff831660608a01526134946060860151602087015190612e94565b90612d23565b60a084015273ffffffffffffffffffffffffffffffffffffffff811673ffffffffffffffffffffffffffffffffffffffff606088015116141580613be3575b613bb95773ffffffffffffffffffffffffffffffffffffffff8516600052600b6020526135246135196040600020548060c087015260208a015190612e87565b602088015190612e94565b60c084015273ffffffffffffffffffffffffffffffffffffffff811673ffffffffffffffffffffffffffffffffffffffff8616146000146139cd575073ffffffffffffffffffffffffffffffffffffffff84811660008181526018602052604090205460608801516135b9936135ae939116146139c35760005b60e0860152602089015190612e87565b60e084015190612e94565b73ffffffffffffffffffffffffffffffffffffffff85166000526017602052604060002054612710036127108111612d365781116139995773ffffffffffffffffffffffffffffffffffffffff851660005260186020526040600020555b61271060c083015111613999577f45ca9a4c8d0119eb329e580d28fe689e484e1be230da8037ade9547d2d25cc91956080958360c073ffffffffffffffffffffffffffffffffffffffff950151858816600052600b60205260406000205561367e84613ed9565b610100820152848416600052600d602052604060002060208201516000526020526001604060002001546101208201526136b661403d565b610140820152602081015160005260106020526001604060002001546101608201526137016136ef61010083015160a084015190612e87565b828a0151908181111561393757612e94565b858516600052600d602052604060002060208301516000526020526040600020556137396136ef61014083015160a084015190612e87565b60208201516000526010602052604060002055604082015160208201511060001461393e57613782613772610120830151855190612e87565b8351908181111561393757612e94565b858516600052600d6020526040600020602083015160005260205260016040600020015560206137cc6137bc610160840151865190612e87565b8451908181111561393757612e94565b91015160005260106020526001604060002001555b426040820151116138e1575b508051838316600052600e6020526040600020604083015160005260205261381b6040600020918254612e87565b905580516040820151600052601160205261383c6040600020918254612e87565b9055828516600052600a60205260406000208383166000526020528260606003604060002084518155602085015160018201556040850151600282015501920151167fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055818416600052600c60205260406000208282166000526020524260406000205581604051944286521660208501521660408301526060820152a1565b8051848416600052600e6020526040600020604083015160005260205261390e6040600020918254612e94565b905560408151910151600052601160205261392f6040600020918254612e94565b9055386137ed565b5080612e94565b8251858516600052600d6020526040600020602083015160005260205261396e6001604060002001918254612e87565b90556020835191015160005260106020526139926001604060002001918254612e87565b90556137e1565b60046040517f36fd87a2000000000000000000000000000000000000000000000000000000008152fd5b602088015161359e565b73ffffffffffffffffffffffffffffffffffffffff85166000526015602052604060002073ffffffffffffffffffffffffffffffffffffffff8216600052602052613a78613a6d60016040600020015473ffffffffffffffffffffffffffffffffffffffff841673ffffffffffffffffffffffffffffffffffffffff60608b01511614600014613bb25760208901515b60e087015260208a015190612e87565b60e085015190612e94565b9073ffffffffffffffffffffffffffffffffffffffff861673ffffffffffffffffffffffffffffffffffffffff60608901511614613b77575b73ffffffffffffffffffffffffffffffffffffffff86166000526015602052604060002073ffffffffffffffffffffffffffffffffffffffff82166000526020526040600020548211613b4d5773ffffffffffffffffffffffffffffffffffffffff8616600052601560205273ffffffffffffffffffffffffffffffffffffffff60406000209116600052602052600160406000200155613617565b60046040517f1dc41441000000000000000000000000000000000000000000000000000000008152fd5b602087015173ffffffffffffffffffffffffffffffffffffffff87166000526018602052613bab6040600020918254612e94565b9055613ab1565b6000613a5d565b60046040517fdc7905d4000000000000000000000000000000000000000000000000000000008152fd5b5073ffffffffffffffffffffffffffffffffffffffff85166000526015602052604060002073ffffffffffffffffffffffffffffffffffffffff60608801511660005260205242600260406000200154116134d9565b60046040517fc71d1071000000000000000000000000000000000000000000000000000000008152fd5b505050505050565b5060208501511561340c565b613c849261349491612e94565b6080830152388080613401565b60046040517f2aa44a5a000000000000000000000000000000000000000000000000000000008152fd5b60046040517f2fe2ca10000000000000000000000000000000000000000000000000000000008152fd5b60046040517ff6fafba0000000000000000000000000000000000000000000000000000000008152fd5b60046040517f665c1c57000000000000000000000000000000000000000000000000000000008152fd5b90506020813d602011613d63575b81613d5460209383612de8565b81010312612c325751386132ba565b3d9150613d47565b6040513d6000823e3d90fd5b506080813d608011613ddb575b81613d9160809383612de8565b81010312612c3257602090606060405191613dab83612dcc565b613db4816130c5565b8352613dc18482016130c5565b84840152604081015160408401520151606082015261321c565b3d9150613d84565b73ffffffffffffffffffffffffffffffffffffffff1690600090828252600960205260ff604083205416613ed35762093a80809104818102918183041490151715613ea65780825260106020526040822054928315613e9f578252600d60205260408220908252602052604081205490670de0b6b3a764000091828102928184041490151715613e7257500490565b807f4e487b7100000000000000000000000000000000000000000000000000000000602492526011600452fd5b5050905090565b6024827f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b50905090565b73ffffffffffffffffffffffffffffffffffffffff166000818152600f9060209082825260408082205491821561403457600d94858552828220848352855282822094835197613f2889612d65565b8654895260018097015496828a01978852845b6101f48110613f53575b505050505050505050505190565b42881161402f5762093a8097888101809111612fee5780988a51818102918183041490151715614002578c51613fbe939291818110613fd3575050878d52878b525b8488528b865288882081895286528888208d518155848c51910155428111613fc3575b50612e29565b613f3b565b8488528686528888205538613fb8565b613fdc91612e94565b8d52848852600e86528888208189528652613ffb898920548c51612e94565b8b52613f95565b6024887f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b613f45565b94505050505090565b60128054908115614189576000918083526010906020928284526040948581209086519661406a88612d65565b8254885260018093015491878901928352805b6101f48110614094575b5050505050505050505190565b4287116141845762093a8096878101809111614157578097855181810291818304149015171561412a578b516140f6939291818110614103575050838c528386525b808452898b528484208c5181558787519101554281116140fb5750612e29565b61407d565b875538613fb8565b61410c91612e94565b8c5280845260118b52614123858520548751612e94565b86526140d6565b6024847f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b614087565b505060009056fea26469706673582212205e0e176cacd2e89318f182f92400490cfd3d429f5777c47e5ce2bead00ab7eb964736f6c63430008140033000000000000000000000000a241a6670231ea66ac3bfe95f29c67f2bb28113b
Deployed Bytecode
0x6080604081815260048036101561001557600080fd5b600092833560e01c90816302346a2114612b84575080630291df2c14612b2257806306aba0e114612adc5780630fd2757514612a7a57806310f28c8d14612a0957806311d96230146129a257806313ed73d8146127f85780631776d6ee146127845780631fac13791461262a57806323bf2982146125bb57806324202739146124245780632445e76d1461234f57806326f4ed51146122db578063276723f6146121a1578063289f338f1461213f5780632c2a002e146120f95780633ae75360146120415780634db28ab6146120015780635bc652a214611dd957806360fc305d14611d7f57806363a9e58e14611d1d57806367fec84d14611ca9578063688f3f1f14611c6c578063689df56e14611c2f5780636ca32ae714611be85780636fa9bbf414611769578063715018a6146116cd5780637244d9601461167b57806372be52761461160a578063730ca21e14611529578063744c8b41146114b757806374a213241461140557806379ba5097146113075780637b71a6cc146112c2578063817135e0146112855780638abf8d7c146111b25780638b7f310d1461114b5780638da5cb5b146110fa57806390bddd0914610fd8578063921e86c714610f44578063992a793314610dec5780639a548bdf14610d8a578063afef3a3614610d06578063b4fcceb014610ccf578063c3a6ca1314610c59578063c424616614610bf7578063c745210414610b88578063c82a462714610b41578063cee308bf14610ac8578063cf4729d614610a68578063d65f66a31461098d578063d93c6ede14610922578063e048f33b146108c2578063e30c39781461086f578063e3699ba314610633578063e75ec6991461059a578063e83418d41461047a578063e8c8d7501461042b578063ec73d906146103c55763f2fde38b146102b757600080fd5b346103c15760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103c1576102ee612c0f565b906102f7612cd2565b73ffffffffffffffffffffffffffffffffffffffff80921692831561039b57828554168414610375575050600154827fffffffffffffffffffffffff0000000000000000000000000000000000000000821617600155167fb3d55174552271a4f1aaf36b72f50381e892171636b3fb5447fe00e995e7a37b8380a380f35b517fd5e889bf000000000000000000000000000000000000000000000000000000008152fd5b517f9fabe1c1000000000000000000000000000000000000000000000000000000008152fd5b8280fd5b5050346104275760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610427578060209273ffffffffffffffffffffffffffffffffffffffff610417612c0f565b168152600b845220549051908152f35b5080fd5b50346103c15760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103c1579181923581526010602052206001815491015482519182526020820152f35b5090346103c157807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103c15767ffffffffffffffff918035838111610596576104ca9036908301612c5a565b9093602435908111610592576104e39036908401612c5a565b9290936104ef33612ea1565b600a831161056c57838303610546575050845b81811061050d578580f35b8061053c61052761052261054194868a612e56565b612e66565b339061053484888a612e56565b3590336130d3565b612e29565b610502565b517fcc6e40b3000000000000000000000000000000000000000000000000000000008152fd5b517f53d79f6a000000000000000000000000000000000000000000000000000000008152fd5b8580fd5b8480fd5b50503461042757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261042757608091816105d6612c0f565b916105df612c37565b73ffffffffffffffffffffffffffffffffffffffff8094168252600a602052838383209116825260205220805492600182015492600360028401549301541692815194855260208501528301526060820152f35b50346103c15760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103c15761066b612c0f565b90602435926044359161067c612cd2565b73ffffffffffffffffffffffffffffffffffffffff841693841561084757851561081f576106cd9073ffffffffffffffffffffffffffffffffffffffff166000526006602052604060002054151590565b6107f85766038d7ea4c680008310806107ef575b80156107de575b6107b757838652600660205284828720556008602052828287205562093a809081420180421161078b5782900482810292818404149015171561075f5750916020917f99bd8149a7afcb4739659acb009a1a66648727f3cd1da7500198717dfecdccb393858852600f84528188205551908152a380f35b8660116024927f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b6024886011847f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b90517f94463346000000000000000000000000000000000000000000000000000000008152fd5b50670de0b6b3a764000083116106e8565b508215156106e1565b90517fa3d582ec000000000000000000000000000000000000000000000000000000008152fd5b5090517f613970e0000000000000000000000000000000000000000000000000000000008152fd5b5090517f9fabe1c1000000000000000000000000000000000000000000000000000000008152fd5b50503461042757817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104275760209073ffffffffffffffffffffffffffffffffffffffff600154169051908152f35b50346103c15760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103c157602092829173ffffffffffffffffffffffffffffffffffffffff610914612c0f565b168252845220549051908152f35b50503461042757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610427578060209273ffffffffffffffffffffffffffffffffffffffff610973612c0f565b168152600e84528181206024358252845220549051908152f35b50346103c157817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103c15773ffffffffffffffffffffffffffffffffffffffff6109d9612c0f565b16908115610a4157338452601360205282842082855260205260ff838520541615610a1a575033835260146020528183209083526020526024359082205580f35b82517f2648c268000000000000000000000000000000000000000000000000000000008152fd5b82517f9fabe1c1000000000000000000000000000000000000000000000000000000008152fd5b5050346104275760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261042757602090610ac1610aa7612c0f565b610ab081613ed9565b50610ab961403d565b504290613de3565b9051908152f35b50503461042757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104275760ff81602093610b06612c0f565b610b0e612c37565b73ffffffffffffffffffffffffffffffffffffffff91821683526013875283832091168252855220549151911615158152f35b8334610b855760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610b8557610b81610b7c612c0f565b613ed9565b5080f35b80fd5b5050346104275760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610427576020918173ffffffffffffffffffffffffffffffffffffffff9182610bdc612c0f565b16815260068552818120548152600385522054169051908152f35b5050346104275760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610427578060209273ffffffffffffffffffffffffffffffffffffffff610c49612c0f565b1681526008845220549051908152f35b50503461042757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261042757809173ffffffffffffffffffffffffffffffffffffffff610ca8612c0f565b168152600d6020528181206024358252602052206001815491015482519182526020820152f35b8334610b8557807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610b8557610b8161403d565b50503461042757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261042757610d3e612c0f565b6024359273ffffffffffffffffffffffffffffffffffffffff80921681526016602052828120908154851015610b855750602093610d7b91612c8b565b92905490519260031b1c168152f35b5050346104275760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610427578060209273ffffffffffffffffffffffffffffffffffffffff610ddc612c0f565b1681526005845220549051908152f35b5090346103c15760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103c157610e25612c0f565b91610e2e612cd2565b73ffffffffffffffffffffffffffffffffffffffff831692831561084757610e799073ffffffffffffffffffffffffffffffffffffffff166000526006602052604060002054151590565b15610f1d57828452600960205260ff8285205416610ef65750818352600960205280832060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008254161790556006602052822054907f37045eded4ae85a16f55cfa4394328cc3531cd6ab3aa97c0a5d1ced6a2b9aae58380a380f35b90517f6cd7ad06000000000000000000000000000000000000000000000000000000008152fd5b90517f665c1c57000000000000000000000000000000000000000000000000000000008152fd5b5090346103c15760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103c157813591610f80612cd2565b66038d7ea4c6800083108015610fc7575b6107b75750816020917f9b8d46d5ada9050fa0320d285f24811d709bba8d11887134fda797788740d0dc9360075551908152a180f35b50670de0b6b3a76400008311610f91565b5090346103c15760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103c15773ffffffffffffffffffffffffffffffffffffffff611026612c0f565b61102e612cd2565b169182156110d357828452600960205260ff8285205416156110ac575081835260096020528083207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0081541690556006602052822054907f3a59461de410bac93671a77196d74419de5bd66391c8c13015cb6c75188a285a8380a380f35b90517f5f128a7a000000000000000000000000000000000000000000000000000000008152fd5b90517f9fabe1c1000000000000000000000000000000000000000000000000000000008152fd5b50503461042757817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104275773ffffffffffffffffffffffffffffffffffffffff60209254169051908152f35b5050346104275760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104275760ff8160209373ffffffffffffffffffffffffffffffffffffffff61119f612c0f565b1681526009855220541690519015158152f35b5090346103c157807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103c15773ffffffffffffffffffffffffffffffffffffffff6111ff612c0f565b169182156110d35750338352601360205280832082845260205280832060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055338352601460205280832082845260205260243590832055337f5f2994004a6cb848619098988e3fd740b8121835cc529569a87fcbb6d301f50d8380a380f35b50503461042757817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610427576020906002549051908152f35b50346103c15760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103c15760209282913581526011845220549051908152f35b5091903461042757817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104275760015473ffffffffffffffffffffffffffffffffffffffff90818116928333036113dd5750839450828454927fffffffffffffffffffffffff00000000000000000000000000000000000000009382858216178755167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08680a3166001557fb3d55174552271a4f1aaf36b72f50381e892171636b3fb5447fe00e995e7a37b8280a380f35b8590517f2f02da58000000000000000000000000000000000000000000000000000000008152fd5b509134610b8557817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610b855761143d612c0f565b62093a8090816024350482810292818404149015171561148b57602092849273ffffffffffffffffffffffffffffffffffffffff8493168252600d8552828220908252845220549051908152f35b6024836011877f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b5050346104275760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104275760209160018273ffffffffffffffffffffffffffffffffffffffff928361150d612c0f565b1681526006865281812054815260038652200154169051908152f35b50346103c157817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103c157611560612c0f565b9173ffffffffffffffffffffffffffffffffffffffff60243593611582612cd2565b169182156110d357828552600660205281852054156115e357828552600960205260ff8286205416610ef65750829082855260066020528420557fa286662a57d383b7aa8efe5ed8dceea19a94848a8189fe24f860b9423aaa779b8380a380f35b90517f613970e0000000000000000000000000000000000000000000000000000000008152fd5b5050346104275760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610427578060209273ffffffffffffffffffffffffffffffffffffffff61165c612c0f565b168152600d8452818120600f8552828220548252845220549051908152f35b505034610427577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610b85576116ca6116b5612c0f565b6116be33612ea1565b339060243590336130d3565b80f35b8334610b8557807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610b8557611704612cd2565b8073ffffffffffffffffffffffffffffffffffffffff81547fffffffffffffffffffffffff000000000000000000000000000000000000000081168355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b509190346104275760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610427576117a3612c0f565b906117ac612c37565b9060443573ffffffffffffffffffffffffffffffffffffffff938481169384875260209060138252848820338952825260ff85892054161580611bde575b611bb65783158015611bab575b611b8357858852601682528488205460018101809111611b2f57603210611b5b5762093a80928360643504848102948186041490151715611b2f5785517fadc63589000000000000000000000000000000000000000000000000000000008152878b82015283816024818c7f000000000000000000000000a241a6670231ea66ac3bfe95f29c67f2bb28113b165afa908115611b25578a91611af4575b50428510908115611aea575b50611ac25786895260148352858920338a528352858920548015159081611aaf575b50611a87576118d090612ea1565b8588526015825284882096811696878952825284882085516118f181612db0565b8660028354938484526001810154878501520154910152611a5f5785885260178252848820546127106119248683612e87565b11611a37578461193391612e87565b8689526017835285892055845161194981612db0565b84815260028382018a815287830190868252898c5260158652888c208b8d528652888c2093518455516001840155519101558588526016825284882080549068010000000000000000821015611a0b57916119d2827fba0729e0f4fe0826a8bfe066da36c2b21bc12084a29dd3a41b796b673c4ad6be989796959460016119ff95018155612c8b565b90919082549060031b9173ffffffffffffffffffffffffffffffffffffffff809116831b921b1916179055565b8351928352820152a380f35b60248a60418d7f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b8986517f38bcb619000000000000000000000000000000000000000000000000000000008152fd5b8885517fe3cbac45000000000000000000000000000000000000000000000000000000008152fd5b8986517f75720d70000000000000000000000000000000000000000000000000000000008152fd5b611aba915042612e87565b8411386118c2565b8986517fb7d09497000000000000000000000000000000000000000000000000000000008152fd5b90508411386118a0565b90508381813d8311611b1e575b611b0b8183612de8565b81010312611b1a575138611894565b8980fd5b503d611b01565b87513d8c823e3d90fd5b60248960118c7f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b8885517f79b9b3a3000000000000000000000000000000000000000000000000000000008152fd5b8885517f2fe2ca10000000000000000000000000000000000000000000000000000000008152fd5b5061271084116117f7565b8885517f2648c268000000000000000000000000000000000000000000000000000000008152fd5b50853314156117ea565b50503461042757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261042757602090610ac1611c26612c0f565b60243590613de3565b50503461042757817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610427576020906007549051908152f35b50503461042757817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610427576020906012549051908152f35b5050346104275760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104275760209173ffffffffffffffffffffffffffffffffffffffff611cfa612c0f565b16815260088352819020548015611d1357905b51908152f35b5060075490611d0d565b5050346104275760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610427578060209273ffffffffffffffffffffffffffffffffffffffff611d6f612c0f565b1681526017845220549051908152f35b50503461042757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261042757602090610ac1611dbd612c0f565b611dc681613ed9565b50611dcf61403d565b5060243590613de3565b5090346103c15760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103c157611e12612c0f565b67ffffffffffffffff60243581811161059257611e329036908601612c5a565b929091604435908111611ffd57611e4c9036908701612c5a565b9290611e5783612ea1565b73ffffffffffffffffffffffffffffffffffffffff83168852601560205285882033895260205285882092865194611e8e86612db0565b845480875260026001968781015460208a015201549089880191825215611fd557514211611fad578996600a8111611f8557818103611f5d5794939291908a955b808710611f0d57505050505050505110611ee7578280f35b517f1dc41441000000000000000000000000000000000000000000000000000000008152fd5b9091929394611f2a8799611f2383998689612e56565b3590612e87565b98611f51611f3c61052283868b612e56565b3390611f4984888b612e56565b3590886130d3565b01959493929190611ecf565b8989517fcc6e40b3000000000000000000000000000000000000000000000000000000008152fd5b8989517f53d79f6a000000000000000000000000000000000000000000000000000000008152fd5b8888517fddb7f867000000000000000000000000000000000000000000000000000000008152fd5b8989517f8ec70231000000000000000000000000000000000000000000000000000000008152fd5b8680fd5b8334610b855760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610b85576116ca61203c612c0f565b612ea1565b5090346103c15760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103c15773ffffffffffffffffffffffffffffffffffffffff61208f612c0f565b169182156110d35750338352601360205280832082845260205282207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008154169055337f50d314463c3d92f422a6a898054175d82c3482b9594ef1431ed666f9da59e1a98380a380f35b5050346104275760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261042757602090610ac1612138612c0f565b4290613de3565b5050346104275760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610427578060209273ffffffffffffffffffffffffffffffffffffffff612191612c0f565b168152600f845220549051908152f35b509190346104275760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610427576121db612c0f565b906121e4612c37565b604435916121f184612ea1565b73ffffffffffffffffffffffffffffffffffffffff84168552601560205280852033865260205280852081519061222782612db0565b600281549182845260018101546020850152015490838301918252156122b35751421161228b5751831161226357506116ca93945033926130d3565b8590517f1dc41441000000000000000000000000000000000000000000000000000000008152fd5b8682517fddb7f867000000000000000000000000000000000000000000000000000000008152fd5b8783517f8ec70231000000000000000000000000000000000000000000000000000000008152fd5b50503461042757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104275780602092612317612c0f565b61231f612c37565b73ffffffffffffffffffffffffffffffffffffffff9182168352600c865283832091168252845220549051908152f35b505034610427576020807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103c15773ffffffffffffffffffffffffffffffffffffffff92836123a0612c0f565b1681526016825282812091835190818185549182815201908195855282852090855b81811061240e57505050826123d8910383612de8565b8451948186019282875251809352850193925b8281106123f85785850386f35b83518716855293810193928101926001016123eb565b82548a16845292840192600192830192016123c2565b50346103c157817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103c15761245b612c0f565b73ffffffffffffffffffffffffffffffffffffffff6024359161247c612cd2565b16918215612594578285526006602052838520541561256d57828552600960205260ff84862054166125465766038d7ea4c6800082108061253d575b801561252c575b612505575060207f849877e3a920a233bd1dadf1bfcdd066f09c852b05378ad093af9c745b327bb39183865260088252808587205560068252848620549451908152a380f35b83517f94463346000000000000000000000000000000000000000000000000000000008152fd5b50670de0b6b3a764000082116124bf565b508115156124b8565b83517f6cd7ad06000000000000000000000000000000000000000000000000000000008152fd5b83517f613970e0000000000000000000000000000000000000000000000000000000008152fd5b83517f9fabe1c1000000000000000000000000000000000000000000000000000000008152fd5b50503461042757817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610427576020905173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000a241a6670231ea66ac3bfe95f29c67f2bb28113b168152f35b50346103c157817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103c157612661612c0f565b9161266a612c37565b92612673612cd2565b73ffffffffffffffffffffffffffffffffffffffff809116938415801561277a575b61275257169283855260056020528185205461272b57845281602052808420549182156115e35750816020917f6f1094cad3fd96620239637ccce6fa95cc123710b81f399069bb5b047ec232ea93865260038352600181872001857fffffffffffffffffffffffff000000000000000000000000000000000000000082541617905584865260058352818187205551908152a280f35b50517fa3d582ec000000000000000000000000000000000000000000000000000000008152fd5b5050517f9fabe1c1000000000000000000000000000000000000000000000000000000008152fd5b5081811615612695565b50503461042757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261042757806020926127c0612c0f565b6127c8612c37565b73ffffffffffffffffffffffffffffffffffffffff91821683526014865283832091168252845220549051908152f35b5091903461042757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261042757612831612c0f565b9061283a612c37565b90612843612cd2565b73ffffffffffffffffffffffffffffffffffffffff8093169182158015612998575b61297057828552602091868352808620541580159061295b575b612933577f1005b8f1174594df83bf60033ed95f2a1503df5a39a7315b66d662617144719f93949596600254926128b584612e29565b60025582516128c381612d65565b87815288868201921698898352858b5260038752600181868d20935116927fffffffffffffffffffffffff0000000000000000000000000000000000000000938482541617815501925116908254161790558588528352818188205585875260058352818188205551908152a380f35b8690517fa3d582ec000000000000000000000000000000000000000000000000000000008152fd5b5084821686526005835280862054151561287f565b8582517f9fabe1c1000000000000000000000000000000000000000000000000000000008152fd5b5083811615612865565b50346103c15760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103c15791819235815260036020522073ffffffffffffffffffffffffffffffffffffffff6001818354169201541682519182526020820152f35b5050346104275760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261042757602090612a71612a48612c0f565b73ffffffffffffffffffffffffffffffffffffffff166000526006602052604060002054151590565b90519015158152f35b5050346104275760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610427578060209273ffffffffffffffffffffffffffffffffffffffff612acc612c0f565b1681526006845220549051908152f35b50503461042757817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610427578060209260125481526010845220549051908152f35b5050346104275760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610427578060209273ffffffffffffffffffffffffffffffffffffffff612b74612c0f565b1681526018845220549051908152f35b849084346103c157807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103c15780606093612bc1612c0f565b612bc9612c37565b9073ffffffffffffffffffffffffffffffffffffffff80911683526015602052838320911682526020522090815491600260018201549101549284526020840152820152f35b6004359073ffffffffffffffffffffffffffffffffffffffff82168203612c3257565b600080fd5b6024359073ffffffffffffffffffffffffffffffffffffffff82168203612c3257565b9181601f84011215612c325782359167ffffffffffffffff8311612c32576020808501948460051b010111612c3257565b8054821015612ca35760005260206000200190600090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b73ffffffffffffffffffffffffffffffffffffffff600054163303612cf357565b60246040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152fd5b81810292918115918404141715612d3657565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6040810190811067ffffffffffffffff821117612d8157604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6060810190811067ffffffffffffffff821117612d8157604052565b6080810190811067ffffffffffffffff821117612d8157604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117612d8157604052565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114612d365760010190565b9190811015612ca35760051b0190565b3573ffffffffffffffffffffffffffffffffffffffff81168103612c325790565b91908201809211612d3657565b91908203918211612d3657565b73ffffffffffffffffffffffffffffffffffffffff809116906000908282526016906020938285526040808520549384156130bc578596945b808810612eeb575050505050505050565b8490848852828752612eff89858a20612c8b565b929054600393841b1c16858952601590818952858a20818b5289526002914283888d200154106000146130ac57908a9291888452808b528784208285528b528784205489855260178c52612f57898620918254612e94565b90558884528a52868320908352895285822082815582600182015501557fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff918282019282841161307f578887898d898e8a8a8403613048575b5093945050505052848952858a20908154801561301b5701918890612fd58484612c8b565b81939154921b1b191690555515612fee57945b94612eda565b6024877f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b60248c7f4e487b710000000000000000000000000000000000000000000000000000000081526031600452fd5b613073966119d2958784528282526130628d868620612c8b565b9054908c1b1c169683525220612c8b565b8887898d898e8a612fb0565b60248a7f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b5050509597600191500196612fe8565b50505050505050565b519081600f0b8203612c3257565b9091604051610180810181811067ffffffffffffffff821117612d81576040526000815260006020820152600060408201526000606082015260006080820152600060a0820152600060c0820152600060e0820152600061010082015260006101208201526000610140820152600061016082015262093a80420462093a80804204020462093a801462093a804204151715612d365762093a8042819004810280835290810110612d365762093a8080804204020160208201526040517f71628bfd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416600482015260808160248173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000a241a6670231ea66ac3bfe95f29c67f2bb28113b165afa8015613d6b57600090613d77575b602091500151600f0b60408201526040517fadc6358900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416600482015260208160248173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000a241a6670231ea66ac3bfe95f29c67f2bb28113b165afa908115613d6b57600091613d39575b5060608201526132ed8473ffffffffffffffffffffffffffffffffffffffff166000526006602052604060002054151590565b15613d0f57606081015160208201511015613ce5576127108211613cbb5773ffffffffffffffffffffffffffffffffffffffff8316600052600c602052604060002073ffffffffffffffffffffffffffffffffffffffff8516600052602052604060002054620d2f008101809111612d36574210613c915773ffffffffffffffffffffffffffffffffffffffff8316600052600a602052604060002073ffffffffffffffffffffffffffffffffffffffff8516600052602052604060002093604051946133b986612dcc565b80548087526001820154602088015273ffffffffffffffffffffffffffffffffffffffff60036002840154938460408b01520154166060880152602084015191828111613c77575b505050821580613c6b575b613c63576040820151600081600f0b12613c395761343f846fffffffffffffffffffffffffffffffff6127109316612d23565b049561349a606084015197604051986134578a612dcc565b818a528660208b015260408a015273ffffffffffffffffffffffffffffffffffffffff831660608a01526134946060860151602087015190612e94565b90612d23565b60a084015273ffffffffffffffffffffffffffffffffffffffff811673ffffffffffffffffffffffffffffffffffffffff606088015116141580613be3575b613bb95773ffffffffffffffffffffffffffffffffffffffff8516600052600b6020526135246135196040600020548060c087015260208a015190612e87565b602088015190612e94565b60c084015273ffffffffffffffffffffffffffffffffffffffff811673ffffffffffffffffffffffffffffffffffffffff8616146000146139cd575073ffffffffffffffffffffffffffffffffffffffff84811660008181526018602052604090205460608801516135b9936135ae939116146139c35760005b60e0860152602089015190612e87565b60e084015190612e94565b73ffffffffffffffffffffffffffffffffffffffff85166000526017602052604060002054612710036127108111612d365781116139995773ffffffffffffffffffffffffffffffffffffffff851660005260186020526040600020555b61271060c083015111613999577f45ca9a4c8d0119eb329e580d28fe689e484e1be230da8037ade9547d2d25cc91956080958360c073ffffffffffffffffffffffffffffffffffffffff950151858816600052600b60205260406000205561367e84613ed9565b610100820152848416600052600d602052604060002060208201516000526020526001604060002001546101208201526136b661403d565b610140820152602081015160005260106020526001604060002001546101608201526137016136ef61010083015160a084015190612e87565b828a0151908181111561393757612e94565b858516600052600d602052604060002060208301516000526020526040600020556137396136ef61014083015160a084015190612e87565b60208201516000526010602052604060002055604082015160208201511060001461393e57613782613772610120830151855190612e87565b8351908181111561393757612e94565b858516600052600d6020526040600020602083015160005260205260016040600020015560206137cc6137bc610160840151865190612e87565b8451908181111561393757612e94565b91015160005260106020526001604060002001555b426040820151116138e1575b508051838316600052600e6020526040600020604083015160005260205261381b6040600020918254612e87565b905580516040820151600052601160205261383c6040600020918254612e87565b9055828516600052600a60205260406000208383166000526020528260606003604060002084518155602085015160018201556040850151600282015501920151167fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055818416600052600c60205260406000208282166000526020524260406000205581604051944286521660208501521660408301526060820152a1565b8051848416600052600e6020526040600020604083015160005260205261390e6040600020918254612e94565b905560408151910151600052601160205261392f6040600020918254612e94565b9055386137ed565b5080612e94565b8251858516600052600d6020526040600020602083015160005260205261396e6001604060002001918254612e87565b90556020835191015160005260106020526139926001604060002001918254612e87565b90556137e1565b60046040517f36fd87a2000000000000000000000000000000000000000000000000000000008152fd5b602088015161359e565b73ffffffffffffffffffffffffffffffffffffffff85166000526015602052604060002073ffffffffffffffffffffffffffffffffffffffff8216600052602052613a78613a6d60016040600020015473ffffffffffffffffffffffffffffffffffffffff841673ffffffffffffffffffffffffffffffffffffffff60608b01511614600014613bb25760208901515b60e087015260208a015190612e87565b60e085015190612e94565b9073ffffffffffffffffffffffffffffffffffffffff861673ffffffffffffffffffffffffffffffffffffffff60608901511614613b77575b73ffffffffffffffffffffffffffffffffffffffff86166000526015602052604060002073ffffffffffffffffffffffffffffffffffffffff82166000526020526040600020548211613b4d5773ffffffffffffffffffffffffffffffffffffffff8616600052601560205273ffffffffffffffffffffffffffffffffffffffff60406000209116600052602052600160406000200155613617565b60046040517f1dc41441000000000000000000000000000000000000000000000000000000008152fd5b602087015173ffffffffffffffffffffffffffffffffffffffff87166000526018602052613bab6040600020918254612e94565b9055613ab1565b6000613a5d565b60046040517fdc7905d4000000000000000000000000000000000000000000000000000000008152fd5b5073ffffffffffffffffffffffffffffffffffffffff85166000526015602052604060002073ffffffffffffffffffffffffffffffffffffffff60608801511660005260205242600260406000200154116134d9565b60046040517fc71d1071000000000000000000000000000000000000000000000000000000008152fd5b505050505050565b5060208501511561340c565b613c849261349491612e94565b6080830152388080613401565b60046040517f2aa44a5a000000000000000000000000000000000000000000000000000000008152fd5b60046040517f2fe2ca10000000000000000000000000000000000000000000000000000000008152fd5b60046040517ff6fafba0000000000000000000000000000000000000000000000000000000008152fd5b60046040517f665c1c57000000000000000000000000000000000000000000000000000000008152fd5b90506020813d602011613d63575b81613d5460209383612de8565b81010312612c325751386132ba565b3d9150613d47565b6040513d6000823e3d90fd5b506080813d608011613ddb575b81613d9160809383612de8565b81010312612c3257602090606060405191613dab83612dcc565b613db4816130c5565b8352613dc18482016130c5565b84840152604081015160408401520151606082015261321c565b3d9150613d84565b73ffffffffffffffffffffffffffffffffffffffff1690600090828252600960205260ff604083205416613ed35762093a80809104818102918183041490151715613ea65780825260106020526040822054928315613e9f578252600d60205260408220908252602052604081205490670de0b6b3a764000091828102928184041490151715613e7257500490565b807f4e487b7100000000000000000000000000000000000000000000000000000000602492526011600452fd5b5050905090565b6024827f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b50905090565b73ffffffffffffffffffffffffffffffffffffffff166000818152600f9060209082825260408082205491821561403457600d94858552828220848352855282822094835197613f2889612d65565b8654895260018097015496828a01978852845b6101f48110613f53575b505050505050505050505190565b42881161402f5762093a8097888101809111612fee5780988a51818102918183041490151715614002578c51613fbe939291818110613fd3575050878d52878b525b8488528b865288882081895286528888208d518155848c51910155428111613fc3575b50612e29565b613f3b565b8488528686528888205538613fb8565b613fdc91612e94565b8d52848852600e86528888208189528652613ffb898920548c51612e94565b8b52613f95565b6024887f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b613f45565b94505050505090565b60128054908115614189576000918083526010906020928284526040948581209086519661406a88612d65565b8254885260018093015491878901928352805b6101f48110614094575b5050505050505050505190565b4287116141845762093a8096878101809111614157578097855181810291818304149015171561412a578b516140f6939291818110614103575050838c528386525b808452898b528484208c5181558787519101554281116140fb5750612e29565b61407d565b875538613fb8565b61410c91612e94565b8c5280845260118b52614123858520548751612e94565b86526140d6565b6024847f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b614087565b505060009056fea26469706673582212205e0e176cacd2e89318f182f92400490cfd3d429f5777c47e5ce2bead00ab7eb964736f6c63430008140033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000a241a6670231ea66ac3bfe95f29c67f2bb28113b
-----Decoded View---------------
Arg [0] : _hPalPower (address): 0xa241A6670231Ea66AC3bFe95F29c67f2Bb28113b
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000a241a6670231ea66ac3bfe95f29c67f2bb28113b
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ 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.