Source Code
Overview
GLMR Balance
GLMR Value
$0.00Latest 1 from a total of 1 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Initialize | 6455813 | 579 days ago | IN | 0 GLMR | 0.015921 |
Cross-Chain Transactions
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 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
0x6080604052600436101561001257600080fd5b60003560e01c8063078dfbe71461237b57806316ac7e30146122ef5780631c9bdb49146122a057806321049028146122585780632477bfbe1461222d57806336539c54146121e95780633659cfe614611fe7578063366c771d14611ea557806338b8765c14611e895780633b7d094614611d7a5780633e39b65014611cc35780633f81a66414611ca25780634e71e0c814611bf55780634f1ef286146118f457806352d1902d1461181e578063632c096d1461174d578063646fb67c14611699578063698766ee14610e125780636aea282614610dc05780638129fc1c14610b6857806382ae9ef714610a635780638d66c284146109665780638da5cb5b1461093f5780638f45ff78146107a857806395de8fa11461072c5780639efc75751461070e578063b292bf95146106e7578063b77f1ba3146106a3578063b837b3db1461067d578063c291230d146105f8578063cc88370e146104d9578063d45f5e21146104aa578063d5cd7d2014610417578063d68ffecb14610282578063e30c39781461025b578063f144cf1714610200578063f4359ce5146101e25763fa78668f146101be57600080fd5b346101dd5760003660031901126101dd5760206040516303bfc4008152f35b600080fd5b346101dd5760003660031901126101dd57602060405162093a808152f35b346101dd5760403660031901126101dd57602061021b61248e565b6001600160801b03908161022d61250e565b1660005260a183526001600160a01b0360016040600020019116600052825260406000205416604051908152f35b346101dd5760003660031901126101dd5760206001600160a01b0360015416604051908152f35b346101dd5760403660031901126101dd5761029b6124ba565b6102a36124a4565b6001600160a01b03906102bb826000541633146126aa565b16906102d482600052609c602052604060002054151590565b6103fe5781600052609e6020526040600020546103e55767ffffffffffffffff1680600052609f60205261030c82604060002061382c565b156103cf5761031a826137da565b156103cf578160005260a060205260406000208167ffffffffffffffff198254161790556103a861035862093a806001600160801b03421604613284565b8360005260a060205260406000209077ffffffffffffffffffffffffffffffff00000000000000001977ffffffffffffffffffffffffffffffff000000000000000083549260401b169116179055565b7f336f0b3cc523e98d21e261389542b62abaffc094a21a82f1eec2779d7c8323cb600080a3005b634e487b7160e01b600052600160045260246000fd5b604051634753d28360e01b815260048101839052602490fd5b604051639e7f1f4160e01b815260048101839052602490fd5b346101dd5760003660031901126101dd5760405180609b5491828152602080910192609b6000527fbba9db4cdbea0a37c207bbb83e20f828cd4441c49891101dc94fd20dc8efc349916000905b8282106104935761048f8561047b8189038261266c565b6040519182916020835260208301906124d1565b0390f35b835486529485019460019384019390910190610464565b346101dd5760203660031901126101dd576104d16001600160a01b036000541633146126aa565b600435603255005b346101dd5760403660031901126101dd57609d80546004356024803590838210156105e6576105088383612d1a565b92600193600181018091116105d0576105209061270d565b95815b8481111561054957878761048f60405192839283526040602084015260408301906124d1565b868110156105bb57816000526001600160a01b03817fd26e832454299e9fabb89e0e5fffdc046d4e14431bc1bf607ffb2e8a1ddecf7b01541661059561058f8584612d1a565b8a6129e6565b5260001981146105a6578501610523565b83634e487b7160e01b60005260116004526000fd5b83634e487b7160e01b60005260326004526000fd5b634e487b7160e01b600052601160045260246000fd5b604051637f52b2bf60e01b8152600490fd5b60203660031901126101dd5761060c6124ba565b6001600160801b039061062562093a8083421604613284565b918216918260005260a160205260ff6040600020541615610664576106519250609a5460801c91612e43565b4761065857005b6106624733612d57565b005b604051631d83110f60e21b815260048101849052602490fd5b346101dd5760003660031901126101dd5760206040516a084595161401484a0000008152f35b346101dd5760003660031901126101dd5760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b346101dd5760003660031901126101dd5760206001600160801b03609a5416604051908152f35b346101dd5760003660031901126101dd576020603254604051908152f35b346101dd5760203660031901126101dd577f415aff8bca0fbb5b26c8976127b380373d8831645591229178dce3dbc2480ddf6020610768612524565b61077e6001600160a01b036000541633146126aa565b6001600160801b03609a54816001600160801b03198460801b16911617609a5560405191168152a1005b346101dd576107b63661256b565b90916001600160a01b03809116600052602060a2815260406000209367ffffffffffffffff80865416946107e9816126f5565b946107f7604051968761266c565b818652610803826126f5565b601f190160005b81811061091a5750506000916001809901925b8181106108b25750505050505060405193849360408501908552604083860152835180915260609280606087019501936000905b83821061085e5787870388f35b9185975082876108a08799849895979951805167ffffffffffffffff16825260209081015180516001600160801b039081168385015291015116604090910152565b01970192018796959391949294610851565b9889836108cc6108c7849b9c9a9d868b6129c2565b612cf1565b16600052848b5260406000206108f583604051926108e984612620565b8981541684520161299d565b8c820152610903828c6129e6565b5261090e818b6129e6565b5001989597969861081d565b95809997989661092b969496612caf565b82828c01015201989597969894929461080a565b346101dd5760003660031901126101dd5760206001600160a01b0360005416604051908152f35b346101dd5760403660031901126101dd5761097f612524565b60243567ffffffffffffffff81116101dd5761099f90369060040161253a565b6001600160801b0380931662093a808106610a4b5760009291925260209060a16020526040600020908154936109d48161270d565b9360019384019160005b818110610a1357888861048f89604051938360ff8695161515855260081c1660208401526060604084015260608301906125af565b806001600160a01b03610a2b6108c78994868a6129c2565b166000528484528960406000205416610a44828a6129e6565b52016109de565b60249060405190637bf16ce960e11b82526004820152fd5b346101dd5760003660031901126101dd57609b805460005b818110610b07576001600160801b03610a9a62093a8082421604613284565b5b8180609a5416911690811180610aee575b1561066257600081815260a160205260409020805460ff1916600117905562093a7f190181811115610a9b57634e487b7160e01b600052601160045260246000fd5b508060005260a160205260ff6040600020541615610aac565b8254811015610b525760019083600052610b4c6001600160a01b03827fbba9db4cdbea0a37c207bbb83e20f828cd4441c49891101dc94fd20dc8efc349015416612a15565b01610a7b565b634e487b7160e01b600052603260045260246000fd5b346101dd5760003660031901126101dd576001805460ff8160a81c161590818092610db1575b8015610d98575b15610d2d5781740100000000000000000000000000000000000000007fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff8316178455610ceb575b5081549060ff8260a81c1615610c8057336001600160a01b031960005416176000556001600160801b03610c1662093a8082421604613284565b166001600160801b0319609a541617609a55610c2e57005b7f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498917fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff602092168155604051908152a1005b60405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608490fd5b7fffffffffffffffffffff0000ffffffffffffffffffffffffffffffffffffffff16750101000000000000000000000000000000000000000017825582610bdc565b60405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608490fd5b50303b158015610b9557508260ff8260a01c1614610b95565b508260ff8260a01c1610610b8e565b346101dd5760403660031901126101dd57610dd961248e565b610de16124a4565b906001600160a01b0380911660005260a3602052604060002091166000526020526020604060002054604051908152f35b346101dd5760403660031901126101dd5760043567ffffffffffffffff81116101dd57610e4390369060040161253a565b60243567ffffffffffffffff81116101dd57610e6390369060040161253a565b9290838303611687576001600160a01b03600054163314938415806115e2575b6115ca5760405194610e9486612620565b6000808752602087015215611506576001600160801b036303bfc400814216018181116105d05762093a8082610ecb921604613284565b1660208601526a084595161401484a00000085525b60005b848110610f33573360005260a260205267ffffffffffffffff60406000205416670de0b6b3a764000090818111610f1657005b6044916040519163903482f560e01b835260048301526024820152fd5b610f606001600160a01b03610f4c6108c78489896129c2565b16600052609c602052604060002054151590565b6114eb575b610f736108c78287876129c2565b90610f87610f828285876129c2565b612d05565b604051610f9381612620565b6000815260006020820152903360005260a26020526040600020906001600160a01b03851660005260a060205260406000209160018101602052610fdd600160406000200161299d565b6001600160801b03815116611342575b5067ffffffffffffffff82166110d1575b50507fa512c82e73ec974de3c794a3ea6bbdfbad18531c1394ace9972f3f0166b6786360406001600160a01b036001968783519501546001600160801b038116865260801c60208601521692a26001600160a01b036110616108c7848a8a6129c2565b6110a3611072610f8286898b6129c2565b9367ffffffffffffffff604051951685526020850190602090816001600160801b0391828151168552015116910152565b16907fc71e393f1527f71ce01b78ea87c9bd4fca84f1482359ce7ac9b73f358c61b1e160603392a301610ee3565b9092506110f46001600160a01b038616600052609c602052604060002054151590565b15611321576040519261110684612620565b6000845260006020850152670de0b6b3a76400006303bfc40061113e8d6001600160801b0367ffffffffffffffff8616915116612e30565b04046001600160801b0381116101dd5761116f8c6001600160801b036020818095169283828b0152015116906132a1565b1684526112bf846001600160801b03602061118c6001880161299d565b61120a83806111d28186604051966111a388612620565b60008852600082890152826111c08c8280855116915116906129fa565b16885201511682878a015116906129fa565b169283858201525116918419928360018c0154161760018b015560018a01906001600160801b0382549181199060801b169116179055565b8282850151168361121a866133b4565b16600052600289018352604060002090828561123a8454938285166129fa565b169116179055600160405161124e81612620565b67ffffffffffffffff881681528381019586526001600160a01b038d16600052818901845267ffffffffffffffff604060002091511667ffffffffffffffff198254161781550193519083825116908554161784550151166001600160801b0382549181199060801b169116179055565b81549067ffffffffffffffff80821681841601116105d05767ffffffffffffffff908116818316011667ffffffffffffffff19919091161790557fa512c82e73ec974de3c794a3ea6bbdfbad18531c1394ace9972f3f0166b678636040610ffe565b60405163913accad60e01b81526001600160a01b0386166004820152602490fd5b6113626001600160a01b038816600052609c602052604060002054151590565b806114ba575b6113ed575b506001600160a01b0386166000526001810160205267ffffffffffffffff6040600020541681549067ffffffffffffffff8181841603116105d05767ffffffffffffffff9081831603169067ffffffffffffffff19161781556001600160a01b03861660005260018101602052600060016040822082815501558b610fed565b60018401906001600160801b03611487816114078561299d565b61147f6040519161141783612620565b600083528380602080860193600085528261143a8c82808551169151169061326b565b168752015116938161145460208b0196828851169061326b565b1680935251169784199889825416178155906001600160801b0382549181199060801b169116179055565b5116926133b4565b16600052600285016020526040600020916001600160801b036114ae84549382851661326b565b1691161790558b61136d565b506001600160801b036020820151161515801561136857506001600160801b036114e3826133b4565b164210611368565b6115016114fc6108c78388886129c2565b612a15565b610f65565b604080516332dad3cf60e21b815233600482015290816024817f0000000000000000000000007310468a0607003ab7dbc23af44c88565e945a3e6001600160a01b03165afa9081156115be57600090600092611576575b506001600160801b038092166020880152168552610ee0565b9150506040813d6040116115b6575b816115926040938361266c565b810103126101dd576115af60206115a883612cdd565b9201612cdd565b908761155d565b3d9150611585565b6040513d6000823e3d90fd5b60405163eb1acbe360e01b8152336004820152602490fd5b506040516370a0823160e01b81523360048201526020816024817f0000000000000000000000007310468a0607003ab7dbc23af44c88565e945a3e6001600160a01b03165afa80156115be57600090611647575b6001600160801b0391501615610e83565b506020813d60201161167f575b816116616020938361266c565b810103126101dd5761167a6001600160801b0391612cdd565b611636565b3d9150611654565b60405163512509d360e11b8152600490fd5b346101dd5760403660031901126101dd576116b261248e565b6116ba6124a4565b906116c3612caf565b506001600160a01b0380911660005260a2602052600160406000200191166000526020526060604060002061171460016040519261170084612620565b67ffffffffffffffff81541684520161299d565b602082810191825260408051935167ffffffffffffffff168452915180516001600160801b03908116858401529101511690820152f35bf35b346101dd5760603660031901126101dd5761176661248e565b61176e6124a4565b6044359161177a612caf565b506001600160a01b0380911660005260a3602052604060002091166000526020526040600020906117a9612caf565b508154811015610b525760609160005260206000209060011b0161174b604051916117d383612620565b6117ed60016001600160801b03928381541686520161299d565b90602084019182526040519351168352516020830190602090816001600160801b0391828151168552015116910152565b346101dd5760003660031901126101dd576001600160a01b037f000000000000000000000000e639755190d50141890b2b5add23ceab49974e091630036118895760206040517f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8152f35b60405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608490fd5b60403660031901126101dd5761190861248e565b6024359067ffffffffffffffff82116101dd57366023830112156101dd5781600401356119348161268e565b92611942604051948561266c565b8184526020918285019136602483830101116101dd578160009260248693018537860101526001600160a01b03807f000000000000000000000000e639755190d50141890b2b5add23ceab49974e09169061199f823014156128b9565b6119ce7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc92828454161461292b565b6119dd816000541633146126aa565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615611a1557505050506106629150613306565b84939416906040516352d1902d60e01b81528581600481865afa60009181611bc6575b50611a995760405162461bcd60e51b815260048101879052602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608490fd5b03611b5b57611aa783613306565b7fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b600080a2835115801590611b53575b611add57005b60008091610662957f416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c60405196611b1388612650565b602788528701527f206661696c65640000000000000000000000000000000000000000000000000060408701525190845af4611b4d612d27565b9161389f565b506001611ad7565b60405162461bcd60e51b815260048101859052602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f7860448201527f6961626c655555494400000000000000000000000000000000000000000000006064820152608490fd5b9091508681813d8311611bee575b611bde818361266c565b810103126101dd57519088611a38565b503d611bd4565b346101dd5760003660031901126101dd576001546001600160a01b0390818116803303611c5e57806000549384167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a36001600160a01b03199283161760005516600155005b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c657220213d2070656e64696e67206f776e65726044820152fd5b346101dd5760003660031901126101dd576020609a5460801c604051908152f35b346101dd5760003660031901126101dd57603354611ce08161270d565b90611cea8161270d565b9060005b818110611d1f57611d118461048f856040519384936040855260408501906125ec565b9083820360208501526124d1565b806001917f82a75bdeeae8604d839476ae9efd8b0e15aa447e21bfd7f41283bb54e22c9a8201548060005260356020526001600160a01b0360406000205416611d6883876129e6565b52611d7382876129e6565b5201611cee565b346101dd5760203660031901126101dd57611d9361248e565b6001600160a01b03611daa816000541633146126aa565b811690611dc482600052609c602052604060002054151590565b15611e70578160005260a060205267ffffffffffffffff611dec816040600020541692612a15565b8260005260a060205260406000205416600052609f602052611e128260406000206135dd565b156103cf57611e20826134dc565b156103cf57611e2e8261376a565b156103cf578160005260a0602052600060016040822082815501557ff2e3b584c4d1ed5ead9a4b7de2a8225fd42d13f09e417cd294d03f1dd07fc914600080a3005b60405163913accad60e01b815260048101839052602490fd5b346101dd5760203660031901126101dd576106626114fc61248e565b346101dd57611eb33661256b565b60405191926001600160a01b0390611eca84612620565b6000845260006020809501521660005260a06020526040600020918254926001600160801b0394600191611f006001820161299d565b93611f0a8661270d565b95600260009301925b818110611f7157898961048f8a611f608b604051958567ffffffffffffffff889716875260401c1660208601526040850190602090816001600160801b0391828151168552015116910152565b60a0608084015260a08301906125af565b62093a808a611f89611f8484868a6129c2565b6129d2565b1606611fc057808a611fa0611f848994868a6129c2565b166000528484528a60406000205416611fb9828b6129e6565b5201611f13565b611fd1611f848b92602494886129c2565b604051637bf16ce960e11b815291166004820152fd5b346101dd576020806003193601126101dd5761200161248e565b6001600160a01b0391827f000000000000000000000000e639755190d50141890b2b5add23ceab49974e09169261203a843014156128b9565b6120697f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc94828654161461292b565b612078816000541633146126aa565b604051938285019185831067ffffffffffffffff8411176121d357826040526000865260ff7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd914354166000146120d557505050506106629150613306565b84939416906040516352d1902d60e01b81528581600481865afa600091816121a4575b506121595760405162461bcd60e51b815260048101879052602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608490fd5b03611b5b5761216783613306565b7fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b600080a283511580159061219c57611add57005b506000611ad7565b9091508681813d83116121cc575b6121bc818361266c565b810103126101dd575190886120f8565b503d6121b2565b634e487b7160e01b600052604160045260246000fd5b346101dd5760003660031901126101dd5760206040516001600160a01b037f0000000000000000000000007310468a0607003ab7dbc23af44c88565e945a3e168152f35b346101dd5760203660031901126101dd57602061225061224b6124ba565b612776565b604051908152f35b60403660031901126101dd5761066261226f61248e565b602435906001600160a01b039061228b826000541633146126aa565b826000526035602052166040600020556136cd565b60603660031901126101dd576122b46124ba565b6122bc61250e565b604435906001600160801b03821682036101dd57610651926122ea6001600160a01b036000541633146126aa565b612e43565b346101dd576020806003193601126101dd5767ffffffffffffffff6123126124ba565b16600052609f8152604060002090604051808383829554938481520190600052836000209260005b85828210612365575050506123519250038361266c565b61048f6040519282849384528301906124d1565b855484526001958601958895509301920161233a565b346101dd5760603660031901126101dd5761239461248e565b60243580151581036101dd576044359081151582036101dd576001600160a01b039283916123c7836000541633146126aa565b1561247457169081159081159161246c575b501561242757806000549283167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a36001600160a01b03198092161760005560015416600155600080f35b60405162461bcd60e51b815260206004820152601560248201527f4f776e61626c653a207a65726f206164647265737300000000000000000000006044820152606490fd5b9050836123d9565b915050166001600160a01b03196001541617600155600080f35b600435906001600160a01b03821682036101dd57565b602435906001600160a01b03821682036101dd57565b6004359067ffffffffffffffff821682036101dd57565b90815180825260208080930193019160005b8281106124f1575050505090565b83516001600160a01b0316855293810193928101926001016124e3565b602435906001600160801b03821682036101dd57565b600435906001600160801b03821682036101dd57565b9181601f840112156101dd5782359167ffffffffffffffff83116101dd576020808501948460051b0101116101dd57565b9060406003198301126101dd576004356001600160a01b03811681036101dd57916024359067ffffffffffffffff82116101dd576125ab9160040161253a565b9091565b90815180825260208080930193019160005b8281106125cf575050505090565b83516001600160801b0316855293810193928101926001016125c1565b90815180825260208080930193019160005b82811061260c575050505090565b8351855293810193928101926001016125fe565b6040810190811067ffffffffffffffff8211176121d357604052565b67ffffffffffffffff81116121d357604052565b6060810190811067ffffffffffffffff8211176121d357604052565b90601f8019910116810190811067ffffffffffffffff8211176121d357604052565b67ffffffffffffffff81116121d357601f01601f191660200190565b156126b157565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b67ffffffffffffffff81116121d35760051b60200190565b90612717826126f5565b612724604051918261266c565b8281528092612735601f19916126f5565b0190602036910137565b91612765906001600160801b0361277395931684526060602085015260608401906124d1565b9160408184039101526125ec565b90565b67ffffffffffffffff164681146128b357600090808252602091609f8352604081205480156128ac576127d96127f8826127b96127b3889561270d565b9161270d565b906127ec60405194859288888501526060604085015260808401906124d1565b601f1993848483030160608501526125ec565b0390810183528261266c565b6001600160a01b038061280a86613464565b6032546040516384fe172160e01b815297889586948594612831949391166004860161323b565b03917f0000000000000000000000000000000000000000000000000000000000000000165afa92831561289f57819361286b575b50505090565b9091809350813d8311612898575b612883818361266c565b81010312612895575051388080612865565b80fd5b503d612879565b50604051903d90823e3d90fd5b5091505090565b50600090565b156128c057565b60405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c00000000000000000000000000000000000000006064820152608490fd5b1561293257565b60405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f787900000000000000000000000000000000000000006064820152608490fd5b906040516129aa81612620565b91546001600160801b038116835260801c6020830152565b9190811015610b525760051b0190565b356001600160801b03811681036101dd5790565b8051821015610b525760209160051b010190565b9190916001600160801b03808094169116019182116105d057565b6001600160a01b031690612a3682600052609c602052604060002054151590565b15611e705760009082825260a092602060a081526001600160801b03906040918083872054841c169162093a809782612a728a82421604613284565b1680851015612ca3579088809a8888999a9b5260a08552612a99600180998a94200161299d565b975b612b71575b5050508689525060a08152968490208351978401516fffffffffffffffffffffffffffffffff1990831660801b16919097166001600160801b0316176001870155939492937fa512c82e73ec974de3c794a3ea6bbdfbad18531c1394ace9972f3f0166b6786393612b4c9177ffffffffffffffffffffffffffffffff00000000000000001977ffffffffffffffffffffffffffffffff000000000000000083549260401b169116179055565b612b6e82518092602090816001600160801b0391828151168552015116910152565ba2565b9091929585819c9b9a99989c169087821015612c965750810195858711612c8257828b9c878a8c9d9e8b9c9d8a848e8385528c8352858520600201978282169889875284528280888820541691885195612bca87612620565b888752828481838a01938c85528501511690612be59161326b565b169052511691612bf4916132a1565b612bfd9161326b565b168152809e612c0b916132bf565b9480835260a190818d5284842080546008898983831c1690612c2c916129fa565b901b70ffffffffffffffffffffffffffffffff00169070ffffffffffffffffffffffffffffffff00191617905583528b5285838320019082528a522091166001600160801b031982541617905591909392612a9b565b634e487b7160e01b8b52601160045260248bfd5b96509a969798999a612aa0565b50505050505050915050565b60405190612cbc82612620565b60008252604051602083612ccf83612620565b600083526000828401520152565b51906001600160801b03821682036101dd57565b356001600160a01b03811681036101dd5790565b3567ffffffffffffffff811681036101dd5790565b919082039182116105d057565b3d15612d52573d90612d388261268e565b91612d46604051938461266c565b82523d6000602084013e565b606090565b814710612deb5760008080936001600160a01b038294165af1612d78612d27565b5015612d8057565b60405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608490fd5b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606490fd5b818102929181159184041417156105d057565b929190926001600160801b03938481169260009584875260209260a1845260409082828a205460081c1695861590816131ee5767ffffffffffffffff1696878b52609f8752838b2090815480156131df57908c9392918651928a84838152019086528a8620865b8c8482106131bc5750505083612ec191038461266c565b612eca8161270d565b938c89898d89935b86851061311a575050505050505050468914600014612f82576001600160a01b03612efc8a613464565b1690813b15612f7e5783612f269587519687958694859363072cbf8760e41b85526004850161273f565b03925af18015612f74577fc78a580f215ba474e75ecbd7636c375e8d2cd25edb0f2467f99b2d0752e104ba9697989950612f65575b505b5191168152a3565b612f6e9061263c565b38612f5b565b82513d8b823e3d90fd5b8380fd5b9290612fa89250612f9a9085519485938a850161273f565b03601f19810183528261266c565b858952603485528189205415613106576001600160a01b039081612fcb88613464565b60325485516384fe172160e01b815290947f000000000000000000000000000000000000000000000000000000000000000016929091169088818061301688888f886004860161323b565b0381865afa9081156130fc578d916130cb575b508047106130ac579082918d94933b156130a8578a9161305e88519788968795869463b2267a7b60e01b86526004860161323b565b03925af18015612f74577fc78a580f215ba474e75ecbd7636c375e8d2cd25edb0f2467f99b2d0752e104ba9697989950613099575b50612f5d565b6130a29061263c565b38613093565b8480fd5b855163704c5be560e11b81524760048201526024810191909152604490fd5b90508881813d83116130f5575b6130e2818361266c565b810103126130f1575138613029565b8c80fd5b503d6130d8565b86513d8f823e3d90fd5b634e487b7160e01b89526001600452602489fd5b908a9161315595969798999a9b5260a18152600183832001906001600160a01b03613145888d6129e6565b51168352522054168a8c16612e30565b62093a80908181029181830414901517156131a757826131925790846001920461317f82896129e6565b5201908e959493929189898f8e90612ed2565b50634e487b7160e01b8f52601260045260248ffd5b50634e487b7160e01b8f52601160045260248ffd5b82949596979850600192938392945481520193019101908f969594939291612eaa565b50505050505050505050509050565b5050505050505050509050565b919082519283825260005b848110613227575050826000602080949584010152601f8019910116010190565b602081830181015184830182015201613206565b9493926060926001600160a01b036132669316875260208701526080604087015260808601906131fb565b930152565b6001600160801b0391821690821603919082116105d057565b9062093a806001600160801b03809316029182169182036105d057565b9190916001600160801b03808094169116029182169182036105d057565b602081016001600160801b03928392836132dc83828651166132a1565b91511693849116116132fd57612773936132f79251166132a1565b9061326b565b50505050600090565b803b15613349576001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc91166001600160a01b0319825416179055565b60405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e7472616374000000000000000000000000000000000000006064820152608490fd5b60208101906001600160801b03908183511680156133f457505191518116911681156133de570490565b634e487b7160e01b600052601260045260246000fd5b826044925116906040519163fbd384a560e01b835260048301526024820152fd5b609b54811015610b5257609b6000527fbba9db4cdbea0a37c207bbb83e20f828cd4441c49891101dc94fd20dc8efc3490190600090565b8054821015610b525760005260206000200190600090565b600052603560205260406000205480158015906134c9575b156134845790565b60405162461bcd60e51b815260206004820152601e60248201527f456e756d657261626c654d61703a206e6f6e6578697374656e74206b657900006044820152606490fd5b506034602052604060002054151561347c565b6000818152609c602052604081205490919080156135d857600019908082018181116135c457609b54908382019182116135b057808203613565575b505050609b5480156135515781019061353082613415565b909182549160031b1b19169055609b558152609c6020526040812055600190565b634e487b7160e01b84526031600452602484fd5b61359a61357461358393613415565b90549060031b1c928392613415565b819391549060031b91821b91600019901b19161790565b90558452609c6020526040842055388080613518565b634e487b7160e01b86526011600452602486fd5b634e487b7160e01b85526011600452602485fd5b505090565b906001820190600092818452826020526040842054908115156000146136c657600019918083018181116136b25782549084820191821161369e57808203613669575b5050508054801561365557820191613638838361344c565b909182549160031b1b191690555582526020526040812055600190565b634e487b7160e01b86526031600452602486fd5b613689613679613583938661344c565b90549060031b1c9283928661344c565b90558652846020526040862055388080613620565b634e487b7160e01b88526011600452602488fd5b634e487b7160e01b87526011600452602487fd5b5050505090565b600081815260346020526040812054613765576033546801000000000000000081101561375157600181018060335581101561373d5790826040927f82a75bdeeae8604d839476ae9efd8b0e15aa447e21bfd7f41283bb54e22c9a82015560335492815260346020522055600190565b634e487b7160e01b82526032600452602482fd5b634e487b7160e01b82526041600452602482fd5b905090565b6000818152609e602052604081205461376557609d5468010000000000000000811015613751576001810180609d5581101561373d5790826040927fd26e832454299e9fabb89e0e5fffdc046d4e14431bc1bf607ffb2e8a1ddecf7b0155609d54928152609e6020522055600190565b6000818152609c602052604081205461376557609b546801000000000000000081101561375157908261381861358384600160409601609b55613415565b9055609b54928152609c6020522055600190565b9190600183016000908282528060205260408220541560001461389957845494680100000000000000008610156138855783613875613583886001604098999a0185558461344c565b9055549382526020522055600190565b634e487b7160e01b83526041600452602483fd5b50925050565b9192901561390157508151156138b3575090565b3b156138bc5790565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b8251909150156139145750805190602001fd5b60405162461bcd60e51b8152602060048201529081906139389060248301906131fb565b0390fdfea2646970667358221220fd5e6e11bcd8f89db8c8c14cdf63c1552fb6e81b0b28ab09ca9b961752cabd7f64736f6c63430008180033
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
Net Worth in USD
$0.00
Net Worth in GLMR
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
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.