Feature Tip: Add private address tag to any address under My Name Tag !
Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
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:
UpgradableMeson
Compiler Version
v0.8.28+commit.7893614a
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import "./MesonManager.sol";
contract UpgradableMeson is UUPSUpgradeable, MesonManager {
function initialize(address owner, address premiumManager) external initializer {
_transferOwnership(owner);
_transferPremiumManager(premiumManager);
}
function _authorizeUpgrade(address) internal override onlyOwner {}
}// 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 IERC1822ProxiableUpgradeable {
/**
* @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 v4.4.1 (proxy/beacon/IBeacon.sol)
pragma solidity ^0.8.0;
/**
* @dev This is the interface that {BeaconProxy} expects of its beacon.
*/
interface IBeaconUpgradeable {
/**
* @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.5.0) (proxy/ERC1967/ERC1967Upgrade.sol)
pragma solidity ^0.8.2;
import "../beacon/IBeaconUpgradeable.sol";
import "../../interfaces/draft-IERC1822Upgradeable.sol";
import "../../utils/AddressUpgradeable.sol";
import "../../utils/StorageSlotUpgradeable.sol";
import "../utils/Initializable.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._
*
* @custom:oz-upgrades-unsafe-allow delegatecall
*/
abstract contract ERC1967UpgradeUpgradeable is Initializable {
function __ERC1967Upgrade_init() internal onlyInitializing {
}
function __ERC1967Upgrade_init_unchained() internal onlyInitializing {
}
// 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 Emitted when the implementation is upgraded.
*/
event Upgraded(address indexed implementation);
/**
* @dev Returns the current implementation address.
*/
function _getImplementation() internal view returns (address) {
return StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value;
}
/**
* @dev Stores a new address in the EIP1967 implementation slot.
*/
function _setImplementation(address newImplementation) private {
require(AddressUpgradeable.isContract(newImplementation), "ERC1967: new implementation is not a contract");
StorageSlotUpgradeable.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) {
_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 (StorageSlotUpgradeable.getBooleanSlot(_ROLLBACK_SLOT).value) {
_setImplementation(newImplementation);
} else {
try IERC1822ProxiableUpgradeable(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 Emitted when the admin account has changed.
*/
event AdminChanged(address previousAdmin, address newAdmin);
/**
* @dev Returns the current admin.
*/
function _getAdmin() internal view returns (address) {
return StorageSlotUpgradeable.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");
StorageSlotUpgradeable.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 Emitted when the beacon is upgraded.
*/
event BeaconUpgraded(address indexed beacon);
/**
* @dev Returns the current beacon.
*/
function _getBeacon() internal view returns (address) {
return StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value;
}
/**
* @dev Stores a new beacon in the EIP1967 beacon slot.
*/
function _setBeacon(address newBeacon) private {
require(AddressUpgradeable.isContract(newBeacon), "ERC1967: new beacon is not a contract");
require(
AddressUpgradeable.isContract(IBeaconUpgradeable(newBeacon).implementation()),
"ERC1967: beacon implementation is not a contract"
);
StorageSlotUpgradeable.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) {
_functionDelegateCall(IBeaconUpgradeable(newBeacon).implementation(), data);
}
}
/**
* @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) private returns (bytes memory) {
require(AddressUpgradeable.isContract(target), "Address: delegate call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.delegatecall(data);
return AddressUpgradeable.verifyCallResult(success, returndata, "Address: low-level delegate call failed");
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.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]
* ```
* 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. Equivalent to `reinitializer(1)`.
*/
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.
*
* `initializer` is equivalent to `reinitializer(1)`, so 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.
*
* 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.
*/
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.
*/
function _disableInitializers() internal virtual {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized < type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (proxy/utils/UUPSUpgradeable.sol)
pragma solidity ^0.8.0;
import "../../interfaces/draft-IERC1822Upgradeable.sol";
import "../ERC1967/ERC1967UpgradeUpgradeable.sol";
import "./Initializable.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 Initializable, IERC1822ProxiableUpgradeable, ERC1967UpgradeUpgradeable {
function __UUPSUpgradeable_init() internal onlyInitializing {
}
function __UUPSUpgradeable_init_unchained() internal onlyInitializing {
}
/// @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 that the this implementation remains valid after 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.
*/
function upgradeTo(address newImplementation) external 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.
*/
function upgradeToAndCall(address newImplementation, bytes memory data) external 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;
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/ERC20.sol)
pragma solidity ^0.8.0;
import "./IERC20Upgradeable.sol";
import "./extensions/IERC20MetadataUpgradeable.sol";
import "../../utils/ContextUpgradeable.sol";
import "../../proxy/utils/Initializable.sol";
/**
* @dev Implementation of the {IERC20} interface.
*
* This implementation is agnostic to the way tokens are created. This means
* that a supply mechanism has to be added in a derived contract using {_mint}.
* For a generic mechanism see {ERC20PresetMinterPauser}.
*
* TIP: For a detailed writeup see our guide
* https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* We have followed general OpenZeppelin Contracts guidelines: functions revert
* instead returning `false` on failure. This behavior is nonetheless
* conventional and does not conflict with the expectations of ERC20
* applications.
*
* Additionally, an {Approval} event is emitted on calls to {transferFrom}.
* This allows applications to reconstruct the allowance for all accounts just
* by listening to said events. Other implementations of the EIP may not emit
* these events, as it isn't required by the specification.
*
* Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
* functions have been added to mitigate the well-known issues around setting
* allowances. See {IERC20-approve}.
*/
contract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable, IERC20MetadataUpgradeable {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
/**
* @dev Sets the values for {name} and {symbol}.
*
* The default value of {decimals} is 18. To select a different value for
* {decimals} you should overload it.
*
* All two of these values are immutable: they can only be set once during
* construction.
*/
function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing {
__ERC20_init_unchained(name_, symbol_);
}
function __ERC20_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing {
_name = name_;
_symbol = symbol_;
}
/**
* @dev Returns the name of the token.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5.05` (`505 / 10 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei. This is the value {ERC20} uses, unless this function is
* overridden;
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/
function decimals() public view virtual override returns (uint8) {
return 18;
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
/**
* @dev See {IERC20-transfer}.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - the caller must have a balance of at least `amount`.
*/
function transfer(address to, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_transfer(owner, to, amount);
return true;
}
/**
* @dev See {IERC20-allowance}.
*/
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
/**
* @dev See {IERC20-approve}.
*
* NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
* `transferFrom`. This is semantically equivalent to an infinite approval.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function approve(address spender, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_approve(owner, spender, amount);
return true;
}
/**
* @dev See {IERC20-transferFrom}.
*
* Emits an {Approval} event indicating the updated allowance. This is not
* required by the EIP. See the note at the beginning of {ERC20}.
*
* NOTE: Does not update the allowance if the current allowance
* is the maximum `uint256`.
*
* Requirements:
*
* - `from` and `to` cannot be the zero address.
* - `from` must have a balance of at least `amount`.
* - the caller must have allowance for ``from``'s tokens of at least
* `amount`.
*/
function transferFrom(
address from,
address to,
uint256 amount
) public virtual override returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, amount);
_transfer(from, to, amount);
return true;
}
/**
* @dev Atomically increases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
address owner = _msgSender();
_approve(owner, spender, allowance(owner, spender) + addedValue);
return true;
}
/**
* @dev Atomically decreases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `spender` must have allowance for the caller of at least
* `subtractedValue`.
*/
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
address owner = _msgSender();
uint256 currentAllowance = allowance(owner, spender);
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(owner, spender, currentAllowance - subtractedValue);
}
return true;
}
/**
* @dev Moves `amount` of tokens from `from` to `to`.
*
* This internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Emits a {Transfer} event.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `from` must have a balance of at least `amount`.
*/
function _transfer(
address from,
address to,
uint256 amount
) internal virtual {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(from, to, amount);
uint256 fromBalance = _balances[from];
require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[from] = fromBalance - amount;
}
_balances[to] += amount;
emit Transfer(from, to, amount);
_afterTokenTransfer(from, to, amount);
}
/** @dev Creates `amount` tokens and assigns them to `account`, increasing
* the total supply.
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
_balances[account] += amount;
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
/**
* @dev Destroys `amount` tokens from `account`, reducing the
* total supply.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens.
*/
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
}
_totalSupply -= amount;
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
/**
* @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
*
* This internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*/
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
/**
* @dev Updates `owner` s allowance for `spender` based on spent `amount`.
*
* Does not update the allowance amount in case of infinite allowance.
* Revert if not enough allowance is available.
*
* Might emit an {Approval} event.
*/
function _spendAllowance(
address owner,
address spender,
uint256 amount
) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
require(currentAllowance >= amount, "ERC20: insufficient allowance");
unchecked {
_approve(owner, spender, currentAllowance - amount);
}
}
}
/**
* @dev Hook that is called before any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* will be transferred to `to`.
* - when `from` is zero, `amount` tokens will be minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens will be burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
/**
* @dev Hook that is called after any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* has been transferred to `to`.
* - when `from` is zero, `amount` tokens have been minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens have been burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _afterTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[45] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.0;
import "../IERC20Upgradeable.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/
interface IERC20MetadataUpgradeable is IERC20Upgradeable {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20Upgradeable {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.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
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract ContextUpgradeable is Initializable {
function __Context_init() internal onlyInitializing {
}
function __Context_init_unchained() internal onlyInitializing {
}
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol)
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:
* ```
* 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`, and `uint256`._
*/
library StorageSlotUpgradeable {
struct AddressSlot {
address value;
}
struct BooleanSlot {
bool value;
}
struct Bytes32Slot {
bytes32 value;
}
struct Uint256Slot {
uint256 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
}
}
}// 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 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.7.0) (proxy/ERC1967/ERC1967Proxy.sol)
pragma solidity ^0.8.0;
import "../Proxy.sol";
import "./ERC1967Upgrade.sol";
/**
* @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an
* implementation address that can be changed. This address is stored in storage in the location specified by
* https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the
* implementation behind the proxy.
*/
contract ERC1967Proxy is Proxy, ERC1967Upgrade {
/**
* @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.
*
* If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded
* function call, and allows initializing the storage of the proxy like a Solidity constructor.
*/
constructor(address _logic, bytes memory _data) payable {
_upgradeToAndCall(_logic, _data, false);
}
/**
* @dev Returns the current implementation address.
*/
function _implementation() internal view virtual override returns (address impl) {
return ERC1967Upgrade._getImplementation();
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol)
pragma solidity ^0.8.2;
import "../beacon/IBeacon.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._
*
* @custom:oz-upgrades-unsafe-allow delegatecall
*/
abstract contract ERC1967Upgrade {
// 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 Emitted when the implementation is upgraded.
*/
event Upgraded(address indexed implementation);
/**
* @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 Emitted when the admin account has changed.
*/
event AdminChanged(address previousAdmin, address newAdmin);
/**
* @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 Emitted when the beacon is upgraded.
*/
event BeaconUpgraded(address indexed beacon);
/**
* @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: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol)
pragma solidity ^0.8.0;
/**
* @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
* instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
* be specified by overriding the virtual {_implementation} function.
*
* Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
* different contract through the {_delegate} function.
*
* The success and return data of the delegated call will be returned back to the caller of the proxy.
*/
abstract contract Proxy {
/**
* @dev Delegates the current call to `implementation`.
*
* This function does not return to its internal call site, it will return directly to the external caller.
*/
function _delegate(address implementation) internal virtual {
assembly {
// Copy msg.data. We take full control of memory in this inline assembly
// block because it will not return to Solidity code. We overwrite the
// Solidity scratch pad at memory position 0.
calldatacopy(0, 0, calldatasize())
// Call the implementation.
// out and outsize are 0 because we don't know the size yet.
let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
// Copy the returned data.
returndatacopy(0, 0, returndatasize())
switch result
// delegatecall returns 0 on error.
case 0 {
revert(0, returndatasize())
}
default {
return(0, returndatasize())
}
}
}
/**
* @dev This is a virtual function that should be overridden so it returns the address to which the fallback function
* and {_fallback} should delegate.
*/
function _implementation() internal view virtual returns (address);
/**
* @dev Delegates the current call to the address returned by `_implementation()`.
*
* This function does not return to its internal call site, it will return directly to the external caller.
*/
function _fallback() internal virtual {
_beforeFallback();
_delegate(_implementation());
}
/**
* @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
* function in the contract matches the call data.
*/
fallback() external payable virtual {
_fallback();
}
/**
* @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data
* is empty.
*/
receive() external payable virtual {
_fallback();
}
/**
* @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`
* call, or as part of the Solidity `fallback` or `receive` functions.
*
* If overridden should call `super._beforeFallback()`.
*/
function _beforeFallback() internal virtual {}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/ERC20.sol)
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./extensions/IERC20Metadata.sol";
import "../../utils/Context.sol";
/**
* @dev Implementation of the {IERC20} interface.
*
* This implementation is agnostic to the way tokens are created. This means
* that a supply mechanism has to be added in a derived contract using {_mint}.
* For a generic mechanism see {ERC20PresetMinterPauser}.
*
* TIP: For a detailed writeup see our guide
* https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* We have followed general OpenZeppelin Contracts guidelines: functions revert
* instead returning `false` on failure. This behavior is nonetheless
* conventional and does not conflict with the expectations of ERC20
* applications.
*
* Additionally, an {Approval} event is emitted on calls to {transferFrom}.
* This allows applications to reconstruct the allowance for all accounts just
* by listening to said events. Other implementations of the EIP may not emit
* these events, as it isn't required by the specification.
*
* Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
* functions have been added to mitigate the well-known issues around setting
* allowances. See {IERC20-approve}.
*/
contract ERC20 is Context, IERC20, IERC20Metadata {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
/**
* @dev Sets the values for {name} and {symbol}.
*
* The default value of {decimals} is 18. To select a different value for
* {decimals} you should overload it.
*
* All two of these values are immutable: they can only be set once during
* construction.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev Returns the name of the token.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5.05` (`505 / 10 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei. This is the value {ERC20} uses, unless this function is
* overridden;
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/
function decimals() public view virtual override returns (uint8) {
return 18;
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
/**
* @dev See {IERC20-transfer}.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - the caller must have a balance of at least `amount`.
*/
function transfer(address to, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_transfer(owner, to, amount);
return true;
}
/**
* @dev See {IERC20-allowance}.
*/
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
/**
* @dev See {IERC20-approve}.
*
* NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
* `transferFrom`. This is semantically equivalent to an infinite approval.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function approve(address spender, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_approve(owner, spender, amount);
return true;
}
/**
* @dev See {IERC20-transferFrom}.
*
* Emits an {Approval} event indicating the updated allowance. This is not
* required by the EIP. See the note at the beginning of {ERC20}.
*
* NOTE: Does not update the allowance if the current allowance
* is the maximum `uint256`.
*
* Requirements:
*
* - `from` and `to` cannot be the zero address.
* - `from` must have a balance of at least `amount`.
* - the caller must have allowance for ``from``'s tokens of at least
* `amount`.
*/
function transferFrom(
address from,
address to,
uint256 amount
) public virtual override returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, amount);
_transfer(from, to, amount);
return true;
}
/**
* @dev Atomically increases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
address owner = _msgSender();
_approve(owner, spender, allowance(owner, spender) + addedValue);
return true;
}
/**
* @dev Atomically decreases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `spender` must have allowance for the caller of at least
* `subtractedValue`.
*/
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
address owner = _msgSender();
uint256 currentAllowance = allowance(owner, spender);
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(owner, spender, currentAllowance - subtractedValue);
}
return true;
}
/**
* @dev Moves `amount` of tokens from `from` to `to`.
*
* This internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Emits a {Transfer} event.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `from` must have a balance of at least `amount`.
*/
function _transfer(
address from,
address to,
uint256 amount
) internal virtual {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(from, to, amount);
uint256 fromBalance = _balances[from];
require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[from] = fromBalance - amount;
}
_balances[to] += amount;
emit Transfer(from, to, amount);
_afterTokenTransfer(from, to, amount);
}
/** @dev Creates `amount` tokens and assigns them to `account`, increasing
* the total supply.
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
_balances[account] += amount;
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
/**
* @dev Destroys `amount` tokens from `account`, reducing the
* total supply.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens.
*/
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
}
_totalSupply -= amount;
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
/**
* @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
*
* This internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*/
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
/**
* @dev Updates `owner` s allowance for `spender` based on spent `amount`.
*
* Does not update the allowance amount in case of infinite allowance.
* Revert if not enough allowance is available.
*
* Might emit an {Approval} event.
*/
function _spendAllowance(
address owner,
address spender,
uint256 amount
) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
require(currentAllowance >= amount, "ERC20: insufficient allowance");
unchecked {
_approve(owner, spender, currentAllowance - amount);
}
}
}
/**
* @dev Hook that is called before any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* will be transferred to `to`.
* - when `from` is zero, `amount` tokens will be minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens will be burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
/**
* @dev Hook that is called after any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* has been transferred to `to`.
* - when `from` is zero, `amount` tokens have been minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens have been burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _afterTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol)
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:
* ```
* 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`, and `uint256`._
*/
library StorageSlot {
struct AddressSlot {
address value;
}
struct BooleanSlot {
bool value;
}
struct Bytes32Slot {
bytes32 value;
}
struct Uint256Slot {
uint256 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
}
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
/// @title Interface for depositWithBeneficiary
interface IDepositWithBeneficiary {
/// @notice Make a token transfer that the *signer* is paying tokens but benefits are given to the *beneficiary*
/// @param token The contract address of the transferring token
/// @param amount The amount of the transfer
/// @param beneficiary The address that will receive benefits of this transfer
/// @param data Extra data passed to the contract
/// @return Returns true for a successful transfer.
function depositWithBeneficiary(address token, uint256 amount, address beneficiary, uint64 data)
payable external returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.5.0;
/// @title Minimal ERC20 interface for Uniswap
/// @notice Contains a subset of the full ERC20 interface that is used in Uniswap V3
interface IERC20Minimal {
/// @notice Returns the balance of a token
/// @param account The account for which to look up the number of tokens it has, i.e. its balance
/// @return The number of tokens held by the account
function balanceOf(address account) external view returns (uint256);
/// @notice Transfers the amount of token from the `msg.sender` to the recipient
/// @param recipient The account that will receive the amount transferred
/// @param amount The number of tokens to send from the sender to the recipient
/// @return Returns true for a successful transfer, false for an unsuccessful transfer
function transfer(address recipient, uint256 amount) external returns (bool);
/// @notice Returns the current allowance given to a spender by an owner
/// @param owner The account of the token owner
/// @param spender The account of the token spender
/// @return The current allowance granted by `owner` to `spender`
function allowance(address owner, address spender) external view returns (uint256);
/// @notice Sets the allowance of a spender from the `msg.sender` to the value `amount`
/// @param spender The account which will be allowed to spend a given amount of the owners tokens
/// @param amount The amount of tokens allowed to be used by `spender`
/// @return Returns true for a successful approval, false for unsuccessful
function approve(address spender, uint256 amount) external returns (bool);
/// @notice Transfers `amount` tokens from `sender` to `recipient` up to the allowance given to the `msg.sender`
/// @param sender The account from which the transfer will be initiated
/// @param recipient The recipient of the transfer
/// @param amount The amount of the transfer
/// @return Returns true for a successful transfer, false for unsuccessful
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
/// @notice Event emitted when tokens are transferred from one address to another, either via `#transfer` or `#transferFrom`.
/// @param from The account from which the tokens were sent, i.e. the balance decreased
/// @param to The account to which the tokens were sent, i.e. the balance increased
/// @param value The amount of tokens that were transferred
event Transfer(address indexed from, address indexed to, uint256 value);
/// @notice Event emitted when the approval amount for the spender of a given owner's tokens changes.
/// @param owner The account that approved spending of its tokens
/// @param spender The account for which the spending allowance was modified
/// @param value The new allowance from the owner to the spender
event Approval(address indexed owner, address indexed spender, uint256 value);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import "./MesonManager.sol";
/// @title Meson
/// @notice A plain non-upgradeable Meson
contract Meson is MesonManager {
constructor(address premiumManager) {
_transferOwnership(_msgSender());
_transferPremiumManager(premiumManager);
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import "./Swap/MesonSwap.sol";
import "./Pools/MesonPools.sol";
/// @title MesonManager
/// @notice The class to store data related to management permissions of Meson
contract MesonManager is MesonSwap, MesonPools {
/// @notice The admin of meson contract
/// The owner has the permission to upgrade meson contract. In future versions,
/// the management authority of meson contract will be decentralized.
address internal _owner;
/// @notice The manager to authorized fee waived swaps
/// Only the premium manager can authorize the execution to release for fee waived swaps.
/// This address is managed by Meson team.
address internal _premiumManager;
/// @dev This empty reserved space is put in place to allow future versions to
/// add new variables without shifting down storage in the inheritance chain.
/// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
uint256[50] private __gap;
event OwnerTransferred(address indexed prevOwner, address indexed newOwner);
event PremiumManagerTransferred(address indexed prevPremiumManager, address indexed newPremiumManager);
/// @notice The owner will also have the permission to add supported tokens
function addSupportToken(address token, uint8 index) external onlyOwner {
_addSupportToken(token, index);
}
/// @notice The owner will also have the permission to remove a supported tokens
function removeSupportToken(uint8 index) external onlyOwner {
_removeSupportToken(index);
}
/// @notice Add multiple tokens
function addMultipleSupportedTokens(address[] memory tokens, uint8[] memory indexes) external onlyOwner {
require(tokens.length == indexes.length, "Tokens and indexes should have the same length");
for (uint8 i = 0; i < tokens.length; i++) {
_addSupportToken(tokens[i], indexes[i]);
}
}
function transferOwnership(address newOwner) public onlyOwner {
_transferOwnership(newOwner);
}
function transferPremiumManager(address newPremiumManager) public {
require(_isPremiumManager(), "Caller is not the premium manager");
_transferPremiumManager(newPremiumManager);
}
function withdrawServiceFee(uint8 tokenIndex, uint256 amount, uint40 toPoolIndex) external onlyOwner {
require(ownerOfPool[toPoolIndex] != address(0), "Pool index not registered");
_balanceOfPoolToken[_poolTokenIndexFrom(tokenIndex, 0)] -= amount;
_balanceOfPoolToken[_poolTokenIndexFrom(tokenIndex, toPoolIndex)] += amount;
}
function adjustToPool(uint8 tokenIndex, uint256 amount, uint40 toPoolIndex) external onlyOwner {
require(ownerOfPool[toPoolIndex] != address(0), "Pool index not registered");
_balanceOfPoolToken[_poolTokenIndexFrom(tokenIndex, toPoolIndex)] += amount;
}
modifier onlyOwner() {
require(_owner == _msgSender(), "Caller is not the owner");
_;
}
function _transferOwnership(address newOwner) internal {
require(newOwner != address(0), "New owner cannot be zero address");
address prevOwner = _owner;
_owner = newOwner;
emit OwnerTransferred(prevOwner, newOwner);
}
function _isPremiumManager() internal view override returns (bool) {
return _premiumManager == _msgSender();
}
function _transferPremiumManager(address newPremiumManager) internal {
require(newPremiumManager != address(0), "New premium manager be zero address");
address prevPremiumManager = _premiumManager;
_premiumManager = newPremiumManager;
emit PremiumManagerTransferred(prevPremiumManager, newPremiumManager);
}
function directSwap(uint256 encodedSwap, address recipient, bytes32 r, bytes32 yParityAndS)
external matchProtocolVersion(encodedSwap) verifyEncodedSwap(encodedSwap) forTargetChain(encodedSwap)
{
require(recipient != address(0), "Recipient cannot be zero address");
bytes32 digest = keccak256(abi.encodePacked(encodedSwap, recipient));
_checkSignature(digest, r, yParityAndS, _premiumManager);
uint256 amount = _amountFrom(encodedSwap);
uint8 inTokenIndex = _inTokenIndexFrom(encodedSwap);
uint256 releaseAmount = amount - _feeForLp(encodedSwap);
_balanceOfPoolToken[_poolTokenIndexFrom(inTokenIndex, 1)] += amount;
_balanceOfPoolToken[_poolTokenIndexForOutToken(encodedSwap, 1)] -= releaseAmount;
_unsafeDepositToken(inTokenIndex, _msgSender(), amount);
_release(encodedSwap, _outTokenIndexFrom(encodedSwap), _msgSender(), recipient, releaseAmount);
emit SwapReleased(encodedSwap);
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
/// @title MesonPools Interface
interface IMesonPoolsEvents {
/// @notice Event when an LP pool is registered.
/// Emit at the end of `depositAndRegister()` calls.
/// @param poolIndex Pool index
/// @param owner Pool owner
event PoolRegistered(uint40 indexed poolIndex, address owner);
/// @notice Event when fund was deposited to an LP pool.
/// Emit at the end of `depositAndRegister()` and `deposit()` calls.
/// @param poolTokenIndex Concatenation of pool index & token index
/// @param amount The amount of tokens to be added to the pool
event PoolDeposited(uint48 indexed poolTokenIndex, uint256 amount);
/// @notice Event when fund was withdrawn from an LP pool.
/// Emit at the end of `withdraw()` calls.
/// @param poolTokenIndex Concatenation of pool index & token index
/// @param amount The amount of tokens to be removed from the pool
event PoolWithdrawn(uint48 indexed poolTokenIndex, uint256 amount);
/// @notice Event when an authorized address was added for an LP pool.
/// Emit at the end of `depositAndRegister()` calls.
/// @param poolIndex Pool index
/// @param addr Authorized address to be added
event PoolAuthorizedAddrAdded(uint40 indexed poolIndex, address addr);
/// @notice Event when an authorized address was removed for an LP pool.
/// Emit at the end of `depositAndRegister()` calls.
/// @param poolIndex Pool index
/// @param addr Authorized address to be removed
event PoolAuthorizedAddrRemoved(uint40 indexed poolIndex, address addr);
/// @notice Event when the ownership of a pool was transferred.
/// Emit at the end of `transferPoolOwner()` calls.
/// @param poolIndex Pool index
/// @param prevOwner Previous owner of the pool
/// @param newOwner New owner of the pool
event PoolOwnerTransferred(uint40 indexed poolIndex, address prevOwner, address newOwner);
/// @notice Event when a swap was locked.
/// Emit at the end of `lock()` and `lockSwap()` calls.
/// @param encodedSwap Encoded swap
event SwapLocked(uint256 indexed encodedSwap);
/// @notice Event when a swap was unlocked.
/// Emit at the end of `unlock()` calls.
/// @param encodedSwap Encoded swap
event SwapUnlocked(uint256 indexed encodedSwap);
/// @notice Event when a swap was released.
/// Emit at the end of `release()`, `directRelease()` calls.
/// @param encodedSwap Encoded swap
event SwapReleased(uint256 indexed encodedSwap);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import "./IMesonPoolsEvents.sol";
import "../utils/MesonStates.sol";
/// @title MesonPools
/// @notice The class to manage pools for LPs, and perform swap operations on the target
/// chain side.
/// Methods in this class will be executed when a user wants to swap into this chain.
/// LP pool operations are also provided in this class.
contract MesonPools is IMesonPoolsEvents, MesonStates {
/// @notice Locked Swaps
/// key: `swapId` is calculated from `encodedSwap` and `initiator`. See `_getSwapId` in `MesonHelpers.sol`
/// encodedSwap: see `MesonSwap.sol` for defination;
/// initiator: The user address who created and signed the swap request.
/// value: `lockedSwap` in format of `until:uint40|poolIndex:uint40`
/// until: The expiration time of this swap on the target chain. Need to `release` the swap fund before `until`;
/// poolIndex: The index of an LP pool. See `ownerOfPool` in `MesonStates.sol` for more information.
mapping(bytes32 => uint80) internal _lockedSwaps;
/// @dev This empty reserved space is put in place to allow future versions to
/// add new variables without shifting down storage in the inheritance chain.
/// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
uint256[50] private __gap;
/// @notice Initially deposit tokens into an LP pool and register a pool index.
/// This is the prerequisite for LPs if they want to participate in Meson swaps.
/// @dev Designed to be used by a new address who wants to be an LP and register a pool index
/// @param amount The amount of tokens to be added to the pool
/// @param poolTokenIndex In format of `tokenIndex:uint8|poolIndex:uint40`. See `_balanceOfPoolToken` in `MesonStates.sol` for more information.
function depositAndRegister(uint256 amount, uint48 poolTokenIndex) payable external {
require(amount > 0, "Amount must be positive");
address poolOwner = _msgSender();
uint40 poolIndex = _poolIndexFrom(poolTokenIndex);
require(poolIndex != 0, "Cannot use 0 as pool index"); // pool 0 is reserved for meson service fee
require(ownerOfPool[poolIndex] == address(0), "Pool index already registered");
require(poolOfAuthorizedAddr[poolOwner] == 0, "Signer address already registered");
ownerOfPool[poolIndex] = poolOwner;
poolOfAuthorizedAddr[poolOwner] = poolIndex;
_balanceOfPoolToken[poolTokenIndex] += amount;
uint8 tokenIndex = _tokenIndexFrom(poolTokenIndex);
_unsafeDepositToken(tokenIndex, poolOwner, amount);
emit PoolRegistered(poolIndex, poolOwner);
emit PoolDeposited(poolTokenIndex, amount);
}
/// @notice Deposit tokens into the liquidity pool.
/// The LP should be careful to make sure the `poolTokenIndex` is correct.
/// Make sure to call `depositAndRegister` first and register a pool index.
/// Otherwise, token may be deposited to others.
/// @dev Designed to be used by addresses authorized to a pool
/// @param amount The amount of tokens to be added to the pool
/// @param poolTokenIndex In format of `tokenIndex:uint8|poolIndex:uint40`. See `_balanceOfPoolToken` in `MesonStates.sol` for more information.
function deposit(uint256 amount, uint48 poolTokenIndex) payable external {
require(amount > 0, "Amount must be positive");
uint40 poolIndex = _poolIndexFrom(poolTokenIndex);
require(poolIndex != 0, "Cannot use 0 as pool index"); // pool 0 is reserved for meson service fee
require(poolIndex == poolOfAuthorizedAddr[_msgSender()], "Need an authorized address as the signer");
_balanceOfPoolToken[poolTokenIndex] += amount;
uint8 tokenIndex = _tokenIndexFrom(poolTokenIndex);
_unsafeDepositToken(tokenIndex, _msgSender(), amount);
emit PoolDeposited(poolTokenIndex, amount);
}
/// @notice Withdraw tokens from the liquidity pool.
/// @dev Designed to be used by LPs (pool owners) who have already registered a pool index
/// @param amount The amount to be removed from the pool
/// @param poolTokenIndex In format of `tokenIndex:uint8|poolIndex:uint40. See `_balanceOfPoolToken` in `MesonStates.sol` for more information.
function withdraw(uint256 amount, uint48 poolTokenIndex) external {
require(amount > 0, "Amount must be positive");
uint40 poolIndex = _poolIndexFrom(poolTokenIndex);
require(poolIndex != 0, "Cannot use 0 as pool index"); // pool 0 is reserved for meson service fee
require(ownerOfPool[poolIndex] == _msgSender(), "Need the pool owner as the signer");
_balanceOfPoolToken[poolTokenIndex] -= amount;
uint8 tokenIndex = _tokenIndexFrom(poolTokenIndex);
_safeTransfer(tokenIndex, _msgSender(), amount);
emit PoolWithdrawn(poolTokenIndex, amount);
}
/// @notice Add an authorized address to the pool
/// @dev Designed to be used by LPs (pool owners)
/// @param addr The address to be added
function addAuthorizedAddr(address addr) external {
address poolOwner = _msgSender();
uint40 poolIndex = poolOfAuthorizedAddr[poolOwner];
require(poolIndex != 0, "The signer does not register a pool");
require(poolOwner == ownerOfPool[poolIndex], "Need the pool owner as the signer");
require(poolOfAuthorizedAddr[addr] == 0, "Addr is authorized for another pool");
poolOfAuthorizedAddr[addr] = poolIndex;
emit PoolAuthorizedAddrAdded(poolIndex, addr);
}
/// @notice Remove an authorized address from the pool
/// @dev Designed to be used by LPs (pool owners)
/// @param addr The address to be removed
function removeAuthorizedAddr(address addr) external {
address poolOwner = _msgSender();
uint40 poolIndex = poolOfAuthorizedAddr[poolOwner];
require(poolIndex != 0, "The signer does not register a pool");
require(poolOwner == ownerOfPool[poolIndex], "Need the pool owner as the signer");
require(poolOfAuthorizedAddr[addr] == poolIndex, "Addr is not authorized for the signer's pool");
delete poolOfAuthorizedAddr[addr];
emit PoolAuthorizedAddrRemoved(poolIndex, addr);
}
/// @notice Transfer the ownership of a pool to another address
/// @dev Designed to be used by LPs (pool owners)
/// @param addr The new address to be the pool owner
function transferPoolOwner(address addr) external {
address poolOwner = _msgSender();
uint40 poolIndex = poolOfAuthorizedAddr[poolOwner];
require(poolIndex != 0, "The signer does not register a pool");
require(poolOwner == ownerOfPool[poolIndex], "Need the pool owner as the signer");
require(poolOfAuthorizedAddr[addr] == poolIndex, "Addr is not authorized for the signer's pool");
ownerOfPool[poolIndex] = addr;
emit PoolOwnerTransferred(poolIndex, poolOwner, addr);
}
function lock(uint256 encodedSwap, bytes32, bytes32, address initiator) external {
// deprecated
lockSwap(encodedSwap, initiator);
}
/// @notice Lock funds to match a swap request. This is step 2️⃣ in a swap.
/// The authorized address of the bonding pool should call this method,
/// which will lock swapping fund on the target chain for `LOCK_TIME_PERIOD`
/// and wait for fund release and execution.
/// @dev Designed to be used by authorized addresses or pool owners
/// @param encodedSwap Encoded swap information
/// @param initiator The swap initiator who created and signed the swap request
function lockSwap(uint256 encodedSwap, address initiator)
public matchProtocolVersion(encodedSwap) forTargetChain(encodedSwap)
{
bytes32 swapId = _getSwapId(encodedSwap, initiator);
require(_lockedSwaps[swapId] == 0, "Swap already exists");
uint40 poolIndex = poolOfAuthorizedAddr[_msgSender()];
require(poolIndex != 0, "Caller not registered. Call depositAndRegister.");
uint256 until = block.timestamp + LOCK_TIME_PERIOD;
require(until < _expireTsFrom(encodedSwap) - 5 minutes, "Cannot lock because expireTs is soon.");
uint48 poolTokenIndex = _poolTokenIndexForOutToken(encodedSwap, poolIndex);
_balanceOfPoolToken[poolTokenIndex] -= _amountToLock(encodedSwap); // The service fee will be charged on release
uint256 coreAmount = _coreTokenAmount(encodedSwap);
if (coreAmount > 0) {
_balanceOfPoolToken[_poolTokenIndexFrom(indexOfToken[address(1)], poolIndex)] -= coreAmount;
}
_lockedSwaps[swapId] = _lockedSwapFrom(until, poolIndex);
emit SwapLocked(encodedSwap);
}
/// @notice If the locked swap is not released after `LOCK_TIME_PERIOD`,
/// the authorized address can call this method to unlock the swapping fund.
/// @dev Designed to be used by authorized addresses or pool owners
/// @param encodedSwap Encoded swap information
/// @param initiator The swap initiator who created and signed the swap request
function unlock(uint256 encodedSwap, address initiator) external {
bytes32 swapId = _getSwapId(encodedSwap, initiator);
uint80 lockedSwap = _lockedSwaps[swapId];
require(lockedSwap > 1, "Swap does not exist");
require(_untilFromLocked(lockedSwap) < block.timestamp, "Swap still in lock");
uint40 poolIndex = _poolIndexFromLocked(lockedSwap);
uint48 poolTokenIndex = _poolTokenIndexForOutToken(encodedSwap, poolIndex);
_balanceOfPoolToken[poolTokenIndex] += _amountToLock(encodedSwap);
uint256 coreAmount = _coreTokenAmount(encodedSwap);
if (coreAmount > 0) {
_balanceOfPoolToken[_poolTokenIndexFrom(indexOfToken[address(1)], poolIndex)] += coreAmount;
}
delete _lockedSwaps[swapId];
emit SwapUnlocked(encodedSwap);
}
/// @notice Release tokens to satisfy a locked swap. This is step 3️⃣ in a swap.
/// This method requires a release signature from the swap initiator,
/// but anyone (initiator herself, the LP, and other people) with the signature
/// can call this method to make sure the swapping fund is guaranteed to be released.
/// @dev Designed to be used by anyone
/// @param encodedSwap Encoded swap information
/// @param r Part of the release signature (same as in the `executeSwap` call)
/// @param yParityAndS Part of the release signature (same as in the `executeSwap` call)
/// @param initiator The swap initiator who created and signed the swap request
/// @param recipient The recipient address of the swap
function release(
uint256 encodedSwap,
bytes32 r,
bytes32 yParityAndS,
address initiator,
address recipient
) external {
require(_msgSender() == tx.origin, "Cannot be called through contracts");
require(_expireTsFrom(encodedSwap) > block.timestamp, "Cannot release because expired");
require(recipient != address(0), "Recipient cannot be zero address");
bool feeWaived = _feeWaived(encodedSwap);
if (feeWaived) {
// For swaps that service fee is waived, need the premium manager as the signer
require(_isPremiumManager(), "Caller is not the premium manager");
}
// For swaps that charge service fee, anyone can call
bytes32 swapId = _getSwapId(encodedSwap, initiator);
require(_lockedSwaps[swapId] > 1, "Swap does not exist");
_checkReleaseSignature(encodedSwap, recipient, r, yParityAndS, initiator);
_lockedSwaps[swapId] = 1;
// LP fee will be subtracted from the swap amount
uint256 releaseAmount = _amountToLock(encodedSwap);
if (!feeWaived) { // If the swap should pay service fee (charged by Meson protocol)
uint256 serviceFee = _serviceFee(encodedSwap);
// Subtract service fee from the release amount
releaseAmount -= serviceFee;
// Collected service fee will be stored in `_balanceOfPoolToken` with `poolIndex = 0`.
// Currently, no one is capable to withdraw fund from pool 0. In the future, Meson protocol
// will specify the purpose of service fee and its usage permission, and upgrade the contract
// accordingly.
_balanceOfPoolToken[_poolTokenIndexForOutToken(encodedSwap, 0)] += serviceFee;
}
uint256 amountToShare = _amountToShare(encodedSwap);
if (amountToShare > 0) {
releaseAmount -= amountToShare;
_balanceOfPoolToken[_poolTokenIndexForOutToken(encodedSwap, _poolIndexToShare(encodedSwap))] += amountToShare;
}
uint256 coreAmount = _coreTokenAmount(encodedSwap);
if (coreAmount > 0) {
_transferCoreToken(recipient, coreAmount);
}
_release(encodedSwap, _outTokenIndexFrom(encodedSwap), initiator, recipient, releaseAmount);
emit SwapReleased(encodedSwap);
}
function directRelease(
uint256 encodedSwap,
bytes32 r,
bytes32 yParityAndS,
address initiator,
address recipient
) external matchProtocolVersion(encodedSwap) forTargetChain(encodedSwap) {
require(_msgSender() == tx.origin, "Cannot be called through contracts");
require(recipient != address(0), "Recipient cannot be zero address");
bool feeWaived = _feeWaived(encodedSwap);
if (feeWaived) {
require(_isPremiumManager(), "Caller is not the premium manager");
}
bytes32 swapId = _getSwapId(encodedSwap, initiator);
require(_lockedSwaps[swapId] == 0, "Swap already exists");
uint40 poolIndex = poolOfAuthorizedAddr[_msgSender()];
require(poolIndex != 0, "Caller not registered. Call depositAndRegister.");
if (r != bytes32(0x0)) {
require(_expireTsFrom(encodedSwap) > block.timestamp, "Cannot release because expired");
_checkReleaseSignature(encodedSwap, recipient, r, yParityAndS, initiator);
} else if (!feeWaived) {
require(_isPremiumManager(), "Caller is not the premium manager");
}
_lockedSwaps[swapId] = 1;
uint256 releaseAmount = _amountToLock(encodedSwap);
_balanceOfPoolToken[_poolTokenIndexForOutToken(encodedSwap, poolIndex)] -= releaseAmount;
if (!feeWaived) {
uint256 serviceFee = _serviceFee(encodedSwap);
releaseAmount -= serviceFee;
_balanceOfPoolToken[_poolTokenIndexForOutToken(encodedSwap, 0)] += serviceFee;
}
uint256 amountToShare = _amountToShare(encodedSwap);
if (amountToShare > 0) {
releaseAmount -= amountToShare;
_balanceOfPoolToken[_poolTokenIndexForOutToken(encodedSwap, _poolIndexToShare(encodedSwap))] += amountToShare;
}
uint256 coreAmount = _coreTokenAmount(encodedSwap);
if (coreAmount > 0) {
_balanceOfPoolToken[_poolTokenIndexFrom(indexOfToken[address(1)], poolIndex)] -= coreAmount;
_transferCoreToken(recipient, coreAmount);
}
_release(encodedSwap, _outTokenIndexFrom(encodedSwap), initiator, recipient, releaseAmount);
emit SwapReleased(encodedSwap);
}
function _release(uint256 encodedSwap, uint8 tokenIndex, address initiator, address recipient, uint256 amount) internal {
if (_willTransferToContract(encodedSwap)) {
_transferToContract(tokenIndex, recipient, initiator, amount, _saltDataFrom(encodedSwap));
} else if (amount > 0) {
_safeTransfer(tokenIndex, recipient, amount);
if ((SHORT_COIN_TYPE == 0x9296 || SHORT_COIN_TYPE == 0xb4b1 || SHORT_COIN_TYPE == 0x6c62) && _swapForCoreToken(encodedSwap)) {
_callSkaleFaucet(recipient);
}
}
}
function _callSkaleFaucet(address recipient) private {
if (SHORT_COIN_TYPE == 0x9296) {
// SKALE Europa
bytes memory data = abi.encodeWithSelector(bytes4(0x6a627842), recipient);
(bool success, ) = address(0x2B267A3e49b351DEdac892400a530ABb2f899d23).call(data);
require(success, "Call faucet not successful");
} else if (SHORT_COIN_TYPE == 0xb4b1) {
// SKALE Nebula
bytes memory data = abi.encodeWithSelector(bytes4(0x0c11dedd), recipient);
(bool success, ) = address(0x5a6869ef5b81DCb58EBF51b8F893c31f5AFE3Fa8).call(data);
require(success, "Call faucet not successful");
} else if (SHORT_COIN_TYPE == 0x6c62) {
// SKALE Calypso
bytes memory data = abi.encodeWithSelector(bytes4(0x0c11dedd), recipient);
(bool success, ) = address(0x02891b34B7911A9C68e82C193cd7A6fBf0c3b30A).call(data);
require(success, "Call faucet not successful");
}
}
/// @notice Read information for a locked swap
function getLockedSwap(uint256 encodedSwap, address initiator) external view
returns (address poolOwner, uint40 until)
{
bytes32 swapId = _getSwapId(encodedSwap, initiator);
uint80 lockedSwap = _lockedSwaps[swapId];
if (lockedSwap == 1) {
poolOwner = address(1);
until = 0;
} else {
poolOwner = ownerOfPool[_poolIndexFromLocked(lockedSwap)];
until = uint40(_untilFromLocked(lockedSwap));
}
}
modifier forTargetChain(uint256 encodedSwap) {
require(_outChainFrom(encodedSwap) == SHORT_COIN_TYPE, "Swap not for this chain");
_;
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
import "./UpgradableMeson.sol";
// Some blockchains do not support deploying another contract in constructor
contract Proxy2ToMeson is ERC1967Proxy {
bytes4 private constant INITIALIZE_SELECTOR = bytes4(keccak256("initialize(address,address)"));
constructor(address implAddress, address premiumManager) ERC1967Proxy(implAddress, _encodeData(msg.sender, premiumManager)) {}
function _encodeData(address owner, address premiumManager) private pure returns (bytes memory) {
return abi.encodeWithSelector(INITIALIZE_SELECTOR, owner, premiumManager);
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
import "./UpgradableMeson.sol";
contract ProxyToMeson is ERC1967Proxy {
bytes4 private constant INITIALIZE_SELECTOR = bytes4(keccak256("initialize(address,address)"));
constructor(address premiumManager) ERC1967Proxy(_deployImpl(), _encodeData(msg.sender, premiumManager)) {}
function _deployImpl() private returns (address) {
UpgradableMeson _impl = new UpgradableMeson();
return address(_impl);
}
function _encodeData(address owner, address premiumManager) private pure returns (bytes memory) {
return abi.encodeWithSelector(INITIALIZE_SELECTOR, owner, premiumManager);
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
/// @title MesonSwapEvents Interface
interface IMesonSwapEvents {
/// @notice Event when a swap request was posted.
/// Emit at the end of `postSwap()` and `postSwapWithSignature()` calls.
/// @param encodedSwap Encoded swap
event SwapPosted(uint256 indexed encodedSwap);
/// @notice Event when a swap request was bonded.
/// Emit at the end of `bondSwap()` calls.
/// @param encodedSwap Encoded swap
event SwapBonded(uint256 indexed encodedSwap);
/// @notice Event when a swap request was cancelled.
/// Emit at the end of `cancelSwap()` and `cancelSwapTo()` calls.
/// @param encodedSwap Encoded swap
event SwapCancelled(uint256 indexed encodedSwap);
/// @notice Event when a swap request was executed.
/// Emit at the end of `executeSwap()`, `directExecuteSwap()` and `simpleExecuteSwap()` calls.
/// @param encodedSwap Encoded swap
event SwapExecuted(uint256 indexed encodedSwap);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import "./IMesonSwapEvents.sol";
import "../utils/MesonStates.sol";
/// @title MesonSwap
/// @notice The class to receive and process swap requests on the initial chain side.
/// Methods in this class will be executed by swap initiators or LPs
/// on the initial chain of swaps.
contract MesonSwap is IMesonSwapEvents, MesonStates {
/// @notice Posted Swaps
/// key: `encodedSwap` in format of `version:uint8|amount:uint40|salt:uint80|fee:uint40|expireTs:uint40|outChain:uint16|outToken:uint8|inChain:uint16|inToken:uint8`
/// version: Version of encoding
/// amount: The amount of tokens of this swap, always in decimal 6. The amount of a swap is capped at $100k so it can be safely encoded in uint48;
/// salt: The salt value of this swap, carrying some information below:
/// salt & 0x80000000000000000000 == true => will release to an EOA address, otherwise a smart contract;
/// salt & 0x40000000000000000000 == true => will waive *service fee*;
/// salt & 0x30000000000000000000 == 0x3. => from TransferToMesonContract;
/// salt & 0x30000000000000000000 == 0x2. => meson.to;
/// salt & 0x30000000000000000000 == 0x1. => API;
/// salt & 0x08000000000000000000 == true => use *non-typed signing* (some wallets such as hardware wallets don't support EIP-712v1);
/// salt & 0x04000000000000000000 == true => swap for core token (n/a for releasing to contract);
/// salt & 0xfffff00000000000 => price for core token;
/// salt & 0x00000fff00000000 => amount for core token;
/// salt & 0x02000000000000000000 == true => share some release amount to partner;
/// salt & 0xffff000000000000 + 65536 => pool index to share;
/// salt & 0x0000ffff00000000 => amount to share;
/// salt & 0x01000000000000000000 == true => use points to waive service fee;
/// in reality, the salt header would be 0x41
/// salt & 0x0000ffffffffffffffff: customized data that can be passed to integrated 3rd-party smart contract;
/// fee: The fee given to LPs (liquidity providers). An extra service fee maybe charged afterwards;
/// expireTs: The expiration time of this swap on the initial chain. The LP should `executeSwap` and receive his funds before `expireTs`;
/// outChain: The target chain of a cross-chain swap (given by the last 2 bytes of SLIP-44);
/// outToken: The index of the token on the target chain. See `tokenForIndex` in `MesonToken.sol`;
/// inChain: The initial chain of a cross-chain swap (given by the last 2 bytes of SLIP-44);
/// inToken: The index of the token on the initial chain. See `tokenForIndex` in `MesonToken.sol`.
/// value: `postedSwap` in format of `tokenNotFromInitiator:byte1|initiator:address|poolIndex:uint40`
/// tokenNotFromInitiator: Token not from initiator (usually sent from a smart contract);
/// initiator: The swap initiator who created and signed the swap request (not necessarily the one who posted the swap);
// poolIndex: The index of an LP pool. See `ownerOfPool` in `MesonStates.sol` for more information.
mapping(uint256 => uint208) internal _postedSwaps;
/// @dev This empty reserved space is put in place to allow future versions to
/// add new variables without shifting down storage in the inheritance chain.
/// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
uint256[50] private __gap;
function postSwap(uint256 encodedSwap, address initiator, uint40 poolIndex)
payable public matchProtocolVersion(encodedSwap) verifyEncodedSwap(encodedSwap)
{
_postedSwaps[encodedSwap] = _postedSwapFrom(initiator, poolIndex, _msgSender() != initiator);
uint8 tokenIndex = _inTokenIndexFrom(encodedSwap);
_unsafeDepositToken(tokenIndex, _msgSender(), _amountFrom(encodedSwap));
emit SwapPosted(encodedSwap);
}
/// @notice Anyone can call this method to post a swap request. This is step 1️⃣ in a swap.
/// The r,s,v signature must be signed by the swap initiator. The initiator can call
/// this method directly, in which case `poolIndex` should be zero and wait for LPs
/// to call `bondSwap`. Initiators can also send the swap requests offchain (through the
/// meson relayer service). An LP (pool owner or authorized addresses) who receives requests through
/// the relayer can call this method to post and bond the swap in a single contract execution,
/// in which case he should give his own `poolIndex`.
///
/// The swap will last until `expireTs` and at most one LP pool can bond to it.
/// After the swap expires, the initiator can cancel the swap and withdraw funds.
///
/// Once a swap is posted and bonded, the bonding LP should call `lock` on the target chain.
///
/// @dev Designed to be used by both swap initiators, pool owner, or authorized addresses
/// @param encodedSwap Encoded swap information; also used as the key of `_postedSwaps`
/// @param r Part of the signature
/// @param yParityAndS Part of the signature
/// @param initiator Initiator
/// @param poolIndex Pool index
function postSwapWithSignature(uint256 encodedSwap, bytes32 r, bytes32 yParityAndS, address initiator, uint40 poolIndex)
external matchProtocolVersion(encodedSwap) verifyEncodedSwap(encodedSwap)
{
if (poolIndex > 0 && _msgSender() != initiator) {
// If pool index is given, the signer should be the initiator or an authorized address
require(poolOfAuthorizedAddr[_msgSender()] == poolIndex, "Signer should be an authorized address of the given pool");
} // Otherwise, this is posted without bonding to a specific pool. Need to execute `bondSwap` later
_checkRequestSignature(encodedSwap, r, yParityAndS, initiator);
_postedSwaps[encodedSwap] = _postedSwapFrom(initiator, poolIndex, false);
uint8 tokenIndex = _inTokenIndexFrom(encodedSwap);
_unsafeDepositToken(tokenIndex, initiator, _amountFrom(encodedSwap));
emit SwapPosted(encodedSwap);
}
// deprecated
function postSwapFromInitiator(uint256 encodedSwap, uint200 postingValue) payable external {
postSwap(encodedSwap, _initiatorFromPosted(postingValue), _poolIndexFromPosted(postingValue));
}
/// @notice If `postSwap` is called by the initiator of the swap and `poolIndex`
/// is zero, an LP (pool owner or authorized addresses) can call this to bond the swap to himself.
/// @dev Designed to be used by pool owner or authorized addresses
/// @param encodedSwap Encoded swap information; also used as the key of `_postedSwaps`
/// @param poolIndex The index of an LP pool. See `ownerOfPool` in `MesonStates.sol` for more information.
function bondSwap(uint256 encodedSwap, uint40 poolIndex) external {
uint208 postedSwap = _postedSwaps[encodedSwap];
require(postedSwap > 1, "Swap does not exist");
require(_poolIndexFromPosted(postedSwap) == 0, "Swap bonded to another pool");
require(poolOfAuthorizedAddr[_msgSender()] == poolIndex, "Signer should be an authorized address of the given pool");
_postedSwaps[encodedSwap] = postedSwap | poolIndex;
emit SwapBonded(encodedSwap);
}
/// @notice Cancel a swap. The swap initiator can call this method to withdraw funds
/// from an expired swap request.
/// @dev Designed to be used by swap initiators
/// @param encodedSwap Encoded swap information; also used as the key of `_postedSwaps`
function cancelSwap(uint256 encodedSwap) external {
uint208 postedSwap = _postedSwaps[encodedSwap];
require(postedSwap > 1, "Swap does not exist");
require(_expireTsFrom(encodedSwap) < block.timestamp, "Swap is still locked");
require((postedSwap >> 200) == 0, "Swap token not from initiator");
delete _postedSwaps[encodedSwap]; // Swap expired so the same one cannot be posted again
uint8 tokenIndex = _inTokenIndexFrom(encodedSwap);
_safeTransfer(tokenIndex, _initiatorFromPosted(postedSwap), _amountFrom(encodedSwap));
emit SwapCancelled(encodedSwap);
}
function cancelSwapTo(uint256 encodedSwap, address recipient) external {
require(_isPremiumManager(), "Caller is not the premium manager");
uint208 postedSwap = _postedSwaps[encodedSwap];
require(postedSwap > 1, "Swap does not exist");
require(_expireTsFrom(encodedSwap) < block.timestamp, "Swap is still locked");
delete _postedSwaps[encodedSwap]; // Swap expired so the same one cannot be posted again
uint8 tokenIndex = _inTokenIndexFrom(encodedSwap);
_safeTransfer(tokenIndex, recipient, _amountFrom(encodedSwap));
emit SwapCancelled(encodedSwap);
}
/// @notice Execute the swap by providing a release signature. This is step 4️⃣ in a swap.
/// Once the signature is verified, the current bonding pool will receive funds deposited
/// by the swap initiator.
/// @dev Designed to be used by pool owner or authorized addresses of the current bonding pool
/// @param encodedSwap Encoded swap information; also used as the key of `_postedSwaps`
/// @param r Part of the release signature (same as in the `release` call)
/// @param yParityAndS Part of the release signature (same as in the `release` call)
/// @param recipient The recipient address of the swap
/// @param depositToPool Whether to deposit funds to the pool (will save gas)
function executeSwap(
uint256 encodedSwap,
bytes32 r,
bytes32 yParityAndS,
address recipient,
bool depositToPool
) external {
uint208 postedSwap = _postedSwaps[encodedSwap];
require(postedSwap > 1, "Swap does not exist");
// Swap expiredTs < current + MIN_BOND_TIME_PERIOD
if (_expireTsFrom(encodedSwap) < block.timestamp + MIN_BOND_TIME_PERIOD) {
// The swap cannot be posted again and therefore safe to remove it.
// LPs who execute in this mode can save ~5000 gas.
delete _postedSwaps[encodedSwap];
} else {
// The same swap information can be posted again, so set `_postedSwaps` value to 1 to prevent that.
_postedSwaps[encodedSwap] = 1;
}
_checkReleaseSignature(encodedSwap, recipient, r, yParityAndS, _initiatorFromPosted(postedSwap));
uint8 tokenIndex = _inTokenIndexFrom(encodedSwap);
uint40 poolIndex = _poolIndexFromPosted(postedSwap);
if (depositToPool) {
_balanceOfPoolToken[_poolTokenIndexFrom(tokenIndex, poolIndex)] += _amountFrom(encodedSwap);
} else {
_safeTransfer(tokenIndex, ownerOfPool[poolIndex], _amountFrom(encodedSwap));
}
emit SwapExecuted(encodedSwap);
}
function directExecuteSwap(
uint256 encodedSwap,
bytes32 r,
bytes32 yParityAndS,
address initiator,
address recipient
) payable external matchProtocolVersion(encodedSwap) verifyEncodedSwap(encodedSwap) {
_checkReleaseSignature(encodedSwap, recipient, r, yParityAndS, initiator);
_postedSwaps[encodedSwap] = 1;
uint256 amount = _amountFrom(encodedSwap);
uint8 tokenIndex = _inTokenIndexFrom(encodedSwap);
_balanceOfPoolToken[_poolTokenIndexFrom(tokenIndex, 1)] += amount;
_unsafeDepositToken(tokenIndex, initiator, amount);
emit SwapExecuted(encodedSwap);
}
function simpleExecuteSwap(uint256 encodedSwap)
payable external matchProtocolVersion(encodedSwap) verifyEncodedSwap(encodedSwap)
{
_postedSwaps[encodedSwap] = 1;
uint256 amount = _amountFrom(encodedSwap);
uint8 tokenIndex = _inTokenIndexFrom(encodedSwap);
_balanceOfPoolToken[_poolTokenIndexFrom(tokenIndex, 1)] += amount;
_unsafeDepositToken(tokenIndex, _msgSender(), amount);
emit SwapExecuted(encodedSwap);
}
/// @notice Read information for a posted swap
function getPostedSwap(uint256 encodedSwap) external view
returns (address initiator, address poolOwner, bool exist)
{
uint208 postedSwap = _postedSwaps[encodedSwap];
initiator = _initiatorFromPosted(postedSwap);
exist = postedSwap > 0;
if (initiator == address(0)) {
poolOwner = address(0);
} else {
poolOwner = ownerOfPool[_poolIndexFromPosted(postedSwap)];
}
}
modifier verifyEncodedSwap(uint256 encodedSwap) {
require(_inChainFrom(encodedSwap) == SHORT_COIN_TYPE, "Swap not for this chain");
require(
_tokenType(_inTokenIndexFrom(encodedSwap)) == _tokenType(_outTokenIndexFrom(encodedSwap)),
"In & out token types do not match"
);
require(_postedSwaps[encodedSwap] == 0, "Swap already exists");
require(_amountFrom(encodedSwap) <= MAX_SWAP_AMOUNT, "For security reason, amount cannot be greater than 100k");
uint256 delta = _expireTsFrom(encodedSwap) - block.timestamp;
require(delta > MIN_BOND_TIME_PERIOD, "Expire ts too early");
require(delta < MAX_BOND_TIME_PERIOD, "Expire ts too late");
_;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IERC20 {
function transferFrom(address from, address to, uint256 value) external returns (bool);
function approve(address spender, uint256 value) external returns (bool);
}
interface UniswapV3SwapRouter {
struct ExactInputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
}
function exactInput(ExactInputParams calldata params)
external
payable
returns (uint256 amountOut);
}
contract CfxSwapAxCNHProxy {
UniswapV3SwapRouter constant ROUTER = UniswapV3SwapRouter(0x3B02e356d09E758E2711bC64CF33e48f3E1239b8);
bytes constant PATH = hex"fe97e85d13abd9c1c33384e796f10b73905637ce0001f470bfd7f7eadf9b9827541272589a6b2bb760ae2e";
function depositWithBeneficiary(
address token,
uint256 amount,
address beneficiary,
uint64 data
) payable external returns (bool) {
if (token == address(0)) {
revert("ETH not supported");
} else {
IERC20(token).transferFrom(msg.sender, address(this), amount);
IERC20(token).approve(address(ROUTER), amount);
// Build params with constant path
UniswapV3SwapRouter.ExactInputParams memory params = UniswapV3SwapRouter.ExactInputParams({
path: PATH,
recipient: beneficiary,
deadline: block.timestamp + 10 minutes,
amountIn: amount,
amountOutMinimum: amount * (data >> 32) / 1e6 / 1e12
});
ROUTER.exactInput(params);
}
return true;
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import "../interfaces/IERC20Minimal.sol";
import "../interfaces/IDepositWithBeneficiary.sol";
/// @notice A sample of 3rd-party dapp that interacts with meson
/// With `depositWithBeneficiary`, the meson contract will be able
/// to deposit cross-chain'ed stablecoins to the 3rd-party dapp contract
/// on behalf of the user. The user will receive the benefits corresponding
/// to this deposit.
contract ForwardTokenContract is IDepositWithBeneficiary {
function depositWithBeneficiary(
address token,
uint256 amount,
address beneficiary,
uint64
) payable external override returns (bool) {
if (token == address(0)) {
// ETH
// No need to take ETH since it is transferred in msg.value
} else {
// Stablecoins
// Required. Take cross-chain'ed token to dapp's contract
IERC20Minimal(token).transferFrom(msg.sender, address(this), amount);
}
// The dapp can do it's own logic with depositing tokens
// e.g. exchange for other tokens, mint NFTs, etc.
// Could use data to determine specific operations.
// Send benefits to the user. Here as an example we just transfer
// deposited tokens to the user.
if (token == address(0)) {
// ETH
(bool success, ) = beneficiary.call{value: amount}("");
require(success, "Transfer failed");
} else {
// Stablecoins
IERC20Minimal(token).transfer(beneficiary, amount);
}
return true;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../interfaces/IERC20Minimal.sol";
import "../interfaces/IDepositWithBeneficiary.sol";
interface ITako {
function deposit(
address asset,
uint256 amount,
address onBehalfOf,
uint16 referralCode
) external;
}
/// @notice A sample of 3rd-party dapp that interacts with meson
/// With `depositWithBeneficiary`, the meson contract will be able
/// to deposit cross-chain'ed stablecoins to the 3rd-party dapp contract
/// on behalf of the user. The user will receive the benefits corresponding
/// to this deposit.
contract FreeDirecToTako is IDepositWithBeneficiary {
address constant _target = address(0x3A2Fd8a16030fFa8D66E47C3f1C0507c673C841e);
address private _admin;
uint16 private _referralCode = 0;
constructor () {
_admin = msg.sender;
}
function setReferralCode(uint16 code) external {
require(_admin == msg.sender, "Not authorized");
_referralCode = code;
}
function depositWithBeneficiary(
address token,
uint256 amount,
address beneficiary,
uint64
) payable external override returns (bool) {
if (token == address(0)) {
revert("ETH not supported");
} else {
IERC20Minimal(token).transferFrom(msg.sender, address(this), amount);
IERC20Minimal(token).approve(_target, amount);
ITako(_target).deposit(token, amount, beneficiary, _referralCode);
}
return true;
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import "../Pools/MesonPools.sol";
contract MesonPoolsTest is MesonPools {
address internal _premiumManager;
constructor(address token, address premiumManager) {
_addSupportToken(token, 1);
_premiumManager = premiumManager;
}
function _isPremiumManager() internal view override returns (bool) {
return _premiumManager == _msgSender();
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import "../utils/MesonStates.sol";
contract MesonStatesTest is MesonStates {
function addSupportToken(address token, uint8 index) external {
_addSupportToken(token, index);
}
function encodeSwap(
uint8 version,
uint40 amount,
uint80 salt,
uint40 fee,
uint40 expireTs,
bytes2 outChain,
uint8 outToken,
bytes2 inChain,
uint8 inToken
) external pure returns (bytes memory) {
return
abi.encodePacked(
version,
amount,
salt,
fee,
expireTs,
outChain,
outToken,
inChain,
inToken
);
}
function decodeSwap(uint256 encodedSwap, uint40 poolIndex) external pure returns (
uint8 version,
uint256 amount,
uint256 feeForLp,
uint256 serviceFee,
uint80 salt,
uint256 expireTs,
bytes2 inChain,
uint8 inTokenIndex,
bytes2 outChain,
uint8 outTokenIndex,
bytes6 poolTokenIndexForOutToken
) {
version = _versionFrom(encodedSwap);
amount = _amountFrom(encodedSwap);
feeForLp = _feeForLp(encodedSwap);
serviceFee = _serviceFee(encodedSwap);
salt = _saltFrom(encodedSwap);
expireTs = _expireTsFrom(encodedSwap);
inChain = bytes2(_inChainFrom(encodedSwap));
inTokenIndex = _inTokenIndexFrom(encodedSwap);
outChain = bytes2(_outChainFrom(encodedSwap));
outTokenIndex = _outTokenIndexFrom(encodedSwap);
poolTokenIndexForOutToken = bytes6(_poolTokenIndexForOutToken(encodedSwap, poolIndex));
}
function decodePostedSwap(uint200 postedSwap) external pure returns (
address initiator,
uint40 poolIndex
) {
initiator = _initiatorFromPosted(postedSwap);
poolIndex = _poolIndexFromPosted(postedSwap);
}
function lockedSwapFrom(uint256 until, uint40 poolIndex) external pure returns (uint80) {
return _lockedSwapFrom(until, poolIndex);
}
function decodeLockedSwap(uint80 lockedSwap) external pure returns (uint40 poolIndex, uint256 until) {
poolIndex = _poolIndexFromLocked(lockedSwap);
until = _untilFromLocked(lockedSwap);
}
function poolTokenIndexFrom(uint8 tokenIndex, uint40 poolIndex) external pure returns (bytes6) {
return bytes6(_poolTokenIndexFrom(tokenIndex, poolIndex));
}
function decodePoolTokenIndex(uint48 poolTokenIndex) external pure returns (
uint8 tokenIndex,
uint40 poolIndex
) {
tokenIndex = _tokenIndexFrom(poolTokenIndex);
poolIndex = _poolIndexFrom(poolTokenIndex);
}
function checkRequestSignature(
uint256 encodedSwap,
bytes32 r,
bytes32 yParityAndS,
address signer
) external pure {
_checkRequestSignature(encodedSwap, r, yParityAndS, signer);
}
function checkReleaseSignature(
uint256 encodedSwap,
address recipient,
bytes32 r,
bytes32 yParityAndS,
address signer
) external pure {
_checkReleaseSignature(encodedSwap, recipient, r, yParityAndS, signer);
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import "../Swap/MesonSwap.sol";
contract MesonSwapTest is MesonSwap {
constructor(address token) {
_addSupportToken(token, 1);
}
function register(uint40 poolIndex) external {
address poolOwner = _msgSender();
require(poolIndex != 0, "Cannot use index 0");
require(ownerOfPool[poolIndex] == address(0), "Pool index already registered");
require(poolOfAuthorizedAddr[poolOwner] == 0, "Signer address already registered");
ownerOfPool[poolIndex] = poolOwner;
poolOfAuthorizedAddr[poolOwner] = poolIndex;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract MockToken is ERC20 {
uint8 private _decimals;
constructor(
string memory name,
string memory symbol,
uint256 initialSupply,
uint8 decimals_
) ERC20(name, symbol) {
_decimals = decimals_;
_mint(msg.sender, initialSupply);
}
function decimals() public view override returns (uint8) {
return _decimals;
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
/// @title PoDUpgradeable
/// @notice The contract of POD, a token minted by Meson as the Proof of Deposit
contract PoDUpgradeable is UUPSUpgradeable, ERC20Upgradeable {
address private _owner;
address private _minter;
address private _mesonContract;
mapping(address => uint256) private _lockedBalances;
mapping(address => uint256) private _lockedSince;
uint256 private _rewardRatePerSecTimes1e12;
mapping(address => uint256) private _prevRewards;
uint256 constant NO_REWARD_LOCK_PERIOD = 3 days;
uint256 constant LESS_REWARD_LOCK_PERIOD = 7 days;
function initialize(address minter, address mesonContract) public initializer {
__ERC20_init("Proof of Deposit (meson.fi)", "PoD");
_owner = _msgSender();
_minter = minter;
require(mesonContract != address(0), "Address of meson contract cannot be zero");
_mesonContract = mesonContract;
}
function decimals() public pure override returns (uint8) {
return 6;
}
function mint(address account, uint256 amount) external onlyMinter {
_mint(account, amount);
}
function _authorizeUpgrade(address) internal view override {
require(_msgSender() == _owner, "Unauthorized");
}
/// @notice Override the default ERC20 allowance method
/// mesonContract will have max allowance so users don't need to execute approve
function allowance(address owner, address spender) public view override returns (uint256) {
if (spender == _mesonContract) {
uint256 x = 0;
unchecked { x--; }
return x;
}
return ERC20Upgradeable.allowance(owner, spender);
}
function transferFrom(address sender, address recipient, uint256 amount) public override returns (bool) {
address msgSender = _msgSender();
if (msgSender == _mesonContract && ERC20Upgradeable.allowance(sender, msgSender) < amount) {
uint256 x = 0;
unchecked { x--; }
_approve(sender, msgSender, x);
}
return ERC20Upgradeable.transferFrom(sender, recipient, amount);
}
function setRewardFactor(uint256 annualPercentageRateTimes1e4) external onlyOwner {
_rewardRatePerSecTimes1e12 = annualPercentageRateTimes1e4 * 1e8 / 365 days;
}
function getCurrentAPR() public view returns (uint256) {
return _rewardRatePerSecTimes1e12 * 365 days / 1e8;
}
function getLockedBalance(address account) public view returns (uint256) {
return _lockedBalances[account];
}
function _getRewards(address account) internal view returns (uint256 total, uint256 pending) {
uint256 lockedBalance = _lockedBalances[account];
if (lockedBalance == 0) {
return (_prevRewards[account], 0);
}
uint256 sinceLastLock = block.timestamp - _lockedSince[account];
uint256 rewardsForCurrentLock = sinceLastLock * lockedBalance * _rewardRatePerSecTimes1e12 / 1e12;
if (sinceLastLock > LESS_REWARD_LOCK_PERIOD) {
return (_prevRewards[account] + rewardsForCurrentLock, 0);
} else if (sinceLastLock > NO_REWARD_LOCK_PERIOD) {
return (_prevRewards[account] + rewardsForCurrentLock, 3 days * lockedBalance * _rewardRatePerSecTimes1e12 / 1e12);
} else {
return (_prevRewards[account] + rewardsForCurrentLock, rewardsForCurrentLock);
}
}
function getTotalRewards(address account) public view returns (uint256) {
(uint256 total, ) = _getRewards(account);
return total;
}
function getClaimableRewards(address account) public view returns (uint256) {
(uint256 total, uint256 pending) = _getRewards(account);
return total - pending;
}
function lockPoD(uint256 amount) external {
require(amount > 0, "amount must be greater than 0");
address account = _msgSender();
(uint256 total, uint256 pending) = _getRewards(account);
_prevRewards[account] = total - pending;
uint256 newLockedBalance = _lockedBalances[account] + amount;
_lockedSince[account] = block.timestamp - pending * 1e12 / _rewardRatePerSecTimes1e12 / newLockedBalance;
_lockedBalances[account] = newLockedBalance;
_transfer(account, address(this), amount);
}
function unlockPoD(uint256 amount) external {
require(amount > 0, "amount must be greater than 0");
address account = _msgSender();
_prevRewards[account] = getClaimableRewards(account);
uint256 newLockedBalance = _lockedBalances[account] - amount; // will throw error if overdrawn
_lockedSince[account] = newLockedBalance > 0 ? block.timestamp : 0;
_lockedBalances[account] = newLockedBalance;
_transfer(address(this), account, amount);
}
function withdrawRewards(uint256 amount) external {
require(amount > 0, "amount must be greater than 0");
address account = _msgSender();
uint256 claimableRewards = getClaimableRewards(account);
require(amount <= claimableRewards, "Insufficient claimable rewards");
_prevRewards[account] = claimableRewards - amount;
if (_lockedSince[account] > 0) {
_lockedSince[account] = block.timestamp;
}
_mint(account, amount);
}
modifier onlyOwner() {
require(_owner == _msgSender(), "Caller is not the owner");
_;
}
modifier onlyMinter() {
require(_minter == _msgSender(), "Caller is not the owner");
_;
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
/// @title UCTUpgradeable
/// @notice The contract of UCT, a token minted by Meson for promotional events
/// UCT (USD Coupon Token) is issued by Meson team to mark participants for
/// community events (such as airdrops, cashbacks, etc). UCT is not an asset
/// and it has no value. UCT obtained directly from Meson during the event period
/// can be redeemed for the actual USDT/USDC rewards on https://meson.fi/ at
/// a ratio of 100:1. UCT has no usage other than redemption for USDT/USDC,
/// and all UCTs will be destroyed at the end of the event.
contract UCTUpgradeable is UUPSUpgradeable, ERC20Upgradeable {
address private _owner;
address private _minter;
address private _mesonContract;
function initialize(address minter, address mesonContract) public initializer {
__ERC20_init("USD Coupon Token (https://meson.fi)", "UCT");
_owner = _msgSender();
_minter = minter;
require(mesonContract != address(0), "Address of meson contract cannot be zero");
_mesonContract = mesonContract;
}
function decimals() public pure override returns (uint8) {
return 4;
}
function batchMint(address[] memory targets, uint256 amount) external onlyMinter {
require(targets.length > 0, "Target array is empty");
require(targets.length < 2048, "Target array is too large");
for (uint i = 0; i < targets.length; i++) {
_mint(targets[i], amount);
}
}
function batchMint2(address[] memory targets, uint256[] memory amounts) external onlyMinter {
require(targets.length > 0, "Target array is empty");
require(targets.length < 2048, "Target array is too large");
require(targets.length == amounts.length, "Targets and amounts should have the same length");
for (uint i = 0; i < targets.length; i++) {
_mint(targets[i], amounts[i]);
}
}
function _authorizeUpgrade(address) internal view override {
require(_msgSender() == _owner, "Unauthorized");
}
/// @notice Override the default ERC20 allowance method
/// mesonContract will have max allowance so users don't need to execute approve
function allowance(address owner, address spender) public view override returns (uint256) {
if (spender == _mesonContract) {
uint256 x = 0;
unchecked { x--; }
return x;
}
return ERC20Upgradeable.allowance(owner, spender);
}
function transferFrom(address sender, address recipient, uint256 amount) public override returns (bool) {
address msgSender = _msgSender();
if (msgSender == _mesonContract && ERC20Upgradeable.allowance(sender, msgSender) < amount) {
uint256 x = 0;
unchecked { x--; }
_approve(sender, msgSender, x);
}
return ERC20Upgradeable.transferFrom(sender, recipient, amount);
}
modifier onlyOwner() {
require(_owner == _msgSender(), "Caller is not the owner");
_;
}
modifier onlyMinter() {
require(_minter == _msgSender(), "Caller is not the owner");
_;
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
interface IMesonMinimal {
function tokenForIndex(uint8 tokenIndex) external view returns (address);
function _isCoreToken(uint8 tokenIndex) external view returns (bool);
function _amountFactor(uint8 tokenIndex) external view returns (uint256);
function simpleExecuteSwap(uint256 encodedSwap) payable external;
}
contract TransferToMesonFactory {
function deploy(address mesonAddress, uint16 destChain, bytes32 destAddr, address via) external returns (address deployedAddress) {
bytes memory bytecode = abi.encodePacked(
type(TransferToMesonContract).creationCode,
abi.encode(mesonAddress, destChain, destAddr, via)
);
assembly {
deployedAddress := create2(0, add(bytecode, 32), mload(bytecode), "")
if iszero(deployedAddress) {
revert(0, 0)
}
}
}
}
contract TransferToMesonContract {
bytes4 private constant ERC20_APPROVE_SELECTOR = bytes4(keccak256("approve(address,uint256)"));
IMesonMinimal public immutable meson;
uint16 public immutable destChain;
bytes32 public immutable destAddr; // Could be used for non-EVMs
address public immutable via;
error EInvalidEncoded();
error EIncorrectDestChain();
error ENeedToContract();
error EApprove();
constructor(address mesonAddress, uint16 _destChain, bytes32 _destAddr, address _via) {
meson = IMesonMinimal(mesonAddress);
destChain = _destChain;
destAddr = _destAddr;
via = _via;
}
receive() external payable {}
function transferToMeson(uint256 encodedSwap) external {
require((encodedSwap & 0x3000000000000000000000000000000000000000000000000000) == 0x3000000000000000000000000000000000000000000000000000, EInvalidEncoded());
require(destChain == uint16(encodedSwap >> 32), EIncorrectDestChain());
if (via != address(0)) {
require((encodedSwap & 0x8000000000000000000000000000000000000000000000000000) == 0, ENeedToContract());
}
uint8 tokenIndex = uint8(encodedSwap);
uint256 amount = (encodedSwap >> 208) & 0xFFFFFFFFFF;
if (meson._isCoreToken(tokenIndex)) {
meson.simpleExecuteSwap{value: amount * 10 ** 12}(encodedSwap);
} else {
address tokenAddr = meson.tokenForIndex(tokenIndex);
(bool success, bytes memory data) = tokenAddr.call(
abi.encodeWithSelector(ERC20_APPROVE_SELECTOR, address(meson), amount * meson._amountFactor(tokenIndex))
);
require(success && (data.length == 0 || abi.decode(data, (bool))), EApprove());
meson.simpleExecuteSwap(encodedSwap);
}
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
/// @notice Parameters of the Meson contract
/// for Ethereum
contract MesonConfig {
uint8 constant MESON_PROTOCOL_VERSION = 1;
// Ref https://github.com/satoshilabs/slips/blob/master/slip-0044.md
uint16 constant SHORT_COIN_TYPE = 0x003c;
uint256 constant MAX_SWAP_AMOUNT = 1e11; // 100,000.000000 = 100k
uint256 constant SERVICE_FEE_RATE = 5; // service fee = 5 / 10000 = 0.05%
uint256 constant SERVICE_FEE_MINIMUM = 500_000; // min $0.5
uint256 constant SERVICE_FEE_MINIMUM_ETH = 500; // min 0.0005 ETH (or SOL)
uint256 constant SERVICE_FEE_MINIMUM_BNB = 5000; // min 0.005 BNB
uint256 constant SERVICE_FEE_MINIMUM_BTC = 10; // min 0.00001 BTC
uint256 constant MIN_BOND_TIME_PERIOD = 1 hours;
uint256 constant MAX_BOND_TIME_PERIOD = 2 hours;
uint256 constant LOCK_TIME_PERIOD = 40 minutes;
bytes28 constant ETH_SIGN_HEADER = bytes28("\x19Ethereum Signed Message:\n32");
bytes28 constant ETH_SIGN_HEADER_52 = bytes28("\x19Ethereum Signed Message:\n52");
bytes25 constant TRON_SIGN_HEADER = bytes25("\x19TRON Signed Message:\n32\n");
bytes25 constant TRON_SIGN_HEADER_33 = bytes25("\x19TRON Signed Message:\n33\n");
bytes25 constant TRON_SIGN_HEADER_53 = bytes25("\x19TRON Signed Message:\n53\n");
bytes32 constant REQUEST_TYPE_HASH = keccak256("bytes32 Sign to request a swap on Meson");
bytes32 constant RELEASE_TYPE_HASH = keccak256("bytes32 Sign to release a swap on Mesonaddress Recipient");
bytes32 constant RELEASE_TO_TRON_TYPE_HASH = keccak256("bytes32 Sign to release a swap on Mesonaddress Recipient (tron address in hex format)");
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import "@openzeppelin/contracts/utils/Context.sol";
import "./MesonConfig.sol";
/// @title MesonHelpers
/// @notice The class that provides helper functions for Meson protocol
contract MesonHelpers is MesonConfig, Context {
modifier matchProtocolVersion(uint256 encodedSwap) {
require(_versionFrom(encodedSwap) == MESON_PROTOCOL_VERSION, "Incorrect encoding version");
_;
}
function getShortCoinType() external pure returns (bytes2) {
return bytes2(SHORT_COIN_TYPE);
}
/// @notice Calculate `swapId` from `encodedSwap`, `initiator`
/// See variable `_postedSwaps` in `MesonSwap.sol` for the defination of `encodedSwap`
function _getSwapId(uint256 encodedSwap, address initiator) internal pure returns (bytes32) {
return keccak256(abi.encodePacked(encodedSwap, initiator));
}
/// @notice Decode `version` from `encodedSwap`
/// See variable `_postedSwaps` in `MesonSwap.sol` for the defination of `encodedSwap`
function _versionFrom(uint256 encodedSwap) internal pure returns (uint8) {
return uint8(encodedSwap >> 248);
}
/// @notice Decode `amount` from `encodedSwap`
/// See variable `_postedSwaps` in `MesonSwap.sol` for the defination of `encodedSwap`
function _amountFrom(uint256 encodedSwap) internal pure returns (uint256) {
return (encodedSwap >> 208) & 0xFFFFFFFFFF;
}
function _amountToLock(uint256 encodedSwap) internal pure returns (uint256) {
return _amountFrom(encodedSwap) - _feeForLp(encodedSwap) - _amountForCoreTokenFrom(encodedSwap);
}
/// @notice Calculate the service fee from `encodedSwap`
/// See variable `_postedSwaps` in `MesonSwap.sol` for the defination of `encodedSwap`
function _serviceFee(uint256 encodedSwap) internal pure returns (uint256) {
uint8 tokenIndex = _inTokenIndexFrom(encodedSwap);
uint256 minFee;
if (tokenIndex >= 252) {
minFee = SERVICE_FEE_MINIMUM_ETH;
} else if (tokenIndex >= 248) {
minFee = SERVICE_FEE_MINIMUM_BNB;
} else if (tokenIndex >= 244) {
minFee = SERVICE_FEE_MINIMUM_ETH;
} else if (tokenIndex >= 240) {
minFee = SERVICE_FEE_MINIMUM_BTC;
} else {
minFee = SERVICE_FEE_MINIMUM;
}
// Default to `serviceFee` = 0.05% * `amount`
uint256 fee = _amountFrom(encodedSwap) * SERVICE_FEE_RATE / 10000;
return fee > minFee ? fee : minFee;
}
/// @notice Decode `fee` (the fee for LPs) from `encodedSwap`
/// See variable `_postedSwaps` in `MesonSwap.sol` for the defination of `encodedSwap`
function _feeForLp(uint256 encodedSwap) internal pure returns (uint256) {
return (encodedSwap >> 88) & 0xFFFFFFFFFF;
}
/// @notice Decode `salt` from `encodedSwap`
/// See variable `_postedSwaps` in `MesonSwap.sol` for the defination of `encodedSwap`
function _saltFrom(uint256 encodedSwap) internal pure returns (uint80) {
return uint80(encodedSwap >> 128);
}
/// @notice Decode data from `salt`
/// See variable `_postedSwaps` in `MesonSwap.sol` for the defination of `encodedSwap`
function _saltDataFrom(uint256 encodedSwap) internal pure returns (uint64) {
return uint64(encodedSwap >> 128);
}
/// @notice Whether the swap should release to a 3rd-party integrated dapp contract
/// See method `release` in `MesonPools.sol` for more details
function _willTransferToContract(uint256 encodedSwap) internal pure returns (bool) {
return (encodedSwap & 0x8000000000000000000000000000000000000000000000000000) == 0;
}
/// @notice Whether the swap needs to pay service fee
/// See method `release` in `MesonPools.sol` for more details about the service fee
function _feeWaived(uint256 encodedSwap) internal pure returns (bool) {
return (encodedSwap & 0x4000000000000000000000000000000000000000000000000000) > 0;
}
/// @notice Whether the swap was signed in the non-typed manner (usually by hardware wallets)
function _signNonTyped(uint256 encodedSwap) internal pure returns (bool) {
return (encodedSwap & 0x0800000000000000000000000000000000000000000000000000) > 0;
}
function _swapForCoreToken(uint256 encodedSwap) internal pure returns (bool) {
return (_outTokenIndexFrom(encodedSwap) < 191) &&
((encodedSwap & 0x8410000000000000000000000000000000000000000000000000) == 0x8410000000000000000000000000000000000000000000000000);
}
function _amountForCoreTokenFrom(uint256 encodedSwap) internal pure returns (uint256) {
if (_swapForCoreToken(encodedSwap)) {
uint256 d = (encodedSwap >> 160) & 0xFFFF;
if (d == 0xFFFF) {
return _amountFrom(encodedSwap) - _feeForLp(encodedSwap) - (_feeWaived(encodedSwap) ? 0 : _serviceFee(encodedSwap));
}
return _decompressFixedPrecision(d) * 1e3;
}
return 0;
}
function _coreTokenAmount(uint256 encodedSwap) internal pure returns (uint256) {
uint256 amountForCore = _amountForCoreTokenFrom(encodedSwap);
if (amountForCore > 0) {
return amountForCore * 1e4 / _decompressFixedPrecision((encodedSwap >> 176) & 0xFFFF);
}
return 0;
}
function _shareWithPartner(uint256 encodedSwap) internal pure returns (bool) {
return !_willTransferToContract(encodedSwap)
&& ((encodedSwap & 0x0600000000000000000000000000000000000000000000000000) == 0x0200000000000000000000000000000000000000000000000000);
}
function _amountToShare(uint256 encodedSwap) internal pure returns (uint256) {
if (_shareWithPartner(encodedSwap)) {
return _decompressFixedPrecision((encodedSwap >> 160) & 0xFFFF);
}
return 0;
}
function _decompressFixedPrecision(uint256 d) internal pure returns (uint256) {
if (d <= 1000) {
return d;
}
return ((d - 1000) % 9000 + 1000) * 10 ** ((d - 1000) / 9000);
}
function _poolIndexToShare(uint256 encodedSwap) internal pure returns (uint40) {
if (_shareWithPartner(encodedSwap)) {
return (uint40(encodedSwap >> 176) & 0xFFFF) + 65536;
}
return 0;
}
/// @notice Decode `expireTs` from `encodedSwap`
/// See variable `_postedSwaps` in `MesonSwap.sol` for the defination of `encodedSwap`
function _expireTsFrom(uint256 encodedSwap) internal pure returns (uint256) {
return (encodedSwap >> 48) & 0xFFFFFFFFFF;
// [Suggestion]: return uint40(encodedSwap >> 48);
}
/// @notice Decode the initial chain (`inChain`) from `encodedSwap`
/// See variable `_postedSwaps` in `MesonSwap.sol` for the defination of `encodedSwap`
function _inChainFrom(uint256 encodedSwap) internal pure returns (uint16) {
return uint16(encodedSwap >> 8);
}
/// @notice Decode the token index of initial chain (`inToken`) from `encodedSwap`
/// See variable `_postedSwaps` in `MesonSwap.sol` for the defination of `encodedSwap`
function _inTokenIndexFrom(uint256 encodedSwap) internal pure returns (uint8) {
return uint8(encodedSwap);
}
/// @notice Decode the target chain (`outChain`) from `encodedSwap`
/// See variable `_postedSwaps` in `MesonSwap.sol` for the defination of `encodedSwap`
function _outChainFrom(uint256 encodedSwap) internal pure returns (uint16) {
return uint16(encodedSwap >> 32);
}
/// @notice Decode the token index of target chain (`outToken`) from `encodedSwap`
/// See variable `_postedSwaps` in `MesonSwap.sol` for the defination of `encodedSwap`
function _outTokenIndexFrom(uint256 encodedSwap) internal pure returns (uint8) {
return uint8(encodedSwap >> 24);
}
function _tokenType(uint8 tokenIndex) internal pure returns (uint8) {
if (tokenIndex >= 192) {
// Non stablecoins [192, 255] -> [48, 63]
return tokenIndex / 4;
} else if (tokenIndex <= 64) {
// Stablecoins [1, 64] -> 0
return 0;
} else if (tokenIndex <= 112) {
// 3rd party tokens [65, 112] -> [1, 24]
return (tokenIndex + 1) / 2 - 32;
} else if (tokenIndex <= 128) {
// 3rd party tokens [113, 128] -> [33, 48]
return tokenIndex - 80;
}
revert("Token index not allowed for swapping");
}
/// @notice Decode `outToken` from `encodedSwap`, and encode it with `poolIndex` to `poolTokenIndex`.
/// See variable `_balanceOfPoolToken` in `MesonStates.sol` for the defination of `poolTokenIndex`
function _poolTokenIndexForOutToken(uint256 encodedSwap, uint40 poolIndex) internal pure returns (uint48) {
return uint48((encodedSwap & 0xFF000000) << 16) | poolIndex;
}
/// @notice Encode `postedSwap` from `initiator` and `poolIndex`
/// See variable `_postedSwaps` in `MesonSwap.sol` for the defination of `postedSwap`
function _postedSwapFrom(address initiator, uint40 poolIndex, bool tokenNotFromInitiator)
internal pure returns (uint208)
{
return (tokenNotFromInitiator ? (uint208(1) << 200) : uint208(0)) | (uint208(uint160(initiator)) << 40) | poolIndex;
}
/// @notice Decode `initiator` from `postedSwap`
/// See variable `_postedSwaps` in `MesonSwap.sol` for the defination of `postedSwap`
function _initiatorFromPosted(uint208 postedSwap) internal pure returns (address) {
return address(uint160(postedSwap >> 40));
}
/// @notice Decode `poolIndex` from `postedSwap`
/// See variable `_postedSwaps` in `MesonSwap.sol` for the defination of `postedSwap`
function _poolIndexFromPosted(uint208 postedSwap) internal pure returns (uint40) {
return uint40(postedSwap);
}
/// @notice Encode `lockedSwap` from `until` and `poolIndex`
/// See variable `_lockedSwaps` in `MesonPools.sol` for the defination of `lockedSwap`
function _lockedSwapFrom(uint256 until, uint40 poolIndex) internal pure returns (uint80) {
return (uint80(until) << 40) | poolIndex;
}
/// @notice Decode `poolIndex` from `lockedSwap`
/// See variable `_lockedSwaps` in `MesonPools.sol` for the defination of `lockedSwap`
function _poolIndexFromLocked(uint80 lockedSwap) internal pure returns (uint40) {
return uint40(lockedSwap);
}
/// @notice Decode `until` from `lockedSwap`
/// See variable `_lockedSwaps` in `MesonPools.sol` for the defination of `lockedSwap`
function _untilFromLocked(uint80 lockedSwap) internal pure returns (uint256) {
return uint256(lockedSwap >> 40);
}
/// @notice Encode `poolTokenIndex` from `tokenIndex` and `poolIndex`
/// See variable `_balanceOfPoolToken` in `MesonStates.sol` for the defination of `poolTokenIndex`
function _poolTokenIndexFrom(uint8 tokenIndex, uint40 poolIndex) internal pure returns (uint48) {
return (uint48(tokenIndex) << 40) | poolIndex;
}
/// @notice Decode `tokenIndex` from `poolTokenIndex`
/// See variable `_balanceOfPoolToken` in `MesonStates.sol` for the defination of `poolTokenIndex`
function _tokenIndexFrom(uint48 poolTokenIndex) internal pure returns (uint8) {
return uint8(poolTokenIndex >> 40);
}
/// @notice Decode `poolIndex` from `poolTokenIndex`
/// See variable `_balanceOfPoolToken` in `MesonStates.sol` for the defination of `poolTokenIndex`
function _poolIndexFrom(uint48 poolTokenIndex) internal pure returns (uint40) {
return uint40(poolTokenIndex);
}
/// @notice Check the initiator's signature for a swap request
/// Signatures are constructed with the package `mesonfi/sdk`. Go to `packages/sdk/src/SwapSigner.ts` and
/// see how to generate a signautre in class `EthersWalletSwapSigner` method `signSwapRequest`
/// @param encodedSwap Encoded swap information. See variable `_postedSwaps` in `MesonSwap.sol` for the defination of `encodedSwap`
/// @param r Part of the signature
/// @param yParityAndS Part of the signature
/// @param signer The signer for the swap request which is the `initiator`
function _checkRequestSignature(
uint256 encodedSwap,
bytes32 r,
bytes32 yParityAndS,
address signer
) internal pure {
require(signer != address(0), "Signer cannot be empty address");
bytes32 s = yParityAndS & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
uint8 v = uint8((uint256(yParityAndS) >> 255) + 27);
require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, "Invalid signature");
bool nonTyped = _signNonTyped(encodedSwap);
bytes32 digest;
if (_inChainFrom(encodedSwap) == 0x00c3) {
digest = keccak256(abi.encodePacked(nonTyped ? TRON_SIGN_HEADER_33 : TRON_SIGN_HEADER, encodedSwap));
} else if (nonTyped) {
digest = keccak256(abi.encodePacked(ETH_SIGN_HEADER, encodedSwap));
} else {
bytes32 typehash = REQUEST_TYPE_HASH;
assembly {
mstore(0, encodedSwap)
mstore(32, keccak256(0, 32))
mstore(0, typehash)
digest := keccak256(0, 64)
}
}
require(signer == ecrecover(digest, v, r, s), "Invalid signature");
}
/// @notice Check the initiator's signature for the release request
/// Signatures are constructed with the package `mesonfi/sdk`. Go to `packages/sdk/src/SwapSigner.ts` and
/// see how to generate a signautre in class `EthersWalletSwapSigner` method `signSwapRelease`
/// @param encodedSwap Encoded swap information. See variable `_postedSwaps` in `MesonSwap.sol` for the defination of `encodedSwap`
/// @param recipient The recipient address of the swap
/// @param r Part of the signature
/// @param yParityAndS Part of the signature
/// @param signer The signer for the swap request which is the `initiator`
function _checkReleaseSignature(
uint256 encodedSwap,
address recipient,
bytes32 r,
bytes32 yParityAndS,
address signer
) internal pure {
require(signer != address(0), "Signer cannot be empty address");
bytes32 s = yParityAndS & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
uint8 v = uint8((uint256(yParityAndS) >> 255) + 27);
require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, "Invalid signature");
bool nonTyped = _signNonTyped(encodedSwap);
bytes32 digest;
if (_inChainFrom(encodedSwap) == 0x00c3) {
digest = keccak256(abi.encodePacked(nonTyped ? TRON_SIGN_HEADER_53 : TRON_SIGN_HEADER, encodedSwap, recipient));
} else if (nonTyped) {
digest = keccak256(abi.encodePacked(ETH_SIGN_HEADER_52, encodedSwap, recipient));
} else {
bytes32 typehash = _outChainFrom(encodedSwap) == 0x00c3 ? RELEASE_TO_TRON_TYPE_HASH : RELEASE_TYPE_HASH;
assembly {
mstore(20, recipient)
mstore(0, encodedSwap)
mstore(32, keccak256(0, 52))
mstore(0, typehash)
digest := keccak256(0, 64)
}
}
require(signer == ecrecover(digest, v, r, s), "Invalid signature");
}
function _checkSignature(bytes32 digest, bytes32 r, bytes32 yParityAndS, address signer) internal pure {
require(signer != address(0), "Signer cannot be empty address");
bytes32 s = yParityAndS & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
uint8 v = uint8((uint256(yParityAndS) >> 255) + 27);
require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, "Invalid signature");
require(signer == ecrecover(digest, v, r, s), "Invalid signature");
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import "@openzeppelin/contracts/utils/Address.sol";
import "../interfaces/IERC20Minimal.sol";
import "../interfaces/IDepositWithBeneficiary.sol";
import "./MesonTokens.sol";
import "./MesonHelpers.sol";
/// @title MesonStates
/// @notice The class that keeps track of LP pool states
contract MesonStates is MesonTokens, MesonHelpers {
bytes4 private constant ERC20_TRANSFER_SELECTOR = bytes4(keccak256("transfer(address,uint256)"));
bytes4 private constant ERC20_TRANSFER_FROM_SELECTOR = bytes4(keccak256("transferFrom(address,address,uint256)"));
/// @notice The mapping from *authorized addresses* to LP pool indexes.
/// See `ownerOfPool` to understand how pool index is defined and used.
///
/// This mapping records the relation between *authorized addresses* and pool indexes, where
/// authorized addresses are those who have the permision to match and complete a swap with funds
/// in a pool with specific index. For example, for an LP pool with index `i` there could be multiple
/// addresses that `poolOfAuthorizedAddr[address] = i`, which means these addresses can all sign to match
/// (call `bondSwap`, `lock`) a swap and complete it (call `release`) with funds in pool `i`. That helps
/// an LP to give other addresses the permission to perform daily swap transactions. However, authorized
/// addresses cannot withdraw funds from the LP pool, unless it's given in `ownerOfPool` which records
/// the *owner* address for each pool.
///
/// The pool index 0 is reserved for use by Meson
mapping(address => uint40) public poolOfAuthorizedAddr;
/// @notice The mapping from LP pool indexes to their owner addresses.
/// Each LP pool in Meson has a uint40 index `i` and each LP needs to register an pool index at
/// initial deposit by calling `depositAndRegister`. The balance for each LP pool is tracked by its
/// pool index and token index (see `_balanceOfPoolToken`).
///
/// This mapping records the *owner* address for each LP pool. Only the owner address can withdraw funds
/// from its corresponding LP pool.
///
/// The pool index 0 is reserved for use by Meson
mapping(uint40 => address) public ownerOfPool;
/// @notice Balance for each token in LP pool, tracked by the `poolTokenIndex`.
/// See `ownerOfPool` to understand how pool index is defined and used.
///
/// The balance of a token in an LP pool is `_balanceOfPoolToken[poolTokenIndex]` in which
/// the `poolTokenIndex` is in format of `tokenIndex:uint8|poolIndex:uint40`. `tokenIndex`
/// is the index of supported tokens given by `tokenForIndex` (see definition in `MesonTokens.sol`).
/// The balances are always store as tokens have decimal 6, which is the case for USDC/USDT on most chains
/// except BNB Smart Chain & Conflux. In the exceptional cases, the value of token amount will be converted
/// on deposit and withdrawal (see `_safeTransfer` and `_unsafeDepositToken` in `MesonHelpers.sol`).
///
/// The pool index 0 is reserved for use by Meson to store service fees
mapping(uint48 => uint256) internal _balanceOfPoolToken;
/// @dev This empty reserved space is put in place to allow future versions to
/// add new variables without shifting down storage in the inheritance chain.
/// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
uint256[50] private __gap;
function _isPremiumManager() internal view virtual returns (bool) {}
function poolTokenBalance(address token, address addr) external view returns (uint256) {
uint8 tokenIndex = indexOfToken[token];
uint40 poolIndex = poolOfAuthorizedAddr[addr];
if (poolIndex == 0 || tokenIndex == 0) {
return 0;
}
return _balanceOfPoolToken[_poolTokenIndexFrom(tokenIndex, poolIndex)];
}
/// @notice The collected service fee of a specific token.
/// @param tokenIndex The index of a supported token. See `tokenForIndex` in `MesonTokens.sol`
function serviceFeeCollected(uint8 tokenIndex) external view returns (uint256) {
return _balanceOfPoolToken[_poolTokenIndexFrom(tokenIndex, 0)];
}
/// @notice Help the senders to transfer their assets to the Meson contract
/// @param tokenIndex The index of token. See `tokenForIndex` in `MesonTokens.sol`
/// @param sender The sender of the transfer
/// @param amount The value of the transfer (always in decimal 6)
function _unsafeDepositToken(
uint8 tokenIndex,
address sender,
uint256 amount
) internal {
require(amount > 0, "Amount must be greater than zero");
if (_isCoreToken(tokenIndex)) {
// Core tokens (e.g. ETH or BNB)
require(amount * 1e12 == msg.value, "msg.value does not match the amount");
} else {
// Stablecoins
address token = tokenForIndex[tokenIndex];
require(token != address(0), "Token not supported");
require(Address.isContract(token), "The given token address is not a contract");
amount *= _amountFactor(tokenIndex);
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(
ERC20_TRANSFER_FROM_SELECTOR,
sender,
address(this),
amount
));
require(success && (data.length == 0 || abi.decode(data, (bool))), "transferFrom failed");
}
}
/// @notice Safe transfers tokens from Meson contract to a recipient
/// for interacting with ERC20 tokens that do not consistently return true/false
/// @param tokenIndex The index of token. See `tokenForIndex` in `MesonTokens.sol`
/// @param recipient The recipient of the transfer
/// @param amount The value of the transfer (always in decimal 6)
function _safeTransfer(
uint8 tokenIndex,
address recipient,
uint256 amount
) internal {
if (_isCoreToken(tokenIndex)) {
// Core tokens (e.g. ETH or BNB)
_transferCoreToken(recipient, amount);
} else {
// Stablecoins
address token = tokenForIndex[tokenIndex];
require(Address.isContract(token), "The given token address is not a contract");
amount *= _amountFactor(tokenIndex);
if (SHORT_COIN_TYPE == 0x00c3) {
IERC20Minimal(token).transfer(recipient, amount);
} else {
// This doesn't works on Tron
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(
ERC20_TRANSFER_SELECTOR,
recipient,
amount
));
require(success && (data.length == 0 || abi.decode(data, (bool))), "transfer failed");
}
}
}
function _transferCoreToken(address recipient, uint256 amount) internal {
(bool success, ) = recipient.call{value: amount * 1e12}("");
require(success, "Transfer failed");
}
/// @notice Transfer tokens to a contract using `depositWithBeneficiary`
/// @param tokenIndex The index of token. See `tokenForIndex` in `MesonTokens.sol`
/// @param contractAddr The smart contract address that will receive transferring tokens
/// @param beneficiary The beneficiary of `depositWithBeneficiary`
/// @param amount The value of the transfer (always in decimal 6)
/// @param data Extra data passed to the contract
function _transferToContract(
uint8 tokenIndex,
address contractAddr,
address beneficiary,
uint256 amount,
uint64 data
) internal {
require(Address.isContract(contractAddr), "The given recipient address is not a contract");
amount *= _amountFactor(tokenIndex);
if (_isCoreToken(tokenIndex)) {
// Core tokens (e.g. ETH or BNB)
IDepositWithBeneficiary(contractAddr).depositWithBeneficiary{value: amount}(
address(0),
amount,
beneficiary,
data
);
} else {
// Stablecoins
address token = tokenForIndex[tokenIndex];
require(Address.isContract(token), "The given token address is not a contract");
IERC20Minimal(token).approve(contractAddr, amount);
IDepositWithBeneficiary(contractAddr).depositWithBeneficiary(
token,
amount,
beneficiary,
data
);
}
}
/// @notice Determine if token has decimal 18 and therefore need to adjust amount
/// @param tokenIndex The index of token. See `tokenForIndex` in `MesonTokens.sol`
function _amountFactor(uint8 tokenIndex) public pure returns (uint256) {
if (tokenIndex <= 32) {
return 1;
} else if (tokenIndex == 242 && SHORT_COIN_TYPE != 0x02ca && SHORT_COIN_TYPE != 0x1771) {
return 100;
} else if (tokenIndex > 112 && tokenIndex <= 123) {
return 100;
} else if (tokenIndex > 123 && tokenIndex <= 128) {
return 1000;
}
return 1e12;
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
/// @title MesonTokens
/// @notice The class that stores the information of Meson's supported tokens
contract MesonTokens {
/// @notice The whitelist of supported tokens in Meson
/// Meson use a whitelist for supported stablecoins, which is specified on first deployment
/// or added through `_addSupportToken` Only modify this mapping through `_addSupportToken`.
/// key: `tokenIndex` in range of 1-255
/// 0: unsupported
/// 1-32: stablecoins with decimals 6
/// 1, 9: USDC, USDC.e
/// 2, 10: USDT, USDT.e
/// 3: BUSD
/// 6: CUSD (Viction/Tomo)
/// 7: pUSD
/// 16: USD1
/// 17: PoD USDC
/// 18: PoD USDT
/// 19: PoD BUSD
/// 32: PoD
/// 33-48: stablecoins with decimals 18
/// 33: USDC
/// 34: USDT
/// 35: BUSD
/// 36: (reserved for DAI)
/// 37: cUSD (Celo)
/// 39: USDB (Blast)
/// 40: FDUSD
/// 41: BBUSD
/// 48: USD1
/// 49-64: stablecoins as core (decimals 18)
/// 49: USDC
/// 52: DAI
/// 65-112: 3rd party tokens (decimals 18)
/// 65: iUSD (iZUMi Bond USD)
/// 67: M-BTC (Merlin BTC)
/// 69: MERL
/// 71: STONE
/// 73: SolvBTC.m
/// 75: SolvBTC
/// 77: SolvBTC.a
/// 79: uBTC
/// 81: xSolvBTC
/// 83: SolvBTC.ENA
/// 85: SolvBTC.JUP
/// 87: PUMP
/// 89: B2
/// 113-123: 3rd party tokens (decimals 8)
/// 113: pumpBTC
/// 114: uniBTC
/// 115: cbBTC
/// 116: FBTC
/// 124-128: 3rd party tokens (decimals 9)
/// 124: DUCK
/// 129-190: (Unspecified)
/// 191: No-swap core
/// 192-195: M & M equivalent
/// 194: ERC20 M
/// 195: M as core
/// 196-199: M & M equivalent
/// 198: ERC20 TAKER
/// 199: TAKER as core
/// 200-235: (Unspecified)
/// 236-239: MATIC & MATIC equivalent
/// 236: PoD MATIC
/// 238: ERC20 MATIC
/// 239: MATIC as core
/// 240-243: BTC & BTC equivalent
/// 240: PoD BTC
/// 241: ERC20 BTC (decimals 18)
/// 242: ERC20 BTC (decimals 8 except BNB Smart Chain & BounceBit)
/// 243: BTC as core
/// 244-247: SOL & SOL equivalent
/// 244: PoD SOL
/// 246: ERC20 SOL
/// 247: SOL as core
/// 248-251: BNB & BNB equivalent
/// 248: PoD BNB
/// 250: (reserved for ERC20 BNB)
/// 251: BNB as core
/// 252-255: ETH & ETH equivalent
/// 252: PoD ETH
/// 254: Wrapped ETH
/// 255: ETH as core
/// value: the supported token's contract address
mapping(uint8 => address) public tokenForIndex;
/// @notice The mapping to get `tokenIndex` from a supported token's address
/// Only modify this mapping through `_addSupportToken`.
/// key: the supported token's contract address
/// value: `tokenIndex` in range of 1-255
mapping(address => uint8) public indexOfToken;
/// @dev This empty reserved space is put in place to allow future versions to
/// add new variables without shifting down storage in the inheritance chain.
/// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
uint256[50] private __gap;
function _isCoreToken(uint8 tokenIndex) public pure returns (bool) {
return (tokenIndex >= 49 && tokenIndex <= 64) || ((tokenIndex > 190) && ((tokenIndex % 4) == 3));
}
/// @notice Return all supported token addresses in an array ordered by `tokenIndex`
/// This method will only return tokens with consecutive token indexes.
function getSupportedTokens() external view returns (address[] memory tokens, uint8[] memory indexes) {
uint8 i;
uint8 num;
for (i = 0; i < 255; i++) {
if (tokenForIndex[i+1] != address(0)) {
num++;
}
}
tokens = new address[](num);
indexes = new uint8[](num);
uint8 j = 0;
for (i = 0; i < 255; i++) {
if (tokenForIndex[i+1] != address(0)) {
tokens[j] = tokenForIndex[i+1];
indexes[j] = i+1;
j++;
}
}
}
function _addSupportToken(address token, uint8 index) internal {
require(index != 0, "Cannot use 0 as token index");
require(token != address(0), "Cannot use zero address");
require(indexOfToken[token] == 0, "Token has been added before");
require(tokenForIndex[index] == address(0), "Index has been used");
if (_isCoreToken(index)) {
require(token == address(0x1), "Core token requires adddress(0x1)");
}
indexOfToken[token] = index;
tokenForIndex[index] = token;
}
function _removeSupportToken(uint8 index) internal {
require(index != 0, "Cannot use 0 as token index");
address token = tokenForIndex[index];
require(token != address(0), "Token for the index does not exist");
delete indexOfToken[token];
delete tokenForIndex[index];
}
}{
"optimizer": {
"enabled": true,
"runs": 100
},
"evmVersion": "paris",
"viaIR": true,
"metadata": {
"bytecodeHash": "none"
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"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":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"prevOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint40","name":"poolIndex","type":"uint40"},{"indexed":false,"internalType":"address","name":"addr","type":"address"}],"name":"PoolAuthorizedAddrAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint40","name":"poolIndex","type":"uint40"},{"indexed":false,"internalType":"address","name":"addr","type":"address"}],"name":"PoolAuthorizedAddrRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint48","name":"poolTokenIndex","type":"uint48"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PoolDeposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint40","name":"poolIndex","type":"uint40"},{"indexed":false,"internalType":"address","name":"prevOwner","type":"address"},{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"PoolOwnerTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint40","name":"poolIndex","type":"uint40"},{"indexed":false,"internalType":"address","name":"owner","type":"address"}],"name":"PoolRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint48","name":"poolTokenIndex","type":"uint48"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PoolWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"prevPremiumManager","type":"address"},{"indexed":true,"internalType":"address","name":"newPremiumManager","type":"address"}],"name":"PremiumManagerTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"encodedSwap","type":"uint256"}],"name":"SwapBonded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"encodedSwap","type":"uint256"}],"name":"SwapCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"encodedSwap","type":"uint256"}],"name":"SwapExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"encodedSwap","type":"uint256"}],"name":"SwapLocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"encodedSwap","type":"uint256"}],"name":"SwapPosted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"encodedSwap","type":"uint256"}],"name":"SwapReleased","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"encodedSwap","type":"uint256"}],"name":"SwapUnlocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[{"internalType":"uint8","name":"tokenIndex","type":"uint8"}],"name":"_amountFactor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint8","name":"tokenIndex","type":"uint8"}],"name":"_isCoreToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"addAuthorizedAddr","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"uint8[]","name":"indexes","type":"uint8[]"}],"name":"addMultipleSupportedTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint8","name":"index","type":"uint8"}],"name":"addSupportToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"tokenIndex","type":"uint8"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint40","name":"toPoolIndex","type":"uint40"}],"name":"adjustToPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"encodedSwap","type":"uint256"},{"internalType":"uint40","name":"poolIndex","type":"uint40"}],"name":"bondSwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"encodedSwap","type":"uint256"}],"name":"cancelSwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"encodedSwap","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"cancelSwapTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint48","name":"poolTokenIndex","type":"uint48"}],"name":"deposit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint48","name":"poolTokenIndex","type":"uint48"}],"name":"depositAndRegister","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"encodedSwap","type":"uint256"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"yParityAndS","type":"bytes32"},{"internalType":"address","name":"initiator","type":"address"},{"internalType":"address","name":"recipient","type":"address"}],"name":"directExecuteSwap","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"encodedSwap","type":"uint256"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"yParityAndS","type":"bytes32"},{"internalType":"address","name":"initiator","type":"address"},{"internalType":"address","name":"recipient","type":"address"}],"name":"directRelease","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"encodedSwap","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"yParityAndS","type":"bytes32"}],"name":"directSwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"encodedSwap","type":"uint256"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"yParityAndS","type":"bytes32"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"bool","name":"depositToPool","type":"bool"}],"name":"executeSwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"encodedSwap","type":"uint256"},{"internalType":"address","name":"initiator","type":"address"}],"name":"getLockedSwap","outputs":[{"internalType":"address","name":"poolOwner","type":"address"},{"internalType":"uint40","name":"until","type":"uint40"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"encodedSwap","type":"uint256"}],"name":"getPostedSwap","outputs":[{"internalType":"address","name":"initiator","type":"address"},{"internalType":"address","name":"poolOwner","type":"address"},{"internalType":"bool","name":"exist","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getShortCoinType","outputs":[{"internalType":"bytes2","name":"","type":"bytes2"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getSupportedTokens","outputs":[{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"uint8[]","name":"indexes","type":"uint8[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"indexOfToken","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"premiumManager","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"encodedSwap","type":"uint256"},{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"address","name":"initiator","type":"address"}],"name":"lock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"encodedSwap","type":"uint256"},{"internalType":"address","name":"initiator","type":"address"}],"name":"lockSwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint40","name":"","type":"uint40"}],"name":"ownerOfPool","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"poolOfAuthorizedAddr","outputs":[{"internalType":"uint40","name":"","type":"uint40"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"addr","type":"address"}],"name":"poolTokenBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"encodedSwap","type":"uint256"},{"internalType":"address","name":"initiator","type":"address"},{"internalType":"uint40","name":"poolIndex","type":"uint40"}],"name":"postSwap","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"encodedSwap","type":"uint256"},{"internalType":"uint200","name":"postingValue","type":"uint200"}],"name":"postSwapFromInitiator","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"encodedSwap","type":"uint256"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"yParityAndS","type":"bytes32"},{"internalType":"address","name":"initiator","type":"address"},{"internalType":"uint40","name":"poolIndex","type":"uint40"}],"name":"postSwapWithSignature","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"encodedSwap","type":"uint256"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"yParityAndS","type":"bytes32"},{"internalType":"address","name":"initiator","type":"address"},{"internalType":"address","name":"recipient","type":"address"}],"name":"release","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"removeAuthorizedAddr","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"index","type":"uint8"}],"name":"removeSupportToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"tokenIndex","type":"uint8"}],"name":"serviceFeeCollected","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"encodedSwap","type":"uint256"}],"name":"simpleExecuteSwap","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint8","name":"","type":"uint8"}],"name":"tokenForIndex","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"transferPoolOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newPremiumManager","type":"address"}],"name":"transferPremiumManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"encodedSwap","type":"uint256"},{"internalType":"address","name":"initiator","type":"address"}],"name":"unlock","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":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint48","name":"poolTokenIndex","type":"uint48"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"tokenIndex","type":"uint8"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint40","name":"toPoolIndex","type":"uint40"}],"name":"withdrawServiceFee","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60a0806040523460305730608052614f0b90816100368239608051818181610a2b01528181610ff401526130ae0152f35b600080fdfe6080604052600436101561001257600080fd5b60003560e01c8063051119f5146102d75780630ffad9c0146102d257806316f35d23146102cd5780631e2a6075146102c85780632335093c146102c3578063264849e7146102be57806330f00f3a146102b957806335eff30f146102b45780633659cfe6146102af57806337b90a4f146102aa578063485cc955146102a55780634a2377e2146102a05780634f1ef2861461029b578063515147ab1461029657806352d1902d1461029157806354d6a2b71461028c57806358d9b4e11461028757806360a2da98146102825780636484396e1461027d5780636f9b41fd146102785780637234cd9514610273578063741c8e2d1461026e5780637fe0282b14610269578063827c87cc1461026457806389a734c01461025f5780638b0a77651461025a5780638f487dc914610255578063a5c9c66c14610250578063ab115fd81461024b578063b805f32114610246578063c11d9ecb14610241578063c8173c441461023c578063cb4f999b14610237578063ce7f79b914610232578063d3c7c2c71461022d578063d3e95ea414610228578063d4f8232214610223578063decf2a481461021e578063eaf250b514610219578063eba7fb7714610214578063f1d2ec1d1461020f578063f2fde38b1461020a578063ff22f272146102055763ff3787191461020057600080fd5b612658565b6125af565b612578565b612447565b612427565b6123ae565b6122cb565b612286565b61225a565b612149565b61200d565b611f16565b611e76565b611dc7565b611d0f565b611aa8565b6118c3565b61172a565b6116e8565b6116a5565b611531565b6114e6565b61142f565b61137b565b611296565b61126b565b6111b8565b611196565b6110a1565b610fe1565b610df2565b610d7b565b610cf7565b610bf5565b610add565b610a0a565b6108f5565b610800565b61075e565b610721565b610651565b610587565b61046d565b610337565b600435906001600160a01b03821682036102f257565b600080fd5b606435906001600160a01b03821682036102f257565b602435906001600160a01b03821682036102f257565b35906001600160a01b03821682036102f257565b346102f25760203660031901126102f2576103506102dc565b3360005260996020527f475b83c893df40ee19fd0783cf26478cdb58478dff65bb62560e1e7c36e0f22f61042c64ffffffffff6040600020541692610396841515612694565b6000848152609a60205260409020546103ca906103c3906001600160a01b03165b6001600160a01b031690565b33146126ec565b6103f8846103f26103e86103dd85610707565b5464ffffffffff1690565b64ffffffffff1690565b14612742565b61041261040482610707565b805464ffffffffff19169055565b6040516001600160a01b0390911681529081906020820190565b0390a2005b6084359064ffffffffff821682036102f257565b6024359064ffffffffff821682036102f257565b6044359064ffffffffff821682036102f257565b346102f25760a03660031901126102f2576105856004356024356044356104926102f7565b9161049b610431565b936104ab60018260f81c146127a3565b6104ca603c61ffff6104c3600885901c5b61ffff1690565b16146127ef565b6104ff6104de60ff83166139f4565b6139f4565b60ff6104f76104f16104d9601887901c82565b60ff1690565b911614612835565b600081815260ce60205260409020610533906001600160d01b039061052c905b546001600160d01b031690565b161561288b565b61055064174876e80060d083901c64ffffffffff165b11156128cd565b610580611c2061056d603084901c64ffffffffff165b429061295f565b61057a610e10821161296c565b106129ae565b612a5c565b005b346102f25760403660031901126102f25760043561062a6105a661030d565b610135546105be906001600160a01b03163314612cfc565b8260005260ce6020526105df6001808060d01b036040600020541611612d52565b6105f6603084901c64ffffffffff165b4211612d94565b600083815260ce6020526040902080546001600160d01b031916905560ff83169060d084901c64ffffffffff165b91613ea0565b7ff6b6b4f7a13f02512c1b3aa8dcc4a07d7775a6a4becbd439efcbd37c5408e67f600080a2005b346102f25760203660031901126102f257600435600090815260ce60205260409020546001600160a01b03602882901c16906001600160d01b03811690826106cc57506106c86000925b604080516001600160a01b0392831681529490911660208501529115159183019190915281906060820190565b0390f35b6107016106f464ffffffffff6106c8931664ffffffffff16600052609a602052604060002090565b546001600160a01b031690565b9261069b565b6001600160a01b0316600090815260996020526040902090565b346102f25760203660031901126102f2576001600160a01b036107426102dc565b166000526066602052602060ff60406000205416604051908152f35b60203660031901126102f25761058560043561077f60018260f81c146127a3565b610794603c61ffff6104c3600885901c6104bc565b6107a36104de60ff83166139f4565b600081815260ce602052604090206107c7906001600160d01b039061052c9061051f565b6107e164174876e80060d083901c64ffffffffff16610549565b6107fb611c2061056d603084901c64ffffffffff16610566565b612e10565b346102f25760203660031901126102f2576108196102dc565b3360005260996020527fc94089e0c0b1b79fdecc6e64fb759cdd390590a15c7e50d281e681ea8273261c61042c64ffffffffff604060002054169261085f841515612694565b6000848152609a6020526040902054610884906103c3906001600160a01b03166103b7565b610897846103f26103e86103dd85610707565b6108d5816108b68664ffffffffff16600052609a602052604060002090565b80546001600160a01b0319166001600160a01b03909216919091179055565b604080513381526001600160a01b03909216602083015290918291820190565b346102f25760403660031901126102f257600435610911610445565b600082815260ce60205260409020546001600160d01b038116919064ffffffffff9061093f60018511612d52565b166109c55761099e9161096a64ffffffffff928361095f6103dd33610707565b9116931683146129ef565b1761097f8360005260ce602052604060002090565b80546001600160d01b0319166001600160d01b03909216919091179055565b7f60a99b51ae498c44acbbe11031aed2a06a32be66d2122e6e2a7a16c087865cc9600080a2005b60405162461bcd60e51b815260206004820152601b60248201527f5377617020626f6e64656420746f20616e6f7468657220706f6f6c00000000006044820152606490fd5b346102f25760203660031901126102f257610585610a266102dc565b610a7e7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610a5f30821415612ea2565b600080516020614edf833981519152546001600160a01b031614612f03565b610a9460018060a01b0361013454163314613397565b604051906020610aa48184610d3a565b60008352601f198101903690840137614036565b60409060031901126102f2576004359060243565ffffffffffff811681036102f25790565b610ae636610ab8565b610af1821515612f64565b64ffffffffff8116610b04811515612faa565b33600052609960205264ffffffffff80604060002054161603610b9f5765ffffffffffff81610b667f7d7d1df74ef3a6434d8d63dc0a25d13d5fa94dbe738c38a3cce26e6f892e2a769365ffffffffffff16600052609b602052604060002090565b610b71858254612e03565b9055610b8d8433610b88602885901c60ff166104f1565b613d5a565b6040519384521691806020810161042c565b60405162461bcd60e51b815260206004820152602860248201527f4e65656420616e20617574686f72697a65642061646472657373206173207468604482015267329039b4b3b732b960c11b6064820152608490fd5b346102f25760403660031901126102f257610c0e6102dc565b610c5b610c1961030d565b60005492610c3f60ff600886901c161580958196610cd9575b8115610cb9575b50612ff6565b83610c52600160ff196000541617600055565b610ca057613059565b610c6157005b610c7161ff001960005416600055565b604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249890602090a1005b610cb461010061ff00196000541617600055565b613059565b303b15915081610ccb575b5038610c39565b60ff16600114905038610cc4565b600160ff8216109150610c32565b6004359060ff821682036102f257565b346102f25760203660031901126102f2576020610d1a610d15610ce7565b613068565b6040519015158152f35b634e487b7160e01b600052604160045260246000fd5b90601f801991011681019081106001600160401b03821117610d5b57604052565b610d24565b6001600160401b038111610d5b57601f01601f191660200190565b60403660031901126102f257610d8f6102dc565b602435906001600160401b0382116102f257366023830112156102f257816004013590610dbb82610d60565b91610dc96040519384610d3a565b80835236602482860101116102f2576020816000926024610585970183870137840101526130a8565b346102f25760803660031901126102f257600435610f56610e3c610e146102f7565b610e2360018560f81c146127a3565b610e36603c61ffff8660201c16146127ef565b83614235565b610e6c6001600160501b0361052c610e5f84600052610101602052604060002090565b546001600160501b031690565b610f3b610f29610e7e6103dd33610707565b610e9064ffffffffff821615156131cc565b610e9942612dd7565b610eb7610eb0603089901c64ffffffffff1661294f565b8210613230565b601087901b60ff60281b1664ffffffffff831617610efb610ef3610eda8a614268565b9265ffffffffffff16600052609b602052604060002090565b91825461295f565b9055610f068761429d565b80610f7d575b5060281b69ffffffffff00000000001664ffffffffff9091161790565b91600052610101602052604060002090565b906001600160501b03166001600160501b0319825416179055565b7fbfb879c34323c5601fafe832c3a8a1e31e12c288695838726ddeada86034edb4600080a2005b60016000526066602052610fd9610ef3610fc185610fab600080516020614ebf8339815191525b5460ff1690565b60281b60ff60281b1664ffffffffff9091161790565b65ffffffffffff16600052609b602052604060002090565b905538610f0c565b346102f25760003660031901126102f2577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316300361103b57604051600080516020614edf8339815191528152602090f35b60405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c6044820152771b1959081d1a1c9bdd59da0819195b1959d85d1958d85b1b60421b6064820152608490fd5b346102f25760203660031901126102f257600435600081815260ce60205260409020546001600160d01b03166110d960018211612d52565b6110ed603083901c64ffffffffff166105ef565b60ff60c882901c166111515761062a906111246111148460005260ce602052604060002090565b80546001600160d01b0319169055565b60ff831690611140906103b79060281c6001600160a81b031681565b60d084901c64ffffffffff16610624565b60405162461bcd60e51b815260206004820152601d60248201527f5377617020746f6b656e206e6f742066726f6d20696e69746961746f720000006044820152606490fd5b346102f25760403660031901126102f257600435610f56610e3c610e1461030d565b346102f25760403660031901126102f2576004356111df6111d761030d565b600092614235565b815261010160205260408120546001600160501b03811691906001830361122c5750505060016000905b604080516001600160a01b0392909216825264ffffffffff929092166020820152f35b64ffffffffff9081168252609a6020526040909120546001600160a01b031691611265916103e89160281c165b6001600160501b031690565b90611209565b346102f25760203660031901126102f257602061128e611289610ce7565b61328a565b604051908152f35b60603660031901126102f2576105856004356112b061030d565b6112b8610459565b916112c860018260f81c146127a3565b6112dd603c61ffff6104c3600885901c6104bc565b6112ec6104de60ff83166139f4565b600081815260ce60205260409020611310906001600160d01b039061052c9061051f565b61132a64174876e80060d083901c64ffffffffff16610549565b611344611c2061056d603084901c64ffffffffff16610566565b613311565b60609060031901126102f25760043560ff811681036102f257906024359060443564ffffffffff811681036102f25790565b346102f25761138936611349565b6113a260018060a09594951b0361013454163314613397565b64ffffffffff81166000908152609a60205260409020546113cd906001600160a01b031615156133dd565b65ffffffffffff602883901b60ff60281b1616600052609b602052604060002080549184830392831161142a576114269361141e93610fc193559064ffffffffff60ff60281b91169160281b161790565b918254612e03565b9055005b612939565b346102f25760803660031901126102f25761058560043561144e61030d565b604435906064359261146560018260f81c146127a3565b61147a603c61ffff6104c3600885901c6104bc565b6114896104de60ff83166139f4565b600081815260ce602052604090206114ad906001600160d01b039061052c9061051f565b6114c764174876e80060d083901c64ffffffffff16610549565b6114e1611c2061056d603084901c64ffffffffff16610566565b613425565b346102f25760203660031901126102f2576001600160a01b036115076102dc565b166000526099602052602064ffffffffff60406000205416604051908152f35b801515036102f257565b346102f25760a03660031901126102f2576004356024356044356115e06115566102f7565b6084359261156384611527565b61157a61051f8760005260ce602052604060002090565b9461159060016001600160d01b03881611612d52565b603087901c64ffffffffff166115a542612de6565b1115611676576115c26111148860005260ce602052604060002090565b6115d96103b76001600160a81b03602889901c1681565b928761456d565b60ff83169164ffffffffff16901561164f5761141e610fc16116259261160e8664ffffffffff9060d01c1690565b9460281b60ff60281b1664ffffffffff9091161790565b90555b7f8d92c805c252261fcfff21ee60740eb8a38922469a7e6ee396976d57c22fc1c9600080a2005b906111406106f46116719364ffffffffff16600052609a602052604060002090565b611628565b6116a061168d8860005260ce602052604060002090565b80546001600160d01b0319166001179055565b6115c2565b346102f25760203660031901126102f25760043564ffffffffff81168091036102f257600052609a602052602060018060a01b0360406000205416604051908152f35b346102f25760203660031901126102f25765ffffffffffff60ff60281b61170d610ce7565b60281b1616600052609b6020526020604060002054604051908152f35b65ffffffffffff7f7d7d1df74ef3a6434d8d63dc0a25d13d5fa94dbe738c38a3cce26e6f892e2a7661175b36610ab8565b6117688294921515612f64565b64ffffffffff81166118058161177f811515612faa565b6117ae60018060a01b036117a76106f48464ffffffffff16600052609a602052604060002090565b16156135ab565b6117c66117c06103e86103dd33610707565b156135f7565b6117e5336108b68364ffffffffff16600052609a602052604060002090565b6117ee33610707565b9064ffffffffff1664ffffffffff19825416179055565b6118218265ffffffffffff16600052609b602052604060002090565b61182c868254612e03565b90556118438533610b88602886901c60ff166104f1565b6040513381527fb8d9c35a714d4e29eaf036b9bf8183a093c5573ac809453b4e8434e25c9126d290602090a26040519384521691806020810161042c565b60a09060031901126102f2576004359060243590604435906064356001600160a01b03811681036102f257906084356001600160a01b03811681036102f25790565b346102f25761198f6119d26119796118da36611881565b9396919490926118eb32331461364d565b611902603089901c64ffffffffff165b42106136a4565b6119166001600160a01b0386161515613560565b61196884600160ce1b8a1615159788611a8b575b611934828c614235565b9361196160016001600160501b0361195a610e5f89600052610101602052604060002090565b1611612d52565b888c61456d565b600052610101602052604060002090565b805469ffffffffffffffffffff19166001179055565b61199885614268565b9215611a47575b6119a885614839565b80611a09575b506119b88561429d565b806119f9575b506119cc601886901c6104f1565b856143a8565b7ffa628b578e095243f0544bfad9255f49d79d03a5bbf6c85875d05a215e247ad2600080a2005b611a03908361488a565b386119be565b9283611a149161295f565b92611a3f61141e610fc1611a278961485c565b899064ffffffffff60ff60281b91169160101b161790565b9055386119ae565b611a5a611a538661477a565b809461295f565b92611a8461141e601088901b60ff60281b1665ffffffffffff16600052609b602052604060002090565b905561199f565b61013554611aa3906001600160a01b03163314612cfc565b61192a565b346102f2576119d2611ab936611881565b9192611acd60018660f89897981c146127a3565b611ae0603c61ffff8860201c16146127ef565b611aeb32331461364d565b611aff6001600160a01b0384161515613560565b611b88611979600160ce1b881615159586611cf2575b8885611b218183614235565b92611b456001600160501b0361052c610e5f87600052610101602052604060002090565b611b516103dd33610707565b96611b6464ffffffffff891615156131cc565b8015611ccc5761196893611b819060301c64ffffffffff166118fb565b898d61456d565b611b9186614268565b93611bc1601088901b60ff60281b1664ffffffffff84161765ffffffffffff16600052609b602052604060002090565b611bcc86825461295f565b905515611c88575b611bdd86614839565b80611c4a575b50611bed8661429d565b80611c03575b506119cc9050601886901c6104f1565b60016000526066602052611c4391611c3090610fc190610fab600080516020614ebf833981519152610fa4565b611c3b82825461295f565b90558361488a565b3880611bf3565b9384611c559161295f565b93611c8061141e610fc1611c688a61485c565b8a9064ffffffffff60ff60281b91169160101b161790565b905538611be3565b611c9b611c948761477a565b809561295f565b93611cc561141e601089901b60ff60281b1665ffffffffffff16600052609b602052604060002090565b9055611bd4565b50505050866119685761013554611ced906001600160a01b03163314612cfc565b611968565b61013554611d0a906001600160a01b03163314612cfc565b611b15565b346102f25760203660031901126102f257610585611d2b6102dc565b61013554611d43906001600160a01b03163314612cfc565b614190565b6001600160401b038111610d5b5760051b60200190565b9080601f830112156102f257813590611d7782611d48565b92611d856040519485610d3a565b82845260208085019360051b8201019182116102f257602001915b818310611dad5750505090565b823560ff811681036102f257815260209283019201611da0565b346102f25760403660031901126102f2576004356001600160401b0381116102f257366023820112156102f257806004013590611e0382611d48565b91611e116040519384610d3a565b8083526024602084019160051b830101913683116102f257602401905b828210611e5e57602435846001600160401b0382116102f257611e58610585923690600401611d5f565b906136f0565b60208091611e6b84610323565b815201910190611e2e565b610585611e8236611881565b93611e9560018260f89694961c146127a3565b611eaa603c61ffff6104c3600885901c6104bc565b611eb96104de60ff83166139f4565b600081815260ce60205260409020611edd906001600160d01b039061052c9061051f565b611ef764174876e80060d083901c64ffffffffff16610549565b611f11611c2061056d603084901c64ffffffffff16610566565b613801565b346102f25760203660031901126102f257611f2f610ce7565b611f4560018060a01b0361013454163314613397565b60ff8116611f548115156148f5565b6000908152606560205260409020546001600160a01b03168015611fbd576001600160a01b03166000908152606660205260409020805460ff1916905561058590611fad905b60ff166000526065602052604060002090565b80546001600160a01b0319169055565b60405162461bcd60e51b815260206004820152602260248201527f546f6b656e20666f722074686520696e64657820646f6573206e6f74206578696044820152611cdd60f21b6064820152608490fd5b346102f25765ffffffffffff7f34c3d1c46f89307d63d8818fcc5c2a9c07a5f7a01ea4319bfba1899f40c6f40061204336610ab8565b6120508294921515612f64565b64ffffffffff8116612063811515612faa565b6000908152609a6020526040902054612086906001600160a01b031633146126ec565b6120a28165ffffffffffff16600052609b602052604060002090565b6120ad85825461295f565b9055610b8d84336120c4602885901c60ff166104f1565b613ea0565b6040810160408252825180915260206060830193019060005b81811061212a5750505060208183039101526020808351928381520192019060005b8181106121115750505090565b825160ff16845260209384019390920191600101612104565b82516001600160a01b03168552602094850194909201916001016120e2565b346102f25760003660031901126102f25760ff6000805b828082161061222357501661217d61217782613890565b91613890565b906000805b60ff8082161061219d5750506106c8604051928392836120c9565b6121af6103b76106f4611f9a8461387e565b6121bf575b60010160ff16612182565b90600161221a60ff926122156121da6106f4611f9a8861387e565b6121fa868416916121eb838b6137d7565b6001600160a01b039091169052565b61220d6122068861387e565b918a6137d7565b9060ff169052565b6137c6565b929150506121b4565b6122356103b76106f4611f9a8461387e565b612244575b6001018216612160565b90600161225184926137c6565b9291505061223a565b346102f25760403660031901126102f257602061128e6122786102dc565b61228061030d565b906138c2565b346102f25760403660031901126102f25761229f6102dc565b60243560ff811681036102f257610585916122c660018060a01b0361013454163314613397565b614a25565b60403660031901126102f2576004356024356001600160c81b03811691908281036102f2576105859260281c6001600160a01b03169064ffffffffff9061231860f885901c6001146127a3565b61232d603c61ffff6104c3600888901c6104bc565b61234f61233c60ff86166139f4565b60ff6104f76104f16104d960188a901c82565b600084815260ce60205260409020612373906001600160d01b039061052c9061051f565b61238d64174876e80060d086901c64ffffffffff16610549565b6123a7611c2061056d603087901c64ffffffffff16610566565b1691613311565b346102f25761240a65ffffffffffff6123c636611349565b9093916123df60018060a01b0361013454163314613397565b64ffffffffff82166000908152609a6020526040902054610fab906001600160a01b031615156133dd565b16600052609b6020526040600020805491820180921161142a5755005b346102f25760003660031901126102f257604051600f60f21b8152602090f35b346102f25760403660031901126102f25760043561251b61250861247261246c61030d565b84614235565b6124c061248d610e5f83600052610101602052604060002090565b6124a260016001600160501b03831611612d52565b6103e86124b964ffffffffff602884901c16611259565b4211613935565b601085901b60ff60281b1664ffffffffff8216176124e361141e610eda88614268565b90556124ee8561429d565b9081612542575b5050600052610101602052604060002090565b805469ffffffffffffffffffff19169055565b7fac7d23c4f0137a4cc35b0e4b4bc8061ea6cb65805e87ceb0a77ca0c85814858c600080a2005b6001600052606660205261256f9061141e90610fc190610fab600080516020614ebf833981519152610fa4565b905538806124f5565b346102f25760203660031901126102f2576105856125946102dc565b6125aa60018060a01b0361013454163314613397565b6140f8565b346102f25760203660031901126102f2576125c86102dc565b3360005260996020527fd49cde4f679ccef3d23ff07aae4f6845e1c661e23e9fe6a54da26f0723fb695f61042c64ffffffffff604060002054169261260e841515612694565b6000848152609a6020526040902054612633906103c3906001600160a01b03166103b7565b61264b6126456103e86103dd84610707565b15613976565b610412846117ee83610707565b346102f25760203660031901126102f25760ff612673610ce7565b166000526065602052602060018060a01b0360406000205416604051908152f35b1561269b57565b60405162461bcd60e51b815260206004820152602360248201527f546865207369676e657220646f6573206e6f74207265676973746572206120706044820152621bdbdb60ea1b6064820152608490fd5b156126f357565b60405162461bcd60e51b815260206004820152602160248201527f4e6565642074686520706f6f6c206f776e657220617320746865207369676e656044820152603960f91b6064820152608490fd5b1561274957565b60405162461bcd60e51b815260206004820152602c60248201527f41646472206973206e6f7420617574686f72697a656420666f7220746865207360448201526b1a59db995c89dcc81c1bdbdb60a21b6064820152608490fd5b156127aa57565b60405162461bcd60e51b815260206004820152601a60248201527f496e636f727265637420656e636f64696e672076657273696f6e0000000000006044820152606490fd5b156127f657565b60405162461bcd60e51b815260206004820152601760248201527629bbb0b8103737ba103337b9103a3434b99031b430b4b760491b6044820152606490fd5b1561283c57565b60405162461bcd60e51b815260206004820152602160248201527f496e2026206f757420746f6b656e20747970657320646f206e6f74206d6174636044820152600d60fb1b6064820152608490fd5b1561289257565b60405162461bcd60e51b81526020600482015260136024820152725377617020616c72656164792065786973747360681b6044820152606490fd5b156128d457565b60405162461bcd60e51b815260206004820152603760248201527f466f7220736563757269747920726561736f6e2c20616d6f756e742063616e6e6044820152766f742062652067726561746572207468616e203130306b60481b6064820152608490fd5b634e487b7160e01b600052601160045260246000fd5b61012b1981019190821161142a57565b9190820391821161142a57565b1561297357565b60405162461bcd60e51b815260206004820152601360248201527245787069726520747320746f6f206561726c7960681b6044820152606490fd5b156129b557565b60405162461bcd60e51b815260206004820152601260248201527145787069726520747320746f6f206c61746560701b6044820152606490fd5b156129f657565b60405162461bcd60e51b815260206004820152603860248201527f5369676e65722073686f756c6420626520616e20617574686f72697a6564206160448201527719191c995cdcc81bd9881d1a194819da5d995b881c1bdbdb60421b6064820152608490fd5b93909291600060209164ffffffffff841680151580612ce9575b612cc6575b506001600160a01b03851695612a92871515613ab1565b6001600160ff1b03821691612b7a90612ab1906104f19060ff1c612df5565b92612ad46fa2a8918ca85bafe22016d0b997e4df60600160ff1b03821115613afd565b600160cb1b8a16151560c361ffff612aef60088e901c6104bc565b16148614612c43578514612c2157780caa2927a71029b4b3b732b21026b2b9b9b0b3b29d0519998560391b5b60405166ffffffffffffff19909116878201908152601981018c905290612b4f81603984015b03601f198101835282610d3a565b519020925b604051948594859094939260ff6060936080840197845216602083015260408201520152565b838052039060015afa15612c1c57600051612bf593612bdf92612bcb929091612bad916001600160a01b03165b14613afd565b64ffffffffff1665010000000000600160c81b03602885901b161790565b61097f8560005260ce602052604060002090565b64ffffffffff60d084901c169060ff8416613d5a565b7f5ce4019f772fda6cb703b26bce3ec3006eb36b73f1d3a0eb441213317d9f5e9d600080a2565b613b3d565b780caa2927a71029b4b3b732b21026b2b9b9b0b3b29d0519990560391b612b1b565b8514612c915789604051612c8881612b418a82019485603c917f19457468657265756d205369676e6564204d6573736167653a0a3332000000008252601c8201520190565b51902092612b54565b89855285852086527f9862d877599564bcd97c37305a7b0fdbe621d9c2a125026f2ad601f754a75abc85526040852092612b54565b612ce3903384526099855264ffffffffff604085205416146129ef565b38612a7b565b50336001600160a01b0387161415612a76565b15612d0357565b60405162461bcd60e51b815260206004820152602160248201527f43616c6c6572206973206e6f7420746865207072656d69756d206d616e6167656044820152603960f91b6064820152608490fd5b15612d5957565b60405162461bcd60e51b815260206004820152601360248201527214ddd85c08191bd95cc81b9bdd08195e1a5cdd606a1b6044820152606490fd5b15612d9b57565b60405162461bcd60e51b815260206004820152601460248201527314ddd85c081a5cc81cdd1a5b1b081b1bd8dad95960621b6044820152606490fd5b90610960820180921161142a57565b90610e10820180921161142a57565b90601b820180921161142a57565b9190820180921161142a57565b600081815260ce6020526040902080546001600160d01b031916600117905560ff811660d082901c64ffffffffff1665ffffffffffff602884901b60ff60281b1660011716600052609b602052604060002091825482810180911161142a57612e7b93553390613d5a565b7f8d92c805c252261fcfff21ee60740eb8a38922469a7e6ee396976d57c22fc1c9600080a2565b15612ea957565b60405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201526b19195b1959d85d1958d85b1b60a21b6064820152608490fd5b15612f0a57565b60405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201526b6163746976652070726f787960a01b6064820152608490fd5b15612f6b57565b60405162461bcd60e51b8152602060048201526017602482015276416d6f756e74206d75737420626520706f73697469766560481b6044820152606490fd5b15612fb157565b60405162461bcd60e51b815260206004820152601a60248201527f43616e6e6f7420757365203020617320706f6f6c20696e6465780000000000006044820152606490fd5b15612ffd57565b60405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608490fd5b90611d43613066926140f8565b565b60ff8116906031821015918261309c575b821561308457505090565b60be10915081613092575090565b6003915081161490565b60408111159250613079565b906130e27f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610a5f30821415612ea2565b6130f860018060a01b0361013454163314613397565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff161561312c575061306690614c42565b6040516352d1902d60e01b8152906020826004816001600160a01b0387165afa6000928161319b575b506131775760405162461bcd60e51b81528061317360048201613fe7565b0390fd5b61306692613196600080516020614edf83398151915260019414613f89565b614b26565b6131be91935060203d6020116131c5575b6131b68183610d3a565b810190613f7a565b9138613155565b503d6131ac565b156131d357565b60405162461bcd60e51b815260206004820152602f60248201527f43616c6c6572206e6f7420726567697374657265642e2043616c6c206465706f60448201526e39b4ba20b7322932b3b4b9ba32b91760891b6064820152608490fd5b1561323757565b60405162461bcd60e51b815260206004820152602560248201527f43616e6e6f74206c6f636b20626563617573652065787069726554732069732060448201526439b7b7b71760d91b6064820152608490fd5b60ff166020811161329b5750600190565b60f2811480613309575b80613301575b156132b65750606490565b60708111806132f6575b156132cb5750606490565b607b811190816132ea575b506132e45764e8d4a5100090565b6103e890565b608091501115386132d6565b50607b8111156132c0565b5060016132ab565b5060016132a5565b91613379916000919064ffffffffff906001600160a01b031633811461339157600160c81b935b5065010000000000600160d01b039060281b1691169117178260005260ce60205260406000209060018060d01b031665ffffffffffff60d01b825416179055565b612bf564ffffffffff8260d01c163360ff8416613d5a565b83613338565b1561339e57565b60405162461bcd60e51b815260206004820152601760248201527621b0b63632b91034b9903737ba103a34329037bbb732b960491b6044820152606490fd5b156133e457565b60405162461bcd60e51b8152602060048201526019602482015278141bdbdb081a5b99195e081b9bdd081c9959da5cdd195c9959603a1b6044820152606490fd5b926135399261349a91613441603c61ffff8860201c16146127ef565b6134556001600160a01b0385161515613560565b6040805160208101888152606087901b6001600160601b031916928201929092526134838160548101612b41565b519020610135546001600160a01b031692906142fa565b60d083901c64ffffffffff169061352b60ff8516926134c4605887901c64ffffffffff168261295f565b936134ee602882901b60ff60281b1660011765ffffffffffff16600052609b602052604060002090565b6134f9838254612e03565b9055600160ff60281b601089901b16176000908152609b6020526040902061352286825461295f565b90553390613d5a565b336119cc601886901c6104f1565b7ffa628b578e095243f0544bfad9255f49d79d03a5bbf6c85875d05a215e247ad2600080a2565b1561356757565b606460405162461bcd60e51b815260206004820152602060248201527f526563697069656e742063616e6e6f74206265207a65726f20616464726573736044820152fd5b156135b257565b60405162461bcd60e51b815260206004820152601d60248201527f506f6f6c20696e64657820616c726561647920726567697374657265640000006044820152606490fd5b156135fe57565b60405162461bcd60e51b815260206004820152602160248201527f5369676e6572206164647265737320616c7265616479207265676973746572656044820152601960fa1b6064820152608490fd5b1561365457565b60405162461bcd60e51b815260206004820152602260248201527f43616e6e6f742062652063616c6c6564207468726f75676820636f6e74726163604482015261747360f01b6064820152608490fd5b156136ab57565b60405162461bcd60e51b815260206004820152601e60248201527f43616e6e6f742072656c656173652062656361757365206578706972656400006044820152606490fd5b909161370860018060a01b0361013454163314613397565b815183510361376a5760005b825160ff82169081101561376357906122158261375861375161374a61373d61375e978a6137d7565b516001600160a01b031690565b92896137d7565b5160ff1690565b90614a25565b613714565b5050915050565b60405162461bcd60e51b815260206004820152602e60248201527f546f6b656e7320616e6420696e64657865732073686f756c642068617665207460448201526d0d0ca40e6c2daca40d8cadccee8d60931b6064820152608490fd5b60ff1660ff811461142a5760010190565b80518210156137eb5760209160051b010190565b634e487b7160e01b600052603260045260246000fd5b9391839161380f938661456d565b600082815260ce6020526040902080546001600160d01b031916600117905564ffffffffff8260d01c1660ff83169165ffffffffffff6138598460ff60281b60019160281b161790565b16600052609b602052604060002092835483810180911161142a57612e7b9455613d5a565b60ff60019116019060ff821161142a57565b9061389a82611d48565b6138a76040519182610d3a565b82815280926138b8601f1991611d48565b0190602036910137565b6001600160a01b0390811660009081526066602090815260408083205494909316825260999052205464ffffffffff169060ff168115801561392d575b6139265761392291610fc1919064ffffffffff60ff60281b91169160281b161790565b5490565b5050600090565b5080156138ff565b1561393c57565b60405162461bcd60e51b815260206004820152601260248201527153776170207374696c6c20696e206c6f636b60701b6044820152606490fd5b1561397d57565b60405162461bcd60e51b815260206004820152602360248201527f4164647220697320617574686f72697a656420666f7220616e6f7468657220706044820152621bdbdb60ea1b6064820152608490fd5b60ff604f199116019060ff821161142a57565b60ff601f199116019060ff821161142a57565b60ff811660c08110613a0d575060021c603f1690565b90565b60408111613a1c575050600090565b60708111613a425750613a3d613a34613a0a9261387e565b60011c607f1690565b6139e1565b60801015613a9b5760405162461bcd60e51b8152602060048201526024808201527f546f6b656e20696e646578206e6f7420616c6c6f77656420666f72207377617060448201526370696e6760e01b6064820152608490fd5b613a0a906139ce565b60d01c64ffffffffff1690565b15613ab857565b60405162461bcd60e51b815260206004820152601e60248201527f5369676e65722063616e6e6f7420626520656d707479206164647265737300006044820152606490fd5b15613b0457565b60405162461bcd60e51b8152602060048201526011602482015270496e76616c6964207369676e617475726560781b6044820152606490fd5b6040513d6000823e3d90fd5b15613b5057565b606460405162461bcd60e51b815260206004820152602060248201527f416d6f756e74206d7573742062652067726561746572207468616e207a65726f6044820152fd5b15613b9b57565b60405162461bcd60e51b8152602060048201526013602482015272151bdad95b881b9bdd081cdd5c1c1bdc9d1959606a1b6044820152606490fd5b15613bdd57565b60405162461bcd60e51b815260206004820152602960248201527f54686520676976656e20746f6b656e2061646472657373206973206e6f7420616044820152680818dbdb9d1c9858dd60ba1b6064820152608490fd5b9064e8d4a5100082029180830464e8d4a51000149015171561142a57565b9060058202918083046005149015171561142a57565b8181029291811591840414171561142a57565b3d15613ca6573d90613c8c82610d60565b91613c9a6040519384610d3a565b82523d6000602084013e565b606090565b908160209103126102f25751613a0a81611527565b15613cc757565b60405162461bcd60e51b81526020600482015260136024820152721d1c985b9cd9995c919c9bdb4819985a5b1959606a1b6044820152606490fd5b15613d0957565b60405162461bcd60e51b815260206004820152602360248201527f6d73672e76616c756520646f6573206e6f74206d617463682074686520616d6f6044820152621d5b9d60ea1b6064820152608490fd5b90613d66831515613b49565b613d6f82613068565b15613d89575050613d8261306691613c34565b3414613d02565b816000929183612b41613e1b613de161306698613ddb613dba6106f4879a60ff166000526065602052604060002090565b97613dcf6001600160a01b038a161515613b94565b611289893b1515613bd6565b90613c68565b6040516323b872dd60e01b602082019081526001600160a01b03909616602482015230604482015260648101919091529182906084820190565b51925af1613e27613c7b565b81613e33575b50613cc0565b8051801592508215613e48575b505038613e2d565b613e5b9250602080918301019101613cab565b3880613e40565b15613e6957565b60405162461bcd60e51b815260206004820152600f60248201526e1d1c985b9cd9995c8819985a5b1959608a1b6044820152606490fd5b919091613eac81613068565b15613ebb57506130669161488a565b80613066936000612b41613f33613eff8397613ddb613ee8869960ff166000526065602052604060002090565b546001600160a01b031697611289893b1515613bd6565b60405163a9059cbb60e01b602082019081526001600160a01b03909616602482015260448101919091529182906064820190565b51925af1613f3f613c7b565b81613f4b575b50613e62565b8051801592508215613f60575b505038613f45565b613f739250602080918301019101613cab565b3880613f58565b908160209103126102f2575190565b15613f9057565b60405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608490fd5b60809060208152602e60208201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960408201526d6f6e206973206e6f74205555505360901b60608201520190565b906140627f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1690565b15614071575061306690614c42565b6040516352d1902d60e01b8152906020826004816001600160a01b0387165afa600092816140d7575b506140b85760405162461bcd60e51b81528061317360048201613fe7565b61306692613196600080516020614edf83398151915260009414613f89565b6140f191935060203d6020116131c5576131b68183610d3a565b913861409a565b6001600160a01b0316801561414c5761013480546001600160a01b0319811683179091556001600160a01b03167f8934ce4adea8d9ce0d714d2c22b86790e41b7731c84b926fbbdc1d40ff6533c9600080a3565b606460405162461bcd60e51b815260206004820152602060248201527f4e6577206f776e65722063616e6e6f74206265207a65726f20616464726573736044820152fd5b6001600160a01b031680156141e45761013580546001600160a01b0319811683179091556001600160a01b03167f4798f31ad3d0ccde6359edf35fc39b882e4e1cff2968ca749b72074d373db27a600080a3565b60405162461bcd60e51b815260206004820152602360248201527f4e6577207072656d69756d206d616e61676572206265207a65726f206164647260448201526265737360e81b6064820152608490fd5b604080516020810192835260609390931b6001600160601b03191690830152906142628160548101612b41565b51902090565b64ffffffffff8160d01c169064ffffffffff8160581c16820391821161142a5761429190614cd3565b810390811161142a5790565b6142a681614cd3565b90811580156142b757505050600090565b612710830292830461271014171561142a5761ffff6142d99160b01c16614d5a565b9081156142e4570490565b634e487b7160e01b600052601260045260246000fd5b6001600160a01b03909316929190614313841515613ab1565b60018060ff1b0382169160ff1c601b810180911161142a5760209360009360ff936143829261435a6fa2a8918ca85bafe22016d0b997e4df60600160ff1b03841115613afd565b6040519586951690859094939260ff6060936080840197845216602083015260408201520152565b838052039060015afa15612c1c57600051613066916001600160a01b0390911614613afd565b600160cf1b81166145555760801c6001600160401b0316936143d9906143d0853b1515614dc1565b613ddb8361328a565b906143e381613068565b1561446a575060405163bff4163f60e01b815260006004820152602481018290526001600160a01b0392831660448201526001600160401b03949094166064850152602092849260849284929091165af18015612c1c57614442575b50565b61443f9060203d602011614463575b61445b8183610d3a565b810190613cab565b503d614451565b6106f46144879194929460ff166000526065602052604060002090565b92614494843b1515613bd6565b60405163095ea7b360e01b81526001600160a01b038316600482015260248101829052936020858060448101038160006001600160a01b0386165af1908115612c1c5760209560009261453a575b5060405163bff4163f60e01b81526001600160a01b039182166004820152602481019390935293841660448301526001600160401b03959095166064820152938492608492849291165af18015612c1c576144425750565b61455090873d89116144635761445b8183610d3a565b6144e2565b50928092915061456457505050565b61306692613ea0565b6001600160a01b03909416936020936000939161465a9190614590881515613ab1565b6001600160ff1b038216916145ab906104f19060ff1c612df5565b946145ce6fa2a8918ca85bafe22016d0b997e4df60600160ff1b03841115613afd565b600160cb1b8216151560c361ffff6145e96104bc8660081c90565b161488146146a557871461467e57780caa2927a71029b4b3b732b21026b2b9b9b0b3b29d051a998560391b91612b4f905b612b416040519384928c8401968791604d939166ffffffffffffff1916835260198301526bffffffffffffffffffffffff199060601b1660398201520190565b838052039060015afa15612c1c5760005161306691906001600160a01b0316612ba7565b780caa2927a71029b4b3b732b21026b2b9b9b0b3b29d0519990560391b91612b4f9061461a565b87146146ff576040517f19457468657265756d205369676e6564204d6573736167653a0a353200000000898201908152601c81019390935260609190911b6001600160601b031916603c830152612c888160508401612b41565b9060c36147126104bc6104bc8460201c90565b148714614753577f28cf5b919ed55db2b14d9e8b261a523eafb98bab117d3a8a56e559791415d17c915b601452865260348620875285526040852092612b54565b7f743e50106a7f059b52151dd4ba27a5f6c87b925ddfbdcf1c332e800da4b3df929161473c565b60ff811660fc81106147c057506147ae6147a66147a16101f49360d01c64ffffffffff1690565b613c52565b612710900490565b90808211156147bb575090565b905090565b60f881106147e357506147ae6147a66147a16113889360d01c64ffffffffff1690565b60f481106147fe57506147ae6147a66147a16101f493613aa4565b60f01161481e576147ae6147a66147a1600a9360d01c64ffffffffff1690565b6147ae6147a66147a16207a1209360d01c64ffffffffff1690565b61484281614e23565b61484c5750600090565b61ffff613a0a9160a01c16614d5a565b61486581614e23565b61486f5750600090565b60b01c61ffff16620100000164ffffffffff811161142a5790565b64e8d4a5100082029180830464e8d4a51000149015171561142a57600080809381935af16148b6613c7b565b50156148be57565b60405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b6044820152606490fd5b156148fc57565b60405162461bcd60e51b815260206004820152601b60248201527f43616e6e6f7420757365203020617320746f6b656e20696e64657800000000006044820152606490fd5b1561494857565b60405162461bcd60e51b815260206004820152601b60248201527f546f6b656e20686173206265656e206164646564206265666f726500000000006044820152606490fd5b1561499457565b60405162461bcd60e51b8152602060048201526013602482015272125b99195e081a185cc81899595b881d5cd959606a1b6044820152606490fd5b156149d657565b60405162461bcd60e51b815260206004820152602160248201527f436f726520746f6b656e207265717569726573206164646472657373283078316044820152602960f81b6064820152608490fd5b614a3360ff831615156148f5565b6001600160a01b0381168015614ae757613066926108b691614a76614a706104f1610fa48760018060a01b03166000526066602052604060002090565b15614941565b614a9c614a966103b76106f48560ff166000526065602052604060002090565b1561498d565b614aa582613068565b614ad5575b506001600160a01b0383166000908152606660205260409020805460ff191660ff8316179055611f9a565b6001614ae191146149cf565b38614aaa565b60405162461bcd60e51b815260206004820152601760248201527643616e6e6f7420757365207a65726f206164647265737360481b6044820152606490fd5b9091614b3182614c42565b604051906001600160a01b0383167fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b600080a283511590811591614c3a575b50614b7a57505050565b813b15614be957506000828192602061443f95519201905af4614b9b613c7b565b60405191614baa606084610d3a565b602783527f416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c6020840152660819985a5b195960ca1b6040840152614e47565b62461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608490fd5b905038614b70565b803b15614c7857600080516020614edf83398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b60405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608490fd5b614cdc81614d9e565b614ce65750600090565b61ffff8160a01c1661ffff8114614d1957614d019150614d5a565b6103e88102908082046103e8149015171561142a5790565b5060d081901c64ffffffffff1690605881901c64ffffffffff16820391821161142a57600160ce1b811615614d4c575090565b614d559061477a565b614291565b6103e8811115613a0a576103e719810190811161142a576123288106906103e8820180921161142a57612328900490604d821161142a57613a0a91600a0a90613c68565b60bf60ff8260181c16109081614db2575090565b61084160c41b90811614919050565b15614dc857565b60405162461bcd60e51b815260206004820152602d60248201527f54686520676976656e20726563697069656e742061646472657373206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608490fd5b600160cf1b811615159081614e36575090565b600360c91b16600160c91b14919050565b90919015614e53575090565b815115614e635750805190602001fd5b6040519062461bcd60e51b8252602060048301528181519182602483015260005b838110614ea65750508160006044809484010152601f80199101168101030190fd5b60208282018101516044878401015285935001614e8456fee34b8b74e1cdcaa1b90aa77af7dd89e496ad9a4ae4a4d4759712101c7da2dce6360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca164736f6c634300081c000a
Deployed Bytecode
0x6080604052600436101561001257600080fd5b60003560e01c8063051119f5146102d75780630ffad9c0146102d257806316f35d23146102cd5780631e2a6075146102c85780632335093c146102c3578063264849e7146102be57806330f00f3a146102b957806335eff30f146102b45780633659cfe6146102af57806337b90a4f146102aa578063485cc955146102a55780634a2377e2146102a05780634f1ef2861461029b578063515147ab1461029657806352d1902d1461029157806354d6a2b71461028c57806358d9b4e11461028757806360a2da98146102825780636484396e1461027d5780636f9b41fd146102785780637234cd9514610273578063741c8e2d1461026e5780637fe0282b14610269578063827c87cc1461026457806389a734c01461025f5780638b0a77651461025a5780638f487dc914610255578063a5c9c66c14610250578063ab115fd81461024b578063b805f32114610246578063c11d9ecb14610241578063c8173c441461023c578063cb4f999b14610237578063ce7f79b914610232578063d3c7c2c71461022d578063d3e95ea414610228578063d4f8232214610223578063decf2a481461021e578063eaf250b514610219578063eba7fb7714610214578063f1d2ec1d1461020f578063f2fde38b1461020a578063ff22f272146102055763ff3787191461020057600080fd5b612658565b6125af565b612578565b612447565b612427565b6123ae565b6122cb565b612286565b61225a565b612149565b61200d565b611f16565b611e76565b611dc7565b611d0f565b611aa8565b6118c3565b61172a565b6116e8565b6116a5565b611531565b6114e6565b61142f565b61137b565b611296565b61126b565b6111b8565b611196565b6110a1565b610fe1565b610df2565b610d7b565b610cf7565b610bf5565b610add565b610a0a565b6108f5565b610800565b61075e565b610721565b610651565b610587565b61046d565b610337565b600435906001600160a01b03821682036102f257565b600080fd5b606435906001600160a01b03821682036102f257565b602435906001600160a01b03821682036102f257565b35906001600160a01b03821682036102f257565b346102f25760203660031901126102f2576103506102dc565b3360005260996020527f475b83c893df40ee19fd0783cf26478cdb58478dff65bb62560e1e7c36e0f22f61042c64ffffffffff6040600020541692610396841515612694565b6000848152609a60205260409020546103ca906103c3906001600160a01b03165b6001600160a01b031690565b33146126ec565b6103f8846103f26103e86103dd85610707565b5464ffffffffff1690565b64ffffffffff1690565b14612742565b61041261040482610707565b805464ffffffffff19169055565b6040516001600160a01b0390911681529081906020820190565b0390a2005b6084359064ffffffffff821682036102f257565b6024359064ffffffffff821682036102f257565b6044359064ffffffffff821682036102f257565b346102f25760a03660031901126102f2576105856004356024356044356104926102f7565b9161049b610431565b936104ab60018260f81c146127a3565b6104ca603c61ffff6104c3600885901c5b61ffff1690565b16146127ef565b6104ff6104de60ff83166139f4565b6139f4565b60ff6104f76104f16104d9601887901c82565b60ff1690565b911614612835565b600081815260ce60205260409020610533906001600160d01b039061052c905b546001600160d01b031690565b161561288b565b61055064174876e80060d083901c64ffffffffff165b11156128cd565b610580611c2061056d603084901c64ffffffffff165b429061295f565b61057a610e10821161296c565b106129ae565b612a5c565b005b346102f25760403660031901126102f25760043561062a6105a661030d565b610135546105be906001600160a01b03163314612cfc565b8260005260ce6020526105df6001808060d01b036040600020541611612d52565b6105f6603084901c64ffffffffff165b4211612d94565b600083815260ce6020526040902080546001600160d01b031916905560ff83169060d084901c64ffffffffff165b91613ea0565b7ff6b6b4f7a13f02512c1b3aa8dcc4a07d7775a6a4becbd439efcbd37c5408e67f600080a2005b346102f25760203660031901126102f257600435600090815260ce60205260409020546001600160a01b03602882901c16906001600160d01b03811690826106cc57506106c86000925b604080516001600160a01b0392831681529490911660208501529115159183019190915281906060820190565b0390f35b6107016106f464ffffffffff6106c8931664ffffffffff16600052609a602052604060002090565b546001600160a01b031690565b9261069b565b6001600160a01b0316600090815260996020526040902090565b346102f25760203660031901126102f2576001600160a01b036107426102dc565b166000526066602052602060ff60406000205416604051908152f35b60203660031901126102f25761058560043561077f60018260f81c146127a3565b610794603c61ffff6104c3600885901c6104bc565b6107a36104de60ff83166139f4565b600081815260ce602052604090206107c7906001600160d01b039061052c9061051f565b6107e164174876e80060d083901c64ffffffffff16610549565b6107fb611c2061056d603084901c64ffffffffff16610566565b612e10565b346102f25760203660031901126102f2576108196102dc565b3360005260996020527fc94089e0c0b1b79fdecc6e64fb759cdd390590a15c7e50d281e681ea8273261c61042c64ffffffffff604060002054169261085f841515612694565b6000848152609a6020526040902054610884906103c3906001600160a01b03166103b7565b610897846103f26103e86103dd85610707565b6108d5816108b68664ffffffffff16600052609a602052604060002090565b80546001600160a01b0319166001600160a01b03909216919091179055565b604080513381526001600160a01b03909216602083015290918291820190565b346102f25760403660031901126102f257600435610911610445565b600082815260ce60205260409020546001600160d01b038116919064ffffffffff9061093f60018511612d52565b166109c55761099e9161096a64ffffffffff928361095f6103dd33610707565b9116931683146129ef565b1761097f8360005260ce602052604060002090565b80546001600160d01b0319166001600160d01b03909216919091179055565b7f60a99b51ae498c44acbbe11031aed2a06a32be66d2122e6e2a7a16c087865cc9600080a2005b60405162461bcd60e51b815260206004820152601b60248201527f5377617020626f6e64656420746f20616e6f7468657220706f6f6c00000000006044820152606490fd5b346102f25760203660031901126102f257610585610a266102dc565b610a7e7f000000000000000000000000370634e1064b945e9010ddfa6077f321eca431cf6001600160a01b0316610a5f30821415612ea2565b600080516020614edf833981519152546001600160a01b031614612f03565b610a9460018060a01b0361013454163314613397565b604051906020610aa48184610d3a565b60008352601f198101903690840137614036565b60409060031901126102f2576004359060243565ffffffffffff811681036102f25790565b610ae636610ab8565b610af1821515612f64565b64ffffffffff8116610b04811515612faa565b33600052609960205264ffffffffff80604060002054161603610b9f5765ffffffffffff81610b667f7d7d1df74ef3a6434d8d63dc0a25d13d5fa94dbe738c38a3cce26e6f892e2a769365ffffffffffff16600052609b602052604060002090565b610b71858254612e03565b9055610b8d8433610b88602885901c60ff166104f1565b613d5a565b6040519384521691806020810161042c565b60405162461bcd60e51b815260206004820152602860248201527f4e65656420616e20617574686f72697a65642061646472657373206173207468604482015267329039b4b3b732b960c11b6064820152608490fd5b346102f25760403660031901126102f257610c0e6102dc565b610c5b610c1961030d565b60005492610c3f60ff600886901c161580958196610cd9575b8115610cb9575b50612ff6565b83610c52600160ff196000541617600055565b610ca057613059565b610c6157005b610c7161ff001960005416600055565b604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249890602090a1005b610cb461010061ff00196000541617600055565b613059565b303b15915081610ccb575b5038610c39565b60ff16600114905038610cc4565b600160ff8216109150610c32565b6004359060ff821682036102f257565b346102f25760203660031901126102f2576020610d1a610d15610ce7565b613068565b6040519015158152f35b634e487b7160e01b600052604160045260246000fd5b90601f801991011681019081106001600160401b03821117610d5b57604052565b610d24565b6001600160401b038111610d5b57601f01601f191660200190565b60403660031901126102f257610d8f6102dc565b602435906001600160401b0382116102f257366023830112156102f257816004013590610dbb82610d60565b91610dc96040519384610d3a565b80835236602482860101116102f2576020816000926024610585970183870137840101526130a8565b346102f25760803660031901126102f257600435610f56610e3c610e146102f7565b610e2360018560f81c146127a3565b610e36603c61ffff8660201c16146127ef565b83614235565b610e6c6001600160501b0361052c610e5f84600052610101602052604060002090565b546001600160501b031690565b610f3b610f29610e7e6103dd33610707565b610e9064ffffffffff821615156131cc565b610e9942612dd7565b610eb7610eb0603089901c64ffffffffff1661294f565b8210613230565b601087901b60ff60281b1664ffffffffff831617610efb610ef3610eda8a614268565b9265ffffffffffff16600052609b602052604060002090565b91825461295f565b9055610f068761429d565b80610f7d575b5060281b69ffffffffff00000000001664ffffffffff9091161790565b91600052610101602052604060002090565b906001600160501b03166001600160501b0319825416179055565b7fbfb879c34323c5601fafe832c3a8a1e31e12c288695838726ddeada86034edb4600080a2005b60016000526066602052610fd9610ef3610fc185610fab600080516020614ebf8339815191525b5460ff1690565b60281b60ff60281b1664ffffffffff9091161790565b65ffffffffffff16600052609b602052604060002090565b905538610f0c565b346102f25760003660031901126102f2577f000000000000000000000000370634e1064b945e9010ddfa6077f321eca431cf6001600160a01b0316300361103b57604051600080516020614edf8339815191528152602090f35b60405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c6044820152771b1959081d1a1c9bdd59da0819195b1959d85d1958d85b1b60421b6064820152608490fd5b346102f25760203660031901126102f257600435600081815260ce60205260409020546001600160d01b03166110d960018211612d52565b6110ed603083901c64ffffffffff166105ef565b60ff60c882901c166111515761062a906111246111148460005260ce602052604060002090565b80546001600160d01b0319169055565b60ff831690611140906103b79060281c6001600160a81b031681565b60d084901c64ffffffffff16610624565b60405162461bcd60e51b815260206004820152601d60248201527f5377617020746f6b656e206e6f742066726f6d20696e69746961746f720000006044820152606490fd5b346102f25760403660031901126102f257600435610f56610e3c610e1461030d565b346102f25760403660031901126102f2576004356111df6111d761030d565b600092614235565b815261010160205260408120546001600160501b03811691906001830361122c5750505060016000905b604080516001600160a01b0392909216825264ffffffffff929092166020820152f35b64ffffffffff9081168252609a6020526040909120546001600160a01b031691611265916103e89160281c165b6001600160501b031690565b90611209565b346102f25760203660031901126102f257602061128e611289610ce7565b61328a565b604051908152f35b60603660031901126102f2576105856004356112b061030d565b6112b8610459565b916112c860018260f81c146127a3565b6112dd603c61ffff6104c3600885901c6104bc565b6112ec6104de60ff83166139f4565b600081815260ce60205260409020611310906001600160d01b039061052c9061051f565b61132a64174876e80060d083901c64ffffffffff16610549565b611344611c2061056d603084901c64ffffffffff16610566565b613311565b60609060031901126102f25760043560ff811681036102f257906024359060443564ffffffffff811681036102f25790565b346102f25761138936611349565b6113a260018060a09594951b0361013454163314613397565b64ffffffffff81166000908152609a60205260409020546113cd906001600160a01b031615156133dd565b65ffffffffffff602883901b60ff60281b1616600052609b602052604060002080549184830392831161142a576114269361141e93610fc193559064ffffffffff60ff60281b91169160281b161790565b918254612e03565b9055005b612939565b346102f25760803660031901126102f25761058560043561144e61030d565b604435906064359261146560018260f81c146127a3565b61147a603c61ffff6104c3600885901c6104bc565b6114896104de60ff83166139f4565b600081815260ce602052604090206114ad906001600160d01b039061052c9061051f565b6114c764174876e80060d083901c64ffffffffff16610549565b6114e1611c2061056d603084901c64ffffffffff16610566565b613425565b346102f25760203660031901126102f2576001600160a01b036115076102dc565b166000526099602052602064ffffffffff60406000205416604051908152f35b801515036102f257565b346102f25760a03660031901126102f2576004356024356044356115e06115566102f7565b6084359261156384611527565b61157a61051f8760005260ce602052604060002090565b9461159060016001600160d01b03881611612d52565b603087901c64ffffffffff166115a542612de6565b1115611676576115c26111148860005260ce602052604060002090565b6115d96103b76001600160a81b03602889901c1681565b928761456d565b60ff83169164ffffffffff16901561164f5761141e610fc16116259261160e8664ffffffffff9060d01c1690565b9460281b60ff60281b1664ffffffffff9091161790565b90555b7f8d92c805c252261fcfff21ee60740eb8a38922469a7e6ee396976d57c22fc1c9600080a2005b906111406106f46116719364ffffffffff16600052609a602052604060002090565b611628565b6116a061168d8860005260ce602052604060002090565b80546001600160d01b0319166001179055565b6115c2565b346102f25760203660031901126102f25760043564ffffffffff81168091036102f257600052609a602052602060018060a01b0360406000205416604051908152f35b346102f25760203660031901126102f25765ffffffffffff60ff60281b61170d610ce7565b60281b1616600052609b6020526020604060002054604051908152f35b65ffffffffffff7f7d7d1df74ef3a6434d8d63dc0a25d13d5fa94dbe738c38a3cce26e6f892e2a7661175b36610ab8565b6117688294921515612f64565b64ffffffffff81166118058161177f811515612faa565b6117ae60018060a01b036117a76106f48464ffffffffff16600052609a602052604060002090565b16156135ab565b6117c66117c06103e86103dd33610707565b156135f7565b6117e5336108b68364ffffffffff16600052609a602052604060002090565b6117ee33610707565b9064ffffffffff1664ffffffffff19825416179055565b6118218265ffffffffffff16600052609b602052604060002090565b61182c868254612e03565b90556118438533610b88602886901c60ff166104f1565b6040513381527fb8d9c35a714d4e29eaf036b9bf8183a093c5573ac809453b4e8434e25c9126d290602090a26040519384521691806020810161042c565b60a09060031901126102f2576004359060243590604435906064356001600160a01b03811681036102f257906084356001600160a01b03811681036102f25790565b346102f25761198f6119d26119796118da36611881565b9396919490926118eb32331461364d565b611902603089901c64ffffffffff165b42106136a4565b6119166001600160a01b0386161515613560565b61196884600160ce1b8a1615159788611a8b575b611934828c614235565b9361196160016001600160501b0361195a610e5f89600052610101602052604060002090565b1611612d52565b888c61456d565b600052610101602052604060002090565b805469ffffffffffffffffffff19166001179055565b61199885614268565b9215611a47575b6119a885614839565b80611a09575b506119b88561429d565b806119f9575b506119cc601886901c6104f1565b856143a8565b7ffa628b578e095243f0544bfad9255f49d79d03a5bbf6c85875d05a215e247ad2600080a2005b611a03908361488a565b386119be565b9283611a149161295f565b92611a3f61141e610fc1611a278961485c565b899064ffffffffff60ff60281b91169160101b161790565b9055386119ae565b611a5a611a538661477a565b809461295f565b92611a8461141e601088901b60ff60281b1665ffffffffffff16600052609b602052604060002090565b905561199f565b61013554611aa3906001600160a01b03163314612cfc565b61192a565b346102f2576119d2611ab936611881565b9192611acd60018660f89897981c146127a3565b611ae0603c61ffff8860201c16146127ef565b611aeb32331461364d565b611aff6001600160a01b0384161515613560565b611b88611979600160ce1b881615159586611cf2575b8885611b218183614235565b92611b456001600160501b0361052c610e5f87600052610101602052604060002090565b611b516103dd33610707565b96611b6464ffffffffff891615156131cc565b8015611ccc5761196893611b819060301c64ffffffffff166118fb565b898d61456d565b611b9186614268565b93611bc1601088901b60ff60281b1664ffffffffff84161765ffffffffffff16600052609b602052604060002090565b611bcc86825461295f565b905515611c88575b611bdd86614839565b80611c4a575b50611bed8661429d565b80611c03575b506119cc9050601886901c6104f1565b60016000526066602052611c4391611c3090610fc190610fab600080516020614ebf833981519152610fa4565b611c3b82825461295f565b90558361488a565b3880611bf3565b9384611c559161295f565b93611c8061141e610fc1611c688a61485c565b8a9064ffffffffff60ff60281b91169160101b161790565b905538611be3565b611c9b611c948761477a565b809561295f565b93611cc561141e601089901b60ff60281b1665ffffffffffff16600052609b602052604060002090565b9055611bd4565b50505050866119685761013554611ced906001600160a01b03163314612cfc565b611968565b61013554611d0a906001600160a01b03163314612cfc565b611b15565b346102f25760203660031901126102f257610585611d2b6102dc565b61013554611d43906001600160a01b03163314612cfc565b614190565b6001600160401b038111610d5b5760051b60200190565b9080601f830112156102f257813590611d7782611d48565b92611d856040519485610d3a565b82845260208085019360051b8201019182116102f257602001915b818310611dad5750505090565b823560ff811681036102f257815260209283019201611da0565b346102f25760403660031901126102f2576004356001600160401b0381116102f257366023820112156102f257806004013590611e0382611d48565b91611e116040519384610d3a565b8083526024602084019160051b830101913683116102f257602401905b828210611e5e57602435846001600160401b0382116102f257611e58610585923690600401611d5f565b906136f0565b60208091611e6b84610323565b815201910190611e2e565b610585611e8236611881565b93611e9560018260f89694961c146127a3565b611eaa603c61ffff6104c3600885901c6104bc565b611eb96104de60ff83166139f4565b600081815260ce60205260409020611edd906001600160d01b039061052c9061051f565b611ef764174876e80060d083901c64ffffffffff16610549565b611f11611c2061056d603084901c64ffffffffff16610566565b613801565b346102f25760203660031901126102f257611f2f610ce7565b611f4560018060a01b0361013454163314613397565b60ff8116611f548115156148f5565b6000908152606560205260409020546001600160a01b03168015611fbd576001600160a01b03166000908152606660205260409020805460ff1916905561058590611fad905b60ff166000526065602052604060002090565b80546001600160a01b0319169055565b60405162461bcd60e51b815260206004820152602260248201527f546f6b656e20666f722074686520696e64657820646f6573206e6f74206578696044820152611cdd60f21b6064820152608490fd5b346102f25765ffffffffffff7f34c3d1c46f89307d63d8818fcc5c2a9c07a5f7a01ea4319bfba1899f40c6f40061204336610ab8565b6120508294921515612f64565b64ffffffffff8116612063811515612faa565b6000908152609a6020526040902054612086906001600160a01b031633146126ec565b6120a28165ffffffffffff16600052609b602052604060002090565b6120ad85825461295f565b9055610b8d84336120c4602885901c60ff166104f1565b613ea0565b6040810160408252825180915260206060830193019060005b81811061212a5750505060208183039101526020808351928381520192019060005b8181106121115750505090565b825160ff16845260209384019390920191600101612104565b82516001600160a01b03168552602094850194909201916001016120e2565b346102f25760003660031901126102f25760ff6000805b828082161061222357501661217d61217782613890565b91613890565b906000805b60ff8082161061219d5750506106c8604051928392836120c9565b6121af6103b76106f4611f9a8461387e565b6121bf575b60010160ff16612182565b90600161221a60ff926122156121da6106f4611f9a8861387e565b6121fa868416916121eb838b6137d7565b6001600160a01b039091169052565b61220d6122068861387e565b918a6137d7565b9060ff169052565b6137c6565b929150506121b4565b6122356103b76106f4611f9a8461387e565b612244575b6001018216612160565b90600161225184926137c6565b9291505061223a565b346102f25760403660031901126102f257602061128e6122786102dc565b61228061030d565b906138c2565b346102f25760403660031901126102f25761229f6102dc565b60243560ff811681036102f257610585916122c660018060a01b0361013454163314613397565b614a25565b60403660031901126102f2576004356024356001600160c81b03811691908281036102f2576105859260281c6001600160a01b03169064ffffffffff9061231860f885901c6001146127a3565b61232d603c61ffff6104c3600888901c6104bc565b61234f61233c60ff86166139f4565b60ff6104f76104f16104d960188a901c82565b600084815260ce60205260409020612373906001600160d01b039061052c9061051f565b61238d64174876e80060d086901c64ffffffffff16610549565b6123a7611c2061056d603087901c64ffffffffff16610566565b1691613311565b346102f25761240a65ffffffffffff6123c636611349565b9093916123df60018060a01b0361013454163314613397565b64ffffffffff82166000908152609a6020526040902054610fab906001600160a01b031615156133dd565b16600052609b6020526040600020805491820180921161142a5755005b346102f25760003660031901126102f257604051600f60f21b8152602090f35b346102f25760403660031901126102f25760043561251b61250861247261246c61030d565b84614235565b6124c061248d610e5f83600052610101602052604060002090565b6124a260016001600160501b03831611612d52565b6103e86124b964ffffffffff602884901c16611259565b4211613935565b601085901b60ff60281b1664ffffffffff8216176124e361141e610eda88614268565b90556124ee8561429d565b9081612542575b5050600052610101602052604060002090565b805469ffffffffffffffffffff19169055565b7fac7d23c4f0137a4cc35b0e4b4bc8061ea6cb65805e87ceb0a77ca0c85814858c600080a2005b6001600052606660205261256f9061141e90610fc190610fab600080516020614ebf833981519152610fa4565b905538806124f5565b346102f25760203660031901126102f2576105856125946102dc565b6125aa60018060a01b0361013454163314613397565b6140f8565b346102f25760203660031901126102f2576125c86102dc565b3360005260996020527fd49cde4f679ccef3d23ff07aae4f6845e1c661e23e9fe6a54da26f0723fb695f61042c64ffffffffff604060002054169261260e841515612694565b6000848152609a6020526040902054612633906103c3906001600160a01b03166103b7565b61264b6126456103e86103dd84610707565b15613976565b610412846117ee83610707565b346102f25760203660031901126102f25760ff612673610ce7565b166000526065602052602060018060a01b0360406000205416604051908152f35b1561269b57565b60405162461bcd60e51b815260206004820152602360248201527f546865207369676e657220646f6573206e6f74207265676973746572206120706044820152621bdbdb60ea1b6064820152608490fd5b156126f357565b60405162461bcd60e51b815260206004820152602160248201527f4e6565642074686520706f6f6c206f776e657220617320746865207369676e656044820152603960f91b6064820152608490fd5b1561274957565b60405162461bcd60e51b815260206004820152602c60248201527f41646472206973206e6f7420617574686f72697a656420666f7220746865207360448201526b1a59db995c89dcc81c1bdbdb60a21b6064820152608490fd5b156127aa57565b60405162461bcd60e51b815260206004820152601a60248201527f496e636f727265637420656e636f64696e672076657273696f6e0000000000006044820152606490fd5b156127f657565b60405162461bcd60e51b815260206004820152601760248201527629bbb0b8103737ba103337b9103a3434b99031b430b4b760491b6044820152606490fd5b1561283c57565b60405162461bcd60e51b815260206004820152602160248201527f496e2026206f757420746f6b656e20747970657320646f206e6f74206d6174636044820152600d60fb1b6064820152608490fd5b1561289257565b60405162461bcd60e51b81526020600482015260136024820152725377617020616c72656164792065786973747360681b6044820152606490fd5b156128d457565b60405162461bcd60e51b815260206004820152603760248201527f466f7220736563757269747920726561736f6e2c20616d6f756e742063616e6e6044820152766f742062652067726561746572207468616e203130306b60481b6064820152608490fd5b634e487b7160e01b600052601160045260246000fd5b61012b1981019190821161142a57565b9190820391821161142a57565b1561297357565b60405162461bcd60e51b815260206004820152601360248201527245787069726520747320746f6f206561726c7960681b6044820152606490fd5b156129b557565b60405162461bcd60e51b815260206004820152601260248201527145787069726520747320746f6f206c61746560701b6044820152606490fd5b156129f657565b60405162461bcd60e51b815260206004820152603860248201527f5369676e65722073686f756c6420626520616e20617574686f72697a6564206160448201527719191c995cdcc81bd9881d1a194819da5d995b881c1bdbdb60421b6064820152608490fd5b93909291600060209164ffffffffff841680151580612ce9575b612cc6575b506001600160a01b03851695612a92871515613ab1565b6001600160ff1b03821691612b7a90612ab1906104f19060ff1c612df5565b92612ad46fa2a8918ca85bafe22016d0b997e4df60600160ff1b03821115613afd565b600160cb1b8a16151560c361ffff612aef60088e901c6104bc565b16148614612c43578514612c2157780caa2927a71029b4b3b732b21026b2b9b9b0b3b29d0519998560391b5b60405166ffffffffffffff19909116878201908152601981018c905290612b4f81603984015b03601f198101835282610d3a565b519020925b604051948594859094939260ff6060936080840197845216602083015260408201520152565b838052039060015afa15612c1c57600051612bf593612bdf92612bcb929091612bad916001600160a01b03165b14613afd565b64ffffffffff1665010000000000600160c81b03602885901b161790565b61097f8560005260ce602052604060002090565b64ffffffffff60d084901c169060ff8416613d5a565b7f5ce4019f772fda6cb703b26bce3ec3006eb36b73f1d3a0eb441213317d9f5e9d600080a2565b613b3d565b780caa2927a71029b4b3b732b21026b2b9b9b0b3b29d0519990560391b612b1b565b8514612c915789604051612c8881612b418a82019485603c917f19457468657265756d205369676e6564204d6573736167653a0a3332000000008252601c8201520190565b51902092612b54565b89855285852086527f9862d877599564bcd97c37305a7b0fdbe621d9c2a125026f2ad601f754a75abc85526040852092612b54565b612ce3903384526099855264ffffffffff604085205416146129ef565b38612a7b565b50336001600160a01b0387161415612a76565b15612d0357565b60405162461bcd60e51b815260206004820152602160248201527f43616c6c6572206973206e6f7420746865207072656d69756d206d616e6167656044820152603960f91b6064820152608490fd5b15612d5957565b60405162461bcd60e51b815260206004820152601360248201527214ddd85c08191bd95cc81b9bdd08195e1a5cdd606a1b6044820152606490fd5b15612d9b57565b60405162461bcd60e51b815260206004820152601460248201527314ddd85c081a5cc81cdd1a5b1b081b1bd8dad95960621b6044820152606490fd5b90610960820180921161142a57565b90610e10820180921161142a57565b90601b820180921161142a57565b9190820180921161142a57565b600081815260ce6020526040902080546001600160d01b031916600117905560ff811660d082901c64ffffffffff1665ffffffffffff602884901b60ff60281b1660011716600052609b602052604060002091825482810180911161142a57612e7b93553390613d5a565b7f8d92c805c252261fcfff21ee60740eb8a38922469a7e6ee396976d57c22fc1c9600080a2565b15612ea957565b60405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201526b19195b1959d85d1958d85b1b60a21b6064820152608490fd5b15612f0a57565b60405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201526b6163746976652070726f787960a01b6064820152608490fd5b15612f6b57565b60405162461bcd60e51b8152602060048201526017602482015276416d6f756e74206d75737420626520706f73697469766560481b6044820152606490fd5b15612fb157565b60405162461bcd60e51b815260206004820152601a60248201527f43616e6e6f7420757365203020617320706f6f6c20696e6465780000000000006044820152606490fd5b15612ffd57565b60405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608490fd5b90611d43613066926140f8565b565b60ff8116906031821015918261309c575b821561308457505090565b60be10915081613092575090565b6003915081161490565b60408111159250613079565b906130e27f000000000000000000000000370634e1064b945e9010ddfa6077f321eca431cf6001600160a01b0316610a5f30821415612ea2565b6130f860018060a01b0361013454163314613397565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff161561312c575061306690614c42565b6040516352d1902d60e01b8152906020826004816001600160a01b0387165afa6000928161319b575b506131775760405162461bcd60e51b81528061317360048201613fe7565b0390fd5b61306692613196600080516020614edf83398151915260019414613f89565b614b26565b6131be91935060203d6020116131c5575b6131b68183610d3a565b810190613f7a565b9138613155565b503d6131ac565b156131d357565b60405162461bcd60e51b815260206004820152602f60248201527f43616c6c6572206e6f7420726567697374657265642e2043616c6c206465706f60448201526e39b4ba20b7322932b3b4b9ba32b91760891b6064820152608490fd5b1561323757565b60405162461bcd60e51b815260206004820152602560248201527f43616e6e6f74206c6f636b20626563617573652065787069726554732069732060448201526439b7b7b71760d91b6064820152608490fd5b60ff166020811161329b5750600190565b60f2811480613309575b80613301575b156132b65750606490565b60708111806132f6575b156132cb5750606490565b607b811190816132ea575b506132e45764e8d4a5100090565b6103e890565b608091501115386132d6565b50607b8111156132c0565b5060016132ab565b5060016132a5565b91613379916000919064ffffffffff906001600160a01b031633811461339157600160c81b935b5065010000000000600160d01b039060281b1691169117178260005260ce60205260406000209060018060d01b031665ffffffffffff60d01b825416179055565b612bf564ffffffffff8260d01c163360ff8416613d5a565b83613338565b1561339e57565b60405162461bcd60e51b815260206004820152601760248201527621b0b63632b91034b9903737ba103a34329037bbb732b960491b6044820152606490fd5b156133e457565b60405162461bcd60e51b8152602060048201526019602482015278141bdbdb081a5b99195e081b9bdd081c9959da5cdd195c9959603a1b6044820152606490fd5b926135399261349a91613441603c61ffff8860201c16146127ef565b6134556001600160a01b0385161515613560565b6040805160208101888152606087901b6001600160601b031916928201929092526134838160548101612b41565b519020610135546001600160a01b031692906142fa565b60d083901c64ffffffffff169061352b60ff8516926134c4605887901c64ffffffffff168261295f565b936134ee602882901b60ff60281b1660011765ffffffffffff16600052609b602052604060002090565b6134f9838254612e03565b9055600160ff60281b601089901b16176000908152609b6020526040902061352286825461295f565b90553390613d5a565b336119cc601886901c6104f1565b7ffa628b578e095243f0544bfad9255f49d79d03a5bbf6c85875d05a215e247ad2600080a2565b1561356757565b606460405162461bcd60e51b815260206004820152602060248201527f526563697069656e742063616e6e6f74206265207a65726f20616464726573736044820152fd5b156135b257565b60405162461bcd60e51b815260206004820152601d60248201527f506f6f6c20696e64657820616c726561647920726567697374657265640000006044820152606490fd5b156135fe57565b60405162461bcd60e51b815260206004820152602160248201527f5369676e6572206164647265737320616c7265616479207265676973746572656044820152601960fa1b6064820152608490fd5b1561365457565b60405162461bcd60e51b815260206004820152602260248201527f43616e6e6f742062652063616c6c6564207468726f75676820636f6e74726163604482015261747360f01b6064820152608490fd5b156136ab57565b60405162461bcd60e51b815260206004820152601e60248201527f43616e6e6f742072656c656173652062656361757365206578706972656400006044820152606490fd5b909161370860018060a01b0361013454163314613397565b815183510361376a5760005b825160ff82169081101561376357906122158261375861375161374a61373d61375e978a6137d7565b516001600160a01b031690565b92896137d7565b5160ff1690565b90614a25565b613714565b5050915050565b60405162461bcd60e51b815260206004820152602e60248201527f546f6b656e7320616e6420696e64657865732073686f756c642068617665207460448201526d0d0ca40e6c2daca40d8cadccee8d60931b6064820152608490fd5b60ff1660ff811461142a5760010190565b80518210156137eb5760209160051b010190565b634e487b7160e01b600052603260045260246000fd5b9391839161380f938661456d565b600082815260ce6020526040902080546001600160d01b031916600117905564ffffffffff8260d01c1660ff83169165ffffffffffff6138598460ff60281b60019160281b161790565b16600052609b602052604060002092835483810180911161142a57612e7b9455613d5a565b60ff60019116019060ff821161142a57565b9061389a82611d48565b6138a76040519182610d3a565b82815280926138b8601f1991611d48565b0190602036910137565b6001600160a01b0390811660009081526066602090815260408083205494909316825260999052205464ffffffffff169060ff168115801561392d575b6139265761392291610fc1919064ffffffffff60ff60281b91169160281b161790565b5490565b5050600090565b5080156138ff565b1561393c57565b60405162461bcd60e51b815260206004820152601260248201527153776170207374696c6c20696e206c6f636b60701b6044820152606490fd5b1561397d57565b60405162461bcd60e51b815260206004820152602360248201527f4164647220697320617574686f72697a656420666f7220616e6f7468657220706044820152621bdbdb60ea1b6064820152608490fd5b60ff604f199116019060ff821161142a57565b60ff601f199116019060ff821161142a57565b60ff811660c08110613a0d575060021c603f1690565b90565b60408111613a1c575050600090565b60708111613a425750613a3d613a34613a0a9261387e565b60011c607f1690565b6139e1565b60801015613a9b5760405162461bcd60e51b8152602060048201526024808201527f546f6b656e20696e646578206e6f7420616c6c6f77656420666f72207377617060448201526370696e6760e01b6064820152608490fd5b613a0a906139ce565b60d01c64ffffffffff1690565b15613ab857565b60405162461bcd60e51b815260206004820152601e60248201527f5369676e65722063616e6e6f7420626520656d707479206164647265737300006044820152606490fd5b15613b0457565b60405162461bcd60e51b8152602060048201526011602482015270496e76616c6964207369676e617475726560781b6044820152606490fd5b6040513d6000823e3d90fd5b15613b5057565b606460405162461bcd60e51b815260206004820152602060248201527f416d6f756e74206d7573742062652067726561746572207468616e207a65726f6044820152fd5b15613b9b57565b60405162461bcd60e51b8152602060048201526013602482015272151bdad95b881b9bdd081cdd5c1c1bdc9d1959606a1b6044820152606490fd5b15613bdd57565b60405162461bcd60e51b815260206004820152602960248201527f54686520676976656e20746f6b656e2061646472657373206973206e6f7420616044820152680818dbdb9d1c9858dd60ba1b6064820152608490fd5b9064e8d4a5100082029180830464e8d4a51000149015171561142a57565b9060058202918083046005149015171561142a57565b8181029291811591840414171561142a57565b3d15613ca6573d90613c8c82610d60565b91613c9a6040519384610d3a565b82523d6000602084013e565b606090565b908160209103126102f25751613a0a81611527565b15613cc757565b60405162461bcd60e51b81526020600482015260136024820152721d1c985b9cd9995c919c9bdb4819985a5b1959606a1b6044820152606490fd5b15613d0957565b60405162461bcd60e51b815260206004820152602360248201527f6d73672e76616c756520646f6573206e6f74206d617463682074686520616d6f6044820152621d5b9d60ea1b6064820152608490fd5b90613d66831515613b49565b613d6f82613068565b15613d89575050613d8261306691613c34565b3414613d02565b816000929183612b41613e1b613de161306698613ddb613dba6106f4879a60ff166000526065602052604060002090565b97613dcf6001600160a01b038a161515613b94565b611289893b1515613bd6565b90613c68565b6040516323b872dd60e01b602082019081526001600160a01b03909616602482015230604482015260648101919091529182906084820190565b51925af1613e27613c7b565b81613e33575b50613cc0565b8051801592508215613e48575b505038613e2d565b613e5b9250602080918301019101613cab565b3880613e40565b15613e6957565b60405162461bcd60e51b815260206004820152600f60248201526e1d1c985b9cd9995c8819985a5b1959608a1b6044820152606490fd5b919091613eac81613068565b15613ebb57506130669161488a565b80613066936000612b41613f33613eff8397613ddb613ee8869960ff166000526065602052604060002090565b546001600160a01b031697611289893b1515613bd6565b60405163a9059cbb60e01b602082019081526001600160a01b03909616602482015260448101919091529182906064820190565b51925af1613f3f613c7b565b81613f4b575b50613e62565b8051801592508215613f60575b505038613f45565b613f739250602080918301019101613cab565b3880613f58565b908160209103126102f2575190565b15613f9057565b60405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608490fd5b60809060208152602e60208201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960408201526d6f6e206973206e6f74205555505360901b60608201520190565b906140627f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1690565b15614071575061306690614c42565b6040516352d1902d60e01b8152906020826004816001600160a01b0387165afa600092816140d7575b506140b85760405162461bcd60e51b81528061317360048201613fe7565b61306692613196600080516020614edf83398151915260009414613f89565b6140f191935060203d6020116131c5576131b68183610d3a565b913861409a565b6001600160a01b0316801561414c5761013480546001600160a01b0319811683179091556001600160a01b03167f8934ce4adea8d9ce0d714d2c22b86790e41b7731c84b926fbbdc1d40ff6533c9600080a3565b606460405162461bcd60e51b815260206004820152602060248201527f4e6577206f776e65722063616e6e6f74206265207a65726f20616464726573736044820152fd5b6001600160a01b031680156141e45761013580546001600160a01b0319811683179091556001600160a01b03167f4798f31ad3d0ccde6359edf35fc39b882e4e1cff2968ca749b72074d373db27a600080a3565b60405162461bcd60e51b815260206004820152602360248201527f4e6577207072656d69756d206d616e61676572206265207a65726f206164647260448201526265737360e81b6064820152608490fd5b604080516020810192835260609390931b6001600160601b03191690830152906142628160548101612b41565b51902090565b64ffffffffff8160d01c169064ffffffffff8160581c16820391821161142a5761429190614cd3565b810390811161142a5790565b6142a681614cd3565b90811580156142b757505050600090565b612710830292830461271014171561142a5761ffff6142d99160b01c16614d5a565b9081156142e4570490565b634e487b7160e01b600052601260045260246000fd5b6001600160a01b03909316929190614313841515613ab1565b60018060ff1b0382169160ff1c601b810180911161142a5760209360009360ff936143829261435a6fa2a8918ca85bafe22016d0b997e4df60600160ff1b03841115613afd565b6040519586951690859094939260ff6060936080840197845216602083015260408201520152565b838052039060015afa15612c1c57600051613066916001600160a01b0390911614613afd565b600160cf1b81166145555760801c6001600160401b0316936143d9906143d0853b1515614dc1565b613ddb8361328a565b906143e381613068565b1561446a575060405163bff4163f60e01b815260006004820152602481018290526001600160a01b0392831660448201526001600160401b03949094166064850152602092849260849284929091165af18015612c1c57614442575b50565b61443f9060203d602011614463575b61445b8183610d3a565b810190613cab565b503d614451565b6106f46144879194929460ff166000526065602052604060002090565b92614494843b1515613bd6565b60405163095ea7b360e01b81526001600160a01b038316600482015260248101829052936020858060448101038160006001600160a01b0386165af1908115612c1c5760209560009261453a575b5060405163bff4163f60e01b81526001600160a01b039182166004820152602481019390935293841660448301526001600160401b03959095166064820152938492608492849291165af18015612c1c576144425750565b61455090873d89116144635761445b8183610d3a565b6144e2565b50928092915061456457505050565b61306692613ea0565b6001600160a01b03909416936020936000939161465a9190614590881515613ab1565b6001600160ff1b038216916145ab906104f19060ff1c612df5565b946145ce6fa2a8918ca85bafe22016d0b997e4df60600160ff1b03841115613afd565b600160cb1b8216151560c361ffff6145e96104bc8660081c90565b161488146146a557871461467e57780caa2927a71029b4b3b732b21026b2b9b9b0b3b29d051a998560391b91612b4f905b612b416040519384928c8401968791604d939166ffffffffffffff1916835260198301526bffffffffffffffffffffffff199060601b1660398201520190565b838052039060015afa15612c1c5760005161306691906001600160a01b0316612ba7565b780caa2927a71029b4b3b732b21026b2b9b9b0b3b29d0519990560391b91612b4f9061461a565b87146146ff576040517f19457468657265756d205369676e6564204d6573736167653a0a353200000000898201908152601c81019390935260609190911b6001600160601b031916603c830152612c888160508401612b41565b9060c36147126104bc6104bc8460201c90565b148714614753577f28cf5b919ed55db2b14d9e8b261a523eafb98bab117d3a8a56e559791415d17c915b601452865260348620875285526040852092612b54565b7f743e50106a7f059b52151dd4ba27a5f6c87b925ddfbdcf1c332e800da4b3df929161473c565b60ff811660fc81106147c057506147ae6147a66147a16101f49360d01c64ffffffffff1690565b613c52565b612710900490565b90808211156147bb575090565b905090565b60f881106147e357506147ae6147a66147a16113889360d01c64ffffffffff1690565b60f481106147fe57506147ae6147a66147a16101f493613aa4565b60f01161481e576147ae6147a66147a1600a9360d01c64ffffffffff1690565b6147ae6147a66147a16207a1209360d01c64ffffffffff1690565b61484281614e23565b61484c5750600090565b61ffff613a0a9160a01c16614d5a565b61486581614e23565b61486f5750600090565b60b01c61ffff16620100000164ffffffffff811161142a5790565b64e8d4a5100082029180830464e8d4a51000149015171561142a57600080809381935af16148b6613c7b565b50156148be57565b60405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b6044820152606490fd5b156148fc57565b60405162461bcd60e51b815260206004820152601b60248201527f43616e6e6f7420757365203020617320746f6b656e20696e64657800000000006044820152606490fd5b1561494857565b60405162461bcd60e51b815260206004820152601b60248201527f546f6b656e20686173206265656e206164646564206265666f726500000000006044820152606490fd5b1561499457565b60405162461bcd60e51b8152602060048201526013602482015272125b99195e081a185cc81899595b881d5cd959606a1b6044820152606490fd5b156149d657565b60405162461bcd60e51b815260206004820152602160248201527f436f726520746f6b656e207265717569726573206164646472657373283078316044820152602960f81b6064820152608490fd5b614a3360ff831615156148f5565b6001600160a01b0381168015614ae757613066926108b691614a76614a706104f1610fa48760018060a01b03166000526066602052604060002090565b15614941565b614a9c614a966103b76106f48560ff166000526065602052604060002090565b1561498d565b614aa582613068565b614ad5575b506001600160a01b0383166000908152606660205260409020805460ff191660ff8316179055611f9a565b6001614ae191146149cf565b38614aaa565b60405162461bcd60e51b815260206004820152601760248201527643616e6e6f7420757365207a65726f206164647265737360481b6044820152606490fd5b9091614b3182614c42565b604051906001600160a01b0383167fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b600080a283511590811591614c3a575b50614b7a57505050565b813b15614be957506000828192602061443f95519201905af4614b9b613c7b565b60405191614baa606084610d3a565b602783527f416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c6020840152660819985a5b195960ca1b6040840152614e47565b62461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608490fd5b905038614b70565b803b15614c7857600080516020614edf83398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b60405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608490fd5b614cdc81614d9e565b614ce65750600090565b61ffff8160a01c1661ffff8114614d1957614d019150614d5a565b6103e88102908082046103e8149015171561142a5790565b5060d081901c64ffffffffff1690605881901c64ffffffffff16820391821161142a57600160ce1b811615614d4c575090565b614d559061477a565b614291565b6103e8811115613a0a576103e719810190811161142a576123288106906103e8820180921161142a57612328900490604d821161142a57613a0a91600a0a90613c68565b60bf60ff8260181c16109081614db2575090565b61084160c41b90811614919050565b15614dc857565b60405162461bcd60e51b815260206004820152602d60248201527f54686520676976656e20726563697069656e742061646472657373206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608490fd5b600160cf1b811615159081614e36575090565b600360c91b16600160c91b14919050565b90919015614e53575090565b815115614e635750805190602001fd5b6040519062461bcd60e51b8252602060048301528181519182602483015260005b838110614ea65750508160006044809484010152601f80199101168101030190fd5b60208282018101516044878401015285935001614e8456fee34b8b74e1cdcaa1b90aa77af7dd89e496ad9a4ae4a4d4759712101c7da2dce6360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca164736f6c634300081c000a
Deployed Bytecode Sourcemap
165:295:33:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;;;-1:-1:-1;;;;;165:295:33;;;;;;:::o;:::-;;;;;;;;-1:-1:-1;;;;;165:295:33;;;;;;:::o;:::-;;;;-1:-1:-1;;;;;165:295:33;;;;;;:::o;:::-;;;-1:-1:-1;;;;;165:295:33;;;;;;:::o;:::-;;;;;;-1:-1:-1;;165:295:33;;;;;;:::i;:::-;719:10:20;-1:-1:-1;165:295:33;5672:20:25;165:295:33;;6011:42:25;;165:295:33;;-1:-1:-1;165:295:33;;;5717:14:25;5709:62;5717:14;;;5709:62;:::i;:::-;-1:-1:-1;165:295:33;;;5798:11:25;165:295:33;;;;;;5777:81:25;;5785:35;;-1:-1:-1;;;;;165:295:33;5798:22:25;-1:-1:-1;;;;;165:295:33;;;5785:35:25;719:10:20;5785:35:25;5777:81;:::i;:::-;5864:96;5872:26;:39;:26;;;;:::i;:::-;165:295:33;;;;;5872:26:25;165:295:33;;;;5872:39:25;;5864:96;:::i;:::-;165:295:33;5973:26:25;;;:::i;:::-;165:295:33;;-1:-1:-1;;165:295:33;;;;;;;-1:-1:-1;;;;;165:295:33;;;;;;;;;;;;;6011:42:25;;;;165:295:33;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;:::o;:::-;;;;;;;;;;;:::o;:::-;;;;;;-1:-1:-1;;165:295:33;;;;12834:1:29;165:295:33;;;;;;;;:::i;:::-;;;;:::i;:::-;;341:90:44;184:1:43;165:295:33;1116:3:44;165:295:33;349:51:44;341:90;:::i;:::-;12204:80:29;295:6:43;165:295:33;6556:24:44;6578:1;165:295:33;;;6563:16:44;165:295:33;;;;6556:24:44;165:295:33;12212:44:29;12204:80;:::i;:::-;12290:153;12305:42;165:295:33;;;12305:42:29;:::i;6854:18:44:-;12305:42:29;:::i;:::-;165:295:33;12305:89:29;12351:43;7428:24:44;7449:2;165:295:33;;;12351:43:29;165:295:33;7434:17:44;165:295:33;;;;12305:89:29;165:295:33;;12305:89:29;12290:153;:::i;:::-;295:6:43;;;;12457:12:29;295:6:43;;;;;12449:62:29;;-1:-1:-1;;;;;295:6:43;12457:25:29;;;295:6:43;-1:-1:-1;;;;;295:6:43;;;12457:25:29;295:6:43;12457:30:29;12449:62;:::i;:::-;12518:111;341:4:43;1370:3:44;165:295:33;;;1377:12:44;1354:35;12526:24:29;:43;;12518:111;:::i;:::-;12768:59;817:7:43;12652:44:29;6228:2:44;165:295:33;;;6234:12:44;6212:34;12652:26:29;12681:15;12652:44;;:::i;:::-;12702:60;766:7:43;12710:28:29;;12702:60;:::i;:::-;12776:28;12768:59;:::i;:::-;12834:1;:::i;:::-;165:295:33;;;;;;;-1:-1:-1;;165:295:33;;;;;;8637:24:29;165:295:33;;:::i;:::-;3242:15:23;165:295:33;8191:65:29;;-1:-1:-1;;;;;165:295:33;719:10:20;3242:31:23;8191:65:29;:::i;:::-;295:6:43;-1:-1:-1;295:6:43;8284:12:29;165:295:33;295:6:43;8315:46:29;8336:1;295:6:43;;;;;165:295:33;-1:-1:-1;295:6:43;;;8323:14:29;8315:46;:::i;:::-;8367:77;6228:2:44;165:295:33;;;6234:12:44;6212:34;8375:26:29;8404:15;-1:-1:-1;8367:77:29;:::i;:::-;-1:-1:-1;295:6:43;;;8284:12:29;165:295:33;295:6:43;165:295:33;295:6:43;;165:295:33;;-1:-1:-1;;;;;;165:295:33;;;;;;8637:24:29;1370:3:44;165:295:33;;;1377:12:44;1354:35;8637:24:29;;;:::i;:::-;8674:26;-1:-1:-1;8674:26:29;;165:295:33;;;;;;;-1:-1:-1;;165:295:33;;;;;;-1:-1:-1;295:6:43;;;11889:12:29;165:295:33;295:6:43;;;;;-1:-1:-1;;;;;165:295:33;;;;;;-1:-1:-1;;;;;295:6:43;;;12002:23:29;165:295:33;;12035:22:29;165:295:33;-1:-1:-1;11998:144:29;;295:6:43;165:295:33;;-1:-1:-1;;;;;165:295:33;;;;;;;;;;;;;11978:14:29;;;165:295:33;;;;;;;;;;;;;;;;;;11998:144:29;12090:45;;165:295:33;;;;;;;;12090:11:29;165:295:33;;;;;;;12090:45:29;165:295:33;-1:-1:-1;;;;;165:295:33;;;12090:45:29;11998:144;;;165:295:33;-1:-1:-1;;;;;165:295:33;;;;;5672:20:25;165:295:33;;;;;;:::o;:::-;;;;;;-1:-1:-1;;165:295:33;;;;-1:-1:-1;;;;;165:295:33;;:::i;:::-;;-1:-1:-1;165:295:33;3372:45:46;165:295:33;;;;;-1:-1:-1;165:295:33;;;;;;;;;;;;-1:-1:-1;;165:295:33;;;;12834:1:29;165:295:33;;341:90:44;184:1:43;165:295:33;1116:3:44;165:295:33;349:51:44;341:90;:::i;:::-;12204:80:29;295:6:43;165:295:33;6556:24:44;6578:1;165:295:33;;;6563:16:44;165:295:33;12204:80:29;12290:153;12305:42;165:295:33;;;12305:42:29;:::i;12290:153::-;295:6:43;;;;12457:12:29;295:6:43;;;;;12449:62:29;;-1:-1:-1;;;;;295:6:43;12457:25:29;;;295:6:43;12449:62:29;12518:111;341:4:43;1370:3:44;165:295:33;;;1377:12:44;1354:35;12526:24:29;1267:127:44;12518:111:29;12768:59;817:7:43;12652:44:29;6228:2:44;165:295:33;;;6234:12:44;6212:34;12652:26:29;6123:183:44;12768:59:29;12834:1;:::i;165:295:33:-;;;;;;-1:-1:-1;;165:295:33;;;;;;:::i;:::-;719:10:20;-1:-1:-1;165:295:33;6348:20:25;165:295:33;;6683:48:25;;165:295:33;;-1:-1:-1;165:295:33;;;6393:14:25;6385:62;6393:14;;;6385:62;:::i;:::-;-1:-1:-1;165:295:33;;;6474:11:25;165:295:33;;;;;;6453:81:25;;6461:35;;-1:-1:-1;;;;;165:295:33;6474:22:25;165:295:33;6453:81:25;6540:96;6548:26;:39;:26;;;;:::i;6540:96::-;6642:29;:22;;;165:295:33;;;;12090:11:29;165:295:33;;;;;;;6642:22:25;165:295:33;;-1:-1:-1;;;;;;165:295:33;-1:-1:-1;;;;;165:295:33;;;;;;;;;;6642:29:25;165:295:33;;;719:10:20;165:295:33;;-1:-1:-1;;;;;165:295:33;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;165:295:33;;;;;;;;:::i;:::-;-1:-1:-1;295:6:43;;;6872:12:29;165:295:33;295:6:43;165:295:33;295:6:43;;;-1:-1:-1;;;;;295:6:43;;;;165:295:33;;6903:46:29;165:295:33;6911:14:29;;6903:46;:::i;:::-;165:295:33;;;7161:50:29;719:10:20;7038:116:29;165:295:33;719:10:20;;7046:34:29;;719:10:20;7046:34:29;:::i;:::-;165:295:33;;;;7046:47:29;;7038:116;:::i;:::-;7189:22;7161:25;;295:6:43;;12457:12:29;295:6:43;;;;;;;7161:25:29;165:295:33;;-1:-1:-1;;;;;;165:295:33;-1:-1:-1;;;;;295:6:43;;;165:295:33;;;;;;;7161:50:29;7222:23;-1:-1:-1;7222:23:29;;165:295:33;;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;165:295:33;;;;3499:5:4;165:295:33;;:::i;:::-;1963:87:4;1898:6;-1:-1:-1;;;;;165:295:33;1873:80:4;1889:4;1881:23;;;1873:80;:::i;:::-;-1:-1:-1;;;;;;;;;;;165:295:33;-1:-1:-1;;;;;165:295:33;1971:30:4;1963:87;:::i;:::-;2848:58:23;165:295:33;;;;;2856:6:23;165:295:33;;719:10:20;2856:22:23;2848:58;:::i;:::-;165:295:33;;;;;;;;:::i;:::-;-1:-1:-1;165:295:33;;-1:-1:-1;;165:295:33;;;;;;;;3499:5:4;:::i;165:295:33:-;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;:::i;:::-;3293:46:25;3301:10;;;3293:46;:::i;:::-;165:295:33;;;3401:53:25;3409:14;;;3401:53;:::i;:::-;719:10:20;3310:1:25;165:295:33;3525:20:25;165:295:33;;;;;3310:1:25;165:295:33;;;;3512:47:25;165:295:33;;;3610:35:25;;3782:37;3610:35;165:295:33;;;;3610:19:25;165:295:33;;;;;;;3610:35:25;:45;165:295:33;;;3610:45:25;:::i;:::-;165:295:33;;3763:6:25;719:10:20;;10755:27:44;10779:2;165:295:33;;;;;10761:20:44;165:295:33;10755:27:44;3763:6:25;:::i;:::-;165:295:33;;;;;;;;;;;3782:37:25;165:295:33;;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;;;;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;;-1:-1:-1;;165:295:33;;;;;;:::i;:::-;3468:1:3;165:295:33;;:::i;:::-;-1:-1:-1;165:295:33;;3157:201:3;165:295:33;;;;;;3133:14:3;;;;3179:34;;;165:295:33;3178:108:3;;;;165:295:33;3157:201:3;;:::i;:::-;3368:16;;165:295:33;;;3134:13:3;165:295:33;;;3134:13:3;165:295:33;;3368:16:3;3394:65;;3468:1;:::i;:::-;3479:99;;165:295:33;3479:99:3;3513:21;165:295:33;;3134:13:3;165:295:33;;3134:13:3;165:295:33;;3513:21:3;165:295:33;;3383:1:3;165:295:33;;3553:14:3;;165:295:33;;3553:14:3;165:295:33;3394:65:3;3428:20;165:295:33;;;3134:13:3;165:295:33;;;3134:13:3;165:295:33;;3428:20:3;3468:1;:::i;3178:108::-;3258:4;1476:19:8;:23;;-1:-1:-1;1476:23:8;3219:66:3;;3178:108;;;;;3219:66;165:295:33;;3284:1:3;3268:17;;-1:-1:-1;3219:66:3;;;3179:34;3212:1;165:295:33;;;3197:16:3;;-1:-1:-1;3179:34:3;;165:295:33;;;;;;;;;;;:::o;:::-;;;;;;-1:-1:-1;;165:295:33;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;165:295:33;;;;;;;:::o;:::-;;:::i;:::-;-1:-1:-1;;;;;165:295:33;;;;;;-1:-1:-1;;165:295:33;;;;:::o;:::-;;;-1:-1:-1;;165:295:33;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;165:295:33;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;-1:-1:-1;165:295:33;;3761:222:4;165:295:33;;;;;;;;;;3761:222:4;:::i;165:295:33:-;;;;;;-1:-1:-1;;165:295:33;;;;;;8315:56:25;7526:34;165:295:33;;:::i;:::-;341:90:44;184:1:43;165:295:33;1116:3:44;165:295:33;349:51:44;341:90;:::i;:::-;16576:81:25;295:6:43;165:295:33;;;;;16584:45:25;16576:81;:::i;:::-;7526:34;;:::i;:::-;7566:57;-1:-1:-1;;;;;7574:20:25;;;295:6:43;;7574:12:25;295:6:43;;;;;;;7574:20:25;165:295:33;-1:-1:-1;;;;;165:295:33;;;7566:57:25;8315:20;8338:33;7649:34;;719:10:20;7649:34:25;:::i;:::-;7689:74;165:295:33;;;7697:14:25;;7689:74;:::i;:::-;7786:34;:15;:34;:::i;:::-;7826:96;7842:38;6228:2:44;165:295:33;;;6234:12:44;6212:34;7842:38:25;:::i;:::-;7834:46;;7826:96;:::i;:::-;8386:2:44;165:295:33;;;-1:-1:-1;;;165:295:33;;;;8349:52:44;8009:65:25;:35;8048:26;;;:::i;:::-;8009:35;165:295:33;;;;3610:19:25;165:295:33;;;;;;;8009:35:25;165:295:33;;;8009:65:25;:::i;:::-;165:295:33;;8148:29:25;;;:::i;:::-;8187:14;8183:126;;165:295:33;-1:-1:-1;9634:2:44;165:295:33;;;;;;;9616:33:44;;9514:140;8338:33:25;8315:20;295:6:43;;7574:12:25;295:6:43;;;;;;;8315:20:25;864:10:43;-1:-1:-1;;;;;165:295:33;-1:-1:-1;;;;;864:10:43;;;;;;;;8315:56:25;8383:23;-1:-1:-1;8383:23:25;;165:295:33;8183:126:25;165:295:33;;;8251:12:25;165:295:33;;8211:91:25;:77;8231:56;8251:24;;-1:-1:-1;;;;;;;;;;;8251:24:25;165:295:33;;;;;8251:24:25;10483:2:44;165:295:33;-1:-1:-1;;;165:295:33;;;;;10460:38:44;;10351:152;8231:56:25;165:295:33;;;;3610:19:25;165:295:33;;;;;;;8211:91:25;165:295:33;;8183:126:25;;;165:295:33;;;;;;-1:-1:-1;;165:295:33;;;;2333:6:4;-1:-1:-1;;;;;165:295:33;2324:4:4;2316:23;165:295:33;;;;-1:-1:-1;;;;;;;;;;;165:295:33;;;;;;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;;;;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;;-1:-1:-1;;165:295:33;;;;;;-1:-1:-1;295:6:43;;;7594:12:29;165:295:33;295:6:43;;;;;-1:-1:-1;;;;;295:6:43;7625:46:29;165:295:33;7633:14:29;;7625:46;:::i;:::-;7677:77;6228:2:44;165:295:33;;;6234:12:44;6212:34;7685:26:29;6123:183:44;7677:77:29;165:295:33;;;;;;;;8042:24:29;7840:25;165:295:33;7840:25:29;;295:6:43;;12457:12:29;295:6:43;;;;;;;7840:25:29;165:295:33;;-1:-1:-1;;;;;;165:295:33;;;;;;;;;9057:34:44;;9065:25;;10779:2;165:295:33;-1:-1:-1;;;;;165:295:33;9065:25:44;165:295:33;9057:34:44;1370:3;165:295:33;;;1377:12:44;1354:35;8042:24:29;1267:127:44;165:295:33;295:6:43;165:295:33;-1:-1:-1;;;165:295:33;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;165:295:33;;;;;;8315:56:25;7526:34;165:295:33;;:::i;:::-;;;;;;-1:-1:-1;;165:295:33;;;;;;16226:34:25;165:295:33;;:::i;:::-;-1:-1:-1;165:295:33;16226:34:25;:::i;:::-;295:6:43;;16286:12:25;165:295:33;295:6:43;165:295:33;295:6:43;;165:295:33;-1:-1:-1;;;;;165:295:33;;;295:6:43;16330:1:25;16316:15;;16330:1;;16341:22;;;16330:1;-1:-1:-1;16312:205:25;;165:295:33;;;-1:-1:-1;;;;;165:295:33;;;;;;;;;;;;;;;;16312:205:25;165:295:33;;;;;;16413:11:25;165:295:33;;;;;;;-1:-1:-1;;;;;165:295:33;;16474:36:25;;10144:25:44;;10779:2;165:295:33;;10152:16:44;-1:-1:-1;;;;;165:295:33;;;16474:36:25;16312:205;;;165:295:33;;;;;;-1:-1:-1;;165:295:33;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;-1:-1:-1;;165:295:33;;;;12834:1:29;165:295:33;;;;:::i;:::-;;;:::i;:::-;;341:90:44;184:1:43;165:295:33;1116:3:44;165:295:33;349:51:44;341:90;:::i;:::-;12204:80:29;295:6:43;165:295:33;6556:24:44;6578:1;165:295:33;;;6563:16:44;165:295:33;12204:80:29;12290:153;12305:42;165:295:33;;;12305:42:29;:::i;12290:153::-;295:6:43;;;;12457:12:29;295:6:43;;;;;12449:62:29;;-1:-1:-1;;;;;295:6:43;12457:25:29;;;295:6:43;12449:62:29;12518:111;341:4:43;1370:3:44;165:295:33;;;1377:12:44;1354:35;12526:24:29;1267:127:44;12518:111:29;12768:59;817:7:43;12652:44:29;6228:2:44;165:295:33;;;6234:12:44;6212:34;12652:26:29;6123:183:44;12768:59:29;12834:1;:::i;165:295:33:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;:::i;:::-;2848:58:23;165:295:33;;;;;;;;2856:6:23;165:295:33;;719:10:20;2856:22:23;2848:58;:::i;:::-;165:295:33;;;-1:-1:-1;165:295:33;;;2325:11:23;165:295:33;;;;;;2317:76:23;;-1:-1:-1;;;;;165:295:33;2325:38:23;;2317:76;:::i;:::-;165:295:33;10483:2:44;165:295:33;;;-1:-1:-1;;;165:295:33;;-1:-1:-1;165:295:33;2399:19:23;165:295:33;;;-1:-1:-1;165:295:33;;;341:4:43;;;;;;;;;2470:75:23;165:295:33;2470:65:23;165:295:33;2490:44:23;165:295:33;;10351:152:44;165:295:33;-1:-1:-1;;;10351:152:44;165:295:33;;10483:2:44;165:295:33;;10460:38:44;10351:152;;2470:65:23;165:295:33;;;2470:75:23;:::i;:::-;165:295:33;;;341:4:43;;:::i;165:295:33:-;;;;;;-1:-1:-1;;165:295:33;;;;12834:1:29;165:295:33;;;;:::i;:::-;;;;;;;341:90:44;184:1:43;165:295:33;1116:3:44;165:295:33;349:51:44;341:90;:::i;:::-;12204:80:29;295:6:43;165:295:33;6556:24:44;6578:1;165:295:33;;;6563:16:44;165:295:33;12204:80:29;12290:153;12305:42;165:295:33;;;12305:42:29;:::i;12290:153::-;295:6:43;;;;12457:12:29;295:6:43;;;;;12449:62:29;;-1:-1:-1;;;;;295:6:43;12457:25:29;;;295:6:43;12449:62:29;12518:111;341:4:43;1370:3:44;165:295:33;;;1377:12:44;1354:35;12526:24:29;1267:127:44;12518:111:29;12768:59;817:7:43;12652:44:29;6228:2:44;165:295:33;;;6234:12:44;6212:34;12652:26:29;6123:183:44;12768:59:29;12834:1;:::i;165:295:33:-;;;;;;-1:-1:-1;;165:295:33;;;;-1:-1:-1;;;;;165:295:33;;:::i;:::-;;-1:-1:-1;165:295:33;1593:54:45;165:295:33;;;;;-1:-1:-1;165:295:33;;;;;;;;;;;;;;;;:::o;:::-;;;;;;-1:-1:-1;;165:295:33;;;;;;;;;;10205:32:29;165:295:33;;:::i;:::-;;;;;;;:::i;:::-;9589:25:29;;;295:6:43;;12457:12:29;295:6:43;;;;;;;9589:25:29;295:6:43;9620:46:29;9641:1;-1:-1:-1;;;;;295:6:43;;9628:14:29;9620:46;:::i;:::-;6228:2:44;165:295:33;;;6234:12:44;6212:34;9761:38:29;:15;:38;:::i;:::-;-1:-1:-1;9761:15:29;;;165:295:33;9948:25:29;;295:6:43;;12457:12:29;295:6:43;;;;;;;165:295:33;9057:34:44;9065:25;-1:-1:-1;;;;;10779:2:44;165:295:33;;;;9065:25:44;165:295:33;9057:34:44;10205:32:29;;;:::i;:::-;165:295:33;;;;;;10357:221:29;;;;10384:63;10404:42;10384:91;10451:24;;;1377:12:44;1267:127;1370:3;165:295:33;1354:35:44;1267:127;;10451:24:29;10404:42;10483:2:44;165:295:33;-1:-1:-1;;;165:295:33;;;;;10460:38:44;;10351:152;10384:91:29;165:295:33;;10357:221:29;10589:25;-1:-1:-1;10589:25:29;;165:295:33;10357:221:29;10522:22;;;10546:24;10522:22;165:295:33;;;;12090:11:29;165:295:33;;;;;;;10546:24:29;10357:221;;9728:408;10100:29;:25;;295:6:43;;12457:12:29;295:6:43;;;;;;;10100:25:29;165:295:33;;-1:-1:-1;;;;;;165:295:33;295:6:43;165:295:33;;;;10100:29:29;9728:408;;165:295:33;;;;;;-1:-1:-1;;165:295:33;;;;;;;;;;;;;;-1:-1:-1;165:295:33;2197:45:45;165:295:33;;;;;;;;;-1:-1:-1;165:295:33;;;;;;;;;;;;;;;-1:-1:-1;;165:295:33;;;;;-1:-1:-1;;;165:295:33;;:::i;:::-;10483:2:44;165:295:33;;;-1:-1:-1;165:295:33;4088:19:45;165:295:33;;;;-1:-1:-1;165:295:33;;;;;;;;;;2631:37:25;165:295:33;;;:::i;:::-;1904:46:25;1912:10;;;;;1904:46;:::i;:::-;165:295:33;;;2365:43:25;165:295:33;2050:53:25;2058:14;;;2050:53;:::i;:::-;2153:78;165:295:33;;;;;2161:22:25;;;165:295:33;;;;12090:11:29;165:295:33;;;;;;;2161:22:25;165:295:33;2161:36:25;2153:78;:::i;:::-;2237:82;2245:36;:31;;719:10:20;2245:31:25;:::i;:36::-;;2237:82;:::i;:::-;2325:34;719:10:20;2325:22:25;;165:295:33;;;;12090:11:29;165:295:33;;;;;;;2325:34:25;2365:31;719:10:20;2365:31:25;:::i;:::-;165:295:33;;;;;;;;;;;;2365:43:25;2415:35;;165:295:33;;;;3610:19:25;165:295:33;;;;;;;2415:35:25;:45;165:295:33;;;2415:45:25;:::i;:::-;165:295:33;;2565:6:25;719:10:20;;10755:27:44;10779:2;165:295:33;;;;;10761:20:44;165:295:33;2565:6:25;165:295:33;;719:10:20;165:295:33;;2584:36:25;;165:295:33;;2584:36:25;165:295:33;;;;;;;;;;;2631:37:25;165:295:33;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;165:295:33;;;;;;;;;-1:-1:-1;;;;;165:295:33;;;;;;;:::o;:::-;;;;11166:24:25;12404:13;11166:20;165:295:33;;;:::i;:::-;10454:9:25;;;;;;10430:72;10454:9;719:10:20;10438:25:25;10430:72;:::i;:::-;10508:87;6228:2:44;165:295:33;;;6234:12:44;6212:34;10516:26:25;10545:15;-1:-1:-1;10508:87:25;:::i;:::-;10601:68;-1:-1:-1;;;;;165:295:33;;10609:23:25;;10601:68;:::i;:::-;11150:9;10693:23;-1:-1:-1;;;3745:68:44;;3744:74;;10722:181:25;;;;165:295:33;10984:34:25;;;;:::i;:::-;11032:20;11024:56;11055:1;-1:-1:-1;;;;;11032:20:25;;;295:6:43;;7574:12:25;295:6:43;;;;;;;11032:20:25;165:295:33;11032:24:25;11024:56;:::i;:::-;11150:9;;;:::i;:::-;295:6:43;;7574:12:25;295:6:43;;;;;;;11166:20:25;864:10:43;;-1:-1:-1;;864:10:43;165:295:33;864:10:43;;;;11166:24:25;11275:26;;;:::i;:::-;11311:10;;11307:629;;165:295:33;11966:27:25;;;:::i;:::-;12003:17;11999:185;;165:295:33;12211:29:25;;;;:::i;:::-;12250:14;12246:76;;165:295:33;-1:-1:-1;7428:24:44;7449:2;165:295:33;;;7434:17:44;165:295:33;7428:24:44;12404:13:25;;:::i;:::-;12430:25;10630:1;12430:25;;165:295:33;12246:76:25;12304:10;;;;:::i;:::-;12246:76;;;11999:185;12030:30;;;;;:::i;:::-;12128;12068:109;:92;12088:71;12128:30;;;:::i;:::-;12088:71;8230:176:44;165:295:33;-1:-1:-1;;;8230:176:44;165:295:33;;8386:2:44;165:295:33;;8349:52:44;8230:176;;12068:109:25;165:295:33;;11999:185:25;;;11307:629;11504:27;11418:24;;;:::i;:::-;11504:27;;;:::i;:::-;11872:42;11852:77;:63;8386:2:44;165:295:33;;;-1:-1:-1;;;165:295:33;;;;;3610:19:25;165:295:33;;;;;;;11852:77:25;165:295:33;;11307:629:25;;10722:181;3242:15:23;165:295:33;10831:65:25;;-1:-1:-1;;;;;165:295:33;719:10:20;3242:31:23;8191:65:29;:::i;10831::25:-;10722:181;;165:295:33;;;;14498:13:25;165:295:33;;;:::i;:::-;;;341:90:44;184:1:43;165:295:33;1116:3:44;165:295:33;;;;349:51:44;341:90;:::i;:::-;16576:81:25;295:6:43;165:295:33;;7150:2:44;165:295:33;;16584:45:25;16576:81;:::i;:::-;12679:72;12703:9;719:10:20;12687:25:25;12679:72;:::i;:::-;12757:68;-1:-1:-1;;;;;165:295:33;;12765:23:25;;12757:68;:::i;:::-;13553:24;:20;-1:-1:-1;;;3745:68:44;;3744:74;;12878:95:25;;;;165:295:33;12996:34:25;;;;;;:::i;:::-;13044:20;13036:57;-1:-1:-1;;;;;13044:20:25;;;295:6:43;;7574:12:25;295:6:43;;;;;;;13036:57:25;13119:34;;719:10:20;13119:34:25;:::i;:::-;165:295:33;13159:74:25;165:295:33;;;13167:14:25;;13159:74;:::i;:::-;13244:17;;;;13429:9;;13271:87;;6228:2:44;165:295:33;6234:12:44;6212:34;13279:26:25;6123:183:44;13271:87:25;13429:9;;;:::i;13553:24::-;13608:26;;;:::i;:::-;13660:50;13640:71;8386:2:44;165:295:33;;;-1:-1:-1;;;165:295:33;;;;8349:52:44;165:295:33;;;;3610:19:25;165:295:33;;;;;;;13640:71:25;:88;165:295:33;;;13640:88:25;:::i;:::-;165:295:33;;13739:10:25;13735:196;;13240:308;13961:27;;;:::i;:::-;13998:17;13994:185;;13240:308;14206:29;;;;:::i;:::-;14245:14;14241:175;;13240:308;-1:-1:-1;7428:24:44;;-1:-1:-1;7449:2:44;165:295:33;;;7434:17:44;165:295:33;14241:175:25;165:295:33;;;8251:12:25;165:295:33;;14398:10:25;;14269:77;;14289:56;;14309:24;-1:-1:-1;;;;;;;;;;;14309:24:25;165:295:33;14269:77:25;:91;165:295:33;;;14269:91:25;:::i;:::-;165:295:33;;14398:10:25;;:::i;:::-;14241:175;;;;13994:185;14025:30;;;;;:::i;:::-;14123;14063:109;:92;14083:71;14123:30;;;:::i;:::-;14083:71;8230:176:44;165:295:33;-1:-1:-1;;;8230:176:44;165:295:33;;8386:2:44;165:295:33;;8349:52:44;8230:176;;14063:109:25;165:295:33;;13994:185:25;;;13735:196;13812:27;13780:24;;;:::i;:::-;13812:27;;;:::i;:::-;13867:42;13847:77;:63;8386:2:44;165:295:33;;;-1:-1:-1;;;165:295:33;;;;;3610:19:25;165:295:33;;;;;;;13847:77:25;165:295:33;;13735:196:25;;13240:308;13456:10;;;;;13553:20;13452:96;3242:15:23;165:295:33;13476:65:25;;-1:-1:-1;;;;;165:295:33;719:10:20;3242:31:23;8191:65:29;:::i;13476::25:-;13240:308;;12878:95;3242:15:23;165:295:33;12901:65:25;;-1:-1:-1;;;;;165:295:33;719:10:20;3242:31:23;8191:65:29;:::i;12901::25:-;12878:95;;165:295:33;;;;;;-1:-1:-1;;165:295:33;;;;2183:17:23;165:295:33;;:::i;:::-;3242:15:23;165:295:33;2088:65:23;;-1:-1:-1;;;;;165:295:33;719:10:20;3242:31:23;8191:65:29;:::i;2088::23:-;2183:17;:::i;165:295:33:-;-1:-1:-1;;;;;165:295:33;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;165:295:33;;;;;;-1:-1:-1;;;;;165:295:33;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;165:295:33;;;;;1601:306:23;165:295:33;;;;;;:::i;:::-;1601:306:23;;:::i;165:295:33:-;;;;;;;:::i;:::-;;;;;;;;;;12834:1:29;165:295:33;;;:::i;:::-;;341:90:44;184:1:43;165:295:33;1116:3:44;165:295:33;;;;349:51:44;341:90;:::i;:::-;12204:80:29;295:6:43;165:295:33;6556:24:44;6578:1;165:295:33;;;6563:16:44;165:295:33;12204:80:29;12290:153;12305:42;165:295:33;;;12305:42:29;:::i;12290:153::-;295:6:43;;;;12457:12:29;295:6:43;;;;;12449:62:29;;-1:-1:-1;;;;;295:6:43;12457:25:29;;;295:6:43;12449:62:29;12518:111;341:4:43;1370:3:44;165:295:33;;;1377:12:44;1354:35;12526:24:29;1267:127:44;12518:111:29;12768:59;817:7:43;12652:44:29;6228:2:44;165:295:33;;;6234:12:44;6212:34;12652:26:29;6123:183:44;12768:59:29;12834:1;:::i;165:295:33:-;;;;;;-1:-1:-1;;165:295:33;;;;;;:::i;:::-;2848:58:23;165:295:33;;;;;2856:6:23;165:295:33;;719:10:20;2856:22:23;2848:58;:::i;:::-;165:295:33;;;5097:50:46;5105:10;;;5097:50;:::i;:::-;-1:-1:-1;165:295:33;;;5169:13:46;165:295:33;;;;;;-1:-1:-1;;;;;165:295:33;5203:19:46;;165:295:33;;-1:-1:-1;;;;;165:295:33;;;;;5274:12:46;165:295:33;;;;;;;-1:-1:-1;;165:295:33;;;;;5306:20:46;;165:295:33;;;;;5169:13:46;165:295:33;;;;;;;5306:20:46;165:295:33;;-1:-1:-1;;;;;;165:295:33;;;;;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;;;;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;4720:37:25;165:295:33;;;:::i;:::-;4253:46:25;4261:10;;;;;4253:46;:::i;:::-;165:295:33;;;4361:53:25;4369:14;;;4361:53;:::i;:::-;4270:1;165:295:33;;;4472:11:25;165:295:33;;;;;;4464:84:25;;-1:-1:-1;;;;;165:295:33;719:10:20;4472:38:25;4464:84;:::i;:::-;4554:35;;165:295:33;;;;3610:19:25;165:295:33;;;;;;;4554:35:25;:45;165:295:33;;;4554:45:25;:::i;:::-;165:295:33;;4701:6:25;719:10:20;;10755:27:44;10779:2;165:295:33;;;;;10761:20:44;165:295:33;10755:27:44;4701:6:25;:::i;165:295:33:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;165:295:33;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;165:295:33;;;;;;4152:9:46;4179:7;165:295:33;;;;4179:7:46;;;165:295:33;;4317:16:46;4283:18;;;:::i;:::-;4317:16;;:::i;:::-;4339:11;165:295:33;;4368:7:46;165:295:33;;;;4368:7:46;;;165:295:33;;;;;;;;;;:::i;4377:3:46:-;4394:32;:18;;4408:3;;;:::i;4394:32::-;4390:126;;4377:3;4221:1;165:295:33;;;4361:5:46;;4390:126;4464:3;4221:1;4504:3;165:295:33;4464:3:46;4478:16;4450:18;;4464:3;;;:::i;4450:18::-;4438:30;165:295:33;;;4438:30:46;;;;;:::i;:::-;-1:-1:-1;;;;;165:295:33;;;;;;4438:30:46;4478:16;4491:3;;;:::i;:::-;4478:16;;;:::i;:::-;165:295:33;;;;;;4478:16:46;4504:3;:::i;:::-;4390:126;;;;;;4188:3;4205:32;:18;;4219:3;;;:::i;4205:32::-;4201:62;;4188:3;4221:1;165:295:33;;;4172:5:46;;4201:62;4249:5;4221:1;4249:5;;;;:::i;:::-;4201:62;;;;;;165:295:33;;;;;;-1:-1:-1;;165:295:33;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;;;;;-1:-1:-1;;165:295:33;;;;;;:::i;:::-;;;;;;;;;;1368:5:23;165:295:33;2848:58:23;165:295:33;;;;;2856:6:23;165:295:33;;719:10:20;2856:22:23;2848:58;:::i;:::-;1368:5;:::i;165:295:33:-;;;-1:-1:-1;;165:295:33;;;;;;;;-1:-1:-1;;;;;165:295:33;;;;;;;;;12834:1:29;;165:295:33;;-1:-1:-1;;;;;165:295:33;;;;341:90:44;1116:3;165:295:33;;;184:1:43;349:51:44;341:90;:::i;:::-;12204:80:29;295:6:43;165:295:33;6556:24:44;6578:1;165:295:33;;;6563:16:44;165:295:33;12204:80:29;12290:153;12305:42;165:295:33;;;12305:42:29;:::i;:::-;165:295:33;12305:89:29;12351:43;7428:24:44;7449:2;165:295:33;;;12351:43:29;165:295:33;12290:153:29;295:6:43;;;;12457:12:29;295:6:43;;;;;12449:62:29;;-1:-1:-1;;;;;295:6:43;12457:25:29;;;295:6:43;12449:62:29;12518:111;341:4:43;1370:3:44;165:295:33;;;1377:12:44;1354:35;12526:24:29;1267:127:44;12518:111:29;12768:59;817:7:43;12652:44:29;6228:2:44;165:295:33;;;6234:12:44;6212:34;12652:26:29;6123:183:44;12768:59:29;165:295:33;12834:1:29;;:::i;165:295:33:-;;;;2757:44:23;165:295:33;;;;:::i;:::-;;;;2848:58:23;165:295:33;;;;;2856:6:23;165:295:33;;719:10:20;2856:22:23;2848:58;:::i;:::-;165:295:33;;;-1:-1:-1;165:295:33;;;2663:11:23;165:295:33;;;;;;2655:76:23;;-1:-1:-1;;;;;165:295:33;2663:38:23;;2655:76;:::i;2757:44::-;165:295:33;-1:-1:-1;165:295:33;2737:19:23;165:295:33;;;-1:-1:-1;165:295:33;;;;;;;;;;;;;;;;;;;-1:-1:-1;;165:295:33;;;;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;-1:-1:-1;;165:295:33;;;;;;;9485:20:25;8859:34;165:295:33;;:::i;:::-;8859:34:25;;:::i;:::-;9891:18:44;8919:20:25;;;295:6:43;;7574:12:25;295:6:43;;;;;;;8919:20:25;8945:46;8966:1;-1:-1:-1;;;;;165:295:33;;8953:14:25;8945:46;:::i;:::-;8997:77;10144:25:44;165:295:33;10779:2:44;165:295:33;;;;10152:16:44;165:295:33;10144:25:44;9036:15:25;-1:-1:-1;8997:77:25;:::i;9891:18:44:-;8386:2;165:295:33;;;-1:-1:-1;;;165:295:33;;;;8349:52:44;9218:65:25;:35;9257:26;;;:::i;9218:65::-;165:295:33;;9311:29:25;;;:::i;:::-;9350:14;;9346:126;;165:295:33;9485:20:25;;295:6:43;;7574:12:25;295:6:43;;;;;;;9485:20:25;165:295:33;;-1:-1:-1;;165:295:33;;;;;9517:25:25;-1:-1:-1;9517:25:25;;165:295:33;9346:126:25;165:295:33;;;8251:12:25;165:295:33;;9374:91:25;;:77;;9394:56;;9414:24;-1:-1:-1;;;;;;;;;;;9414:24:25;165:295:33;9374:91:25;165:295:33;;9346:126:25;;;;165:295:33;;;;;;-1:-1:-1;;165:295:33;;;;1998:8:23;165:295:33;;:::i;:::-;2848:58:23;165:295:33;;;;;2856:6:23;165:295:33;;719:10:20;2856:22:23;2848:58;:::i;:::-;1998:8;:::i;165:295:33:-;;;;;;-1:-1:-1;;165:295:33;;;;;;:::i;:::-;719:10:20;-1:-1:-1;165:295:33;5025:20:25;165:295:33;;5352:40:25;;165:295:33;;-1:-1:-1;165:295:33;;;5070:14:25;5062:62;5070:14;;;5062:62;:::i;:::-;-1:-1:-1;165:295:33;;;5151:11:25;165:295:33;;;;;;5130:81:25;;5138:35;;-1:-1:-1;;;;;165:295:33;5151:22:25;165:295:33;5130:81:25;5217:79;5225:31;:26;;;;:::i;:31::-;;5217:79;:::i;:::-;5302:38;:26;;;;:::i;165:295:33:-;;;;;;-1:-1:-1;;165:295:33;;;;;;;:::i;:::-;;-1:-1:-1;165:295:33;3088:46:46;165:295:33;;;;;;;;;-1:-1:-1;165:295:33;;;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;;;;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;;;;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;;;;;;-1:-1:-1;;;165:295:33;;;;;;;184:1:43;;;;:::o;:::-;165:295:33;;-1:-1:-1;;;184:1:43;;;;;;;;;;;165:295:33;184:1:43;165:295:33;;;184:1:43;;;;295:6;;;;:::o;:::-;165:295:33;;-1:-1:-1;;;295:6:43;;;;;;;;;;;165:295:33;-1:-1:-1;;;165:295:33;;;295:6:43;;;;;;;;:::o;:::-;165:295:33;;-1:-1:-1;;;295:6:43;;;;;;;;;;;165:295:33;295:6:43;165:295:33;;;295:6:43;-1:-1:-1;;;295:6:43;;;;;;;;;;;:::o;:::-;165:295:33;;-1:-1:-1;;;295:6:43;;;;;;;;;;;165:295:33;-1:-1:-1;;;165:295:33;;;295:6:43;;;;341:4;;;;:::o;:::-;165:295:33;;-1:-1:-1;;;341:4:43;;;;;;;;;;;165:295:33;341:4:43;165:295:33;;;341:4:43;-1:-1:-1;;;341:4:43;;;;;;;;165:295:33;;;341:4:43;;;;;;;;;-1:-1:-1;;341:4:43;;;;;;;;:::o;:::-;;;;;;;;;;:::o;766:7::-;;;;:::o;:::-;165:295:33;;-1:-1:-1;;;766:7:43;;;;;;;;;;;165:295:33;-1:-1:-1;;;165:295:33;;;766:7:43;;;;817;;;;:::o;:::-;165:295:33;;-1:-1:-1;;;817:7:43;;;;;;;;;;;165:295:33;-1:-1:-1;;;165:295:33;;;817:7:43;;;;165:295:33;;;;:::o;:::-;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;;;;;;-1:-1:-1;;;165:295:33;;;;;;;5215:893:29;;;;;5438:1;12687:26:44;5215:893:29;165:295:33;;;5426:13:29;;;:42;;;5215:893;5422:272;;5215:893;-1:-1:-1;;;;;;165:295:33;;;11776:63:44;11784:20;;;11776:63;:::i;:::-;-1:-1:-1;;;;;11857:89:44;;;12687:26;;11962:41;;11968:34;;11879:66;165:295:33;11968:34:44;:::i;11962:41::-;12031:66;12009:110;-1:-1:-1;;;;;12017:80:44;;;12009:110;:::i;:::-;-1:-1:-1;;;4012:68:44;;4011:74;;12227:6;165:295:33;6556:24:44;165:295:33;;;;6563:16:44;165:295:33;6556:24:44;165:295:33;12198:35:44;12227:6;;;;12279:49;;;;-1:-1:-1;;;12279:49:44;165:295:33;;-1:-1:-1;;1166:41:43;;;12262:80:44;;;1166:41:43;;;;;;165:295:33;;;12262:80:44;;165:295:33;1166:41:43;;;12262:80:44;;165:295:33;;12262:80:44;;;;;;:::i;:::-;165:295:33;12252:91:44;;12194:470;;165:295:33;;12687:26:44;;;;1166:41:43;;;;165:295:33;1166:41:43;;;;;165:295:33;;;;1166:41:43;;;165:295:33;1166:41:43;;;165:295:33;1166:41:43;165:295:33;1166:41:43;12687:26:44;;;;;;;;;;;;5438:1:29;12687:26:44;6043:24:29;;5866:72;;5894:44;;12687:26:44;;12669:66;;-1:-1:-1;;;;;165:295:33;12677:36:44;;12669:66;:::i;:::-;165:295:33;;-1:-1:-1;;;;;165:295:33;;;;;8706:108:44;;8565:254;5894:44:29;5866:25;;295:6:43;;12457:12:29;295:6:43;;;;;;;5866:72:29;1377:12:44;1370:3;165:295:33;;;1354:35:44;;165:295:33;;;6043:24:29;:::i;:::-;6080:23;5438:1;6080:23;;5215:893::o;12687:26:44:-;;:::i;12279:49::-;-1:-1:-1;;;12279:49:44;;12194:470;12356:308;;;;165:295:33;;;12397:46:44;;;;;;;;914:43:43;;1333:52;914:43;;;;;165:295:33;914:43:43;;;12397:46:44;165:295:33;12387:57:44;;12356:308;12194:470;;12356:308;12509:149;;;;;;;;1333:52:43;12509:149:44;;;;;12356:308;12194:470;;5422:272:29;5571:116;719:10:20;;165:295:33;;5579:20:29;165:295:33;;;;;;;;5579:47:29;5571:116;:::i;:::-;5422:272;;;5426:42;-1:-1:-1;719:10:20;-1:-1:-1;;;;;165:295:33;;5443:25:29;;5426:42;;165:295:33;;;;:::o;:::-;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;;;;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;-1:-1:-1;;;165:295:33;;;;;;;;;864:10:43;165:295:33;;;;;;;:::o;:::-;;766:7:43;165:295:33;;;;;;;:::o;:::-;;12000:2:44;165:295:33;;;;;;;:::o;:::-;;;;;;;;;;:::o;11239:447:29:-;-1:-1:-1;295:6:43;;;11381:12:29;295:6:43;;;;;165:295:33;;-1:-1:-1;;;;;;165:295:33;295:6:43;165:295:33;;;;;;1370:3:44;165:295:33;;;1377:12:44;1354:35;165:295:33;10483:2:44;165:295:33;;;-1:-1:-1;;;165:295:33;;10460:38:44;165:295:33;-1:-1:-1;165:295:33;11519:19:29;295:6:43;165:295:33;295:6:43;-1:-1:-1;165:295:33;;;;;;;;;;;;11637:6:29;165:295:33;;719:10:20;11637:6:29;;:::i;:::-;11656:25;-1:-1:-1;11656:25:29;;11239:447::o;165:295:33:-;;;;:::o;:::-;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;;;;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;;;;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;;;;;;-1:-1:-1;;;165:295:33;;;;;;;227:161;;332:5;368:14;227:161;332:5;:::i;368:14::-;227:161::o;3692:174:46:-;165:295:33;;;3773:16:46;3787:2;3773:16;;;:36;;;;3692:174;3772:89;;;;3765:96;;3692:174;:::o;3772:89::-;3829:3;-1:-1:-1;3816:16:46;-1:-1:-1;3816:16:46;3815:45;;3772:89;3692:174;:::o;3815:45::-;3858:1;165:295:33;;;;3838:21:46;3692:174;:::o;3773:36::-;3807:2;3793:16;;;;-1:-1:-1;3773:36:46;;1842:226:4;;1963:87;1898:6;-1:-1:-1;;;;;165:295:33;1873:80:4;1889:4;1881:23;;;1873:80;:::i;1963:87::-;2848:58:23;165:295:33;;;;;2856:6:23;165:295:33;;719:10:20;2856:22:23;2848:58;:::i;:::-;951:66:1;;165:295:33;;951:66:1;;;3478:17;;;;:::i;3380:526::-;165:295:33;;-1:-1:-1;;;3531:63:1;;165:295:33;3531:63:1;165:295:33;3531:63:1;165:295:33;-1:-1:-1;;;;;165:295:33;;3531:63:1;;3384:59;;3531:63;;;3380:526;-1:-1:-1;3527:302:1;;165:295:33;;-1:-1:-1;;;3758:56:1;;165:295:33;3758:56:1;3531:63;3758:56;;;:::i;:::-;;;;3527:302;3885:9;3644:28;3636:82;-1:-1:-1;;;;;;;;;;;3971:4:4;3644:28:1;;3636:82;:::i;:::-;3885:9;:::i;3531:63::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;;;165:295:33;;;;:::o;:::-;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;;;;;;-1:-1:-1;;;165:295:33;;;;;;;864:10:43;;;;:::o;:::-;165:295:33;;-1:-1:-1;;;864:10:43;;;;;;;;;;;165:295:33;864:10:43;165:295:33;;;864:10:43;-1:-1:-1;;;864:10:43;;;;;;;8261:404:45;165:295:33;;8356:2:45;8342:16;;8356:2;;8368:8;8375:1;8368:8;:::o;8338:306::-;8407:3;8393:17;;:46;;;8338:306;8393:75;;;8338:306;8389:255;;;8478:10;8485:3;8478:10;:::o;8389:255::-;8518:3;8505:16;;:37;;;8389:255;8501:143;;;8552:10;8559:3;8552:10;:::o;8501:143::-;8592:3;8579:16;;:37;;;;8501:143;8575:69;;;8656:4;8261:404;:::o;8575:69::-;8633:4;8626:11;:::o;8579:37::-;8613:3;8599:17;;;;8579:37;;;8505;8525:17;8539:3;8525:17;;;8505:37;;8393:75;;8443:25;8393:75;;:46;;8414:25;8393:46;;3548:433:29;;3716:92;;-1:-1:-1;;3548:433:29;165:295:33;;-1:-1:-1;;;;;165:295:33;719:10:20;3782:25:29;;165:295:33;;-1:-1:-1;;;165:295:33;8707:56:44;295:6:43;;165:295:33;295:6:43;;;165:295:33;;;295:6:43;165:295:33;;8706:96:44;;:108;295:6:43;-1:-1:-1;295:6:43;3716:12:29;295:6:43;;;-1:-1:-1;295:6:43;165:295:33;;295:6:43;;;;;165:295:33;;;;;;;;;;3716:92:29;3916:24;1377:12:44;165:295:33;1370:3:44;165:295:33;1354:35:44;719:10:20;165:295:33;;;3916:24:29;:::i;8707:56:44:-;;;;165:295:33;;;;:::o;:::-;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;-1:-1:-1;;;165:295:33;;;;;;;16525:144:25;;4496:13:23;16525:144:25;4006:15:23;16525:144:25;16576:81;295:6:43;165:295:33;;7150:2:44;165:295:33;;16584:45:25;16576:81;:::i;:::-;3817:68:23;-1:-1:-1;;;;;165:295:33;;3825:23:23;;3817:68;:::i;:::-;165:295:33;;;7150:2:44;3919:40:23;;165:295:33;;;;;;;-1:-1:-1;;;;;;165:295:33;;;;;;;;3919:40:23;165:295:33;;;;3919:40:23;165:295:33;3919:40:23;165:295:33;3909:51:23;;4006:15;165:295:33;-1:-1:-1;;;;;165:295:33;;3909:51:23;4006:15;:::i;:::-;1370:3:44;165:295:33;;;1377:12:44;1354:35;6854:18;4403:6:23;165:295:33;;;4166:22:23;4157:31;2657:2:44;165:295:33;;;2663:12:44;2641:34;4157:31:23;;:::i;:::-;4215:36;4195:57;10483:2:44;165:295:33;;;-1:-1:-1;;;165:295:33;;10460:38:44;165:295:33;;;;3610:19:25;165:295:33;;;;;;;4195:57:23;:67;165:295:33;;;4195:67:23;:::i;:::-;165:295:33;;;-1:-1:-1;;;8386:2:44;165:295:33;;;;8349:52:44;165:295:33;;;;3610:19:25;165:295:33;;;;;4268:80:23;165:295:33;;;4268:80:23;:::i;:::-;165:295:33;;719:10:20;4403:6:23;;:::i;:::-;719:10:20;7428:24:44;7449:2;165:295:33;;;7434:17:44;165:295:33;4496:13:23;4522:25;-1:-1:-1;4522:25:23;;16525:144:25:o;165:295:33:-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;;;;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;;;;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;;;;;;;;;2821:97:23;;;2848:58;165:295:33;;;;;2856:6:23;165:295:33;;719:10:20;2856:22:23;2848:58;:::i;:::-;165:295:33;;;;1719:31:23;165:295:33;;-1:-1:-1;1844:3:23;165:295:33;;;;;1825:17:23;;;;;;1874:9;1885:10;1874:9;1885:10;;1874:9;;1844:3;1874:9;;;:::i;:::-;165:295:33;-1:-1:-1;;;;;165:295:33;;;1874:9:23;1885:10;;;:::i;:::-;165:295:33;;;;;1885:10:23;;;:::i;1844:3::-;1812:11;;1825:17;;;;;;2821:97::o;165:295:33:-;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;;;;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;10623:612:29;;;;;10916:9;10623:612;10916:9;;:::i;:::-;-1:-1:-1;295:6:43;;;10933:12:29;295:6:43;;;;;165:295:33;;-1:-1:-1;;;;;;165:295:33;295:6:43;165:295:33;;;1377:12:44;165:295:33;1370:3:44;165:295:33;1354:35:44;165:295:33;;;11091:34:29;165:295:33;11091:34:29;;-1:-1:-1;;;165:295:33;10351:152:44;10483:2;165:295:33;;10460:38:44;10351:152;;11091:34:29;165:295:33;-1:-1:-1;165:295:33;11071:19:29;295:6:43;165:295:33;295:6:43;-1:-1:-1;165:295:33;;;;;;;;;;;;11186:6:29;165:295:33;;11186:6:29;:::i;165:295:33:-;;;;;;;;;;;;:::o;:::-;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;;:::o;3502:330:45:-;-1:-1:-1;;;;;165:295:33;;;;;;;3614:12:45;165:295:33;;;;;;;;;;;;;;;3658:20:45;165:295:33;;;;;;;;;3694:14:45;;:33;;;;3502:330;3690:62;;3764:63;3784:42;;;10351:152:44;165:295:33;-1:-1:-1;;;10351:152:44;165:295:33;;10483:2:44;165:295:33;;10460:38:44;10351:152;;3764:63:45;165:295:33;3502:330:45;:::o;3690:62::-;3737:8;;165:295:33;3737:8:45;:::o;3694:33::-;3712:15;;;3694:33;;165:295:33;;;;:::o;:::-;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;;;;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;:::o;7461:560:44:-;165:295:33;;;7553:3:44;7539:17;;7553:3;;-1:-1:-1;165:295:33;;;;7614:21:44;:::o;7621:14::-;7614:21;:::o;7535:430::-;7666:2;7652:16;;7666:2;;7712:8;;165:295:33;7712:8:44;:::o;7648:317::-;7751:3;7737:17;;7751:3;;7819:14;7818:20;7819:14;7818:25;7819:14;;:::i;:::-;165:295:33;;;;;;7818:20:44;:25;:::i;7733:232::-;7874:3;-1:-1:-1;7860:17:44;7856:109;;165:295:33;;-1:-1:-1;;;7970:46:44;;165:295:33;7970:46:44;;;165:295:33;;;;;;;;;;;-1:-1:-1;;;165:295:33;;;;;;3758:56:1;7856:109:44;7943:15;;;:::i;1267:127::-;1370:3;165:295:33;1377:12:44;1354:35;;1267:127::o;165:295:33:-;;;;:::o;:::-;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;-1:-1:-1;;;165:295:33;;;;;;;1166:41:43;165:295:33;;1166:41:43;;;;;;;165:295:33;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;;;;;;-1:-1:-1;;;165:295:33;;;;;;;;;4696:4:45;165:295:33;;;;;;4696:4:45;165:295:33;;;;;;;:::o;:::-;;410:1:43;165:295:33;;;;;;410:1:43;165:295:33;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;:::o;550:58:45:-;;;;;;165:295:33;;;;:::i;:::-;;;;;;;;:::i;:::-;;;550:58:45;-1:-1:-1;550:58:45;;;;:::o;:::-;165:295:33;550:58:45;:::o;:::-;;;;;;;;;;;;;:::i;:::-;;;;:::o;:::-;165:295:33;;-1:-1:-1;;;550:58:45;;;;;;;;;;;165:295:33;-1:-1:-1;;;165:295:33;;;550:58:45;;;;;;;;:::o;:::-;165:295:33;;-1:-1:-1;;;550:58:45;;;;;;;;;;;165:295:33;550:58:45;165:295:33;;;550:58:45;-1:-1:-1;;;550:58:45;;;;;;;4430:884;;4540:55;4548:10;;;4540:55;:::i;:::-;4606:24;;;:::i;:::-;;;;4687:13;;;4679:74;4687:13;;:::i;:::-;4704:9;4687:26;4679:74;:::i;4602:708::-;4811:25;4557:1;4811:25;;;5082:123;;4992:35;5214:89;4811:25;5002;4811;;;;165:295:33;;;;5169:13:46;165:295:33;;;;;;;4811:25:45;165:295:33;4845:51:45;-1:-1:-1;;;;;165:295:33;;4853:19:45;;4845:51;:::i;:::-;4904:79;1476:19:8;;:23;;4904:79:45;:::i;5002:25::-;4992:35;;:::i;:::-;165:295:33;;-1:-1:-1;;;5082:123:45;;;;;;-1:-1:-1;;;;;165:295:33;;;5082:123:45;;;165:295:33;5176:4:45;550:58;;;165:295:33;550:58:45;;;165:295:33;;;;;;;550:58:45;;;;;5082:123;5071:135;;;;;;:::i;:::-;5222:57;;;4602:708;5214:89;;:::i;5222:57::-;165:295:33;;5234:16:45;;;-1:-1:-1;5234:44:45;;;;5222:57;;;;;;5234:44;5254:24;;;5082:123;5254:24;;;;;;;;:::i;:::-;5234:44;;;;445:46;;;;:::o;:::-;165:295:33;;-1:-1:-1;;;445:46:45;;;;;;;;;;;165:295:33;-1:-1:-1;;;165:295:33;;;445:46:45;;;;5678:864;;;;5789:24;;;:::i;:::-;;;;5892:6;;;;:::i;5785:753::-;5957:25;6438:85;5957:25;6126;6321:106;;6079:35;5957:25;;6089;5957;;;165:295:33;;;;5169:13:46;165:295:33;;;;;;;5957:25:45;165:295:33;-1:-1:-1;;;;;165:295:33;;5991:79:45;1476:19:8;;:23;;4904:79:45;:::i;6079:35::-;165:295:33;;-1:-1:-1;;;6321:106:45;;;;;;-1:-1:-1;;;;;165:295:33;;;6321:106:45;;;165:295:33;445:46:45;;;165:295:33;;;;;;;445:46:45;;;;;6321:106;6310:118;;;;;;:::i;:::-;6446:57;;;5785:753;6438:85;;:::i;6446:57::-;165:295:33;;6458:16:45;;;-1:-1:-1;6458:44:45;;;;6446:57;;;;;;6458:44;6478:24;;;6321:106;6478:24;;;;;;;;:::i;:::-;6458:44;;;;951:66:1;;;;;;;;;;;:::o;:::-;;;;:::o;:::-;165:295:33;;-1:-1:-1;;;951:66:1;;;;;;;;;;;165:295:33;951:66:1;165:295:33;;;951:66:1;-1:-1:-1;;;951:66:1;;;;;;;;;;;;;;;;;165:295:33;951:66:1;165:295:33;;;951:66:1;-1:-1:-1;;;951:66:1;;;;;;:::o;2938:974::-;;951:66;;;165:295:33;;;;951:66:1;;;;3478:17;;;;:::i;3380:526::-;165:295:33;;-1:-1:-1;;;3531:63:1;;165:295:33;3531:63:1;165:295:33;3531:63:1;165:295:33;-1:-1:-1;;;;;165:295:33;;3531:63:1;;3495:1:4;;3531:63:1;;;3380:526;-1:-1:-1;3527:302:1;;165:295:33;;-1:-1:-1;;;3758:56:1;;165:295:33;3758:56:1;3531:63;3758:56;;;:::i;3527:302::-;3885:9;3644:28;3636:82;-1:-1:-1;;;;;;;;;;;3495:1:4;3644:28:1;;3636:82;:::i;3531:63::-;;;;;;;;;;;;;;;:::i;:::-;;;;;2922:236:23;-1:-1:-1;;;;;165:295:33;2991:22:23;;165:295:33;;3076:6:23;165:295:33;;-1:-1:-1;;;;;;165:295:33;;;;;;;-1:-1:-1;;;;;165:295:33;3116:37:23;-1:-1:-1;;3116:37:23;2922:236::o;165:295:33:-;;;;;;;;;;;;;;;;;;;;;;;;;3282:325:23;-1:-1:-1;;;;;165:295:33;3365:31:23;;165:295:33;;3471:15:23;165:295:33;;-1:-1:-1;;;;;;165:295:33;;;;;;;-1:-1:-1;;;;;165:295:33;3538:64:23;-1:-1:-1;;3538:64:23;3282:325::o;165:295:33:-;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;;;;;;-1:-1:-1;;;165:295:33;;;;;;;705:161:44;165:295:33;;;820:40:44;;;165:295:33;;;;;;;;-1:-1:-1;;;;;;165:295:33;;;;;820:40:44;;165:295:33;;;;820:40:44;165:295:33;820:40:44;165:295:33;810:51:44;;705:161;:::o;1398:182::-;1377:12;165:295:33;1370:3:44;165:295:33;1354:35:44;1514:22;2663:12;165:295:33;2657:2:44;165:295:33;2641:34:44;341:4:43;;;;;;;1539:36:44;;;:::i;:::-;341:4:43;;;;;;;1398:182:44;:::o;4785:292::-;4894:36;;;:::i;:::-;4940:17;;;;;4936:123;;5064:8;;;165:295:33;4785:292:44;:::o;4936:123::-;4990:3;165:295:33;;;;;4990:3:44;165:295:33;;;;;5045:6:44;4996:56;165:295:33;5038:3:44;165:295:33;5022:29:44;4996:56;:::i;:::-;165:295:33;;;;;;4967:85:44;:::o;165:295:33:-;;;;;;;;;;;;14626:530:44;-1:-1:-1;;;;;165:295:33;;;;14626:530:44;;14735:63;14743:20;;;14735:63;:::i;:::-;165:295:33;11879:66:44;;;;14816:89;;165:295:33;;;14959:2:44;165:295:33;;;;;;;15103:26:44;;14761:1;;165:295:33;;15103:26:44;;14968:110;-1:-1:-1;;;;;14976:80:44;;;14968:110;:::i;:::-;165:295:33;;;;;;15103:26:44;;1166:41:43;;;;165:295:33;1166:41:43;;;;;165:295:33;;;;1166:41:43;;;165:295:33;1166:41:43;;;165:295:33;1166:41:43;165:295:33;1166:41:43;15103:26:44;;;;;;;;;;;;14761:1;15103:26;15085:66;;-1:-1:-1;;;;;165:295:33;;;15093:36:44;15085:66;:::i;14558:535:25:-;-1:-1:-1;;;3436:68:44;;165:295:33;;3176:3:44;165:295:33;-1:-1:-1;;;;;165:295:33;;7428:35:45;;7331:90;1476:19:8;;:23;;7331:90:45;:::i;:::-;7438:25;;;:::i;7428:35::-;7473:24;;;;:::i;:::-;;;;-1:-1:-1;165:295:33;;-1:-1:-1;;;7546:154:45;;165:295:33;7546:154:45;;;165:295:33;;;;;;;-1:-1:-1;;;;;165:295:33;;;;;;;-1:-1:-1;;;;;165:295:33;;;;;;;;7546:154:45;;165:295:33;;;;;;;;;7546:154:45;;;;;;;;7469:615;;14558:535:25:o;7546:154:45:-;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;7469:615;7758:25;;;;;;165:295:33;;;;5169:13:46;165:295:33;;;;;;;7758:25:45;7799;7791:79;1476:19:8;;:23;;4904:79:45;:::i;7791:::-;165:295:33;;-1:-1:-1;;;7885:50:45;;-1:-1:-1;;;;;165:295:33;;7885:50:45;;;165:295:33;445:46:45;;;165:295:33;;;;7885:50:45;165:295:33;;445:46:45;;;7885:50;165:295:33;-1:-1:-1;;;;;;165:295:33;;7885:50:45;;;;;;;;;-1:-1:-1;7885:50:45;;;7469:615;-1:-1:-1;165:295:33;;-1:-1:-1;;;7943:134:45;;-1:-1:-1;;;;;165:295:33;;;7885:50:45;7943:134;;165:295:33;;;;;;;;;;;;;;;-1:-1:-1;;;;;165:295:33;;;;;;;;;;;;;;;;;7943:134:45;;;;;;;;7469:615;227:161:33:o;7885:50:45:-;;;;;;;;;;;;;:::i;:::-;;;14684:405:25;14840:10;;;;;;14836:253;;14684:405;;;14558:535::o;14836:253::-;14897:6;;;:::i;13372:1250:44:-;-1:-1:-1;;;;;165:295:33;;;;14569:26:44;;13562:1;;13372:1250;14569:26;;13372:1250;13536:63;13544:20;;;13536:63;:::i;:::-;-1:-1:-1;;;;;13617:89:44;;;13722:41;;13728:34;;11879:66;165:295:33;11968:34:44;:::i;13722:41::-;12031:66;13769:110;-1:-1:-1;;;;;13777:80:44;;;13769:110;:::i;:::-;-1:-1:-1;;;4012:68:44;;4011:74;;13987:6;165:295:33;6556:24:44;6563:16;;165:295:33;;;;6556:24:44;165:295:33;13958:35:44;13987:6;;;;14039:49;;;;-1:-1:-1;;;999:43:43;14022:91:44;;14039:49;14022:91;165:295:33;;14022:91:44;;;;;;;;1250:41:43;;;;1166;;;;;1250;;;165:295:33;;;;;;;1250:41:43;;;165:295:33;1250:41:43;;;14569:26:44;;;;;;;;;;;;13562:1;14569:26;14551:66;;14569:26;-1:-1:-1;;;;;165:295:33;14559:36:44;165:295:33;14039:49:44;-1:-1:-1;;;914:43:43;14022:91:44;;14039:49;;13954:592;14127:419;;;;165:295:33;;1545:98:43;14168:60:44;;;914:43:43;;;999;;;165:295:33;;;;;;;;;-1:-1:-1;;;;;;165:295:33;999:43:43;;;165:295:33;14168:60:44;165:295:33;999:43:43;;;14168:60:44;999:43:43;14127:419:44;7135:17;13987:6;14269:36;7128:25;7135:17;;165:295:33;;;;14269:36:44;;:84;;;;1545:98:43;14269:84:44;;14361:179;;;;;;;;;;;;;;14127:419;13954:592;;14269:84;1426:69:43;14269:84:44;;;1732:667;165:295:33;;;1905:3:44;1891:17;;1905:3;;1918:32;2303:51;:43;:24;555:3:43;1887:347:44;1370:3;165:295:33;1377:12:44;1354:35;;1267:127;2303:24;:43;:::i;:::-;2349:5;165:295:33;;;;2303:51:44;2367:27;:12;;;;;;:27;1732:667;:::o;2367:27::-;;;1732:667;:::o;1887:347::-;1981:3;1967:17;;1981:3;;1994:32;2303:51;:43;:24;632:4:43;1963:271:44;1370:3;165:295:33;1377:12:44;1354:35;;1267:127;1963:271;2057:3;2043:17;;2057:3;;2070:32;2303:51;:43;:24;555:3:43;2039:195:44;1887:347;;2039:195;2133:3;-1:-1:-1;2133:3:44;;2303:51;:43;:24;700:2:43;2115:119:44;1370:3;165:295:33;1377:12:44;1354:35;;1267:127;2115:119;2303:51;:43;:24;489:7:43;2115:119:44;1370:3;165:295:33;1377:12:44;1354:35;;1267:127;5357:215;5444:30;;;:::i;:::-;5440:114;;5559:8;165:295:33;5357:215:44;:::o;5440:114::-;5540:6;5491:56;165:295:33;5533:3:44;165:295:33;5517:29:44;5491:56;:::i;5773:206::-;5862:30;;;:::i;:::-;5858:103;;5966:8;165:295:33;5773:206:44;:::o;5858:103::-;5932:3;165:295:33;5939:6:44;5910:35;5949:5;165:295:33;;;;;;5902:52:44;:::o;6546:183:45:-;6674:4;165:295:33;;;;;;6674:4:45;165:295:33;;;;;;;-1:-1:-1;6643:40:45;;;;;;;;;:::i;:::-;;165:295:33;;;6546:183:45:o;165:295:33:-;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;;;;;;-1:-1:-1;;;165:295:33;;;;;;;4530:506:46;4599:50;165:295:33;;;4607:10:46;;4599:50;:::i;:::-;-1:-1:-1;;;;;165:295:33;;4663:19:46;;165:295:33;;5003:28:46;4724:19;5003:20;4724:19;4716:64;4724:24;:19;;;165:295:33;;;;;;;;5274:12:46;165:295:33;;;;;;;4724:24:46;;4716:64;:::i;:::-;4786:66;4794:34;:20;;;165:295:33;;;;5169:13:46;165:295:33;;;;;;;4794:34:46;;4786:66;:::i;:::-;4862:19;;;:::i;:::-;4858:107;;4530:506;-1:-1:-1;;;;;;165:295:33;;;;;;5274:12:46;165:295:33;;;;;;;-1:-1:-1;;165:295:33;;;;;;;4970:27:46;165:295:33;4858:107:46;4916:3;4891:67;4899:21;;4891:67;:::i;:::-;4858:107;;;165:295:33;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;-1:-1:-1;;;165:295:33;;;;;;;2478:288:1;;;2277:17;;;:::i;:::-;165:295:33;;;-1:-1:-1;;;;;165:295:33;;2310:27:1;;;;165:295:33;;2659:15:1;;;;:28;;;2478:288;2655:105;;;2478:288;;;:::o;2655:105::-;1476:19:8;;:23;165:295:33;;7395:25:1;2310:27;7395:25;;;;7437:99;7395:25;;;;;;;;;:::i;:::-;165:295:33;;;;;;;:::i;:::-;;;;;7395:25:1;165:295:33;;;-1:-1:-1;;;165:295:33;;;;7437:99:1;:::i;165:295:33:-;-1:-1:-1;;;165:295:33;;;;;;;;;;;;;;;;;-1:-1:-1;;;165:295:33;;;;;;;2659:28:1;;;;;;1805:281;1476:19:8;;:23;165:295:33;;-1:-1:-1;;;;;;;;;;;165:295:33;;-1:-1:-1;;;;;;165:295:33;-1:-1:-1;;;;;165:295:33;;;;;;;;;;1805:281:1:o;165:295:33:-;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;;;;;;-1:-1:-1;;;165:295:33;;;;;;;4372:409:44;4468:30;;;:::i;:::-;4464:299;;4768:8;165:295:33;4372:409:44;:::o;4464:299::-;4543:6;165:295:33;4536:3:44;165:295:33;4520:29:44;4543:6;4561:11;;4557:151;;4722:28;;;;:::i;:::-;4753:3;165:295:33;;;;;;4753:3:44;165:295:33;;;;;;;4715:41:44;:::o;4557:151::-;-1:-1:-1;1370:3:44;165:295:33;;;1377:12:44;1354:35;4618:22;2657:2;165:295:33;;;2663:12:44;2641:34;341:4:43;;;;;;;-1:-1:-1;;;3745:68:44;;3744:74;165:295:33;;-1:-1:-1;4584:115:44;:::o;4644:54::-;4674:24;;;:::i;:::-;4644:54;;5576:193;5669:4;5664:9;;;5660:38;;-1:-1:-1;;341:4:43;;;;;;;5724::44;165:295:33;;;5669:4:44;165:295:33;;;;;;;5724:4:44;341::43;165:295:33;;;;;;;5710:54:44;165:295:33;;;5710:54:44;;:::i;4094:274::-;4219:3;165:295:33;;7449:2:44;165:295:33;;4185:37:44;4184:179;;;;4177:186;4094:274;:::o;4184:179::-;-1:-1:-1;;;4235:68:44;;;4234:128;;4094:274;-1:-1:-1;4094:274:44:o;165:295:33:-;;;;:::o;:::-;;;-1:-1:-1;;;165:295:33;;;;;;;;;;;;;;;;;-1:-1:-1;;;165:295:33;;;;;;;5081:272:44;-1:-1:-1;;;3436:68:44;;3435:75;5171:37;;;:177;;5164:184;5081:272;:::o;5171:177::-;-1:-1:-1;;;5220:68:44;-1:-1:-1;;;5219:128:44;;5081:272;-1:-1:-1;5081:272:44:o;6622:742:8:-;;;;6792:566;;;6819:17;;:::o;6792:566::-;165:295:33;;6937:21:8;:17;;7121:154;;;;;;;6933:415;165:295:33;;;;;;7313:20:8;;165:295:33;7313:20:8;;;165:295:33;;;;;;;;;;6957:1:8;165:295:33;;;;;;;;;6957:1:8;165:295:33;;;;;;;;;;;;;;;7313:20:8;;;;165:295:33;;;;;;;;;;;;;;;;-1:-1:-1;165:295:33;;
Swarm Source
none
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.