Overview
GLMR Balance
GLMR Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 29 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Vote | 8461525 | 150 days ago | IN | 0 GLMR | 0.04561 | ||||
Vote | 7875956 | 191 days ago | IN | 0 GLMR | 0.04561 | ||||
Vote | 7618210 | 209 days ago | IN | 0 GLMR | 0.046074 | ||||
Vote | 7447316 | 221 days ago | IN | 0 GLMR | 0.037149 | ||||
Vote | 6662352 | 276 days ago | IN | 0 GLMR | 0.02674728 | ||||
Vote | 6662338 | 276 days ago | IN | 0 GLMR | 0.01153933 | ||||
Vote | 6662330 | 276 days ago | IN | 0 GLMR | 0.01077021 | ||||
Vote | 6662310 | 276 days ago | IN | 0 GLMR | 0.0110682 | ||||
Vote | 6653341 | 277 days ago | IN | 0 GLMR | 0.02674728 | ||||
Vote | 6652506 | 277 days ago | IN | 0 GLMR | 0.037149 | ||||
Vote | 6527407 | 291 days ago | IN | 0 GLMR | 0.026535 | ||||
Vote | 6516091 | 292 days ago | IN | 0 GLMR | 0.021228 | ||||
Vote | 6515255 | 292 days ago | IN | 0 GLMR | 0.03859038 | ||||
Vote | 6510051 | 293 days ago | IN | 0 GLMR | 0.0106425 | ||||
Claim Ownership | 6479363 | 297 days ago | IN | 0 GLMR | 0.0077825 | ||||
Vote | 6464256 | 300 days ago | IN | 0 GLMR | 0.047763 | ||||
Add Pool | 6464031 | 300 days ago | IN | 0 GLMR | 0.026535 | ||||
Remove Pool | 6463783 | 300 days ago | IN | 0 GLMR | 0.015921 | ||||
Transfer Ownersh... | 6458958 | 300 days ago | IN | 0 GLMR | 0.007831 | ||||
Transfer Ownersh... | 6458954 | 300 days ago | IN | 0 GLMR | 0.00783062 | ||||
Transfer Ownersh... | 6458949 | 300 days ago | IN | 0 GLMR | 0.00783062 | ||||
Transfer Ownersh... | 6458942 | 300 days ago | IN | 0 GLMR | 0.00783062 | ||||
Transfer Ownersh... | 6458935 | 300 days ago | IN | 0 GLMR | 0.00783062 | ||||
Add Pool | 6458770 | 300 days ago | IN | 0 GLMR | 0.026535 | ||||
Add Pool | 6458654 | 300 days ago | IN | 0 GLMR | 0.037149 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
ZenlinkVotingControllerUpg
Compiler Version
v0.8.24+commit.e11b9ed9
Optimization Enabled:
Yes with 800 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.24; import {UUPSUpgradeable} from "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol"; import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import {EnumerableMap} from "@openzeppelin/contracts/utils/structs/EnumerableMap.sol"; import {VotingControllerStorageUpg} from "./VotingControllerStorageUpg.sol"; import {ZenlinkMsgSenderAppUpg} from "../CrossChainMsg/ZenlinkMsgSenderAppUpg.sol"; import {VeBalanceLib, VeBalance, LockedPosition} from "../libraries/VeBalanceLib.sol"; import {PMath} from "../../core/libraries/math/PMath.sol"; import {BoringOwnableUpgradeable} from "../../core/libraries/BoringOwnableUpgradeable.sol"; import {Errors} from "../../core/libraries/Errors.sol"; import {WeekMath} from "../libraries/WeekMath.sol"; import {IPGaugeControllerMainchain} from "../../interfaces/IPGaugeControllerMainchain.sol"; import {IPVotingController} from "../../interfaces/IPVotingController.sol"; /* Voting accounting: - For gauge controller, it will consider each message from voting controller as a pack of money to incentivize it during the very next WEEK (block.timestamp -> block.timestamp + WEEK) - If the reward duration for the last pack of money has not ended, it will combine the leftover reward with the current reward to distribute. - In the very extreme case where no one broadcast the result of week x, and at week x+1, the results for both are now broadcasted, then the WEEK of (block.timestamp -> WEEK) will receive both of the reward pack - Each pack of money will has it own id as timestamp, a gauge controller does not receive a pack of money with the same id twice, this allow governance to rebroadcast in case the last message was corrupted by LayerZero Pros: - If governance does not forget broadcasting the reward on the early of the week, the mechanism works just the same as the epoch-based one - If governance forget to broadcast the reward, the whole system still works normally, the reward is still incentivized, but only approximately fair Cons: - Does not guarantee the reward will be distributed on epoch start and end */ contract ZenlinkVotingControllerUpg is ZenlinkMsgSenderAppUpg, VotingControllerStorageUpg, UUPSUpgradeable { using VeBalanceLib for VeBalance; using PMath for uint256; using PMath for int256; using EnumerableMap for EnumerableMap.UintToAddressMap; using EnumerableSet for EnumerableSet.AddressSet; constructor(address _veZLK, address _zenlinkMsgSendEndpoint, uint256 initialApproxDestinationGas) VotingControllerStorageUpg(_veZLK) ZenlinkMsgSenderAppUpg(_zenlinkMsgSendEndpoint, initialApproxDestinationGas) {} function initialize() external initializer { __BoringOwnable_init(); deployedWTime = WeekMath.getCurrentWeekStart(); } /*/////////////////////////////////////////////////////////////// FUNCTIONS CAN BE CALLED BY ANYONE //////////////////////////////////////////////////////////////*/ /** * @notice updates a user's vote weights, also allowing user to divide their voting power * across different pools * @param pools pools to change vote weights, if not listed then existing weight won't change * @param weights voting weight on each pool in `pools`, must be same length as `pools` * @dev A user's max voting weights is equal to `USER_VOTE_MAX_WEIGHT` (1e18). If their total * voted weights is less than such, then the excess weight is not counted. For such reason, a * user's voting power will only be fully utilized if their total voted weight is exactly 1e18. * @dev Reverts if, after all vote changes, the total voted weight is more than 1e18. * @dev A removed pool can be included, but the new weight must be 0, otherwise will revert. * @dev See {`VotingControllerStorageUpg - getUserData()`} for current user data. */ function vote(address[] calldata pools, uint64[] calldata weights) external { address user = msg.sender; if (pools.length != weights.length) revert Errors.ArrayLengthMismatch(); if (user != owner && veZLK.balanceOf(user) == 0) revert Errors.VCZeroVeZenlink(user); LockedPosition memory userPosition = _getUserVeZLKPosition(user); for (uint256 i = 0; i < pools.length; ++i) { if (_isPoolActive(pools[i])) applyPoolSlopeChanges(pools[i]); VeBalance memory newVote = _modifyVoteWeight(user, pools[i], userPosition, weights[i]); emit Vote(user, pools[i], weights[i], newVote); } uint256 totalVotedWeight = userData[user].totalVotedWeight; if (totalVotedWeight > VeBalanceLib.USER_VOTE_MAX_WEIGHT) { revert Errors.VCExceededMaxWeight(totalVotedWeight, VeBalanceLib.USER_VOTE_MAX_WEIGHT); } } /** * @notice Process all the slopeChanges that haven't been processed & update these data into * poolData * @dev reverts if pool is not active * @dev if pool is already up-to-date, the function will succeed without any state updates */ function applyPoolSlopeChanges(address pool) public { if (!_isPoolActive(pool)) revert Errors.VCInactivePool(pool); uint128 wTime = poolData[pool].lastSlopeChangeAppliedAt; uint128 currentWeekStart = WeekMath.getCurrentWeekStart(); // no state changes are expected if (wTime >= currentWeekStart) return; VeBalance memory currentVote = poolData[pool].totalVote; while (wTime < currentWeekStart) { wTime += WEEK; currentVote = currentVote.sub(poolData[pool].slopeChanges[wTime], wTime); _setFinalPoolVoteForWeek(pool, wTime, currentVote.getValueAt(wTime)); } _setNewVotePoolData(pool, currentVote, wTime); } /** * @notice finalize the voting results of all pools, up to the current epoch * @dev See `applyPoolSlopeChanges()` for more details * @dev This function might be gas-costly if there are a lot of active pools, but this can be * mitigated by calling `applyPoolSlopeChanges()` for each pool separately, spreading the gas * cost across multiple txs (although the total gas cost will be higher). * This is because `applyPoolSlopeChanges()` will not update anything if already up-to-date. */ function finalizeEpoch() public { uint256 length = allActivePools.length(); for (uint256 i = 0; i < length; ++i) { applyPoolSlopeChanges(allActivePools.at(i)); } _setAllPastEpochsAsFinalized(); } /** * @notice broadcast the voting results of the current week to the chain with chainId. Can be * called by anyone. * @dev It's intentional to allow the same results to be broadcasted multiple * times. The receiver should be able to filter these duplicated messages * @dev The epoch must have already been finalized by `finalizeEpoch()`, otherwise will revert. */ function broadcastResults(uint64 chainId) external payable refundUnusedEth { uint128 wTime = WeekMath.getCurrentWeekStart(); if (!weekData[wTime].isEpochFinalized) revert Errors.VCEpochNotFinalized(wTime); _broadcastResults(chainId, wTime, zlkPerSec); } /*/////////////////////////////////////////////////////////////// GOVERNANCE-ONLY FUNCTIONS //////////////////////////////////////////////////////////////*/ /** * @notice add a pool to allow users to vote. Can only be done by governance * @custom:gov NOTE TO GOV: * - Previous week's results should have been broadcasted prior to calling this function. * - `pool` must not have been added before (even if has been removed). * - `chainId` must be valid. */ function addPool(uint64 chainId, address pool) external onlyOwner { if (_isPoolActive(pool)) revert Errors.VCPoolAlreadyActive(pool); if (allRemovedPools.contains(pool)) revert Errors.VCPoolAlreadyAddAndRemoved(pool); _addPool(chainId, pool); emit AddPool(chainId, pool); } /** * @notice remove a pool from voting. Can only be done by governance * @custom:gov NOTE TO GOV: * - Previous week's results should have been broadcasted prior to calling this function. * - `pool` must be currently active. */ function removePool(address pool) external onlyOwner { if (!_isPoolActive(pool)) revert Errors.VCInactivePool(pool); uint64 chainId = poolData[pool].chainId; applyPoolSlopeChanges(pool); _removePool(pool); emit RemovePool(chainId, pool); } /** * @notice use the gov-privilege to force broadcast a message in case there are issues with LayerZero * @custom:gov NOTE TO GOV: gov should always call finalizeEpoch beforehand */ function forceBroadcastResults(uint64 chainId, uint128 wTime, uint128 forcedzlkPerSec) external payable onlyOwner refundUnusedEth { _broadcastResults(chainId, wTime, forcedzlkPerSec); } /** * @notice sets new zlkPerSec * @dev no zero checks because gov may want to stop liquidity mining * @custom:gov NOTE TO GOV: Should be done mid-week, well before the next broadcast to avoid * race condition */ function setZLKPerSec(uint128 newZLKPerSec) external onlyOwner { zlkPerSec = newZLKPerSec; emit SetZLKPerSec(newZLKPerSec); } function getBroadcastResultFee(uint64 chainId) external view returns (uint256) { if (chainId == block.chainid) return 0; // Mainchain broadcast uint256 length = activeChainPools[chainId].length(); if (length == 0) return 0; address[] memory pools = new address[](length); uint256[] memory totalZLKAmounts = new uint256[](length); return _getSendMessageFee(chainId, abi.encode(uint128(0), pools, totalZLKAmounts)); } /*/////////////////////////////////////////////////////////////// INTERNAL FUNCTIONS //////////////////////////////////////////////////////////////*/ /// @notice broadcast voting results of the timestamp to chainId function _broadcastResults(uint64 chainId, uint128 wTime, uint128 totalZLKPerSec) internal { uint256 totalVotes = weekData[wTime].totalVotes; if (totalVotes == 0) return; uint256 length = activeChainPools[chainId].length(); if (length == 0) return; address[] memory pools = activeChainPools[chainId].values(); uint256[] memory totalZLKAmounts = new uint256[](length); for (uint256 i = 0; i < length; ++i) { uint256 poolVotes = weekData[wTime].poolVotes[pools[i]]; totalZLKAmounts[i] = (totalZLKPerSec * poolVotes * WEEK) / totalVotes; } if (chainId == block.chainid) { address gaugeController = destinationContracts.get(chainId); IPGaugeControllerMainchain(gaugeController).updateVotingResults(wTime, pools, totalZLKAmounts); } else { _sendMessage(chainId, abi.encode(wTime, pools, totalZLKAmounts)); } emit BroadcastResults(chainId, wTime, totalZLKPerSec); } function _getUserVeZLKPosition(address user) internal view returns (LockedPosition memory userPosition) { if (user == owner) { (userPosition.amount, userPosition.expiry) = (GOVERNANCE_ZLK_VOTE, WeekMath.getWeekStartTimestamp(uint128(block.timestamp) + MAX_LOCK_TIME)); } else { (userPosition.amount, userPosition.expiry) = veZLK.positionData(user); } } function _authorizeUpgrade(address newImplementation) internal override onlyOwner {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/UUPSUpgradeable.sol) pragma solidity ^0.8.0; import "../../interfaces/draft-IERC1822.sol"; import "../ERC1967/ERC1967Upgrade.sol"; /** * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy. * * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing * `UUPSUpgradeable` with a custom implementation of upgrades. * * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism. * * _Available since v4.1._ */ abstract contract UUPSUpgradeable is IERC1822Proxiable, ERC1967Upgrade { /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment address private immutable __self = address(this); /** * @dev Check that the execution is being performed through a delegatecall call and that the execution context is * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to * fail. */ modifier onlyProxy() { require(address(this) != __self, "Function must be called through delegatecall"); require(_getImplementation() == __self, "Function must be called through active proxy"); _; } /** * @dev Check that the execution is not being performed through a delegate call. This allows a function to be * callable on the implementing contract but not through proxies. */ modifier notDelegated() { require(address(this) == __self, "UUPSUpgradeable: must not be called through delegatecall"); _; } /** * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the * implementation. It is used to validate the implementation's compatibility when performing an upgrade. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier. */ function proxiableUUID() external view virtual override notDelegated returns (bytes32) { return _IMPLEMENTATION_SLOT; } /** * @dev Upgrade the implementation of the proxy to `newImplementation`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. * * @custom:oz-upgrades-unsafe-allow-reachable delegatecall */ function upgradeTo(address newImplementation) public virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, new bytes(0), false); } /** * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call * encoded in `data`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. * * @custom:oz-upgrades-unsafe-allow-reachable delegatecall */ function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, data, true); } /** * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by * {upgradeTo} and {upgradeToAndCall}. * * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}. * * ```solidity * function _authorizeUpgrade(address) internal override onlyOwner {} * ``` */ function _authorizeUpgrade(address newImplementation) internal virtual; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol) // This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. pragma solidity ^0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ```solidity * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure * unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an * array of EnumerableSet. * ==== */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; if (lastIndex != toDeleteIndex) { bytes32 lastValue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastValue; // Update the index for the moved value set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex } // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { bytes32[] memory store = _values(set._inner); bytes32[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values in the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableMap.sol) // This file was procedurally generated from scripts/generate/templates/EnumerableMap.js. pragma solidity ^0.8.0; import "./EnumerableSet.sol"; /** * @dev Library for managing an enumerable variant of Solidity's * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`] * type. * * Maps have the following properties: * * - Entries are added, removed, and checked for existence in constant time * (O(1)). * - Entries are enumerated in O(n). No guarantees are made on the ordering. * * ```solidity * contract Example { * // Add the library methods * using EnumerableMap for EnumerableMap.UintToAddressMap; * * // Declare a set state variable * EnumerableMap.UintToAddressMap private myMap; * } * ``` * * The following map types are supported: * * - `uint256 -> address` (`UintToAddressMap`) since v3.0.0 * - `address -> uint256` (`AddressToUintMap`) since v4.6.0 * - `bytes32 -> bytes32` (`Bytes32ToBytes32Map`) since v4.6.0 * - `uint256 -> uint256` (`UintToUintMap`) since v4.7.0 * - `bytes32 -> uint256` (`Bytes32ToUintMap`) since v4.7.0 * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure * unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableMap, you can either remove all elements one by one or create a fresh instance using an * array of EnumerableMap. * ==== */ library EnumerableMap { using EnumerableSet for EnumerableSet.Bytes32Set; // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Map type with // bytes32 keys and values. // The Map implementation uses private functions, and user-facing // implementations (such as Uint256ToAddressMap) are just wrappers around // the underlying Map. // This means that we can only create new EnumerableMaps for types that fit // in bytes32. struct Bytes32ToBytes32Map { // Storage of keys EnumerableSet.Bytes32Set _keys; mapping(bytes32 => bytes32) _values; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set(Bytes32ToBytes32Map storage map, bytes32 key, bytes32 value) internal returns (bool) { map._values[key] = value; return map._keys.add(key); } /** * @dev Removes a key-value pair from a map. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(Bytes32ToBytes32Map storage map, bytes32 key) internal returns (bool) { delete map._values[key]; return map._keys.remove(key); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool) { return map._keys.contains(key); } /** * @dev Returns the number of key-value pairs in the map. O(1). */ function length(Bytes32ToBytes32Map storage map) internal view returns (uint256) { return map._keys.length(); } /** * @dev Returns the key-value pair stored at position `index` in the map. O(1). * * Note that there are no guarantees on the ordering of entries inside the * array, and it may change when more entries are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32ToBytes32Map storage map, uint256 index) internal view returns (bytes32, bytes32) { bytes32 key = map._keys.at(index); return (key, map._values[key]); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. */ function tryGet(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool, bytes32) { bytes32 value = map._values[key]; if (value == bytes32(0)) { return (contains(map, key), bytes32(0)); } else { return (true, value); } } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bytes32) { bytes32 value = map._values[key]; require(value != 0 || contains(map, key), "EnumerableMap: nonexistent key"); return value; } /** * @dev Same as {get}, with a custom error message when `key` is not in the map. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryGet}. */ function get( Bytes32ToBytes32Map storage map, bytes32 key, string memory errorMessage ) internal view returns (bytes32) { bytes32 value = map._values[key]; require(value != 0 || contains(map, key), errorMessage); return value; } /** * @dev Return the an array containing all the keys * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block. */ function keys(Bytes32ToBytes32Map storage map) internal view returns (bytes32[] memory) { return map._keys.values(); } // UintToUintMap struct UintToUintMap { Bytes32ToBytes32Map _inner; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set(UintToUintMap storage map, uint256 key, uint256 value) internal returns (bool) { return set(map._inner, bytes32(key), bytes32(value)); } /** * @dev Removes a value from a map. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(UintToUintMap storage map, uint256 key) internal returns (bool) { return remove(map._inner, bytes32(key)); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(UintToUintMap storage map, uint256 key) internal view returns (bool) { return contains(map._inner, bytes32(key)); } /** * @dev Returns the number of elements in the map. O(1). */ function length(UintToUintMap storage map) internal view returns (uint256) { return length(map._inner); } /** * @dev Returns the element stored at position `index` in the map. O(1). * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintToUintMap storage map, uint256 index) internal view returns (uint256, uint256) { (bytes32 key, bytes32 value) = at(map._inner, index); return (uint256(key), uint256(value)); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. */ function tryGet(UintToUintMap storage map, uint256 key) internal view returns (bool, uint256) { (bool success, bytes32 value) = tryGet(map._inner, bytes32(key)); return (success, uint256(value)); } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(UintToUintMap storage map, uint256 key) internal view returns (uint256) { return uint256(get(map._inner, bytes32(key))); } /** * @dev Same as {get}, with a custom error message when `key` is not in the map. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryGet}. */ function get(UintToUintMap storage map, uint256 key, string memory errorMessage) internal view returns (uint256) { return uint256(get(map._inner, bytes32(key), errorMessage)); } /** * @dev Return the an array containing all the keys * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block. */ function keys(UintToUintMap storage map) internal view returns (uint256[] memory) { bytes32[] memory store = keys(map._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // UintToAddressMap struct UintToAddressMap { Bytes32ToBytes32Map _inner; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) { return set(map._inner, bytes32(key), bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a map. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) { return remove(map._inner, bytes32(key)); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) { return contains(map._inner, bytes32(key)); } /** * @dev Returns the number of elements in the map. O(1). */ function length(UintToAddressMap storage map) internal view returns (uint256) { return length(map._inner); } /** * @dev Returns the element stored at position `index` in the map. O(1). * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) { (bytes32 key, bytes32 value) = at(map._inner, index); return (uint256(key), address(uint160(uint256(value)))); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. */ function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) { (bool success, bytes32 value) = tryGet(map._inner, bytes32(key)); return (success, address(uint160(uint256(value)))); } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(UintToAddressMap storage map, uint256 key) internal view returns (address) { return address(uint160(uint256(get(map._inner, bytes32(key))))); } /** * @dev Same as {get}, with a custom error message when `key` is not in the map. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryGet}. */ function get( UintToAddressMap storage map, uint256 key, string memory errorMessage ) internal view returns (address) { return address(uint160(uint256(get(map._inner, bytes32(key), errorMessage)))); } /** * @dev Return the an array containing all the keys * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block. */ function keys(UintToAddressMap storage map) internal view returns (uint256[] memory) { bytes32[] memory store = keys(map._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // AddressToUintMap struct AddressToUintMap { Bytes32ToBytes32Map _inner; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set(AddressToUintMap storage map, address key, uint256 value) internal returns (bool) { return set(map._inner, bytes32(uint256(uint160(key))), bytes32(value)); } /** * @dev Removes a value from a map. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(AddressToUintMap storage map, address key) internal returns (bool) { return remove(map._inner, bytes32(uint256(uint160(key)))); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(AddressToUintMap storage map, address key) internal view returns (bool) { return contains(map._inner, bytes32(uint256(uint160(key)))); } /** * @dev Returns the number of elements in the map. O(1). */ function length(AddressToUintMap storage map) internal view returns (uint256) { return length(map._inner); } /** * @dev Returns the element stored at position `index` in the map. O(1). * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressToUintMap storage map, uint256 index) internal view returns (address, uint256) { (bytes32 key, bytes32 value) = at(map._inner, index); return (address(uint160(uint256(key))), uint256(value)); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. */ function tryGet(AddressToUintMap storage map, address key) internal view returns (bool, uint256) { (bool success, bytes32 value) = tryGet(map._inner, bytes32(uint256(uint160(key)))); return (success, uint256(value)); } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(AddressToUintMap storage map, address key) internal view returns (uint256) { return uint256(get(map._inner, bytes32(uint256(uint160(key))))); } /** * @dev Same as {get}, with a custom error message when `key` is not in the map. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryGet}. */ function get( AddressToUintMap storage map, address key, string memory errorMessage ) internal view returns (uint256) { return uint256(get(map._inner, bytes32(uint256(uint160(key))), errorMessage)); } /** * @dev Return the an array containing all the keys * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block. */ function keys(AddressToUintMap storage map) internal view returns (address[] memory) { bytes32[] memory store = keys(map._inner); address[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // Bytes32ToUintMap struct Bytes32ToUintMap { Bytes32ToBytes32Map _inner; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set(Bytes32ToUintMap storage map, bytes32 key, uint256 value) internal returns (bool) { return set(map._inner, key, bytes32(value)); } /** * @dev Removes a value from a map. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(Bytes32ToUintMap storage map, bytes32 key) internal returns (bool) { return remove(map._inner, key); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool) { return contains(map._inner, key); } /** * @dev Returns the number of elements in the map. O(1). */ function length(Bytes32ToUintMap storage map) internal view returns (uint256) { return length(map._inner); } /** * @dev Returns the element stored at position `index` in the map. O(1). * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32ToUintMap storage map, uint256 index) internal view returns (bytes32, uint256) { (bytes32 key, bytes32 value) = at(map._inner, index); return (key, uint256(value)); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. */ function tryGet(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool, uint256) { (bool success, bytes32 value) = tryGet(map._inner, key); return (success, uint256(value)); } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(Bytes32ToUintMap storage map, bytes32 key) internal view returns (uint256) { return uint256(get(map._inner, key)); } /** * @dev Same as {get}, with a custom error message when `key` is not in the map. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryGet}. */ function get( Bytes32ToUintMap storage map, bytes32 key, string memory errorMessage ) internal view returns (uint256) { return uint256(get(map._inner, key, errorMessage)); } /** * @dev Return the an array containing all the keys * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block. */ function keys(Bytes32ToUintMap storage map) internal view returns (bytes32[] memory) { bytes32[] memory store = keys(map._inner); bytes32[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.24; import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import {VeBalanceLib, VeBalance, LockedPosition} from "../libraries/VeBalanceLib.sol"; import {WeekMath} from "../libraries/WeekMath.sol"; import {Checkpoints, Checkpoint} from "../libraries/VeHistoryLib.sol"; import {MiniHelpers} from "../../core/libraries/MiniHelpers.sol"; import {Errors} from "../../core/libraries/Errors.sol"; import {IPVeToken} from "../../interfaces/IPVeToken.sol"; import {IPVotingController} from "../../interfaces/IPVotingController.sol"; abstract contract VotingControllerStorageUpg is IPVotingController { using VeBalanceLib for VeBalance; using VeBalanceLib for LockedPosition; using EnumerableSet for EnumerableSet.AddressSet; using Checkpoints for Checkpoints.History; using WeekMath for uint128; struct PoolData { uint64 chainId; uint128 lastSlopeChangeAppliedAt; VeBalance totalVote; // wTime => slopeChange value mapping(uint128 => uint128) slopeChanges; } struct UserPoolData { uint64 weight; VeBalance vote; } struct UserData { uint64 totalVotedWeight; mapping(address => UserPoolData) voteForPools; } struct WeekData { bool isEpochFinalized; uint128 totalVotes; mapping(address => uint128) poolVotes; } uint128 public constant MAX_LOCK_TIME = 104 weeks; uint128 public constant WEEK = 1 weeks; uint128 public constant GOVERNANCE_ZLK_VOTE = 10 * (10 ** 6) * (10 ** 18); // 10 mils of ZLK IPVeToken public immutable veZLK; uint128 public deployedWTime; uint128 public zlkPerSec; EnumerableSet.AddressSet internal allActivePools; EnumerableSet.AddressSet internal allRemovedPools; // [chainId] => [pool] mapping(uint64 => EnumerableSet.AddressSet) internal activeChainPools; // [poolAddress] -> PoolData mapping(address => PoolData) internal poolData; // [wTime] => WeekData mapping(uint128 => WeekData) internal weekData; // user voting data mapping(address => UserData) internal userData; // [user][pool] => checkpoint mapping(address => mapping(address => Checkpoints.History)) internal __dep_userPoolHistory; uint256[100] private __gap; constructor(address _veZLK) { veZLK = IPVeToken(_veZLK); } /*/////////////////////////////////////////////////////////////// VIEW FUNCTIONS //////////////////////////////////////////////////////////////*/ function getPoolTotalVoteAt(address pool, uint128 wTime) public view returns (uint128) { return weekData[wTime].poolVotes[pool]; } /// @notice deprecated, only kept for compatibility reasons function getUserPoolHistoryLength(address user, address pool) external view returns (uint256) { return __dep_userPoolHistory[user][pool].length(); } /// @notice deprecated, only kept for compatibility reasons function getUserPoolHistoryAt(address user, address pool, uint256 index) external view returns (Checkpoint memory) { return __dep_userPoolHistory[user][pool].get(index); } function getPoolData(address pool, uint128[] calldata wTimes) public view returns ( uint64 chainId, uint128 lastSlopeChangeAppliedAt, VeBalance memory totalVote, uint128[] memory slopeChanges ) { PoolData storage data = poolData[pool]; (chainId, lastSlopeChangeAppliedAt, totalVote) = (data.chainId, data.lastSlopeChangeAppliedAt, data.totalVote); slopeChanges = new uint128[](wTimes.length); for (uint256 i = 0; i < wTimes.length; ++i) { if (!wTimes[i].isValidWTime()) revert Errors.InvalidWTime(wTimes[i]); slopeChanges[i] = data.slopeChanges[wTimes[i]]; } } function getUserData(address user, address[] calldata pools) public view returns (uint64 totalVotedWeight, UserPoolData[] memory voteForPools) { UserData storage data = userData[user]; totalVotedWeight = data.totalVotedWeight; voteForPools = new UserPoolData[](pools.length); for (uint256 i = 0; i < pools.length; ++i) { voteForPools[i] = data.voteForPools[pools[i]]; } } function getWeekData(uint128 wTime, address[] calldata pools) public view returns (bool isEpochFinalized, uint128 totalVotes, uint128[] memory poolVotes) { if (!wTime.isValidWTime()) revert Errors.InvalidWTime(wTime); WeekData storage data = weekData[wTime]; (isEpochFinalized, totalVotes) = (data.isEpochFinalized, data.totalVotes); poolVotes = new uint128[](pools.length); for (uint256 i = 0; i < pools.length; ++i) { poolVotes[i] = data.poolVotes[pools[i]]; } } function getAllActivePools() external view returns (address[] memory) { return allActivePools.values(); } function getAllRemovedPools(uint256 start, uint256 end) external view returns (uint256 lengthOfRemovedPools, address[] memory arr) { lengthOfRemovedPools = allRemovedPools.length(); if (end >= lengthOfRemovedPools) revert Errors.ArrayOutOfBounds(); arr = new address[](end - start + 1); for (uint256 i = start; i <= end; ++i) { arr[i - start] = allRemovedPools.at(i); } } function getActiveChainPools(uint64 chainId) external view returns (address[] memory) { return activeChainPools[chainId].values(); } function getUserPoolVote(address user, address pool) external view returns (UserPoolData memory) { return userData[user].voteForPools[pool]; } /*/////////////////////////////////////////////////////////////// INTERNAL DATA MANIPULATION FUNCTIONS //////////////////////////////////////////////////////////////*/ function _addPool(uint64 chainId, address pool) internal { if (!activeChainPools[chainId].add(pool)) assert(false); if (!allActivePools.add(pool)) assert(false); poolData[pool].chainId = chainId; poolData[pool].lastSlopeChangeAppliedAt = WeekMath.getCurrentWeekStart(); } function _removePool(address pool) internal { uint64 chainId = poolData[pool].chainId; if (!activeChainPools[chainId].remove(pool)) assert(false); if (!allActivePools.remove(pool)) assert(false); if (!allRemovedPools.add(pool)) assert(false); delete poolData[pool]; } function _setFinalPoolVoteForWeek(address pool, uint128 wTime, uint128 vote) internal { weekData[wTime].totalVotes += vote; weekData[wTime].poolVotes[pool] = vote; } function _setNewVotePoolData(address pool, VeBalance memory vote, uint128 wTime) internal { poolData[pool].totalVote = vote; poolData[pool].lastSlopeChangeAppliedAt = wTime; emit PoolVoteChange(pool, vote); } /** * @notice modifies `user`'s vote weight on `pool` * @dev works by simply removing the old vote position, then adds in a fresh vote */ function _modifyVoteWeight(address user, address pool, LockedPosition memory userPosition, uint64 weight) internal returns (VeBalance memory newVote) { UserData storage uData = userData[user]; PoolData storage pData = poolData[pool]; VeBalance memory oldVote = uData.voteForPools[pool].vote; // REMOVE OLD VOTE if (oldVote.bias != 0) { if (_isPoolActive(pool) && _isVoteActive(oldVote)) { pData.totalVote = pData.totalVote.sub(oldVote); pData.slopeChanges[oldVote.getExpiry()] -= oldVote.slope; } uData.totalVotedWeight -= uData.voteForPools[pool].weight; delete uData.voteForPools[pool]; } // ADD NEW VOTE if (weight != 0) { if (!_isPoolActive(pool)) revert Errors.VCInactivePool(pool); newVote = userPosition.convertToVeBalance(weight); pData.totalVote = pData.totalVote.add(newVote); pData.slopeChanges[newVote.getExpiry()] += newVote.slope; uData.voteForPools[pool] = UserPoolData(weight, newVote); uData.totalVotedWeight += weight; } emit PoolVoteChange(pool, pData.totalVote); } function _setAllPastEpochsAsFinalized() internal { uint128 wTime = WeekMath.getCurrentWeekStart(); while (wTime > deployedWTime && weekData[wTime].isEpochFinalized == false) { weekData[wTime].isEpochFinalized = true; wTime -= WEEK; } } function _isPoolActive(address pool) internal view returns (bool) { return allActivePools.contains(pool); } /// @notice check if a vote still counts by checking if the vote is not (x,0) (in case the /// weight of the vote is too small) & the expiry is after the current time function _isVoteActive(VeBalance memory vote) internal view returns (bool) { return vote.slope != 0 && !MiniHelpers.isCurrentlyExpired(vote.getExpiry()); } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.24; import {EnumerableMap} from "@openzeppelin/contracts/utils/structs/EnumerableMap.sol"; import {Address} from "@openzeppelin/contracts/utils/Address.sol"; import {BoringOwnableUpgradeable} from "../../core/libraries/BoringOwnableUpgradeable.sol"; import {Errors} from "../../core/libraries/Errors.sol"; import {IPMsgSendEndpoint} from "../../interfaces/IPMsgSendEndpoint.sol"; abstract contract ZenlinkMsgSenderAppUpg is BoringOwnableUpgradeable { using EnumerableMap for EnumerableMap.UintToAddressMap; uint256 public approxDstExecutionGas; IPMsgSendEndpoint public immutable zenlinkMsgSendEndpoint; // destinationContracts mapping contains one address for each chainId only EnumerableMap.UintToAddressMap internal destinationContracts; uint256[100] private __gap; modifier refundUnusedEth() { _; if (address(this).balance > 0) { Address.sendValue(payable(msg.sender), address(this).balance); } } constructor(address _zenlinkMsgSendEndpoint, uint256 _approxDstExecutionGas) { zenlinkMsgSendEndpoint = IPMsgSendEndpoint(_zenlinkMsgSendEndpoint); approxDstExecutionGas = _approxDstExecutionGas; } function _sendMessage(uint256 chainId, bytes memory message) internal { assert(destinationContracts.contains(chainId)); address toAddr = destinationContracts.get(chainId); uint256 estimatedGasAmount = approxDstExecutionGas; uint256 fee = zenlinkMsgSendEndpoint.calcFee(toAddr, chainId, message, estimatedGasAmount); // LM contracts won't hold ETH on its own so this is fine if (address(this).balance < fee) revert Errors.InsufficientFeeToSendMsg(address(this).balance, fee); zenlinkMsgSendEndpoint.sendMessage{value: fee}(toAddr, chainId, message, estimatedGasAmount); } function addDestinationContract(address _address, uint256 _chainId) external payable onlyOwner { destinationContracts.set(_chainId, _address); } function setApproxDstExecutionGas(uint256 gas) external onlyOwner { approxDstExecutionGas = gas; } function getAllDestinationContracts() public view returns (uint256[] memory chainIds, address[] memory addrs) { uint256 length = destinationContracts.length(); chainIds = new uint256[](length); addrs = new address[](length); for (uint256 i = 0; i < length; ++i) { (chainIds[i], addrs[i]) = destinationContracts.at(i); } } function _getSendMessageFee(uint256 chainId, bytes memory message) internal view returns (uint256) { return zenlinkMsgSendEndpoint.calcFee(destinationContracts.get(chainId), chainId, message, approxDstExecutionGas); } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.24; import {PMath} from "../../core/libraries/math/PMath.sol"; import {Errors} from "../../core/libraries/Errors.sol"; struct VeBalance { uint128 bias; uint128 slope; } struct LockedPosition { uint128 amount; uint128 expiry; } library VeBalanceLib { using PMath for uint256; uint128 internal constant MAX_LOCK_TIME = 104 weeks; uint256 internal constant USER_VOTE_MAX_WEIGHT = 10 ** 18; function add(VeBalance memory a, VeBalance memory b) internal pure returns (VeBalance memory res) { res.bias = a.bias + b.bias; res.slope = a.slope + b.slope; } function sub(VeBalance memory a, VeBalance memory b) internal pure returns (VeBalance memory res) { res.bias = a.bias - b.bias; res.slope = a.slope - b.slope; } function sub(VeBalance memory a, uint128 slope, uint128 expiry) internal pure returns (VeBalance memory res) { res.slope = a.slope - slope; res.bias = a.bias - slope * expiry; } function isExpired(VeBalance memory a) internal view returns (bool) { return a.slope * uint128(block.timestamp) >= a.bias; } function getCurrentValue(VeBalance memory a) internal view returns (uint128) { if (isExpired(a)) return 0; return getValueAt(a, uint128(block.timestamp)); } function getValueAt(VeBalance memory a, uint128 t) internal pure returns (uint128) { if (a.slope * t > a.bias) { return 0; } return a.bias - a.slope * t; } function getExpiry(VeBalance memory a) internal pure returns (uint128) { if (a.slope == 0) revert Errors.VEZeroSlope(a.bias, a.slope); return a.bias / a.slope; } function convertToVeBalance(LockedPosition memory position) internal pure returns (VeBalance memory res) { res.slope = position.amount / MAX_LOCK_TIME; res.bias = res.slope * position.expiry; } function convertToVeBalance(LockedPosition memory position, uint256 weight) internal pure returns (VeBalance memory res) { res.slope = ((position.amount * weight) / MAX_LOCK_TIME / USER_VOTE_MAX_WEIGHT).Uint128(); res.bias = res.slope * position.expiry; } function convertToVeBalance(uint128 amount, uint128 expiry) internal pure returns (uint128, uint128) { VeBalance memory balance = convertToVeBalance(LockedPosition(amount, expiry)); return (balance.bias, balance.slope); } }
// SPDX-License-Identifier: GPL-3.0-or-later // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. pragma solidity ^0.8.24; library PMath { uint256 internal constant ONE = 1e18; // 18 decimal places int256 internal constant IONE = 1e18; // 18 decimal places function subMax0(uint256 a, uint256 b) internal pure returns (uint256) { unchecked { return (a >= b ? a - b : 0); } } function subNoNeg(int256 a, int256 b) internal pure returns (int256) { require(a >= b, "negative"); return a - b; // no unchecked since if b is very negative, a - b might overflow } function mulDown(uint256 a, uint256 b) internal pure returns (uint256) { uint256 product = a * b; unchecked { return product / ONE; } } function mulDown(int256 a, int256 b) internal pure returns (int256) { int256 product = a * b; unchecked { return product / IONE; } } function divDown(uint256 a, uint256 b) internal pure returns (uint256) { uint256 aInflated = a * ONE; unchecked { return aInflated / b; } } function divDown(int256 a, int256 b) internal pure returns (int256) { int256 aInflated = a * IONE; unchecked { return aInflated / b; } } function rawDivUp(uint256 a, uint256 b) internal pure returns (uint256) { return (a + b - 1) / b; } // @author Uniswap function sqrt(uint256 y) internal pure returns (uint256 z) { if (y > 3) { z = y; uint256 x = y / 2 + 1; while (x < z) { z = x; x = (y / x + x) / 2; } } else if (y != 0) { z = 1; } } function square(uint256 x) internal pure returns (uint256) { return x * x; } function squareDown(uint256 x) internal pure returns (uint256) { return mulDown(x, x); } function abs(int256 x) internal pure returns (uint256) { return uint256(x > 0 ? x : -x); } function neg(int256 x) internal pure returns (int256) { return x * (-1); } function neg(uint256 x) internal pure returns (int256) { return Int(x) * (-1); } function max(uint256 x, uint256 y) internal pure returns (uint256) { return (x > y ? x : y); } function max(int256 x, int256 y) internal pure returns (int256) { return (x > y ? x : y); } function min(uint256 x, uint256 y) internal pure returns (uint256) { return (x < y ? x : y); } function min(int256 x, int256 y) internal pure returns (int256) { return (x < y ? x : y); } /*/////////////////////////////////////////////////////////////// SIGNED CASTS //////////////////////////////////////////////////////////////*/ function Int(uint256 x) internal pure returns (int256) { require(x <= uint256(type(int256).max)); return int256(x); } function Int128(int256 x) internal pure returns (int128) { require(type(int128).min <= x && x <= type(int128).max); return int128(x); } function Int128(uint256 x) internal pure returns (int128) { return Int128(Int(x)); } /*/////////////////////////////////////////////////////////////// UNSIGNED CASTS //////////////////////////////////////////////////////////////*/ function Uint(int256 x) internal pure returns (uint256) { require(x >= 0); return uint256(x); } function Uint32(uint256 x) internal pure returns (uint32) { require(x <= type(uint32).max); return uint32(x); } function Uint64(uint256 x) internal pure returns (uint64) { require(x <= type(uint64).max); return uint64(x); } function Uint112(uint256 x) internal pure returns (uint112) { require(x <= type(uint112).max); return uint112(x); } function Uint96(uint256 x) internal pure returns (uint96) { require(x <= type(uint96).max); return uint96(x); } function Uint128(uint256 x) internal pure returns (uint128) { require(x <= type(uint128).max); return uint128(x); } function Uint192(uint256 x) internal pure returns (uint192) { require(x <= type(uint192).max); return uint192(x); } function isAApproxB(uint256 a, uint256 b, uint256 eps) internal pure returns (bool) { return mulDown(b, ONE - eps) <= a && a <= mulDown(b, ONE + eps); } function isAGreaterApproxB(uint256 a, uint256 b, uint256 eps) internal pure returns (bool) { return a >= b && a <= mulDown(b, ONE + eps); } function isASmallerApproxB(uint256 a, uint256 b, uint256 eps) internal pure returns (bool) { return a <= b && a >= mulDown(b, ONE - eps); } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.24; import {Initializable} from "@openzeppelin-upgradeable/contracts/proxy/utils/Initializable.sol"; contract BoringOwnableUpgradeableData { address public owner; address public pendingOwner; } abstract contract BoringOwnableUpgradeable is BoringOwnableUpgradeableData, Initializable { event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); function __BoringOwnable_init() internal onlyInitializing { owner = msg.sender; } /// @notice Transfers ownership to `newOwner`. Either directly or claimable by the new pending owner. /// Can only be invoked by the current `owner`. /// @param newOwner Address of the new owner. /// @param direct True if `newOwner` should be set immediately. False if `newOwner` needs to use `claimOwnership`. /// @param renounce Allows the `newOwner` to be `address(0)` if `direct` and `renounce` is True. Has no effect otherwise. function transferOwnership(address newOwner, bool direct, bool renounce) public onlyOwner { if (direct) { // Checks require(newOwner != address(0) || renounce, "Ownable: zero address"); // Effects emit OwnershipTransferred(owner, newOwner); owner = newOwner; pendingOwner = address(0); } else { // Effects pendingOwner = newOwner; } } /// @notice Needs to be called by `pendingOwner` to claim ownership. function claimOwnership() public { address _pendingOwner = pendingOwner; // Checks require(msg.sender == _pendingOwner, "Ownable: caller != pending owner"); // Effects emit OwnershipTransferred(owner, _pendingOwner); owner = _pendingOwner; pendingOwner = address(0); } /// @notice Only allows the `owner` to execute the function. modifier onlyOwner() { require(msg.sender == owner, "Ownable: caller is not the owner"); _; } uint256[48] private __gap; }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.24; library Errors { // BulkSeller error BulkInsufficientSyForTrade(uint256 currentAmount, uint256 requiredAmount); error BulkInsufficientTokenForTrade(uint256 currentAmount, uint256 requiredAmount); error BulkInSufficientSyOut(uint256 actualSyOut, uint256 requiredSyOut); error BulkInSufficientTokenOut(uint256 actualTokenOut, uint256 requiredTokenOut); error BulkInsufficientSyReceived(uint256 actualBalance, uint256 requiredBalance); error BulkNotMaintainer(); error BulkNotAdmin(); error BulkSellerAlreadyExisted(address token, address SY, address bulk); error BulkSellerInvalidToken(address token, address SY); error BulkBadRateTokenToSy(uint256 actualRate, uint256 currentRate, uint256 eps); error BulkBadRateSyToToken(uint256 actualRate, uint256 currentRate, uint256 eps); // APPROX error ApproxFail(); error ApproxParamsInvalid(uint256 guessMin, uint256 guessMax, uint256 eps); error ApproxBinarySearchInputInvalid( uint256 approxGuessMin, uint256 approxGuessMax, uint256 minGuessMin, uint256 maxGuessMax ); // MARKET + MARKET MATH CORE error MarketExpired(); error MarketZeroAmountsInput(); error MarketZeroAmountsOutput(); error MarketZeroLnImpliedRate(); error MarketInsufficientPtForTrade(int256 currentAmount, int256 requiredAmount); error MarketInsufficientPtReceived(uint256 actualBalance, uint256 requiredBalance); error MarketInsufficientSyReceived(uint256 actualBalance, uint256 requiredBalance); error MarketZeroTotalPtOrTotalAsset(int256 totalPt, int256 totalAsset); error MarketExchangeRateBelowOne(int256 exchangeRate); error MarketProportionMustNotEqualOne(); error MarketRateScalarBelowZero(int256 rateScalar); error MarketScalarRootBelowZero(int256 scalarRoot); error MarketProportionTooHigh(int256 proportion, int256 maxProportion); error OracleUninitialized(); error OracleTargetTooOld(uint32 target, uint32 oldest); error OracleZeroCardinality(); error MarketFactoryExpiredPt(); error MarketFactoryInvalidPt(); error MarketFactoryMarketExists(); error MarketFactoryGaugeControllerExists(); error MarketFactoryGaugeControllerNotSet(); error MarketFactoryLnFeeRateRootTooHigh(uint80 lnFeeRateRoot, uint256 maxLnFeeRateRoot); error MarketFactoryOverriddenFeeTooHigh(uint80 overriddenFee, uint256 marketLnFeeRateRoot); error MarketFactoryReserveFeePercentTooHigh(uint8 reserveFeePercent, uint8 maxReserveFeePercent); error MarketFactoryZeroTreasury(); error MarketFactoryInitialAnchorTooLow(int256 initialAnchor, int256 minInitialAnchor); error MFNotZenlinkMarket(address addr); // ROUTER error RouterInsufficientLpOut(uint256 actualLpOut, uint256 requiredLpOut); error RouterInsufficientSyOut(uint256 actualSyOut, uint256 requiredSyOut); error RouterInsufficientPtOut(uint256 actualPtOut, uint256 requiredPtOut); error RouterInsufficientYtOut(uint256 actualYtOut, uint256 requiredYtOut); error RouterInsufficientPYOut(uint256 actualPYOut, uint256 requiredPYOut); error RouterInsufficientTokenOut(uint256 actualTokenOut, uint256 requiredTokenOut); error RouterInsufficientSyRepay(uint256 actualSyRepay, uint256 requiredSyRepay); error RouterInsufficientPtRepay(uint256 actualPtRepay, uint256 requiredPtRepay); error RouterNotAllSyUsed(uint256 netSyDesired, uint256 netSyUsed); error RouterTimeRangeZero(); error RouterCallbackNotZenlinkMarket(address caller); error RouterInvalidAction(bytes4 selector); error RouterInvalidFacet(address facet); error RouterKyberSwapDataZero(); error SimulationResults(bool success, bytes res); // YIELD CONTRACT error YCExpired(); error YCNotExpired(); error YieldContractInsufficientSy(uint256 actualSy, uint256 requiredSy); error YCNothingToRedeem(); error YCPostExpiryDataNotSet(); error YCNoFloatingSy(); // YieldFactory error YCFactoryInvalidExpiry(); error YCFactoryYieldContractExisted(); error YCFactoryZeroExpiryDivisor(); error YCFactoryZeroTreasury(); error YCFactoryInterestFeeRateTooHigh(uint256 interestFeeRate, uint256 maxInterestFeeRate); error YCFactoryRewardFeeRateTooHigh(uint256 newRewardFeeRate, uint256 maxRewardFeeRate); // SY error SYInvalidTokenIn(address token); error SYInvalidTokenOut(address token); error SYZeroDeposit(); error SYZeroRedeem(); error SYInsufficientSharesOut(uint256 actualSharesOut, uint256 requiredSharesOut); error SYInsufficientTokenOut(uint256 actualTokenOut, uint256 requiredTokenOut); // SY-specific error SYQiTokenMintFailed(uint256 errCode); error SYQiTokenRedeemFailed(uint256 errCode); error SYQiTokenRedeemRewardsFailed(uint256 rewardAccruedType0, uint256 rewardAccruedType1); error SYQiTokenBorrowRateTooHigh(uint256 borrowRate, uint256 borrowRateMax); error SYCurveInvalidPid(); error SYCurve3crvPoolNotFound(); error SYApeDepositAmountTooSmall(uint256 amountDeposited); error SYBalancerInvalidPid(); error SYInvalidRewardToken(address token); error SYStargateRedeemCapExceeded(uint256 amountLpDesired, uint256 amountLpRedeemable); error SYBalancerReentrancy(); error NotFromTrustedRemote(uint16 srcChainId, bytes path); error ApxETHNotEnoughBuffer(); // Liquidity Mining error VCInactivePool(address pool); error VCPoolAlreadyActive(address pool); error VCZeroVeZenlink(address user); error VCExceededMaxWeight(uint256 totalWeight, uint256 maxWeight); error VCEpochNotFinalized(uint256 wTime); error VCPoolAlreadyAddAndRemoved(address pool); error VEInvalidNewExpiry(uint256 newExpiry); error VEExceededMaxLockTime(); error VEInsufficientLockTime(); error VENotAllowedReduceExpiry(); error VEZeroAmountLocked(); error VEPositionNotExpired(); error VEZeroPosition(); error VEZeroSlope(uint128 bias, uint128 slope); error VEReceiveOldSupply(uint256 msgTime); error GCNotZenlinkMarket(address caller); error GCNotVotingController(address caller); error InvalidWTime(uint256 wTime); error ExpiryInThePast(uint256 expiry); error ChainNotSupported(uint256 chainId); error FDTotalAmountFundedNotMatch(uint256 actualTotalAmount, uint256 expectedTotalAmount); error FDEpochLengthMismatch(); error FDInvalidPool(address pool); error FDPoolAlreadyExists(address pool); error FDInvalidNewFinishedEpoch(uint256 oldFinishedEpoch, uint256 newFinishedEpoch); error FDInvalidStartEpoch(uint256 startEpoch); error FDInvalidWTimeFund(uint256 lastFunded, uint256 wTime); error FDFutureFunding(uint256 lastFunded, uint256 currentWTime); error BDInvalidEpoch(uint256 epoch, uint256 startTime); // Cross-Chain error MsgNotFromSendEndpoint(uint16 srcChainId, bytes path); error MsgNotFromReceiveEndpoint(address sender); error InsufficientFeeToSendMsg(uint256 currentFee, uint256 requiredFee); error ApproxDstExecutionGasNotSet(); error InvalidRetryData(); // GENERIC MSG error ArrayLengthMismatch(); error ArrayEmpty(); error ArrayOutOfBounds(); error ZeroAddress(); error FailedToSendEther(); error InvalidMerkleProof(); error OnlyLayerZeroEndpoint(); error OnlyYT(); error OnlyYCFactory(); error OnlyWhitelisted(); // Swap Aggregator error SAInsufficientTokenIn(address tokenIn, uint256 amountExpected, uint256 amountActual); error UnsupportedSelector(uint256 aggregatorType, bytes4 selector); }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.24; library WeekMath { uint128 internal constant WEEK = 7 days; function getWeekStartTimestamp(uint128 timestamp) internal pure returns (uint128) { return (timestamp / WEEK) * WEEK; } function getCurrentWeekStart() internal view returns (uint128) { return getWeekStartTimestamp(uint128(block.timestamp)); } function isValidWTime(uint256 time) internal pure returns (bool) { return time % WEEK == 0; } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.24; import {IPGaugeController} from "./IPGaugeController.sol"; interface IPGaugeControllerMainchain is IPGaugeController { function updateVotingResults(uint128 wTime, address[] calldata markets, uint256[] calldata zlkSpeeds) external; }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.24; import {VeBalance} from "../LiquidityMining/libraries/VeBalanceLib.sol"; import {Checkpoint} from "../LiquidityMining/libraries/VeHistoryLib.sol"; interface IPVotingController { event AddPool(uint64 indexed chainId, address indexed pool); event RemovePool(uint64 indexed chainId, address indexed pool); event Vote(address indexed user, address indexed pool, uint64 weight, VeBalance vote); event PoolVoteChange(address indexed pool, VeBalance vote); event SetZLKPerSec(uint256 newZLKPerSec); event BroadcastResults(uint64 indexed chainId, uint128 indexed wTime, uint128 totalZLKPerSec); function applyPoolSlopeChanges(address pool) external; /// @notice deprecated, only kept for compatibility reasons function getUserPoolHistoryLength(address user, address pool) external view returns (uint256); /// @notice deprecated, only kept for compatibility reasons function getUserPoolHistoryAt(address user, address pool, uint256 index) external view returns (Checkpoint memory); function getWeekData(uint128 wTime, address[] calldata pools) external view returns (bool isEpochFinalized, uint128 totalVotes, uint128[] memory poolVotes); function getPoolTotalVoteAt(address pool, uint128 wTime) external view returns (uint128); function finalizeEpoch() external; function getBroadcastResultFee(uint64 chainId) external view returns (uint256); function broadcastResults(uint64 chainId) external payable; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol) pragma solidity ^0.8.0; /** * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified * proxy whose upgrades are fully controlled by the current implementation. */ interface IERC1822Proxiable { /** * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation * address. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. */ function proxiableUUID() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol) pragma solidity ^0.8.2; import "../beacon/IBeacon.sol"; import "../../interfaces/IERC1967.sol"; import "../../interfaces/draft-IERC1822.sol"; import "../../utils/Address.sol"; import "../../utils/StorageSlot.sol"; /** * @dev This abstract contract provides getters and event emitting update functions for * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots. * * _Available since v4.1._ */ abstract contract ERC1967Upgrade is IERC1967 { // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1 bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143; /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev Returns the current implementation address. */ function _getImplementation() internal view returns (address) { return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; } /** * @dev Stores a new address in the EIP1967 implementation slot. */ function _setImplementation(address newImplementation) private { require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; } /** * @dev Perform implementation upgrade * * Emits an {Upgraded} event. */ function _upgradeTo(address newImplementation) internal { _setImplementation(newImplementation); emit Upgraded(newImplementation); } /** * @dev Perform implementation upgrade with additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal { _upgradeTo(newImplementation); if (data.length > 0 || forceCall) { Address.functionDelegateCall(newImplementation, data); } } /** * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal { // Upgrades from old implementations will perform a rollback test. This test requires the new // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing // this special case will break upgrade paths from old UUPS implementation to new ones. if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) { _setImplementation(newImplementation); } else { try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) { require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID"); } catch { revert("ERC1967Upgrade: new implementation is not UUPS"); } _upgradeToAndCall(newImplementation, data, forceCall); } } /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Returns the current admin. */ function _getAdmin() internal view returns (address) { return StorageSlot.getAddressSlot(_ADMIN_SLOT).value; } /** * @dev Stores a new address in the EIP1967 admin slot. */ function _setAdmin(address newAdmin) private { require(newAdmin != address(0), "ERC1967: new admin is the zero address"); StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin; } /** * @dev Changes the admin of the proxy. * * Emits an {AdminChanged} event. */ function _changeAdmin(address newAdmin) internal { emit AdminChanged(_getAdmin(), newAdmin); _setAdmin(newAdmin); } /** * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy. * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor. */ bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; /** * @dev Returns the current beacon. */ function _getBeacon() internal view returns (address) { return StorageSlot.getAddressSlot(_BEACON_SLOT).value; } /** * @dev Stores a new beacon in the EIP1967 beacon slot. */ function _setBeacon(address newBeacon) private { require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract"); require( Address.isContract(IBeacon(newBeacon).implementation()), "ERC1967: beacon implementation is not a contract" ); StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon; } /** * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that). * * Emits a {BeaconUpgraded} event. */ function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal { _setBeacon(newBeacon); emit BeaconUpgraded(newBeacon); if (data.length > 0 || forceCall) { Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data); } } }
// SPDX-License-Identifier: GPL-3.0-or-later // Forked from OpenZeppelin (v4.5.0) (utils/Checkpoints.sol) pragma solidity ^0.8.24; import {PMath} from "../../core/libraries/math/PMath.sol"; import {VeBalance} from "./VeBalanceLib.sol"; import {WeekMath} from "./WeekMath.sol"; struct Checkpoint { uint128 timestamp; VeBalance value; } library CheckpointHelper { function assignWith(Checkpoint memory a, Checkpoint memory b) internal pure { a.timestamp = b.timestamp; a.value = b.value; } } library Checkpoints { struct History { Checkpoint[] _checkpoints; } function length(History storage self) internal view returns (uint256) { return self._checkpoints.length; } function get(History storage self, uint256 index) internal view returns (Checkpoint memory) { return self._checkpoints[index]; } function push(History storage self, VeBalance memory value) internal { uint256 pos = self._checkpoints.length; if (pos > 0 && self._checkpoints[pos - 1].timestamp == WeekMath.getCurrentWeekStart()) { self._checkpoints[pos - 1].value = value; } else { self._checkpoints.push(Checkpoint({timestamp: WeekMath.getCurrentWeekStart(), value: value})); } } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.24; library MiniHelpers { function isCurrentlyExpired(uint256 expiry) internal view returns (bool) { return (expiry <= block.timestamp); } function isExpired(uint256 expiry, uint256 blockTime) internal pure returns (bool) { return (expiry <= blockTime); } function isTimeInThePast(uint256 timestamp) internal view returns (bool) { return (timestamp <= block.timestamp); // same definition as isCurrentlyExpired } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.24; interface IPVeToken { // ============= USER INFO ============= function balanceOf(address user) external view returns (uint128); function positionData(address user) external view returns (uint128 amount, uint128 expiry); // ============= META DATA ============= function totalSupplyStored() external view returns (uint128); function totalSupplyCurrent() external returns (uint128); function totalSupplyAndBalanceCurrent(address user) external returns (uint128, uint128); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage); } } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.24; interface IPMsgSendEndpoint { function calcFee(address dstAddress, uint256 dstChainId, bytes memory payload, uint256 estimatedGasAmount) external view returns (uint256 fee); function sendMessage(address dstAddress, uint256 dstChainId, bytes calldata payload, uint256 estimatedGasAmount) external payable; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a * constructor. * * Emits an {Initialized} event. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: setting the version to 255 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized != type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _initializing; } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.24; interface IPGaugeController { event MarketClaimReward(address indexed market, uint256 amount); event ReceiveVotingResults(uint128 indexed wTime, address[] markets, uint256[] zlkAmounts); event UpdateMarketReward(address indexed market, uint256 zlkPerSec, uint256 incentiveEndsAt); function fundZLK(uint256 amount) external; function withdrawZLK(uint256 amount) external; function ZLK() external returns (address); function redeemMarketReward() external; function rewardData(address pool) external view returns (uint128 zlkPerSec, uint128, uint128, uint128); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol) pragma solidity ^0.8.0; /** * @dev This is the interface that {BeaconProxy} expects of its beacon. */ interface IBeacon { /** * @dev Must return an address that can be used as a delegate call target. * * {BeaconProxy} will check that this address is a contract. */ function implementation() external view returns (address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol) pragma solidity ^0.8.0; /** * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC. * * _Available since v4.8.3._ */ interface IERC1967 { /** * @dev Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Emitted when the beacon is changed. */ event BeaconUpgraded(address indexed beacon); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol) // This file was procedurally generated from scripts/generate/templates/StorageSlot.js. pragma solidity ^0.8.0; /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC1967 implementation slot: * ```solidity * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` * * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._ * _Available since v4.9 for `string`, `bytes`._ */ library StorageSlot { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } struct StringSlot { string value; } struct BytesSlot { bytes value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` with member `value` located at `slot`. */ function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` representation of the string storage pointer `store`. */ function getStringSlot(string storage store) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } /** * @dev Returns an `BytesSlot` with member `value` located at `slot`. */ function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`. */ function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage); } } }
{ "remappings": [ "@openzeppelin/=lib/openzeppelin-contracts/", "@openzeppelin-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "forge-std/=lib/forge-std/src/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "openzeppelin/=lib/openzeppelin-contracts-upgradeable/contracts/" ], "optimizer": { "enabled": true, "runs": 800 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "viaIR": true, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_veZLK","type":"address"},{"internalType":"address","name":"_zenlinkMsgSendEndpoint","type":"address"},{"internalType":"uint256","name":"initialApproxDestinationGas","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ArrayLengthMismatch","type":"error"},{"inputs":[],"name":"ArrayOutOfBounds","type":"error"},{"inputs":[{"internalType":"uint256","name":"currentFee","type":"uint256"},{"internalType":"uint256","name":"requiredFee","type":"uint256"}],"name":"InsufficientFeeToSendMsg","type":"error"},{"inputs":[{"internalType":"uint256","name":"wTime","type":"uint256"}],"name":"InvalidWTime","type":"error"},{"inputs":[{"internalType":"uint256","name":"wTime","type":"uint256"}],"name":"VCEpochNotFinalized","type":"error"},{"inputs":[{"internalType":"uint256","name":"totalWeight","type":"uint256"},{"internalType":"uint256","name":"maxWeight","type":"uint256"}],"name":"VCExceededMaxWeight","type":"error"},{"inputs":[{"internalType":"address","name":"pool","type":"address"}],"name":"VCInactivePool","type":"error"},{"inputs":[{"internalType":"address","name":"pool","type":"address"}],"name":"VCPoolAlreadyActive","type":"error"},{"inputs":[{"internalType":"address","name":"pool","type":"address"}],"name":"VCPoolAlreadyAddAndRemoved","type":"error"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"VCZeroVeZenlink","type":"error"},{"inputs":[{"internalType":"uint128","name":"bias","type":"uint128"},{"internalType":"uint128","name":"slope","type":"uint128"}],"name":"VEZeroSlope","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"chainId","type":"uint64"},{"indexed":true,"internalType":"address","name":"pool","type":"address"}],"name":"AddPool","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"chainId","type":"uint64"},{"indexed":true,"internalType":"uint128","name":"wTime","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"totalZLKPerSec","type":"uint128"}],"name":"BroadcastResults","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","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":"pool","type":"address"},{"components":[{"internalType":"uint128","name":"bias","type":"uint128"},{"internalType":"uint128","name":"slope","type":"uint128"}],"indexed":false,"internalType":"struct VeBalance","name":"vote","type":"tuple"}],"name":"PoolVoteChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"chainId","type":"uint64"},{"indexed":true,"internalType":"address","name":"pool","type":"address"}],"name":"RemovePool","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newZLKPerSec","type":"uint256"}],"name":"SetZLKPerSec","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"pool","type":"address"},{"indexed":false,"internalType":"uint64","name":"weight","type":"uint64"},{"components":[{"internalType":"uint128","name":"bias","type":"uint128"},{"internalType":"uint128","name":"slope","type":"uint128"}],"indexed":false,"internalType":"struct VeBalance","name":"vote","type":"tuple"}],"name":"Vote","type":"event"},{"inputs":[],"name":"GOVERNANCE_ZLK_VOTE","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_LOCK_TIME","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WEEK","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"uint256","name":"_chainId","type":"uint256"}],"name":"addDestinationContract","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"address","name":"pool","type":"address"}],"name":"addPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"}],"name":"applyPoolSlopeChanges","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"approxDstExecutionGas","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"}],"name":"broadcastResults","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"claimOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"deployedWTime","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"finalizeEpoch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"uint128","name":"wTime","type":"uint128"},{"internalType":"uint128","name":"forcedzlkPerSec","type":"uint128"}],"name":"forceBroadcastResults","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"}],"name":"getActiveChainPools","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllActivePools","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllDestinationContracts","outputs":[{"internalType":"uint256[]","name":"chainIds","type":"uint256[]"},{"internalType":"address[]","name":"addrs","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"end","type":"uint256"}],"name":"getAllRemovedPools","outputs":[{"internalType":"uint256","name":"lengthOfRemovedPools","type":"uint256"},{"internalType":"address[]","name":"arr","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"}],"name":"getBroadcastResultFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"uint128[]","name":"wTimes","type":"uint128[]"}],"name":"getPoolData","outputs":[{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"uint128","name":"lastSlopeChangeAppliedAt","type":"uint128"},{"components":[{"internalType":"uint128","name":"bias","type":"uint128"},{"internalType":"uint128","name":"slope","type":"uint128"}],"internalType":"struct VeBalance","name":"totalVote","type":"tuple"},{"internalType":"uint128[]","name":"slopeChanges","type":"uint128[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"uint128","name":"wTime","type":"uint128"}],"name":"getPoolTotalVoteAt","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address[]","name":"pools","type":"address[]"}],"name":"getUserData","outputs":[{"internalType":"uint64","name":"totalVotedWeight","type":"uint64"},{"components":[{"internalType":"uint64","name":"weight","type":"uint64"},{"components":[{"internalType":"uint128","name":"bias","type":"uint128"},{"internalType":"uint128","name":"slope","type":"uint128"}],"internalType":"struct VeBalance","name":"vote","type":"tuple"}],"internalType":"struct VotingControllerStorageUpg.UserPoolData[]","name":"voteForPools","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"pool","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getUserPoolHistoryAt","outputs":[{"components":[{"internalType":"uint128","name":"timestamp","type":"uint128"},{"components":[{"internalType":"uint128","name":"bias","type":"uint128"},{"internalType":"uint128","name":"slope","type":"uint128"}],"internalType":"struct VeBalance","name":"value","type":"tuple"}],"internalType":"struct Checkpoint","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"pool","type":"address"}],"name":"getUserPoolHistoryLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"pool","type":"address"}],"name":"getUserPoolVote","outputs":[{"components":[{"internalType":"uint64","name":"weight","type":"uint64"},{"components":[{"internalType":"uint128","name":"bias","type":"uint128"},{"internalType":"uint128","name":"slope","type":"uint128"}],"internalType":"struct VeBalance","name":"vote","type":"tuple"}],"internalType":"struct VotingControllerStorageUpg.UserPoolData","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint128","name":"wTime","type":"uint128"},{"internalType":"address[]","name":"pools","type":"address[]"}],"name":"getWeekData","outputs":[{"internalType":"bool","name":"isEpochFinalized","type":"bool"},{"internalType":"uint128","name":"totalVotes","type":"uint128"},{"internalType":"uint128[]","name":"poolVotes","type":"uint128[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"nonpayable","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":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"}],"name":"removePool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"gas","type":"uint256"}],"name":"setApproxDstExecutionGas","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"newZLKPerSec","type":"uint128"}],"name":"setZLKPerSec","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"},{"internalType":"bool","name":"direct","type":"bool"},{"internalType":"bool","name":"renounce","type":"bool"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"veZLK","outputs":[{"internalType":"contract IPVeToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"pools","type":"address[]"},{"internalType":"uint64[]","name":"weights","type":"uint64[]"}],"name":"vote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"zenlinkMsgSendEndpoint","outputs":[{"internalType":"contract IPMsgSendEndpoint","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"zlkPerSec","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60e034620000ce57601f62003a7138819003918201601f19168301916001600160401b03831184841017620000d357808492606094604052833981010312620000ce576200004d81620000e9565b60406200005d60208401620000e9565b9201516001600160a01b039283166080526032551660a0523060c0526040516139729081620000ff82396080518181816106c3015281816128350152612fde015260a051818181611521015281816115fe0152612209015260c05181818161183901528181611972015261200d0152f35b600080fd5b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b0382168203620000ce5756fe6080604052600436101561001257600080fd5b60003560e01c8063078dfbe71461237b57806316ac7e30146122ef5780631c9bdb49146122a057806321049028146122585780632477bfbe1461222d57806336539c54146121e95780633659cfe614611fe7578063366c771d14611ea557806338b8765c14611e895780633b7d094614611d7a5780633e39b65014611cc35780633f81a66414611ca25780634e71e0c814611bf55780634f1ef286146118f457806352d1902d1461181e578063632c096d1461174d578063646fb67c14611699578063698766ee14610e125780636aea282614610dc05780638129fc1c14610b6857806382ae9ef714610a635780638d66c284146109665780638da5cb5b1461093f5780638f45ff78146107a857806395de8fa11461072c5780639efc75751461070e578063b292bf95146106e7578063b77f1ba3146106a3578063b837b3db1461067d578063c291230d146105f8578063cc88370e146104d9578063d45f5e21146104aa578063d5cd7d2014610417578063d68ffecb14610282578063e30c39781461025b578063f144cf1714610200578063f4359ce5146101e25763fa78668f146101be57600080fd5b346101dd5760003660031901126101dd5760206040516303bfc4008152f35b600080fd5b346101dd5760003660031901126101dd57602060405162093a808152f35b346101dd5760403660031901126101dd57602061021b61248e565b6001600160801b03908161022d61250e565b1660005260a183526001600160a01b0360016040600020019116600052825260406000205416604051908152f35b346101dd5760003660031901126101dd5760206001600160a01b0360015416604051908152f35b346101dd5760403660031901126101dd5761029b6124ba565b6102a36124a4565b6001600160a01b03906102bb826000541633146126aa565b16906102d482600052609c602052604060002054151590565b6103fe5781600052609e6020526040600020546103e55767ffffffffffffffff1680600052609f60205261030c82604060002061382c565b156103cf5761031a826137da565b156103cf578160005260a060205260406000208167ffffffffffffffff198254161790556103a861035862093a806001600160801b03421604613284565b8360005260a060205260406000209077ffffffffffffffffffffffffffffffff00000000000000001977ffffffffffffffffffffffffffffffff000000000000000083549260401b169116179055565b7f336f0b3cc523e98d21e261389542b62abaffc094a21a82f1eec2779d7c8323cb600080a3005b634e487b7160e01b600052600160045260246000fd5b604051634753d28360e01b815260048101839052602490fd5b604051639e7f1f4160e01b815260048101839052602490fd5b346101dd5760003660031901126101dd5760405180609b5491828152602080910192609b6000527fbba9db4cdbea0a37c207bbb83e20f828cd4441c49891101dc94fd20dc8efc349916000905b8282106104935761048f8561047b8189038261266c565b6040519182916020835260208301906124d1565b0390f35b835486529485019460019384019390910190610464565b346101dd5760203660031901126101dd576104d16001600160a01b036000541633146126aa565b600435603255005b346101dd5760403660031901126101dd57609d80546004356024803590838210156105e6576105088383612d1a565b92600193600181018091116105d0576105209061270d565b95815b8481111561054957878761048f60405192839283526040602084015260408301906124d1565b868110156105bb57816000526001600160a01b03817fd26e832454299e9fabb89e0e5fffdc046d4e14431bc1bf607ffb2e8a1ddecf7b01541661059561058f8584612d1a565b8a6129e6565b5260001981146105a6578501610523565b83634e487b7160e01b60005260116004526000fd5b83634e487b7160e01b60005260326004526000fd5b634e487b7160e01b600052601160045260246000fd5b604051637f52b2bf60e01b8152600490fd5b60203660031901126101dd5761060c6124ba565b6001600160801b039061062562093a8083421604613284565b918216918260005260a160205260ff6040600020541615610664576106519250609a5460801c91612e43565b4761065857005b6106624733612d57565b005b604051631d83110f60e21b815260048101849052602490fd5b346101dd5760003660031901126101dd5760206040516a084595161401484a0000008152f35b346101dd5760003660031901126101dd5760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b346101dd5760003660031901126101dd5760206001600160801b03609a5416604051908152f35b346101dd5760003660031901126101dd576020603254604051908152f35b346101dd5760203660031901126101dd577f415aff8bca0fbb5b26c8976127b380373d8831645591229178dce3dbc2480ddf6020610768612524565b61077e6001600160a01b036000541633146126aa565b6001600160801b03609a54816001600160801b03198460801b16911617609a5560405191168152a1005b346101dd576107b63661256b565b90916001600160a01b03809116600052602060a2815260406000209367ffffffffffffffff80865416946107e9816126f5565b946107f7604051968761266c565b818652610803826126f5565b601f190160005b81811061091a5750506000916001809901925b8181106108b25750505050505060405193849360408501908552604083860152835180915260609280606087019501936000905b83821061085e5787870388f35b9185975082876108a08799849895979951805167ffffffffffffffff16825260209081015180516001600160801b039081168385015291015116604090910152565b01970192018796959391949294610851565b9889836108cc6108c7849b9c9a9d868b6129c2565b612cf1565b16600052848b5260406000206108f583604051926108e984612620565b8981541684520161299d565b8c820152610903828c6129e6565b5261090e818b6129e6565b5001989597969861081d565b95809997989661092b969496612caf565b82828c01015201989597969894929461080a565b346101dd5760003660031901126101dd5760206001600160a01b0360005416604051908152f35b346101dd5760403660031901126101dd5761097f612524565b60243567ffffffffffffffff81116101dd5761099f90369060040161253a565b6001600160801b0380931662093a808106610a4b5760009291925260209060a16020526040600020908154936109d48161270d565b9360019384019160005b818110610a1357888861048f89604051938360ff8695161515855260081c1660208401526060604084015260608301906125af565b806001600160a01b03610a2b6108c78994868a6129c2565b166000528484528960406000205416610a44828a6129e6565b52016109de565b60249060405190637bf16ce960e11b82526004820152fd5b346101dd5760003660031901126101dd57609b805460005b818110610b07576001600160801b03610a9a62093a8082421604613284565b5b8180609a5416911690811180610aee575b1561066257600081815260a160205260409020805460ff1916600117905562093a7f190181811115610a9b57634e487b7160e01b600052601160045260246000fd5b508060005260a160205260ff6040600020541615610aac565b8254811015610b525760019083600052610b4c6001600160a01b03827fbba9db4cdbea0a37c207bbb83e20f828cd4441c49891101dc94fd20dc8efc349015416612a15565b01610a7b565b634e487b7160e01b600052603260045260246000fd5b346101dd5760003660031901126101dd576001805460ff8160a81c161590818092610db1575b8015610d98575b15610d2d5781740100000000000000000000000000000000000000007fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff8316178455610ceb575b5081549060ff8260a81c1615610c8057336001600160a01b031960005416176000556001600160801b03610c1662093a8082421604613284565b166001600160801b0319609a541617609a55610c2e57005b7f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498917fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff602092168155604051908152a1005b60405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608490fd5b7fffffffffffffffffffff0000ffffffffffffffffffffffffffffffffffffffff16750101000000000000000000000000000000000000000017825582610bdc565b60405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608490fd5b50303b158015610b9557508260ff8260a01c1614610b95565b508260ff8260a01c1610610b8e565b346101dd5760403660031901126101dd57610dd961248e565b610de16124a4565b906001600160a01b0380911660005260a3602052604060002091166000526020526020604060002054604051908152f35b346101dd5760403660031901126101dd5760043567ffffffffffffffff81116101dd57610e4390369060040161253a565b60243567ffffffffffffffff81116101dd57610e6390369060040161253a565b9290838303611687576001600160a01b03600054163314938415806115e2575b6115ca5760405194610e9486612620565b6000808752602087015215611506576001600160801b036303bfc400814216018181116105d05762093a8082610ecb921604613284565b1660208601526a084595161401484a00000085525b60005b848110610f33573360005260a260205267ffffffffffffffff60406000205416670de0b6b3a764000090818111610f1657005b6044916040519163903482f560e01b835260048301526024820152fd5b610f606001600160a01b03610f4c6108c78489896129c2565b16600052609c602052604060002054151590565b6114eb575b610f736108c78287876129c2565b90610f87610f828285876129c2565b612d05565b604051610f9381612620565b6000815260006020820152903360005260a26020526040600020906001600160a01b03851660005260a060205260406000209160018101602052610fdd600160406000200161299d565b6001600160801b03815116611342575b5067ffffffffffffffff82166110d1575b50507fa512c82e73ec974de3c794a3ea6bbdfbad18531c1394ace9972f3f0166b6786360406001600160a01b036001968783519501546001600160801b038116865260801c60208601521692a26001600160a01b036110616108c7848a8a6129c2565b6110a3611072610f8286898b6129c2565b9367ffffffffffffffff604051951685526020850190602090816001600160801b0391828151168552015116910152565b16907fc71e393f1527f71ce01b78ea87c9bd4fca84f1482359ce7ac9b73f358c61b1e160603392a301610ee3565b9092506110f46001600160a01b038616600052609c602052604060002054151590565b15611321576040519261110684612620565b6000845260006020850152670de0b6b3a76400006303bfc40061113e8d6001600160801b0367ffffffffffffffff8616915116612e30565b04046001600160801b0381116101dd5761116f8c6001600160801b036020818095169283828b0152015116906132a1565b1684526112bf846001600160801b03602061118c6001880161299d565b61120a83806111d28186604051966111a388612620565b60008852600082890152826111c08c8280855116915116906129fa565b16885201511682878a015116906129fa565b169283858201525116918419928360018c0154161760018b015560018a01906001600160801b0382549181199060801b169116179055565b8282850151168361121a866133b4565b16600052600289018352604060002090828561123a8454938285166129fa565b169116179055600160405161124e81612620565b67ffffffffffffffff881681528381019586526001600160a01b038d16600052818901845267ffffffffffffffff604060002091511667ffffffffffffffff198254161781550193519083825116908554161784550151166001600160801b0382549181199060801b169116179055565b81549067ffffffffffffffff80821681841601116105d05767ffffffffffffffff908116818316011667ffffffffffffffff19919091161790557fa512c82e73ec974de3c794a3ea6bbdfbad18531c1394ace9972f3f0166b678636040610ffe565b60405163913accad60e01b81526001600160a01b0386166004820152602490fd5b6113626001600160a01b038816600052609c602052604060002054151590565b806114ba575b6113ed575b506001600160a01b0386166000526001810160205267ffffffffffffffff6040600020541681549067ffffffffffffffff8181841603116105d05767ffffffffffffffff9081831603169067ffffffffffffffff19161781556001600160a01b03861660005260018101602052600060016040822082815501558b610fed565b60018401906001600160801b03611487816114078561299d565b61147f6040519161141783612620565b600083528380602080860193600085528261143a8c82808551169151169061326b565b168752015116938161145460208b0196828851169061326b565b1680935251169784199889825416178155906001600160801b0382549181199060801b169116179055565b5116926133b4565b16600052600285016020526040600020916001600160801b036114ae84549382851661326b565b1691161790558b61136d565b506001600160801b036020820151161515801561136857506001600160801b036114e3826133b4565b164210611368565b6115016114fc6108c78388886129c2565b612a15565b610f65565b604080516332dad3cf60e21b815233600482015290816024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156115be57600090600092611576575b506001600160801b038092166020880152168552610ee0565b9150506040813d6040116115b6575b816115926040938361266c565b810103126101dd576115af60206115a883612cdd565b9201612cdd565b908761155d565b3d9150611585565b6040513d6000823e3d90fd5b60405163eb1acbe360e01b8152336004820152602490fd5b506040516370a0823160e01b81523360048201526020816024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa80156115be57600090611647575b6001600160801b0391501615610e83565b506020813d60201161167f575b816116616020938361266c565b810103126101dd5761167a6001600160801b0391612cdd565b611636565b3d9150611654565b60405163512509d360e11b8152600490fd5b346101dd5760403660031901126101dd576116b261248e565b6116ba6124a4565b906116c3612caf565b506001600160a01b0380911660005260a2602052600160406000200191166000526020526060604060002061171460016040519261170084612620565b67ffffffffffffffff81541684520161299d565b602082810191825260408051935167ffffffffffffffff168452915180516001600160801b03908116858401529101511690820152f35bf35b346101dd5760603660031901126101dd5761176661248e565b61176e6124a4565b6044359161177a612caf565b506001600160a01b0380911660005260a3602052604060002091166000526020526040600020906117a9612caf565b508154811015610b525760609160005260206000209060011b0161174b604051916117d383612620565b6117ed60016001600160801b03928381541686520161299d565b90602084019182526040519351168352516020830190602090816001600160801b0391828151168552015116910152565b346101dd5760003660031901126101dd576001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036118895760206040517f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8152f35b60405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608490fd5b60403660031901126101dd5761190861248e565b6024359067ffffffffffffffff82116101dd57366023830112156101dd5781600401356119348161268e565b92611942604051948561266c565b8184526020918285019136602483830101116101dd578160009260248693018537860101526001600160a01b03807f0000000000000000000000000000000000000000000000000000000000000000169061199f823014156128b9565b6119ce7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc92828454161461292b565b6119dd816000541633146126aa565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615611a1557505050506106629150613306565b84939416906040516352d1902d60e01b81528581600481865afa60009181611bc6575b50611a995760405162461bcd60e51b815260048101879052602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608490fd5b03611b5b57611aa783613306565b7fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b600080a2835115801590611b53575b611add57005b60008091610662957f416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c60405196611b1388612650565b602788528701527f206661696c65640000000000000000000000000000000000000000000000000060408701525190845af4611b4d612d27565b9161389f565b506001611ad7565b60405162461bcd60e51b815260048101859052602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f7860448201527f6961626c655555494400000000000000000000000000000000000000000000006064820152608490fd5b9091508681813d8311611bee575b611bde818361266c565b810103126101dd57519088611a38565b503d611bd4565b346101dd5760003660031901126101dd576001546001600160a01b0390818116803303611c5e57806000549384167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a36001600160a01b03199283161760005516600155005b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c657220213d2070656e64696e67206f776e65726044820152fd5b346101dd5760003660031901126101dd576020609a5460801c604051908152f35b346101dd5760003660031901126101dd57603354611ce08161270d565b90611cea8161270d565b9060005b818110611d1f57611d118461048f856040519384936040855260408501906125ec565b9083820360208501526124d1565b806001917f82a75bdeeae8604d839476ae9efd8b0e15aa447e21bfd7f41283bb54e22c9a8201548060005260356020526001600160a01b0360406000205416611d6883876129e6565b52611d7382876129e6565b5201611cee565b346101dd5760203660031901126101dd57611d9361248e565b6001600160a01b03611daa816000541633146126aa565b811690611dc482600052609c602052604060002054151590565b15611e70578160005260a060205267ffffffffffffffff611dec816040600020541692612a15565b8260005260a060205260406000205416600052609f602052611e128260406000206135dd565b156103cf57611e20826134dc565b156103cf57611e2e8261376a565b156103cf578160005260a0602052600060016040822082815501557ff2e3b584c4d1ed5ead9a4b7de2a8225fd42d13f09e417cd294d03f1dd07fc914600080a3005b60405163913accad60e01b815260048101839052602490fd5b346101dd5760203660031901126101dd576106626114fc61248e565b346101dd57611eb33661256b565b60405191926001600160a01b0390611eca84612620565b6000845260006020809501521660005260a06020526040600020918254926001600160801b0394600191611f006001820161299d565b93611f0a8661270d565b95600260009301925b818110611f7157898961048f8a611f608b604051958567ffffffffffffffff889716875260401c1660208601526040850190602090816001600160801b0391828151168552015116910152565b60a0608084015260a08301906125af565b62093a808a611f89611f8484868a6129c2565b6129d2565b1606611fc057808a611fa0611f848994868a6129c2565b166000528484528a60406000205416611fb9828b6129e6565b5201611f13565b611fd1611f848b92602494886129c2565b604051637bf16ce960e11b815291166004820152fd5b346101dd576020806003193601126101dd5761200161248e565b6001600160a01b0391827f0000000000000000000000000000000000000000000000000000000000000000169261203a843014156128b9565b6120697f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc94828654161461292b565b612078816000541633146126aa565b604051938285019185831067ffffffffffffffff8411176121d357826040526000865260ff7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd914354166000146120d557505050506106629150613306565b84939416906040516352d1902d60e01b81528581600481865afa600091816121a4575b506121595760405162461bcd60e51b815260048101879052602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608490fd5b03611b5b5761216783613306565b7fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b600080a283511580159061219c57611add57005b506000611ad7565b9091508681813d83116121cc575b6121bc818361266c565b810103126101dd575190886120f8565b503d6121b2565b634e487b7160e01b600052604160045260246000fd5b346101dd5760003660031901126101dd5760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b346101dd5760203660031901126101dd57602061225061224b6124ba565b612776565b604051908152f35b60403660031901126101dd5761066261226f61248e565b602435906001600160a01b039061228b826000541633146126aa565b826000526035602052166040600020556136cd565b60603660031901126101dd576122b46124ba565b6122bc61250e565b604435906001600160801b03821682036101dd57610651926122ea6001600160a01b036000541633146126aa565b612e43565b346101dd576020806003193601126101dd5767ffffffffffffffff6123126124ba565b16600052609f8152604060002090604051808383829554938481520190600052836000209260005b85828210612365575050506123519250038361266c565b61048f6040519282849384528301906124d1565b855484526001958601958895509301920161233a565b346101dd5760603660031901126101dd5761239461248e565b60243580151581036101dd576044359081151582036101dd576001600160a01b039283916123c7836000541633146126aa565b1561247457169081159081159161246c575b501561242757806000549283167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a36001600160a01b03198092161760005560015416600155600080f35b60405162461bcd60e51b815260206004820152601560248201527f4f776e61626c653a207a65726f206164647265737300000000000000000000006044820152606490fd5b9050836123d9565b915050166001600160a01b03196001541617600155600080f35b600435906001600160a01b03821682036101dd57565b602435906001600160a01b03821682036101dd57565b6004359067ffffffffffffffff821682036101dd57565b90815180825260208080930193019160005b8281106124f1575050505090565b83516001600160a01b0316855293810193928101926001016124e3565b602435906001600160801b03821682036101dd57565b600435906001600160801b03821682036101dd57565b9181601f840112156101dd5782359167ffffffffffffffff83116101dd576020808501948460051b0101116101dd57565b9060406003198301126101dd576004356001600160a01b03811681036101dd57916024359067ffffffffffffffff82116101dd576125ab9160040161253a565b9091565b90815180825260208080930193019160005b8281106125cf575050505090565b83516001600160801b0316855293810193928101926001016125c1565b90815180825260208080930193019160005b82811061260c575050505090565b8351855293810193928101926001016125fe565b6040810190811067ffffffffffffffff8211176121d357604052565b67ffffffffffffffff81116121d357604052565b6060810190811067ffffffffffffffff8211176121d357604052565b90601f8019910116810190811067ffffffffffffffff8211176121d357604052565b67ffffffffffffffff81116121d357601f01601f191660200190565b156126b157565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b67ffffffffffffffff81116121d35760051b60200190565b90612717826126f5565b612724604051918261266c565b8281528092612735601f19916126f5565b0190602036910137565b91612765906001600160801b0361277395931684526060602085015260608401906124d1565b9160408184039101526125ec565b90565b67ffffffffffffffff164681146128b357600090808252602091609f8352604081205480156128ac576127d96127f8826127b96127b3889561270d565b9161270d565b906127ec60405194859288888501526060604085015260808401906124d1565b601f1993848483030160608501526125ec565b0390810183528261266c565b6001600160a01b038061280a86613464565b6032546040516384fe172160e01b815297889586948594612831949391166004860161323b565b03917f0000000000000000000000000000000000000000000000000000000000000000165afa92831561289f57819361286b575b50505090565b9091809350813d8311612898575b612883818361266c565b81010312612895575051388080612865565b80fd5b503d612879565b50604051903d90823e3d90fd5b5091505090565b50600090565b156128c057565b60405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c00000000000000000000000000000000000000006064820152608490fd5b1561293257565b60405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f787900000000000000000000000000000000000000006064820152608490fd5b906040516129aa81612620565b91546001600160801b038116835260801c6020830152565b9190811015610b525760051b0190565b356001600160801b03811681036101dd5790565b8051821015610b525760209160051b010190565b9190916001600160801b03808094169116019182116105d057565b6001600160a01b031690612a3682600052609c602052604060002054151590565b15611e705760009082825260a092602060a081526001600160801b03906040918083872054841c169162093a809782612a728a82421604613284565b1680851015612ca3579088809a8888999a9b5260a08552612a99600180998a94200161299d565b975b612b71575b5050508689525060a08152968490208351978401516fffffffffffffffffffffffffffffffff1990831660801b16919097166001600160801b0316176001870155939492937fa512c82e73ec974de3c794a3ea6bbdfbad18531c1394ace9972f3f0166b6786393612b4c9177ffffffffffffffffffffffffffffffff00000000000000001977ffffffffffffffffffffffffffffffff000000000000000083549260401b169116179055565b612b6e82518092602090816001600160801b0391828151168552015116910152565ba2565b9091929585819c9b9a99989c169087821015612c965750810195858711612c8257828b9c878a8c9d9e8b9c9d8a848e8385528c8352858520600201978282169889875284528280888820541691885195612bca87612620565b888752828481838a01938c85528501511690612be59161326b565b169052511691612bf4916132a1565b612bfd9161326b565b168152809e612c0b916132bf565b9480835260a190818d5284842080546008898983831c1690612c2c916129fa565b901b70ffffffffffffffffffffffffffffffff00169070ffffffffffffffffffffffffffffffff00191617905583528b5285838320019082528a522091166001600160801b031982541617905591909392612a9b565b634e487b7160e01b8b52601160045260248bfd5b96509a969798999a612aa0565b50505050505050915050565b60405190612cbc82612620565b60008252604051602083612ccf83612620565b600083526000828401520152565b51906001600160801b03821682036101dd57565b356001600160a01b03811681036101dd5790565b3567ffffffffffffffff811681036101dd5790565b919082039182116105d057565b3d15612d52573d90612d388261268e565b91612d46604051938461266c565b82523d6000602084013e565b606090565b814710612deb5760008080936001600160a01b038294165af1612d78612d27565b5015612d8057565b60405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608490fd5b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606490fd5b818102929181159184041417156105d057565b929190926001600160801b03938481169260009584875260209260a1845260409082828a205460081c1695861590816131ee5767ffffffffffffffff1696878b52609f8752838b2090815480156131df57908c9392918651928a84838152019086528a8620865b8c8482106131bc5750505083612ec191038461266c565b612eca8161270d565b938c89898d89935b86851061311a575050505050505050468914600014612f82576001600160a01b03612efc8a613464565b1690813b15612f7e5783612f269587519687958694859363072cbf8760e41b85526004850161273f565b03925af18015612f74577fc78a580f215ba474e75ecbd7636c375e8d2cd25edb0f2467f99b2d0752e104ba9697989950612f65575b505b5191168152a3565b612f6e9061263c565b38612f5b565b82513d8b823e3d90fd5b8380fd5b9290612fa89250612f9a9085519485938a850161273f565b03601f19810183528261266c565b858952603485528189205415613106576001600160a01b039081612fcb88613464565b60325485516384fe172160e01b815290947f000000000000000000000000000000000000000000000000000000000000000016929091169088818061301688888f886004860161323b565b0381865afa9081156130fc578d916130cb575b508047106130ac579082918d94933b156130a8578a9161305e88519788968795869463b2267a7b60e01b86526004860161323b565b03925af18015612f74577fc78a580f215ba474e75ecbd7636c375e8d2cd25edb0f2467f99b2d0752e104ba9697989950613099575b50612f5d565b6130a29061263c565b38613093565b8480fd5b855163704c5be560e11b81524760048201526024810191909152604490fd5b90508881813d83116130f5575b6130e2818361266c565b810103126130f1575138613029565b8c80fd5b503d6130d8565b86513d8f823e3d90fd5b634e487b7160e01b89526001600452602489fd5b908a9161315595969798999a9b5260a18152600183832001906001600160a01b03613145888d6129e6565b51168352522054168a8c16612e30565b62093a80908181029181830414901517156131a757826131925790846001920461317f82896129e6565b5201908e959493929189898f8e90612ed2565b50634e487b7160e01b8f52601260045260248ffd5b50634e487b7160e01b8f52601160045260248ffd5b82949596979850600192938392945481520193019101908f969594939291612eaa565b50505050505050505050509050565b5050505050505050509050565b919082519283825260005b848110613227575050826000602080949584010152601f8019910116010190565b602081830181015184830182015201613206565b9493926060926001600160a01b036132669316875260208701526080604087015260808601906131fb565b930152565b6001600160801b0391821690821603919082116105d057565b9062093a806001600160801b03809316029182169182036105d057565b9190916001600160801b03808094169116029182169182036105d057565b602081016001600160801b03928392836132dc83828651166132a1565b91511693849116116132fd57612773936132f79251166132a1565b9061326b565b50505050600090565b803b15613349576001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc91166001600160a01b0319825416179055565b60405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e7472616374000000000000000000000000000000000000006064820152608490fd5b60208101906001600160801b03908183511680156133f457505191518116911681156133de570490565b634e487b7160e01b600052601260045260246000fd5b826044925116906040519163fbd384a560e01b835260048301526024820152fd5b609b54811015610b5257609b6000527fbba9db4cdbea0a37c207bbb83e20f828cd4441c49891101dc94fd20dc8efc3490190600090565b8054821015610b525760005260206000200190600090565b600052603560205260406000205480158015906134c9575b156134845790565b60405162461bcd60e51b815260206004820152601e60248201527f456e756d657261626c654d61703a206e6f6e6578697374656e74206b657900006044820152606490fd5b506034602052604060002054151561347c565b6000818152609c602052604081205490919080156135d857600019908082018181116135c457609b54908382019182116135b057808203613565575b505050609b5480156135515781019061353082613415565b909182549160031b1b19169055609b558152609c6020526040812055600190565b634e487b7160e01b84526031600452602484fd5b61359a61357461358393613415565b90549060031b1c928392613415565b819391549060031b91821b91600019901b19161790565b90558452609c6020526040842055388080613518565b634e487b7160e01b86526011600452602486fd5b634e487b7160e01b85526011600452602485fd5b505090565b906001820190600092818452826020526040842054908115156000146136c657600019918083018181116136b25782549084820191821161369e57808203613669575b5050508054801561365557820191613638838361344c565b909182549160031b1b191690555582526020526040812055600190565b634e487b7160e01b86526031600452602486fd5b613689613679613583938661344c565b90549060031b1c9283928661344c565b90558652846020526040862055388080613620565b634e487b7160e01b88526011600452602488fd5b634e487b7160e01b87526011600452602487fd5b5050505090565b600081815260346020526040812054613765576033546801000000000000000081101561375157600181018060335581101561373d5790826040927f82a75bdeeae8604d839476ae9efd8b0e15aa447e21bfd7f41283bb54e22c9a82015560335492815260346020522055600190565b634e487b7160e01b82526032600452602482fd5b634e487b7160e01b82526041600452602482fd5b905090565b6000818152609e602052604081205461376557609d5468010000000000000000811015613751576001810180609d5581101561373d5790826040927fd26e832454299e9fabb89e0e5fffdc046d4e14431bc1bf607ffb2e8a1ddecf7b0155609d54928152609e6020522055600190565b6000818152609c602052604081205461376557609b546801000000000000000081101561375157908261381861358384600160409601609b55613415565b9055609b54928152609c6020522055600190565b9190600183016000908282528060205260408220541560001461389957845494680100000000000000008610156138855783613875613583886001604098999a0185558461344c565b9055549382526020522055600190565b634e487b7160e01b83526041600452602483fd5b50925050565b9192901561390157508151156138b3575090565b3b156138bc5790565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b8251909150156139145750805190602001fd5b60405162461bcd60e51b8152602060048201529081906139389060248301906131fb565b0390fdfea2646970667358221220fd5e6e11bcd8f89db8c8c14cdf63c1552fb6e81b0b28ab09ca9b961752cabd7f64736f6c634300081800330000000000000000000000007310468a0607003ab7dbc23af44c88565e945a3e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x6080604052600436101561001257600080fd5b60003560e01c8063078dfbe71461237b57806316ac7e30146122ef5780631c9bdb49146122a057806321049028146122585780632477bfbe1461222d57806336539c54146121e95780633659cfe614611fe7578063366c771d14611ea557806338b8765c14611e895780633b7d094614611d7a5780633e39b65014611cc35780633f81a66414611ca25780634e71e0c814611bf55780634f1ef286146118f457806352d1902d1461181e578063632c096d1461174d578063646fb67c14611699578063698766ee14610e125780636aea282614610dc05780638129fc1c14610b6857806382ae9ef714610a635780638d66c284146109665780638da5cb5b1461093f5780638f45ff78146107a857806395de8fa11461072c5780639efc75751461070e578063b292bf95146106e7578063b77f1ba3146106a3578063b837b3db1461067d578063c291230d146105f8578063cc88370e146104d9578063d45f5e21146104aa578063d5cd7d2014610417578063d68ffecb14610282578063e30c39781461025b578063f144cf1714610200578063f4359ce5146101e25763fa78668f146101be57600080fd5b346101dd5760003660031901126101dd5760206040516303bfc4008152f35b600080fd5b346101dd5760003660031901126101dd57602060405162093a808152f35b346101dd5760403660031901126101dd57602061021b61248e565b6001600160801b03908161022d61250e565b1660005260a183526001600160a01b0360016040600020019116600052825260406000205416604051908152f35b346101dd5760003660031901126101dd5760206001600160a01b0360015416604051908152f35b346101dd5760403660031901126101dd5761029b6124ba565b6102a36124a4565b6001600160a01b03906102bb826000541633146126aa565b16906102d482600052609c602052604060002054151590565b6103fe5781600052609e6020526040600020546103e55767ffffffffffffffff1680600052609f60205261030c82604060002061382c565b156103cf5761031a826137da565b156103cf578160005260a060205260406000208167ffffffffffffffff198254161790556103a861035862093a806001600160801b03421604613284565b8360005260a060205260406000209077ffffffffffffffffffffffffffffffff00000000000000001977ffffffffffffffffffffffffffffffff000000000000000083549260401b169116179055565b7f336f0b3cc523e98d21e261389542b62abaffc094a21a82f1eec2779d7c8323cb600080a3005b634e487b7160e01b600052600160045260246000fd5b604051634753d28360e01b815260048101839052602490fd5b604051639e7f1f4160e01b815260048101839052602490fd5b346101dd5760003660031901126101dd5760405180609b5491828152602080910192609b6000527fbba9db4cdbea0a37c207bbb83e20f828cd4441c49891101dc94fd20dc8efc349916000905b8282106104935761048f8561047b8189038261266c565b6040519182916020835260208301906124d1565b0390f35b835486529485019460019384019390910190610464565b346101dd5760203660031901126101dd576104d16001600160a01b036000541633146126aa565b600435603255005b346101dd5760403660031901126101dd57609d80546004356024803590838210156105e6576105088383612d1a565b92600193600181018091116105d0576105209061270d565b95815b8481111561054957878761048f60405192839283526040602084015260408301906124d1565b868110156105bb57816000526001600160a01b03817fd26e832454299e9fabb89e0e5fffdc046d4e14431bc1bf607ffb2e8a1ddecf7b01541661059561058f8584612d1a565b8a6129e6565b5260001981146105a6578501610523565b83634e487b7160e01b60005260116004526000fd5b83634e487b7160e01b60005260326004526000fd5b634e487b7160e01b600052601160045260246000fd5b604051637f52b2bf60e01b8152600490fd5b60203660031901126101dd5761060c6124ba565b6001600160801b039061062562093a8083421604613284565b918216918260005260a160205260ff6040600020541615610664576106519250609a5460801c91612e43565b4761065857005b6106624733612d57565b005b604051631d83110f60e21b815260048101849052602490fd5b346101dd5760003660031901126101dd5760206040516a084595161401484a0000008152f35b346101dd5760003660031901126101dd5760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b346101dd5760003660031901126101dd5760206001600160801b03609a5416604051908152f35b346101dd5760003660031901126101dd576020603254604051908152f35b346101dd5760203660031901126101dd577f415aff8bca0fbb5b26c8976127b380373d8831645591229178dce3dbc2480ddf6020610768612524565b61077e6001600160a01b036000541633146126aa565b6001600160801b03609a54816001600160801b03198460801b16911617609a5560405191168152a1005b346101dd576107b63661256b565b90916001600160a01b03809116600052602060a2815260406000209367ffffffffffffffff80865416946107e9816126f5565b946107f7604051968761266c565b818652610803826126f5565b601f190160005b81811061091a5750506000916001809901925b8181106108b25750505050505060405193849360408501908552604083860152835180915260609280606087019501936000905b83821061085e5787870388f35b9185975082876108a08799849895979951805167ffffffffffffffff16825260209081015180516001600160801b039081168385015291015116604090910152565b01970192018796959391949294610851565b9889836108cc6108c7849b9c9a9d868b6129c2565b612cf1565b16600052848b5260406000206108f583604051926108e984612620565b8981541684520161299d565b8c820152610903828c6129e6565b5261090e818b6129e6565b5001989597969861081d565b95809997989661092b969496612caf565b82828c01015201989597969894929461080a565b346101dd5760003660031901126101dd5760206001600160a01b0360005416604051908152f35b346101dd5760403660031901126101dd5761097f612524565b60243567ffffffffffffffff81116101dd5761099f90369060040161253a565b6001600160801b0380931662093a808106610a4b5760009291925260209060a16020526040600020908154936109d48161270d565b9360019384019160005b818110610a1357888861048f89604051938360ff8695161515855260081c1660208401526060604084015260608301906125af565b806001600160a01b03610a2b6108c78994868a6129c2565b166000528484528960406000205416610a44828a6129e6565b52016109de565b60249060405190637bf16ce960e11b82526004820152fd5b346101dd5760003660031901126101dd57609b805460005b818110610b07576001600160801b03610a9a62093a8082421604613284565b5b8180609a5416911690811180610aee575b1561066257600081815260a160205260409020805460ff1916600117905562093a7f190181811115610a9b57634e487b7160e01b600052601160045260246000fd5b508060005260a160205260ff6040600020541615610aac565b8254811015610b525760019083600052610b4c6001600160a01b03827fbba9db4cdbea0a37c207bbb83e20f828cd4441c49891101dc94fd20dc8efc349015416612a15565b01610a7b565b634e487b7160e01b600052603260045260246000fd5b346101dd5760003660031901126101dd576001805460ff8160a81c161590818092610db1575b8015610d98575b15610d2d5781740100000000000000000000000000000000000000007fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff8316178455610ceb575b5081549060ff8260a81c1615610c8057336001600160a01b031960005416176000556001600160801b03610c1662093a8082421604613284565b166001600160801b0319609a541617609a55610c2e57005b7f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498917fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff602092168155604051908152a1005b60405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608490fd5b7fffffffffffffffffffff0000ffffffffffffffffffffffffffffffffffffffff16750101000000000000000000000000000000000000000017825582610bdc565b60405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608490fd5b50303b158015610b9557508260ff8260a01c1614610b95565b508260ff8260a01c1610610b8e565b346101dd5760403660031901126101dd57610dd961248e565b610de16124a4565b906001600160a01b0380911660005260a3602052604060002091166000526020526020604060002054604051908152f35b346101dd5760403660031901126101dd5760043567ffffffffffffffff81116101dd57610e4390369060040161253a565b60243567ffffffffffffffff81116101dd57610e6390369060040161253a565b9290838303611687576001600160a01b03600054163314938415806115e2575b6115ca5760405194610e9486612620565b6000808752602087015215611506576001600160801b036303bfc400814216018181116105d05762093a8082610ecb921604613284565b1660208601526a084595161401484a00000085525b60005b848110610f33573360005260a260205267ffffffffffffffff60406000205416670de0b6b3a764000090818111610f1657005b6044916040519163903482f560e01b835260048301526024820152fd5b610f606001600160a01b03610f4c6108c78489896129c2565b16600052609c602052604060002054151590565b6114eb575b610f736108c78287876129c2565b90610f87610f828285876129c2565b612d05565b604051610f9381612620565b6000815260006020820152903360005260a26020526040600020906001600160a01b03851660005260a060205260406000209160018101602052610fdd600160406000200161299d565b6001600160801b03815116611342575b5067ffffffffffffffff82166110d1575b50507fa512c82e73ec974de3c794a3ea6bbdfbad18531c1394ace9972f3f0166b6786360406001600160a01b036001968783519501546001600160801b038116865260801c60208601521692a26001600160a01b036110616108c7848a8a6129c2565b6110a3611072610f8286898b6129c2565b9367ffffffffffffffff604051951685526020850190602090816001600160801b0391828151168552015116910152565b16907fc71e393f1527f71ce01b78ea87c9bd4fca84f1482359ce7ac9b73f358c61b1e160603392a301610ee3565b9092506110f46001600160a01b038616600052609c602052604060002054151590565b15611321576040519261110684612620565b6000845260006020850152670de0b6b3a76400006303bfc40061113e8d6001600160801b0367ffffffffffffffff8616915116612e30565b04046001600160801b0381116101dd5761116f8c6001600160801b036020818095169283828b0152015116906132a1565b1684526112bf846001600160801b03602061118c6001880161299d565b61120a83806111d28186604051966111a388612620565b60008852600082890152826111c08c8280855116915116906129fa565b16885201511682878a015116906129fa565b169283858201525116918419928360018c0154161760018b015560018a01906001600160801b0382549181199060801b169116179055565b8282850151168361121a866133b4565b16600052600289018352604060002090828561123a8454938285166129fa565b169116179055600160405161124e81612620565b67ffffffffffffffff881681528381019586526001600160a01b038d16600052818901845267ffffffffffffffff604060002091511667ffffffffffffffff198254161781550193519083825116908554161784550151166001600160801b0382549181199060801b169116179055565b81549067ffffffffffffffff80821681841601116105d05767ffffffffffffffff908116818316011667ffffffffffffffff19919091161790557fa512c82e73ec974de3c794a3ea6bbdfbad18531c1394ace9972f3f0166b678636040610ffe565b60405163913accad60e01b81526001600160a01b0386166004820152602490fd5b6113626001600160a01b038816600052609c602052604060002054151590565b806114ba575b6113ed575b506001600160a01b0386166000526001810160205267ffffffffffffffff6040600020541681549067ffffffffffffffff8181841603116105d05767ffffffffffffffff9081831603169067ffffffffffffffff19161781556001600160a01b03861660005260018101602052600060016040822082815501558b610fed565b60018401906001600160801b03611487816114078561299d565b61147f6040519161141783612620565b600083528380602080860193600085528261143a8c82808551169151169061326b565b168752015116938161145460208b0196828851169061326b565b1680935251169784199889825416178155906001600160801b0382549181199060801b169116179055565b5116926133b4565b16600052600285016020526040600020916001600160801b036114ae84549382851661326b565b1691161790558b61136d565b506001600160801b036020820151161515801561136857506001600160801b036114e3826133b4565b164210611368565b6115016114fc6108c78388886129c2565b612a15565b610f65565b604080516332dad3cf60e21b815233600482015290816024817f0000000000000000000000007310468a0607003ab7dbc23af44c88565e945a3e6001600160a01b03165afa9081156115be57600090600092611576575b506001600160801b038092166020880152168552610ee0565b9150506040813d6040116115b6575b816115926040938361266c565b810103126101dd576115af60206115a883612cdd565b9201612cdd565b908761155d565b3d9150611585565b6040513d6000823e3d90fd5b60405163eb1acbe360e01b8152336004820152602490fd5b506040516370a0823160e01b81523360048201526020816024817f0000000000000000000000007310468a0607003ab7dbc23af44c88565e945a3e6001600160a01b03165afa80156115be57600090611647575b6001600160801b0391501615610e83565b506020813d60201161167f575b816116616020938361266c565b810103126101dd5761167a6001600160801b0391612cdd565b611636565b3d9150611654565b60405163512509d360e11b8152600490fd5b346101dd5760403660031901126101dd576116b261248e565b6116ba6124a4565b906116c3612caf565b506001600160a01b0380911660005260a2602052600160406000200191166000526020526060604060002061171460016040519261170084612620565b67ffffffffffffffff81541684520161299d565b602082810191825260408051935167ffffffffffffffff168452915180516001600160801b03908116858401529101511690820152f35bf35b346101dd5760603660031901126101dd5761176661248e565b61176e6124a4565b6044359161177a612caf565b506001600160a01b0380911660005260a3602052604060002091166000526020526040600020906117a9612caf565b508154811015610b525760609160005260206000209060011b0161174b604051916117d383612620565b6117ed60016001600160801b03928381541686520161299d565b90602084019182526040519351168352516020830190602090816001600160801b0391828151168552015116910152565b346101dd5760003660031901126101dd576001600160a01b037f0000000000000000000000003fbaf4fbf6a2198c1e347e9e6f5bd842c3d704881630036118895760206040517f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8152f35b60405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608490fd5b60403660031901126101dd5761190861248e565b6024359067ffffffffffffffff82116101dd57366023830112156101dd5781600401356119348161268e565b92611942604051948561266c565b8184526020918285019136602483830101116101dd578160009260248693018537860101526001600160a01b03807f0000000000000000000000003fbaf4fbf6a2198c1e347e9e6f5bd842c3d70488169061199f823014156128b9565b6119ce7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc92828454161461292b565b6119dd816000541633146126aa565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615611a1557505050506106629150613306565b84939416906040516352d1902d60e01b81528581600481865afa60009181611bc6575b50611a995760405162461bcd60e51b815260048101879052602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608490fd5b03611b5b57611aa783613306565b7fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b600080a2835115801590611b53575b611add57005b60008091610662957f416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c60405196611b1388612650565b602788528701527f206661696c65640000000000000000000000000000000000000000000000000060408701525190845af4611b4d612d27565b9161389f565b506001611ad7565b60405162461bcd60e51b815260048101859052602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f7860448201527f6961626c655555494400000000000000000000000000000000000000000000006064820152608490fd5b9091508681813d8311611bee575b611bde818361266c565b810103126101dd57519088611a38565b503d611bd4565b346101dd5760003660031901126101dd576001546001600160a01b0390818116803303611c5e57806000549384167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a36001600160a01b03199283161760005516600155005b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c657220213d2070656e64696e67206f776e65726044820152fd5b346101dd5760003660031901126101dd576020609a5460801c604051908152f35b346101dd5760003660031901126101dd57603354611ce08161270d565b90611cea8161270d565b9060005b818110611d1f57611d118461048f856040519384936040855260408501906125ec565b9083820360208501526124d1565b806001917f82a75bdeeae8604d839476ae9efd8b0e15aa447e21bfd7f41283bb54e22c9a8201548060005260356020526001600160a01b0360406000205416611d6883876129e6565b52611d7382876129e6565b5201611cee565b346101dd5760203660031901126101dd57611d9361248e565b6001600160a01b03611daa816000541633146126aa565b811690611dc482600052609c602052604060002054151590565b15611e70578160005260a060205267ffffffffffffffff611dec816040600020541692612a15565b8260005260a060205260406000205416600052609f602052611e128260406000206135dd565b156103cf57611e20826134dc565b156103cf57611e2e8261376a565b156103cf578160005260a0602052600060016040822082815501557ff2e3b584c4d1ed5ead9a4b7de2a8225fd42d13f09e417cd294d03f1dd07fc914600080a3005b60405163913accad60e01b815260048101839052602490fd5b346101dd5760203660031901126101dd576106626114fc61248e565b346101dd57611eb33661256b565b60405191926001600160a01b0390611eca84612620565b6000845260006020809501521660005260a06020526040600020918254926001600160801b0394600191611f006001820161299d565b93611f0a8661270d565b95600260009301925b818110611f7157898961048f8a611f608b604051958567ffffffffffffffff889716875260401c1660208601526040850190602090816001600160801b0391828151168552015116910152565b60a0608084015260a08301906125af565b62093a808a611f89611f8484868a6129c2565b6129d2565b1606611fc057808a611fa0611f848994868a6129c2565b166000528484528a60406000205416611fb9828b6129e6565b5201611f13565b611fd1611f848b92602494886129c2565b604051637bf16ce960e11b815291166004820152fd5b346101dd576020806003193601126101dd5761200161248e565b6001600160a01b0391827f0000000000000000000000003fbaf4fbf6a2198c1e347e9e6f5bd842c3d70488169261203a843014156128b9565b6120697f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc94828654161461292b565b612078816000541633146126aa565b604051938285019185831067ffffffffffffffff8411176121d357826040526000865260ff7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd914354166000146120d557505050506106629150613306565b84939416906040516352d1902d60e01b81528581600481865afa600091816121a4575b506121595760405162461bcd60e51b815260048101879052602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608490fd5b03611b5b5761216783613306565b7fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b600080a283511580159061219c57611add57005b506000611ad7565b9091508681813d83116121cc575b6121bc818361266c565b810103126101dd575190886120f8565b503d6121b2565b634e487b7160e01b600052604160045260246000fd5b346101dd5760003660031901126101dd5760206040516001600160a01b037f0000000000000000000000007310468a0607003ab7dbc23af44c88565e945a3e168152f35b346101dd5760203660031901126101dd57602061225061224b6124ba565b612776565b604051908152f35b60403660031901126101dd5761066261226f61248e565b602435906001600160a01b039061228b826000541633146126aa565b826000526035602052166040600020556136cd565b60603660031901126101dd576122b46124ba565b6122bc61250e565b604435906001600160801b03821682036101dd57610651926122ea6001600160a01b036000541633146126aa565b612e43565b346101dd576020806003193601126101dd5767ffffffffffffffff6123126124ba565b16600052609f8152604060002090604051808383829554938481520190600052836000209260005b85828210612365575050506123519250038361266c565b61048f6040519282849384528301906124d1565b855484526001958601958895509301920161233a565b346101dd5760603660031901126101dd5761239461248e565b60243580151581036101dd576044359081151582036101dd576001600160a01b039283916123c7836000541633146126aa565b1561247457169081159081159161246c575b501561242757806000549283167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a36001600160a01b03198092161760005560015416600155600080f35b60405162461bcd60e51b815260206004820152601560248201527f4f776e61626c653a207a65726f206164647265737300000000000000000000006044820152606490fd5b9050836123d9565b915050166001600160a01b03196001541617600155600080f35b600435906001600160a01b03821682036101dd57565b602435906001600160a01b03821682036101dd57565b6004359067ffffffffffffffff821682036101dd57565b90815180825260208080930193019160005b8281106124f1575050505090565b83516001600160a01b0316855293810193928101926001016124e3565b602435906001600160801b03821682036101dd57565b600435906001600160801b03821682036101dd57565b9181601f840112156101dd5782359167ffffffffffffffff83116101dd576020808501948460051b0101116101dd57565b9060406003198301126101dd576004356001600160a01b03811681036101dd57916024359067ffffffffffffffff82116101dd576125ab9160040161253a565b9091565b90815180825260208080930193019160005b8281106125cf575050505090565b83516001600160801b0316855293810193928101926001016125c1565b90815180825260208080930193019160005b82811061260c575050505090565b8351855293810193928101926001016125fe565b6040810190811067ffffffffffffffff8211176121d357604052565b67ffffffffffffffff81116121d357604052565b6060810190811067ffffffffffffffff8211176121d357604052565b90601f8019910116810190811067ffffffffffffffff8211176121d357604052565b67ffffffffffffffff81116121d357601f01601f191660200190565b156126b157565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b67ffffffffffffffff81116121d35760051b60200190565b90612717826126f5565b612724604051918261266c565b8281528092612735601f19916126f5565b0190602036910137565b91612765906001600160801b0361277395931684526060602085015260608401906124d1565b9160408184039101526125ec565b90565b67ffffffffffffffff164681146128b357600090808252602091609f8352604081205480156128ac576127d96127f8826127b96127b3889561270d565b9161270d565b906127ec60405194859288888501526060604085015260808401906124d1565b601f1993848483030160608501526125ec565b0390810183528261266c565b6001600160a01b038061280a86613464565b6032546040516384fe172160e01b815297889586948594612831949391166004860161323b565b03917f0000000000000000000000000000000000000000000000000000000000000000165afa92831561289f57819361286b575b50505090565b9091809350813d8311612898575b612883818361266c565b81010312612895575051388080612865565b80fd5b503d612879565b50604051903d90823e3d90fd5b5091505090565b50600090565b156128c057565b60405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c00000000000000000000000000000000000000006064820152608490fd5b1561293257565b60405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f787900000000000000000000000000000000000000006064820152608490fd5b906040516129aa81612620565b91546001600160801b038116835260801c6020830152565b9190811015610b525760051b0190565b356001600160801b03811681036101dd5790565b8051821015610b525760209160051b010190565b9190916001600160801b03808094169116019182116105d057565b6001600160a01b031690612a3682600052609c602052604060002054151590565b15611e705760009082825260a092602060a081526001600160801b03906040918083872054841c169162093a809782612a728a82421604613284565b1680851015612ca3579088809a8888999a9b5260a08552612a99600180998a94200161299d565b975b612b71575b5050508689525060a08152968490208351978401516fffffffffffffffffffffffffffffffff1990831660801b16919097166001600160801b0316176001870155939492937fa512c82e73ec974de3c794a3ea6bbdfbad18531c1394ace9972f3f0166b6786393612b4c9177ffffffffffffffffffffffffffffffff00000000000000001977ffffffffffffffffffffffffffffffff000000000000000083549260401b169116179055565b612b6e82518092602090816001600160801b0391828151168552015116910152565ba2565b9091929585819c9b9a99989c169087821015612c965750810195858711612c8257828b9c878a8c9d9e8b9c9d8a848e8385528c8352858520600201978282169889875284528280888820541691885195612bca87612620565b888752828481838a01938c85528501511690612be59161326b565b169052511691612bf4916132a1565b612bfd9161326b565b168152809e612c0b916132bf565b9480835260a190818d5284842080546008898983831c1690612c2c916129fa565b901b70ffffffffffffffffffffffffffffffff00169070ffffffffffffffffffffffffffffffff00191617905583528b5285838320019082528a522091166001600160801b031982541617905591909392612a9b565b634e487b7160e01b8b52601160045260248bfd5b96509a969798999a612aa0565b50505050505050915050565b60405190612cbc82612620565b60008252604051602083612ccf83612620565b600083526000828401520152565b51906001600160801b03821682036101dd57565b356001600160a01b03811681036101dd5790565b3567ffffffffffffffff811681036101dd5790565b919082039182116105d057565b3d15612d52573d90612d388261268e565b91612d46604051938461266c565b82523d6000602084013e565b606090565b814710612deb5760008080936001600160a01b038294165af1612d78612d27565b5015612d8057565b60405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608490fd5b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606490fd5b818102929181159184041417156105d057565b929190926001600160801b03938481169260009584875260209260a1845260409082828a205460081c1695861590816131ee5767ffffffffffffffff1696878b52609f8752838b2090815480156131df57908c9392918651928a84838152019086528a8620865b8c8482106131bc5750505083612ec191038461266c565b612eca8161270d565b938c89898d89935b86851061311a575050505050505050468914600014612f82576001600160a01b03612efc8a613464565b1690813b15612f7e5783612f269587519687958694859363072cbf8760e41b85526004850161273f565b03925af18015612f74577fc78a580f215ba474e75ecbd7636c375e8d2cd25edb0f2467f99b2d0752e104ba9697989950612f65575b505b5191168152a3565b612f6e9061263c565b38612f5b565b82513d8b823e3d90fd5b8380fd5b9290612fa89250612f9a9085519485938a850161273f565b03601f19810183528261266c565b858952603485528189205415613106576001600160a01b039081612fcb88613464565b60325485516384fe172160e01b815290947f000000000000000000000000000000000000000000000000000000000000000016929091169088818061301688888f886004860161323b565b0381865afa9081156130fc578d916130cb575b508047106130ac579082918d94933b156130a8578a9161305e88519788968795869463b2267a7b60e01b86526004860161323b565b03925af18015612f74577fc78a580f215ba474e75ecbd7636c375e8d2cd25edb0f2467f99b2d0752e104ba9697989950613099575b50612f5d565b6130a29061263c565b38613093565b8480fd5b855163704c5be560e11b81524760048201526024810191909152604490fd5b90508881813d83116130f5575b6130e2818361266c565b810103126130f1575138613029565b8c80fd5b503d6130d8565b86513d8f823e3d90fd5b634e487b7160e01b89526001600452602489fd5b908a9161315595969798999a9b5260a18152600183832001906001600160a01b03613145888d6129e6565b51168352522054168a8c16612e30565b62093a80908181029181830414901517156131a757826131925790846001920461317f82896129e6565b5201908e959493929189898f8e90612ed2565b50634e487b7160e01b8f52601260045260248ffd5b50634e487b7160e01b8f52601160045260248ffd5b82949596979850600192938392945481520193019101908f969594939291612eaa565b50505050505050505050509050565b5050505050505050509050565b919082519283825260005b848110613227575050826000602080949584010152601f8019910116010190565b602081830181015184830182015201613206565b9493926060926001600160a01b036132669316875260208701526080604087015260808601906131fb565b930152565b6001600160801b0391821690821603919082116105d057565b9062093a806001600160801b03809316029182169182036105d057565b9190916001600160801b03808094169116029182169182036105d057565b602081016001600160801b03928392836132dc83828651166132a1565b91511693849116116132fd57612773936132f79251166132a1565b9061326b565b50505050600090565b803b15613349576001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc91166001600160a01b0319825416179055565b60405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e7472616374000000000000000000000000000000000000006064820152608490fd5b60208101906001600160801b03908183511680156133f457505191518116911681156133de570490565b634e487b7160e01b600052601260045260246000fd5b826044925116906040519163fbd384a560e01b835260048301526024820152fd5b609b54811015610b5257609b6000527fbba9db4cdbea0a37c207bbb83e20f828cd4441c49891101dc94fd20dc8efc3490190600090565b8054821015610b525760005260206000200190600090565b600052603560205260406000205480158015906134c9575b156134845790565b60405162461bcd60e51b815260206004820152601e60248201527f456e756d657261626c654d61703a206e6f6e6578697374656e74206b657900006044820152606490fd5b506034602052604060002054151561347c565b6000818152609c602052604081205490919080156135d857600019908082018181116135c457609b54908382019182116135b057808203613565575b505050609b5480156135515781019061353082613415565b909182549160031b1b19169055609b558152609c6020526040812055600190565b634e487b7160e01b84526031600452602484fd5b61359a61357461358393613415565b90549060031b1c928392613415565b819391549060031b91821b91600019901b19161790565b90558452609c6020526040842055388080613518565b634e487b7160e01b86526011600452602486fd5b634e487b7160e01b85526011600452602485fd5b505090565b906001820190600092818452826020526040842054908115156000146136c657600019918083018181116136b25782549084820191821161369e57808203613669575b5050508054801561365557820191613638838361344c565b909182549160031b1b191690555582526020526040812055600190565b634e487b7160e01b86526031600452602486fd5b613689613679613583938661344c565b90549060031b1c9283928661344c565b90558652846020526040862055388080613620565b634e487b7160e01b88526011600452602488fd5b634e487b7160e01b87526011600452602487fd5b5050505090565b600081815260346020526040812054613765576033546801000000000000000081101561375157600181018060335581101561373d5790826040927f82a75bdeeae8604d839476ae9efd8b0e15aa447e21bfd7f41283bb54e22c9a82015560335492815260346020522055600190565b634e487b7160e01b82526032600452602482fd5b634e487b7160e01b82526041600452602482fd5b905090565b6000818152609e602052604081205461376557609d5468010000000000000000811015613751576001810180609d5581101561373d5790826040927fd26e832454299e9fabb89e0e5fffdc046d4e14431bc1bf607ffb2e8a1ddecf7b0155609d54928152609e6020522055600190565b6000818152609c602052604081205461376557609b546801000000000000000081101561375157908261381861358384600160409601609b55613415565b9055609b54928152609c6020522055600190565b9190600183016000908282528060205260408220541560001461389957845494680100000000000000008610156138855783613875613583886001604098999a0185558461344c565b9055549382526020522055600190565b634e487b7160e01b83526041600452602483fd5b50925050565b9192901561390157508151156138b3575090565b3b156138bc5790565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b8251909150156139145750805190602001fd5b60405162461bcd60e51b8152602060048201529081906139389060248301906131fb565b0390fdfea2646970667358221220fd5e6e11bcd8f89db8c8c14cdf63c1552fb6e81b0b28ab09ca9b961752cabd7f64736f6c63430008180033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000007310468a0607003ab7dbc23af44c88565e945a3e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _veZLK (address): 0x7310468a0607003AB7DBc23af44c88565E945a3e
Arg [1] : _zenlinkMsgSendEndpoint (address): 0x0000000000000000000000000000000000000000
Arg [2] : initialApproxDestinationGas (uint256): 0
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 0000000000000000000000007310468a0607003ab7dbc23af44c88565e945a3e
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
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.