20M+ users trust MoonPay worldwide. Checkout with your preferred payment method.
Ready to onboard to Ethereum? With MetaMask Portfolio, you're in control.
Don’t invest unless you’re prepared to lose all the money you invest.
Everyday giveaways up to 100 ETH, Lucky Spins. Deposit BONUS 300% and Cashbacks!
5000+ Slots & Live Casino Games, 50+cryptos. Register with Etherscan and get 760% deposit bonus. Win Big$, withdraw it fast.
Slots, Roulette, Poker & more - Proud sponsors of UFC, Everton & StakeF1 team!
5000+ Slots & Live Casino Games, 50+cryptos. Register with Etherscan and get 760% deposit bonus. Win Big$, withdraw it fast.
Anonymous play on awesome games - sign up now for 25 free jackpot spins - worth $100s!
100s of games, generous bonuses, 20+ years of trusted gaming. Join CryptoWins & start winning today!
Overview
ETH Balance
Eth Value
$80,940.55 (@ $3,431.51/ETH)Token Holdings
Could not find any matches!
- ERC-20 Tokens (25)0.001797 pumpBTCpumpBTC (pumpBT...)$174.85@97,301.78110.682499 SolvBTC.BBNSolvBTC Baby... (SolvBT...)$66,566.17@97,533.0033,570.128099 USDTTether USD (USDT)$33,637.27@1.00240,325.077342 USDCUSDC (USDC)$40,365.40@1.0011.00221 WBTCWrapped BTC (WBTC)$97,995.09@97,779.004.75ERC20 ***1 BLXBlotix1,000 EFTEverflow Token999,140.448671 MERLMERL (MERL)0.539376 M-BTCMerlin BTC (M-BTC)1.885742 SolvBTCSolv BTC$184,472.71@97,825.0033.226261 STONEStakeStone Ether$116,546.76@3,507.671.7 TokenERC-20 TOKEN*[Suspicious]3,999.99 TokenERC-20 TOKEN*[Suspicious]3,999.99 TokenERC-20 TOKEN*[Suspicious]7,000 TokenERC-20 TOKEN*[Suspicious]9,000 TokenERC-20 TOKEN*[Suspicious]7,000 TokenERC-20 TOKEN*[Suspicious]7,000 TokenERC-20 TOKEN*[Suspicious]7,000 TokenERC-20 TOKEN*[Unsafe]1.4 TokenERC-20 TOKEN*[Spam]9,283 TokenERC-20 TOKEN*[Spam]7,000 TokenERC-20 TOKEN*[Spam]50,000 TokenERC-20 TOKEN*[Spam]1,000 TokenERC-20 TOKEN*[Spam]NFT Tokens (20)claim rewards on apyusd.netapyusd.netERC-1155claim rewards on eth-pool.neteth-pool.netERC-1155Reward Club [E4H2EAoC]Reward Club [aA18Dds3]ERC-1155claim rewards on wbtcnetwork.netwbtcnetwork.netERC-1155debridgeth.comWithdrawal Badge debridgeth.comERC-1155debridgeth.comWithdrawal Badge debridgeth.comERC-1155ERC-1155 TOKEN*[Suspicious]ERC-1155 TOKEN*[Suspicious]ERC-1155 TOKEN*[Suspicious]ERC-1155 TOKEN*[Suspicious]ERC-1155 TOKEN*[Suspicious]ERC-1155 TOKEN*[Suspicious]
More Info
Private Name Tags
ContractCreator
Multichain Info
21 addresses found via- Arbiscan ($649,644)
BscScan ($467,562)
Optimism ($152,517)
Polygonscan ($121,274)
ScrollScan ($77,434)
SnowScan ($74,192)
LineaScan ($62,560)
BaseScan ($58,729)
Mantle ($42,298)
Cronos ($29,649)
opBNB ($28,331)
FTMScan ($22,217)
BlastScan ($19,973)
Polygon zkEVM ($10,824)
Taiko ($9,706)
Gnossiscan ($9,368)
Moonbeam ($9,067)
KromaScan ($8,303)
CeloScan ($5,720)
zkSync Era ($3,469)
Moonriver ($188)
- Transactions
- Internal Transactions
- Token Transfers (ERC-20)
- NFT Transfers
- Contract
- Events
- Analytics
- Multichain Portfolio
- Cards New
Advanced Filter- Filter by Tx Type:
- Tx
- Internal Tx
- ERC-20
- NFTs
Latest 25 from a total of 125,818 transactions
Transaction Hash MethodBlockFromToDirect Release 21251968 2024-11-23 17:35:11 9 mins ago 1732383311 IN 0 ETH$0.00 0.00214672 20.55619911 Direct Release 21251941 2024-11-23 17:29:47 15 mins ago 1732382987 IN 0 ETH$0.00 0.00227319 21.32991109 Direct Release 21251933 2024-11-23 17:28:11 16 mins ago 1732382891 IN 0 ETH$0.00 0.00233619 19.81119997 Direct Execute S... 21251903 2024-11-23 17:22:11 22 mins ago 1732382531 IN 0 ETH$0.00 0.00207912 23.07781848 Direct Release 21251779 2024-11-23 16:57:11 47 mins ago 1732381031 IN 0 ETH$0.00 0.00179238 20.0273255 Direct Release 21251729 2024-11-23 16:47:11 57 mins ago 1732380431 IN 0 ETH$0.00 0.002379 22.3177557 Direct Execute S... 21251704 2024-11-23 16:42:11 1 hr ago 1732380131 IN 0 ETH$0.00 0.00225852 23.7950256 Direct Release 21251479 2024-11-23 15:57:11 1 hr ago 1732377431 IN 0 ETH$0.00 0.00197037 25.46165513 Direct Release 21251454 2024-11-23 15:52:11 1 hr ago 1732377131 IN 0 ETH$0.00 0.00250167 22.25271774 Direct Execute S... 21251321 2024-11-23 15:25:35 2 hrs ago 1732375535 IN 1 ETH$3,431.51 0.00127754 20.35865744 Execute Swap 21251054 2024-11-23 14:31:59 3 hrs ago 1732372319 IN 0 ETH$0.00 0.00111094 24.98859818 Post Swap From I... 21251034 2024-11-23 14:27:59 3 hrs ago 1732372079 IN 0 ETH$0.00 0.00194351 23.4076493 Direct Release 21251006 2024-11-23 14:22:11 3 hrs ago 1732371731 IN 0 ETH$0.00 0.00218979 20.54275344 Direct Release 21251006 2024-11-23 14:22:11 3 hrs ago 1732371731 IN 0 ETH$0.00 0.00165757 20.54275344 Direct Release 21250982 2024-11-23 14:17:11 3 hrs ago 1732371431 IN 0 ETH$0.00 0.00189804 23.52302442 Direct Execute S... 21250952 2024-11-23 14:10:59 3 hrs ago 1732371059 IN 1 ETH$3,431.51 0.00138203 22.02371827 Direct Release 21250564 2024-11-23 12:52:59 4 hrs ago 1732366379 IN 0 ETH$0.00 0.0012569 15.57711969 Direct Release 21250431 2024-11-23 12:26:11 5 hrs ago 1732364771 IN 0 ETH$0.00 0.00133547 11.32422723 Direct Release 21250428 2024-11-23 12:25:35 5 hrs ago 1732364735 IN 0 ETH$0.00 0.00097354 12.08861151 Direct Execute S... 21250230 2024-11-23 11:45:59 5 hrs ago 1732362359 IN 0.029 ETH$99.51 0.00062684 9.99490316 Direct Execute S... 21250107 2024-11-23 11:21:23 6 hrs ago 1732360883 IN 0 ETH$0.00 0.0010762 12.16244112 Direct Release 21250017 2024-11-23 11:03:11 6 hrs ago 1732359791 IN 0 ETH$0.00 0.0011417 11.27706794 Direct Execute S... 21249894 2024-11-23 10:38:35 7 hrs ago 1732358315 IN 0.06 ETH$205.89 0.00070095 11.17445011 Direct Execute S... 21249876 2024-11-23 10:34:59 7 hrs ago 1732358099 IN 0 ETH$0.00 0.00090874 10.26709031 Direct Release 21249749 2024-11-23 10:09:23 7 hrs ago 1732356563 IN 0 ETH$0.00 0.00101336 10.61994993 Advanced mode: Intended for advanced users or developers and will display all Internal Transactions including zero value transfers. Name tag integration is not available in advanced view.Latest 25 internal transactions (View All)
Advanced mode:Parent Transaction Hash Block From To 21251968 2024-11-23 17:35:11 9 mins ago 1732383311 0 ETH$0.00 21251968 2024-11-23 17:35:11 9 mins ago 1732383311 0 ETH$0.00 21251968 2024-11-23 17:35:11 9 mins ago 1732383311 0 ETH$0.00 21251941 2024-11-23 17:29:47 15 mins ago 1732382987 0 ETH$0.00 21251941 2024-11-23 17:29:47 15 mins ago 1732382987 0 ETH$0.00 21251941 2024-11-23 17:29:47 15 mins ago 1732382987 0 ETH$0.00 21251933 2024-11-23 17:28:11 16 mins ago 1732382891 0 ETH$0.00 21251933 2024-11-23 17:28:11 16 mins ago 1732382891 0 ETH$0.00 21251933 2024-11-23 17:28:11 16 mins ago 1732382891 0 ETH$0.00 21251903 2024-11-23 17:22:11 22 mins ago 1732382531 0 ETH$0.00 21251903 2024-11-23 17:22:11 22 mins ago 1732382531 0 ETH$0.00 21251903 2024-11-23 17:22:11 22 mins ago 1732382531 0 ETH$0.00 21251779 2024-11-23 16:57:11 47 mins ago 1732381031 0 ETH$0.00 21251779 2024-11-23 16:57:11 47 mins ago 1732381031 0 ETH$0.00 21251779 2024-11-23 16:57:11 47 mins ago 1732381031 0 ETH$0.00 21251729 2024-11-23 16:47:11 57 mins ago 1732380431 0 ETH$0.00 21251729 2024-11-23 16:47:11 57 mins ago 1732380431 0 ETH$0.00 21251729 2024-11-23 16:47:11 57 mins ago 1732380431 0 ETH$0.00 21251704 2024-11-23 16:42:11 1 hr ago 1732380131 0 ETH$0.00 21251704 2024-11-23 16:42:11 1 hr ago 1732380131 0 ETH$0.00 21251704 2024-11-23 16:42:11 1 hr ago 1732380131 0 ETH$0.00 21251479 2024-11-23 15:57:11 1 hr ago 1732377431 10 ETH$34,315.06 21251479 2024-11-23 15:57:11 1 hr ago 1732377431 0 ETH$0.00 21251479 2024-11-23 15:57:11 1 hr ago 1732377431 0 ETH$0.00 21251454 2024-11-23 15:52:11 1 hr ago 1732377131 0 ETH$0.00 Loading...LoadingThis 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:ProxyToMeson
Compiler Versionv0.8.16+commit.07a7930e
Contract Source Code (Solidity Standard Json-Input format)
// Sources flattened with hardhat v2.10.1 https://hardhat.org // File @openzeppelin/contracts/proxy/[email protected] // 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 {} } // File @openzeppelin/contracts/proxy/beacon/[email protected] // 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); } // File @openzeppelin/contracts/interfaces/[email protected] // 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); } // File @openzeppelin/contracts/utils/[email protected] // 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); } } } } // File @openzeppelin/contracts/utils/[email protected] // 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 } } } // File @openzeppelin/contracts/proxy/ERC1967/[email protected] // OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol) pragma solidity ^0.8.2; /** * @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); } } } // File @openzeppelin/contracts/proxy/ERC1967/[email protected] // OpenZeppelin Contracts (last updated v4.7.0) (proxy/ERC1967/ERC1967Proxy.sol) pragma solidity ^0.8.0; /** * @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(); } } // File @openzeppelin/contracts-upgradeable/interfaces/[email protected] // 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); } // File @openzeppelin/contracts-upgradeable/proxy/beacon/[email protected] // 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); } // File @openzeppelin/contracts-upgradeable/utils/[email protected] // 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); } } } } // File @openzeppelin/contracts-upgradeable/utils/[email protected] // 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 } } } // File @openzeppelin/contracts-upgradeable/proxy/utils/[email protected] // OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; /** * @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); } } } // File @openzeppelin/contracts-upgradeable/proxy/ERC1967/[email protected] // OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol) pragma solidity ^0.8.2; /** * @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; } // File @openzeppelin/contracts-upgradeable/proxy/utils/[email protected] // OpenZeppelin Contracts (last updated v4.5.0) (proxy/utils/UUPSUpgradeable.sol) pragma solidity ^0.8.0; /** * @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; } // File contracts/Swap/IMesonSwapEvents.sol pragma solidity 0.8.16; /// @title MesonSwapEvents Interface interface IMesonSwapEvents { /// @notice Event when a swap request was posted. /// Emit at the end of `postSwap()` 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()` calls. /// @param encodedSwap Encoded swap event SwapCancelled(uint256 indexed encodedSwap); } // File contracts/utils/MesonTokens.sol pragma solidity 0.8.16; /// @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; zero means unsupported /// 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; zero means unsupported 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; /// @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"); indexOfToken[token] = index; tokenForIndex[index] = token; } } // File @openzeppelin/contracts/utils/[email protected] // 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; } } // File contracts/utils/IERC20Minimal.sol // SPDX-License-Identifier: GPL-2.0-or-later 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); } // File contracts/utils/ITransferWithBeneficiary.sol pragma solidity 0.8.16; /// @title Interface for transferWithBeneficiary interface ITransferWithBeneficiary { /// @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 transferWithBeneficiary(address token, uint256 amount, address beneficiary, uint64 data) external returns (bool); } // File contracts/utils/MesonConfig.sol pragma solidity 0.8.16; /// @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 = 10; // service fee = 10 / 10000 = 0.1% 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)"); } // File contracts/utils/MesonHelpers.sol pragma solidity 0.8.16; /// @title MesonHelpers /// @notice The class that provides helper functions for Meson protocol contract MesonHelpers is MesonConfig, Context { bytes4 private constant ERC20_TRANSFER_SELECTOR = bytes4(keccak256("transfer(address,uint256)")); bytes4 private constant ERC20_TRANSFER_FROM_SELECTOR = bytes4(keccak256("transferFrom(address,address,uint256)")); 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 Safe transfers tokens from Meson contract to a recipient /// for interacting with ERC20 tokens that do not consistently return true/false /// @param token The contract address of the token which will be transferred /// @param recipient The recipient of the transfer /// @param amount The value of the transfer (always in decimal 6) /// @param tokenIndex The index of token. See `tokenForIndex` in `MesonTokens.sol` function _safeTransfer( address token, address recipient, uint256 amount, uint8 tokenIndex ) internal { require(Address.isContract(token), "The given token address is not a contract"); if (_needAdjustAmount(tokenIndex)) { amount *= 1e12; } (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"); // The above do not support Tron, so need to switch to the next line if deploying to Tron // IERC20Minimal(token).transfer(recipient, amount); } /// @notice Transfer tokens to a contract using `transferWithBeneficiary` /// @param token The contract address of the token which will be transferred /// @param contractAddr The smart contract address that will receive transferring tokens /// @param beneficiary The beneficiary of `transferWithBeneficiary` /// @param amount The value of the transfer (always in decimal 6) /// @param tokenIndex The index of token. See `tokenForIndex` in `MesonTokens.sol` /// @param data Extra data passed to the contract function _transferToContract( address token, address contractAddr, address beneficiary, uint256 amount, uint8 tokenIndex, uint64 data ) internal { require(Address.isContract(token), "The given token address is not a contract"); require(Address.isContract(contractAddr), "The given recipient address is not a contract"); if (_needAdjustAmount(tokenIndex)) { amount *= 1e12; } IERC20Minimal(token).approve(contractAddr, amount); ITransferWithBeneficiary(contractAddr).transferWithBeneficiary(token, amount, beneficiary, data); } /// @notice Help the senders to transfer their assets to the Meson contract /// @param token The contract address of the token which will be transferred /// @param sender The sender of the transfer /// @param amount The value of the transfer (always in decimal 6) /// @param tokenIndex The index of token. See `tokenForIndex` in `MesonTokens.sol` function _unsafeDepositToken( address token, address sender, uint256 amount, uint8 tokenIndex ) internal { require(token != address(0), "Token not supported"); require(amount > 0, "Amount must be greater than zero"); require(Address.isContract(token), "The given token address is not a contract"); if (_needAdjustAmount(tokenIndex)) { amount *= 1e12; } (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 Determine if token has decimal 18 and therefore need to adjust amount /// @param tokenIndex The index of token. See `tokenForIndex` in `MesonTokens.sol` function _needAdjustAmount(uint8 tokenIndex) internal pure returns (bool) { return tokenIndex > 32 && tokenIndex < 255; } /// @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; } /// @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) { return _amountFrom(encodedSwap) * SERVICE_FEE_RATE / 10000; // Default to `serviceFee` = 0.1% * `amount` } /// @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; } /// @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); } /// @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 Decode `initiator` from `postedSwap` /// See variable `_postedSwaps` in `MesonSwap.sol` for the defination of `postedSwap` function _initiatorFromPosted(uint200 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(uint200 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 s Part of the signature /// @param v Part of the signature /// @param signer The signer for the swap request which is the `initiator` function _checkRequestSignature( uint256 encodedSwap, bytes32 r, bytes32 s, uint8 v, address signer ) internal pure { require(signer != address(0), "Signer cannot be empty address"); require(v == 27 || v == 28, "Invalid signature"); 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 s Part of the signature /// @param v 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 s, uint8 v, address signer ) internal pure { require(signer != address(0), "Signer cannot be empty address"); require(v == 27 || v == 28, "Invalid signature"); 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"); } } // File contracts/utils/MesonStates.sol pragma solidity 0.8.16; /// @title MesonStates /// @notice The class that keeps track of LP pool states contract MesonStates is MesonTokens, MesonHelpers { /// @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 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 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)]; } } // File contracts/Swap/MesonSwap.sol pragma solidity 0.8.16; /// @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 owa address, otherwise a smart contract; /// salt & 0x40000000000000000000 == true => will waive *service fee*; /// salt & 0x08000000000000000000 == true => use *non-typed signing* (some wallets such as hardware wallets don't support EIP-712v1); /// 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 `initiator:address|poolIndex:uint40` /// 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 => uint200) 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; /// @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 s Part of the signature /// @param v Part of the signature /// @param postingValue The value to be written to `_postedSwaps`. See `_postedSwaps` for encoding format function postSwap(uint256 encodedSwap, bytes32 r, bytes32 s, uint8 v, uint200 postingValue) external matchProtocolVersion(encodedSwap) forInitialChain(encodedSwap) { require(_postedSwaps[encodedSwap] == 0, "Swap already exists"); uint256 amount = _amountFrom(encodedSwap); require(amount <= MAX_SWAP_AMOUNT, "For security reason, amount cannot be greater than 100k"); uint256 delta = _expireTsFrom(encodedSwap) - block.timestamp; // Underflow would trigger "Expire ts too late" error require(delta > MIN_BOND_TIME_PERIOD, "Expire ts too early"); require(delta < MAX_BOND_TIME_PERIOD, "Expire ts too late"); uint40 poolIndex = _poolIndexFromPosted(postingValue); if (poolIndex > 0) { // In pool index is given, the signer should be 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 address initiator = _initiatorFromPosted(postingValue); _checkRequestSignature(encodedSwap, r, s, v, initiator); _postedSwaps[encodedSwap] = postingValue; uint8 tokenIndex = _inTokenIndexFrom(encodedSwap); _unsafeDepositToken(tokenForIndex[tokenIndex], initiator, amount, tokenIndex); emit SwapPosted(encodedSwap); } /// @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 { uint200 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 { uint200 postedSwap = _postedSwaps[encodedSwap]; require(postedSwap > 1, "Swap does not exist"); require(_expireTsFrom(encodedSwap) < block.timestamp, "Swap is still locked"); _postedSwaps[encodedSwap] = 0; // Swap expired so the same one cannot be posted again uint8 tokenIndex = _inTokenIndexFrom(encodedSwap); _safeTransfer(tokenForIndex[tokenIndex], _initiatorFromPosted(postedSwap), _amountFrom(encodedSwap), tokenIndex); 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 s Part of the release signature (same as in the `release` call) /// @param v 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 s, uint8 v, address recipient, bool depositToPool ) external { uint200 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. _postedSwaps[encodedSwap] = 0; } 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, s, v, _initiatorFromPosted(postedSwap)); uint8 tokenIndex = _inTokenIndexFrom(encodedSwap); uint40 poolIndex = _poolIndexFromPosted(postedSwap); if (depositToPool) { _balanceOfPoolToken[_poolTokenIndexFrom(tokenIndex, poolIndex)] += _amountFrom(encodedSwap); } else { _safeTransfer(tokenForIndex[tokenIndex], ownerOfPool[poolIndex], _amountFrom(encodedSwap), tokenIndex); } } /// @notice Read information for a posted swap function getPostedSwap(uint256 encodedSwap) external view returns (address initiator, address poolOwner, bool exist) { uint200 postedSwap = _postedSwaps[encodedSwap]; initiator = _initiatorFromPosted(postedSwap); exist = postedSwap > 0; if (initiator == address(0)) { poolOwner = address(0); } else { poolOwner = ownerOfPool[_poolIndexFromPosted(postedSwap)]; } } modifier forInitialChain(uint256 encodedSwap) { require(_inChainFrom(encodedSwap) == SHORT_COIN_TYPE, "Swap not for this chain"); _; } } // File contracts/Pools/IMesonPoolsEvents.sol pragma solidity 0.8.16; /// @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 a swap was locked. /// Emit at the end of `lock()` 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()` calls. /// @param encodedSwap Encoded swap event SwapReleased(uint256 indexed encodedSwap); } // File contracts/Pools/MesonPools.sol pragma solidity 0.8.16; /// @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) 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(tokenForIndex[tokenIndex], poolOwner, amount, tokenIndex); 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) 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(tokenForIndex[tokenIndex], _msgSender(), amount, tokenIndex); 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(tokenForIndex[tokenIndex], _msgSender(), amount, tokenIndex); 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 { require(poolOfAuthorizedAddr[addr] == 0, "Addr is authorized for another pool"); 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"); 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"); poolOfAuthorizedAddr[addr] = 0; emit PoolAuthorizedAddrRemoved(poolIndex, addr); } /// @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 with /// the same signature given by `postSwap`. This method 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 r Part of the signature (the one given by `postSwap` call) /// @param s Part of the signature (the one given by `postSwap` call) /// @param v Part of the signature (the one given by `postSwap` call) /// @param initiator The swap initiator who created and signed the swap request function lock( uint256 encodedSwap, bytes32 r, bytes32 s, uint8 v, address initiator ) external matchProtocolVersion(encodedSwap) forTargetChain(encodedSwap) { bytes32 swapId = _getSwapId(encodedSwap, initiator); require(_lockedSwaps[swapId] == 0, "Swap already exists"); _checkRequestSignature(encodedSwap, r, s, v, initiator); 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); // Only (amount - lp fee) is locked from the LP pool. The service fee will be charged on release _balanceOfPoolToken[poolTokenIndex] -= (_amountFrom(encodedSwap) - _feeForLp(encodedSwap)); _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 != 0, "Swap does not exist"); require(_untilFromLocked(lockedSwap) < block.timestamp, "Swap still in lock"); uint48 poolTokenIndex = _poolTokenIndexForOutToken(encodedSwap, _poolIndexFromLocked(lockedSwap)); // (amount - lp fee) will be returned because only that amount was locked _balanceOfPoolToken[poolTokenIndex] += (_amountFrom(encodedSwap) - _feeForLp(encodedSwap)); _lockedSwaps[swapId] = 0; 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 s Part of the release signature (same as in the `executeSwap` call) /// @param v 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 s, uint8 v, address initiator, address recipient ) external { bool feeWaived = _feeWaived(encodedSwap); if (feeWaived) { // For swaps that service fee is waived, need the premium manager as the signer _onlyPremiumManager(); } // For swaps that charge service fee, anyone can call bytes32 swapId = _getSwapId(encodedSwap, initiator); uint80 lockedSwap = _lockedSwaps[swapId]; require(lockedSwap != 0, "Swap does not exist"); require(recipient != address(0), "Recipient cannot be zero address"); require(_expireTsFrom(encodedSwap) > block.timestamp, "Cannot release because expired"); _checkReleaseSignature(encodedSwap, recipient, r, s, v, initiator); _lockedSwaps[swapId] = 0; uint8 tokenIndex = _outTokenIndexFrom(encodedSwap); // LP fee will be subtracted from the swap amount uint256 releaseAmount = _amountFrom(encodedSwap) - _feeForLp(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; } _release(encodedSwap, tokenIndex, initiator, recipient, releaseAmount); emit SwapReleased(encodedSwap); } function _release(uint256 encodedSwap, uint8 tokenIndex, address initiator, address recipient, uint256 amount) private { if (_willTransferToContract(encodedSwap)) { _transferToContract(tokenForIndex[tokenIndex], recipient, initiator, amount, tokenIndex, _saltDataFrom(encodedSwap)); } else { _safeTransfer(tokenForIndex[tokenIndex], recipient, amount, tokenIndex); } } /// @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]; poolOwner = ownerOfPool[_poolIndexFromLocked(lockedSwap)]; until = uint40(_untilFromLocked(lockedSwap)); } modifier forTargetChain(uint256 encodedSwap) { require(_outChainFrom(encodedSwap) == SHORT_COIN_TYPE, "Swap not for this chain"); _; } function _onlyPremiumManager() internal view virtual {} } // File contracts/MesonManager.sol pragma solidity 0.8.16; /// @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 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 { _onlyPremiumManager(); _transferPremiumManager(newPremiumManager); } 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 _onlyPremiumManager() internal view override { require(_premiumManager == _msgSender(), "Caller is not the premium manager"); } function _transferPremiumManager(address newPremiumManager) internal { require(newPremiumManager != address(0), "New premium manager be zero address"); address prevPremiumManager = _premiumManager; _premiumManager = newPremiumManager; emit PremiumManagerTransferred(prevPremiumManager, newPremiumManager); } } // File contracts/UpgradableMeson.sol pragma solidity 0.8.16; contract UpgradableMeson is UUPSUpgradeable, MesonManager { function initialize(address owner, address premiumManager) external initializer { _transferOwnership(owner); _transferPremiumManager(premiumManager); } function _authorizeUpgrade(address) internal override onlyOwner {} } // File contracts/ProxyToMeson.sol pragma solidity 0.8.16; 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); } }
{ "optimizer": { "enabled": true, "runs": 10000 }, "evmVersion": "istanbul", "metadata": { "bytecodeHash": "none" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
[{"inputs":[{"internalType":"address","name":"premiumManager","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"stateMutability":"payable","type":"fallback"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
608060405234801561001057600080fd5b506040516154b73803806154b783398101604081905261002f91610370565b610037610094565b604080513360248201526001600160a01b0384166044808301919091528251808303909101815260649091019091526020810180516001600160e01b031663485cc95560e01b17905261008c828260006100c6565b50505061040c565b6000806040516100a390610363565b604051809103906000f0801580156100bf573d6000803e3d6000fd5b5092915050565b6100cf836100fc565b6000825111806100dc5750805b156100f7576100f5838361013c60201b6100291760201c565b505b505050565b61010581610168565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061016183836040518060600160405280602781526020016154906027913961023a565b9392505050565b61017b8161031860201b6100551760201c565b6101e25760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084015b60405180910390fd5b806102197f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b61032760201b6100711760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b60606001600160a01b0384163b6102a25760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b60648201526084016101d9565b600080856001600160a01b0316856040516102bd91906103bd565b600060405180830381855af49150503d80600081146102f8576040519150601f19603f3d011682016040523d82523d6000602084013e6102fd565b606091505b50909250905061030e82828661032a565b9695505050505050565b6001600160a01b03163b151590565b90565b60608315610339575081610161565b8251156103495782518084602001fd5b8160405162461bcd60e51b81526004016101d991906103d9565b614d538061073d83390190565b60006020828403121561038257600080fd5b81516001600160a01b038116811461016157600080fd5b60005b838110156103b457818101518382015260200161039c565b50506000910152565b600082516103cf818460208701610399565b9190910192915050565b60208152600082518060208401526103f8816040850160208701610399565b601f01601f19169190910160400192915050565b6103228061041b6000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610074565b6100b9565b565b606061004e83836040518060600160405280602781526020016102ef602791396100dd565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156100d8573d6000f35b3d6000fd5b606073ffffffffffffffffffffffffffffffffffffffff84163b610188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516101b09190610281565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b509150915061020082828661020a565b9695505050505050565b6060831561021957508161004e565b8251156102295782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017f919061029d565b60005b83811015610278578181015183820152602001610260565b50506000910152565b6000825161029381846020870161025d565b9190910192915050565b60208152600082518060208401526102bc81604085016020870161025d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c6343000810000a60a06040523060805234801561001457600080fd5b50608051614d0761004c60003960008181610b4601528181610bdc015281816112060152818161129c01526113970152614d076000f3fe6080604052600436106101cd5760003560e01c80638b0a7765116100f7578063d3c7c2c711610095578063f1d2ec1d11610064578063f1d2ec1d1461060b578063f2fde38b1461062b578063ff22f2721461064b578063ff3787191461066b57600080fd5b8063d3c7c2c71461056e578063d3e95ea414610591578063d4f82322146105b1578063eba7fb77146105d157600080fd5b8063be18e8a4116100d1578063be18e8a4146104ee578063c11d9ecb1461050e578063ce7f79b91461052e578063ce9247431461054e57600080fd5b80638b0a7765146104765780638f487dc9146104ae578063b805f321146104ce57600080fd5b80634d11b0f11161016f57806360a2da981161013e57806360a2da98146103795780637fe0282b146103be5780638302ce5a1461040857806389a734c01461042857600080fd5b80634d11b0f1146103035780634f1ef2861461032357806352d1902d1461033657806354d6a2b71461035957600080fd5b806335eff30f116101ab57806335eff30f146102835780633659cfe6146102a357806337b90a4f146102c3578063485cc955146102e357600080fd5b8063051119f5146101d25780631e2a6075146101f45780632335093c14610241575b600080fd5b3480156101de57600080fd5b506101f26101ed3660046144b9565b6106a1565b005b34801561020057600080fd5b5061021461020f3660046144d4565b6108e2565b604080516001600160a01b0394851681529390921660208401521515908201526060015b60405180910390f35b34801561024d57600080fd5b5061027161025c3660046144b9565b60666020526000908152604090205460ff1681565b60405160ff9091168152602001610238565b34801561028f57600080fd5b506101f261029e366004614502565b610959565b3480156102af57600080fd5b506101f26102be3660046144b9565b610b3c565b3480156102cf57600080fd5b506101f26102de36600461452e565b610cd9565b3480156102ef57600080fd5b506101f26102fe366004614569565b610eaf565b34801561030f57600080fd5b506101f261031e3660046145b2565b611033565b6101f2610331366004614693565b6111fc565b34801561034257600080fd5b5061034b61138a565b604051908152602001610238565b34801561036557600080fd5b506101f26103743660046144d4565b61144f565b34801561038557600080fd5b50610399610394366004614757565b6115c2565b604080516001600160a01b03909316835264ffffffffff909116602083015201610238565b3480156103ca57600080fd5b506103f26103d93660046144b9565b60996020526000908152604090205464ffffffffff1681565b60405164ffffffffff9091168152602001610238565b34801561041457600080fd5b506101f261042336600461477a565b611611565b34801561043457600080fd5b5061045e6104433660046147ec565b609a602052600090815260409020546001600160a01b031681565b6040516001600160a01b039091168152602001610238565b34801561048257600080fd5b5061034b610491366004614807565b60281b65ff0000000000166000908152609b602052604090205490565b3480156104ba57600080fd5b506101f26104c936600461452e565b6119f2565b3480156104da57600080fd5b506101f26104e93660046144b9565b611cfc565b3480156104fa57600080fd5b506101f2610509366004614822565b611d0d565b34801561051a57600080fd5b506101f2610529366004614908565b612054565b34801561053a57600080fd5b506101f261054936600461452e565b612189565b34801561055a57600080fd5b506101f26105693660046149c8565b612357565b34801561057a57600080fd5b506105836125db565b604051610238929190614a27565b34801561059d57600080fd5b5061034b6105ac366004614569565b6127d1565b3480156105bd57600080fd5b506101f26105cc366004614aae565b612854565b3480156105dd57600080fd5b506040517e3c0000000000000000000000000000000000000000000000000000000000008152602001610238565b34801561061757600080fd5b506101f2610626366004614757565b6128b9565b34801561063757600080fd5b506101f26106463660046144b9565b612a4e565b34801561065757600080fd5b506101f26106663660046144b9565b612ab2565b34801561067757600080fd5b5061045e610686366004614807565b6065602052600090815260409020546001600160a01b031681565b3360008181526099602052604081205464ffffffffff16908190036107335760405162461bcd60e51b815260206004820152602360248201527f546865207369676e657220646f6573206e6f742072656769737465722061207060448201527f6f6f6c000000000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b64ffffffffff81166000908152609a60205260409020546001600160a01b038381169116146107ca5760405162461bcd60e51b815260206004820152602160248201527f4e6565642074686520706f6f6c206f776e657220617320746865207369676e6560448201527f7200000000000000000000000000000000000000000000000000000000000000606482015260840161072a565b6001600160a01b03831660009081526099602052604090205464ffffffffff8281169116146108615760405162461bcd60e51b815260206004820152602c60248201527f41646472206973206e6f7420617574686f72697a656420666f7220746865207360448201527f69676e6572277320706f6f6c0000000000000000000000000000000000000000606482015260840161072a565b6001600160a01b03831660008181526099602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000169055905191825264ffffffffff8316917f475b83c893df40ee19fd0783cf26478cdb58478dff65bb62560e1e7c36e0f22f91015b60405180910390a2505050565b600081815260ce60205260408120546001600160a01b03602882901c16919078ffffffffffffffffffffffffffffffffffffffffffffffffff16801515908361092e5760009250610951565b64ffffffffff81166000908152609a60205260409020546001600160a01b031692505b509193909250565b600082815260ce602052604090205478ffffffffffffffffffffffffffffffffffffffffffffffffff16600181116109d35760405162461bcd60e51b815260206004820152601360248201527f5377617020646f6573206e6f7420657869737400000000000000000000000000604482015260640161072a565b8064ffffffffff1615610a285760405162461bcd60e51b815260206004820152601b60248201527f5377617020626f6e64656420746f20616e6f7468657220706f6f6c0000000000604482015260640161072a565b3360009081526099602052604090205464ffffffffff838116911614610ab65760405162461bcd60e51b815260206004820152603860248201527f5369676e65722073686f756c6420626520616e20617574686f72697a6564206160448201527f646472657373206f662074686520676976656e20706f6f6c0000000000000000606482015260840161072a565b600083815260ce602052604080822080547fffffffffffffff000000000000000000000000000000000000000000000000001664ffffffffff861678ffffffffffffffffffffffffffffffffffffffffffffffffff8616171790555184917f60a99b51ae498c44acbbe11031aed2a06a32be66d2122e6e2a7a16c087865cc991a2505050565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610bda5760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c0000000000000000000000000000000000000000606482015260840161072a565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610c357f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b031614610cb15760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f78790000000000000000000000000000000000000000606482015260840161072a565b610cba81612ce6565b60408051600080825260208201909252610cd691839190612d41565b50565b60008211610d295760405162461bcd60e51b815260206004820152601760248201527f416d6f756e74206d75737420626520706f736974697665000000000000000000604482015260640161072a565b8064ffffffffff8116600003610d815760405162461bcd60e51b815260206004820152601a60248201527f43616e6e6f7420757365203020617320706f6f6c20696e646578000000000000604482015260640161072a565b3360009081526099602052604090205464ffffffffff828116911614610e0f5760405162461bcd60e51b815260206004820152602860248201527f4e65656420616e20617574686f72697a6564206164647265737320617320746860448201527f65207369676e6572000000000000000000000000000000000000000000000000606482015260840161072a565b65ffffffffffff82166000908152609b602052604081208054859290610e36908490614b07565b909155505060ff602883901c16600081815260656020526040902054610e67906001600160a01b0316338684612eff565b8265ffffffffffff167f7d7d1df74ef3a6434d8d63dc0a25d13d5fa94dbe738c38a3cce26e6f892e2a7685604051610ea191815260200190565b60405180910390a250505050565b600054610100900460ff1615808015610ecf5750600054600160ff909116105b80610ee95750303b158015610ee9575060005460ff166001145b610f5b5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161072a565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610fb957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610fc283613192565b610fcb82613253565b801561102e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b600086815260ce602052604090205478ffffffffffffffffffffffffffffffffffffffffffffffffff16600181116110ad5760405162461bcd60e51b815260206004820152601360248201527f5377617020646f6573206e6f7420657869737400000000000000000000000000604482015260640161072a565b6110b9610e1042614b07565b603088901c64ffffffffff16101561110457600087815260ce6020526040902080547fffffffffffffff0000000000000000000000000000000000000000000000000016905561113c565b600087815260ce6020526040902080547fffffffffffffff000000000000000000000000000000000000000000000000001660011790555b6111578784888888602887901c6001600160a01b031661333a565b868183156111a95764ffffffffff818116602884901b65ff000000000016176000908152609b60205260408120805460d08d901c939093169290919061119e908490614b07565b909155506111f19050565b60ff821660009081526065602090815260408083205464ffffffffff8581168552609a9093529220546111f1926001600160a01b039081169291169060d08d901c168561370e565b505050505050505050565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016300361129a5760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c0000000000000000000000000000000000000000606482015260840161072a565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166112f57f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b0316146113715760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f78790000000000000000000000000000000000000000606482015260840161072a565b61137a82612ce6565b61138682826001612d41565b5050565b6000306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461142a5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c0000000000000000606482015260840161072a565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b600081815260ce602052604090205478ffffffffffffffffffffffffffffffffffffffffffffffffff16600181116114c95760405162461bcd60e51b815260206004820152601360248201527f5377617020646f6573206e6f7420657869737400000000000000000000000000604482015260640161072a565b42603083901c64ffffffffff16106115235760405162461bcd60e51b815260206004820152601460248201527f53776170206973207374696c6c206c6f636b6564000000000000000000000000604482015260640161072a565b600082815260ce6020908152604080832080547fffffffffffffff0000000000000000000000000000000000000000000000000016905560ff8516835260659091529020548290611592906001600160a01b0390811690602885901c1664ffffffffff60d085901c168461370e565b60405183907ff6b6b4f7a13f02512c1b3aa8dcc4a07d7775a6a4becbd439efcbd37c5408e67f90600090a2505050565b60008060006115d185856138ed565b6000908152610101602090815260408083205464ffffffffff8082168552609a9093529220546001600160a01b03169760289290921c1695509350505050565b84600161161e8260f81c90565b60ff161461166e5760405162461bcd60e51b815260206004820152601a60248201527f496e636f727265637420656e636f64696e672076657273696f6e000000000000604482015260640161072a565b85603c61167b8260081c90565b61ffff16146116cc5760405162461bcd60e51b815260206004820152601760248201527f53776170206e6f7420666f72207468697320636861696e000000000000000000604482015260640161072a565b600087815260ce602052604090205478ffffffffffffffffffffffffffffffffffffffffffffffffff16156117435760405162461bcd60e51b815260206004820152601360248201527f5377617020616c72656164792065786973747300000000000000000000000000604482015260640161072a565b64ffffffffff60d088901c1664174876e8008111156117ca5760405162461bcd60e51b815260206004820152603760248201527f466f7220736563757269747920726561736f6e2c20616d6f756e742063616e6e60448201527f6f742062652067726561746572207468616e203130306b000000000000000000606482015260840161072a565b60006117e14264ffffffffff60308c901c16614b1a565b9050610e1081116118345760405162461bcd60e51b815260206004820152601360248201527f45787069726520747320746f6f206561726c7900000000000000000000000000604482015260640161072a565b611c2081106118855760405162461bcd60e51b815260206004820152601260248201527f45787069726520747320746f6f206c6174650000000000000000000000000000604482015260640161072a565b8464ffffffffff811615611921573360009081526099602052604090205464ffffffffff8281169116146119215760405162461bcd60e51b815260206004820152603860248201527f5369676e65722073686f756c6420626520616e20617574686f72697a6564206160448201527f646472657373206f662074686520676976656e20706f6f6c0000000000000000606482015260840161072a565b6001600160a01b03602887901c1661193c8b8b8b8b8561394e565b60008b815260ce6020526040812080547fffffffffffffff000000000000000000000000000000000000000000000000001678ffffffffffffffffffffffffffffffffffffffffffffffffff8a161790558b60ff81166000908152606560205260409020549091506119b9906001600160a01b0316838784612eff565b6040518c907f5ce4019f772fda6cb703b26bce3ec3006eb36b73f1d3a0eb441213317d9f5e9d90600090a2505050505050505050505050565b60008211611a425760405162461bcd60e51b815260206004820152601760248201527f416d6f756e74206d75737420626520706f736974697665000000000000000000604482015260640161072a565b338164ffffffffff8116600003611a9b5760405162461bcd60e51b815260206004820152601a60248201527f43616e6e6f7420757365203020617320706f6f6c20696e646578000000000000604482015260640161072a565b64ffffffffff81166000908152609a60205260409020546001600160a01b031615611b085760405162461bcd60e51b815260206004820152601d60248201527f506f6f6c20696e64657820616c72656164792072656769737465726564000000604482015260640161072a565b6001600160a01b03821660009081526099602052604090205464ffffffffff1615611b9b5760405162461bcd60e51b815260206004820152602160248201527f5369676e6572206164647265737320616c72656164792072656769737465726560448201527f6400000000000000000000000000000000000000000000000000000000000000606482015260840161072a565b64ffffffffff81166000818152609a6020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03881690811790915583526099825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000001690941790935565ffffffffffff86168252609b90529081208054869290611c3d908490614b07565b909155505060ff602884901c16600081815260656020526040902054611c6e906001600160a01b0316848784612eff565b6040516001600160a01b038416815264ffffffffff8316907fb8d9c35a714d4e29eaf036b9bf8183a093c5573ac809453b4e8434e25c9126d29060200160405180910390a28365ffffffffffff167f7d7d1df74ef3a6434d8d63dc0a25d13d5fa94dbe738c38a3cce26e6f892e2a7686604051611ced91815260200190565b60405180910390a25050505050565b611d04613c80565b610cd681613253565b846001611d1a8260f81c90565b60ff1614611d6a5760405162461bcd60e51b815260206004820152601a60248201527f496e636f727265637420656e636f64696e672076657273696f6e000000000000604482015260640161072a565b85603c611d778260201c90565b61ffff1614611dc85760405162461bcd60e51b815260206004820152601760248201527f53776170206e6f7420666f72207468697320636861696e000000000000000000604482015260640161072a565b6000611dd488856138ed565b6000818152610101602052604090205490915069ffffffffffffffffffff1615611e405760405162461bcd60e51b815260206004820152601360248201527f5377617020616c72656164792065786973747300000000000000000000000000604482015260640161072a565b611e4d888888888861394e565b3360009081526099602052604081205464ffffffffff1690819003611eda5760405162461bcd60e51b815260206004820152602f60248201527f43616c6c6572206e6f7420726567697374657265642e2043616c6c206465706f60448201527f736974416e6452656769737465722e0000000000000000000000000000000000606482015260840161072a565b6000611ee861096042614b07565b9050611f0161012c64ffffffffff60308d901c16614b1a565b8110611f755760405162461bcd60e51b815260206004820152602560248201527f43616e6e6f74206c6f636b20626563617573652065787069726554732069732060448201527f736f6f6e2e000000000000000000000000000000000000000000000000000000606482015260840161072a565b64ffffffffff82811660108c901b65ff0000000000161790611fa49060588d901c81169060d08e901c16614b1a565b65ffffffffffff82166000908152609b602052604081208054909190611fcb908490614b1a565b90915550506000848152610101602052604080822080547fffffffffffffffffffffffffffffffffffffffffffff000000000000000000001664ffffffffff8716602887901b69ffffffffff00000000001617179055518c917fbfb879c34323c5601fafe832c3a8a1e31e12c288695838726ddeada86034edb491a25050505050505050505050565b610134546001600160a01b031633146120af5760405162461bcd60e51b815260206004820152601760248201527f43616c6c6572206973206e6f7420746865206f776e6572000000000000000000604482015260640161072a565b80518251146121265760405162461bcd60e51b815260206004820152602e60248201527f546f6b656e7320616e6420696e64657865732073686f756c642068617665207460448201527f68652073616d65206c656e677468000000000000000000000000000000000000606482015260840161072a565b60005b82518160ff16101561102e57612177838260ff168151811061214d5761214d614b2d565b6020026020010151838360ff168151811061216a5761216a614b2d565b6020026020010151613d03565b8061218181614b5c565b915050612129565b600082116121d95760405162461bcd60e51b815260206004820152601760248201527f416d6f756e74206d75737420626520706f736974697665000000000000000000604482015260640161072a565b8064ffffffffff81166000036122315760405162461bcd60e51b815260206004820152601a60248201527f43616e6e6f7420757365203020617320706f6f6c20696e646578000000000000604482015260640161072a565b64ffffffffff81166000908152609a60205260409020546001600160a01b031633146122c55760405162461bcd60e51b815260206004820152602160248201527f4e6565642074686520706f6f6c206f776e657220617320746865207369676e6560448201527f7200000000000000000000000000000000000000000000000000000000000000606482015260840161072a565b65ffffffffffff82166000908152609b6020526040812080548592906122ec908490614b1a565b909155505060ff602883901c1660008181526065602052604090205461231d906001600160a01b031633868461370e565b8265ffffffffffff167f34c3d1c46f89307d63d8818fcc5c2a9c07a5f7a01ea4319bfba1899f40c6f40085604051610ea191815260200190565b79400000000000000000000000000000000000000000000000000086161580159061238457612384613c80565b600061239088856138ed565b6000818152610101602052604081205491925069ffffffffffffffffffff909116908190036124015760405162461bcd60e51b815260206004820152601360248201527f5377617020646f6573206e6f7420657869737400000000000000000000000000604482015260640161072a565b6001600160a01b0384166124575760405162461bcd60e51b815260206004820181905260248201527f526563697069656e742063616e6e6f74206265207a65726f2061646472657373604482015260640161072a565b4260308a901c64ffffffffff16116124b15760405162461bcd60e51b815260206004820152601e60248201527f43616e6e6f742072656c65617365206265636175736520657870697265640000604482015260640161072a565b6124bf89858a8a8a8a61333a565b60008281526101016020526040812080547fffffffffffffffffffffffffffffffffffffffffffff000000000000000000001690556124fe8a60181c90565b9050600061251e64ffffffffff60588d901c81169060d08e901c16614b1a565b9050846125965760006125308c613eff565b905061253c8183614b1a565b915080609b60006125628f600064ffffffffff1660109190911b65ff0000000000161790565b65ffffffffffff1665ffffffffffff168152602001908152602001600020600082825461258f9190614b07565b9091555050505b6125a38b83898985613f24565b6040518b907ffa628b578e095243f0544bfad9255f49d79d03a5bbf6c85875d05a215e247ad290600090a25050505050505050505050565b6060806000805b60ff8260ff1610156126405760006065816125fe856001614b7b565b60ff1681526020810191909152604001600020546001600160a01b03161461262e578061262a81614b5c565b9150505b8161263881614b5c565b9250506125e2565b8060ff1667ffffffffffffffff81111561265c5761265c614615565b604051908082528060200260200182016040528015612685578160200160208202803683370190505b5093508060ff1667ffffffffffffffff8111156126a4576126a4614615565b6040519080825280602002602001820160405280156126cd578160200160208202803683370190505b50925060008092505b60ff8360ff1610156127ca5760006065816126f2866001614b7b565b60ff1681526020810191909152604001600020546001600160a01b0316146127b85760656000612723856001614b7b565b60ff1660ff16815260200190815260200160002060009054906101000a90046001600160a01b0316858260ff168151811061276057612760614b2d565b6001600160a01b0390921660209283029190910190910152612783836001614b7b565b848260ff168151811061279857612798614b2d565b60ff90921660209283029190910190910152806127b481614b5c565b9150505b826127c281614b5c565b9350506126d6565b5050509091565b6001600160a01b0380831660009081526066602090815260408083205493851683526099909152812054909160ff169064ffffffffff16801580612816575060ff8216155b156128265760009250505061284e565b64ffffffffff1660289190911b65ff000000000016176000908152609b602052604090205490505b92915050565b610134546001600160a01b031633146128af5760405162461bcd60e51b815260206004820152601760248201527f43616c6c6572206973206e6f7420746865206f776e6572000000000000000000604482015260640161072a565b6113868282613d03565b60006128c583836138ed565b6000818152610101602052604081205491925069ffffffffffffffffffff909116908190036129365760405162461bcd60e51b815260206004820152601360248201527f5377617020646f6573206e6f7420657869737400000000000000000000000000604482015260640161072a565b42602882901c64ffffffffff16106129905760405162461bcd60e51b815260206004820152601260248201527f53776170207374696c6c20696e206c6f636b0000000000000000000000000000604482015260640161072a565b64ffffffffff818116601086901b65ff00000000001617906129bf90605887901c81169060d088901c16614b1a565b65ffffffffffff82166000908152609b6020526040812080549091906129e6908490614b07565b90915550506000838152610101602052604080822080547fffffffffffffffffffffffffffffffffffffffffffff000000000000000000001690555186917fac7d23c4f0137a4cc35b0e4b4bc8061ea6cb65805e87ceb0a77ca0c85814858c91a25050505050565b610134546001600160a01b03163314612aa95760405162461bcd60e51b815260206004820152601760248201527f43616c6c6572206973206e6f7420746865206f776e6572000000000000000000604482015260640161072a565b610cd681613192565b6001600160a01b03811660009081526099602052604090205464ffffffffff1615612b455760405162461bcd60e51b815260206004820152602360248201527f4164647220697320617574686f72697a656420666f7220616e6f74686572207060448201527f6f6f6c0000000000000000000000000000000000000000000000000000000000606482015260840161072a565b3360008181526099602052604081205464ffffffffff1690819003612bd25760405162461bcd60e51b815260206004820152602360248201527f546865207369676e657220646f6573206e6f742072656769737465722061207060448201527f6f6f6c0000000000000000000000000000000000000000000000000000000000606482015260840161072a565b64ffffffffff81166000908152609a60205260409020546001600160a01b03838116911614612c695760405162461bcd60e51b815260206004820152602160248201527f4e6565642074686520706f6f6c206f776e657220617320746865207369676e6560448201527f7200000000000000000000000000000000000000000000000000000000000000606482015260840161072a565b6001600160a01b03831660008181526099602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000001664ffffffffff8616908117909155915192835290917fd49cde4f679ccef3d23ff07aae4f6845e1c661e23e9fe6a54da26f0723fb695f91016108d5565b610134546001600160a01b03163314610cd65760405162461bcd60e51b815260206004820152601760248201527f43616c6c6572206973206e6f7420746865206f776e6572000000000000000000604482015260640161072a565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615612d745761102e83613fac565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612dec575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252612de991810190614b94565b60015b612e5e5760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201527f6f6e206973206e6f742055555053000000000000000000000000000000000000606482015260840161072a565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114612ef35760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f7860448201527f6961626c65555549440000000000000000000000000000000000000000000000606482015260840161072a565b5061102e838383614082565b6001600160a01b038416612f555760405162461bcd60e51b815260206004820152601360248201527f546f6b656e206e6f7420737570706f7274656400000000000000000000000000604482015260640161072a565b60008211612fa55760405162461bcd60e51b815260206004820181905260248201527f416d6f756e74206d7573742062652067726561746572207468616e207a65726f604482015260640161072a565b6001600160a01b0384163b6130225760405162461bcd60e51b815260206004820152602960248201527f54686520676976656e20746f6b656e2061646472657373206973206e6f74206160448201527f20636f6e74726163740000000000000000000000000000000000000000000000606482015260840161072a565b61302b816140ad565b156130425761303f64e8d4a5100083614bad565b91505b604080516001600160a01b038581166024830152306044830152606480830186905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd0000000000000000000000000000000000000000000000000000000017905291516000928392908816916130d29190614c0e565b6000604051808303816000865af19150503d806000811461310f576040519150601f19603f3d011682016040523d82523d6000602084013e613114565b606091505b509150915081801561313e57508051158061313e57508080602001905181019061313e9190614c2a565b61318a5760405162461bcd60e51b815260206004820152601360248201527f7472616e7366657246726f6d206661696c656400000000000000000000000000604482015260640161072a565b505050505050565b6001600160a01b0381166131e85760405162461bcd60e51b815260206004820181905260248201527f4e6577206f776e65722063616e6e6f74206265207a65726f2061646472657373604482015260640161072a565b61013480546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8934ce4adea8d9ce0d714d2c22b86790e41b7731c84b926fbbdc1d40ff6533c990600090a35050565b6001600160a01b0381166132cf5760405162461bcd60e51b815260206004820152602360248201527f4e6577207072656d69756d206d616e61676572206265207a65726f206164647260448201527f6573730000000000000000000000000000000000000000000000000000000000606482015260840161072a565b61013580546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f4798f31ad3d0ccde6359edf35fc39b882e4e1cff2968ca749b72074d373db27a90600090a35050565b6001600160a01b0381166133905760405162461bcd60e51b815260206004820152601e60248201527f5369676e65722063616e6e6f7420626520656d70747920616464726573730000604482015260640161072a565b8160ff16601b14806133a557508160ff16601c145b6133f15760405162461bcd60e51b815260206004820152601160248201527f496e76616c6964207369676e6174757265000000000000000000000000000000604482015260640161072a565b7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156134615760405162461bcd60e51b815260206004820152601160248201527f496e76616c6964207369676e6174757265000000000000000000000000000000604482015260640161072a565b790800000000000000000000000000000000000000000000000000861615156000600888901c61ffff1660c30361355f57816134bd577f1954524f4e205369676e6564204d6573736167653a0a33320a000000000000006134df565b7f1954524f4e205369676e6564204d6573736167653a0a35330a000000000000005b6040517fffffffffffffffffffffffffffffffffffffffffffffffffff000000000000009091166020820152603981018990527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606089901b166059820152606d015b604051602081830303815290604052805190602001209050613647565b81156135c9576040517f19457468657265756d205369676e6564204d6573736167653a0a3532000000006020820152603c81018990527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606089901b16605c820152607001613542565b60006135d58960201c90565b61ffff1660c314613606577f743e50106a7f059b52151dd4ba27a5f6c87b925ddfbdcf1c332e800da4b3df92613628565b7f28cf5b919ed55db2b14d9e8b261a523eafb98bab117d3a8a56e559791415d17c5b9050876014528860005260346000206020528060005260406000209150505b60408051600081526020810180835283905260ff861691810191909152606081018790526080810186905260019060a0016020604051602081039080840390855afa15801561369a573d6000803e3d6000fd5b505050602060405103516001600160a01b0316836001600160a01b0316146137045760405162461bcd60e51b815260206004820152601160248201527f496e76616c6964207369676e6174757265000000000000000000000000000000604482015260640161072a565b5050505050505050565b6001600160a01b0384163b61378b5760405162461bcd60e51b815260206004820152602960248201527f54686520676976656e20746f6b656e2061646472657373206973206e6f74206160448201527f20636f6e74726163740000000000000000000000000000000000000000000000606482015260840161072a565b613794816140ad565b156137ab576137a864e8d4a5100083614bad565b91505b604080516001600160a01b038581166024830152604480830186905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905291516000928392908816916138359190614c0e565b6000604051808303816000865af19150503d8060008114613872576040519150601f19603f3d011682016040523d82523d6000602084013e613877565b606091505b50915091508180156138a15750805115806138a15750808060200190518101906138a19190614c2a565b61318a5760405162461bcd60e51b815260206004820152600f60248201527f7472616e73666572206661696c65640000000000000000000000000000000000604482015260640161072a565b6000828260405160200161393092919091825260601b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602082015260340190565b60405160208183030381529060405280519060200120905092915050565b6001600160a01b0381166139a45760405162461bcd60e51b815260206004820152601e60248201527f5369676e65722063616e6e6f7420626520656d70747920616464726573730000604482015260640161072a565b8160ff16601b14806139b957508160ff16601c145b613a055760405162461bcd60e51b815260206004820152601160248201527f496e76616c6964207369676e6174757265000000000000000000000000000000604482015260640161072a565b7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115613a755760405162461bcd60e51b815260206004820152601160248201527f496e76616c6964207369676e6174757265000000000000000000000000000000604482015260640161072a565b790800000000000000000000000000000000000000000000000000851615156000600887901c61ffff1660c303613b475781613ad1577f1954524f4e205369676e6564204d6573736167653a0a33320a00000000000000613af3565b7f1954524f4e205369676e6564204d6573736167653a0a33330a000000000000005b6040517fffffffffffffffffffffffffffffffffffffffffffffffffff000000000000009091166020820152603981018890526059015b604051602081830303815290604052805190602001209050613bba565b8115613b85576040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101889052605c01613b2a565b506000868152602080822090527f9862d877599564bcd97c37305a7b0fdbe621d9c2a125026f2ad601f754a75abc8152604090205b60408051600081526020810180835283905260ff861691810191909152606081018790526080810186905260019060a0016020604051602081039080840390855afa158015613c0d573d6000803e3d6000fd5b505050602060405103516001600160a01b0316836001600160a01b031614613c775760405162461bcd60e51b815260206004820152601160248201527f496e76616c6964207369676e6174757265000000000000000000000000000000604482015260640161072a565b50505050505050565b610135546001600160a01b03163314613d015760405162461bcd60e51b815260206004820152602160248201527f43616c6c6572206973206e6f7420746865207072656d69756d206d616e61676560448201527f7200000000000000000000000000000000000000000000000000000000000000606482015260840161072a565b565b8060ff16600003613d565760405162461bcd60e51b815260206004820152601b60248201527f43616e6e6f7420757365203020617320746f6b656e20696e6465780000000000604482015260640161072a565b6001600160a01b038216613dac5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f7420757365207a65726f2061646472657373000000000000000000604482015260640161072a565b6001600160a01b03821660009081526066602052604090205460ff1615613e155760405162461bcd60e51b815260206004820152601b60248201527f546f6b656e20686173206265656e206164646564206265666f72650000000000604482015260640161072a565b60ff81166000908152606560205260409020546001600160a01b031615613e7e5760405162461bcd60e51b815260206004820152601360248201527f496e64657820686173206265656e207573656400000000000000000000000000604482015260640161072a565b6001600160a01b039091166000818152606660209081526040808320805460ff9096167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090961686179055938252606590529190912080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169091179055565b6000612710613f1a600a64ffffffffff60d086901c16614bad565b61284e9190614c47565b7980000000000000000000000000000000000000000000000000008516613f7d5760ff8416600090815260656020526040902054613f78906001600160a01b031683858488613f738b60801c90565b6140c7565b613fa5565b60ff8416600090815260656020526040902054613fa5906001600160a01b031683838761370e565b5050505050565b6001600160a01b0381163b6140295760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e747261637400000000000000000000000000000000000000606482015260840161072a565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b61408b83614312565b6000825111806140985750805b1561102e576140a78383614352565b50505050565b600060208260ff1611801561284e57505060ff9081161090565b6001600160a01b0386163b6141445760405162461bcd60e51b815260206004820152602960248201527f54686520676976656e20746f6b656e2061646472657373206973206e6f74206160448201527f20636f6e74726163740000000000000000000000000000000000000000000000606482015260840161072a565b6001600160a01b0385163b6141c15760405162461bcd60e51b815260206004820152602d60248201527f54686520676976656e20726563697069656e742061646472657373206973206e60448201527f6f74206120636f6e747261637400000000000000000000000000000000000000606482015260840161072a565b6141ca826140ad565b156141e1576141de64e8d4a5100084614bad565b92505b6040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b0386811660048301526024820185905287169063095ea7b3906044016020604051808303816000875af1158015614249573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061426d9190614c2a565b506040517f3ea1ef2d0000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260248201859052858116604483015267ffffffffffffffff83166064830152861690633ea1ef2d906084016020604051808303816000875af11580156142ee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c779190614c2a565b61431b81613fac565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606001600160a01b0383163b6143d15760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e74726163740000000000000000000000000000000000000000000000000000606482015260840161072a565b600080846001600160a01b0316846040516143ec9190614c0e565b600060405180830381855af49150503d8060008114614427576040519150601f19603f3d011682016040523d82523d6000602084013e61442c565b606091505b50915091506144548282604051806060016040528060278152602001614cd46027913961445d565b95945050505050565b6060831561446c575081614496565b82511561447c5782518084602001fd5b8160405162461bcd60e51b815260040161072a9190614c82565b9392505050565b80356001600160a01b03811681146144b457600080fd5b919050565b6000602082840312156144cb57600080fd5b6144968261449d565b6000602082840312156144e657600080fd5b5035919050565b803564ffffffffff811681146144b457600080fd5b6000806040838503121561451557600080fd5b82359150614525602084016144ed565b90509250929050565b6000806040838503121561454157600080fd5b82359150602083013565ffffffffffff8116811461455e57600080fd5b809150509250929050565b6000806040838503121561457c57600080fd5b6145858361449d565b91506145256020840161449d565b803560ff811681146144b457600080fd5b8015158114610cd657600080fd5b60008060008060008060c087890312156145cb57600080fd5b8635955060208701359450604087013593506145e960608801614593565b92506145f76080880161449d565b915060a0870135614607816145a4565b809150509295509295509295565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561468b5761468b614615565b604052919050565b600080604083850312156146a657600080fd5b6146af8361449d565b915060208084013567ffffffffffffffff808211156146cd57600080fd5b818601915086601f8301126146e157600080fd5b8135818111156146f3576146f3614615565b614723847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614644565b9150808252878482850101111561473957600080fd5b80848401858401376000848284010152508093505050509250929050565b6000806040838503121561476a57600080fd5b823591506145256020840161449d565b600080600080600060a0868803121561479257600080fd5b8535945060208601359350604086013592506147b060608701614593565b9150608086013578ffffffffffffffffffffffffffffffffffffffffffffffffff811681146147de57600080fd5b809150509295509295909350565b6000602082840312156147fe57600080fd5b614496826144ed565b60006020828403121561481957600080fd5b61449682614593565b600080600080600060a0868803121561483a57600080fd5b85359450602086013593506040860135925061485860608701614593565b91506148666080870161449d565b90509295509295909350565b600067ffffffffffffffff82111561488c5761488c614615565b5060051b60200190565b600082601f8301126148a757600080fd5b813560206148bc6148b783614872565b614644565b82815260059290921b840181019181810190868411156148db57600080fd5b8286015b848110156148fd576148f081614593565b83529183019183016148df565b509695505050505050565b6000806040838503121561491b57600080fd5b823567ffffffffffffffff8082111561493357600080fd5b818501915085601f83011261494757600080fd5b813560206149576148b783614872565b82815260059290921b8401810191818101908984111561497657600080fd5b948201945b8386101561499b5761498c8661449d565b8252948201949082019061497b565b965050860135925050808211156149b157600080fd5b506149be85828601614896565b9150509250929050565b60008060008060008060c087890312156149e157600080fd5b8635955060208701359450604087013593506149ff60608801614593565b9250614a0d6080880161449d565b9150614a1b60a0880161449d565b90509295509295509295565b604080825283519082018190526000906020906060840190828701845b82811015614a695781516001600160a01b031684529284019290840190600101614a44565b5050508381038285015284518082528583019183019060005b81811015614aa157835160ff1683529284019291840191600101614a82565b5090979650505050505050565b60008060408385031215614ac157600080fd5b614aca8361449d565b915061452560208401614593565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561284e5761284e614ad8565b8181038181111561284e5761284e614ad8565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff821660ff8103614b7257614b72614ad8565b60010192915050565b60ff818116838216019081111561284e5761284e614ad8565b600060208284031215614ba657600080fd5b5051919050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615614be557614be5614ad8565b500290565b60005b83811015614c05578181015183820152602001614bed565b50506000910152565b60008251614c20818460208701614bea565b9190910192915050565b600060208284031215614c3c57600080fd5b8151614496816145a4565b600082614c7d577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6020815260008251806020840152614ca1816040850160208701614bea565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c6343000810000a416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564000000000000000000000000666d6b8a44d226150ca9058beebafe0e3ac065a2Deployed Bytecode
0x60806040523661001357610011610017565b005b6100115b610027610022610074565b6100b9565b565b606061004e83836040518060600160405280602781526020016102ef602791396100dd565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156100d8573d6000f35b3d6000fd5b606073ffffffffffffffffffffffffffffffffffffffff84163b610188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516101b09190610281565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b509150915061020082828661020a565b9695505050505050565b6060831561021957508161004e565b8251156102295782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017f919061029d565b60005b83811015610278578181015183820152602001610260565b50506000910152565b6000825161029381846020870161025d565b9190910192915050565b60208152600082518060208401526102bc81604085016020870161025d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c6343000810000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000666d6b8a44d226150ca9058beebafe0e3ac065a2
-----Decoded View---------------
Arg [0] : premiumManager (address): 0x666d6b8a44d226150ca9058bEEbafe0e3aC065A2
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000666d6b8a44d226150ca9058beebafe0e3ac065a2Deployed Bytecode Sourcemap
107645:570:0:-:0;;;;;;2986:11;:9;:11::i;:::-;107645:570;;2763:11;2410:110;2485:28;2495:17;:15;:17::i;:::-;2485:9;:28::i;:::-;2410:110::o;11340:198::-;11423:12;11454:77;11475:6;11483:4;11454:77;;;;;;;;;;;;;;;;;:20;:77::i;:::-;11447:84;11340:198;-1:-1:-1;;;11340:198:0:o;5945:320::-;6235:19;;;:23;;;5945:320::o;14723:190::-;14893:4;14723:190::o;23326:140::-;23393:12;23424:35;16706:66;17056:54;;;;16977:140;23424:35;23417:42;;23326:140;:::o;1036:895::-;1374:14;1371:1;1368;1355:34;1588:1;1585;1569:14;1566:1;1550:14;1543:5;1530:60;1664:16;1661:1;1658;1643:38;1702:6;1769:66;;;;1884:16;1881:1;1874:27;1769:66;1804:16;1801:1;1794:27;11724:387;11865:12;6235:19;;;;11889:69;;;;;;;216:2:1;11889:69:0;;;198:21:1;255:2;235:18;;;228:30;294:34;274:18;;;267:62;365:8;345:18;;;338:36;391:19;;11889:69:0;;;;;;;;;11970:12;11984:23;12011:6;:19;;12031:4;12011:25;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11969:67;;;;12053:51;12070:7;12079:10;12091:12;12053:16;:51::i;:::-;12046:58;11724:387;-1:-1:-1;;;;;;11724:387:0:o;12331:742::-;12477:12;12505:7;12501:566;;;-1:-1:-1;12535:10:0;12528:17;;12501:566;12646:17;;:21;12642:415;;12890:10;12884:17;12950:15;12937:10;12933:2;12929:19;12922:44;12642:415;13029:12;13022:20;;;;;;;;;;;:::i;421:250:1:-;506:1;516:113;530:6;527:1;524:13;516:113;;;606:11;;;600:18;587:11;;;580:39;552:2;545:10;516:113;;;-1:-1:-1;;663:1:1;645:16;;638:27;421:250::o;676:287::-;805:3;843:6;837:13;859:66;918:6;913:3;906:4;898:6;894:17;859:66;:::i;:::-;941:16;;;;;676:287;-1:-1:-1;;676:287:1:o;968:455::-;1117:2;1106:9;1099:21;1080:4;1149:6;1143:13;1192:6;1187:2;1176:9;1172:18;1165:34;1208:79;1280:6;1275:2;1264:9;1260:18;1255:2;1247:6;1243:15;1208:79;:::i;:::-;1339:2;1327:15;1344:66;1323:88;1308:104;;;;1414:2;1304:113;;968:455;-1:-1:-1;;968:455:1:o
Swarm Source
none
Loading...LoadingLoading...Loading
Loading...Loading
Loading...LoadingLoading...LoadingLoading...LoadingLoading...LoadingLoading...LoadingLoading...LoadingMultichain Portfolio | 30 Chains
Chain Token Portfolio % Price Amount Value ARB 12.36% $97,846 3.1382 $307,064.72 ARB 5.27% $97,907 1.3361 $130,813.54 ARB 4.10% $3,430.6 29.6612 $101,755.79 ARB 2.65% $1 65,670.2745 $65,735.94 ARB 0.89% $97,588 0.2276 $22,207.61 ARB 0.88% $1 21,872.4345 $21,938.05 ARB <0.01% $0.858003 85.1747 $73.08 ARB <0.01% $1.07 52 $55.42 ETH 7.43% $97,825 1.8857 $184,472.71 ETH 4.69% $3,507.67 33.2263 $116,546.76 ETH 3.95% $97,779 1.0022 $97,995.09 ETH Ether (ETH)3.26% $3,431.51 23.5875 $80,940.55 ETH 2.68% $97,533 0.6825 $66,566.17 ETH 1.63% $1 40,325.0773 $40,365.4 ETH 1.35% $1 33,570.1281 $33,637.27 ETH <0.01% $97,301.78 0.001797 $174.85 BSC 5.91% $97,879 1.5 $146,820.75 BSC 5.48% $1.07 127,775.2775 $136,182.1 BSC 2.14% $0.999889 53,090.329 $53,084.45 BSC 2.07% $1 51,359.4445 $51,513.52 BSC 1.18% $0.998762 29,335.9281 $29,299.62 BSC 0.64% $97,913.43 0.1625 $15,906.72 BSC 0.59% $97,577 0.1503 $14,667.48 BSC 0.53% $1.86 7,095.4187 $13,226.25 BSC 0.27% $658.95 10.3087 $6,792.9 BSC <0.01% $1 67.8102 $67.93 BSC <0.01% $0.000002 55,555 $0.1116 BSC <0.01% $0.001099 100 $0.1099 OP 3.18% $3,431.39 23.0156 $78,975.66 OP 1.50% $1 37,027.5496 $37,138.63 OP 1.43% $1 35,501.4523 $35,501.45 OP 0.04% $1 901.2914 $901.29 POL 2.32% $1 57,339.2905 $57,511.31 POL 1.71% $1 42,496.7855 $42,539.28 POL 0.42% $97,865 0.1075 $10,519.8 POL 0.39% $0.574606 16,994.4704 $9,765.12 POL 0.04% $1 937.4646 $938.4 SCROLL 1.35% $3,431.51 9.7398 $33,422.23 SCROLL 0.92% $1 22,765.99 $22,788.76 SCROLL 0.85% $1 21,187.5531 $21,222.8 AVAX 1.51% $0.999889 37,514.0924 $37,509.94 AVAX 1.48% $1 36,614.6518 $36,681.76 LINEA 1.03% $3,431.51 7.4569 $25,588.42 LINEA 0.76% $1 18,851.2656 $18,870.12 LINEA 0.73% $1 18,065.1272 $18,101.26 BASE 1.25% $3,434.25 9.0595 $31,112.55 BASE 1.11% $1 27,587.8349 $27,615.42 BASE <0.01% $0.001068 500 $0.5341 MANTLE 1.05% $1 26,081.8128 $26,186.14 MANTLE 0.65% $1.01 16,031.2074 $16,111.36 MANTLE <0.01% $0.884259 0.00001301 $0.000012 CRONOS 0.66% $1 16,245.4098 $16,294.15 CRONOS 0.54% $1 13,341.5989 $13,354.94 OPBNB 0.85% $1 20,967.9852 $21,009.92 OPBNB 0.29% $658.33 11.1213 $7,321.5 FTM 0.89% $1 22,195.2193 $22,217.41 BLAST 0.46% $3,431.68 3.3285 $11,422.51 BLAST 0.34% $1.01 8,457.4121 $8,550.44 ZKEVM 0.02% $0.999889 580.6492 $580.58 ZKEVM 0.26% $1 6,447.9634 $6,467.31 ZKEVM 0.15% $0.999889 3,776.9231 $3,776.5 TAIKO 0.23% $1.01 5,679.5833 $5,725.02 TAIKO 0.16% $3,431.51 1.16 $3,980.56 GNO 0.38% $0.99997 9,368.1684 $9,367.88 GLMR 0.37% $1 9,049.1513 $9,067.25 KROMA 0.33% $3,432.6 2.4189 $8,303.23 CELO 0.23% $1 5,713.8122 $5,719.53 ZKSYNC 0.14% $3,431.51 1.0108 $3,468.53 MOVR <0.01% $1 187.5409 $187.54 ARBNOVA <0.01% $3,432.28 0.000103 $0.353525 APE <0.01% $1.29 0.2216 $0.285297 Loading...Loading[ Download: CSV Export ]A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.
Address QR Code
My Address - Private Name Tag or Note
My Name Tag:
Private Name Tags (up to 35 characters) can be used for easy identification of addressesPrivate Note:
A private note (up to 500 characters) can be attached to this address.
Please DO NOT store any passwords or private keys here.Compiler specific version warnings:
The compiled contract might be susceptible to VerbatimInvalidDeduplication (low-severity), FullInlinerNonExpressionSplitArgumentEvaluationOrder (low-severity), MissingSideEffectsOnSelectorAccess (low-severity), StorageWriteRemovalBeforeConditionalTermination (medium/high-severity) Solidity Compiler Bugs.
Connect a Wallet
Connecting wallet for read function is optional, useful if you want to call certain functions or simply use your wallet's node.Connect a Wallet
Connecting wallet for read function is optional, useful if you want to call certain functions or simply use your wallet's node.Connect a Wallet
Connecting wallet for read function is optional, useful if you want to call certain functions or simply use your wallet's node.SignIn
Address Cards
To use this feature, please login to your Etherscan account and return to this page.Before You Copy
Transaction Private Note
This website uses cookies to improve your experience. By continuing to use this website, you agree to its Terms and Privacy Policy.