Overview
ETH Balance
ETH Value
$0.00Multichain Info
Latest 25 from a total of 454 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Deposit And Brid... | 12625445 | 2 days ago | IN | 0.00001531 ETH | 0.00000135 | ||||
Deposit | 12625342 | 2 days ago | IN | 0 ETH | 0.00000135 | ||||
Bridge | 12181471 | 7 days ago | IN | 0.00001586 ETH | 0.0000017 | ||||
Bridge | 12136096 | 8 days ago | IN | 0.00001718 ETH | 0.00000138 | ||||
Deposit And Brid... | 12122255 | 8 days ago | IN | 0.0000166 ETH | 0.00000135 | ||||
Deposit And Brid... | 11782899 | 12 days ago | IN | 0.00003988 ETH | 0.00000155 | ||||
Deposit And Brid... | 11782855 | 12 days ago | IN | 0.00003988 ETH | 0.00000135 | ||||
Deposit And Brid... | 11782796 | 12 days ago | IN | 0.00003988 ETH | 0.00000155 | ||||
Deposit And Brid... | 11782716 | 12 days ago | IN | 0.00003988 ETH | 0.00000136 | ||||
Deposit And Brid... | 11782669 | 12 days ago | IN | 0.00003988 ETH | 0.00000136 | ||||
Deposit And Brid... | 11782603 | 12 days ago | IN | 0.00003988 ETH | 0.00000153 | ||||
Deposit And Brid... | 11782523 | 12 days ago | IN | 0.00003988 ETH | 0.00000155 | ||||
Deposit And Brid... | 11782463 | 12 days ago | IN | 0.00003988 ETH | 0.00000148 | ||||
Deposit And Brid... | 11782410 | 12 days ago | IN | 0.00003988 ETH | 0.00000163 | ||||
Deposit And Brid... | 11782317 | 12 days ago | IN | 0.0000369 ETH | 0.00000135 | ||||
Deposit And Brid... | 11782117 | 12 days ago | IN | 0.0000369 ETH | 0.00000175 | ||||
Deposit And Brid... | 11782076 | 12 days ago | IN | 0.0000369 ETH | 0.00000175 | ||||
Deposit And Brid... | 11782034 | 12 days ago | IN | 0.0000369 ETH | 0.00000174 | ||||
Deposit And Brid... | 11781985 | 12 days ago | IN | 0.00003353 ETH | 0.00000175 | ||||
Deposit And Brid... | 11781940 | 12 days ago | IN | 0.00003353 ETH | 0.00000174 | ||||
Deposit And Brid... | 11781891 | 12 days ago | IN | 0.00003353 ETH | 0.00000175 | ||||
Deposit And Brid... | 11781733 | 12 days ago | IN | 0.00003353 ETH | 0.00000135 | ||||
Deposit | 11781656 | 12 days ago | IN | 0 ETH | 0.00000135 | ||||
Deposit And Brid... | 11781468 | 12 days ago | IN | 0.00002929 ETH | 0.00000135 | ||||
Deposit And Brid... | 11781313 | 12 days ago | IN | 0.00003132 ETH | 0.00000136 |
Latest 25 internal transactions (View All)
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
12625445 | 2 days ago | 0.00001531 ETH | ||||
12181471 | 7 days ago | 0.00001586 ETH | ||||
12122255 | 8 days ago | 0.0000166 ETH | ||||
11782899 | 12 days ago | 0.00003988 ETH | ||||
11782855 | 12 days ago | 0.00003988 ETH | ||||
11782796 | 12 days ago | 0.00003988 ETH | ||||
11782716 | 12 days ago | 0.00003988 ETH | ||||
11782669 | 12 days ago | 0.00003988 ETH | ||||
11782603 | 12 days ago | 0.00003988 ETH | ||||
11782523 | 12 days ago | 0.00003988 ETH | ||||
11782463 | 12 days ago | 0.00003988 ETH | ||||
11782410 | 12 days ago | 0.00003988 ETH | ||||
11782317 | 12 days ago | 0.0000369 ETH | ||||
11782117 | 12 days ago | 0.0000369 ETH | ||||
11782076 | 12 days ago | 0.0000369 ETH | ||||
11782034 | 12 days ago | 0.0000369 ETH | ||||
11781985 | 12 days ago | 0.00003353 ETH | ||||
11781940 | 12 days ago | 0.00003353 ETH | ||||
11781891 | 12 days ago | 0.00003353 ETH | ||||
11781733 | 12 days ago | 0.00003353 ETH | ||||
11781468 | 12 days ago | 0.00002929 ETH | ||||
11781313 | 12 days ago | 0.00003132 ETH | ||||
11781216 | 12 days ago | 0.00003132 ETH | ||||
11781146 | 12 days ago | 0.00003132 ETH | ||||
11781039 | 12 days ago | 0.00003496 ETH |
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.21; import { CrossChainTellerWithGenericBridge, ERC20 } from "../../../../../../src/base/Roles/CrossChain/CrossChainTellerWithGenericBridge.sol"; import {SafeTransferLib} from "@solmate/utils/SafeTransferLib.sol"; import {OAppAuth, Origin, MessagingFee, MessagingReceipt} from "@oapp-auth/OAppAuth.sol"; import {AddressToBytes32Lib} from "../../../../../../src/helper/AddressToBytes32Lib.sol"; import {OptionsBuilder} from "@oapp-auth/OptionsBuilder.sol"; contract LayerZeroTeller is CrossChainTellerWithGenericBridge, OAppAuth { using SafeTransferLib for ERC20; using AddressToBytes32Lib for address; using AddressToBytes32Lib for bytes32; using OptionsBuilder for bytes; // ========================================= STRUCTS ========================================= /** * @notice Stores information about a chain. * @dev Sender is stored in OAppAuthCore `peers` mapping. * @param allowMessagesFrom Whether to allow messages from this chain. * @param allowMessagesTo Whether to allow messages to this chain. * @param messageGasLimit The gas limit for messages to this chain. */ struct Chain { bool allowMessagesFrom; bool allowMessagesTo; uint128 messageGasLimit; } // ========================================= STATE ========================================= /** * @notice Maps chain selector to chain information. */ mapping(uint32 => Chain) public idToChains; //============================== ERRORS =============================== error LayerZeroTeller__MessagesNotAllowedFrom(uint256 chainSelector); error LayerZeroTeller__MessagesNotAllowedFromSender(uint256 chainSelector, address sender); error LayerZeroTeller__MessagesNotAllowedTo(uint256 chainSelector); error LayerZeroTeller__FeeExceedsMax(uint256 chainSelector, uint256 fee, uint256 maxFee); error LayerZeroTeller__BadFeeToken(); error LayerZeroTeller__ZeroMessageGasLimit(); //============================== EVENTS =============================== event ChainAdded(uint256 chainId, bool allowMessagesFrom, bool allowMessagesTo, address targetTeller); event ChainRemoved(uint256 chainId); event ChainAllowMessagesFrom(uint256 chainId, address targetTeller); event ChainAllowMessagesTo(uint256 chainId, address targetTeller); event ChainStopMessagesFrom(uint256 chainId); event ChainStopMessagesTo(uint256 chainId); event ChainSetGasLimit(uint256 chainId, uint128 messageGasLimit); //============================== IMMUTABLES =============================== /** * @notice The LayerZero token. */ address internal immutable lzToken; constructor( address _owner, address _vault, address _accountant, address _weth, address _lzEndPoint, address _delegate, address _lzToken ) CrossChainTellerWithGenericBridge(_owner, _vault, _accountant, _weth) OAppAuth(_lzEndPoint, _delegate) { lzToken = _lzToken; } // ========================================= ADMIN FUNCTIONS ========================================= /** * @notice Add a chain to the teller. * @dev Callable by OWNER_ROLE. * @param chainId The LayerZero chain id to add. * @param allowMessagesFrom Whether to allow messages from this chain. * @param allowMessagesTo Whether to allow messages to this chain. * @param targetTeller The address of the target teller on the other chain. * @param messageGasLimit The gas limit for messages to this chain. */ function addChain( uint32 chainId, bool allowMessagesFrom, bool allowMessagesTo, address targetTeller, uint128 messageGasLimit ) external requiresAuth { if (allowMessagesTo && messageGasLimit == 0) { revert LayerZeroTeller__ZeroMessageGasLimit(); } idToChains[chainId] = Chain(allowMessagesFrom, allowMessagesTo, messageGasLimit); _setPeer(chainId, targetTeller.toBytes32()); emit ChainAdded(chainId, allowMessagesFrom, allowMessagesTo, targetTeller); } /** * @notice Remove a chain from the teller. * @dev Callable by MULTISIG_ROLE. */ function removeChain(uint32 chainId) external requiresAuth { delete idToChains[chainId]; _setPeer(chainId, bytes32(0)); emit ChainRemoved(chainId); } /** * @notice Allow messages from a chain. * @dev Callable by OWNER_ROLE. */ function allowMessagesFromChain(uint32 chainId, address targetTeller) external requiresAuth { Chain storage chain = idToChains[chainId]; chain.allowMessagesFrom = true; _setPeer(chainId, targetTeller.toBytes32()); emit ChainAllowMessagesFrom(chainId, targetTeller); } /** * @notice Allow messages to a chain. * @dev Callable by OWNER_ROLE. */ function allowMessagesToChain(uint32 chainId, address targetTeller, uint128 messageGasLimit) external requiresAuth { if (messageGasLimit == 0) { revert LayerZeroTeller__ZeroMessageGasLimit(); } Chain storage chain = idToChains[chainId]; chain.allowMessagesTo = true; chain.messageGasLimit = messageGasLimit; _setPeer(chainId, targetTeller.toBytes32()); emit ChainAllowMessagesTo(chainId, targetTeller); } /** * @notice Stop messages from a chain. * @dev Callable by MULTISIG_ROLE. */ function stopMessagesFromChain(uint32 chainId) external requiresAuth { Chain storage chain = idToChains[chainId]; chain.allowMessagesFrom = false; emit ChainStopMessagesFrom(chainId); } /** * @notice Stop messages to a chain. * @dev Callable by MULTISIG_ROLE. */ function stopMessagesToChain(uint32 chainId) external requiresAuth { Chain storage chain = idToChains[chainId]; chain.allowMessagesTo = false; emit ChainStopMessagesTo(chainId); } /** * @notice Set the gas limit for messages to a chain. * @dev Callable by OWNER_ROLE. */ function setChainGasLimit(uint32 chainId, uint128 messageGasLimit) external requiresAuth { if (messageGasLimit == 0) { revert LayerZeroTeller__ZeroMessageGasLimit(); } Chain storage chain = idToChains[chainId]; chain.messageGasLimit = messageGasLimit; emit ChainSetGasLimit(chainId, messageGasLimit); } // ========================================= OAppAuthReceiver ========================================= /** * @notice Receive messages from the LayerZero endpoint. * @dev `lzReceive` only sanitizes the message sender, but we also need to make sure we are allowing messages * from the source chain. */ function _lzReceive( Origin calldata _origin, bytes32 _guid, bytes calldata _message, address, /*_executor*/ bytes calldata /*_extraData*/ ) internal override { Chain memory source = idToChains[_origin.srcEid]; if (!source.allowMessagesFrom) revert LayerZeroTeller__MessagesNotAllowedFrom(_origin.srcEid); uint256 message = abi.decode(_message, (uint256)); _completeMessageReceive(_guid, message); } // ========================================= INTERNAL BRIDGE FUNCTIONS ========================================= /** * @notice Sends messages using Layer Zero end point. * @dev This function does NOT revert if the `feeToken` is invalid, * rather the Layer Zero end point will revert. * @dev This function will revert if maxFee is exceeded. * @dev This function will revert if destination chain does not allow messages. * @param message The message to send. * @param bridgeWildCard An abi encoded uint32 containing the destination chain id. * @param feeToken The token to pay the bridge fee in. * @param maxFee The maximum fee to pay the bridge. */ function _sendMessage(uint256 message, bytes calldata bridgeWildCard, ERC20 feeToken, uint256 maxFee) internal override returns (bytes32 messageId) { uint32 destinationId = abi.decode(bridgeWildCard, (uint32)); Chain memory chain = idToChains[destinationId]; if (!chain.allowMessagesTo) { revert LayerZeroTeller__MessagesNotAllowedTo(destinationId); } bytes memory m = abi.encode(message); bytes memory options = OptionsBuilder.newOptions().addExecutorLzReceiveOption(chain.messageGasLimit, 0); MessagingFee memory fee = _quote(destinationId, m, options, address(feeToken) != NATIVE); if (address(feeToken) == NATIVE) { if (fee.nativeFee > maxFee) { revert LayerZeroTeller__FeeExceedsMax(destinationId, fee.nativeFee, maxFee); } } else if (address(feeToken) == lzToken) { if (fee.lzTokenFee > maxFee) { revert LayerZeroTeller__FeeExceedsMax(destinationId, fee.lzTokenFee, maxFee); } } else { revert LayerZeroTeller__BadFeeToken(); } MessagingReceipt memory receipt = _lzSend(destinationId, m, options, fee, msg.sender); messageId = receipt.guid; } /** * @notice Preview fee required to bridge shares in a given feeToken. * @param message The message to send. * @param bridgeWildCard An abi encoded uint32 containing the destination chain id. * @param feeToken The token to pay the bridge fee in. */ function _previewFee(uint256 message, bytes calldata bridgeWildCard, ERC20 feeToken) internal view override returns (uint256 fee) { // Make sure feeToken is either NATIVE or lzToken. if (address(feeToken) != NATIVE && address(feeToken) != lzToken) { revert LayerZeroTeller__BadFeeToken(); } uint32 destinationId = abi.decode(bridgeWildCard, (uint32)); Chain memory chain = idToChains[destinationId]; if (!chain.allowMessagesTo) { revert LayerZeroTeller__MessagesNotAllowedTo(destinationId); } bytes memory m = abi.encode(message); bytes memory options = OptionsBuilder.newOptions().addExecutorLzReceiveOption(chain.messageGasLimit, 0); MessagingFee memory messageFee = _quote(destinationId, m, options, address(feeToken) != NATIVE); fee = address(feeToken) == NATIVE ? messageFee.nativeFee : messageFee.lzTokenFee; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import {IOAppReceiver, Origin} from "@lz-oapp-evm/interfaces/IOAppReceiver.sol"; import {OAppAuthCore} from "./OAppAuthCore.sol"; /** * @title OAppReceiver * @dev Abstract contract implementing the ILayerZeroReceiver interface and extending OAppCore for OApp receivers. */ abstract contract OAppAuthReceiver is IOAppReceiver, OAppAuthCore { // Custom error message for when the caller is not the registered endpoint/ error OnlyEndpoint(address addr); // @dev The version of the OAppReceiver implementation. // @dev Version is bumped when changes are made to this contract. uint64 internal constant RECEIVER_VERSION = 1; /** * @notice Retrieves the OApp version information. * @return senderVersion The version of the OAppSender.sol contract. * @return receiverVersion The version of the OAppReceiver.sol contract. * * @dev Providing 0 as the default for OAppSender version. Indicates that the OAppSender is not implemented. * ie. this is a RECEIVE only OApp. * @dev If the OApp uses both OAppSender and OAppReceiver, then this needs to be override returning the correct versions. */ function oAppVersion() public view virtual returns (uint64 senderVersion, uint64 receiverVersion) { return (0, RECEIVER_VERSION); } /** * @notice Retrieves the address responsible for 'sending' composeMsg's to the Endpoint. * @return sender The address responsible for 'sending' composeMsg's to the Endpoint. * * @dev Applications can optionally choose to implement a separate composeMsg sender that is NOT the bridging layer. * @dev The default sender IS the OApp implementer. */ function composeMsgSender() public view virtual returns (address sender) { return address(this); } /** * @notice Checks if the path initialization is allowed based on the provided origin. * @param origin The origin information containing the source endpoint and sender address. * @return Whether the path has been initialized. * * @dev This indicates to the endpoint that the OApp has enabled msgs for this particular path to be received. * @dev This defaults to assuming if a peer has been set, its initialized. * Can be overridden by the OApp if there is other logic to determine this. */ function allowInitializePath(Origin calldata origin) public view virtual returns (bool) { return peers[origin.srcEid] == origin.sender; } /** * @notice Retrieves the next nonce for a given source endpoint and sender address. * @dev _srcEid The source endpoint ID. * @dev _sender The sender address. * @return nonce The next nonce. * * @dev The path nonce starts from 1. If 0 is returned it means that there is NO nonce ordered enforcement. * @dev Is required by the off-chain executor to determine the OApp expects msg execution is ordered. * @dev This is also enforced by the OApp. * @dev By default this is NOT enabled. ie. nextNonce is hardcoded to return 0. */ function nextNonce(uint32, /*_srcEid*/ bytes32 /*_sender*/ ) public view virtual returns (uint64 nonce) { return 0; } /** * @dev Entry point for receiving messages or packets from the endpoint. * @param _origin The origin information containing the source endpoint and sender address. * - srcEid: The source chain endpoint ID. * - sender: The sender address on the src chain. * - nonce: The nonce of the message. * @param _guid The unique identifier for the received LayerZero message. * @param _message The payload of the received message. * @param _executor The address of the executor for the received message. * @param _extraData Additional arbitrary data provided by the corresponding executor. * * @dev Entry point for receiving msg/packet from the LayerZero endpoint. */ function lzReceive( Origin calldata _origin, bytes32 _guid, bytes calldata _message, address _executor, bytes calldata _extraData ) public payable virtual { // Ensures that only the endpoint can attempt to lzReceive() messages to this OApp. if (address(endpoint) != msg.sender) revert OnlyEndpoint(msg.sender); // Ensure that the sender matches the expected peer for the source endpoint. if (_getPeerOrRevert(_origin.srcEid) != _origin.sender) revert OnlyPeer(_origin.srcEid, _origin.sender); // Call the internal OApp implementation of lzReceive. _lzReceive(_origin, _guid, _message, _executor, _extraData); } /** * @dev Internal function to implement lzReceive logic without needing to copy the basic parameter validation. */ function _lzReceive( Origin calldata _origin, bytes32 _guid, bytes calldata _message, address _executor, bytes calldata _extraData ) internal virtual; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/utils/ERC1155Holder.sol) pragma solidity ^0.8.20; import {IERC165, ERC165} from "../../../utils/introspection/ERC165.sol"; import {IERC1155Receiver} from "../IERC1155Receiver.sol"; /** * @dev Simple implementation of `IERC1155Receiver` that will allow a contract to hold ERC-1155 tokens. * * IMPORTANT: When inheriting this contract, you must include a way to use the received tokens, otherwise they will be * stuck. */ abstract contract ERC1155Holder is ERC165, IERC1155Receiver { /// @inheritdoc IERC165 function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId); } function onERC1155Received( address, address, uint256, uint256, bytes memory ) public virtual override returns (bytes4) { return this.onERC1155Received.selector; } function onERC1155BatchReceived( address, address, uint256[] memory, uint256[] memory, bytes memory ) public virtual override returns (bytes4) { return this.onERC1155BatchReceived.selector; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.2.0) (utils/Address.sol) pragma solidity ^0.8.20; import {Errors} from "./Errors.sol"; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert Errors.InsufficientBalance(address(this).balance, amount); } (bool success, bytes memory returndata) = recipient.call{value: amount}(""); if (!success) { _revert(returndata); } } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {Errors.FailedCall} error. * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert Errors.InsufficientBalance(address(this).balance, value); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case * of an unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {Errors.FailedCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}. */ function _revert(bytes memory returndata) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly ("memory-safe") { revert(add(returndata, 0x20), mload(returndata)) } } else { revert Errors.FailedCall(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol) pragma solidity ^0.8.20; import {IERC165} from "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` */ abstract contract ERC165 is IERC165 { /// @inheritdoc IERC165 function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Gas optimized reentrancy protection for smart contracts. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/ReentrancyGuard.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/security/ReentrancyGuard.sol) abstract contract ReentrancyGuard { uint256 private locked = 1; modifier nonReentrant() virtual { require(locked == 1, "REENTRANCY"); locked = 2; _; locked = 1; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/IERC1155Receiver.sol) pragma solidity ^0.8.20; import {IERC165} from "../../utils/introspection/IERC165.sol"; /** * @dev Interface that must be implemented by smart contracts in order to receive * ERC-1155 token transfers. */ interface IERC1155Receiver is IERC165 { /** * @dev Handles the receipt of a single ERC-1155 token type. This function is * called at the end of a `safeTransferFrom` after the balance has been updated. * * NOTE: To accept the transfer, this must return * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` * (i.e. 0xf23a6e61, or its own function selector). * * @param operator The address which initiated the transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param id The ID of the token being transferred * @param value The amount of tokens being transferred * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed */ function onERC1155Received( address operator, address from, uint256 id, uint256 value, bytes calldata data ) external returns (bytes4); /** * @dev Handles the receipt of a multiple ERC-1155 token types. This function * is called at the end of a `safeBatchTransferFrom` after the balances have * been updated. * * NOTE: To accept the transfer(s), this must return * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` * (i.e. 0xbc197c81, or its own function selector). * * @param operator The address which initiated the batch transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param ids An array containing ids of each token being transferred (order and length must match values array) * @param values An array containing amounts of each token being transferred (order and length must match ids array) * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed */ function onERC1155BatchReceived( address operator, address from, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; struct SetConfigParam { uint32 eid; uint32 configType; bytes config; } interface IMessageLibManager { struct Timeout { address lib; uint256 expiry; } event LibraryRegistered(address newLib); event DefaultSendLibrarySet(uint32 eid, address newLib); event DefaultReceiveLibrarySet(uint32 eid, address newLib); event DefaultReceiveLibraryTimeoutSet(uint32 eid, address oldLib, uint256 expiry); event SendLibrarySet(address sender, uint32 eid, address newLib); event ReceiveLibrarySet(address receiver, uint32 eid, address newLib); event ReceiveLibraryTimeoutSet(address receiver, uint32 eid, address oldLib, uint256 timeout); function registerLibrary(address _lib) external; function isRegisteredLibrary(address _lib) external view returns (bool); function getRegisteredLibraries() external view returns (address[] memory); function setDefaultSendLibrary(uint32 _eid, address _newLib) external; function defaultSendLibrary(uint32 _eid) external view returns (address); function setDefaultReceiveLibrary(uint32 _eid, address _newLib, uint256 _timeout) external; function defaultReceiveLibrary(uint32 _eid) external view returns (address); function setDefaultReceiveLibraryTimeout(uint32 _eid, address _lib, uint256 _expiry) external; function defaultReceiveLibraryTimeout(uint32 _eid) external view returns (address lib, uint256 expiry); function isSupportedEid(uint32 _eid) external view returns (bool); function isValidReceiveLibrary(address _receiver, uint32 _eid, address _lib) external view returns (bool); /// ------------------- OApp interfaces ------------------- function setSendLibrary(address _oapp, uint32 _eid, address _newLib) external; function getSendLibrary(address _sender, uint32 _eid) external view returns (address lib); function isDefaultSendLibrary(address _sender, uint32 _eid) external view returns (bool); function setReceiveLibrary(address _oapp, uint32 _eid, address _newLib, uint256 _gracePeriod) external; function getReceiveLibrary(address _receiver, uint32 _eid) external view returns (address lib, bool isDefault); function setReceiveLibraryTimeout(address _oapp, uint32 _eid, address _lib, uint256 _gracePeriod) external; function receiveLibraryTimeout(address _receiver, uint32 _eid) external view returns (address lib, uint256 expiry); function setConfig(address _oapp, address _lib, SetConfigParam[] calldata _params) external; function getConfig( address _oapp, address _lib, uint32 _eid, uint32 _configType ) external view returns (bytes memory config); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol) /// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) /// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. abstract contract ERC20 { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event Transfer(address indexed from, address indexed to, uint256 amount); event Approval(address indexed owner, address indexed spender, uint256 amount); /*////////////////////////////////////////////////////////////// METADATA STORAGE //////////////////////////////////////////////////////////////*/ string public name; string public symbol; uint8 public immutable decimals; /*////////////////////////////////////////////////////////////// ERC20 STORAGE //////////////////////////////////////////////////////////////*/ uint256 public totalSupply; mapping(address => uint256) public balanceOf; mapping(address => mapping(address => uint256)) public allowance; /*////////////////////////////////////////////////////////////// EIP-2612 STORAGE //////////////////////////////////////////////////////////////*/ uint256 internal immutable INITIAL_CHAIN_ID; bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR; mapping(address => uint256) public nonces; /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor( string memory _name, string memory _symbol, uint8 _decimals ) { name = _name; symbol = _symbol; decimals = _decimals; INITIAL_CHAIN_ID = block.chainid; INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); } /*////////////////////////////////////////////////////////////// ERC20 LOGIC //////////////////////////////////////////////////////////////*/ function approve(address spender, uint256 amount) public virtual returns (bool) { allowance[msg.sender][spender] = amount; emit Approval(msg.sender, spender, amount); return true; } function transfer(address to, uint256 amount) public virtual returns (bool) { balanceOf[msg.sender] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(msg.sender, to, amount); return true; } function transferFrom( address from, address to, uint256 amount ) public virtual returns (bool) { uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount; balanceOf[from] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(from, to, amount); return true; } /*////////////////////////////////////////////////////////////// EIP-2612 LOGIC //////////////////////////////////////////////////////////////*/ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public virtual { require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); // Unchecked because the only math done is incrementing // the owner's nonce which cannot realistically overflow. unchecked { address recoveredAddress = ecrecover( keccak256( abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR(), keccak256( abi.encode( keccak256( "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" ), owner, spender, value, nonces[owner]++, deadline ) ) ) ), v, r, s ); require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); allowance[recoveredAddress][spender] = value; } emit Approval(owner, spender, value); } function DOMAIN_SEPARATOR() public view virtual returns (bytes32) { return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator(); } function computeDomainSeparator() internal view virtual returns (bytes32) { return keccak256( abi.encode( keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256(bytes(name)), keccak256("1"), block.chainid, address(this) ) ); } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint(address to, uint256 amount) internal virtual { totalSupply += amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(address(0), to, amount); } function _burn(address from, uint256 amount) internal virtual { balanceOf[from] -= amount; // Cannot underflow because a user's balance // will never be larger than the total supply. unchecked { totalSupply -= amount; } emit Transfer(from, address(0), amount); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.21; interface BeforeTransferHook { function beforeTransfer(address from, address to, address operator) external view; }
// SPDX-License-Identifier: UNLICENSED // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. pragma solidity ^0.8.0; interface IRateProvider { function getRate() external view returns (uint256); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol) pragma solidity ^0.8.20; /** * @dev Collection of common custom errors used in multiple contracts * * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library. * It is recommended to avoid relying on the error API for critical functionality. * * _Available since v5.1._ */ library Errors { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error InsufficientBalance(uint256 balance, uint256 needed); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedCall(); /** * @dev The deployment failed. */ error FailedDeployment(); /** * @dev A necessary precompile is missing. */ error MissingPrecompile(address); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; interface IMessagingComposer { event ComposeSent(address from, address to, bytes32 guid, uint16 index, bytes message); event ComposeDelivered(address from, address to, bytes32 guid, uint16 index); event LzComposeAlert( address indexed from, address indexed to, address indexed executor, bytes32 guid, uint16 index, uint256 gas, uint256 value, bytes message, bytes extraData, bytes reason ); function composeQueue( address _from, address _to, bytes32 _guid, uint16 _index ) external view returns (bytes32 messageHash); function sendCompose(address _to, bytes32 _guid, uint16 _index, bytes calldata _message) external; function lzCompose( address _from, address _to, bytes32 _guid, uint16 _index, bytes calldata _message, bytes calldata _extraData ) external payable; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { ILayerZeroReceiver, Origin } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroReceiver.sol"; interface IOAppReceiver is ILayerZeroReceiver { /** * @notice Retrieves the address responsible for 'sending' composeMsg's to the Endpoint. * @return sender The address responsible for 'sending' composeMsg's to the Endpoint. * * @dev Applications can optionally choose to implement a separate composeMsg sender that is NOT the bridging layer. * @dev The default sender IS the OApp implementer. */ function composeMsgSender() external view returns (address sender); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; import {ERC20} from "../tokens/ERC20.sol"; /// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol) /// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer. library SafeTransferLib { /*////////////////////////////////////////////////////////////// ETH OPERATIONS //////////////////////////////////////////////////////////////*/ function safeTransferETH(address to, uint256 amount) internal { bool success; /// @solidity memory-safe-assembly assembly { // Transfer the ETH and store if it succeeded or not. success := call(gas(), to, amount, 0, 0, 0, 0) } require(success, "ETH_TRANSFER_FAILED"); } /*////////////////////////////////////////////////////////////// ERC20 OPERATIONS //////////////////////////////////////////////////////////////*/ function safeTransferFrom( ERC20 token, address from, address to, uint256 amount ) internal { bool success; /// @solidity memory-safe-assembly assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), and(from, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "from" argument. mstore(add(freeMemoryPointer, 36), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument. mstore(add(freeMemoryPointer, 68), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type. // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. success := call(gas(), token, 0, freeMemoryPointer, 100, 0, 32) // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data and token has code. if and(iszero(and(eq(mload(0), 1), gt(returndatasize(), 31))), success) { success := iszero(or(iszero(extcodesize(token)), returndatasize())) } } require(success, "TRANSFER_FROM_FAILED"); } function safeTransfer( ERC20 token, address to, uint256 amount ) internal { bool success; /// @solidity memory-safe-assembly assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument. mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type. // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. success := call(gas(), token, 0, freeMemoryPointer, 68, 0, 32) // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data and token has code. if and(iszero(and(eq(mload(0), 1), gt(returndatasize(), 31))), success) { success := iszero(or(iszero(extcodesize(token)), returndatasize())) } } require(success, "TRANSFER_FAILED"); } function safeApprove( ERC20 token, address to, uint256 amount ) internal { bool success; /// @solidity memory-safe-assembly assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument. mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type. // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. success := call(gas(), token, 0, freeMemoryPointer, 68, 0, 32) // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data and token has code. if and(iszero(and(eq(mload(0), 1), gt(returndatasize(), 31))), success) { success := iszero(or(iszero(extcodesize(token)), returndatasize())) } } require(success, "APPROVE_FAILED"); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Provides a flexible and updatable auth pattern which is completely separate from application logic. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Auth.sol) /// @author Modified from Dappsys (https://github.com/dapphub/ds-auth/blob/master/src/auth.sol) abstract contract Auth { event OwnershipTransferred(address indexed user, address indexed newOwner); event AuthorityUpdated(address indexed user, Authority indexed newAuthority); address public owner; Authority public authority; constructor(address _owner, Authority _authority) { owner = _owner; authority = _authority; emit OwnershipTransferred(msg.sender, _owner); emit AuthorityUpdated(msg.sender, _authority); } modifier requiresAuth() virtual { require(isAuthorized(msg.sender, msg.sig), "UNAUTHORIZED"); _; } function isAuthorized(address user, bytes4 functionSig) internal view virtual returns (bool) { Authority auth = authority; // Memoizing authority saves us a warm SLOAD, around 100 gas. // Checking if the caller is the owner only after calling the authority saves gas in most cases, but be // aware that this makes protected functions uncallable even to the owner if the authority is out of order. return (address(auth) != address(0) && auth.canCall(user, address(this), functionSig)) || user == owner; } function setAuthority(Authority newAuthority) public virtual { // We check if the caller is the owner first because we want to ensure they can // always swap out the authority even if it's reverting or using up a lot of gas. require(msg.sender == owner || authority.canCall(msg.sender, address(this), msg.sig)); authority = newAuthority; emit AuthorityUpdated(msg.sender, newAuthority); } function transferOwnership(address newOwner) public virtual requiresAuth { owner = newOwner; emit OwnershipTransferred(msg.sender, newOwner); } } /// @notice A generic interface for a contract which provides authorization data to an Auth instance. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Auth.sol) /// @author Modified from Dappsys (https://github.com/dapphub/ds-auth/blob/master/src/auth.sol) interface Authority { function canCall( address user, address target, bytes4 functionSig ) external view returns (bool); }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.20; import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol"; import {BytesLib} from "@sbu/contracts/BytesLib.sol"; library OptionsBuilder { using SafeCast for uint256; using BytesLib for bytes; // Constants for options types uint16 internal constant TYPE_3 = 3; uint8 internal constant OPTION_TYPE_LZRECEIVE = 1; uint8 internal constant WORKER_ID = 1; error InvalidOptionType(uint16 optionType); // Modifier to ensure only options of type 3 are used modifier onlyType3(bytes memory _options) { if (_options.toUint16(0) != TYPE_3) revert InvalidOptionType(_options.toUint16(0)); _; } /** * @dev Creates a new options container with type 3. * @return options The newly created options container. */ function newOptions() internal pure returns (bytes memory) { return abi.encodePacked(TYPE_3); } /** * @dev Adds an executor LZ receive option to the existing options. * @param _options The existing options container. * @param _gas The gasLimit used on the lzReceive() function in the OApp. * @param _value The msg.value passed to the lzReceive() function in the OApp. * @return options The updated options container. * * @dev When multiples of this option are added, they are summed by the executor * eg. if (_gas: 200k, and _value: 1 ether) AND (_gas: 100k, _value: 0.5 ether) are sent in an option to the LayerZeroEndpoint, * that becomes (300k, 1.5 ether) when the message is executed on the remote lzReceive() function. */ function addExecutorLzReceiveOption(bytes memory _options, uint128 _gas, uint128 _value) internal pure onlyType3(_options) returns (bytes memory) { bytes memory option = encodeLzReceiveOption(_gas, _value); return addExecutorOption(_options, OPTION_TYPE_LZRECEIVE, option); } /** * @dev Adds an executor option to the existing options. * @param _options The existing options container. * @param _optionType The type of the executor option. * @param _option The encoded data for the executor option. * @return options The updated options container. */ function addExecutorOption(bytes memory _options, uint8 _optionType, bytes memory _option) internal pure onlyType3(_options) returns (bytes memory) { return abi.encodePacked( _options, WORKER_ID, _option.length.toUint16() + 1, // +1 for optionType _optionType, _option ); } function encodeLzReceiveOption(uint128 _gas, uint128 _value) internal pure returns (bytes memory) { return _value == 0 ? abi.encodePacked(_gas) : abi.encodePacked(_gas, _value); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[ERC]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; import {ERC20} from "./ERC20.sol"; import {SafeTransferLib} from "../utils/SafeTransferLib.sol"; /// @notice Minimalist and modern Wrapped Ether implementation. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/WETH.sol) /// @author Inspired by WETH9 (https://github.com/dapphub/ds-weth/blob/master/src/weth9.sol) contract WETH is ERC20("Wrapped Ether", "WETH", 18) { using SafeTransferLib for address; event Deposit(address indexed from, uint256 amount); event Withdrawal(address indexed to, uint256 amount); function deposit() public payable virtual { _mint(msg.sender, msg.value); emit Deposit(msg.sender, msg.value); } function withdraw(uint256 amount) public virtual { _burn(msg.sender, amount); emit Withdrawal(msg.sender, amount); msg.sender.safeTransferETH(amount); } receive() external payable virtual { deposit(); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { ILayerZeroEndpointV2 } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol"; /** * @title IOAppCore */ interface IOAppCore { // Custom error messages error OnlyPeer(uint32 eid, bytes32 sender); error NoPeer(uint32 eid); error InvalidEndpointCall(); error InvalidDelegate(); // Event emitted when a peer (OApp) is set for a corresponding endpoint event PeerSet(uint32 eid, bytes32 peer); /** * @notice Retrieves the OApp version information. * @return senderVersion The version of the OAppSender.sol contract. * @return receiverVersion The version of the OAppReceiver.sol contract. */ function oAppVersion() external view returns (uint64 senderVersion, uint64 receiverVersion); /** * @notice Retrieves the LayerZero endpoint associated with the OApp. * @return iEndpoint The LayerZero endpoint as an interface. */ function endpoint() external view returns (ILayerZeroEndpointV2 iEndpoint); /** * @notice Retrieves the peer (OApp) associated with a corresponding endpoint. * @param _eid The endpoint ID. * @return peer The peer address (OApp instance) associated with the corresponding endpoint. */ function peers(uint32 _eid) external view returns (bytes32 peer); /** * @notice Sets the peer address (OApp instance) for a corresponding endpoint. * @param _eid The endpoint ID. * @param _peer The address of the peer to be associated with the corresponding endpoint. */ function setPeer(uint32 _eid, bytes32 _peer) external; /** * @notice Sets the delegate address for the OApp Core. * @param _delegate The address of the delegate to be set. */ function setDelegate(address _delegate) external; }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.21; import {FixedPointMathLib} from "@solmate/utils/FixedPointMathLib.sol"; import {IRateProvider} from "../../../src/interfaces/IRateProvider.sol"; import {ERC20} from "@solmate/tokens/ERC20.sol"; import {SafeTransferLib} from "@solmate/utils/SafeTransferLib.sol"; import {BoringVault} from "../../../src/base/BoringVault.sol"; import {Auth, Authority} from "@solmate/auth/Auth.sol"; import {IPausable} from "../../../src/interfaces/IPausable.sol"; contract AccountantWithRateProviders is Auth, IRateProvider, IPausable { using FixedPointMathLib for uint256; using SafeTransferLib for ERC20; // ========================================= STRUCTS ========================================= /** * @param payoutAddress the address `claimFees` sends fees to * @param highwaterMark the highest value of the BoringVault's share price * @param feesOwedInBase total pending fees owed in terms of base * @param totalSharesLastUpdate total amount of shares the last exchange rate update * @param exchangeRate the current exchange rate in terms of base * @param allowedExchangeRateChangeUpper the max allowed change to exchange rate from an update * @param allowedExchangeRateChangeLower the min allowed change to exchange rate from an update * @param lastUpdateTimestamp the block timestamp of the last exchange rate update * @param isPaused whether or not this contract is paused * @param minimumUpdateDelayInSeconds the minimum amount of time that must pass between * exchange rate updates, such that the update won't trigger the contract to be paused * @param platformFee the platform fee * @param performanceFee the performance fee */ struct AccountantState { address payoutAddress; uint96 highwaterMark; uint128 feesOwedInBase; uint128 totalSharesLastUpdate; uint96 exchangeRate; uint16 allowedExchangeRateChangeUpper; uint16 allowedExchangeRateChangeLower; uint64 lastUpdateTimestamp; bool isPaused; uint24 minimumUpdateDelayInSeconds; uint16 platformFee; uint16 performanceFee; } /** * @param isPeggedToBase whether or not the asset is 1:1 with the base asset * @param rateProvider the rate provider for this asset if `isPeggedToBase` is false */ struct RateProviderData { bool isPeggedToBase; IRateProvider rateProvider; } // ========================================= STATE ========================================= /** * @notice Store the accountant state in 3 packed slots. */ AccountantState public accountantState; /** * @notice Maps ERC20s to their RateProviderData. */ mapping(ERC20 => RateProviderData) public rateProviderData; //============================== ERRORS =============================== error AccountantWithRateProviders__UpperBoundTooSmall(); error AccountantWithRateProviders__LowerBoundTooLarge(); error AccountantWithRateProviders__PlatformFeeTooLarge(); error AccountantWithRateProviders__PerformanceFeeTooLarge(); error AccountantWithRateProviders__Paused(); error AccountantWithRateProviders__ZeroFeesOwed(); error AccountantWithRateProviders__OnlyCallableByBoringVault(); error AccountantWithRateProviders__UpdateDelayTooLarge(); error AccountantWithRateProviders__ExchangeRateAboveHighwaterMark(); //============================== EVENTS =============================== event Paused(); event Unpaused(); event DelayInSecondsUpdated(uint24 oldDelay, uint24 newDelay); event UpperBoundUpdated(uint16 oldBound, uint16 newBound); event LowerBoundUpdated(uint16 oldBound, uint16 newBound); event PlatformFeeUpdated(uint16 oldFee, uint16 newFee); event PerformanceFeeUpdated(uint16 oldFee, uint16 newFee); event PayoutAddressUpdated(address oldPayout, address newPayout); event RateProviderUpdated(address asset, bool isPegged, address rateProvider); event ExchangeRateUpdated(uint96 oldRate, uint96 newRate, uint64 currentTime); event FeesClaimed(address indexed feeAsset, uint256 amount); event HighwaterMarkReset(); //============================== IMMUTABLES =============================== /** * @notice The base asset rates are provided in. */ ERC20 public immutable base; /** * @notice The decimals rates are provided in. */ uint8 public immutable decimals; /** * @notice The BoringVault this accountant is working with. * Used to determine share supply for fee calculation. */ BoringVault public immutable vault; /** * @notice One share of the BoringVault. */ uint256 internal immutable ONE_SHARE; constructor( address _owner, address _vault, address payoutAddress, uint96 startingExchangeRate, address _base, uint16 allowedExchangeRateChangeUpper, uint16 allowedExchangeRateChangeLower, uint24 minimumUpdateDelayInSeconds, uint16 platformFee, uint16 performanceFee ) Auth(_owner, Authority(address(0))) { base = ERC20(_base); decimals = ERC20(_base).decimals(); vault = BoringVault(payable(_vault)); ONE_SHARE = 10 ** vault.decimals(); accountantState = AccountantState({ payoutAddress: payoutAddress, highwaterMark: startingExchangeRate, feesOwedInBase: 0, totalSharesLastUpdate: uint128(vault.totalSupply()), exchangeRate: startingExchangeRate, allowedExchangeRateChangeUpper: allowedExchangeRateChangeUpper, allowedExchangeRateChangeLower: allowedExchangeRateChangeLower, lastUpdateTimestamp: uint64(block.timestamp), isPaused: false, minimumUpdateDelayInSeconds: minimumUpdateDelayInSeconds, platformFee: platformFee, performanceFee: performanceFee }); } // ========================================= ADMIN FUNCTIONS ========================================= /** * @notice Pause this contract, which prevents future calls to `updateExchangeRate`, and any safe rate * calls will revert. * @dev Callable by MULTISIG_ROLE. */ function pause() external requiresAuth { accountantState.isPaused = true; emit Paused(); } /** * @notice Unpause this contract, which allows future calls to `updateExchangeRate`, and any safe rate * calls will stop reverting. * @dev Callable by MULTISIG_ROLE. */ function unpause() external requiresAuth { accountantState.isPaused = false; emit Unpaused(); } /** * @notice Update the minimum time delay between `updateExchangeRate` calls. * @dev There are no input requirements, as it is possible the admin would want * the exchange rate updated as frequently as needed. * @dev Callable by OWNER_ROLE. */ function updateDelay(uint24 minimumUpdateDelayInSeconds) external requiresAuth { if (minimumUpdateDelayInSeconds > 14 days) revert AccountantWithRateProviders__UpdateDelayTooLarge(); uint24 oldDelay = accountantState.minimumUpdateDelayInSeconds; accountantState.minimumUpdateDelayInSeconds = minimumUpdateDelayInSeconds; emit DelayInSecondsUpdated(oldDelay, minimumUpdateDelayInSeconds); } /** * @notice Update the allowed upper bound change of exchange rate between `updateExchangeRateCalls`. * @dev Callable by OWNER_ROLE. */ function updateUpper(uint16 allowedExchangeRateChangeUpper) external requiresAuth { if (allowedExchangeRateChangeUpper < 1e4) revert AccountantWithRateProviders__UpperBoundTooSmall(); uint16 oldBound = accountantState.allowedExchangeRateChangeUpper; accountantState.allowedExchangeRateChangeUpper = allowedExchangeRateChangeUpper; emit UpperBoundUpdated(oldBound, allowedExchangeRateChangeUpper); } /** * @notice Update the allowed lower bound change of exchange rate between `updateExchangeRateCalls`. * @dev Callable by OWNER_ROLE. */ function updateLower(uint16 allowedExchangeRateChangeLower) external requiresAuth { if (allowedExchangeRateChangeLower > 1e4) revert AccountantWithRateProviders__LowerBoundTooLarge(); uint16 oldBound = accountantState.allowedExchangeRateChangeLower; accountantState.allowedExchangeRateChangeLower = allowedExchangeRateChangeLower; emit LowerBoundUpdated(oldBound, allowedExchangeRateChangeLower); } /** * @notice Update the platform fee to a new value. * @dev Callable by OWNER_ROLE. */ function updatePlatformFee(uint16 platformFee) external requiresAuth { if (platformFee > 0.2e4) revert AccountantWithRateProviders__PlatformFeeTooLarge(); uint16 oldFee = accountantState.platformFee; accountantState.platformFee = platformFee; emit PlatformFeeUpdated(oldFee, platformFee); } /** * @notice Update the performance fee to a new value. * @dev Callable by OWNER_ROLE. */ function updatePerformanceFee(uint16 performanceFee) external requiresAuth { if (performanceFee > 0.5e4) revert AccountantWithRateProviders__PerformanceFeeTooLarge(); uint16 oldFee = accountantState.performanceFee; accountantState.performanceFee = performanceFee; emit PerformanceFeeUpdated(oldFee, performanceFee); } /** * @notice Update the payout address fees are sent to. * @dev Callable by OWNER_ROLE. */ function updatePayoutAddress(address payoutAddress) external requiresAuth { address oldPayout = accountantState.payoutAddress; accountantState.payoutAddress = payoutAddress; emit PayoutAddressUpdated(oldPayout, payoutAddress); } /** * @notice Update the rate provider data for a specific `asset`. * @dev Rate providers must return rates in terms of `base` or * an asset pegged to base and they must use the same decimals * as `asset`. * @dev Callable by OWNER_ROLE. */ function setRateProviderData(ERC20 asset, bool isPeggedToBase, address rateProvider) external requiresAuth { rateProviderData[asset] = RateProviderData({isPeggedToBase: isPeggedToBase, rateProvider: IRateProvider(rateProvider)}); emit RateProviderUpdated(address(asset), isPeggedToBase, rateProvider); } /** * @notice Reset the highwater mark to the current exchange rate. * @dev Callable by OWNER_ROLE. */ function resetHighwaterMark() external virtual requiresAuth { AccountantState storage state = accountantState; if (state.exchangeRate > state.highwaterMark) { revert AccountantWithRateProviders__ExchangeRateAboveHighwaterMark(); } uint64 currentTime = uint64(block.timestamp); uint256 currentTotalShares = vault.totalSupply(); _calculateFeesOwed(state, state.exchangeRate, state.exchangeRate, currentTotalShares, currentTime); state.totalSharesLastUpdate = uint128(currentTotalShares); state.highwaterMark = accountantState.exchangeRate; state.lastUpdateTimestamp = currentTime; emit HighwaterMarkReset(); } // ========================================= UPDATE EXCHANGE RATE/FEES FUNCTIONS ========================================= /** * @notice Updates this contract exchangeRate. * @dev If new exchange rate is outside of accepted bounds, or if not enough time has passed, this * will pause the contract, and this function will NOT calculate fees owed. * @dev Callable by UPDATE_EXCHANGE_RATE_ROLE. */ function updateExchangeRate(uint96 newExchangeRate) external virtual requiresAuth { ( bool shouldPause, AccountantState storage state, uint64 currentTime, uint256 currentExchangeRate, uint256 currentTotalShares ) = _beforeUpdateExchangeRate(newExchangeRate); if (shouldPause) { // Instead of reverting, pause the contract. This way the exchange rate updater is able to update the exchange rate // to a better value, and pause it. state.isPaused = true; } else { _calculateFeesOwed(state, newExchangeRate, currentExchangeRate, currentTotalShares, currentTime); } newExchangeRate = _setExchangeRate(newExchangeRate, state); state.totalSharesLastUpdate = uint128(currentTotalShares); state.lastUpdateTimestamp = currentTime; emit ExchangeRateUpdated(uint96(currentExchangeRate), newExchangeRate, currentTime); } /** * @notice Claim pending fees. * @dev This function must be called by the BoringVault. * @dev This function will lose precision if the exchange rate * decimals is greater than the feeAsset's decimals. */ function claimFees(ERC20 feeAsset) external { if (msg.sender != address(vault)) revert AccountantWithRateProviders__OnlyCallableByBoringVault(); AccountantState storage state = accountantState; if (state.isPaused) revert AccountantWithRateProviders__Paused(); if (state.feesOwedInBase == 0) revert AccountantWithRateProviders__ZeroFeesOwed(); // Determine amount of fees owed in feeAsset. uint256 feesOwedInFeeAsset; RateProviderData memory data = rateProviderData[feeAsset]; if (address(feeAsset) == address(base)) { feesOwedInFeeAsset = state.feesOwedInBase; } else { uint8 feeAssetDecimals = ERC20(feeAsset).decimals(); uint256 feesOwedInBaseUsingFeeAssetDecimals = _changeDecimals(state.feesOwedInBase, decimals, feeAssetDecimals); if (data.isPeggedToBase) { feesOwedInFeeAsset = feesOwedInBaseUsingFeeAssetDecimals; } else { uint256 rate = data.rateProvider.getRate(); feesOwedInFeeAsset = feesOwedInBaseUsingFeeAssetDecimals.mulDivDown(10 ** feeAssetDecimals, rate); } } // Zero out fees owed. state.feesOwedInBase = 0; // Transfer fee asset to payout address. feeAsset.safeTransferFrom(msg.sender, state.payoutAddress, feesOwedInFeeAsset); emit FeesClaimed(address(feeAsset), feesOwedInFeeAsset); } // ========================================= VIEW FUNCTIONS ========================================= /** * @notice Get this BoringVault's current rate in the base. */ function getRate() public view returns (uint256 rate) { rate = accountantState.exchangeRate; } /** * @notice Get this BoringVault's current rate in the base. * @dev Revert if paused. */ function getRateSafe() external view returns (uint256 rate) { if (accountantState.isPaused) revert AccountantWithRateProviders__Paused(); rate = getRate(); } /** * @notice Get this BoringVault's current rate in the provided quote. * @dev `quote` must have its RateProviderData set, else this will revert. * @dev This function will lose precision if the exchange rate * decimals is greater than the quote's decimals. */ function getRateInQuote(ERC20 quote) public view returns (uint256 rateInQuote) { if (address(quote) == address(base)) { rateInQuote = accountantState.exchangeRate; } else { RateProviderData memory data = rateProviderData[quote]; uint8 quoteDecimals = ERC20(quote).decimals(); uint256 exchangeRateInQuoteDecimals = _changeDecimals(accountantState.exchangeRate, decimals, quoteDecimals); if (data.isPeggedToBase) { rateInQuote = exchangeRateInQuoteDecimals; } else { uint256 quoteRate = data.rateProvider.getRate(); uint256 oneQuote = 10 ** quoteDecimals; rateInQuote = oneQuote.mulDivDown(exchangeRateInQuoteDecimals, quoteRate); } } } /** * @notice Get this BoringVault's current rate in the provided quote. * @dev `quote` must have its RateProviderData set, else this will revert. * @dev Revert if paused. */ function getRateInQuoteSafe(ERC20 quote) external view returns (uint256 rateInQuote) { if (accountantState.isPaused) revert AccountantWithRateProviders__Paused(); rateInQuote = getRateInQuote(quote); } /** * @notice Preview the result of an update to the exchange rate. * @return updateWillPause Whether the update will pause the contract. * @return newFeesOwedInBase The new fees owed in base. * @return totalFeesOwedInBase The total fees owed in base. */ function previewUpdateExchangeRate(uint96 newExchangeRate) external view virtual returns (bool updateWillPause, uint256 newFeesOwedInBase, uint256 totalFeesOwedInBase) { ( bool shouldPause, AccountantState storage state, uint64 currentTime, uint256 currentExchangeRate, uint256 currentTotalShares ) = _beforeUpdateExchangeRate(newExchangeRate); updateWillPause = shouldPause; totalFeesOwedInBase = state.feesOwedInBase; if (!shouldPause) { (uint256 platformFeesOwedInBase, uint256 shareSupplyToUse) = _calculatePlatformFee( state.totalSharesLastUpdate, state.lastUpdateTimestamp, state.platformFee, newExchangeRate, currentExchangeRate, currentTotalShares, currentTime ); uint256 performanceFeesOwedInBase; if (newExchangeRate > state.highwaterMark) { (performanceFeesOwedInBase,) = _calculatePerformanceFee( newExchangeRate, shareSupplyToUse, state.highwaterMark, state.performanceFee ); } newFeesOwedInBase = platformFeesOwedInBase + performanceFeesOwedInBase; totalFeesOwedInBase += newFeesOwedInBase; } } // ========================================= INTERNAL HELPER FUNCTIONS ========================================= /** * @notice Used to change the decimals of precision used for an amount. */ function _changeDecimals(uint256 amount, uint8 fromDecimals, uint8 toDecimals) internal pure returns (uint256) { if (fromDecimals == toDecimals) { return amount; } else if (fromDecimals < toDecimals) { return amount * 10 ** (toDecimals - fromDecimals); } else { return amount / 10 ** (fromDecimals - toDecimals); } } /** * @notice Check if the new exchange rate is outside of the allowed bounds or if not enough time has passed. */ function _beforeUpdateExchangeRate(uint96 newExchangeRate) internal view returns ( bool shouldPause, AccountantState storage state, uint64 currentTime, uint256 currentExchangeRate, uint256 currentTotalShares ) { state = accountantState; if (state.isPaused) revert AccountantWithRateProviders__Paused(); currentTime = uint64(block.timestamp); currentExchangeRate = state.exchangeRate; currentTotalShares = vault.totalSupply(); shouldPause = currentTime < state.lastUpdateTimestamp + state.minimumUpdateDelayInSeconds || newExchangeRate > currentExchangeRate.mulDivDown(state.allowedExchangeRateChangeUpper, 1e4) || newExchangeRate < currentExchangeRate.mulDivDown(state.allowedExchangeRateChangeLower, 1e4); } /** * @notice Set the exchange rate. */ function _setExchangeRate(uint96 newExchangeRate, AccountantState storage state) internal virtual returns (uint96) { state.exchangeRate = newExchangeRate; return newExchangeRate; } /** * @notice Calculate platform fees. */ function _calculatePlatformFee( uint128 totalSharesLastUpdate, uint64 lastUpdateTimestamp, uint16 platformFee, uint96 newExchangeRate, uint256 currentExchangeRate, uint256 currentTotalShares, uint64 currentTime ) internal view returns (uint256 platformFeesOwedInBase, uint256 shareSupplyToUse) { shareSupplyToUse = currentTotalShares; // Use the minimum between current total supply and total supply for last update. if (totalSharesLastUpdate < shareSupplyToUse) { shareSupplyToUse = totalSharesLastUpdate; } // Determine platform fees owned. if (platformFee > 0) { uint256 timeDelta = currentTime - lastUpdateTimestamp; uint256 minimumAssets = newExchangeRate > currentExchangeRate ? shareSupplyToUse.mulDivDown(currentExchangeRate, ONE_SHARE) : shareSupplyToUse.mulDivDown(newExchangeRate, ONE_SHARE); uint256 platformFeesAnnual = minimumAssets.mulDivDown(platformFee, 1e4); platformFeesOwedInBase = platformFeesAnnual.mulDivDown(timeDelta, 365 days); } } /** * @notice Calculate performance fees. */ function _calculatePerformanceFee( uint96 newExchangeRate, uint256 shareSupplyToUse, uint96 datum, uint16 performanceFee ) internal view returns (uint256 performanceFeesOwedInBase, uint256 yieldEarned) { uint256 changeInExchangeRate = newExchangeRate - datum; yieldEarned = changeInExchangeRate.mulDivDown(shareSupplyToUse, ONE_SHARE); if (performanceFee > 0) { performanceFeesOwedInBase = yieldEarned.mulDivDown(performanceFee, 1e4); } } /** * @notice Calculate fees owed in base. * @dev This function will update the highwater mark if the new exchange rate is higher. */ function _calculateFeesOwed( AccountantState storage state, uint96 newExchangeRate, uint256 currentExchangeRate, uint256 currentTotalShares, uint64 currentTime ) internal virtual { // Only update fees if we are not paused. // Update fee accounting. (uint256 newFeesOwedInBase, uint256 shareSupplyToUse) = _calculatePlatformFee( state.totalSharesLastUpdate, state.lastUpdateTimestamp, state.platformFee, newExchangeRate, currentExchangeRate, currentTotalShares, currentTime ); // Account for performance fees. if (newExchangeRate > state.highwaterMark) { (uint256 performanceFeesOwedInBase,) = _calculatePerformanceFee(newExchangeRate, shareSupplyToUse, state.highwaterMark, state.performanceFee); // Add performance fees to fees owed. newFeesOwedInBase += performanceFeesOwedInBase; // Always update the highwater mark if the new exchange rate is higher. // This way if we are not iniitiall taking performance fees, we can start taking them // without back charging them on past performance. state.highwaterMark = newExchangeRate; } state.feesOwedInBase += uint128(newFeesOwedInBase); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import {Auth, Authority} from "@solmate/auth/Auth.sol"; import {IOAppCore, ILayerZeroEndpointV2} from "@lz-oapp-evm/interfaces/IOAppCore.sol"; /** * @title OAppCore * @dev Abstract contract implementing the IOAppCore interface with basic OApp configurations. */ abstract contract OAppAuthCore is IOAppCore, Auth { // The LayerZero endpoint associated with the given OApp ILayerZeroEndpointV2 public immutable endpoint; // Mapping to store peers associated with corresponding endpoints mapping(uint32 eid => bytes32 peer) public peers; /** * @dev Constructor to initialize the OAppCore with the provided endpoint and delegate. * @param _endpoint The address of the LOCAL Layer Zero endpoint. * @param _delegate The delegate capable of making OApp configurations inside of the endpoint. * * @dev The delegate typically should be set as the owner of the contract. */ constructor(address _endpoint, address _delegate) { endpoint = ILayerZeroEndpointV2(_endpoint); if (_delegate == address(0)) revert InvalidDelegate(); endpoint.setDelegate(_delegate); } /** * @notice Sets the peer address (OApp instance) for a corresponding endpoint. * @param _eid The endpoint ID. * @param _peer The address of the peer to be associated with the corresponding endpoint. * * @dev Only the owner/admin of the OApp can call this function. * @dev Indicates that the peer is trusted to send LayerZero messages to this OApp. * @dev Set this to bytes32(0) to remove the peer address. * @dev Peer is a bytes32 to accommodate non-evm chains. */ function setPeer(uint32 _eid, bytes32 _peer) public virtual requiresAuth { _setPeer(_eid, _peer); } /** * @notice Sets the peer address (OApp instance) for a corresponding endpoint. * @param _eid The endpoint ID. * @param _peer The address of the peer to be associated with the corresponding endpoint. * * @dev Indicates that the peer is trusted to send LayerZero messages to this OApp. * @dev Set this to bytes32(0) to remove the peer address. * @dev Peer is a bytes32 to accommodate non-evm chains. */ function _setPeer(uint32 _eid, bytes32 _peer) internal virtual { peers[_eid] = _peer; emit PeerSet(_eid, _peer); } /** * @notice Internal function to get the peer address associated with a specific endpoint; reverts if NOT set. * ie. the peer is set to bytes32(0). * @param _eid The endpoint ID. * @return peer The address of the peer associated with the specified endpoint. */ function _getPeerOrRevert(uint32 _eid) internal view virtual returns (bytes32) { bytes32 peer = peers[_eid]; if (peer == bytes32(0)) revert NoPeer(_eid); return peer; } /** * @notice Sets the delegate address for the OApp. * @param _delegate The address of the delegate to be set. * * @dev Only the owner/admin of the OApp can call this function. * @dev Provides the ability for a delegate to set configs, on behalf of the OApp, directly on the Endpoint contract. */ function setDelegate(address _delegate) public requiresAuth { endpoint.setDelegate(_delegate); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/utils/ERC721Holder.sol) pragma solidity ^0.8.20; import {IERC721Receiver} from "../IERC721Receiver.sol"; /** * @dev Implementation of the {IERC721Receiver} interface. * * Accepts all token transfers. * Make sure the contract is able to use its token with {IERC721-safeTransferFrom}, {IERC721-approve} or * {IERC721-setApprovalForAll}. */ abstract contract ERC721Holder is IERC721Receiver { /** * @dev See {IERC721Receiver-onERC721Received}. * * Always returns `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received(address, address, uint256, bytes memory) public virtual returns (bytes4) { return this.onERC721Received.selector; } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.21; interface IPausable { function pause() external; function unpause() external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol) // This file was procedurally generated from scripts/generate/templates/SafeCast.js. pragma solidity ^0.8.20; /** * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow * checks. * * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such an operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeCast { /** * @dev Value doesn't fit in an uint of `bits` size. */ error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value); /** * @dev An int value doesn't fit in an uint of `bits` size. */ error SafeCastOverflowedIntToUint(int256 value); /** * @dev Value doesn't fit in an int of `bits` size. */ error SafeCastOverflowedIntDowncast(uint8 bits, int256 value); /** * @dev An uint value doesn't fit in an int of `bits` size. */ error SafeCastOverflowedUintToInt(uint256 value); /** * @dev Returns the downcasted uint248 from uint256, reverting on * overflow (when the input is greater than largest uint248). * * Counterpart to Solidity's `uint248` operator. * * Requirements: * * - input must fit into 248 bits */ function toUint248(uint256 value) internal pure returns (uint248) { if (value > type(uint248).max) { revert SafeCastOverflowedUintDowncast(248, value); } return uint248(value); } /** * @dev Returns the downcasted uint240 from uint256, reverting on * overflow (when the input is greater than largest uint240). * * Counterpart to Solidity's `uint240` operator. * * Requirements: * * - input must fit into 240 bits */ function toUint240(uint256 value) internal pure returns (uint240) { if (value > type(uint240).max) { revert SafeCastOverflowedUintDowncast(240, value); } return uint240(value); } /** * @dev Returns the downcasted uint232 from uint256, reverting on * overflow (when the input is greater than largest uint232). * * Counterpart to Solidity's `uint232` operator. * * Requirements: * * - input must fit into 232 bits */ function toUint232(uint256 value) internal pure returns (uint232) { if (value > type(uint232).max) { revert SafeCastOverflowedUintDowncast(232, value); } return uint232(value); } /** * @dev Returns the downcasted uint224 from uint256, reverting on * overflow (when the input is greater than largest uint224). * * Counterpart to Solidity's `uint224` operator. * * Requirements: * * - input must fit into 224 bits */ function toUint224(uint256 value) internal pure returns (uint224) { if (value > type(uint224).max) { revert SafeCastOverflowedUintDowncast(224, value); } return uint224(value); } /** * @dev Returns the downcasted uint216 from uint256, reverting on * overflow (when the input is greater than largest uint216). * * Counterpart to Solidity's `uint216` operator. * * Requirements: * * - input must fit into 216 bits */ function toUint216(uint256 value) internal pure returns (uint216) { if (value > type(uint216).max) { revert SafeCastOverflowedUintDowncast(216, value); } return uint216(value); } /** * @dev Returns the downcasted uint208 from uint256, reverting on * overflow (when the input is greater than largest uint208). * * Counterpart to Solidity's `uint208` operator. * * Requirements: * * - input must fit into 208 bits */ function toUint208(uint256 value) internal pure returns (uint208) { if (value > type(uint208).max) { revert SafeCastOverflowedUintDowncast(208, value); } return uint208(value); } /** * @dev Returns the downcasted uint200 from uint256, reverting on * overflow (when the input is greater than largest uint200). * * Counterpart to Solidity's `uint200` operator. * * Requirements: * * - input must fit into 200 bits */ function toUint200(uint256 value) internal pure returns (uint200) { if (value > type(uint200).max) { revert SafeCastOverflowedUintDowncast(200, value); } return uint200(value); } /** * @dev Returns the downcasted uint192 from uint256, reverting on * overflow (when the input is greater than largest uint192). * * Counterpart to Solidity's `uint192` operator. * * Requirements: * * - input must fit into 192 bits */ function toUint192(uint256 value) internal pure returns (uint192) { if (value > type(uint192).max) { revert SafeCastOverflowedUintDowncast(192, value); } return uint192(value); } /** * @dev Returns the downcasted uint184 from uint256, reverting on * overflow (when the input is greater than largest uint184). * * Counterpart to Solidity's `uint184` operator. * * Requirements: * * - input must fit into 184 bits */ function toUint184(uint256 value) internal pure returns (uint184) { if (value > type(uint184).max) { revert SafeCastOverflowedUintDowncast(184, value); } return uint184(value); } /** * @dev Returns the downcasted uint176 from uint256, reverting on * overflow (when the input is greater than largest uint176). * * Counterpart to Solidity's `uint176` operator. * * Requirements: * * - input must fit into 176 bits */ function toUint176(uint256 value) internal pure returns (uint176) { if (value > type(uint176).max) { revert SafeCastOverflowedUintDowncast(176, value); } return uint176(value); } /** * @dev Returns the downcasted uint168 from uint256, reverting on * overflow (when the input is greater than largest uint168). * * Counterpart to Solidity's `uint168` operator. * * Requirements: * * - input must fit into 168 bits */ function toUint168(uint256 value) internal pure returns (uint168) { if (value > type(uint168).max) { revert SafeCastOverflowedUintDowncast(168, value); } return uint168(value); } /** * @dev Returns the downcasted uint160 from uint256, reverting on * overflow (when the input is greater than largest uint160). * * Counterpart to Solidity's `uint160` operator. * * Requirements: * * - input must fit into 160 bits */ function toUint160(uint256 value) internal pure returns (uint160) { if (value > type(uint160).max) { revert SafeCastOverflowedUintDowncast(160, value); } return uint160(value); } /** * @dev Returns the downcasted uint152 from uint256, reverting on * overflow (when the input is greater than largest uint152). * * Counterpart to Solidity's `uint152` operator. * * Requirements: * * - input must fit into 152 bits */ function toUint152(uint256 value) internal pure returns (uint152) { if (value > type(uint152).max) { revert SafeCastOverflowedUintDowncast(152, value); } return uint152(value); } /** * @dev Returns the downcasted uint144 from uint256, reverting on * overflow (when the input is greater than largest uint144). * * Counterpart to Solidity's `uint144` operator. * * Requirements: * * - input must fit into 144 bits */ function toUint144(uint256 value) internal pure returns (uint144) { if (value > type(uint144).max) { revert SafeCastOverflowedUintDowncast(144, value); } return uint144(value); } /** * @dev Returns the downcasted uint136 from uint256, reverting on * overflow (when the input is greater than largest uint136). * * Counterpart to Solidity's `uint136` operator. * * Requirements: * * - input must fit into 136 bits */ function toUint136(uint256 value) internal pure returns (uint136) { if (value > type(uint136).max) { revert SafeCastOverflowedUintDowncast(136, value); } return uint136(value); } /** * @dev Returns the downcasted uint128 from uint256, reverting on * overflow (when the input is greater than largest uint128). * * Counterpart to Solidity's `uint128` operator. * * Requirements: * * - input must fit into 128 bits */ function toUint128(uint256 value) internal pure returns (uint128) { if (value > type(uint128).max) { revert SafeCastOverflowedUintDowncast(128, value); } return uint128(value); } /** * @dev Returns the downcasted uint120 from uint256, reverting on * overflow (when the input is greater than largest uint120). * * Counterpart to Solidity's `uint120` operator. * * Requirements: * * - input must fit into 120 bits */ function toUint120(uint256 value) internal pure returns (uint120) { if (value > type(uint120).max) { revert SafeCastOverflowedUintDowncast(120, value); } return uint120(value); } /** * @dev Returns the downcasted uint112 from uint256, reverting on * overflow (when the input is greater than largest uint112). * * Counterpart to Solidity's `uint112` operator. * * Requirements: * * - input must fit into 112 bits */ function toUint112(uint256 value) internal pure returns (uint112) { if (value > type(uint112).max) { revert SafeCastOverflowedUintDowncast(112, value); } return uint112(value); } /** * @dev Returns the downcasted uint104 from uint256, reverting on * overflow (when the input is greater than largest uint104). * * Counterpart to Solidity's `uint104` operator. * * Requirements: * * - input must fit into 104 bits */ function toUint104(uint256 value) internal pure returns (uint104) { if (value > type(uint104).max) { revert SafeCastOverflowedUintDowncast(104, value); } return uint104(value); } /** * @dev Returns the downcasted uint96 from uint256, reverting on * overflow (when the input is greater than largest uint96). * * Counterpart to Solidity's `uint96` operator. * * Requirements: * * - input must fit into 96 bits */ function toUint96(uint256 value) internal pure returns (uint96) { if (value > type(uint96).max) { revert SafeCastOverflowedUintDowncast(96, value); } return uint96(value); } /** * @dev Returns the downcasted uint88 from uint256, reverting on * overflow (when the input is greater than largest uint88). * * Counterpart to Solidity's `uint88` operator. * * Requirements: * * - input must fit into 88 bits */ function toUint88(uint256 value) internal pure returns (uint88) { if (value > type(uint88).max) { revert SafeCastOverflowedUintDowncast(88, value); } return uint88(value); } /** * @dev Returns the downcasted uint80 from uint256, reverting on * overflow (when the input is greater than largest uint80). * * Counterpart to Solidity's `uint80` operator. * * Requirements: * * - input must fit into 80 bits */ function toUint80(uint256 value) internal pure returns (uint80) { if (value > type(uint80).max) { revert SafeCastOverflowedUintDowncast(80, value); } return uint80(value); } /** * @dev Returns the downcasted uint72 from uint256, reverting on * overflow (when the input is greater than largest uint72). * * Counterpart to Solidity's `uint72` operator. * * Requirements: * * - input must fit into 72 bits */ function toUint72(uint256 value) internal pure returns (uint72) { if (value > type(uint72).max) { revert SafeCastOverflowedUintDowncast(72, value); } return uint72(value); } /** * @dev Returns the downcasted uint64 from uint256, reverting on * overflow (when the input is greater than largest uint64). * * Counterpart to Solidity's `uint64` operator. * * Requirements: * * - input must fit into 64 bits */ function toUint64(uint256 value) internal pure returns (uint64) { if (value > type(uint64).max) { revert SafeCastOverflowedUintDowncast(64, value); } return uint64(value); } /** * @dev Returns the downcasted uint56 from uint256, reverting on * overflow (when the input is greater than largest uint56). * * Counterpart to Solidity's `uint56` operator. * * Requirements: * * - input must fit into 56 bits */ function toUint56(uint256 value) internal pure returns (uint56) { if (value > type(uint56).max) { revert SafeCastOverflowedUintDowncast(56, value); } return uint56(value); } /** * @dev Returns the downcasted uint48 from uint256, reverting on * overflow (when the input is greater than largest uint48). * * Counterpart to Solidity's `uint48` operator. * * Requirements: * * - input must fit into 48 bits */ function toUint48(uint256 value) internal pure returns (uint48) { if (value > type(uint48).max) { revert SafeCastOverflowedUintDowncast(48, value); } return uint48(value); } /** * @dev Returns the downcasted uint40 from uint256, reverting on * overflow (when the input is greater than largest uint40). * * Counterpart to Solidity's `uint40` operator. * * Requirements: * * - input must fit into 40 bits */ function toUint40(uint256 value) internal pure returns (uint40) { if (value > type(uint40).max) { revert SafeCastOverflowedUintDowncast(40, value); } return uint40(value); } /** * @dev Returns the downcasted uint32 from uint256, reverting on * overflow (when the input is greater than largest uint32). * * Counterpart to Solidity's `uint32` operator. * * Requirements: * * - input must fit into 32 bits */ function toUint32(uint256 value) internal pure returns (uint32) { if (value > type(uint32).max) { revert SafeCastOverflowedUintDowncast(32, value); } return uint32(value); } /** * @dev Returns the downcasted uint24 from uint256, reverting on * overflow (when the input is greater than largest uint24). * * Counterpart to Solidity's `uint24` operator. * * Requirements: * * - input must fit into 24 bits */ function toUint24(uint256 value) internal pure returns (uint24) { if (value > type(uint24).max) { revert SafeCastOverflowedUintDowncast(24, value); } return uint24(value); } /** * @dev Returns the downcasted uint16 from uint256, reverting on * overflow (when the input is greater than largest uint16). * * Counterpart to Solidity's `uint16` operator. * * Requirements: * * - input must fit into 16 bits */ function toUint16(uint256 value) internal pure returns (uint16) { if (value > type(uint16).max) { revert SafeCastOverflowedUintDowncast(16, value); } return uint16(value); } /** * @dev Returns the downcasted uint8 from uint256, reverting on * overflow (when the input is greater than largest uint8). * * Counterpart to Solidity's `uint8` operator. * * Requirements: * * - input must fit into 8 bits */ function toUint8(uint256 value) internal pure returns (uint8) { if (value > type(uint8).max) { revert SafeCastOverflowedUintDowncast(8, value); } return uint8(value); } /** * @dev Converts a signed int256 into an unsigned uint256. * * Requirements: * * - input must be greater than or equal to 0. */ function toUint256(int256 value) internal pure returns (uint256) { if (value < 0) { revert SafeCastOverflowedIntToUint(value); } return uint256(value); } /** * @dev Returns the downcasted int248 from int256, reverting on * overflow (when the input is less than smallest int248 or * greater than largest int248). * * Counterpart to Solidity's `int248` operator. * * Requirements: * * - input must fit into 248 bits */ function toInt248(int256 value) internal pure returns (int248 downcasted) { downcasted = int248(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(248, value); } } /** * @dev Returns the downcasted int240 from int256, reverting on * overflow (when the input is less than smallest int240 or * greater than largest int240). * * Counterpart to Solidity's `int240` operator. * * Requirements: * * - input must fit into 240 bits */ function toInt240(int256 value) internal pure returns (int240 downcasted) { downcasted = int240(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(240, value); } } /** * @dev Returns the downcasted int232 from int256, reverting on * overflow (when the input is less than smallest int232 or * greater than largest int232). * * Counterpart to Solidity's `int232` operator. * * Requirements: * * - input must fit into 232 bits */ function toInt232(int256 value) internal pure returns (int232 downcasted) { downcasted = int232(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(232, value); } } /** * @dev Returns the downcasted int224 from int256, reverting on * overflow (when the input is less than smallest int224 or * greater than largest int224). * * Counterpart to Solidity's `int224` operator. * * Requirements: * * - input must fit into 224 bits */ function toInt224(int256 value) internal pure returns (int224 downcasted) { downcasted = int224(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(224, value); } } /** * @dev Returns the downcasted int216 from int256, reverting on * overflow (when the input is less than smallest int216 or * greater than largest int216). * * Counterpart to Solidity's `int216` operator. * * Requirements: * * - input must fit into 216 bits */ function toInt216(int256 value) internal pure returns (int216 downcasted) { downcasted = int216(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(216, value); } } /** * @dev Returns the downcasted int208 from int256, reverting on * overflow (when the input is less than smallest int208 or * greater than largest int208). * * Counterpart to Solidity's `int208` operator. * * Requirements: * * - input must fit into 208 bits */ function toInt208(int256 value) internal pure returns (int208 downcasted) { downcasted = int208(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(208, value); } } /** * @dev Returns the downcasted int200 from int256, reverting on * overflow (when the input is less than smallest int200 or * greater than largest int200). * * Counterpart to Solidity's `int200` operator. * * Requirements: * * - input must fit into 200 bits */ function toInt200(int256 value) internal pure returns (int200 downcasted) { downcasted = int200(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(200, value); } } /** * @dev Returns the downcasted int192 from int256, reverting on * overflow (when the input is less than smallest int192 or * greater than largest int192). * * Counterpart to Solidity's `int192` operator. * * Requirements: * * - input must fit into 192 bits */ function toInt192(int256 value) internal pure returns (int192 downcasted) { downcasted = int192(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(192, value); } } /** * @dev Returns the downcasted int184 from int256, reverting on * overflow (when the input is less than smallest int184 or * greater than largest int184). * * Counterpart to Solidity's `int184` operator. * * Requirements: * * - input must fit into 184 bits */ function toInt184(int256 value) internal pure returns (int184 downcasted) { downcasted = int184(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(184, value); } } /** * @dev Returns the downcasted int176 from int256, reverting on * overflow (when the input is less than smallest int176 or * greater than largest int176). * * Counterpart to Solidity's `int176` operator. * * Requirements: * * - input must fit into 176 bits */ function toInt176(int256 value) internal pure returns (int176 downcasted) { downcasted = int176(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(176, value); } } /** * @dev Returns the downcasted int168 from int256, reverting on * overflow (when the input is less than smallest int168 or * greater than largest int168). * * Counterpart to Solidity's `int168` operator. * * Requirements: * * - input must fit into 168 bits */ function toInt168(int256 value) internal pure returns (int168 downcasted) { downcasted = int168(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(168, value); } } /** * @dev Returns the downcasted int160 from int256, reverting on * overflow (when the input is less than smallest int160 or * greater than largest int160). * * Counterpart to Solidity's `int160` operator. * * Requirements: * * - input must fit into 160 bits */ function toInt160(int256 value) internal pure returns (int160 downcasted) { downcasted = int160(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(160, value); } } /** * @dev Returns the downcasted int152 from int256, reverting on * overflow (when the input is less than smallest int152 or * greater than largest int152). * * Counterpart to Solidity's `int152` operator. * * Requirements: * * - input must fit into 152 bits */ function toInt152(int256 value) internal pure returns (int152 downcasted) { downcasted = int152(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(152, value); } } /** * @dev Returns the downcasted int144 from int256, reverting on * overflow (when the input is less than smallest int144 or * greater than largest int144). * * Counterpart to Solidity's `int144` operator. * * Requirements: * * - input must fit into 144 bits */ function toInt144(int256 value) internal pure returns (int144 downcasted) { downcasted = int144(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(144, value); } } /** * @dev Returns the downcasted int136 from int256, reverting on * overflow (when the input is less than smallest int136 or * greater than largest int136). * * Counterpart to Solidity's `int136` operator. * * Requirements: * * - input must fit into 136 bits */ function toInt136(int256 value) internal pure returns (int136 downcasted) { downcasted = int136(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(136, value); } } /** * @dev Returns the downcasted int128 from int256, reverting on * overflow (when the input is less than smallest int128 or * greater than largest int128). * * Counterpart to Solidity's `int128` operator. * * Requirements: * * - input must fit into 128 bits */ function toInt128(int256 value) internal pure returns (int128 downcasted) { downcasted = int128(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(128, value); } } /** * @dev Returns the downcasted int120 from int256, reverting on * overflow (when the input is less than smallest int120 or * greater than largest int120). * * Counterpart to Solidity's `int120` operator. * * Requirements: * * - input must fit into 120 bits */ function toInt120(int256 value) internal pure returns (int120 downcasted) { downcasted = int120(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(120, value); } } /** * @dev Returns the downcasted int112 from int256, reverting on * overflow (when the input is less than smallest int112 or * greater than largest int112). * * Counterpart to Solidity's `int112` operator. * * Requirements: * * - input must fit into 112 bits */ function toInt112(int256 value) internal pure returns (int112 downcasted) { downcasted = int112(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(112, value); } } /** * @dev Returns the downcasted int104 from int256, reverting on * overflow (when the input is less than smallest int104 or * greater than largest int104). * * Counterpart to Solidity's `int104` operator. * * Requirements: * * - input must fit into 104 bits */ function toInt104(int256 value) internal pure returns (int104 downcasted) { downcasted = int104(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(104, value); } } /** * @dev Returns the downcasted int96 from int256, reverting on * overflow (when the input is less than smallest int96 or * greater than largest int96). * * Counterpart to Solidity's `int96` operator. * * Requirements: * * - input must fit into 96 bits */ function toInt96(int256 value) internal pure returns (int96 downcasted) { downcasted = int96(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(96, value); } } /** * @dev Returns the downcasted int88 from int256, reverting on * overflow (when the input is less than smallest int88 or * greater than largest int88). * * Counterpart to Solidity's `int88` operator. * * Requirements: * * - input must fit into 88 bits */ function toInt88(int256 value) internal pure returns (int88 downcasted) { downcasted = int88(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(88, value); } } /** * @dev Returns the downcasted int80 from int256, reverting on * overflow (when the input is less than smallest int80 or * greater than largest int80). * * Counterpart to Solidity's `int80` operator. * * Requirements: * * - input must fit into 80 bits */ function toInt80(int256 value) internal pure returns (int80 downcasted) { downcasted = int80(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(80, value); } } /** * @dev Returns the downcasted int72 from int256, reverting on * overflow (when the input is less than smallest int72 or * greater than largest int72). * * Counterpart to Solidity's `int72` operator. * * Requirements: * * - input must fit into 72 bits */ function toInt72(int256 value) internal pure returns (int72 downcasted) { downcasted = int72(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(72, value); } } /** * @dev Returns the downcasted int64 from int256, reverting on * overflow (when the input is less than smallest int64 or * greater than largest int64). * * Counterpart to Solidity's `int64` operator. * * Requirements: * * - input must fit into 64 bits */ function toInt64(int256 value) internal pure returns (int64 downcasted) { downcasted = int64(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(64, value); } } /** * @dev Returns the downcasted int56 from int256, reverting on * overflow (when the input is less than smallest int56 or * greater than largest int56). * * Counterpart to Solidity's `int56` operator. * * Requirements: * * - input must fit into 56 bits */ function toInt56(int256 value) internal pure returns (int56 downcasted) { downcasted = int56(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(56, value); } } /** * @dev Returns the downcasted int48 from int256, reverting on * overflow (when the input is less than smallest int48 or * greater than largest int48). * * Counterpart to Solidity's `int48` operator. * * Requirements: * * - input must fit into 48 bits */ function toInt48(int256 value) internal pure returns (int48 downcasted) { downcasted = int48(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(48, value); } } /** * @dev Returns the downcasted int40 from int256, reverting on * overflow (when the input is less than smallest int40 or * greater than largest int40). * * Counterpart to Solidity's `int40` operator. * * Requirements: * * - input must fit into 40 bits */ function toInt40(int256 value) internal pure returns (int40 downcasted) { downcasted = int40(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(40, value); } } /** * @dev Returns the downcasted int32 from int256, reverting on * overflow (when the input is less than smallest int32 or * greater than largest int32). * * Counterpart to Solidity's `int32` operator. * * Requirements: * * - input must fit into 32 bits */ function toInt32(int256 value) internal pure returns (int32 downcasted) { downcasted = int32(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(32, value); } } /** * @dev Returns the downcasted int24 from int256, reverting on * overflow (when the input is less than smallest int24 or * greater than largest int24). * * Counterpart to Solidity's `int24` operator. * * Requirements: * * - input must fit into 24 bits */ function toInt24(int256 value) internal pure returns (int24 downcasted) { downcasted = int24(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(24, value); } } /** * @dev Returns the downcasted int16 from int256, reverting on * overflow (when the input is less than smallest int16 or * greater than largest int16). * * Counterpart to Solidity's `int16` operator. * * Requirements: * * - input must fit into 16 bits */ function toInt16(int256 value) internal pure returns (int16 downcasted) { downcasted = int16(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(16, value); } } /** * @dev Returns the downcasted int8 from int256, reverting on * overflow (when the input is less than smallest int8 or * greater than largest int8). * * Counterpart to Solidity's `int8` operator. * * Requirements: * * - input must fit into 8 bits */ function toInt8(int256 value) internal pure returns (int8 downcasted) { downcasted = int8(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(8, value); } } /** * @dev Converts an unsigned uint256 into a signed int256. * * Requirements: * * - input must be less than or equal to maxInt256. */ function toInt256(uint256 value) internal pure returns (int256) { // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive if (value > uint256(type(int256).max)) { revert SafeCastOverflowedUintToInt(value); } return int256(value); } /** * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump. */ function toUint(bool b) internal pure returns (uint256 u) { assembly ("memory-safe") { u := iszero(iszero(b)) } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import { Origin } from "./ILayerZeroEndpointV2.sol"; interface ILayerZeroReceiver { function allowInitializePath(Origin calldata _origin) external view returns (bool); function nextNonce(uint32 _eid, bytes32 _sender) external view returns (uint64); function lzReceive( Origin calldata _origin, bytes32 _guid, bytes calldata _message, address _executor, bytes calldata _extraData ) external payable; }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; interface IMessagingChannel { event InboundNonceSkipped(uint32 srcEid, bytes32 sender, address receiver, uint64 nonce); event PacketNilified(uint32 srcEid, bytes32 sender, address receiver, uint64 nonce, bytes32 payloadHash); event PacketBurnt(uint32 srcEid, bytes32 sender, address receiver, uint64 nonce, bytes32 payloadHash); function eid() external view returns (uint32); // this is an emergency function if a message cannot be verified for some reasons // required to provide _nextNonce to avoid race condition function skip(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce) external; function nilify(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce, bytes32 _payloadHash) external; function burn(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce, bytes32 _payloadHash) external; function nextGuid(address _sender, uint32 _dstEid, bytes32 _receiver) external view returns (bytes32); function inboundNonce(address _receiver, uint32 _srcEid, bytes32 _sender) external view returns (uint64); function outboundNonce(address _sender, uint32 _dstEid, bytes32 _receiver) external view returns (uint64); function inboundPayloadHash( address _receiver, uint32 _srcEid, bytes32 _sender, uint64 _nonce ) external view returns (bytes32); function lazyInboundNonce(address _receiver, uint32 _srcEid, bytes32 _sender) external view returns (uint64); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import { IMessageLibManager } from "./IMessageLibManager.sol"; import { IMessagingComposer } from "./IMessagingComposer.sol"; import { IMessagingChannel } from "./IMessagingChannel.sol"; import { IMessagingContext } from "./IMessagingContext.sol"; struct MessagingParams { uint32 dstEid; bytes32 receiver; bytes message; bytes options; bool payInLzToken; } struct MessagingReceipt { bytes32 guid; uint64 nonce; MessagingFee fee; } struct MessagingFee { uint256 nativeFee; uint256 lzTokenFee; } struct Origin { uint32 srcEid; bytes32 sender; uint64 nonce; } interface ILayerZeroEndpointV2 is IMessageLibManager, IMessagingComposer, IMessagingChannel, IMessagingContext { event PacketSent(bytes encodedPayload, bytes options, address sendLibrary); event PacketVerified(Origin origin, address receiver, bytes32 payloadHash); event PacketDelivered(Origin origin, address receiver); event LzReceiveAlert( address indexed receiver, address indexed executor, Origin origin, bytes32 guid, uint256 gas, uint256 value, bytes message, bytes extraData, bytes reason ); event LzTokenSet(address token); event DelegateSet(address sender, address delegate); function quote(MessagingParams calldata _params, address _sender) external view returns (MessagingFee memory); function send( MessagingParams calldata _params, address _refundAddress ) external payable returns (MessagingReceipt memory); function verify(Origin calldata _origin, address _receiver, bytes32 _payloadHash) external; function verifiable(Origin calldata _origin, address _receiver) external view returns (bool); function initializable(Origin calldata _origin, address _receiver) external view returns (bool); function lzReceive( Origin calldata _origin, address _receiver, bytes32 _guid, bytes calldata _message, bytes calldata _extraData ) external payable; // oapp can burn messages partially by calling this function with its own business logic if messages are verified in order function clear(address _oapp, Origin calldata _origin, bytes32 _guid, bytes calldata _message) external; function setLzToken(address _lzToken) external; function lzToken() external view returns (address); function nativeToken() external view returns (address); function setDelegate(address _delegate) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; // @dev Import the 'MessagingFee' and 'MessagingReceipt' so it's exposed to OApp implementers // solhint-disable-next-line no-unused-import import {OAppAuthSender, MessagingFee, MessagingReceipt} from "./OAppAuthSender.sol"; // @dev Import the 'Origin' so it's exposed to OApp implementers // solhint-disable-next-line no-unused-import import {OAppAuthReceiver, Origin} from "./OAppAuthReceiver.sol"; import {OAppAuthCore} from "./OAppAuthCore.sol"; /** * @title OApp * @dev Abstract contract serving as the base for OApp implementation, combining OAppSender and OAppReceiver functionality. */ abstract contract OAppAuth is OAppAuthSender, OAppAuthReceiver { /** * @dev Constructor to initialize the OApp with the provided endpoint and owner. * @param _endpoint The address of the LOCAL LayerZero endpoint. * @param _delegate The delegate capable of making OApp configurations inside of the endpoint. */ constructor(address _endpoint, address _delegate) OAppAuthCore(_endpoint, _delegate) {} /** * @notice Retrieves the OApp version information. * @return senderVersion The version of the OAppSender.sol implementation. * @return receiverVersion The version of the OAppReceiver.sol implementation. */ function oAppVersion() public pure virtual override(OAppAuthSender, OAppAuthReceiver) returns (uint64 senderVersion, uint64 receiverVersion) { return (SENDER_VERSION, RECEIVER_VERSION); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.21; import {TellerWithMultiAssetSupport, ERC20} from "../../../../src/base/Roles/TellerWithMultiAssetSupport.sol"; import {MessageLib} from "../../../../src/base/Roles/CrossChain/MessageLib.sol"; abstract contract CrossChainTellerWithGenericBridge is TellerWithMultiAssetSupport { using MessageLib for uint256; using MessageLib for MessageLib.Message; //============================== ERRORS =============================== error CrossChainTellerWithGenericBridge__UnsafeCastToUint96(); //============================== EVENTS =============================== event MessageSent(bytes32 indexed messageId, uint256 shareAmount, address indexed to); event MessageReceived(bytes32 indexed messageId, uint256 shareAmount, address indexed to); //============================== IMMUTABLES =============================== constructor(address _owner, address _vault, address _accountant, address _weth) TellerWithMultiAssetSupport(_owner, _vault, _accountant, _weth) {} // ========================================= PUBLIC FUNCTIONS ========================================= /** * @notice Deposit an asset and bridge the shares to another chain. * @dev This function will REVERT if `beforeTransfer` hook reverts from: * - shares being locked * - allow list * @dev Since call to `bridge` is public, msg.sig is not updated which means any role capabilities regarding this function * are also granted to the `bridge` function. */ function depositAndBridge( ERC20 depositAsset, uint256 depositAmount, uint256 minimumMint, address to, bytes calldata bridgeWildCard, ERC20 feeToken, uint256 maxFee ) external payable requiresAuth nonReentrant revertOnNativeDeposit(address(depositAsset)) returns (uint256 sharesBridged) { // Deposit Asset memory asset = _beforeDeposit(depositAsset); sharesBridged = _erc20Deposit(depositAsset, depositAmount, minimumMint, msg.sender, msg.sender, asset); _afterPublicDeposit(msg.sender, depositAsset, depositAmount, sharesBridged, shareLockPeriod); // Bridge shares if (sharesBridged > type(uint96).max) revert CrossChainTellerWithGenericBridge__UnsafeCastToUint96(); _bridge(uint96(sharesBridged), to, bridgeWildCard, feeToken, maxFee); } /** * @notice Deposit an asset and bridge the shares to another chain using a permit. * @dev This function will REVERT if `beforeTransfer` hook reverts from: * - shares being locked * - allow list * @dev Since calls to `depositWithPermit` and `bridge` are public, msg.sig is not updated which means any role capabilities regarding this function * are also granted to the `depositWithPermit` and `bridge` function. */ function depositAndBridgeWithPermit( ERC20 depositAsset, uint256 depositAmount, uint256 minimumMint, uint256 deadline, uint8 v, bytes32 r, bytes32 s, address to, bytes calldata bridgeWildCard, ERC20 feeToken, uint256 maxFee ) external payable requiresAuth nonReentrant revertOnNativeDeposit(address(depositAsset)) returns (uint256 sharesBridged) { // Permit deposit { Asset memory asset = _beforeDeposit(depositAsset); _handlePermit(depositAsset, depositAmount, deadline, v, r, s); sharesBridged = _erc20Deposit(depositAsset, depositAmount, minimumMint, msg.sender, msg.sender, asset); } _afterPublicDeposit(msg.sender, depositAsset, depositAmount, sharesBridged, shareLockPeriod); // Bridge shares if (sharesBridged > type(uint96).max) revert CrossChainTellerWithGenericBridge__UnsafeCastToUint96(); _bridge(uint96(sharesBridged), to, bridgeWildCard, feeToken, maxFee); } /** * @notice Bridge shares to another chain. * @param shareAmount The amount of shares to bridge. * @param to The address to send the shares to on the other chain. * @param bridgeWildCard The bridge specific data to configure message. * @param feeToken The token to pay the bridge fee in. * @param maxFee The maximum fee to pay the bridge. */ function bridge(uint96 shareAmount, address to, bytes calldata bridgeWildCard, ERC20 feeToken, uint256 maxFee) external payable requiresAuth nonReentrant { if (isPaused) revert TellerWithMultiAssetSupport__Paused(); _bridge(shareAmount, to, bridgeWildCard, feeToken, maxFee); } /** * @notice Preview fee required to bridge shares in a given feeToken. */ function previewFee(uint96 shareAmount, address to, bytes calldata bridgeWildCard, ERC20 feeToken) external view returns (uint256 fee) { MessageLib.Message memory m = MessageLib.Message(shareAmount, to); uint256 message = m.messageToUint256(); return _previewFee(message, bridgeWildCard, feeToken); } // ========================================= INTERNAL BRIDGE FUNCTIONS ========================================= /** * @notice Implement the bridge logic. */ function _bridge(uint96 shareAmount, address to, bytes calldata bridgeWildCard, ERC20 feeToken, uint256 maxFee) internal { // Since shares are directly burned, call `beforeTransfer` to enforce before transfer hooks. beforeTransfer(msg.sender, address(0), msg.sender); // Burn shares from sender vault.exit(address(0), ERC20(address(0)), 0, msg.sender, shareAmount); // Send the message. MessageLib.Message memory m = MessageLib.Message(shareAmount, to); // `messageToUnit256` reverts on overflow, eventhough it is not possible to overflow. // This was done for future proofing. uint256 message = m.messageToUint256(); bytes32 messageId = _sendMessage(message, bridgeWildCard, feeToken, maxFee); emit MessageSent(messageId, shareAmount, to); } /** * @notice Complete the message receive process, should be called in child contract once * message has been confirmed as legit.` */ function _completeMessageReceive(bytes32 messageId, uint256 message) internal { MessageLib.Message memory m = message.uint256ToMessage(); // Mint shares to message.to vault.enter(address(0), ERC20(address(0)), 0, m.to, m.shareAmount); emit MessageReceived(messageId, m.shareAmount, m.to); } /** * @notice Send the message to the bridge implementation. * @dev This function should handle reverting if maxFee exceeds the fee required to send the message. * @dev This function should handle collecting the fee. * @param message The message to send. * @param bridgeWildCard The bridge specific data to configure message. * @param feeToken The token to pay the bridge fee in. * @param maxFee The maximum fee to pay the bridge. */ function _sendMessage(uint256 message, bytes calldata bridgeWildCard, ERC20 feeToken, uint256 maxFee) internal virtual returns (bytes32 messageId); /** * @notice Preview fee required to bridge shares in a given token. */ function _previewFee(uint256 message, bytes calldata bridgeWildCard, ERC20 feeToken) internal view virtual returns (uint256 fee); }
// SPDX-License-Identifier: Unlicense /* * @title Solidity Bytes Arrays Utils * @author Gonçalo Sá <[email protected]> * * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity. * The library lets you concatenate, slice and type cast bytes arrays both in memory and storage. */ pragma solidity >=0.8.0 <0.9.0; library BytesLib { function concat( bytes memory _preBytes, bytes memory _postBytes ) internal pure returns (bytes memory) { bytes memory tempBytes; assembly { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // Store the length of the first bytes array at the beginning of // the memory for tempBytes. let length := mload(_preBytes) mstore(tempBytes, length) // Maintain a memory counter for the current write location in the // temp bytes array by adding the 32 bytes for the array length to // the starting location. let mc := add(tempBytes, 0x20) // Stop copying when the memory counter reaches the length of the // first bytes array. let end := add(mc, length) for { // Initialize a copy counter to the start of the _preBytes data, // 32 bytes into its memory. let cc := add(_preBytes, 0x20) } lt(mc, end) { // Increase both counters by 32 bytes each iteration. mc := add(mc, 0x20) cc := add(cc, 0x20) } { // Write the _preBytes data into the tempBytes memory 32 bytes // at a time. mstore(mc, mload(cc)) } // Add the length of _postBytes to the current length of tempBytes // and store it as the new length in the first 32 bytes of the // tempBytes memory. length := mload(_postBytes) mstore(tempBytes, add(length, mload(tempBytes))) // Move the memory counter back from a multiple of 0x20 to the // actual end of the _preBytes data. mc := end // Stop copying when the memory counter reaches the new combined // length of the arrays. end := add(mc, length) for { let cc := add(_postBytes, 0x20) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } // Update the free-memory pointer by padding our last write location // to 32 bytes: add 31 bytes to the end of tempBytes to move to the // next 32 byte block, then round down to the nearest multiple of // 32. If the sum of the length of the two arrays is zero then add // one before rounding down to leave a blank 32 bytes (the length block with 0). mstore(0x40, and( add(add(end, iszero(add(length, mload(_preBytes)))), 31), not(31) // Round down to the nearest 32 bytes. )) } return tempBytes; } function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal { assembly { // Read the first 32 bytes of _preBytes storage, which is the length // of the array. (We don't need to use the offset into the slot // because arrays use the entire slot.) let fslot := sload(_preBytes.slot) // Arrays of 31 bytes or less have an even value in their slot, // while longer arrays have an odd value. The actual length is // the slot divided by two for odd values, and the lowest order // byte divided by two for even values. // If the slot is even, bitwise and the slot with 255 and divide by // two to get the length. If the slot is odd, bitwise and the slot // with -1 and divide by two. let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2) let mlength := mload(_postBytes) let newlength := add(slength, mlength) // slength can contain both the length and contents of the array // if length < 32 bytes so let's prepare for that // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage switch add(lt(slength, 32), lt(newlength, 32)) case 2 { // Since the new array still fits in the slot, we just need to // update the contents of the slot. // uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length sstore( _preBytes.slot, // all the modifications to the slot are inside this // next block add( // we can just add to the slot contents because the // bytes we want to change are the LSBs fslot, add( mul( div( // load the bytes from memory mload(add(_postBytes, 0x20)), // zero all bytes to the right exp(0x100, sub(32, mlength)) ), // and now shift left the number of bytes to // leave space for the length in the slot exp(0x100, sub(32, newlength)) ), // increase length by the double of the memory // bytes length mul(mlength, 2) ) ) ) } case 1 { // The stored value fits in the slot, but the combined value // will exceed it. // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) let sc := add(keccak256(0x0, 0x20), div(slength, 32)) // save new length sstore(_preBytes.slot, add(mul(newlength, 2), 1)) // The contents of the _postBytes array start 32 bytes into // the structure. Our first read should obtain the `submod` // bytes that can fit into the unused space in the last word // of the stored array. To get this, we read 32 bytes starting // from `submod`, so the data we read overlaps with the array // contents by `submod` bytes. Masking the lowest-order // `submod` bytes allows us to add that value directly to the // stored value. let submod := sub(32, slength) let mc := add(_postBytes, submod) let end := add(_postBytes, mlength) let mask := sub(exp(0x100, submod), 1) sstore( sc, add( and( fslot, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00 ), and(mload(mc), mask) ) ) for { mc := add(mc, 0x20) sc := add(sc, 1) } lt(mc, end) { sc := add(sc, 1) mc := add(mc, 0x20) } { sstore(sc, mload(mc)) } mask := exp(0x100, sub(mc, end)) sstore(sc, mul(div(mload(mc), mask), mask)) } default { // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) // Start copying to the last used word of the stored array. let sc := add(keccak256(0x0, 0x20), div(slength, 32)) // save new length sstore(_preBytes.slot, add(mul(newlength, 2), 1)) // Copy over the first `submod` bytes of the new data as in // case 1 above. let slengthmod := mod(slength, 32) let mlengthmod := mod(mlength, 32) let submod := sub(32, slengthmod) let mc := add(_postBytes, submod) let end := add(_postBytes, mlength) let mask := sub(exp(0x100, submod), 1) sstore(sc, add(sload(sc), and(mload(mc), mask))) for { sc := add(sc, 1) mc := add(mc, 0x20) } lt(mc, end) { sc := add(sc, 1) mc := add(mc, 0x20) } { sstore(sc, mload(mc)) } mask := exp(0x100, sub(mc, end)) sstore(sc, mul(div(mload(mc), mask), mask)) } } } function slice( bytes memory _bytes, uint256 _start, uint256 _length ) internal pure returns (bytes memory) { require(_length + 31 >= _length, "slice_overflow"); require(_bytes.length >= _start + _length, "slice_outOfBounds"); bytes memory tempBytes; assembly { switch iszero(_length) case 0 { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // The first word of the slice result is potentially a partial // word read from the original array. To read it, we calculate // the length of that partial word and start copying that many // bytes into the array. The first word we copy will start with // data we don't care about, but the last `lengthmod` bytes will // land at the beginning of the contents of the new array. When // we're done copying, we overwrite the full first word with // the actual length of the slice. let lengthmod := and(_length, 31) // The multiplication in the next line is necessary // because when slicing multiples of 32 bytes (lengthmod == 0) // the following copy loop was copying the origin's length // and then ending prematurely not copying everything it should. let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod))) let end := add(mc, _length) for { // The multiplication in the next line has the same exact purpose // as the one above. let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } mstore(tempBytes, _length) //update free-memory pointer //allocating the array padded to 32 bytes like the compiler does now mstore(0x40, and(add(mc, 31), not(31))) } //if we want a zero-length slice let's just return a zero-length array default { tempBytes := mload(0x40) //zero out the 32 bytes slice we are about to return //we need to do it because Solidity does not garbage collect mstore(tempBytes, 0) mstore(0x40, add(tempBytes, 0x20)) } } return tempBytes; } function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) { require(_bytes.length >= _start + 20, "toAddress_outOfBounds"); address tempAddress; assembly { tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000) } return tempAddress; } function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) { require(_bytes.length >= _start + 1 , "toUint8_outOfBounds"); uint8 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x1), _start)) } return tempUint; } function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) { require(_bytes.length >= _start + 2, "toUint16_outOfBounds"); uint16 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x2), _start)) } return tempUint; } function toUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) { require(_bytes.length >= _start + 4, "toUint32_outOfBounds"); uint32 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x4), _start)) } return tempUint; } function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) { require(_bytes.length >= _start + 8, "toUint64_outOfBounds"); uint64 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x8), _start)) } return tempUint; } function toUint96(bytes memory _bytes, uint256 _start) internal pure returns (uint96) { require(_bytes.length >= _start + 12, "toUint96_outOfBounds"); uint96 tempUint; assembly { tempUint := mload(add(add(_bytes, 0xc), _start)) } return tempUint; } function toUint128(bytes memory _bytes, uint256 _start) internal pure returns (uint128) { require(_bytes.length >= _start + 16, "toUint128_outOfBounds"); uint128 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x10), _start)) } return tempUint; } function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) { require(_bytes.length >= _start + 32, "toUint256_outOfBounds"); uint256 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x20), _start)) } return tempUint; } function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) { require(_bytes.length >= _start + 32, "toBytes32_outOfBounds"); bytes32 tempBytes32; assembly { tempBytes32 := mload(add(add(_bytes, 0x20), _start)) } return tempBytes32; } function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) { bool success = true; assembly { let length := mload(_preBytes) // if lengths don't match the arrays are not equal switch eq(length, mload(_postBytes)) case 1 { // cb is a circuit breaker in the for loop since there's // no said feature for inline assembly loops // cb = 1 - don't breaker // cb = 0 - break let cb := 1 let mc := add(_preBytes, 0x20) let end := add(mc, length) for { let cc := add(_postBytes, 0x20) // the next line is the loop condition: // while(uint256(mc < end) + cb == 2) } eq(add(lt(mc, end), cb), 2) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { // if any of these checks fails then arrays are not equal if iszero(eq(mload(mc), mload(cc))) { // unsuccess: success := 0 cb := 0 } } } default { // unsuccess: success := 0 } } return success; } function equal_nonAligned(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) { bool success = true; assembly { let length := mload(_preBytes) // if lengths don't match the arrays are not equal switch eq(length, mload(_postBytes)) case 1 { // cb is a circuit breaker in the for loop since there's // no said feature for inline assembly loops // cb = 1 - don't breaker // cb = 0 - break let cb := 1 let endMinusWord := add(_preBytes, length) let mc := add(_preBytes, 0x20) let cc := add(_postBytes, 0x20) for { // the next line is the loop condition: // while(uint256(mc < endWord) + cb == 2) } eq(add(lt(mc, endMinusWord), cb), 2) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { // if any of these checks fails then arrays are not equal if iszero(eq(mload(mc), mload(cc))) { // unsuccess: success := 0 cb := 0 } } // Only if still successful // For <1 word tail bytes if gt(success, 0) { // Get the remainder of length/32 // length % 32 = AND(length, 32 - 1) let numTailBytes := and(length, 0x1f) let mcRem := mload(mc) let ccRem := mload(cc) for { let i := 0 // the next line is the loop condition: // while(uint256(i < numTailBytes) + cb == 2) } eq(add(lt(i, numTailBytes), cb), 2) { i := add(i, 1) } { if iszero(eq(byte(i, mcRem), byte(i, ccRem))) { // unsuccess: success := 0 cb := 0 } } } } default { // unsuccess: success := 0 } } return success; } function equalStorage( bytes storage _preBytes, bytes memory _postBytes ) internal view returns (bool) { bool success = true; assembly { // we know _preBytes_offset is 0 let fslot := sload(_preBytes.slot) // Decode the length of the stored array like in concatStorage(). let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2) let mlength := mload(_postBytes) // if lengths don't match the arrays are not equal switch eq(slength, mlength) case 1 { // slength can contain both the length and contents of the array // if length < 32 bytes so let's prepare for that // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage if iszero(iszero(slength)) { switch lt(slength, 32) case 1 { // blank the last byte which is the length fslot := mul(div(fslot, 0x100), 0x100) if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) { // unsuccess: success := 0 } } default { // cb is a circuit breaker in the for loop since there's // no said feature for inline assembly loops // cb = 1 - don't breaker // cb = 0 - break let cb := 1 // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) let sc := keccak256(0x0, 0x20) let mc := add(_postBytes, 0x20) let end := add(mc, mlength) // the next line is the loop condition: // while(uint256(mc < end) + cb == 2) for {} eq(add(lt(mc, end), cb), 2) { sc := add(sc, 1) mc := add(mc, 0x20) } { if iszero(eq(sload(sc), mload(mc))) { // unsuccess: success := 0 cb := 0 } } } } } default { // unsuccess: success := 0 } } return success; } }
// SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.0; library AddressToBytes32Lib { function toBytes32(address addressValue) internal pure returns (bytes32) { return bytes32(uint256(uint160(addressValue))); } function toAddress(bytes32 bytes32Value) internal pure returns (address) { return address(bytes20(bytes32Value << 96)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import {SafeTransferLib, ERC20} from "@solmate/utils/SafeTransferLib.sol"; import { MessagingParams, MessagingFee, MessagingReceipt } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol"; import {OAppAuthCore} from "./OAppAuthCore.sol"; /** * @title OAppSender * @dev Abstract contract implementing the OAppSender functionality for sending messages to a LayerZero endpoint. */ abstract contract OAppAuthSender is OAppAuthCore { using SafeTransferLib for ERC20; // Custom error messages error NotEnoughNative(uint256 msgValue); error LzTokenUnavailable(); // @dev The version of the OAppSender implementation. // @dev Version is bumped when changes are made to this contract. uint64 internal constant SENDER_VERSION = 1; /** * @notice Retrieves the OApp version information. * @return senderVersion The version of the OAppSender.sol contract. * @return receiverVersion The version of the OAppReceiver.sol contract. * * @dev Providing 0 as the default for OAppReceiver version. Indicates that the OAppReceiver is not implemented. * ie. this is a SEND only OApp. * @dev If the OApp uses both OAppSender and OAppReceiver, then this needs to be override returning the correct versions */ function oAppVersion() public view virtual returns (uint64 senderVersion, uint64 receiverVersion) { return (SENDER_VERSION, 0); } /** * @dev Internal function to interact with the LayerZero EndpointV2.quote() for fee calculation. * @param _dstEid The destination endpoint ID. * @param _message The message payload. * @param _options Additional options for the message. * @param _payInLzToken Flag indicating whether to pay the fee in LZ tokens. * @return fee The calculated MessagingFee for the message. * - nativeFee: The native fee for the message. * - lzTokenFee: The LZ token fee for the message. */ function _quote(uint32 _dstEid, bytes memory _message, bytes memory _options, bool _payInLzToken) internal view virtual returns (MessagingFee memory fee) { return endpoint.quote( MessagingParams(_dstEid, _getPeerOrRevert(_dstEid), _message, _options, _payInLzToken), address(this) ); } /** * @dev Internal function to interact with the LayerZero EndpointV2.send() for sending a message. * @param _dstEid The destination endpoint ID. * @param _message The message payload. * @param _options Additional options for the message. * @param _fee The calculated LayerZero fee for the message. * - nativeFee: The native fee. * - lzTokenFee: The lzToken fee. * @param _refundAddress The address to receive any excess fee values sent to the endpoint. * @return receipt The receipt for the sent message. * - guid: The unique identifier for the sent message. * - nonce: The nonce of the sent message. * - fee: The LayerZero fee incurred for the message. */ function _lzSend( uint32 _dstEid, bytes memory _message, bytes memory _options, MessagingFee memory _fee, address _refundAddress ) internal virtual returns (MessagingReceipt memory receipt) { // @dev Push corresponding fees to the endpoint, any excess is sent back to the _refundAddress from the endpoint. uint256 messageValue = _payNative(_fee.nativeFee); if (_fee.lzTokenFee > 0) _payLzToken(_fee.lzTokenFee); return endpoint // solhint-disable-next-line check-send-result .send{value: messageValue}( MessagingParams(_dstEid, _getPeerOrRevert(_dstEid), _message, _options, _fee.lzTokenFee > 0), _refundAddress ); } /** * @dev Internal function to pay the native fee associated with the message. * @param _nativeFee The native fee to be paid. * @return nativeFee The amount of native currency paid. * * @dev If the OApp needs to initiate MULTIPLE LayerZero messages in a single transaction, * this will need to be overridden because msg.value would contain multiple lzFees. * @dev Should be overridden in the event the LayerZero endpoint requires a different native currency. * @dev Some EVMs use an ERC20 as a method for paying transactions/gasFees. * @dev The endpoint is EITHER/OR, ie. it will NOT support both types of native payment at a time. */ function _payNative(uint256 _nativeFee) internal virtual returns (uint256 nativeFee) { if (msg.value != _nativeFee) revert NotEnoughNative(msg.value); return _nativeFee; } /** * @dev Internal function to pay the LZ token fee associated with the message. * @param _lzTokenFee The LZ token fee to be paid. * * @dev If the caller is trying to pay in the specified lzToken, then the lzTokenFee is passed to the endpoint. * @dev Any excess sent, is passed back to the specified _refundAddress in the _lzSend(). */ function _payLzToken(uint256 _lzTokenFee) internal virtual { // @dev Cannot cache the token because it is not immutable in the endpoint. address lzToken = endpoint.lzToken(); if (lzToken == address(0)) revert LzTokenUnavailable(); // Pay LZ token fee by sending tokens to the endpoint. ERC20(lzToken).safeTransferFrom(msg.sender, address(endpoint), _lzTokenFee); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; interface IMessagingContext { function isSendingMessage() external view returns (bool); function getSendContext() external view returns (uint32 dstEid, address sender); }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.21; import {ERC20} from "@solmate/tokens/ERC20.sol"; import {WETH} from "@solmate/tokens/WETH.sol"; import {BoringVault} from "../../../src/base/BoringVault.sol"; import {AccountantWithRateProviders} from "../../../src/base/Roles/AccountantWithRateProviders.sol"; import {FixedPointMathLib} from "@solmate/utils/FixedPointMathLib.sol"; import {SafeTransferLib} from "@solmate/utils/SafeTransferLib.sol"; import {BeforeTransferHook} from "../../../src/interfaces/BeforeTransferHook.sol"; import {Auth, Authority} from "@solmate/auth/Auth.sol"; import {ReentrancyGuard} from "@solmate/utils/ReentrancyGuard.sol"; import {IPausable} from "../../../src/interfaces/IPausable.sol"; contract TellerWithMultiAssetSupport is Auth, BeforeTransferHook, ReentrancyGuard, IPausable { using FixedPointMathLib for uint256; using SafeTransferLib for ERC20; using SafeTransferLib for WETH; // ========================================= STRUCTS ========================================= /** * @param allowDeposits bool indicating whether or not deposits are allowed for this asset. * @param allowWithdraws bool indicating whether or not withdraws are allowed for this asset. * @param sharePremium uint16 indicating the premium to apply to the shares minted. * where 40 represents a 40bps reduction in shares minted using this asset. */ struct Asset { bool allowDeposits; bool allowWithdraws; uint16 sharePremium; } // ========================================= CONSTANTS ========================================= /** * @notice Native address used to tell the contract to handle native asset deposits. */ address internal constant NATIVE = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; /** * @notice The maximum possible share lock period. */ uint256 internal constant MAX_SHARE_LOCK_PERIOD = 3 days; /** * @notice The maximum possible share premium that can be set using `updateAssetData`. * @dev 1,000 or 10% */ uint16 internal constant MAX_SHARE_PREMIUM = 1000; // ========================================= STATE ========================================= /** * @notice Mapping ERC20s to their assetData. */ mapping(ERC20 => Asset) public assetData; /** * @notice The deposit nonce used to map to a deposit hash. */ uint96 public depositNonce; /** * @notice After deposits, shares are locked to the msg.sender's address * for `shareLockPeriod`. * @dev During this time all trasnfers from msg.sender will revert, and * deposits are refundable. */ uint64 public shareLockPeriod; /** * @notice Used to pause calls to `deposit` and `depositWithPermit`. */ bool public isPaused; /** * @dev Maps deposit nonce to keccak256(address receiver, address depositAsset, uint256 depositAmount, uint256 shareAmount, uint256 timestamp, uint256 shareLockPeriod). */ mapping(uint256 => bytes32) public publicDepositHistory; /** * @notice Maps user address to the time their shares will be unlocked. */ mapping(address => uint256) public shareUnlockTime; /** * @notice Mapping `from` address to a bool to deny them from transferring shares. */ mapping(address => bool) public fromDenyList; /** * @notice Mapping `to` address to a bool to deny them from receiving shares. */ mapping(address => bool) public toDenyList; /** * @notice Mapping `opeartor` address to a bool to deny them from calling `transfer` or `transferFrom`. */ mapping(address => bool) public operatorDenyList; //============================== ERRORS =============================== error TellerWithMultiAssetSupport__ShareLockPeriodTooLong(); error TellerWithMultiAssetSupport__SharesAreLocked(); error TellerWithMultiAssetSupport__SharesAreUnLocked(); error TellerWithMultiAssetSupport__BadDepositHash(); error TellerWithMultiAssetSupport__AssetNotSupported(); error TellerWithMultiAssetSupport__ZeroAssets(); error TellerWithMultiAssetSupport__MinimumMintNotMet(); error TellerWithMultiAssetSupport__MinimumAssetsNotMet(); error TellerWithMultiAssetSupport__PermitFailedAndAllowanceTooLow(); error TellerWithMultiAssetSupport__ZeroShares(); error TellerWithMultiAssetSupport__DualDeposit(); error TellerWithMultiAssetSupport__Paused(); error TellerWithMultiAssetSupport__TransferDenied(address from, address to, address operator); error TellerWithMultiAssetSupport__SharePremiumTooLarge(); error TellerWithMultiAssetSupport__CannotDepositNative(); //============================== EVENTS =============================== event Paused(); event Unpaused(); event AssetDataUpdated(address indexed asset, bool allowDeposits, bool allowWithdraws, uint16 sharePremium); event Deposit( uint256 indexed nonce, address indexed receiver, address indexed depositAsset, uint256 depositAmount, uint256 shareAmount, uint256 depositTimestamp, uint256 shareLockPeriodAtTimeOfDeposit ); event BulkDeposit(address indexed asset, uint256 depositAmount); event BulkWithdraw(address indexed asset, uint256 shareAmount); event DepositRefunded(uint256 indexed nonce, bytes32 depositHash, address indexed user); event DenyFrom(address indexed user); event DenyTo(address indexed user); event DenyOperator(address indexed user); event AllowFrom(address indexed user); event AllowTo(address indexed user); event AllowOperator(address indexed user); // =============================== MODIFIERS =============================== /** * @notice Reverts if the deposit asset is the native asset. */ modifier revertOnNativeDeposit(address depositAsset) { if (depositAsset == NATIVE) revert TellerWithMultiAssetSupport__CannotDepositNative(); _; } //============================== IMMUTABLES =============================== /** * @notice The BoringVault this contract is working with. */ BoringVault public immutable vault; /** * @notice The AccountantWithRateProviders this contract is working with. */ AccountantWithRateProviders public immutable accountant; /** * @notice One share of the BoringVault. */ uint256 internal immutable ONE_SHARE; /** * @notice The native wrapper contract. */ WETH public immutable nativeWrapper; constructor(address _owner, address _vault, address _accountant, address _weth) Auth(_owner, Authority(address(0))) { vault = BoringVault(payable(_vault)); ONE_SHARE = 10 ** vault.decimals(); accountant = AccountantWithRateProviders(_accountant); nativeWrapper = WETH(payable(_weth)); } // ========================================= ADMIN FUNCTIONS ========================================= /** * @notice Pause this contract, which prevents future calls to `deposit` and `depositWithPermit`. * @dev Callable by MULTISIG_ROLE. */ function pause() external requiresAuth { isPaused = true; emit Paused(); } /** * @notice Unpause this contract, which allows future calls to `deposit` and `depositWithPermit`. * @dev Callable by MULTISIG_ROLE. */ function unpause() external requiresAuth { isPaused = false; emit Unpaused(); } /** * @notice Updates the asset data for a given asset. * @dev The accountant must also support pricing this asset, else the `deposit` call will revert. * @dev Callable by OWNER_ROLE. */ function updateAssetData(ERC20 asset, bool allowDeposits, bool allowWithdraws, uint16 sharePremium) external requiresAuth { if (sharePremium > MAX_SHARE_PREMIUM) revert TellerWithMultiAssetSupport__SharePremiumTooLarge(); assetData[asset] = Asset(allowDeposits, allowWithdraws, sharePremium); emit AssetDataUpdated(address(asset), allowDeposits, allowWithdraws, sharePremium); } /** * @notice Sets the share lock period. * @dev This not only locks shares to the user address, but also serves as the pending deposit period, where deposits can be reverted. * @dev If a new shorter share lock period is set, users with pending share locks could make a new deposit to receive 1 wei shares, * and have their shares unlock sooner than their original deposit allows. This state would allow for the user deposit to be refunded, * but only if they have not transferred their shares out of there wallet. This is an accepted limitation, and should be known when decreasing * the share lock period. * @dev Callable by OWNER_ROLE. */ function setShareLockPeriod(uint64 _shareLockPeriod) external requiresAuth { if (_shareLockPeriod > MAX_SHARE_LOCK_PERIOD) revert TellerWithMultiAssetSupport__ShareLockPeriodTooLong(); shareLockPeriod = _shareLockPeriod; } /** * @notice Deny a user from transferring or receiving shares. * @dev Callable by OWNER_ROLE, and DENIER_ROLE. */ function denyAll(address user) external requiresAuth { fromDenyList[user] = true; toDenyList[user] = true; operatorDenyList[user] = true; emit DenyFrom(user); emit DenyTo(user); emit DenyOperator(user); } /** * @notice Allow a user to transfer or receive shares. * @dev Callable by OWNER_ROLE, and DENIER_ROLE. */ function allowAll(address user) external requiresAuth { fromDenyList[user] = false; toDenyList[user] = false; operatorDenyList[user] = false; emit AllowFrom(user); emit AllowTo(user); emit AllowOperator(user); } /** * @notice Deny a user from transferring shares. * @dev Callable by OWNER_ROLE, and DENIER_ROLE. */ function denyFrom(address user) external requiresAuth { fromDenyList[user] = true; emit DenyFrom(user); } /** * @notice Allow a user to transfer shares. * @dev Callable by OWNER_ROLE, and DENIER_ROLE. */ function allowFrom(address user) external requiresAuth { fromDenyList[user] = false; emit AllowFrom(user); } /** * @notice Deny a user from receiving shares. * @dev Callable by OWNER_ROLE, and DENIER_ROLE. */ function denyTo(address user) external requiresAuth { toDenyList[user] = true; emit DenyTo(user); } /** * @notice Allow a user to receive shares. * @dev Callable by OWNER_ROLE, and DENIER_ROLE. */ function allowTo(address user) external requiresAuth { toDenyList[user] = false; emit AllowTo(user); } /** * @notice Deny an operator from transferring shares. * @dev Callable by OWNER_ROLE, and DENIER_ROLE. */ function denyOperator(address user) external requiresAuth { operatorDenyList[user] = true; emit DenyOperator(user); } /** * @notice Allow an operator to transfer shares. * @dev Callable by OWNER_ROLE, and DENIER_ROLE. */ function allowOperator(address user) external requiresAuth { operatorDenyList[user] = false; emit AllowOperator(user); } // ========================================= BeforeTransferHook FUNCTIONS ========================================= /** * @notice Implement beforeTransfer hook to check if shares are locked, or if `from`, `to`, or `operator` are on the deny list. * @notice If share lock period is set to zero, then users will be able to mint and transfer in the same tx. * if this behavior is not desired then a share lock period of >=1 should be used. */ function beforeTransfer(address from, address to, address operator) public view virtual { if (fromDenyList[from] || toDenyList[to] || operatorDenyList[operator]) { revert TellerWithMultiAssetSupport__TransferDenied(from, to, operator); } if (shareUnlockTime[from] > block.timestamp) revert TellerWithMultiAssetSupport__SharesAreLocked(); } // ========================================= REVERT DEPOSIT FUNCTIONS ========================================= /** * @notice Allows DEPOSIT_REFUNDER_ROLE to revert a pending deposit. * @dev Once a deposit share lock period has passed, it can no longer be reverted. * @dev It is possible the admin does not setup the BoringVault to call the transfer hook, * but this contract can still be saving share lock state. In the event this happens * deposits are still refundable if the user has not transferred their shares. * But there is no guarantee that the user has not transferred their shares. * @dev Callable by STRATEGIST_MULTISIG_ROLE. */ function refundDeposit( uint256 nonce, address receiver, address depositAsset, uint256 depositAmount, uint256 shareAmount, uint256 depositTimestamp, uint256 shareLockUpPeriodAtTimeOfDeposit ) external requiresAuth { if ((block.timestamp - depositTimestamp) >= shareLockUpPeriodAtTimeOfDeposit) { // Shares are already unlocked, so we can not revert deposit. revert TellerWithMultiAssetSupport__SharesAreUnLocked(); } bytes32 depositHash = keccak256( abi.encode( receiver, depositAsset, depositAmount, shareAmount, depositTimestamp, shareLockUpPeriodAtTimeOfDeposit ) ); if (publicDepositHistory[nonce] != depositHash) revert TellerWithMultiAssetSupport__BadDepositHash(); // Delete hash to prevent refund gas. delete publicDepositHistory[nonce]; // If deposit used native asset, send user back wrapped native asset. depositAsset = depositAsset == NATIVE ? address(nativeWrapper) : depositAsset; // Burn shares and refund assets to receiver. vault.exit(receiver, ERC20(depositAsset), depositAmount, receiver, shareAmount); emit DepositRefunded(nonce, depositHash, receiver); } // ========================================= USER FUNCTIONS ========================================= /** * @notice Allows users to deposit into the BoringVault, if this contract is not paused. * @dev Publicly callable. */ function deposit(ERC20 depositAsset, uint256 depositAmount, uint256 minimumMint) external payable requiresAuth nonReentrant returns (uint256 shares) { Asset memory asset = _beforeDeposit(depositAsset); address from; if (address(depositAsset) == NATIVE) { if (msg.value == 0) revert TellerWithMultiAssetSupport__ZeroAssets(); nativeWrapper.deposit{value: msg.value}(); // Set depositAmount to msg.value. depositAmount = msg.value; nativeWrapper.safeApprove(address(vault), depositAmount); // Update depositAsset to nativeWrapper. depositAsset = nativeWrapper; // Set from to this address since user transferred value. from = address(this); } else { if (msg.value > 0) revert TellerWithMultiAssetSupport__DualDeposit(); from = msg.sender; } shares = _erc20Deposit(depositAsset, depositAmount, minimumMint, from, msg.sender, asset); _afterPublicDeposit(msg.sender, depositAsset, depositAmount, shares, shareLockPeriod); } /** * @notice Allows users to deposit into BoringVault using permit. * @dev Publicly callable. */ function depositWithPermit( ERC20 depositAsset, uint256 depositAmount, uint256 minimumMint, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external requiresAuth nonReentrant revertOnNativeDeposit(address(depositAsset)) returns (uint256 shares) { Asset memory asset = _beforeDeposit(depositAsset); _handlePermit(depositAsset, depositAmount, deadline, v, r, s); shares = _erc20Deposit(depositAsset, depositAmount, minimumMint, msg.sender, msg.sender, asset); _afterPublicDeposit(msg.sender, depositAsset, depositAmount, shares, shareLockPeriod); } /** * @notice Allows on ramp role to deposit into this contract. * @dev Does NOT support native deposits. * @dev Callable by SOLVER_ROLE. */ function bulkDeposit(ERC20 depositAsset, uint256 depositAmount, uint256 minimumMint, address to) external requiresAuth nonReentrant returns (uint256 shares) { Asset memory asset = _beforeDeposit(depositAsset); shares = _erc20Deposit(depositAsset, depositAmount, minimumMint, msg.sender, to, asset); emit BulkDeposit(address(depositAsset), depositAmount); } /** * @notice Allows off ramp role to withdraw from this contract. * @dev Callable by SOLVER_ROLE. */ function bulkWithdraw(ERC20 withdrawAsset, uint256 shareAmount, uint256 minimumAssets, address to) external requiresAuth returns (uint256 assetsOut) { if (isPaused) revert TellerWithMultiAssetSupport__Paused(); Asset memory asset = assetData[withdrawAsset]; if (!asset.allowWithdraws) revert TellerWithMultiAssetSupport__AssetNotSupported(); if (shareAmount == 0) revert TellerWithMultiAssetSupport__ZeroShares(); assetsOut = shareAmount.mulDivDown(accountant.getRateInQuoteSafe(withdrawAsset), ONE_SHARE); if (assetsOut < minimumAssets) revert TellerWithMultiAssetSupport__MinimumAssetsNotMet(); vault.exit(to, withdrawAsset, assetsOut, msg.sender, shareAmount); emit BulkWithdraw(address(withdrawAsset), shareAmount); } // ========================================= INTERNAL HELPER FUNCTIONS ========================================= /** * @notice Implements a common ERC20 deposit into BoringVault. */ function _erc20Deposit( ERC20 depositAsset, uint256 depositAmount, uint256 minimumMint, address from, address to, Asset memory asset ) internal returns (uint256 shares) { if (depositAmount == 0) revert TellerWithMultiAssetSupport__ZeroAssets(); shares = depositAmount.mulDivDown(ONE_SHARE, accountant.getRateInQuoteSafe(depositAsset)); shares = asset.sharePremium > 0 ? shares.mulDivDown(1e4 - asset.sharePremium, 1e4) : shares; if (shares < minimumMint) revert TellerWithMultiAssetSupport__MinimumMintNotMet(); vault.enter(from, depositAsset, depositAmount, to, shares); } /** * @notice Handle pre-deposit checks. */ function _beforeDeposit(ERC20 depositAsset) internal view returns (Asset memory asset) { if (isPaused) revert TellerWithMultiAssetSupport__Paused(); asset = assetData[depositAsset]; if (!asset.allowDeposits) revert TellerWithMultiAssetSupport__AssetNotSupported(); } /** * @notice Handle share lock logic, and event. */ function _afterPublicDeposit( address user, ERC20 depositAsset, uint256 depositAmount, uint256 shares, uint256 currentShareLockPeriod ) internal { // Increment then assign as its slightly more gas efficient. uint256 nonce = ++depositNonce; // Only set share unlock time and history if share lock period is greater than 0. if (currentShareLockPeriod > 0) { shareUnlockTime[user] = block.timestamp + currentShareLockPeriod; publicDepositHistory[nonce] = keccak256( abi.encode(user, depositAsset, depositAmount, shares, block.timestamp, currentShareLockPeriod) ); } emit Deposit(nonce, user, address(depositAsset), depositAmount, shares, block.timestamp, currentShareLockPeriod); } /** * @notice Handle permit logic. */ function _handlePermit(ERC20 depositAsset, uint256 depositAmount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) internal { try depositAsset.permit(msg.sender, address(vault), depositAmount, deadline, v, r, s) {} catch { if (depositAsset.allowance(msg.sender, address(vault)) < depositAmount) { revert TellerWithMultiAssetSupport__PermitFailedAndAllowanceTooLow(); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.20; /** * @title ERC-721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC-721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be * reverted. * * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.21; import {Address} from "@openzeppelin/contracts/utils/Address.sol"; import {ERC721Holder} from "@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol"; import {ERC1155Holder} from "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol"; import {FixedPointMathLib} from "@solmate/utils/FixedPointMathLib.sol"; import {SafeTransferLib} from "@solmate/utils/SafeTransferLib.sol"; import {ERC20} from "@solmate/tokens/ERC20.sol"; import {BeforeTransferHook} from "../../src/interfaces/BeforeTransferHook.sol"; import {Auth, Authority} from "@solmate/auth/Auth.sol"; contract BoringVault is ERC20, Auth, ERC721Holder, ERC1155Holder { using Address for address; using SafeTransferLib for ERC20; using FixedPointMathLib for uint256; // ========================================= STATE ========================================= /** * @notice Contract responsbile for implementing `beforeTransfer`. */ BeforeTransferHook public hook; //============================== EVENTS =============================== event Enter(address indexed from, address indexed asset, uint256 amount, address indexed to, uint256 shares); event Exit(address indexed to, address indexed asset, uint256 amount, address indexed from, uint256 shares); //============================== CONSTRUCTOR =============================== constructor(address _owner, string memory _name, string memory _symbol, uint8 _decimals) ERC20(_name, _symbol, _decimals) Auth(_owner, Authority(address(0))) {} //============================== MANAGE =============================== /** * @notice Allows manager to make an arbitrary function call from this contract. * @dev Callable by MANAGER_ROLE. */ function manage(address target, bytes calldata data, uint256 value) external requiresAuth returns (bytes memory result) { result = target.functionCallWithValue(data, value); } /** * @notice Allows manager to make arbitrary function calls from this contract. * @dev Callable by MANAGER_ROLE. */ function manage(address[] calldata targets, bytes[] calldata data, uint256[] calldata values) external requiresAuth returns (bytes[] memory results) { uint256 targetsLength = targets.length; results = new bytes[](targetsLength); for (uint256 i; i < targetsLength; ++i) { results[i] = targets[i].functionCallWithValue(data[i], values[i]); } } //============================== ENTER =============================== /** * @notice Allows minter to mint shares, in exchange for assets. * @dev If assetAmount is zero, no assets are transferred in. * @dev Callable by MINTER_ROLE. */ function enter(address from, ERC20 asset, uint256 assetAmount, address to, uint256 shareAmount) external requiresAuth { // Transfer assets in if (assetAmount > 0) asset.safeTransferFrom(from, address(this), assetAmount); // Mint shares. _mint(to, shareAmount); emit Enter(from, address(asset), assetAmount, to, shareAmount); } //============================== EXIT =============================== /** * @notice Allows burner to burn shares, in exchange for assets. * @dev If assetAmount is zero, no assets are transferred out. * @dev Callable by BURNER_ROLE. */ function exit(address to, ERC20 asset, uint256 assetAmount, address from, uint256 shareAmount) external requiresAuth { // Burn shares. _burn(from, shareAmount); // Transfer assets out. if (assetAmount > 0) asset.safeTransfer(to, assetAmount); emit Exit(to, address(asset), assetAmount, from, shareAmount); } //============================== BEFORE TRANSFER HOOK =============================== /** * @notice Sets the share locker. * @notice If set to zero address, the share locker logic is disabled. * @dev Callable by OWNER_ROLE. */ function setBeforeTransferHook(address _hook) external requiresAuth { hook = BeforeTransferHook(_hook); } /** * @notice Call `beforeTransferHook` passing in `from` `to`, and `msg.sender`. */ function _callBeforeTransfer(address from, address to) internal view { if (address(hook) != address(0)) hook.beforeTransfer(from, to, msg.sender); } function transfer(address to, uint256 amount) public override returns (bool) { _callBeforeTransfer(msg.sender, to); return super.transfer(to, amount); } function transferFrom(address from, address to, uint256 amount) public override returns (bool) { _callBeforeTransfer(from, to); return super.transferFrom(from, to, amount); } //============================== RECEIVE =============================== receive() external payable {} }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Arithmetic library with operations for fixed-point numbers. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol) /// @author Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol) library FixedPointMathLib { /*////////////////////////////////////////////////////////////// SIMPLIFIED FIXED POINT OPERATIONS //////////////////////////////////////////////////////////////*/ uint256 internal constant MAX_UINT256 = 2**256 - 1; uint256 internal constant WAD = 1e18; // The scalar of ETH and most ERC20s. function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down. } function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up. } function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down. } function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up. } /*////////////////////////////////////////////////////////////// LOW LEVEL FIXED POINT OPERATIONS //////////////////////////////////////////////////////////////*/ function mulDivDown( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y)) if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) { revert(0, 0) } // Divide x * y by the denominator. z := div(mul(x, y), denominator) } } function mulDivUp( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y)) if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) { revert(0, 0) } // If x * y modulo the denominator is strictly greater than 0, // 1 is added to round up the division of x * y by the denominator. z := add(gt(mod(mul(x, y), denominator), 0), div(mul(x, y), denominator)) } } function rpow( uint256 x, uint256 n, uint256 scalar ) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { switch x case 0 { switch n case 0 { // 0 ** 0 = 1 z := scalar } default { // 0 ** n = 0 z := 0 } } default { switch mod(n, 2) case 0 { // If n is even, store scalar in z for now. z := scalar } default { // If n is odd, store x in z for now. z := x } // Shifting right by 1 is like dividing by 2. let half := shr(1, scalar) for { // Shift n right by 1 before looping to halve it. n := shr(1, n) } n { // Shift n right by 1 each iteration to halve it. n := shr(1, n) } { // Revert immediately if x ** 2 would overflow. // Equivalent to iszero(eq(div(xx, x), x)) here. if shr(128, x) { revert(0, 0) } // Store x squared. let xx := mul(x, x) // Round to the nearest number. let xxRound := add(xx, half) // Revert if xx + half overflowed. if lt(xxRound, xx) { revert(0, 0) } // Set x to scaled xxRound. x := div(xxRound, scalar) // If n is even: if mod(n, 2) { // Compute z * x. let zx := mul(z, x) // If z * x overflowed: if iszero(eq(div(zx, x), z)) { // Revert if x is non-zero. if iszero(iszero(x)) { revert(0, 0) } } // Round to the nearest number. let zxRound := add(zx, half) // Revert if zx + half overflowed. if lt(zxRound, zx) { revert(0, 0) } // Return properly scaled zxRound. z := div(zxRound, scalar) } } } } } /*////////////////////////////////////////////////////////////// GENERAL NUMBER UTILITIES //////////////////////////////////////////////////////////////*/ function sqrt(uint256 x) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { let y := x // We start y at x, which will help us make our initial estimate. z := 181 // The "correct" value is 1, but this saves a multiplication later. // This segment is to get a reasonable initial estimate for the Babylonian method. With a bad // start, the correct # of bits increases ~linearly each iteration instead of ~quadratically. // We check y >= 2^(k + 8) but shift right by k bits // each branch to ensure that if x >= 256, then y >= 256. if iszero(lt(y, 0x10000000000000000000000000000000000)) { y := shr(128, y) z := shl(64, z) } if iszero(lt(y, 0x1000000000000000000)) { y := shr(64, y) z := shl(32, z) } if iszero(lt(y, 0x10000000000)) { y := shr(32, y) z := shl(16, z) } if iszero(lt(y, 0x1000000)) { y := shr(16, y) z := shl(8, z) } // Goal was to get z*z*y within a small factor of x. More iterations could // get y in a tighter range. Currently, we will have y in [256, 256*2^16). // We ensured y >= 256 so that the relative difference between y and y+1 is small. // That's not possible if x < 256 but we can just verify those cases exhaustively. // Now, z*z*y <= x < z*z*(y+1), and y <= 2^(16+8), and either y >= 256, or x < 256. // Correctness can be checked exhaustively for x < 256, so we assume y >= 256. // Then z*sqrt(y) is within sqrt(257)/sqrt(256) of sqrt(x), or about 20bps. // For s in the range [1/256, 256], the estimate f(s) = (181/1024) * (s+1) is in the range // (1/2.84 * sqrt(s), 2.84 * sqrt(s)), with largest error when s = 1 and when s = 256 or 1/256. // Since y is in [256, 256*2^16), let a = y/65536, so that a is in [1/256, 256). Then we can estimate // sqrt(y) using sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2^18. // There is no overflow risk here since y < 2^136 after the first branch above. z := shr(18, mul(z, add(y, 65536))) // A mul() is saved from starting z at 181. // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough. z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) // If x+1 is a perfect square, the Babylonian method cycles between // floor(sqrt(x)) and ceil(sqrt(x)). This statement ensures we return floor. // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division // Since the ceil is rare, we save gas on the assignment and repeat division in the rare case. // If you don't care whether the floor or ceil square root is returned, you can remove this statement. z := sub(z, lt(div(x, z), z)) } } function unsafeMod(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { // Mod x by y. Note this will return // 0 instead of reverting if y is zero. z := mod(x, y) } } function unsafeDiv(uint256 x, uint256 y) internal pure returns (uint256 r) { /// @solidity memory-safe-assembly assembly { // Divide x by y. Note this will return // 0 instead of reverting if y is zero. r := div(x, y) } } function unsafeDivUp(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { // Add 1 to x * y if x % y > 0. Note this will // return 0 instead of reverting if y is zero. z := add(gt(mod(x, y), 0), div(x, y)) } } }
// SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.0; library MessageLib { error MessageLib__ShareAmountOverflow(); uint256 internal constant MAX_SHARE_AMOUNT = type(uint96).max; /** * @notice Messages are transferred between chains as uint256 * The first 96 bits are the share amount. * The remaining 160 bits are the address to send the shares to. * @dev Using a uint256 was chosen because most bridging protocols charge based off the number of * bytes sent, and packing a uint256 in this way caps it at 32 bytes. */ struct Message { uint256 shareAmount; // The amount of shares to bridge. address to; } /** * @notice Extracts a Message from a uint256. */ function uint256ToMessage(uint256 b) internal pure returns (Message memory m) { m.shareAmount = uint96(b >> 160); m.to = address(uint160(b)); } /** * @notice Packs a Message into a uint256. */ function messageToUint256(Message memory m) internal pure returns (uint256 b) { if (m.shareAmount > MAX_SHARE_AMOUNT) revert MessageLib__ShareAmountOverflow(); b |= m.shareAmount << 160; b |= uint160(m.to); } }
{ "evmVersion": "shanghai", "metadata": { "appendCBOR": true, "bytecodeHash": "ipfs", "useLiteralContent": false }, "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "remappings": [ "@ccip/=lib/boring-vault/lib/ccip/", "@devtools-oapp-evm/=lib/boring-vault/lib/OAppAuth/lib/devtools/packages/oapp-evm/contracts/oapp/", "@ds-test/=lib/boring-vault/lib/forge-std/lib/ds-test/src/", "@forge-std/=lib/boring-vault/lib/forge-std/src/", "@layerzerolabs/lz-evm-messagelib-v2/=lib/boring-vault/lib/OAppAuth/node_modules/@layerzerolabs/lz-evm-messagelib-v2/", "@layerzerolabs/lz-evm-protocol-v2/=lib/boring-vault/lib/OAppAuth/lib/LayerZero-V2/packages/layerzero-v2/evm/protocol/", "@layerzerolabs/oapp-evm/=lib/boring-vault/lib/OAppAuth/lib/devtools/packages/oapp-evm/", "@lz-oapp-evm/=lib/boring-vault/lib/OAppAuth/lib/LayerZero-V2/packages/layerzero-v2/evm/oapp/contracts/oapp/", "@oapp-auth/=lib/boring-vault/lib/OAppAuth/src/", "@openzeppelin/=lib/boring-vault/lib/openzeppelin-contracts/", "@solmate/=lib/boring-vault/lib/solmate/src/", "LayerZero-V2/=lib/boring-vault/lib/OAppAuth/lib/", "OAppAuth/=lib/boring-vault/lib/OAppAuth/", "boring-vault/=lib/boring-vault/", "ccip/=lib/boring-vault/lib/ccip/contracts/", "ds-test/=lib/solmate/lib/ds-test/src/", "erc4626-tests/=lib/boring-vault/lib/openzeppelin-contracts/lib/erc4626-tests/", "forge-std/=lib/forge-std/src/", "halmos-cheatcodes/=lib/boring-vault/lib/OAppAuth/lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/", "openzeppelin-contracts/=lib/boring-vault/lib/openzeppelin-contracts/", "solady/=lib/solady/src/", "solidity-bytes-utils/=lib/boring-vault/lib/OAppAuth/node_modules/solidity-bytes-utils/", "solmate/=lib/solmate/src/", "yearn-vaults/=lib/yearn-vaults/contracts/", "@sbu/=lib/boring-vault/lib/OAppAuth/lib/solidity-bytes-utils/", "morpho-blue/=lib/boring-vault/lib/morpho-blue/" ], "viaIR": false }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_vault","type":"address"},{"internalType":"address","name":"_accountant","type":"address"},{"internalType":"address","name":"_weth","type":"address"},{"internalType":"address","name":"_lzEndPoint","type":"address"},{"internalType":"address","name":"_delegate","type":"address"},{"internalType":"address","name":"_lzToken","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CrossChainTellerWithGenericBridge__UnsafeCastToUint96","type":"error"},{"inputs":[],"name":"InvalidDelegate","type":"error"},{"inputs":[],"name":"InvalidEndpointCall","type":"error"},{"inputs":[{"internalType":"uint16","name":"optionType","type":"uint16"}],"name":"InvalidOptionType","type":"error"},{"inputs":[],"name":"LayerZeroTeller__BadFeeToken","type":"error"},{"inputs":[{"internalType":"uint256","name":"chainSelector","type":"uint256"},{"internalType":"uint256","name":"fee","type":"uint256"},{"internalType":"uint256","name":"maxFee","type":"uint256"}],"name":"LayerZeroTeller__FeeExceedsMax","type":"error"},{"inputs":[{"internalType":"uint256","name":"chainSelector","type":"uint256"}],"name":"LayerZeroTeller__MessagesNotAllowedFrom","type":"error"},{"inputs":[{"internalType":"uint256","name":"chainSelector","type":"uint256"},{"internalType":"address","name":"sender","type":"address"}],"name":"LayerZeroTeller__MessagesNotAllowedFromSender","type":"error"},{"inputs":[{"internalType":"uint256","name":"chainSelector","type":"uint256"}],"name":"LayerZeroTeller__MessagesNotAllowedTo","type":"error"},{"inputs":[],"name":"LayerZeroTeller__ZeroMessageGasLimit","type":"error"},{"inputs":[],"name":"LzTokenUnavailable","type":"error"},{"inputs":[],"name":"MessageLib__ShareAmountOverflow","type":"error"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"}],"name":"NoPeer","type":"error"},{"inputs":[{"internalType":"uint256","name":"msgValue","type":"uint256"}],"name":"NotEnoughNative","type":"error"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"OnlyEndpoint","type":"error"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"}],"name":"OnlyPeer","type":"error"},{"inputs":[{"internalType":"uint8","name":"bits","type":"uint8"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"SafeCastOverflowedUintDowncast","type":"error"},{"inputs":[],"name":"TellerWithMultiAssetSupport__AssetNotSupported","type":"error"},{"inputs":[],"name":"TellerWithMultiAssetSupport__BadDepositHash","type":"error"},{"inputs":[],"name":"TellerWithMultiAssetSupport__CannotDepositNative","type":"error"},{"inputs":[],"name":"TellerWithMultiAssetSupport__DualDeposit","type":"error"},{"inputs":[],"name":"TellerWithMultiAssetSupport__MinimumAssetsNotMet","type":"error"},{"inputs":[],"name":"TellerWithMultiAssetSupport__MinimumMintNotMet","type":"error"},{"inputs":[],"name":"TellerWithMultiAssetSupport__Paused","type":"error"},{"inputs":[],"name":"TellerWithMultiAssetSupport__PermitFailedAndAllowanceTooLow","type":"error"},{"inputs":[],"name":"TellerWithMultiAssetSupport__ShareLockPeriodTooLong","type":"error"},{"inputs":[],"name":"TellerWithMultiAssetSupport__SharePremiumTooLarge","type":"error"},{"inputs":[],"name":"TellerWithMultiAssetSupport__SharesAreLocked","type":"error"},{"inputs":[],"name":"TellerWithMultiAssetSupport__SharesAreUnLocked","type":"error"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"TellerWithMultiAssetSupport__TransferDenied","type":"error"},{"inputs":[],"name":"TellerWithMultiAssetSupport__ZeroAssets","type":"error"},{"inputs":[],"name":"TellerWithMultiAssetSupport__ZeroShares","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"}],"name":"AllowFrom","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"}],"name":"AllowOperator","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"}],"name":"AllowTo","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"bool","name":"allowDeposits","type":"bool"},{"indexed":false,"internalType":"bool","name":"allowWithdraws","type":"bool"},{"indexed":false,"internalType":"uint16","name":"sharePremium","type":"uint16"}],"name":"AssetDataUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"contract Authority","name":"newAuthority","type":"address"}],"name":"AuthorityUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"depositAmount","type":"uint256"}],"name":"BulkDeposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"shareAmount","type":"uint256"}],"name":"BulkWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"chainId","type":"uint256"},{"indexed":false,"internalType":"bool","name":"allowMessagesFrom","type":"bool"},{"indexed":false,"internalType":"bool","name":"allowMessagesTo","type":"bool"},{"indexed":false,"internalType":"address","name":"targetTeller","type":"address"}],"name":"ChainAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"chainId","type":"uint256"},{"indexed":false,"internalType":"address","name":"targetTeller","type":"address"}],"name":"ChainAllowMessagesFrom","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"chainId","type":"uint256"},{"indexed":false,"internalType":"address","name":"targetTeller","type":"address"}],"name":"ChainAllowMessagesTo","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"chainId","type":"uint256"}],"name":"ChainRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"chainId","type":"uint256"},{"indexed":false,"internalType":"uint128","name":"messageGasLimit","type":"uint128"}],"name":"ChainSetGasLimit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"chainId","type":"uint256"}],"name":"ChainStopMessagesFrom","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"chainId","type":"uint256"}],"name":"ChainStopMessagesTo","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"}],"name":"DenyFrom","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"}],"name":"DenyOperator","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"}],"name":"DenyTo","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"address","name":"depositAsset","type":"address"},{"indexed":false,"internalType":"uint256","name":"depositAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shareAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"depositTimestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shareLockPeriodAtTimeOfDeposit","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"depositHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"user","type":"address"}],"name":"DepositRefunded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"messageId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"shareAmount","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"MessageReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"messageId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"shareAmount","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"MessageSent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"eid","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"peer","type":"bytes32"}],"name":"PeerSet","type":"event"},{"anonymous":false,"inputs":[],"name":"Unpaused","type":"event"},{"inputs":[],"name":"accountant","outputs":[{"internalType":"contract AccountantWithRateProviders","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"chainId","type":"uint32"},{"internalType":"bool","name":"allowMessagesFrom","type":"bool"},{"internalType":"bool","name":"allowMessagesTo","type":"bool"},{"internalType":"address","name":"targetTeller","type":"address"},{"internalType":"uint128","name":"messageGasLimit","type":"uint128"}],"name":"addChain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"allowAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"allowFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"origin","type":"tuple"}],"name":"allowInitializePath","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"chainId","type":"uint32"},{"internalType":"address","name":"targetTeller","type":"address"}],"name":"allowMessagesFromChain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"chainId","type":"uint32"},{"internalType":"address","name":"targetTeller","type":"address"},{"internalType":"uint128","name":"messageGasLimit","type":"uint128"}],"name":"allowMessagesToChain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"allowOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"allowTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ERC20","name":"","type":"address"}],"name":"assetData","outputs":[{"internalType":"bool","name":"allowDeposits","type":"bool"},{"internalType":"bool","name":"allowWithdraws","type":"bool"},{"internalType":"uint16","name":"sharePremium","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"authority","outputs":[{"internalType":"contract Authority","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"beforeTransfer","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint96","name":"shareAmount","type":"uint96"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes","name":"bridgeWildCard","type":"bytes"},{"internalType":"contract ERC20","name":"feeToken","type":"address"},{"internalType":"uint256","name":"maxFee","type":"uint256"}],"name":"bridge","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"contract ERC20","name":"depositAsset","type":"address"},{"internalType":"uint256","name":"depositAmount","type":"uint256"},{"internalType":"uint256","name":"minimumMint","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"bulkDeposit","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ERC20","name":"withdrawAsset","type":"address"},{"internalType":"uint256","name":"shareAmount","type":"uint256"},{"internalType":"uint256","name":"minimumAssets","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"bulkWithdraw","outputs":[{"internalType":"uint256","name":"assetsOut","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"composeMsgSender","outputs":[{"internalType":"address","name":"sender","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"denyAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"denyFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"denyOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"denyTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ERC20","name":"depositAsset","type":"address"},{"internalType":"uint256","name":"depositAmount","type":"uint256"},{"internalType":"uint256","name":"minimumMint","type":"uint256"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"contract ERC20","name":"depositAsset","type":"address"},{"internalType":"uint256","name":"depositAmount","type":"uint256"},{"internalType":"uint256","name":"minimumMint","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes","name":"bridgeWildCard","type":"bytes"},{"internalType":"contract ERC20","name":"feeToken","type":"address"},{"internalType":"uint256","name":"maxFee","type":"uint256"}],"name":"depositAndBridge","outputs":[{"internalType":"uint256","name":"sharesBridged","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"contract ERC20","name":"depositAsset","type":"address"},{"internalType":"uint256","name":"depositAmount","type":"uint256"},{"internalType":"uint256","name":"minimumMint","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes","name":"bridgeWildCard","type":"bytes"},{"internalType":"contract ERC20","name":"feeToken","type":"address"},{"internalType":"uint256","name":"maxFee","type":"uint256"}],"name":"depositAndBridgeWithPermit","outputs":[{"internalType":"uint256","name":"sharesBridged","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"depositNonce","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ERC20","name":"depositAsset","type":"address"},{"internalType":"uint256","name":"depositAmount","type":"uint256"},{"internalType":"uint256","name":"minimumMint","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"depositWithPermit","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"endpoint","outputs":[{"internalType":"contract ILayerZeroEndpointV2","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"fromDenyList","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"}],"name":"idToChains","outputs":[{"internalType":"bool","name":"allowMessagesFrom","type":"bool"},{"internalType":"bool","name":"allowMessagesTo","type":"bool"},{"internalType":"uint128","name":"messageGasLimit","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"_origin","type":"tuple"},{"internalType":"bytes32","name":"_guid","type":"bytes32"},{"internalType":"bytes","name":"_message","type":"bytes"},{"internalType":"address","name":"_executor","type":"address"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"lzReceive","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"nativeWrapper","outputs":[{"internalType":"contract WETH","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"nextNonce","outputs":[{"internalType":"uint64","name":"nonce","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oAppVersion","outputs":[{"internalType":"uint64","name":"senderVersion","type":"uint64"},{"internalType":"uint64","name":"receiverVersion","type":"uint64"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"operatorDenyList","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"}],"name":"peers","outputs":[{"internalType":"bytes32","name":"peer","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint96","name":"shareAmount","type":"uint96"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes","name":"bridgeWildCard","type":"bytes"},{"internalType":"contract ERC20","name":"feeToken","type":"address"}],"name":"previewFee","outputs":[{"internalType":"uint256","name":"fee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"publicDepositHistory","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"depositAsset","type":"address"},{"internalType":"uint256","name":"depositAmount","type":"uint256"},{"internalType":"uint256","name":"shareAmount","type":"uint256"},{"internalType":"uint256","name":"depositTimestamp","type":"uint256"},{"internalType":"uint256","name":"shareLockUpPeriodAtTimeOfDeposit","type":"uint256"}],"name":"refundDeposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"chainId","type":"uint32"}],"name":"removeChain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract Authority","name":"newAuthority","type":"address"}],"name":"setAuthority","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"chainId","type":"uint32"},{"internalType":"uint128","name":"messageGasLimit","type":"uint128"}],"name":"setChainGasLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_delegate","type":"address"}],"name":"setDelegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_eid","type":"uint32"},{"internalType":"bytes32","name":"_peer","type":"bytes32"}],"name":"setPeer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_shareLockPeriod","type":"uint64"}],"name":"setShareLockPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"shareLockPeriod","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"shareUnlockTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"chainId","type":"uint32"}],"name":"stopMessagesFromChain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"chainId","type":"uint32"}],"name":"stopMessagesToChain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"toDenyList","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ERC20","name":"asset","type":"address"},{"internalType":"bool","name":"allowDeposits","type":"bool"},{"internalType":"bool","name":"allowWithdraws","type":"bool"},{"internalType":"uint16","name":"sharePremium","type":"uint16"}],"name":"updateAssetData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"vault","outputs":[{"internalType":"contract BoringVault","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
610140604052600160025534801562000016575f80fd5b5060405162004b8f38038062004b8f833981016040819052620000399162000237565b5f80546001600160a01b0389166001600160a01b0319918216811783556001805490921690915560405185928592849284928d928d928d928d9286928692869286928692919033907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908490a36040516001600160a01b0382169033907fa3396fd7f6e0a21b50e5089d2da70d5ac0a3bbbd1f617a93f134b76389980198905f90a350506001600160a01b03831660808190526040805163313ce56760e01b8152905163313ce567916004808201926020929091908290030181865afa15801562000126573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906200014c9190620002c7565b6200015990600a620003ff565b60c0526001600160a01b0391821660a052811660e05288811661010052871695506200019e94505050505057604051632d618d8160e21b815260040160405180910390fd5b6101005160405163ca5eb5e160e01b81526001600160a01b0383811660048301529091169063ca5eb5e1906024015f604051808303815f87803b158015620001e4575f80fd5b505af1158015620001f7573d5f803e3d5ffd5b5050506001600160a01b0390951661012052506200040f9950505050505050505050565b80516001600160a01b038116811462000232575f80fd5b919050565b5f805f805f805f60e0888a0312156200024e575f80fd5b62000259886200021b565b965062000269602089016200021b565b955062000279604089016200021b565b945062000289606089016200021b565b935062000299608089016200021b565b9250620002a960a089016200021b565b9150620002b960c089016200021b565b905092959891949750929550565b5f60208284031215620002d8575f80fd5b815160ff81168114620002e9575f80fd5b9392505050565b634e487b7160e01b5f52601160045260245ffd5b600181815b808511156200034457815f1904821115620003285762000328620002f0565b808516156200033657918102915b93841c939080029062000309565b509250929050565b5f826200035c57506001620003f9565b816200036a57505f620003f9565b81600181146200038357600281146200038e57620003ae565b6001915050620003f9565b60ff841115620003a257620003a2620002f0565b50506001821b620003f9565b5060208310610133831016604e8410600b8410161715620003d3575081810a620003f9565b620003df838362000304565b805f1904821115620003f557620003f5620002f0565b0290505b92915050565b5f620002e960ff8416836200034c565b60805160a05160c05160e051610100516101205161469e620004f15f395f8181613121015261343801525f818161072301528181610e77015281816124e50152818161364e01528181613748015281816139850152613a3c01525f81816103ae01528181610c8d01528181610d0a01528181610d580152611ac801525f81816117ab0152612b4d01525f81816106d10152818161173c0152612b6f01525f8181610afa01528181610d2e0152818161180901528181611b02015281816128c901528181612c5401528181612f5901528181612ff9015261351b015261469e5ff3fe608060405260043610610341575f3560e01c80635f45bac8116101bd578063b92d0eff116100f2578063d555f36811610092578063f07f287d1161006d578063f07f287d14610a9c578063f2fde38b14610aca578063fbfa77cf14610ae9578063ff7bd03d14610b1c575f80fd5b8063d555f36814610a27578063d7424e3314610a46578063de35f5cb14610a65575f80fd5b8063c29d2f10116100cd578063c29d2f1014610967578063ca5eb5e114610986578063cab716e8146109a5578063d1822216146109b8575f80fd5b8063b92d0eff1461090b578063bb0b6a531461091d578063bf7e214f14610948575f80fd5b80639a94d3d01161015d578063a924bf6111610138578063a924bf611461088e578063abd626b0146108ad578063b187bd26146108cc578063b5ba6182146108ec575f80fd5b80639a94d3d01461081e5780639d574420146108495780639fdb11b614610868575f80fd5b80638456cb59116101985780638456cb59146107ba5780638da5cb5b146107ce5780638dfd8ba1146107ec57806394f512891461080b575f80fd5b80635f45bac8146107455780637a9e5e4b146107645780637d25a05e14610783575f80fd5b806326a64b40116102935780633f4ba83a1161023357806346b563f41161020e57806346b563f4146106a15780634fb3ccc5146106c057806355a2d64d146106f35780635e280f1114610712575f80fd5b80633f4ba83a1461060957806341fee44a1461061d57806345ad606314610682575f80fd5b806334dafd6b1161026e57806334dafd6b1461058d5780633b575407146105ac5780633d935d9e146105cb5780633e64ce99146105ea575f80fd5b806326a64b40146105215780632c524c421461054f5780633400288b1461056e575f80fd5b80631568fc58116102fe57806318aed921116102d957806318aed921146104a55780631b62636c146104c45780631ba9a458146104e3578063202eac5714610502575f80fd5b80631568fc581461043b57806317442b701461045a5780631899ea811461047a575f80fd5b806304ded84a1461034557806305921740146103885780630b48a8b81461039d5780630efe6a8b146103e857806312056e2d1461040957806313137d6514610428575b5f80fd5b348015610350575f80fd5b5061037361035f366004613b91565b60086020525f908152604090205460ff1681565b60405190151581526020015b60405180910390f35b61039b610396366004613c06565b610b3b565b005b3480156103a8575f80fd5b506103d07f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161037f565b6103fb6103f6366004613c83565b610be1565b60405190815260200161037f565b348015610414575f80fd5b5061039b610423366004613cc9565b610dea565b61039b610436366004613cfa565b610e75565b348015610446575f80fd5b5061039b610455366004613dbb565b610f30565b348015610465575f80fd5b5060408051600180825260208201520161037f565b348015610485575f80fd5b506103fb610494366004613b91565b60066020525f908152604090205481565b3480156104b0575f80fd5b5061039b6104bf366004613b91565b611005565b3480156104cf575f80fd5b5061039b6104de366004613b91565b61110d565b3480156104ee575f80fd5b5061039b6104fd366004613b91565b611189565b34801561050d575f80fd5b5061039b61051c366004613dec565b611202565b34801561052c575f80fd5b5061037361053b366004613b91565b60076020525f908152604090205460ff1681565b34801561055a575f80fd5b5061039b610569366004613b91565b6112a9565b348015610579575f80fd5b5061039b610588366004613e21565b611325565b348015610598575f80fd5b5061039b6105a7366004613e56565b611364565b3480156105b7575f80fd5b5061039b6105c6366004613b91565b6114b8565b3480156105d6575f80fd5b506103fb6105e5366004613ecd565b611534565b3480156105f5575f80fd5b506103fb610604366004613f2d565b611632565b348015610614575f80fd5b5061039b6118bf565b348015610628575f80fd5b50610661610637366004613b91565b60036020525f908152604090205460ff8082169161010081049091169062010000900461ffff1683565b604080519315158452911515602084015261ffff169082015260600161037f565b34801561068d575f80fd5b5061039b61069c366004613f74565b611927565b3480156106ac575f80fd5b5061039b6106bb366004613f8d565b6119b0565b3480156106cb575f80fd5b506103d07f000000000000000000000000000000000000000000000000000000000000000081565b3480156106fe575f80fd5b5061039b61070d366004613f74565b611bba565b34801561071d575f80fd5b506103d07f000000000000000000000000000000000000000000000000000000000000000081565b348015610750575f80fd5b5061039b61075f366004613b91565b611c5f565b34801561076f575f80fd5b5061039b61077e366004613b91565b611cd8565b34801561078e575f80fd5b506107a261079d366004613e21565b611dbc565b6040516001600160401b03909116815260200161037f565b3480156107c5575f80fd5b5061039b611dc4565b3480156107d9575f80fd5b505f546103d0906001600160a01b031681565b3480156107f7575f80fd5b5061039b610806366004613fed565b611e32565b6103fb610819366004614041565b611f4b565b348015610829575f80fd5b506103fb610838366004614105565b60056020525f908152604090205481565b348015610854575f80fd5b506103fb610863366004613f2d565b612084565b348015610873575f80fd5b506004546107a290600160601b90046001600160401b031681565b348015610899575f80fd5b5061039b6108a8366004613b91565b612149565b3480156108b8575f80fd5b5061039b6108c736600461411c565b6121c2565b3480156108d7575f80fd5b5060045461037390600160a01b900460ff1681565b3480156108f7575f80fd5b5061039b610906366004614164565b612297565b348015610916575f80fd5b50306103d0565b348015610928575f80fd5b506103fb610937366004613f74565b600a6020525f908152604090205481565b348015610953575f80fd5b506001546103d0906001600160a01b031681565b348015610972575f80fd5b5061039b610981366004613b91565b612394565b348015610991575f80fd5b5061039b6109a0366004613b91565b612495565b6103fb6109b33660046141a6565b61253f565b3480156109c3575f80fd5b50610a016109d2366004613f74565b600b6020525f908152604090205460ff808216916101008104909116906201000090046001600160801b031683565b60408051931515845291151560208401526001600160801b03169082015260600161037f565b348015610a32575f80fd5b5061039b610a41366004613f74565b612666565b348015610a51575f80fd5b506103fb610a60366004614238565b6126e6565b348015610a70575f80fd5b50600454610a84906001600160601b031681565b6040516001600160601b03909116815260200161037f565b348015610aa7575f80fd5b50610373610ab6366004613b91565b60096020525f908152604090205460ff1681565b348015610ad5575f80fd5b5061039b610ae4366004613b91565b612731565b348015610af4575f80fd5b506103d07f000000000000000000000000000000000000000000000000000000000000000081565b348015610b27575f80fd5b50610373610b363660046142ad565b6127ac565b610b50335f356001600160e01b0319166127e0565b610b755760405162461bcd60e51b8152600401610b6c906142c7565b60405180910390fd5b600254600114610b975760405162461bcd60e51b8152600401610b6c906142ed565b60028055600454600160a01b900460ff1615610bc65760405163e0f9e71d60e01b815260040160405180910390fd5b610bd4868686868686612886565b5050600160025550505050565b5f610bf7335f356001600160e01b0319166127e0565b610c135760405162461bcd60e51b8152600401610b6c906142c7565b600254600114610c355760405162461bcd60e51b8152600401610b6c906142ed565b600280555f610c43856129c0565b90505f73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03871601610d7f57345f03610c8b5760405163259be69560e11b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004015f604051808303818588803b158015610ce4575f80fd5b505af1158015610cf6573d5f803e3d5ffd5b50349850610d559350506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691507f0000000000000000000000000000000000000000000000000000000000000000905087612a7b565b507f0000000000000000000000000000000000000000000000000000000000000000945030610da1565b3415610d9e57604051631cf02cf960e21b815260040160405180910390fd5b50335b610daf868686843387612b09565b9250610ddc338787866004600c9054906101000a90046001600160401b03166001600160401b0316612cc8565b505060016002559392505050565b610dff335f356001600160e01b0319166127e0565b610e1b5760405162461bcd60e51b8152600401610b6c906142c7565b6203f480816001600160401b03161115610e4857604051631fac010160e21b815260040160405180910390fd5b600480546001600160401b03909216600160601b0267ffffffffffffffff60601b19909216919091179055565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163314610ec0576040516391ac5e4f60e01b8152336004820152602401610b6c565b60208701803590610eda90610ed5908a613f74565b612df7565b14610f1857610eec6020880188613f74565b60405163309afaf360e21b815263ffffffff909116600482015260208801356024820152604401610b6c565b610f2787878787878787612e32565b50505050505050565b610f45335f356001600160e01b0319166127e0565b610f615760405162461bcd60e51b8152600401610b6c906142c7565b806001600160801b03165f03610f8a5760405163c80ed59560e01b815260040160405180910390fd5b63ffffffff82165f818152600b6020908152604091829020805462010000600160901b031916620100006001600160801b038716908102919091178255835194855291840191909152917f0aa48359f83e8464fda3f4ea4bd3f2d6af01e90b46ab9464aa7d538e1772947a91015b60405180910390a1505050565b61101a335f356001600160e01b0319166127e0565b6110365760405162461bcd60e51b8152600401610b6c906142c7565b6001600160a01b0381165f8181526007602090815260408083208054600160ff1991821681179092556008845282852080548216831790556009909352818420805490931617909155517fd658022b1a3aaf6ad3b3c615253712807f21a8f7bc3e4996e10618175d4afb2b9190a26040516001600160a01b038216907f79fc685a7dbabb75a67df5e69a90602cef1f19bc465b060eab1ac56685e04a13905f90a26040516001600160a01b038216907f3afb02134e37f7205acf470adc2fc4ebb70614b1599a602d069790915380e2aa905f90a250565b611122335f356001600160e01b0319166127e0565b61113e5760405162461bcd60e51b8152600401610b6c906142c7565b6001600160a01b0381165f81815260096020526040808220805460ff19166001179055517f3afb02134e37f7205acf470adc2fc4ebb70614b1599a602d069790915380e2aa9190a250565b61119e335f356001600160e01b0319166127e0565b6111ba5760405162461bcd60e51b8152600401610b6c906142c7565b6001600160a01b0381165f81815260096020526040808220805460ff19169055517f77cb944c14da76928795279d1519ce9150085a06e0a53c61d5a86fc4e0fd57c69190a250565b611217335f356001600160e01b0319166127e0565b6112335760405162461bcd60e51b8152600401610b6c906142c7565b63ffffffff82165f908152600b60205260409020805460ff19166001178155611265836001600160a01b038416612eef565b6040805163ffffffff851681526001600160a01b03841660208201527fe925de263dcdbdc20307c9ab92758ed8cc0edf3d173dad4a3aa54c070f27a5439101610ff8565b6112be335f356001600160e01b0319166127e0565b6112da5760405162461bcd60e51b8152600401610b6c906142c7565b6001600160a01b0381165f81815260076020526040808220805460ff19166001179055517fd658022b1a3aaf6ad3b3c615253712807f21a8f7bc3e4996e10618175d4afb2b9190a250565b61133a335f356001600160e01b0319166127e0565b6113565760405162461bcd60e51b8152600401610b6c906142c7565b6113608282612eef565b5050565b611379335f356001600160e01b0319166127e0565b6113955760405162461bcd60e51b8152600401610b6c906142c7565b8280156113a957506001600160801b038116155b156113c75760405163c80ed59560e01b815260040160405180910390fd5b60408051606081018252851515815284151560208083019182526001600160801b0385811684860190815263ffffffff8b165f908152600b90935294909120925183549251945161ffff1990931690151561ff00191617610100941515949094029390931762010000600160901b03191662010000919093160291909117905561145a856001600160a01b038416612eef565b6040805163ffffffff871681528515156020820152841515818301526001600160a01b038416606082015290517f5dbe727bffd24a6d61a5aeef919510389c66c0deeaa82634862cf4f098961fb89181900360800190a15050505050565b6114cd335f356001600160e01b0319166127e0565b6114e95760405162461bcd60e51b8152600401610b6c906142c7565b6001600160a01b0381165f81815260086020526040808220805460ff19166001179055517f79fc685a7dbabb75a67df5e69a90602cef1f19bc465b060eab1ac56685e04a139190a250565b5f61154a335f356001600160e01b0319166127e0565b6115665760405162461bcd60e51b8152600401610b6c906142c7565b6002546001146115885760405162461bcd60e51b8152600401610b6c906142ed565b600280558773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b038216016115cb576040516316df5df960e31b815260040160405180910390fd5b5f6115d58a6129c0565b90506115e58a8a89898989612f3c565b6115f38a8a8a333386612b09565b9250611620338b8b866004600c9054906101000a90046001600160401b03166001600160401b0316612cc8565b50506001600255979650505050505050565b5f611648335f356001600160e01b0319166127e0565b6116645760405162461bcd60e51b8152600401610b6c906142c7565b600454600160a01b900460ff161561168f5760405163e0f9e71d60e01b815260040160405180910390fd5b6001600160a01b0385165f908152600360209081526040918290208251606081018452905460ff80821615158352610100820416151592820183905262010000900461ffff16928101929092526116f95760405163645fd19f60e11b815260040160405180910390fd5b845f0361171957604051630ea3153160e21b815260040160405180910390fd5b604051634104b9ed60e11b81526001600160a01b0387811660048301526117cf917f00000000000000000000000000000000000000000000000000000000000000009091169063820973da90602401602060405180830381865afa158015611783573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117a79190614311565b86907f0000000000000000000000000000000000000000000000000000000000000000613094565b9150838210156117f2576040516302620f6160e61b815260040160405180910390fd5b6040516318457e6160e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906318457e61906118469086908a90879033908c90600401614328565b5f604051808303815f87803b15801561185d575f80fd5b505af115801561186f573d5f803e3d5ffd5b50505050856001600160a01b03167fdcc60b41ff1c604459e6aa4a7299817416b19fc586a392f111646e26597c4af9866040516118ae91815260200190565b60405180910390a250949350505050565b6118d4335f356001600160e01b0319166127e0565b6118f05760405162461bcd60e51b8152600401610b6c906142c7565b6004805460ff60a01b191690556040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d16933905f90a1565b61193c335f356001600160e01b0319166127e0565b6119585760405162461bcd60e51b8152600401610b6c906142c7565b63ffffffff81165f818152600b6020908152604091829020805461ff0019168155915192835290917fc45af64a13a09ef916a1114c59589294ec9c3095f2bfbbb093a7a96656858ded91015b60405180910390a15050565b6119c5335f356001600160e01b0319166127e0565b6119e15760405162461bcd60e51b8152600401610b6c906142c7565b806119ec834261436f565b10611a0a57604051634c1eef1760e11b815260040160405180910390fd5b604080516001600160a01b038089166020830152871691810191909152606081018590526080810184905260a0810183905260c081018290525f9060e00160408051601f1981840301815291815281516020928301205f8b815260059093529120549091508114611a8e5760405163fa174ecb60e01b815260040160405180910390fd5b5f888152600560205260408120556001600160a01b03861673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611ac65785611ae8565b7f00000000000000000000000000000000000000000000000000000000000000005b6040516318457e6160e01b81529096506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906318457e6190611b3f908a908a908a9083908b90600401614328565b5f604051808303815f87803b158015611b56575f80fd5b505af1158015611b68573d5f803e3d5ffd5b50505050866001600160a01b0316887faf98ea774275cadfa3e477a7b52cba03e01197445a76bd5d0d561608708c362483604051611ba891815260200190565b60405180910390a35050505050505050565b611bcf335f356001600160e01b0319166127e0565b611beb5760405162461bcd60e51b8152600401610b6c906142c7565b63ffffffff81165f908152600b60205260408120805471ffffffffffffffffffffffffffffffffffff19169055611c23908290612eef565b60405163ffffffff821681527f11a9d1a77f76361ed131c19b1dc5758504c51dbde2e49fc973a0ef9577ad13d59060200160405180910390a150565b611c74335f356001600160e01b0319166127e0565b611c905760405162461bcd60e51b8152600401610b6c906142c7565b6001600160a01b0381165f81815260086020526040808220805460ff19169055517f039bcf51833310242b8b7c6aa0fbabf1bf2b5e5270807ee020f1920ef200666b9190a250565b5f546001600160a01b0316331480611d69575060015460405163b700961360e01b81526001600160a01b039091169063b700961390611d2a90339030906001600160e01b03195f351690600401614382565b602060405180830381865afa158015611d45573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d6991906143af565b611d71575f80fd5b600180546001600160a01b0319166001600160a01b03831690811790915560405133907fa3396fd7f6e0a21b50e5089d2da70d5ac0a3bbbd1f617a93f134b76389980198905f90a350565b5f5b92915050565b611dd9335f356001600160e01b0319166127e0565b611df55760405162461bcd60e51b8152600401610b6c906142c7565b6004805460ff60a01b1916600160a01b1790556040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e752905f90a1565b611e47335f356001600160e01b0319166127e0565b611e635760405162461bcd60e51b8152600401610b6c906142c7565b6103e861ffff82161115611e8a57604051636c5cde8760e01b815260040160405180910390fd5b6040805160608082018352851515808352851515602080850182815261ffff8881168789018181526001600160a01b038e165f818152600387528b902099518a549551925161ffff1990961690151561ff00191617610100921515929092029190911763ffff0000191662010000949093169390930291909117909655865193845290830191909152938101929092527fe08301321781ac43935a2099b2c3fd42de0a0ee87a519cac00e8c9cecd26ff12910160405180910390a250505050565b5f611f61335f356001600160e01b0319166127e0565b611f7d5760405162461bcd60e51b8152600401610b6c906142c7565b600254600114611f9f5760405162461bcd60e51b8152600401610b6c906142ed565b600280558c73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03821601611fe2576040516316df5df960e31b815260040160405180910390fd5b5f611fec8f6129c0565b9050611ffc8f8f8e8e8e8e612f3c565b61200a8f8f8f333386612b09565b925050612038338f8f856004600c9054906101000a90046001600160401b03166001600160401b0316612cc8565b6001600160601b03821115612060576040516389588ab360e01b815260040160405180910390fd5b61206e828888888888612886565b5060016002559c9b505050505050505050505050565b5f61209a335f356001600160e01b0319166127e0565b6120b65760405162461bcd60e51b8152600401610b6c906142c7565b6002546001146120d85760405162461bcd60e51b8152600401610b6c906142ed565b600280555f6120e6866129c0565b90506120f6868686338786612b09565b9150856001600160a01b03167f6f9b974223f85a1ae805c33b8b519039e2435481d949db1110de151a94d587af8660405161213391815260200190565b60405180910390a2506001600255949350505050565b61215e335f356001600160e01b0319166127e0565b61217a5760405162461bcd60e51b8152600401610b6c906142c7565b6001600160a01b0381165f81815260076020526040808220805460ff19169055517fae893dda71e2eee548f8291f458cceae4bd22b56a79906928591e4420444c0e99190a250565b6001600160a01b0383165f9081526007602052604090205460ff16806121ff57506001600160a01b0382165f9081526008602052604090205460ff165b8061222157506001600160a01b0381165f9081526009602052604090205460ff165b1561225a57604051632821264f60e01b81526001600160a01b038085166004830152808416602483015282166044820152606401610b6c565b6001600160a01b0383165f908152600660205260409020544210156122925760405163f64059db60e01b815260040160405180910390fd5b505050565b6122ac335f356001600160e01b0319166127e0565b6122c85760405162461bcd60e51b8152600401610b6c906142c7565b806001600160801b03165f036122f15760405163c80ed59560e01b815260040160405180910390fd5b63ffffffff83165f908152600b60205260409020805461010071ffffffffffffffffffffffffffffffffff0019909116620100006001600160801b0385160217178155612347846001600160a01b038516612eef565b6040805163ffffffff861681526001600160a01b03851660208201527f34fe916485e02ec88e487b0e611e5c9bacabba9e3eaae7a900aa08be8197d419910160405180910390a150505050565b6123a9335f356001600160e01b0319166127e0565b6123c55760405162461bcd60e51b8152600401610b6c906142c7565b6001600160a01b0381165f818152600760209081526040808320805460ff199081169091556008835281842080548216905560099092528083208054909216909155517fae893dda71e2eee548f8291f458cceae4bd22b56a79906928591e4420444c0e99190a26040516001600160a01b038216907f039bcf51833310242b8b7c6aa0fbabf1bf2b5e5270807ee020f1920ef200666b905f90a26040516001600160a01b038216907f77cb944c14da76928795279d1519ce9150085a06e0a53c61d5a86fc4e0fd57c6905f90a250565b6124aa335f356001600160e01b0319166127e0565b6124c65760405162461bcd60e51b8152600401610b6c906142c7565b60405163ca5eb5e160e01b81526001600160a01b0382811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063ca5eb5e1906024015f604051808303815f87803b158015612526575f80fd5b505af1158015612538573d5f803e3d5ffd5b5050505050565b5f612555335f356001600160e01b0319166127e0565b6125715760405162461bcd60e51b8152600401610b6c906142c7565b6002546001146125935760405162461bcd60e51b8152600401610b6c906142ed565b600280558873eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b038216016125d6576040516316df5df960e31b815260040160405180910390fd5b5f6125e08b6129c0565b90506125f08b8b8b333386612b09565b925061261d338c8c866004600c9054906101000a90046001600160401b03166001600160401b0316612cc8565b6001600160601b03831115612645576040516389588ab360e01b815260040160405180910390fd5b612653838989898989612886565b5050600160025598975050505050505050565b61267b335f356001600160e01b0319166127e0565b6126975760405162461bcd60e51b8152600401610b6c906142c7565b63ffffffff81165f818152600b6020908152604091829020805460ff19168155915192835290917f1cb867ed6a020e020ea220d4f48bb8e36552abf9095e093e377d33933f2b31e491016119a4565b604080518082019091526001600160601b03861681526001600160a01b03851660208201525f9081612717826130af565b9050612725818787876130f6565b98975050505050505050565b612746335f356001600160e01b0319166127e0565b6127625760405162461bcd60e51b8152600401610b6c906142c7565b5f80546001600160a01b0319166001600160a01b0383169081178255604051909133917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a350565b5f60208201803590600a9083906127c39086613f74565b63ffffffff16815260208101919091526040015f20541492915050565b6001545f906001600160a01b03168015801590612867575060405163b700961360e01b81526001600160a01b0382169063b70096139061282890879030908890600401614382565b602060405180830381865afa158015612843573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061286791906143af565b8061287e57505f546001600160a01b038581169116145b949350505050565b612891335f336121c2565b6040516318457e6160e01b81525f600482018190526024820181905260448201523360648201526001600160601b03871660848201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906318457e619060a4015f604051808303815f87803b158015612912575f80fd5b505af1158015612924573d5f803e3d5ffd5b5050604080518082019091526001600160601b03891681526001600160a01b038816602082015291505f9050612959826130af565b90505f61296982888888886132c5565b6040516001600160601b038b1681529091506001600160a01b0389169082907fe0ec62d39b054dc2fd626dbc271483735df6e6fa1ef8389754bf8ab27a75eab29060200160405180910390a3505050505050505050565b604080516060810182525f8082526020820181905291810191909152600454600160a01b900460ff1615612a075760405163e0f9e71d60e01b815260040160405180910390fd5b506001600160a01b0381165f908152600360209081526040918290208251606081018452905460ff8082161515808452610100830490911615159383019390935262010000900461ffff1692810192909252612a765760405163645fd19f60e11b815260040160405180910390fd5b919050565b5f60405163095ea7b360e01b81526001600160a01b038416600482015282602482015260205f6044835f895af191505080601f3d1160015f511416151615612ac55750823b153d17155b80612b035760405162461bcd60e51b815260206004820152600e60248201526d1054141493d59157d1905253115160921b6044820152606401610b6c565b50505050565b5f855f03612b2a5760405163259be69560e11b815260040160405180910390fd5b604051634104b9ed60e11b81526001600160a01b038881166004830152612be0917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000169063820973da90602401602060405180830381865afa158015612bb4573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612bd89190614311565b889190613094565b90505f826040015161ffff1611612bf75780612c1a565b612c1a8260400151612710612c0c91906143ca565b829061ffff16612710613094565b905084811015612c3d5760405163097b2ad560e31b815260040160405180910390fd5b604051631ceb5d1960e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906339d6ba3290612c919087908b908b9089908890600401614328565b5f604051808303815f87803b158015612ca8575f80fd5b505af1158015612cba573d5f803e3d5ffd5b505050509695505050505050565b600480545f91908290612ce3906001600160601b03166143ec565b82546001600160601b039182166101009390930a838102920219161790915590508115612d8757612d148242614411565b6001600160a01b038781165f81815260066020908152604091829020949094558051938401919091529087169082015260608101859052608081018490524260a082015260c0810183905260e00160408051601f1981840301815291815281516020928301205f84815260059093529120555b846001600160a01b0316866001600160a01b0316827fe96d7872363f475d18b2f5390caaa5eaa96b2d38e42c62afe4ac08ebd2b13c3a87874288604051612de7949392919093845260208401929092526040830152606082015260800190565b60405180910390a4505050505050565b63ffffffff81165f908152600a602052604081205480611dbe5760405163f6ff4fb760e01b815263ffffffff84166004820152602401610b6c565b5f600b81612e4360208b018b613f74565b63ffffffff16815260208082019290925260409081015f208151606081018352905460ff808216151580845261010083049091161515948301949094526201000090046001600160801b0316918101919091529150612ecb57612ea96020890189613f74565b6040516315b73a2960e21b815263ffffffff9091166004820152602401610b6c565b5f612ed886880188614105565b9050612ee488826134e8565b505050505050505050565b63ffffffff82165f818152600a6020908152604091829020849055815192835282018390527f238399d427b947898edb290f5ff0f9109849b1c3ba196a42e35f00c50a54b98b91016119a4565b60405163d505accf60e01b81523360048201526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166024830152604482018790526064820186905260ff8516608483015260a4820184905260c4820183905287169063d505accf9060e4015f604051808303815f87803b158015612fc7575f80fd5b505af1925050508015612fd8575060015b61308c57604051636eb1769f60e11b81523360048201526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116602483015286919088169063dd62ed3e90604401602060405180830381865afa158015613049573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061306d9190614311565b101561308c576040516301b8851f60e41b815260040160405180910390fd5b505050505050565b5f825f1904841183021582026130a8575f80fd5b5091020490565b80515f906001600160601b0310156130da57604051633524486360e01b815260040160405180910390fd5b81516020909201516001600160a01b031660a09290921b171790565b5f6001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1480159061315657507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031614155b1561317457604051637f3cd08160e11b815260040160405180910390fd5b5f61318184860186613f74565b63ffffffff81165f908152600b60209081526040918290208251606081018452905460ff8082161515835261010082041615159282018390526201000090046001600160801b031692810192909252919250906131f95760405163420eae3760e01b815263ffffffff83166004820152602401610b6c565b5f8760405160200161320d91815260200190565b60405160208183030381529060405290505f61325583604001515f61324e60408051600360f01b602082015281516002818303018152602290910190915290565b91906135d4565b90505f6132848584846001600160a01b038b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613639565b90506001600160a01b03871673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee146132b45780602001516132b7565b80515b9a9950505050505050505050565b5f806132d385870187613f74565b63ffffffff81165f908152600b60209081526040918290208251606081018452905460ff8082161515835261010082041615159282018390526201000090046001600160801b0316928101929092529192509061334b5760405163420eae3760e01b815263ffffffff83166004820152602401610b6c565b5f8860405160200161335f91815260200190565b60405160208183030381529060405290505f6133a083604001515f61324e60408051600360f01b602082015281516002818303018152602290910190915290565b90505f6133cf8584846001600160a01b038c1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613639565b905073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b0389160161343657805187101561343157805160405163f5ac3fa760e01b815263ffffffff87166004820152602481019190915260448101889052606401610b6c565b6134c9565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316886001600160a01b0316036134b057868160200151111561343157602081015160405163f5ac3fa760e01b815263ffffffff87166004820152602481019190915260448101889052606401610b6c565b604051637f3cd08160e11b815260040160405180910390fd5b5f6134d78685858533613717565b519c9b505050505050505050505050565b60408051808201825260a083901c8082526001600160a01b03808516602084018190529351631ceb5d1960e11b815292937f0000000000000000000000000000000000000000000000000000000000000000909116926339d6ba3292613557925f928392839291600401614328565b5f604051808303815f87803b15801561356e575f80fd5b505af1158015613580573d5f803e3d5ffd5b5050505080602001516001600160a01b0316837fb944fddc61d7fedb8b736790454ba972000703b0d21c7481d6dbf95b7c2cc2f1835f01516040516135c791815260200190565b60405180910390a3505050565b60608360036135e3825f61381d565b61ffff1614613616576135f6815f61381d565b604051633a51740d60e01b815261ffff9091166004820152602401610b6c565b5f6136218585613879565b905061362f866001836138f2565b9695505050505050565b604080518082019091525f80825260208201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ddc28c586040518060a001604052808863ffffffff16815260200161369b89612df7565b8152602001878152602001868152602001851515815250306040518363ffffffff1660e01b81526004016136d0929190614471565b6040805180830381865afa1580156136ea573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061370e9190614541565b95945050505050565b61371f613b2c565b5f61372c845f015161395b565b602085015190915015613746576137468460200151613982565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632637a450826040518060a001604052808b63ffffffff1681526020016137968c612df7565b81526020018a81526020018981526020015f8960200151111515815250866040518463ffffffff1660e01b81526004016137d1929190614471565b60806040518083038185885af11580156137ed573d5f803e3d5ffd5b50505050506040513d601f19601f82011682018060405250810190613812919061455b565b979650505050505050565b5f613829826002614411565b835110156138705760405162461bcd60e51b8152602060048201526014602482015273746f55696e7431365f6f75744f66426f756e647360601b6044820152606401610b6c565b50016002015190565b60606001600160801b038216156138c157604080516001600160801b0319608086811b8216602084015285901b166030820152016040516020818303038152906040526138eb565b6040516001600160801b0319608085901b1660208201526030016040516020818303038152906040525b9392505050565b6060836003613901825f61381d565b61ffff1614613914576135f6815f61381d565b8460016139218551613a61565b61392c9060016145cc565b86866040516020016139429594939291906145e7565b6040516020818303038152906040529150509392505050565b5f81341461397e576040516304fb820960e51b8152346004820152602401610b6c565b5090565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e4fe1d946040518163ffffffff1660e01b8152600401602060405180830381865afa1580156139df573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613a03919061464d565b90506001600160a01b038116613a2c576040516329b99a9560e11b815260040160405180910390fd5b6113606001600160a01b038216337f000000000000000000000000000000000000000000000000000000000000000085613a8f565b5f61ffff82111561397e576040516306dfcc6560e41b81526010600482015260248101839052604401610b6c565b5f6040516323b872dd60e01b81526001600160a01b03851660048201526001600160a01b038416602482015282604482015260205f6064835f8a5af191505080601f3d1160015f511416151615613ae85750833b153d17155b806125385760405162461bcd60e51b81526020600482015260146024820152731514905394d1915497d19493d357d1905253115160621b6044820152606401610b6c565b60405180606001604052805f80191681526020015f6001600160401b03168152602001613b6a60405180604001604052805f81526020015f81525090565b905290565b6001600160a01b0381168114613b83575f80fd5b50565b8035612a7681613b6f565b5f60208284031215613ba1575f80fd5b81356138eb81613b6f565b80356001600160601b0381168114612a76575f80fd5b5f8083601f840112613bd2575f80fd5b5081356001600160401b03811115613be8575f80fd5b602083019150836020828501011115613bff575f80fd5b9250929050565b5f805f805f8060a08789031215613c1b575f80fd5b613c2487613bac565b95506020870135613c3481613b6f565b945060408701356001600160401b03811115613c4e575f80fd5b613c5a89828a01613bc2565b9095509350506060870135613c6e81613b6f565b80925050608087013590509295509295509295565b5f805f60608486031215613c95575f80fd5b8335613ca081613b6f565b95602085013595506040909401359392505050565b6001600160401b0381168114613b83575f80fd5b5f60208284031215613cd9575f80fd5b81356138eb81613cb5565b5f60608284031215613cf4575f80fd5b50919050565b5f805f805f805f60e0888a031215613d10575f80fd5b613d1a8989613ce4565b96506060880135955060808801356001600160401b0380821115613d3c575f80fd5b613d488b838c01613bc2565b909750955060a08a01359150613d5d82613b6f565b90935060c08901359080821115613d72575f80fd5b50613d7f8a828b01613bc2565b989b979a50959850939692959293505050565b803563ffffffff81168114612a76575f80fd5b80356001600160801b0381168114612a76575f80fd5b5f8060408385031215613dcc575f80fd5b613dd583613d92565b9150613de360208401613da5565b90509250929050565b5f8060408385031215613dfd575f80fd5b613e0683613d92565b91506020830135613e1681613b6f565b809150509250929050565b5f8060408385031215613e32575f80fd5b613e3b83613d92565b946020939093013593505050565b8015158114613b83575f80fd5b5f805f805f60a08688031215613e6a575f80fd5b613e7386613d92565b94506020860135613e8381613e49565b93506040860135613e9381613e49565b92506060860135613ea381613b6f565b9150613eb160808701613da5565b90509295509295909350565b803560ff81168114612a76575f80fd5b5f805f805f805f60e0888a031215613ee3575f80fd5b8735613eee81613b6f565b9650602088013595506040880135945060608801359350613f1160808901613ebd565b925060a0880135915060c0880135905092959891949750929550565b5f805f8060808587031215613f40575f80fd5b8435613f4b81613b6f565b935060208501359250604085013591506060850135613f6981613b6f565b939692955090935050565b5f60208284031215613f84575f80fd5b6138eb82613d92565b5f805f805f805f60e0888a031215613fa3575f80fd5b873596506020880135613fb581613b6f565b95506040880135613fc581613b6f565b969995985095966060810135965060808101359560a0820135955060c0909101359350915050565b5f805f8060808587031215614000575f80fd5b843561400b81613b6f565b9350602085013561401b81613e49565b9250604085013561402b81613e49565b9150606085013561ffff81168114613f69575f80fd5b5f805f805f805f805f805f806101608d8f03121561405d575f80fd5b6140678d35613b6f565b8c359b5060208d01359a5060408d0135995060608d0135985061408c60808e01613ebd565b975060a08d0135965060c08d013595506140a960e08e0135613b6f565b60e08d013594506001600160401b036101008e013511156140c8575f80fd5b6140d98e6101008f01358f01613bc2565b90945092506140eb6101208e01613b86565b91506101408d013590509295989b509295989b509295989b565b5f60208284031215614115575f80fd5b5035919050565b5f805f6060848603121561412e575f80fd5b833561413981613b6f565b9250602084013561414981613b6f565b9150604084013561415981613b6f565b809150509250925092565b5f805f60608486031215614176575f80fd5b61417f84613d92565b9250602084013561418f81613b6f565b915061419d60408501613da5565b90509250925092565b5f805f805f805f8060e0898b0312156141bd575f80fd5b88356141c881613b6f565b9750602089013596506040890135955060608901356141e681613b6f565b945060808901356001600160401b03811115614200575f80fd5b61420c8b828c01613bc2565b90955093505060a089013561422081613b6f565b8092505060c089013590509295985092959890939650565b5f805f805f6080868803121561424c575f80fd5b61425586613bac565b9450602086013561426581613b6f565b935060408601356001600160401b0381111561427f575f80fd5b61428b88828901613bc2565b909450925050606086013561429f81613b6f565b809150509295509295909350565b5f606082840312156142bd575f80fd5b6138eb8383613ce4565b6020808252600c908201526b15539055551213d49256915160a21b604082015260600190565b6020808252600a90820152695245454e5452414e435960b01b604082015260600190565b5f60208284031215614321575f80fd5b5051919050565b6001600160a01b039586168152938516602085015260408401929092529092166060820152608081019190915260a00190565b634e487b7160e01b5f52601160045260245ffd5b81810381811115611dbe57611dbe61435b565b6001600160a01b0393841681529190921660208201526001600160e01b0319909116604082015260600190565b5f602082840312156143bf575f80fd5b81516138eb81613e49565b61ffff8281168282160390808211156143e5576143e561435b565b5092915050565b5f6001600160601b038083168181036144075761440761435b565b6001019392505050565b80820180821115611dbe57611dbe61435b565b5f5b8381101561443e578181015183820152602001614426565b50505f910152565b5f815180845261445d816020860160208601614424565b601f01601f19169290920160200192915050565b6040815263ffffffff8351166040820152602083015160608201525f604084015160a060808401526144a660e0840182614446565b90506060850151603f198483030160a08501526144c38282614446565b60809690960151151560c08501525050506001600160a01b039190911660209091015290565b5f604082840312156144f9575f80fd5b604051604081018181106001600160401b038211171561452757634e487b7160e01b5f52604160045260245ffd5b604052825181526020928301519281019290925250919050565b5f60408284031215614551575f80fd5b6138eb83836144e9565b5f6080828403121561456b575f80fd5b604051606081018181106001600160401b038211171561459957634e487b7160e01b5f52604160045260245ffd5b6040528251815260208301516145ae81613cb5565b60208201526145c084604085016144e9565b60408201529392505050565b61ffff8181168382160190808211156143e5576143e561435b565b5f86516145f8818460208b01614424565b6001600160f81b031960f888811b82169285019283526001600160f01b031960f089901b16600184015286901b166003820152835161463e816004840160208801614424565b01600401979650505050505050565b5f6020828403121561465d575f80fd5b81516138eb81613b6f56fea2646970667358221220cb71701720759819c3db6acbf1de0eac330b5b6a96d2a7821d79070002a95ccd64736f6c63430008150033000000000000000000000000771263e3bc6acda5ae388a3f8a0c2dd7a17275fc000000000000000000000000279cad277447965af3d24a78197aad1b02a2c58900000000000000000000000003d9a9ce13d16c7cfce564f41bd7e85e5cde8da6000000000000000000000000ee7d8bcfb72bc1880d0cf19822eb0a2e6577ab620000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b000000000000000000000000771263e3bc6acda5ae388a3f8a0c2dd7a17275fc0000000000000000000000000000000000000000000000000000000000000001
Deployed Bytecode
0x608060405260043610610341575f3560e01c80635f45bac8116101bd578063b92d0eff116100f2578063d555f36811610092578063f07f287d1161006d578063f07f287d14610a9c578063f2fde38b14610aca578063fbfa77cf14610ae9578063ff7bd03d14610b1c575f80fd5b8063d555f36814610a27578063d7424e3314610a46578063de35f5cb14610a65575f80fd5b8063c29d2f10116100cd578063c29d2f1014610967578063ca5eb5e114610986578063cab716e8146109a5578063d1822216146109b8575f80fd5b8063b92d0eff1461090b578063bb0b6a531461091d578063bf7e214f14610948575f80fd5b80639a94d3d01161015d578063a924bf6111610138578063a924bf611461088e578063abd626b0146108ad578063b187bd26146108cc578063b5ba6182146108ec575f80fd5b80639a94d3d01461081e5780639d574420146108495780639fdb11b614610868575f80fd5b80638456cb59116101985780638456cb59146107ba5780638da5cb5b146107ce5780638dfd8ba1146107ec57806394f512891461080b575f80fd5b80635f45bac8146107455780637a9e5e4b146107645780637d25a05e14610783575f80fd5b806326a64b40116102935780633f4ba83a1161023357806346b563f41161020e57806346b563f4146106a15780634fb3ccc5146106c057806355a2d64d146106f35780635e280f1114610712575f80fd5b80633f4ba83a1461060957806341fee44a1461061d57806345ad606314610682575f80fd5b806334dafd6b1161026e57806334dafd6b1461058d5780633b575407146105ac5780633d935d9e146105cb5780633e64ce99146105ea575f80fd5b806326a64b40146105215780632c524c421461054f5780633400288b1461056e575f80fd5b80631568fc58116102fe57806318aed921116102d957806318aed921146104a55780631b62636c146104c45780631ba9a458146104e3578063202eac5714610502575f80fd5b80631568fc581461043b57806317442b701461045a5780631899ea811461047a575f80fd5b806304ded84a1461034557806305921740146103885780630b48a8b81461039d5780630efe6a8b146103e857806312056e2d1461040957806313137d6514610428575b5f80fd5b348015610350575f80fd5b5061037361035f366004613b91565b60086020525f908152604090205460ff1681565b60405190151581526020015b60405180910390f35b61039b610396366004613c06565b610b3b565b005b3480156103a8575f80fd5b506103d07f000000000000000000000000ee7d8bcfb72bc1880d0cf19822eb0a2e6577ab6281565b6040516001600160a01b03909116815260200161037f565b6103fb6103f6366004613c83565b610be1565b60405190815260200161037f565b348015610414575f80fd5b5061039b610423366004613cc9565b610dea565b61039b610436366004613cfa565b610e75565b348015610446575f80fd5b5061039b610455366004613dbb565b610f30565b348015610465575f80fd5b5060408051600180825260208201520161037f565b348015610485575f80fd5b506103fb610494366004613b91565b60066020525f908152604090205481565b3480156104b0575f80fd5b5061039b6104bf366004613b91565b611005565b3480156104cf575f80fd5b5061039b6104de366004613b91565b61110d565b3480156104ee575f80fd5b5061039b6104fd366004613b91565b611189565b34801561050d575f80fd5b5061039b61051c366004613dec565b611202565b34801561052c575f80fd5b5061037361053b366004613b91565b60076020525f908152604090205460ff1681565b34801561055a575f80fd5b5061039b610569366004613b91565b6112a9565b348015610579575f80fd5b5061039b610588366004613e21565b611325565b348015610598575f80fd5b5061039b6105a7366004613e56565b611364565b3480156105b7575f80fd5b5061039b6105c6366004613b91565b6114b8565b3480156105d6575f80fd5b506103fb6105e5366004613ecd565b611534565b3480156105f5575f80fd5b506103fb610604366004613f2d565b611632565b348015610614575f80fd5b5061039b6118bf565b348015610628575f80fd5b50610661610637366004613b91565b60036020525f908152604090205460ff8082169161010081049091169062010000900461ffff1683565b604080519315158452911515602084015261ffff169082015260600161037f565b34801561068d575f80fd5b5061039b61069c366004613f74565b611927565b3480156106ac575f80fd5b5061039b6106bb366004613f8d565b6119b0565b3480156106cb575f80fd5b506103d07f00000000000000000000000003d9a9ce13d16c7cfce564f41bd7e85e5cde8da681565b3480156106fe575f80fd5b5061039b61070d366004613f74565b611bba565b34801561071d575f80fd5b506103d07f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b81565b348015610750575f80fd5b5061039b61075f366004613b91565b611c5f565b34801561076f575f80fd5b5061039b61077e366004613b91565b611cd8565b34801561078e575f80fd5b506107a261079d366004613e21565b611dbc565b6040516001600160401b03909116815260200161037f565b3480156107c5575f80fd5b5061039b611dc4565b3480156107d9575f80fd5b505f546103d0906001600160a01b031681565b3480156107f7575f80fd5b5061039b610806366004613fed565b611e32565b6103fb610819366004614041565b611f4b565b348015610829575f80fd5b506103fb610838366004614105565b60056020525f908152604090205481565b348015610854575f80fd5b506103fb610863366004613f2d565b612084565b348015610873575f80fd5b506004546107a290600160601b90046001600160401b031681565b348015610899575f80fd5b5061039b6108a8366004613b91565b612149565b3480156108b8575f80fd5b5061039b6108c736600461411c565b6121c2565b3480156108d7575f80fd5b5060045461037390600160a01b900460ff1681565b3480156108f7575f80fd5b5061039b610906366004614164565b612297565b348015610916575f80fd5b50306103d0565b348015610928575f80fd5b506103fb610937366004613f74565b600a6020525f908152604090205481565b348015610953575f80fd5b506001546103d0906001600160a01b031681565b348015610972575f80fd5b5061039b610981366004613b91565b612394565b348015610991575f80fd5b5061039b6109a0366004613b91565b612495565b6103fb6109b33660046141a6565b61253f565b3480156109c3575f80fd5b50610a016109d2366004613f74565b600b6020525f908152604090205460ff808216916101008104909116906201000090046001600160801b031683565b60408051931515845291151560208401526001600160801b03169082015260600161037f565b348015610a32575f80fd5b5061039b610a41366004613f74565b612666565b348015610a51575f80fd5b506103fb610a60366004614238565b6126e6565b348015610a70575f80fd5b50600454610a84906001600160601b031681565b6040516001600160601b03909116815260200161037f565b348015610aa7575f80fd5b50610373610ab6366004613b91565b60096020525f908152604090205460ff1681565b348015610ad5575f80fd5b5061039b610ae4366004613b91565b612731565b348015610af4575f80fd5b506103d07f000000000000000000000000279cad277447965af3d24a78197aad1b02a2c58981565b348015610b27575f80fd5b50610373610b363660046142ad565b6127ac565b610b50335f356001600160e01b0319166127e0565b610b755760405162461bcd60e51b8152600401610b6c906142c7565b60405180910390fd5b600254600114610b975760405162461bcd60e51b8152600401610b6c906142ed565b60028055600454600160a01b900460ff1615610bc65760405163e0f9e71d60e01b815260040160405180910390fd5b610bd4868686868686612886565b5050600160025550505050565b5f610bf7335f356001600160e01b0319166127e0565b610c135760405162461bcd60e51b8152600401610b6c906142c7565b600254600114610c355760405162461bcd60e51b8152600401610b6c906142ed565b600280555f610c43856129c0565b90505f73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03871601610d7f57345f03610c8b5760405163259be69560e11b815260040160405180910390fd5b7f000000000000000000000000ee7d8bcfb72bc1880d0cf19822eb0a2e6577ab626001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004015f604051808303818588803b158015610ce4575f80fd5b505af1158015610cf6573d5f803e3d5ffd5b50349850610d559350506001600160a01b037f000000000000000000000000ee7d8bcfb72bc1880d0cf19822eb0a2e6577ab621691507f000000000000000000000000279cad277447965af3d24a78197aad1b02a2c589905087612a7b565b507f000000000000000000000000ee7d8bcfb72bc1880d0cf19822eb0a2e6577ab62945030610da1565b3415610d9e57604051631cf02cf960e21b815260040160405180910390fd5b50335b610daf868686843387612b09565b9250610ddc338787866004600c9054906101000a90046001600160401b03166001600160401b0316612cc8565b505060016002559392505050565b610dff335f356001600160e01b0319166127e0565b610e1b5760405162461bcd60e51b8152600401610b6c906142c7565b6203f480816001600160401b03161115610e4857604051631fac010160e21b815260040160405180910390fd5b600480546001600160401b03909216600160601b0267ffffffffffffffff60601b19909216919091179055565b7f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b03163314610ec0576040516391ac5e4f60e01b8152336004820152602401610b6c565b60208701803590610eda90610ed5908a613f74565b612df7565b14610f1857610eec6020880188613f74565b60405163309afaf360e21b815263ffffffff909116600482015260208801356024820152604401610b6c565b610f2787878787878787612e32565b50505050505050565b610f45335f356001600160e01b0319166127e0565b610f615760405162461bcd60e51b8152600401610b6c906142c7565b806001600160801b03165f03610f8a5760405163c80ed59560e01b815260040160405180910390fd5b63ffffffff82165f818152600b6020908152604091829020805462010000600160901b031916620100006001600160801b038716908102919091178255835194855291840191909152917f0aa48359f83e8464fda3f4ea4bd3f2d6af01e90b46ab9464aa7d538e1772947a91015b60405180910390a1505050565b61101a335f356001600160e01b0319166127e0565b6110365760405162461bcd60e51b8152600401610b6c906142c7565b6001600160a01b0381165f8181526007602090815260408083208054600160ff1991821681179092556008845282852080548216831790556009909352818420805490931617909155517fd658022b1a3aaf6ad3b3c615253712807f21a8f7bc3e4996e10618175d4afb2b9190a26040516001600160a01b038216907f79fc685a7dbabb75a67df5e69a90602cef1f19bc465b060eab1ac56685e04a13905f90a26040516001600160a01b038216907f3afb02134e37f7205acf470adc2fc4ebb70614b1599a602d069790915380e2aa905f90a250565b611122335f356001600160e01b0319166127e0565b61113e5760405162461bcd60e51b8152600401610b6c906142c7565b6001600160a01b0381165f81815260096020526040808220805460ff19166001179055517f3afb02134e37f7205acf470adc2fc4ebb70614b1599a602d069790915380e2aa9190a250565b61119e335f356001600160e01b0319166127e0565b6111ba5760405162461bcd60e51b8152600401610b6c906142c7565b6001600160a01b0381165f81815260096020526040808220805460ff19169055517f77cb944c14da76928795279d1519ce9150085a06e0a53c61d5a86fc4e0fd57c69190a250565b611217335f356001600160e01b0319166127e0565b6112335760405162461bcd60e51b8152600401610b6c906142c7565b63ffffffff82165f908152600b60205260409020805460ff19166001178155611265836001600160a01b038416612eef565b6040805163ffffffff851681526001600160a01b03841660208201527fe925de263dcdbdc20307c9ab92758ed8cc0edf3d173dad4a3aa54c070f27a5439101610ff8565b6112be335f356001600160e01b0319166127e0565b6112da5760405162461bcd60e51b8152600401610b6c906142c7565b6001600160a01b0381165f81815260076020526040808220805460ff19166001179055517fd658022b1a3aaf6ad3b3c615253712807f21a8f7bc3e4996e10618175d4afb2b9190a250565b61133a335f356001600160e01b0319166127e0565b6113565760405162461bcd60e51b8152600401610b6c906142c7565b6113608282612eef565b5050565b611379335f356001600160e01b0319166127e0565b6113955760405162461bcd60e51b8152600401610b6c906142c7565b8280156113a957506001600160801b038116155b156113c75760405163c80ed59560e01b815260040160405180910390fd5b60408051606081018252851515815284151560208083019182526001600160801b0385811684860190815263ffffffff8b165f908152600b90935294909120925183549251945161ffff1990931690151561ff00191617610100941515949094029390931762010000600160901b03191662010000919093160291909117905561145a856001600160a01b038416612eef565b6040805163ffffffff871681528515156020820152841515818301526001600160a01b038416606082015290517f5dbe727bffd24a6d61a5aeef919510389c66c0deeaa82634862cf4f098961fb89181900360800190a15050505050565b6114cd335f356001600160e01b0319166127e0565b6114e95760405162461bcd60e51b8152600401610b6c906142c7565b6001600160a01b0381165f81815260086020526040808220805460ff19166001179055517f79fc685a7dbabb75a67df5e69a90602cef1f19bc465b060eab1ac56685e04a139190a250565b5f61154a335f356001600160e01b0319166127e0565b6115665760405162461bcd60e51b8152600401610b6c906142c7565b6002546001146115885760405162461bcd60e51b8152600401610b6c906142ed565b600280558773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b038216016115cb576040516316df5df960e31b815260040160405180910390fd5b5f6115d58a6129c0565b90506115e58a8a89898989612f3c565b6115f38a8a8a333386612b09565b9250611620338b8b866004600c9054906101000a90046001600160401b03166001600160401b0316612cc8565b50506001600255979650505050505050565b5f611648335f356001600160e01b0319166127e0565b6116645760405162461bcd60e51b8152600401610b6c906142c7565b600454600160a01b900460ff161561168f5760405163e0f9e71d60e01b815260040160405180910390fd5b6001600160a01b0385165f908152600360209081526040918290208251606081018452905460ff80821615158352610100820416151592820183905262010000900461ffff16928101929092526116f95760405163645fd19f60e11b815260040160405180910390fd5b845f0361171957604051630ea3153160e21b815260040160405180910390fd5b604051634104b9ed60e11b81526001600160a01b0387811660048301526117cf917f00000000000000000000000003d9a9ce13d16c7cfce564f41bd7e85e5cde8da69091169063820973da90602401602060405180830381865afa158015611783573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117a79190614311565b86907f00000000000000000000000000000000000000000000000000000000000f4240613094565b9150838210156117f2576040516302620f6160e61b815260040160405180910390fd5b6040516318457e6160e01b81526001600160a01b037f000000000000000000000000279cad277447965af3d24a78197aad1b02a2c58916906318457e61906118469086908a90879033908c90600401614328565b5f604051808303815f87803b15801561185d575f80fd5b505af115801561186f573d5f803e3d5ffd5b50505050856001600160a01b03167fdcc60b41ff1c604459e6aa4a7299817416b19fc586a392f111646e26597c4af9866040516118ae91815260200190565b60405180910390a250949350505050565b6118d4335f356001600160e01b0319166127e0565b6118f05760405162461bcd60e51b8152600401610b6c906142c7565b6004805460ff60a01b191690556040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d16933905f90a1565b61193c335f356001600160e01b0319166127e0565b6119585760405162461bcd60e51b8152600401610b6c906142c7565b63ffffffff81165f818152600b6020908152604091829020805461ff0019168155915192835290917fc45af64a13a09ef916a1114c59589294ec9c3095f2bfbbb093a7a96656858ded91015b60405180910390a15050565b6119c5335f356001600160e01b0319166127e0565b6119e15760405162461bcd60e51b8152600401610b6c906142c7565b806119ec834261436f565b10611a0a57604051634c1eef1760e11b815260040160405180910390fd5b604080516001600160a01b038089166020830152871691810191909152606081018590526080810184905260a0810183905260c081018290525f9060e00160408051601f1981840301815291815281516020928301205f8b815260059093529120549091508114611a8e5760405163fa174ecb60e01b815260040160405180910390fd5b5f888152600560205260408120556001600160a01b03861673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611ac65785611ae8565b7f000000000000000000000000ee7d8bcfb72bc1880d0cf19822eb0a2e6577ab625b6040516318457e6160e01b81529096506001600160a01b037f000000000000000000000000279cad277447965af3d24a78197aad1b02a2c58916906318457e6190611b3f908a908a908a9083908b90600401614328565b5f604051808303815f87803b158015611b56575f80fd5b505af1158015611b68573d5f803e3d5ffd5b50505050866001600160a01b0316887faf98ea774275cadfa3e477a7b52cba03e01197445a76bd5d0d561608708c362483604051611ba891815260200190565b60405180910390a35050505050505050565b611bcf335f356001600160e01b0319166127e0565b611beb5760405162461bcd60e51b8152600401610b6c906142c7565b63ffffffff81165f908152600b60205260408120805471ffffffffffffffffffffffffffffffffffff19169055611c23908290612eef565b60405163ffffffff821681527f11a9d1a77f76361ed131c19b1dc5758504c51dbde2e49fc973a0ef9577ad13d59060200160405180910390a150565b611c74335f356001600160e01b0319166127e0565b611c905760405162461bcd60e51b8152600401610b6c906142c7565b6001600160a01b0381165f81815260086020526040808220805460ff19169055517f039bcf51833310242b8b7c6aa0fbabf1bf2b5e5270807ee020f1920ef200666b9190a250565b5f546001600160a01b0316331480611d69575060015460405163b700961360e01b81526001600160a01b039091169063b700961390611d2a90339030906001600160e01b03195f351690600401614382565b602060405180830381865afa158015611d45573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d6991906143af565b611d71575f80fd5b600180546001600160a01b0319166001600160a01b03831690811790915560405133907fa3396fd7f6e0a21b50e5089d2da70d5ac0a3bbbd1f617a93f134b76389980198905f90a350565b5f5b92915050565b611dd9335f356001600160e01b0319166127e0565b611df55760405162461bcd60e51b8152600401610b6c906142c7565b6004805460ff60a01b1916600160a01b1790556040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e752905f90a1565b611e47335f356001600160e01b0319166127e0565b611e635760405162461bcd60e51b8152600401610b6c906142c7565b6103e861ffff82161115611e8a57604051636c5cde8760e01b815260040160405180910390fd5b6040805160608082018352851515808352851515602080850182815261ffff8881168789018181526001600160a01b038e165f818152600387528b902099518a549551925161ffff1990961690151561ff00191617610100921515929092029190911763ffff0000191662010000949093169390930291909117909655865193845290830191909152938101929092527fe08301321781ac43935a2099b2c3fd42de0a0ee87a519cac00e8c9cecd26ff12910160405180910390a250505050565b5f611f61335f356001600160e01b0319166127e0565b611f7d5760405162461bcd60e51b8152600401610b6c906142c7565b600254600114611f9f5760405162461bcd60e51b8152600401610b6c906142ed565b600280558c73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03821601611fe2576040516316df5df960e31b815260040160405180910390fd5b5f611fec8f6129c0565b9050611ffc8f8f8e8e8e8e612f3c565b61200a8f8f8f333386612b09565b925050612038338f8f856004600c9054906101000a90046001600160401b03166001600160401b0316612cc8565b6001600160601b03821115612060576040516389588ab360e01b815260040160405180910390fd5b61206e828888888888612886565b5060016002559c9b505050505050505050505050565b5f61209a335f356001600160e01b0319166127e0565b6120b65760405162461bcd60e51b8152600401610b6c906142c7565b6002546001146120d85760405162461bcd60e51b8152600401610b6c906142ed565b600280555f6120e6866129c0565b90506120f6868686338786612b09565b9150856001600160a01b03167f6f9b974223f85a1ae805c33b8b519039e2435481d949db1110de151a94d587af8660405161213391815260200190565b60405180910390a2506001600255949350505050565b61215e335f356001600160e01b0319166127e0565b61217a5760405162461bcd60e51b8152600401610b6c906142c7565b6001600160a01b0381165f81815260076020526040808220805460ff19169055517fae893dda71e2eee548f8291f458cceae4bd22b56a79906928591e4420444c0e99190a250565b6001600160a01b0383165f9081526007602052604090205460ff16806121ff57506001600160a01b0382165f9081526008602052604090205460ff165b8061222157506001600160a01b0381165f9081526009602052604090205460ff165b1561225a57604051632821264f60e01b81526001600160a01b038085166004830152808416602483015282166044820152606401610b6c565b6001600160a01b0383165f908152600660205260409020544210156122925760405163f64059db60e01b815260040160405180910390fd5b505050565b6122ac335f356001600160e01b0319166127e0565b6122c85760405162461bcd60e51b8152600401610b6c906142c7565b806001600160801b03165f036122f15760405163c80ed59560e01b815260040160405180910390fd5b63ffffffff83165f908152600b60205260409020805461010071ffffffffffffffffffffffffffffffffff0019909116620100006001600160801b0385160217178155612347846001600160a01b038516612eef565b6040805163ffffffff861681526001600160a01b03851660208201527f34fe916485e02ec88e487b0e611e5c9bacabba9e3eaae7a900aa08be8197d419910160405180910390a150505050565b6123a9335f356001600160e01b0319166127e0565b6123c55760405162461bcd60e51b8152600401610b6c906142c7565b6001600160a01b0381165f818152600760209081526040808320805460ff199081169091556008835281842080548216905560099092528083208054909216909155517fae893dda71e2eee548f8291f458cceae4bd22b56a79906928591e4420444c0e99190a26040516001600160a01b038216907f039bcf51833310242b8b7c6aa0fbabf1bf2b5e5270807ee020f1920ef200666b905f90a26040516001600160a01b038216907f77cb944c14da76928795279d1519ce9150085a06e0a53c61d5a86fc4e0fd57c6905f90a250565b6124aa335f356001600160e01b0319166127e0565b6124c65760405162461bcd60e51b8152600401610b6c906142c7565b60405163ca5eb5e160e01b81526001600160a01b0382811660048301527f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b169063ca5eb5e1906024015f604051808303815f87803b158015612526575f80fd5b505af1158015612538573d5f803e3d5ffd5b5050505050565b5f612555335f356001600160e01b0319166127e0565b6125715760405162461bcd60e51b8152600401610b6c906142c7565b6002546001146125935760405162461bcd60e51b8152600401610b6c906142ed565b600280558873eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b038216016125d6576040516316df5df960e31b815260040160405180910390fd5b5f6125e08b6129c0565b90506125f08b8b8b333386612b09565b925061261d338c8c866004600c9054906101000a90046001600160401b03166001600160401b0316612cc8565b6001600160601b03831115612645576040516389588ab360e01b815260040160405180910390fd5b612653838989898989612886565b5050600160025598975050505050505050565b61267b335f356001600160e01b0319166127e0565b6126975760405162461bcd60e51b8152600401610b6c906142c7565b63ffffffff81165f818152600b6020908152604091829020805460ff19168155915192835290917f1cb867ed6a020e020ea220d4f48bb8e36552abf9095e093e377d33933f2b31e491016119a4565b604080518082019091526001600160601b03861681526001600160a01b03851660208201525f9081612717826130af565b9050612725818787876130f6565b98975050505050505050565b612746335f356001600160e01b0319166127e0565b6127625760405162461bcd60e51b8152600401610b6c906142c7565b5f80546001600160a01b0319166001600160a01b0383169081178255604051909133917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a350565b5f60208201803590600a9083906127c39086613f74565b63ffffffff16815260208101919091526040015f20541492915050565b6001545f906001600160a01b03168015801590612867575060405163b700961360e01b81526001600160a01b0382169063b70096139061282890879030908890600401614382565b602060405180830381865afa158015612843573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061286791906143af565b8061287e57505f546001600160a01b038581169116145b949350505050565b612891335f336121c2565b6040516318457e6160e01b81525f600482018190526024820181905260448201523360648201526001600160601b03871660848201527f000000000000000000000000279cad277447965af3d24a78197aad1b02a2c5896001600160a01b0316906318457e619060a4015f604051808303815f87803b158015612912575f80fd5b505af1158015612924573d5f803e3d5ffd5b5050604080518082019091526001600160601b03891681526001600160a01b038816602082015291505f9050612959826130af565b90505f61296982888888886132c5565b6040516001600160601b038b1681529091506001600160a01b0389169082907fe0ec62d39b054dc2fd626dbc271483735df6e6fa1ef8389754bf8ab27a75eab29060200160405180910390a3505050505050505050565b604080516060810182525f8082526020820181905291810191909152600454600160a01b900460ff1615612a075760405163e0f9e71d60e01b815260040160405180910390fd5b506001600160a01b0381165f908152600360209081526040918290208251606081018452905460ff8082161515808452610100830490911615159383019390935262010000900461ffff1692810192909252612a765760405163645fd19f60e11b815260040160405180910390fd5b919050565b5f60405163095ea7b360e01b81526001600160a01b038416600482015282602482015260205f6044835f895af191505080601f3d1160015f511416151615612ac55750823b153d17155b80612b035760405162461bcd60e51b815260206004820152600e60248201526d1054141493d59157d1905253115160921b6044820152606401610b6c565b50505050565b5f855f03612b2a5760405163259be69560e11b815260040160405180910390fd5b604051634104b9ed60e11b81526001600160a01b038881166004830152612be0917f00000000000000000000000000000000000000000000000000000000000f4240917f00000000000000000000000003d9a9ce13d16c7cfce564f41bd7e85e5cde8da6169063820973da90602401602060405180830381865afa158015612bb4573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612bd89190614311565b889190613094565b90505f826040015161ffff1611612bf75780612c1a565b612c1a8260400151612710612c0c91906143ca565b829061ffff16612710613094565b905084811015612c3d5760405163097b2ad560e31b815260040160405180910390fd5b604051631ceb5d1960e11b81526001600160a01b037f000000000000000000000000279cad277447965af3d24a78197aad1b02a2c58916906339d6ba3290612c919087908b908b9089908890600401614328565b5f604051808303815f87803b158015612ca8575f80fd5b505af1158015612cba573d5f803e3d5ffd5b505050509695505050505050565b600480545f91908290612ce3906001600160601b03166143ec565b82546001600160601b039182166101009390930a838102920219161790915590508115612d8757612d148242614411565b6001600160a01b038781165f81815260066020908152604091829020949094558051938401919091529087169082015260608101859052608081018490524260a082015260c0810183905260e00160408051601f1981840301815291815281516020928301205f84815260059093529120555b846001600160a01b0316866001600160a01b0316827fe96d7872363f475d18b2f5390caaa5eaa96b2d38e42c62afe4ac08ebd2b13c3a87874288604051612de7949392919093845260208401929092526040830152606082015260800190565b60405180910390a4505050505050565b63ffffffff81165f908152600a602052604081205480611dbe5760405163f6ff4fb760e01b815263ffffffff84166004820152602401610b6c565b5f600b81612e4360208b018b613f74565b63ffffffff16815260208082019290925260409081015f208151606081018352905460ff808216151580845261010083049091161515948301949094526201000090046001600160801b0316918101919091529150612ecb57612ea96020890189613f74565b6040516315b73a2960e21b815263ffffffff9091166004820152602401610b6c565b5f612ed886880188614105565b9050612ee488826134e8565b505050505050505050565b63ffffffff82165f818152600a6020908152604091829020849055815192835282018390527f238399d427b947898edb290f5ff0f9109849b1c3ba196a42e35f00c50a54b98b91016119a4565b60405163d505accf60e01b81523360048201526001600160a01b037f000000000000000000000000279cad277447965af3d24a78197aad1b02a2c58981166024830152604482018790526064820186905260ff8516608483015260a4820184905260c4820183905287169063d505accf9060e4015f604051808303815f87803b158015612fc7575f80fd5b505af1925050508015612fd8575060015b61308c57604051636eb1769f60e11b81523360048201526001600160a01b037f000000000000000000000000279cad277447965af3d24a78197aad1b02a2c5898116602483015286919088169063dd62ed3e90604401602060405180830381865afa158015613049573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061306d9190614311565b101561308c576040516301b8851f60e41b815260040160405180910390fd5b505050505050565b5f825f1904841183021582026130a8575f80fd5b5091020490565b80515f906001600160601b0310156130da57604051633524486360e01b815260040160405180910390fd5b81516020909201516001600160a01b031660a09290921b171790565b5f6001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1480159061315657507f00000000000000000000000000000000000000000000000000000000000000016001600160a01b0316826001600160a01b031614155b1561317457604051637f3cd08160e11b815260040160405180910390fd5b5f61318184860186613f74565b63ffffffff81165f908152600b60209081526040918290208251606081018452905460ff8082161515835261010082041615159282018390526201000090046001600160801b031692810192909252919250906131f95760405163420eae3760e01b815263ffffffff83166004820152602401610b6c565b5f8760405160200161320d91815260200190565b60405160208183030381529060405290505f61325583604001515f61324e60408051600360f01b602082015281516002818303018152602290910190915290565b91906135d4565b90505f6132848584846001600160a01b038b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613639565b90506001600160a01b03871673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee146132b45780602001516132b7565b80515b9a9950505050505050505050565b5f806132d385870187613f74565b63ffffffff81165f908152600b60209081526040918290208251606081018452905460ff8082161515835261010082041615159282018390526201000090046001600160801b0316928101929092529192509061334b5760405163420eae3760e01b815263ffffffff83166004820152602401610b6c565b5f8860405160200161335f91815260200190565b60405160208183030381529060405290505f6133a083604001515f61324e60408051600360f01b602082015281516002818303018152602290910190915290565b90505f6133cf8584846001600160a01b038c1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613639565b905073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b0389160161343657805187101561343157805160405163f5ac3fa760e01b815263ffffffff87166004820152602481019190915260448101889052606401610b6c565b6134c9565b7f00000000000000000000000000000000000000000000000000000000000000016001600160a01b0316886001600160a01b0316036134b057868160200151111561343157602081015160405163f5ac3fa760e01b815263ffffffff87166004820152602481019190915260448101889052606401610b6c565b604051637f3cd08160e11b815260040160405180910390fd5b5f6134d78685858533613717565b519c9b505050505050505050505050565b60408051808201825260a083901c8082526001600160a01b03808516602084018190529351631ceb5d1960e11b815292937f000000000000000000000000279cad277447965af3d24a78197aad1b02a2c589909116926339d6ba3292613557925f928392839291600401614328565b5f604051808303815f87803b15801561356e575f80fd5b505af1158015613580573d5f803e3d5ffd5b5050505080602001516001600160a01b0316837fb944fddc61d7fedb8b736790454ba972000703b0d21c7481d6dbf95b7c2cc2f1835f01516040516135c791815260200190565b60405180910390a3505050565b60608360036135e3825f61381d565b61ffff1614613616576135f6815f61381d565b604051633a51740d60e01b815261ffff9091166004820152602401610b6c565b5f6136218585613879565b905061362f866001836138f2565b9695505050505050565b604080518082019091525f80825260208201527f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b031663ddc28c586040518060a001604052808863ffffffff16815260200161369b89612df7565b8152602001878152602001868152602001851515815250306040518363ffffffff1660e01b81526004016136d0929190614471565b6040805180830381865afa1580156136ea573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061370e9190614541565b95945050505050565b61371f613b2c565b5f61372c845f015161395b565b602085015190915015613746576137468460200151613982565b7f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b0316632637a450826040518060a001604052808b63ffffffff1681526020016137968c612df7565b81526020018a81526020018981526020015f8960200151111515815250866040518463ffffffff1660e01b81526004016137d1929190614471565b60806040518083038185885af11580156137ed573d5f803e3d5ffd5b50505050506040513d601f19601f82011682018060405250810190613812919061455b565b979650505050505050565b5f613829826002614411565b835110156138705760405162461bcd60e51b8152602060048201526014602482015273746f55696e7431365f6f75744f66426f756e647360601b6044820152606401610b6c565b50016002015190565b60606001600160801b038216156138c157604080516001600160801b0319608086811b8216602084015285901b166030820152016040516020818303038152906040526138eb565b6040516001600160801b0319608085901b1660208201526030016040516020818303038152906040525b9392505050565b6060836003613901825f61381d565b61ffff1614613914576135f6815f61381d565b8460016139218551613a61565b61392c9060016145cc565b86866040516020016139429594939291906145e7565b6040516020818303038152906040529150509392505050565b5f81341461397e576040516304fb820960e51b8152346004820152602401610b6c565b5090565b5f7f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b031663e4fe1d946040518163ffffffff1660e01b8152600401602060405180830381865afa1580156139df573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613a03919061464d565b90506001600160a01b038116613a2c576040516329b99a9560e11b815260040160405180910390fd5b6113606001600160a01b038216337f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b85613a8f565b5f61ffff82111561397e576040516306dfcc6560e41b81526010600482015260248101839052604401610b6c565b5f6040516323b872dd60e01b81526001600160a01b03851660048201526001600160a01b038416602482015282604482015260205f6064835f8a5af191505080601f3d1160015f511416151615613ae85750833b153d17155b806125385760405162461bcd60e51b81526020600482015260146024820152731514905394d1915497d19493d357d1905253115160621b6044820152606401610b6c565b60405180606001604052805f80191681526020015f6001600160401b03168152602001613b6a60405180604001604052805f81526020015f81525090565b905290565b6001600160a01b0381168114613b83575f80fd5b50565b8035612a7681613b6f565b5f60208284031215613ba1575f80fd5b81356138eb81613b6f565b80356001600160601b0381168114612a76575f80fd5b5f8083601f840112613bd2575f80fd5b5081356001600160401b03811115613be8575f80fd5b602083019150836020828501011115613bff575f80fd5b9250929050565b5f805f805f8060a08789031215613c1b575f80fd5b613c2487613bac565b95506020870135613c3481613b6f565b945060408701356001600160401b03811115613c4e575f80fd5b613c5a89828a01613bc2565b9095509350506060870135613c6e81613b6f565b80925050608087013590509295509295509295565b5f805f60608486031215613c95575f80fd5b8335613ca081613b6f565b95602085013595506040909401359392505050565b6001600160401b0381168114613b83575f80fd5b5f60208284031215613cd9575f80fd5b81356138eb81613cb5565b5f60608284031215613cf4575f80fd5b50919050565b5f805f805f805f60e0888a031215613d10575f80fd5b613d1a8989613ce4565b96506060880135955060808801356001600160401b0380821115613d3c575f80fd5b613d488b838c01613bc2565b909750955060a08a01359150613d5d82613b6f565b90935060c08901359080821115613d72575f80fd5b50613d7f8a828b01613bc2565b989b979a50959850939692959293505050565b803563ffffffff81168114612a76575f80fd5b80356001600160801b0381168114612a76575f80fd5b5f8060408385031215613dcc575f80fd5b613dd583613d92565b9150613de360208401613da5565b90509250929050565b5f8060408385031215613dfd575f80fd5b613e0683613d92565b91506020830135613e1681613b6f565b809150509250929050565b5f8060408385031215613e32575f80fd5b613e3b83613d92565b946020939093013593505050565b8015158114613b83575f80fd5b5f805f805f60a08688031215613e6a575f80fd5b613e7386613d92565b94506020860135613e8381613e49565b93506040860135613e9381613e49565b92506060860135613ea381613b6f565b9150613eb160808701613da5565b90509295509295909350565b803560ff81168114612a76575f80fd5b5f805f805f805f60e0888a031215613ee3575f80fd5b8735613eee81613b6f565b9650602088013595506040880135945060608801359350613f1160808901613ebd565b925060a0880135915060c0880135905092959891949750929550565b5f805f8060808587031215613f40575f80fd5b8435613f4b81613b6f565b935060208501359250604085013591506060850135613f6981613b6f565b939692955090935050565b5f60208284031215613f84575f80fd5b6138eb82613d92565b5f805f805f805f60e0888a031215613fa3575f80fd5b873596506020880135613fb581613b6f565b95506040880135613fc581613b6f565b969995985095966060810135965060808101359560a0820135955060c0909101359350915050565b5f805f8060808587031215614000575f80fd5b843561400b81613b6f565b9350602085013561401b81613e49565b9250604085013561402b81613e49565b9150606085013561ffff81168114613f69575f80fd5b5f805f805f805f805f805f806101608d8f03121561405d575f80fd5b6140678d35613b6f565b8c359b5060208d01359a5060408d0135995060608d0135985061408c60808e01613ebd565b975060a08d0135965060c08d013595506140a960e08e0135613b6f565b60e08d013594506001600160401b036101008e013511156140c8575f80fd5b6140d98e6101008f01358f01613bc2565b90945092506140eb6101208e01613b86565b91506101408d013590509295989b509295989b509295989b565b5f60208284031215614115575f80fd5b5035919050565b5f805f6060848603121561412e575f80fd5b833561413981613b6f565b9250602084013561414981613b6f565b9150604084013561415981613b6f565b809150509250925092565b5f805f60608486031215614176575f80fd5b61417f84613d92565b9250602084013561418f81613b6f565b915061419d60408501613da5565b90509250925092565b5f805f805f805f8060e0898b0312156141bd575f80fd5b88356141c881613b6f565b9750602089013596506040890135955060608901356141e681613b6f565b945060808901356001600160401b03811115614200575f80fd5b61420c8b828c01613bc2565b90955093505060a089013561422081613b6f565b8092505060c089013590509295985092959890939650565b5f805f805f6080868803121561424c575f80fd5b61425586613bac565b9450602086013561426581613b6f565b935060408601356001600160401b0381111561427f575f80fd5b61428b88828901613bc2565b909450925050606086013561429f81613b6f565b809150509295509295909350565b5f606082840312156142bd575f80fd5b6138eb8383613ce4565b6020808252600c908201526b15539055551213d49256915160a21b604082015260600190565b6020808252600a90820152695245454e5452414e435960b01b604082015260600190565b5f60208284031215614321575f80fd5b5051919050565b6001600160a01b039586168152938516602085015260408401929092529092166060820152608081019190915260a00190565b634e487b7160e01b5f52601160045260245ffd5b81810381811115611dbe57611dbe61435b565b6001600160a01b0393841681529190921660208201526001600160e01b0319909116604082015260600190565b5f602082840312156143bf575f80fd5b81516138eb81613e49565b61ffff8281168282160390808211156143e5576143e561435b565b5092915050565b5f6001600160601b038083168181036144075761440761435b565b6001019392505050565b80820180821115611dbe57611dbe61435b565b5f5b8381101561443e578181015183820152602001614426565b50505f910152565b5f815180845261445d816020860160208601614424565b601f01601f19169290920160200192915050565b6040815263ffffffff8351166040820152602083015160608201525f604084015160a060808401526144a660e0840182614446565b90506060850151603f198483030160a08501526144c38282614446565b60809690960151151560c08501525050506001600160a01b039190911660209091015290565b5f604082840312156144f9575f80fd5b604051604081018181106001600160401b038211171561452757634e487b7160e01b5f52604160045260245ffd5b604052825181526020928301519281019290925250919050565b5f60408284031215614551575f80fd5b6138eb83836144e9565b5f6080828403121561456b575f80fd5b604051606081018181106001600160401b038211171561459957634e487b7160e01b5f52604160045260245ffd5b6040528251815260208301516145ae81613cb5565b60208201526145c084604085016144e9565b60408201529392505050565b61ffff8181168382160190808211156143e5576143e561435b565b5f86516145f8818460208b01614424565b6001600160f81b031960f888811b82169285019283526001600160f01b031960f089901b16600184015286901b166003820152835161463e816004840160208801614424565b01600401979650505050505050565b5f6020828403121561465d575f80fd5b81516138eb81613b6f56fea2646970667358221220cb71701720759819c3db6acbf1de0eac330b5b6a96d2a7821d79070002a95ccd64736f6c63430008150033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000771263e3bc6acda5ae388a3f8a0c2dd7a17275fc000000000000000000000000279cad277447965af3d24a78197aad1b02a2c58900000000000000000000000003d9a9ce13d16c7cfce564f41bd7e85e5cde8da6000000000000000000000000ee7d8bcfb72bc1880d0cf19822eb0a2e6577ab620000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b000000000000000000000000771263e3bc6acda5ae388a3f8a0c2dd7a17275fc0000000000000000000000000000000000000000000000000000000000000001
-----Decoded View---------------
Arg [0] : _owner (address): 0x771263e3Bc6aCDa5aE388A3F8A0c2dd7A17275FC
Arg [1] : _vault (address): 0x279CAD277447965AF3d24a78197aad1B02a2c589
Arg [2] : _accountant (address): 0x03D9a9cE13D16C7cFCE564f41bd7E85E5cde8Da6
Arg [3] : _weth (address): 0xEE7D8BCFb72bC1880D0Cf19822eB0A2e6577aB62
Arg [4] : _lzEndPoint (address): 0x6F475642a6e85809B1c36Fa62763669b1b48DD5B
Arg [5] : _delegate (address): 0x771263e3Bc6aCDa5aE388A3F8A0c2dd7A17275FC
Arg [6] : _lzToken (address): 0x0000000000000000000000000000000000000001
-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 000000000000000000000000771263e3bc6acda5ae388a3f8a0c2dd7a17275fc
Arg [1] : 000000000000000000000000279cad277447965af3d24a78197aad1b02a2c589
Arg [2] : 00000000000000000000000003d9a9ce13d16c7cfce564f41bd7e85e5cde8da6
Arg [3] : 000000000000000000000000ee7d8bcfb72bc1880d0cf19822eb0a2e6577ab62
Arg [4] : 0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b
Arg [5] : 000000000000000000000000771263e3bc6acda5ae388a3f8a0c2dd7a17275fc
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000001
Deployed Bytecode Sourcemap
525:10166:31:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3532:42:34;;;;;;;;;;-1:-1:-1;3532:42:34;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;706:14:39;;699:22;681:41;;669:2;654:18;3532:42:34;;;;;;;;4482:333:32;;;;;;:::i;:::-;;:::i;:::-;;6613:35:34;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;2300:32:39;;;2282:51;;2270:2;2255:18;6613:35:34;2115:224:39;14661:1156:34;;;;;;:::i;:::-;;:::i;:::-;;;2892:25:39;;;2880:2;2865:18;14661:1156:34;2746:177:39;8966:242:34;;;;;;;;;;-1:-1:-1;8966:242:34;;;;;:::i;:::-;;:::i;3998:708:11:-;;;;;;:::i;:::-;;:::i;6249:359:31:-;;;;;;;;;;-1:-1:-1;6249:359:31;;;;;:::i;:::-;;:::i;1321:243:9:-;;;;;;;;;;-1:-1:-1;1321:243:9;;;856:1:12;5354:34:39;;;5419:2;5404:18;;5397:43;5290:18;1321:243:9;5147:299:39;3223:50:34;;;;;;;;;;-1:-1:-1;3223:50:34;;;;;:::i;:::-;;;;;;;;;;;;;;9349:256;;;;;;;;;;-1:-1:-1;9349:256:34;;;;;:::i;:::-;;:::i;11127:137::-;;;;;;;;;;-1:-1:-1;11127:137:34;;;;;:::i;:::-;;:::i;11392:140::-;;;;;;;;;;-1:-1:-1;11392:140:34;;;;;:::i;:::-;;:::i;4604:304:31:-;;;;;;;;;;-1:-1:-1;4604:304:31;;;;;:::i;:::-;;:::i;3383:44:34:-;;;;;;;;;;-1:-1:-1;3383:44:34;;;;;:::i;:::-;;;;;;;;;;;;;;;;10130:125;;;;;;;;;;-1:-1:-1;10130:125:34;;;;;:::i;:::-;;:::i;1720:111:10:-;;;;;;;;;;-1:-1:-1;1720:111:10;;;;;:::i;:::-;;:::i;3662:554:31:-;;;;;;;;;;-1:-1:-1;3662:554:31;;;;;:::i;:::-;;:::i;10631:119:34:-;;;;;;;;;;-1:-1:-1;10631:119:34;;;;;:::i;:::-;;:::i;15940:646::-;;;;;;;;;;-1:-1:-1;15940:646:34;;;;;:::i;:::-;;:::i;17305:818::-;;;;;;;;;;-1:-1:-1;17305:818:34;;;;;:::i;:::-;;:::i;7517:99::-;;;;;;;;;;;;;:::i;2324:40::-;;;;;;;;;;-1:-1:-1;2324:40:34;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8689:14:39;;8682:22;8664:41;;8748:14;;8741:22;8736:2;8721:18;;8714:50;8812:6;8800:19;8780:18;;;8773:47;8652:2;8637:18;2324:40:34;8476:350:39;5925:208:31;;;;;;;;;;-1:-1:-1;5925:208:31;;;;;:::i;:::-;;:::i;13106:1302:34:-;;;;;;;;;;-1:-1:-1;13106:1302:34;;;;;:::i;:::-;;:::i;6387:55::-;;;;;;;;;;;;;;;4324:178:31;;;;;;;;;;-1:-1:-1;4324:178:31;;;;;:::i;:::-;;:::i;442:46:10:-;;;;;;;;;;;;;;;10872:122:34;;;;;;;;;;-1:-1:-1;10872:122:34;;;;;:::i;:::-;;:::i;1523:434:23:-;;;;;;;;;;-1:-1:-1;1523:434:23;;;;;:::i;:::-;;:::i;3136:129:11:-;;;;;;;;;;-1:-1:-1;3136:129:11;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;10669:31:39;;;10651:50;;10639:2;10624:18;3136:129:11;10507:200:39;7260:94:34;;;;;;;;;;;;;:::i;562:20:23:-;;;;;;;;;;-1:-1:-1;562:20:23;;;;-1:-1:-1;;;;;562:20:23;;;7833:426:34;;;;;;;;;;-1:-1:-1;7833:426:34;;;;;:::i;:::-;;:::i;2980:1113:32:-;;;;;;:::i;:::-;;:::i;3069:55:34:-;;;;;;;;;;-1:-1:-1;3069:55:34;;;;;:::i;:::-;;;;;;;;;;;;;;16757:421;;;;;;;;;;-1:-1:-1;16757:421:34;;;;;:::i;:::-;;:::i;2728:29::-;;;;;;;;;;-1:-1:-1;2728:29:34;;;;-1:-1:-1;;;2728:29:34;;-1:-1:-1;;;;;2728:29:34;;;10378:128;;;;;;;;;;-1:-1:-1;10378:128:34;;;;;:::i;:::-;;:::i;12015:379::-;;;;;;;;;;-1:-1:-1;12015:379:34;;;;;:::i;:::-;;:::i;2853:20::-;;;;;;;;;;-1:-1:-1;2853:20:34;;;;-1:-1:-1;;;2853:20:34;;;;;;5008:497:31;;;;;;;;;;-1:-1:-1;5008:497:31;;;;;:::i;:::-;;:::i;1748:110:11:-;;;;;;;;;;-1:-1:-1;1846:4:11;1748:110;;565:48:10;;;;;;;;;;-1:-1:-1;565:48:10;;;;;:::i;:::-;;;;;;;;;;;;;;589:26:23;;;;;;;;;;-1:-1:-1;589:26:23;;;;-1:-1:-1;;;;;589:26:23;;;9739:263:34;;;;;;;;;;-1:-1:-1;9739:263:34;;;;;:::i;:::-;;:::i;3251:108:10:-;;;;;;;;;;-1:-1:-1;3251:108:10;;;;;:::i;:::-;;:::i;1593:912:32:-;;;;;;:::i;:::-;;:::i;1499:42:31:-;;;;;;;;;;-1:-1:-1;1499:42:31;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1499:42:31;;;;;;;15698:14:39;;15691:22;15673:41;;15757:14;;15750:22;15745:2;15730:18;;15723:50;-1:-1:-1;;;;;15809:47:39;15789:18;;;15782:75;15661:2;15646:18;1499:42:31;15483:380:39;5609:214:31;;;;;;;;;;-1:-1:-1;5609:214:31;;;;;:::i;:::-;;:::i;4911:357:32:-;;;;;;;;;;-1:-1:-1;4911:357:32;;;;;:::i;:::-;;:::i;2451:26:34:-;;;;;;;;;;-1:-1:-1;2451:26:34;;;;-1:-1:-1;;;;;2451:26:34;;;;;;-1:-1:-1;;;;;16807:39:39;;;16789:58;;16777:2;16762:18;2451:26:34;16645:208:39;3705:48:34;;;;;;;;;;-1:-1:-1;3705:48:34;;;;;:::i;:::-;;;;;;;;;;;;;;;;1963:164:23;;;;;;;;;;-1:-1:-1;1963:164:23;;;;;:::i;:::-;;:::i;6252:34:34:-;;;;;;;;;;;;;;;2400:149:11;;;;;;;;;;-1:-1:-1;2400:149:11;;;;;:::i;:::-;;:::i;4482:333:32:-;902:33:23;915:10;927:7;;-1:-1:-1;;;;;;927:7:23;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:23;;;;;;;:::i;:::-;;;;;;;;;512:6:27::1;;522:1;512:11;504:34;;;;-1:-1:-1::0;;;504:34:27::1;;;;;;;:::i;:::-;558:1;549:10:::0;;4686:8:32::2;::::0;-1:-1:-1;;;4686:8:32;::::2;;;4682:58;;;4703:37;;-1:-1:-1::0;;;4703:37:32::2;;;;;;;;;;;4682:58;4750;4758:11;4771:2;4775:14;;4791:8;4801:6;4750:7;:58::i;:::-;-1:-1:-1::0;;591:1:27::1;582:6;:10:::0;-1:-1:-1;;;;4482:333:32:o;14661:1156:34:-;14834:14;902:33:23;915:10;927:7;;-1:-1:-1;;;;;;927:7:23;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:23;;;;;;;:::i;:::-;512:6:27::1;;522:1;512:11;504:34;;;;-1:-1:-1::0;;;504:34:27::1;;;;;;;:::i;:::-;558:1;549:10:::0;;14864:18:34::2;14885:28;14900:12:::0;14885:14:::2;:28::i;:::-;14864:49:::0;-1:-1:-1;14924:12:34::2;-1:-1:-1::0;;;;;;;14950:31:34;::::2;::::0;14946:670:::2;;15001:9;15014:1;15001:14:::0;14997:68:::2;;15024:41;;-1:-1:-1::0;;;15024:41:34::2;;;;;;;;;;;14997:68;15079:13;-1:-1:-1::0;;;;;15079:21:34::2;;15108:9;15079:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;-1:-1:-1::0;15197:9:34::2;::::0;-1:-1:-1;15220:56:34::2;::::0;-1:-1:-1;;;;;;;15220:13:34::2;:25;::::0;-1:-1:-1;15254:5:34::2;::::0;-1:-1:-1;15197:9:34;15220:25:::2;:56::i;:::-;-1:-1:-1::0;15358:13:34::2;::::0;-1:-1:-1;15470:4:34::2;14946:670;;;15510:9;:13:::0;15506:68:::2;;15532:42;;-1:-1:-1::0;;;15532:42:34::2;;;;;;;;;;;15506:68;-1:-1:-1::0;15595:10:34::2;14946:670;15635:80;15649:12;15663:13;15678:11;15691:4;15697:10;15709:5;15635:13;:80::i;:::-;15626:89;;15725:85;15745:10;15757:12;15771:13;15786:6;15794:15;;;;;;;;;-1:-1:-1::0;;;;;15794:15:34::2;-1:-1:-1::0;;;;;15725:85:34::2;:19;:85::i;:::-;-1:-1:-1::0;;591:1:27::1;582:6;:10:::0;14661:1156:34;;-1:-1:-1;;;14661:1156:34:o;8966:242::-;902:33:23;915:10;927:7;;-1:-1:-1;;;;;;927:7:23;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:23;;;;;;;:::i;:::-;1959:6:34::1;9055:16;-1:-1:-1::0;;;;;9055:40:34::1;;9051:106;;;9104:53;;-1:-1:-1::0;;;9104:53:34::1;;;;;;;;;;;9051:106;9167:15;:34:::0;;-1:-1:-1;;;;;9167:34:34;;::::1;-1:-1:-1::0;;;9167:34:34::1;-1:-1:-1::0;;;;9167:34:34;;::::1;::::0;;;::::1;::::0;;8966:242::o;3998:708:11:-;4311:8;-1:-1:-1;;;;;4303:31:11;4324:10;4303:31;4299:68;;4343:24;;-1:-1:-1;;;4343:24:11;;4356:10;4343:24;;;2282:51:39;2255:18;;4343:24:11;2115:224:39;4299:68:11;4503:14;;;;;;4467:32;;4484:14;;4503:7;4484:14;:::i;:::-;4467:16;:32::i;:::-;:50;4463:103;;4535:14;;;;:7;:14;:::i;:::-;4526:40;;-1:-1:-1;;;4526:40:11;;18216:10:39;18204:23;;;4526:40:11;;;18186:42:39;4551:14:11;;;;18244:18:39;;;18237:34;18159:18;;4526:40:11;18014:263:39;4463:103:11;4640:59;4651:7;4660:5;4667:8;;4677:9;4688:10;;4640;:59::i;:::-;3998:708;;;;;;;:::o;6249:359:31:-;902:33:23;915:10;927:7;;-1:-1:-1;;;;;;927:7:23;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:23;;;;;;;:::i;:::-;6352:15:31::1;-1:-1:-1::0;;;;;6352:20:31::1;6371:1;6352:20:::0;6348:96:::1;;6395:38;;-1:-1:-1::0;;;6395:38:31::1;;;;;;;;;;;6348:96;6475:19;::::0;::::1;6453;6475::::0;;;:10:::1;:19;::::0;;;;;;;;6504:39;;-1:-1:-1;;;;;;6504:39:31::1;::::0;-1:-1:-1;;;;;6504:39:31;::::1;::::0;;::::1;::::0;;;::::1;::::0;;6559:42;;18455::39;;;18513:18;;;18506:75;;;;6475:19:31;6559:42:::1;::::0;18428:18:39;6559:42:31::1;;;;;;;;6338:270;6249:359:::0;;:::o;9349:256:34:-;902:33:23;915:10;927:7;;-1:-1:-1;;;;;;927:7:23;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:23;;;;;;;:::i;:::-;-1:-1:-1;;;;;9412:18:34;::::1;;::::0;;;:12:::1;:18;::::0;;;;;;;:25;;9433:4:::1;-1:-1:-1::0;;9412:25:34;;::::1;::::0;::::1;::::0;;;9447:10:::1;:16:::0;;;;;:23;;;::::1;::::0;::::1;::::0;;9480:16:::1;:22:::0;;;;;;:29;;;;::::1;;::::0;;;9524:14;::::1;::::0;9412:18;9524:14:::1;9553:12;::::0;-1:-1:-1;;;;;9553:12:34;::::1;::::0;::::1;::::0;;;::::1;9580:18;::::0;-1:-1:-1;;;;;9580:18:34;::::1;::::0;::::1;::::0;;;::::1;9349:256:::0;:::o;11127:137::-;902:33:23;915:10;927:7;;-1:-1:-1;;;;;;927:7:23;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:23;;;;;;;:::i;:::-;-1:-1:-1;;;;;11195:22:34;::::1;;::::0;;;:16:::1;:22;::::0;;;;;:29;;-1:-1:-1;;11195:29:34::1;11220:4;11195:29;::::0;;11239:18;::::1;::::0;11195:22;11239:18:::1;11127:137:::0;:::o;11392:140::-;902:33:23;915:10;927:7;;-1:-1:-1;;;;;;927:7:23;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:23;;;;;;;:::i;:::-;-1:-1:-1;;;;;11461:22:34;::::1;11486:5;11461:22:::0;;;:16:::1;:22;::::0;;;;;:30;;-1:-1:-1;;11461:30:34::1;::::0;;11506:19;::::1;::::0;11486:5;11506:19:::1;11392:140:::0;:::o;4604:304:31:-;902:33:23;915:10;927:7;;-1:-1:-1;;;;;;927:7:23;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:23;;;;;;;:::i;:::-;4728:19:31::1;::::0;::::1;4706;4728::::0;;;:10:::1;:19;::::0;;;;4757:30;;-1:-1:-1;;4757:30:31::1;4783:4;4757:30;::::0;;4797:43:::1;4728:19:::0;-1:-1:-1;;;;;4815:22:31;::::1;4797:8;:43::i;:::-;4856:45;::::0;;18795:10:39;18783:23;;18765:42;;-1:-1:-1;;;;;18843:32:39;;18838:2;18823:18;;18816:60;4856:45:31::1;::::0;18738:18:39;4856:45:31::1;18592:290:39::0;10130:125:34;902:33:23;915:10;927:7;;-1:-1:-1;;;;;;927:7:23;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:23;;;;;;;:::i;:::-;-1:-1:-1;;;;;10194:18:34;::::1;;::::0;;;:12:::1;:18;::::0;;;;;:25;;-1:-1:-1;;10194:25:34::1;10215:4;10194:25;::::0;;10234:14;::::1;::::0;10194:18;10234:14:::1;10130:125:::0;:::o;1720:111:10:-;902:33:23;915:10;927:7;;-1:-1:-1;;;;;;927:7:23;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:23;;;;;;;:::i;:::-;1803:21:10::1;1812:4;1818:5;1803:8;:21::i;:::-;1720:111:::0;;:::o;3662:554:31:-;902:33:23;915:10;927:7;;-1:-1:-1;;;;;;927:7:23;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:23;;;;;;;:::i;:::-;3871:15:31::1;:39;;;;-1:-1:-1::0;;;;;;3890:20:31;::::1;::::0;3871:39:::1;3867:115;;;3933:38;;-1:-1:-1::0;;;3933:38:31::1;;;;;;;;;;;3867:115;4013:58;::::0;;::::1;::::0;::::1;::::0;;;::::1;;::::0;;;::::1;;;::::0;;::::1;::::0;;;-1:-1:-1;;;;;4013:58:31;;::::1;::::0;;;;;;3991:19:::1;::::0;::::1;-1:-1:-1::0;3991:19:31;;;:10:::1;:19:::0;;;;;;;:80;;;;;;;;-1:-1:-1;;3991:80:31;;;;::::1;;-1:-1:-1::0;;3991:80:31;;::::1;::::0;::::1;;::::0;;;::::1;::::0;;;::::1;-1:-1:-1::0;;;;;;3991:80:31::1;::::0;;;;::::1;;::::0;;;::::1;::::0;;4081:43:::1;3991:19:::0;-1:-1:-1;;;;;4099:22:31;::::1;4797:8;:43::i;4081:::-;4140:69;::::0;;19135:10:39;19123:23;;19105:42;;19190:14;;19183:22;19178:2;19163:18;;19156:50;19249:14;;19242:22;19222:18;;;19215:50;-1:-1:-1;;;;;19301:32:39;;19296:2;19281:18;;19274:60;4140:69:31;;::::1;::::0;;;;19092:3:39;4140:69:31;;::::1;3662:554:::0;;;;;:::o;10631:119:34:-;902:33:23;915:10;927:7;;-1:-1:-1;;;;;;927:7:23;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:23;;;;;;;:::i;:::-;-1:-1:-1;;;;;10693:16:34;::::1;;::::0;;;:10:::1;:16;::::0;;;;;:23;;-1:-1:-1;;10693:23:34::1;10712:4;10693:23;::::0;;10731:12;::::1;::::0;10693:16;10731:12:::1;10631:119:::0;:::o;15940:646::-;16231:14;902:33:23;915:10;927:7;;-1:-1:-1;;;;;;927:7:23;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:23;;;;;;;:::i;:::-;512:6:27::1;;522:1;512:11;504:34;;;;-1:-1:-1::0;;;504:34:27::1;;;;;;;:::i;:::-;558:1;549:10:::0;;16207:12:34;-1:-1:-1;;;;;;;5988:22:34;::::2;::::0;5984:85:::2;;6019:50;;-1:-1:-1::0;;;6019:50:34::2;;;;;;;;;;;5984:85;16257:18:::3;16278:28;16293:12;16278:14;:28::i;:::-;16257:49;;16317:61;16331:12;16345:13;16360:8;16370:1;16373;16376;16317:13;:61::i;:::-;16398:86;16412:12;16426:13;16441:11;16454:10;16466;16478:5;16398:13;:86::i;:::-;16389:95;;16494:85;16514:10;16526:12;16540:13;16555:6;16563:15;;;;;;;;;-1:-1:-1::0;;;;;16563:15:34::3;-1:-1:-1::0;;;;;16494:85:34::3;:19;:85::i;:::-;-1:-1:-1::0;;591:1:27::1;582:6;:10:::0;15940:646:34;;-1:-1:-1;;;;;;;15940:646:34:o;17305:818::-;17459:17;902:33:23;915:10;927:7;;-1:-1:-1;;;;;;927:7:23;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:23;;;;;;;:::i;:::-;17496:8:34::1;::::0;-1:-1:-1;;;17496:8:34;::::1;;;17492:58;;;17513:37;;-1:-1:-1::0;;;17513:37:34::1;;;;;;;;;;;17492:58;-1:-1:-1::0;;;;;17581:24:34;::::1;17560:18;17581:24:::0;;;:9:::1;:24;::::0;;;;;;;;17560:45;;::::1;::::0;::::1;::::0;;;;::::1;::::0;;::::1;;;::::0;;::::1;::::0;::::1;;;;::::0;;::::1;::::0;;;;;::::1;;;::::0;;;;;;;17615:82:::1;;17649:48;;-1:-1:-1::0;;;17649:48:34::1;;;;;;;;;;;17615:82;17712:11;17727:1;17712:16:::0;17708:70:::1;;17737:41;;-1:-1:-1::0;;;17737:41:34::1;;;;;;;;;;;17708:70;17823:44;::::0;-1:-1:-1;;;17823:44:34;;-1:-1:-1;;;;;2300:32:39;;;17823:44:34::1;::::0;::::1;2282:51:39::0;17800:79:34::1;::::0;17823:10:::1;:29:::0;;::::1;::::0;::::1;::::0;2255:18:39;;17823:44:34::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;17800:11:::0;;17869:9:::1;17800:22;:79::i;:::-;17788:91;;17905:13;17893:9;:25;17889:88;;;17927:50;;-1:-1:-1::0;;;17927:50:34::1;;;;;;;;;;;17889:88;17987:65;::::0;-1:-1:-1;;;17987:65:34;;-1:-1:-1;;;;;17987:5:34::1;:10;::::0;::::1;::::0;:65:::1;::::0;17998:2;;18002:13;;18017:9;;18028:10:::1;::::0;18040:11;;17987:65:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;18088:13;-1:-1:-1::0;;;;;18067:49:34::1;;18104:11;18067:49;;;;2892:25:39::0;;2880:2;2865:18;;2746:177;18067:49:34::1;;;;;;;;17482:641;17305:818:::0;;;;;;:::o;7517:99::-;902:33:23;915:10;927:7;;-1:-1:-1;;;;;;927:7:23;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:23;;;;;;;:::i;:::-;7568:8:34::1;:16:::0;;-1:-1:-1;;;;7568:16:34::1;::::0;;7599:10:::1;::::0;::::1;::::0;7579:5:::1;::::0;7599:10:::1;7517:99::o:0;5925:208:31:-;902:33:23;915:10;927:7;;-1:-1:-1;;;;;;927:7:23;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:23;;;;;;;:::i;:::-;6024:19:31::1;::::0;::::1;6002;6024::::0;;;:10:::1;:19;::::0;;;;;;;;6053:29;;-1:-1:-1;;6053:29:31::1;::::0;;6098:28;;20448:42:39;;;6024:19:31;;6098:28:::1;::::0;20421:18:39;6098:28:31::1;;;;;;;;5992:141;5925:208:::0;:::o;13106:1302:34:-;902:33:23;915:10;927:7;;-1:-1:-1;;;;;;927:7:23;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:23;;;;;;;:::i;:::-;13434:32:34;13395:34:::1;13413:16:::0;13395:15:::1;:34;:::i;:::-;13394:72;13390:232;;13563:48;;-1:-1:-1::0;;;13563:48:34::1;;;;;;;;;;;13390:232;13676:144;::::0;;-1:-1:-1;;;;;21109:15:39;;;13676:144:34::1;::::0;::::1;21091:34:39::0;21161:15;;21141:18;;;21134:43;;;;21193:18;;;21186:34;;;21236:18;;;21229:34;;;21279:19;;;21272:35;;;21323:19;;;21316:35;;;13631:19:34::1;::::0;21025::39;;13676:144:34::1;::::0;;-1:-1:-1;;13676:144:34;;::::1;::::0;;;;;;13653:177;;13676:144:::1;13653:177:::0;;::::1;::::0;13844:27:::1;::::0;;;:20:::1;:27:::0;;;;;;13653:177;;-1:-1:-1;13844:42:34;::::1;13840:100;;13895:45;;-1:-1:-1::0;;;13895:45:34::1;;;;;;;;;;;13840:100;14004:27;::::0;;;:20:::1;:27;::::0;;;;13997:34;-1:-1:-1;;;;;14135:22:34;::::1;1789:42;14135:22;:62;;14185:12;14135:62;;;14168:13;14135:62;14261:79;::::0;-1:-1:-1;;;14261:79:34;;14120:77;;-1:-1:-1;;;;;;14261:5:34::1;:10;::::0;::::1;::::0;:79:::1;::::0;14272:8;;14120:77;;14303:13;;14272:8;;14328:11;;14261:79:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;14392:8;-1:-1:-1::0;;;;;14356:45:34::1;14372:5;14356:45;14379:11;14356:45;;;;2892:25:39::0;;2880:2;2865:18;;2746:177;14356:45:34::1;;;;;;;;13380:1028;13106:1302:::0;;;;;;;:::o;4324:178:31:-;902:33:23;915:10;927:7;;-1:-1:-1;;;;;;927:7:23;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:23;;;;;;;:::i;:::-;4400:19:31::1;::::0;::::1;;::::0;;;:10:::1;:19;::::0;;;;4393:26;;-1:-1:-1;;4393:26:31;;;4429:29:::1;::::0;4411:7;;4429:8:::1;:29::i;:::-;4474:21;::::0;20478:10:39;20466:23;;20448:42;;4474:21:31::1;::::0;20436:2:39;20421:18;4474:21:31::1;;;;;;;4324:178:::0;:::o;10872:122:34:-;902:33:23;915:10;927:7;;-1:-1:-1;;;;;;927:7:23;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:23;;;;;;;:::i;:::-;-1:-1:-1;;;;;10935:16:34;::::1;10954:5;10935:16:::0;;;:10:::1;:16;::::0;;;;;:24;;-1:-1:-1;;10935:24:34::1;::::0;;10974:13;::::1;::::0;10954:5;10974:13:::1;10872:122:::0;:::o;1523:434:23:-;1794:5;;-1:-1:-1;;;;;1794:5:23;1780:10;:19;;:76;;-1:-1:-1;1803:9:23;;:53;;-1:-1:-1;;;1803:53:23;;-1:-1:-1;;;;;1803:9:23;;;;:17;;:53;;1821:10;;1841:4;;-1:-1:-1;;;;;;1803:9:23;1848:7;;;1803:53;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1772:85;;;;;;1868:9;:24;;-1:-1:-1;;;;;;1868:24:23;-1:-1:-1;;;;;1868:24:23;;;;;;;;1908:42;;1925:10;;1908:42;;-1:-1:-1;;1908:42:23;1523:434;:::o;3136:129:11:-;3226:12;3136:129;;;;;:::o;7260:94:34:-;902:33:23;915:10;927:7;;-1:-1:-1;;;;;;927:7:23;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:23;;;;;;;:::i;:::-;7309:8:34::1;:15:::0;;-1:-1:-1;;;;7309:15:34::1;-1:-1:-1::0;;;7309:15:34::1;::::0;;7339:8:::1;::::0;::::1;::::0;7309:15;;7339:8:::1;7260:94::o:0;7833:426::-;902:33:23;915:10;927:7;;-1:-1:-1;;;;;;927:7:23;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:23;;;;;;;:::i;:::-;2149:4:34::1;7989:32;::::0;::::1;;7985:96;;;8030:51;;-1:-1:-1::0;;;8030:51:34::1;;;;;;;;;;;7985:96;8110:50;::::0;;::::1;::::0;;::::1;::::0;;;::::1;;::::0;;;;::::1;;;::::0;;::::1;::::0;;;::::1;::::0;;::::1;::::0;;;;;;-1:-1:-1;;;;;8091:16:34;::::1;-1:-1:-1::0;8091:16:34;;;:9:::1;:16:::0;;;;;:69;;;;;;;;-1:-1:-1;;8091:69:34;;;;::::1;;-1:-1:-1::0;;8091:69:34;;::::1;::::0;::::1;;::::0;;;::::1;::::0;;;::::1;-1:-1:-1::0;;8091:69:34::1;::::0;;;;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;;8175:77;;8664:41:39;;;8721:18;;;8714:50;;;;8780:18;;;8773:47;;;;8175:77:34::1;::::0;8637:18:39;8175:77:34::1;;;;;;;7833:426:::0;;;;:::o;2980:1113:32:-;3443:21;902:33:23;915:10;927:7;;-1:-1:-1;;;;;;927:7:23;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:23;;;;;;;:::i;:::-;512:6:27::1;;522:1;512:11;504:34;;;;-1:-1:-1::0;;;504:34:27::1;;;;;;;:::i;:::-;558:1;549:10:::0;;3411:12:32;-1:-1:-1;;;;;;;5988:22:34;::::2;::::0;5984:85:::2;;6019:50;;-1:-1:-1::0;;;6019:50:34::2;;;;;;;;;;;5984:85;3520:18:32::3;3541:28;3556:12;3541:14;:28::i;:::-;3520:49;;3583:61;3597:12;3611:13;3626:8;3636:1;3639;3642;3583:13;:61::i;:::-;3674:86;3688:12;3702:13;3717:11;3730:10;3742;3754:5;3674:13;:86::i;:::-;3658:102;;3506:265;3780:92;3800:10;3812:12;3826:13;3841;3856:15;;;;;;;;;-1:-1:-1::0;;;;;3856:15:32::3;-1:-1:-1::0;;;;;3780:92:32::3;:19;:92::i;:::-;-1:-1:-1::0;;;;;3912:32:32;::::3;3908:100;;;3953:55;;-1:-1:-1::0;;;3953:55:32::3;;;;;;;;;;;3908:100;4018:68;4033:13;4049:2;4053:14;;4069:8;4079:6;4018:7;:68::i;:::-;-1:-1:-1::0;591:1:27::1;582:6;:10:::0;2980:1113:32;;-1:-1:-1;;;;;;;;;;;;2980:1113:32:o;16757:421:34:-;16930:14;902:33:23;915:10;927:7;;-1:-1:-1;;;;;;927:7:23;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:23;;;;;;;:::i;:::-;512:6:27::1;;522:1;512:11;504:34;;;;-1:-1:-1::0;;;504:34:27::1;;;;;;;:::i;:::-;558:1;549:10:::0;;16960:18:34::2;16981:28;16996:12:::0;16981:14:::2;:28::i;:::-;16960:49;;17029:78;17043:12;17057:13;17072:11;17085:10;17097:2;17101:5;17029:13;:78::i;:::-;17020:87;;17142:12;-1:-1:-1::0;;;;;17122:49:34::2;;17157:13;17122:49;;;;2892:25:39::0;;2880:2;2865:18;;2746:177;17122:49:34::2;;;;;;;;-1:-1:-1::0;591:1:27::1;582:6;:10:::0;16757:421:34;;-1:-1:-1;;;;16757:421:34:o;10378:128::-;902:33:23;915:10;927:7;;-1:-1:-1;;;;;;927:7:23;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:23;;;;;;;:::i;:::-;-1:-1:-1;;;;;10443:18:34;::::1;10464:5;10443:18:::0;;;:12:::1;:18;::::0;;;;;:26;;-1:-1:-1;;10443:26:34::1;::::0;;10484:15;::::1;::::0;10464:5;10484:15:::1;10378:128:::0;:::o;12015:379::-;-1:-1:-1;;;;;12117:18:34;;;;;;:12;:18;;;;;;;;;:36;;-1:-1:-1;;;;;;12139:14:34;;;;;;:10;:14;;;;;;;;12117:36;:66;;;-1:-1:-1;;;;;;12157:26:34;;;;;;:16;:26;;;;;;;;12117:66;12113:167;;;12206:63;;-1:-1:-1;;;12206:63:34;;-1:-1:-1;;;;;22275:15:39;;;12206:63:34;;;22257:34:39;22327:15;;;22307:18;;;22300:43;22379:15;;22359:18;;;22352:43;22192:18;;12206:63:34;22017:384:39;12113:167:34;-1:-1:-1;;;;;12293:21:34;;;;;;:15;:21;;;;;;12317:15;-1:-1:-1;12289:98:34;;;12341:46;;-1:-1:-1;;;12341:46:34;;;;;;;;;;;12289:98;12015:379;;;:::o;5008:497:31:-;902:33:23;915:10;927:7;;-1:-1:-1;;;;;;927:7:23;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:23;;;;;;;:::i;:::-;5157:15:31::1;-1:-1:-1::0;;;;;5157:20:31::1;5176:1;5157:20:::0;5153:96:::1;;5200:38;;-1:-1:-1::0;;;5200:38:31::1;;;;;;;;;;;5153:96;5280:19;::::0;::::1;5258;5280::::0;;;:10:::1;:19;::::0;;;;5309:28;;::::1;-1:-1:-1::0;;5347:39:31;;;;-1:-1:-1;;;;;5347:39:31;::::1;;::::0;;;;5396:43:::1;5280:19:::0;-1:-1:-1;;;;;5414:22:31;::::1;4797:8;:43::i;5396:::-;5455;::::0;;18795:10:39;18783:23;;18765:42;;-1:-1:-1;;;;;18843:32:39;;18838:2;18823:18;;18816:60;5455:43:31::1;::::0;18738:18:39;5455:43:31::1;;;;;;;5143:362;5008:497:::0;;;:::o;9739:263:34:-;902:33:23;915:10;927:7;;-1:-1:-1;;;;;;927:7:23;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:23;;;;;;;:::i;:::-;-1:-1:-1;;;;;9803:18:34;::::1;9824:5;9803:18:::0;;;:12:::1;:18;::::0;;;;;;;:26;;-1:-1:-1;;9803:26:34;;::::1;::::0;;;9839:10:::1;:16:::0;;;;;:24;;;::::1;::::0;;9873:16:::1;:22:::0;;;;;;:30;;;;::::1;::::0;;;9918:15;::::1;::::0;9824:5;9918:15:::1;9948:13;::::0;-1:-1:-1;;;;;9948:13:34;::::1;::::0;::::1;::::0;;;::::1;9976:19;::::0;-1:-1:-1;;;;;9976:19:34;::::1;::::0;::::1;::::0;;;::::1;9739:263:::0;:::o;3251:108:10:-;902:33:23;915:10;927:7;;-1:-1:-1;;;;;;927:7:23;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:23;;;;;;;:::i;:::-;3321:31:10::1;::::0;-1:-1:-1;;;3321:31:10;;-1:-1:-1;;;;;2300:32:39;;;3321:31:10::1;::::0;::::1;2282:51:39::0;3321:8:10::1;:20;::::0;::::1;::::0;2255:18:39;;3321:31:10::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;3251:108:::0;:::o;1593:912:32:-;1965:21;902:33:23;915:10;927:7;;-1:-1:-1;;;;;;927:7:23;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:23;;;;;;;:::i;:::-;512:6:27::1;;522:1;512:11;504:34;;;;-1:-1:-1::0;;;504:34:27::1;;;;;;;:::i;:::-;558:1;549:10:::0;;1933:12:32;-1:-1:-1;;;;;;;5988:22:34;::::2;::::0;5984:85:::2;;6019:50;;-1:-1:-1::0;;;6019:50:34::2;;;;;;;;;;;5984:85;2021:18:32::3;2042:28;2057:12;2042:14;:28::i;:::-;2021:49;;2096:86;2110:12;2124:13;2139:11;2152:10;2164;2176:5;2096:13;:86::i;:::-;2080:102;;2192:92;2212:10;2224:12;2238:13;2253;2268:15;;;;;;;;;-1:-1:-1::0;;;;;2268:15:32::3;-1:-1:-1::0;;;;;2192:92:32::3;:19;:92::i;:::-;-1:-1:-1::0;;;;;2324:32:32;::::3;2320:100;;;2365:55;;-1:-1:-1::0;;;2365:55:32::3;;;;;;;;;;;2320:100;2430:68;2445:13;2461:2;2465:14;;2481:8;2491:6;2430:7;:68::i;:::-;-1:-1:-1::0;;591:1:27::1;582:6;:10:::0;1593:912:32;;-1:-1:-1;;;;;;;;1593:912:32:o;5609:214:31:-;902:33:23;915:10;927:7;;-1:-1:-1;;;;;;927:7:23;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:23;;;;;;;:::i;:::-;5710:19:31::1;::::0;::::1;5688;5710::::0;;;:10:::1;:19;::::0;;;;;;;;5739:31;;-1:-1:-1;;5739:31:31::1;::::0;;5786:30;;20448:42:39;;;5710:19:31;;5786:30:::1;::::0;20421:18:39;5786:30:31::1;20303:193:39::0;4911:357:32;5114:35;;;;;;;;;-1:-1:-1;;;;;5114:35:32;;;;-1:-1:-1;;;;;5114:35:32;;;;;;5057:11;;;5177:20;5114:35;5177:18;:20::i;:::-;5159:38;;5215:46;5227:7;5236:14;;5252:8;5215:11;:46::i;:::-;5208:53;4911:357;-1:-1:-1;;;;;;;;4911:357:32:o;1963:164:23:-;902:33;915:10;927:7;;-1:-1:-1;;;;;;927:7:23;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:23;;;;;;;:::i;:::-;2046:5:::1;:16:::0;;-1:-1:-1;;;;;;2046:16:23::1;-1:-1:-1::0;;;;;2046:16:23;::::1;::::0;;::::1;::::0;;2078:42:::1;::::0;2046:16;;2099:10:::1;::::0;2078:42:::1;::::0;2046:5;2078:42:::1;1963:164:::0;:::o;2400:149:11:-;2482:4;2529:13;;;;;;2505:5;;2482:4;;2511:13;;2529:6;2511:13;:::i;:::-;2505:20;;;;;;;;;;;;;-1:-1:-1;2505:20:11;;:37;;2400:149;-1:-1:-1;;2400:149:11:o;977:540:23:-;1097:9;;1064:4;;-1:-1:-1;;;;;1097:9:23;1415:27;;;;;:77;;-1:-1:-1;1446:46:23;;-1:-1:-1;;;1446:46:23;;-1:-1:-1;;;;;1446:12:23;;;;;:46;;1459:4;;1473;;1480:11;;1446:46;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1414:96;;;-1:-1:-1;1505:5:23;;-1:-1:-1;;;;;1497:13:23;;;1505:5;;1497:13;1414:96;1407:103;977:540;-1:-1:-1;;;;977:540:23:o;5451:850:32:-;5695:50;5710:10;5730:1;5734:10;5695:14;:50::i;:::-;5791:69;;-1:-1:-1;;;5791:69:32;;5810:1;5791:69;;;22724:34:39;;;22774:18;;;22767:43;;;22826:18;;;22819:34;5836:10:32;22869:18:39;;;22862:43;-1:-1:-1;;;;;22942:39:39;;22921:19;;;22914:68;5791:5:32;-1:-1:-1;;;;;5791:10:32;;;;22658:19:39;;5791:69:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;5930:35:32;;;;;;;;;-1:-1:-1;;;;;5930:35:32;;;;-1:-1:-1;;;;;5930:35:32;;;;;;;-1:-1:-1;5900:27:32;;-1:-1:-1;6133:20:32;5930:35;6133:18;:20::i;:::-;6115:38;;6164:17;6184:55;6197:7;6206:14;;6222:8;6232:6;6184:12;:55::i;:::-;6255:39;;-1:-1:-1;;;;;16807:39:39;;16789:58;;6164:75:32;;-1:-1:-1;;;;;;6255:39:32;;;6164:75;;6255:39;;16777:2:39;16762:18;6255:39:32;;;;;;;5584:717;;;5451:850;;;;;;:::o;19063:294:34:-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;19164:8:34;;-1:-1:-1;;;19164:8:34;;;;19160:58;;;19181:37;;-1:-1:-1;;;19181:37:34;;;;;;;;;;;19160:58;-1:-1:-1;;;;;;19236:23:34;;;;;;:9;:23;;;;;;;;;19228:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19269:81;;19302:48;;-1:-1:-1;;;19302:48:34;;;;;;;;;;;19269:81;19063:294;;;:::o;4302:1462:28:-;4413:12;4583:4;4577:11;-1:-1:-1;;;4706:17:28;4699:93;-1:-1:-1;;;;;4843:2:28;4839:51;4835:1;4816:17;4812:25;4805:86;4977:6;4972:2;4953:17;4949:26;4942:42;5324:2;5321:1;5317:2;5298:17;5295:1;5288:5;5281;5276:51;5265:62;;;5594:7;5587:2;5569:16;5566:24;5562:1;5558;5552:8;5549:15;5545:46;5538:54;5534:68;5531:172;;;-1:-1:-1;5649:18:28;;5642:26;5670:16;5639:48;5632:56;5531:172;5731:7;5723:34;;;;-1:-1:-1;;;5723:34:28;;23409:2:39;5723:34:28;;;23391:21:39;23448:2;23428:18;;;23421:30;-1:-1:-1;;;23467:18:39;;;23460:44;23521:18;;5723:34:28;23207:338:39;5723:34:28;4403:1361;4302:1462;;;:::o;18330:669:34:-;18535:14;18565:13;18582:1;18565:18;18561:72;;18592:41;;-1:-1:-1;;;18592:41:34;;;;;;;;;;;18561:72;18688:43;;-1:-1:-1;;;18688:43:34;;-1:-1:-1;;;;;2300:32:39;;;18688:43:34;;;2282:51:39;18652:80:34;;18677:9;;18688:10;:29;;;;2255:18:39;;18688:43:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;18652:13;;:80;:24;:80::i;:::-;18643:89;;18772:1;18751:5;:18;;;:22;;;:82;;18827:6;18751:82;;;18776:48;18800:5;:18;;;18794:3;:24;;;;:::i;:::-;18776:6;;:48;;18820:3;18776:17;:48::i;:::-;18742:91;;18856:11;18847:6;:20;18843:81;;;18876:48;;-1:-1:-1;;;18876:48:34;;;;;;;;;;;18843:81;18934:58;;-1:-1:-1;;;18934:58:34;;-1:-1:-1;;;;;18934:5:34;:11;;;;:58;;18946:4;;18952:12;;18966:13;;18981:2;;18985:6;;18934:58;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18330:669;;;;;;;;:::o;19430:826::-;19716:12;19714:14;;19698:13;;19716:12;19698:13;;19714:14;;-1:-1:-1;;;;;19714:14:34;;:::i;:::-;;;-1:-1:-1;;;;;19714:14:34;;;;;;;;;;;;;;;;;;;;-1:-1:-1;19832:26:34;;19828:300;;19898:40;19916:22;19898:15;:40;:::i;:::-;-1:-1:-1;;;;;19874:21:34;;;;;;;:15;:21;;;;;;;;;:64;;;;20009:94;;;;;21091:34:39;;;;21161:15;;;21141:18;;;21134:43;21193:18;;;21186:34;;;21236:18;;;21229:34;;;20063:15:34;21279:19:39;;;21272:35;21323:19;;;21316:35;;;21025:19;;20009:94:34;;;-1:-1:-1;;20009:94:34;;;;;;;;;19982:135;;20009:94;19982:135;;;;19952:27;;;;:20;:27;;;;;:165;19828:300;20171:12;-1:-1:-1;;;;;20142:107:34;20157:4;-1:-1:-1;;;;;20142:107:34;20150:5;20142:107;20186:13;20201:6;20209:15;20226:22;20142:107;;;;;;;;24919:25:39;;;24975:2;24960:18;;24953:34;;;;25018:2;25003:18;;24996:34;25061:2;25046:18;;25039:34;24906:3;24891:19;;24688:391;20142:107:34;;;;;;;;19619:637;19430:826;;;;;:::o;2717:196:10:-;2821:11;;;2787:7;2821:11;;;:5;:11;;;;;;;2842:43;;2873:12;;-1:-1:-1;;;2873:12:10;;20478:10:39;20466:23;;2873:12:10;;;20448:42:39;20421:18;;2873:12:10;20303:193:39;6949:479:31;7162:19;7184:10;7162:19;7195:14;;;;:7;:14;:::i;:::-;7184:26;;;;;;;;;;;;;;;;-1:-1:-1;7184:26:31;7162:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;7162:48:31;;;;;;;;;-1:-1:-1;7220:93:31;;7298:14;;;;:7;:14;:::i;:::-;7258:55;;-1:-1:-1;;;7258:55:31;;20478:10:39;20466:23;;;7258:55:31;;;20448:42:39;20421:18;;7258:55:31;20303:193:39;7220:93:31;7323:15;7341:31;;;;7352:8;7341:31;:::i;:::-;7323:49;;7382:39;7406:5;7413:7;7382:23;:39::i;:::-;7152:276;;6949:479;;;;;;;:::o;2285:134:10:-;2358:11;;;;;;;:5;:11;;;;;;;;;:19;;;2392:20;;18186:42:39;;;18244:18;;18237:34;;;2392:20:10;;18159:18:39;2392:20:10;18014:263:39;20314:452:34;20464:81;;-1:-1:-1;;;20464:81:34;;20484:10;20464:81;;;25630:34:39;-1:-1:-1;;;;;20504:5:34;25700:15:39;;25680:18;;;25673:43;25732:18;;;25725:34;;;25775:18;;;25768:34;;;25851:4;25839:17;;25818:19;;;25811:46;25873:19;;;25866:35;;;25917:19;;;25910:35;;;20464:19:34;;;;;25564::39;;20464:81:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20460:300;;20581:50;;-1:-1:-1;;;20581:50:34;;20604:10;20581:50;;;26168:34:39;-1:-1:-1;;;;;20624:5:34;26238:15:39;;26218:18;;;26211:43;20634:13:34;;20581:22;;;;;;26103:18:39;;20581:50:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:66;20577:173;;;20674:61;;-1:-1:-1;;;20674:61:34;;;;;;;;;;;20577:173;20314:452;;;;;;:::o;1564:526:26:-;1680:9;1928:1;-1:-1:-1;;1911:19:26;1908:1;1905:26;1902:1;1898:34;1891:42;1878:11;1874:60;1864:116;;1964:1;1961;1954:12;1864:116;-1:-1:-1;2051:9:26;;2047:27;;1564:526::o;1009:237:33:-;1101:13;;1076:9;;-1:-1:-1;;;;;;1097:78:33;;;1142:33;;-1:-1:-1;;;1142:33:33;;;;;;;;;;;1097:78;1191:13;;1234:4;;;;;-1:-1:-1;;;;;1221:18:33;1208:3;1191:20;;;;1186:25;1221:18;;1009:237::o;9720:969:31:-;9869:11;-1:-1:-1;;;;;9959:27:31;;1789:42:34;9959:27:31;;;;:59;;;10011:7;-1:-1:-1;;;;;9990:28:31;9998:8;-1:-1:-1;;;;;9990:28:31;;;9959:59;9955:127;;;10041:30;;-1:-1:-1;;;10041:30:31;;;;;;;;;;;9955:127;10091:20;10114:36;;;;10125:14;10114:36;:::i;:::-;10181:25;;;10160:18;10181:25;;;:10;:25;;;;;;;;;10160:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;10160:46:31;;;;;;;;10181:25;;-1:-1:-1;10160:46:31;10216:112;;10265:52;;-1:-1:-1;;;10265:52:31;;20478:10:39;20466:23;;10265:52:31;;;20448:42:39;20421:18;;10265:52:31;20303:193:39;10216:112:31;10337:14;10365:7;10354:19;;;;;;2892:25:39;;2880:2;2865:18;;2746:177;10354:19:31;;;;;;;;;;;;;10337:36;;10383:20;10406:80;10461:5;:21;;;10484:1;10406:27;936:24:13;;;-1:-1:-1;;;936:24:13;;;27287:51:39;936:24:13;;;;;;;;;27354:11:39;;;;936:24:13;;;;860:107;10406:27:31;:54;:80;:54;:80::i;:::-;10383:103;-1:-1:-1;10496:30:31;10529:62;10536:13;10551:1;10383:103;-1:-1:-1;;;;;10563:27:31;;1789:42:34;10563:27:31;;10529:6;:62::i;:::-;10496:95;-1:-1:-1;;;;;;10608:27:31;;1789:42:34;10608:27:31;:74;;10661:10;:21;;;10608:74;;;10638:20;;10608:74;10602:80;9720:969;-1:-1:-1;;;;;;;;;;9720:969:31:o;8146:1288::-;8299:17;;8355:36;;;;8366:14;8355:36;:::i;:::-;8422:25;;;8401:18;8422:25;;;:10;:25;;;;;;;;;8401:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;8401:46:31;;;;;;;;8422:25;;-1:-1:-1;8401:46:31;8457:112;;8506:52;;-1:-1:-1;;;8506:52:31;;20478:10:39;20466:23;;8506:52:31;;;20448:42:39;20421:18;;8506:52:31;20303:193:39;8457:112:31;8578:14;8606:7;8595:19;;;;;;2892:25:39;;2880:2;2865:18;;2746:177;8595:19:31;;;;;;;;;;;;;8578:36;;8624:20;8647:80;8702:5;:21;;;8725:1;8647:27;936:24:13;;;-1:-1:-1;;;936:24:13;;;27287:51:39;936:24:13;;;;;;;;;27354:11:39;;;;936:24:13;;;;860:107;8647:80:31;8624:103;-1:-1:-1;8737:23:31;8763:62;8770:13;8785:1;8624:103;-1:-1:-1;;;;;8797:27:31;;1789:42:34;8797:27:31;;8763:6;:62::i;:::-;8737:88;-1:-1:-1;;;;;;;;8839:27:31;;;8835:463;;8886:13;;:22;-1:-1:-1;8882:136:31;;;8981:13;;8935:68;;-1:-1:-1;;;8935:68:31;;26496:10:39;26484:23;;8935:68:31;;;26466:42:39;26524:18;;;26517:34;;;;26567:18;;;26560:34;;;26439:18;;8935:68:31;26265:335:39;8882:136:31;8835:463;;;9059:7;-1:-1:-1;;;;;9038:28:31;9046:8;-1:-1:-1;;;;;9038:28:31;;9034:264;;9103:6;9086:3;:14;;;:23;9082:138;;;9182:14;;;;9136:69;;-1:-1:-1;;;9136:69:31;;26496:10:39;26484:23;;9136:69:31;;;26466:42:39;26524:18;;;26517:34;;;;26567:18;;;26560:34;;;26439:18;;9136:69:31;26265:335:39;9034:264:31;9257:30;;-1:-1:-1;;;9257:30:31;;;;;;;;;;;9034:264;9307:31;9341:51;9349:13;9364:1;9367:7;9376:3;9381:10;9341:7;:51::i;:::-;9415:12;;8146:1288;-1:-1:-1;;;;;;;;;;;;8146:1288:31:o;6469:328:32:-;-1:-1:-1;;;;;;;;893:3:33;888:8;;;865:32;;;-1:-1:-1;;;;;907:26:33;;;-1:-1:-1;;;907:26:33;;;6661:66:32;;-1:-1:-1;;;6661:66:32;;-1:-1:-1;;6661:5:32;:11;;;;;;:66;;-1:-1:-1;;;;;;907:26:33;6661:66:32;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6785:1;:4;;;-1:-1:-1;;;;;6743:47:32;6759:9;6743:47;6770:1;:13;;;6743:47;;;;2892:25:39;;2880:2;2865:18;;2746:177;6743:47:32;;;;;;;;6547:250;6469:328;;:::o;1658:331:13:-;1822:12;1795:8;356:1;625:20;1795:8;643:1;625:17;:20::i;:::-;:30;;;621:82;;682:20;:8;700:1;682:17;:20::i;:::-;664:39;;-1:-1:-1;;;664:39:13;;27550:6:39;27538:19;;;664:39:13;;;27520:38:39;27493:18;;664:39:13;27376:188:39;621:82:13;1850:19:::1;1872:35;1894:4;1900:6;1872:21;:35::i;:::-;1850:57;;1924:58;1942:8;411:1;1975:6;1924:17;:58::i;:::-;1917:65:::0;1658:331;-1:-1:-1;;;;;;1658:331:13:o;2051:353:12:-;-1:-1:-1;;;;;;;;;;;;;;;;;2258:8:12;-1:-1:-1;;;;;2258:14:12;;2286:86;;;;;;;;2302:7;2286:86;;;;;;2311:25;2328:7;2311:16;:25::i;:::-;2286:86;;;;2338:8;2286:86;;;;2348:8;2286:86;;;;2358:13;2286:86;;;;;2382:4;2258:139;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2251:146;2051:353;-1:-1:-1;;;;;2051:353:12:o;3163:741::-;3364:31;;:::i;:::-;3529:20;3552:26;3563:4;:14;;;3552:10;:26::i;:::-;3592:15;;;;3529:49;;-1:-1:-1;3592:19:12;3588:53;;3613:28;3625:4;:15;;;3613:11;:28::i;:::-;3659:8;-1:-1:-1;;;;;3659:85:12;;3752:12;3779:92;;;;;;;;3795:7;3779:92;;;;;;3804:25;3821:7;3804:16;:25::i;:::-;3779:92;;;;3831:8;3779:92;;;;3841:8;3779:92;;;;3869:1;3851:4;:15;;;:19;3779:92;;;;;3873:14;3659:238;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3652:245;3163:741;-1:-1:-1;;;;;;;3163:741:12:o;12935:305:8:-;13013:6;13056:10;:6;13065:1;13056:10;:::i;:::-;13039:6;:13;:27;;13031:60;;;;-1:-1:-1;;;13031:60:8;;30818:2:39;13031:60:8;;;30800:21:39;30857:2;30837:18;;;30830:30;-1:-1:-1;;;30876:18:39;;;30869:50;30936:18;;13031:60:8;30616:344:39;13031:60:8;-1:-1:-1;13168:29:8;13184:3;13168:29;13162:36;;12935:305::o;2699:191:13:-;2783:12;-1:-1:-1;;;;;2814:11:13;;;:69;;2853:30;;;-1:-1:-1;;;;;;31200:3:39;31196:16;;;31192:25;;2853:30:13;;;31180:38:39;31252:16;;;31248:25;31234:12;;;31227:47;31290:12;2853:30:13;;;;;;;;;;;;2814:69;;;2828:22;;-1:-1:-1;;;;;;31462:3:39;31458:16;;;31454:62;2828:22:13;;;31442:75:39;31533:12;;2828:22:13;;;;;;;;;;;;2814:69;2807:76;2699:191;-1:-1:-1;;;2699:191:13:o;2304:389::-;2470:12;2443:8;356:1;625:20;2443:8;643:1;625:17;:20::i;:::-;:30;;;621:82;;682:20;:8;700:1;682:17;:20::i;621:82::-;2535:8:::1;454:1;2580:25;:7;:14;:23;:25::i;:::-;:29;::::0;2608:1:::1;2580:29;:::i;:::-;2644:11;2669:7;2505:181;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;2498:188;;2304:389:::0;;;;;;:::o;4600:191:12:-;4666:17;4712:10;4699:9;:23;4695:62;;4731:26;;-1:-1:-1;;;4731:26:12;;4747:9;4731:26;;;2892:25:39;2865:18;;4731:26:12;2746:177:39;4695:62:12;-1:-1:-1;4774:10:12;4600:191::o;5168:409::-;5321:15;5339:8;-1:-1:-1;;;;;5339:16:12;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5321:36;-1:-1:-1;;;;;;5371:21:12;;5367:54;;5401:20;;-1:-1:-1;;;5401:20:12;;;;;;;;;;;5367:54;5495:75;-1:-1:-1;;;;;5495:31:12;;5527:10;5547:8;5558:11;5495:31;:75::i;16296:213:22:-;16352:6;16382:16;16374:24;;16370:103;;;16421:41;;-1:-1:-1;;;16421:41:22;;16452:2;16421:41;;;32961:36:39;33013:18;;;33006:34;;;32934:18;;16421:41:22;32780:266:39;1187:1639:28;1325:12;1495:4;1489:11;-1:-1:-1;;;1618:17:28;1611:93;-1:-1:-1;;;;;1755:4:28;1751:53;1747:1;1728:17;1724:25;1717:88;-1:-1:-1;;;;;1897:2:28;1893:51;1888:2;1869:17;1865:26;1858:87;2031:6;2026:2;2007:17;2003:26;1996:42;2380:2;2377:1;2372:3;2353:17;2350:1;2343:5;2336;2331:52;2320:63;;;2650:7;2643:2;2625:16;2622:24;2618:1;2614;2608:8;2605:15;2601:46;2594:54;2590:68;2587:172;;;-1:-1:-1;2705:18:28;;2698:26;2726:16;2695:48;2688:56;2587:172;2787:7;2779:40;;;;-1:-1:-1;;;2779:40:28;;33253:2:39;2779:40:28;;;33235:21:39;33292:2;33272:18;;;33265:30;-1:-1:-1;;;33311:18:39;;;33304:50;33371:18;;2779:40:28;33051:344:39;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;14:131:39:-;-1:-1:-1;;;;;89:31:39;;79:42;;69:70;;135:1;132;125:12;69:70;14:131;:::o;150:134::-;218:20;;247:31;218:20;247:31;:::i;289:247::-;348:6;401:2;389:9;380:7;376:23;372:32;369:52;;;417:1;414;407:12;369:52;456:9;443:23;475:31;500:5;475:31;:::i;733:179::-;800:20;;-1:-1:-1;;;;;849:38:39;;839:49;;829:77;;902:1;899;892:12;917:347;968:8;978:6;1032:3;1025:4;1017:6;1013:17;1009:27;999:55;;1050:1;1047;1040:12;999:55;-1:-1:-1;1073:20:39;;-1:-1:-1;;;;;1105:30:39;;1102:50;;;1148:1;1145;1138:12;1102:50;1185:4;1177:6;1173:17;1161:29;;1237:3;1230:4;1221:6;1213;1209:19;1205:30;1202:39;1199:59;;;1254:1;1251;1244:12;1199:59;917:347;;;;;:::o;1269:841::-;1388:6;1396;1404;1412;1420;1428;1481:3;1469:9;1460:7;1456:23;1452:33;1449:53;;;1498:1;1495;1488:12;1449:53;1521:28;1539:9;1521:28;:::i;:::-;1511:38;;1599:2;1588:9;1584:18;1571:32;1612:31;1637:5;1612:31;:::i;:::-;1662:5;-1:-1:-1;1718:2:39;1703:18;;1690:32;-1:-1:-1;;;;;1734:30:39;;1731:50;;;1777:1;1774;1767:12;1731:50;1816:58;1866:7;1857:6;1846:9;1842:22;1816:58;:::i;:::-;1893:8;;-1:-1:-1;1790:84:39;-1:-1:-1;;1980:2:39;1965:18;;1952:32;1993:33;1952:32;1993:33;:::i;:::-;2045:7;2035:17;;;2099:3;2088:9;2084:19;2071:33;2061:43;;1269:841;;;;;;;;:::o;2344:397::-;2435:6;2443;2451;2504:2;2492:9;2483:7;2479:23;2475:32;2472:52;;;2520:1;2517;2510:12;2472:52;2559:9;2546:23;2578:31;2603:5;2578:31;:::i;:::-;2628:5;2680:2;2665:18;;2652:32;;-1:-1:-1;2731:2:39;2716:18;;;2703:32;;2344:397;-1:-1:-1;;;2344:397:39:o;2928:129::-;-1:-1:-1;;;;;3006:5:39;3002:30;2995:5;2992:41;2982:69;;3047:1;3044;3037:12;3062:245;3120:6;3173:2;3161:9;3152:7;3148:23;3144:32;3141:52;;;3189:1;3186;3179:12;3141:52;3228:9;3215:23;3247:30;3271:5;3247:30;:::i;3312:154::-;3371:5;3416:2;3407:6;3402:3;3398:16;3394:25;3391:45;;;3432:1;3429;3422:12;3391:45;-1:-1:-1;3454:6:39;3312:154;-1:-1:-1;3312:154:39:o;3471:1047::-;3613:6;3621;3629;3637;3645;3653;3661;3714:3;3702:9;3693:7;3689:23;3685:33;3682:53;;;3731:1;3728;3721:12;3682:53;3754;3799:7;3788:9;3754:53;:::i;:::-;3744:63;;3854:2;3843:9;3839:18;3826:32;3816:42;;3909:3;3898:9;3894:19;3881:33;-1:-1:-1;;;;;3974:2:39;3966:6;3963:14;3960:34;;;3990:1;3987;3980:12;3960:34;4029:58;4079:7;4070:6;4059:9;4055:22;4029:58;:::i;:::-;4106:8;;-1:-1:-1;4003:84:39;-1:-1:-1;4191:3:39;4176:19;;4163:33;;-1:-1:-1;4205:31:39;4163:33;4205:31;:::i;:::-;4255:5;;-1:-1:-1;4313:3:39;4298:19;;4285:33;;4330:16;;;4327:36;;;4359:1;4356;4349:12;4327:36;;4398:60;4450:7;4439:8;4428:9;4424:24;4398:60;:::i;:::-;3471:1047;;;;-1:-1:-1;3471:1047:39;;-1:-1:-1;3471:1047:39;;;;4372:86;;-1:-1:-1;;;3471:1047:39:o;4523:163::-;4590:20;;4650:10;4639:22;;4629:33;;4619:61;;4676:1;4673;4666:12;4691:188;4759:20;;-1:-1:-1;;;;;4808:46:39;;4798:57;;4788:85;;4869:1;4866;4859:12;4884:258;4951:6;4959;5012:2;5000:9;4991:7;4987:23;4983:32;4980:52;;;5028:1;5025;5018:12;4980:52;5051:28;5069:9;5051:28;:::i;:::-;5041:38;;5098;5132:2;5121:9;5117:18;5098:38;:::i;:::-;5088:48;;4884:258;;;;;:::o;5451:319::-;5518:6;5526;5579:2;5567:9;5558:7;5554:23;5550:32;5547:52;;;5595:1;5592;5585:12;5547:52;5618:28;5636:9;5618:28;:::i;:::-;5608:38;;5696:2;5685:9;5681:18;5668:32;5709:31;5734:5;5709:31;:::i;:::-;5759:5;5749:15;;;5451:319;;;;;:::o;5775:252::-;5842:6;5850;5903:2;5891:9;5882:7;5878:23;5874:32;5871:52;;;5919:1;5916;5909:12;5871:52;5942:28;5960:9;5942:28;:::i;:::-;5932:38;6017:2;6002:18;;;;5989:32;;-1:-1:-1;;;5775:252:39:o;6032:118::-;6118:5;6111:13;6104:21;6097:5;6094:32;6084:60;;6140:1;6137;6130:12;6155:665;6243:6;6251;6259;6267;6275;6328:3;6316:9;6307:7;6303:23;6299:33;6296:53;;;6345:1;6342;6335:12;6296:53;6368:28;6386:9;6368:28;:::i;:::-;6358:38;;6446:2;6435:9;6431:18;6418:32;6459:28;6481:5;6459:28;:::i;:::-;6506:5;-1:-1:-1;6563:2:39;6548:18;;6535:32;6576:30;6535:32;6576:30;:::i;:::-;6625:7;-1:-1:-1;6684:2:39;6669:18;;6656:32;6697:33;6656:32;6697:33;:::i;:::-;6749:7;-1:-1:-1;6775:39:39;6809:3;6794:19;;6775:39;:::i;:::-;6765:49;;6155:665;;;;;;;;:::o;6825:156::-;6891:20;;6951:4;6940:16;;6930:27;;6920:55;;6971:1;6968;6961:12;6986:675;7111:6;7119;7127;7135;7143;7151;7159;7212:3;7200:9;7191:7;7187:23;7183:33;7180:53;;;7229:1;7226;7219:12;7180:53;7268:9;7255:23;7287:31;7312:5;7287:31;:::i;:::-;7337:5;-1:-1:-1;7389:2:39;7374:18;;7361:32;;-1:-1:-1;7440:2:39;7425:18;;7412:32;;-1:-1:-1;7491:2:39;7476:18;;7463:32;;-1:-1:-1;7514:37:39;7546:3;7531:19;;7514:37;:::i;:::-;7504:47;;7598:3;7587:9;7583:19;7570:33;7560:43;;7650:3;7639:9;7635:19;7622:33;7612:43;;6986:675;;;;;;;;;;:::o;7666:539::-;7766:6;7774;7782;7790;7843:3;7831:9;7822:7;7818:23;7814:33;7811:53;;;7860:1;7857;7850:12;7811:53;7899:9;7886:23;7918:31;7943:5;7918:31;:::i;:::-;7968:5;-1:-1:-1;8020:2:39;8005:18;;7992:32;;-1:-1:-1;8071:2:39;8056:18;;8043:32;;-1:-1:-1;8127:2:39;8112:18;;8099:32;8140:33;8099:32;8140:33;:::i;:::-;7666:539;;;;-1:-1:-1;7666:539:39;;-1:-1:-1;;7666:539:39:o;8831:184::-;8889:6;8942:2;8930:9;8921:7;8917:23;8913:32;8910:52;;;8958:1;8955;8948:12;8910:52;8981:28;8999:9;8981:28;:::i;9020:732::-;9133:6;9141;9149;9157;9165;9173;9181;9234:3;9222:9;9213:7;9209:23;9205:33;9202:53;;;9251:1;9248;9241:12;9202:53;9287:9;9274:23;9264:33;;9347:2;9336:9;9332:18;9319:32;9360:31;9385:5;9360:31;:::i;:::-;9410:5;-1:-1:-1;9467:2:39;9452:18;;9439:32;9480:33;9439:32;9480:33;:::i;:::-;9020:732;;;;-1:-1:-1;9532:7:39;;9586:2;9571:18;;9558:32;;-1:-1:-1;9637:3:39;9622:19;;9609:33;;9689:3;9674:19;;9661:33;;-1:-1:-1;9741:3:39;9726:19;;;9713:33;;-1:-1:-1;9020:732:39;-1:-1:-1;;9020:732:39:o;10920:700::-;11013:6;11021;11029;11037;11090:3;11078:9;11069:7;11065:23;11061:33;11058:53;;;11107:1;11104;11097:12;11058:53;11146:9;11133:23;11165:31;11190:5;11165:31;:::i;:::-;11215:5;-1:-1:-1;11272:2:39;11257:18;;11244:32;11285:30;11244:32;11285:30;:::i;:::-;11334:7;-1:-1:-1;11393:2:39;11378:18;;11365:32;11406:30;11365:32;11406:30;:::i;:::-;11455:7;-1:-1:-1;11514:2:39;11499:18;;11486:32;11562:6;11549:20;;11537:33;;11527:61;;11584:1;11581;11574:12;11625:1261;11811:6;11819;11827;11835;11843;11851;11859;11867;11875;11883;11891:7;11900;11954:3;11942:9;11933:7;11929:23;11925:33;11922:53;;;11971:1;11968;11961:12;11922:53;11984:49;12022:9;12009:23;11984:49;:::i;:::-;12065:9;12052:23;12042:33;;12122:2;12111:9;12107:18;12094:32;12084:42;;12173:2;12162:9;12158:18;12145:32;12135:42;;12224:2;12213:9;12209:18;12196:32;12186:42;;12247:37;12279:3;12268:9;12264:19;12247:37;:::i;:::-;12237:47;;12331:3;12320:9;12316:19;12303:33;12293:43;;12383:3;12372:9;12368:19;12355:33;12345:43;;12397:59;12450:3;12439:9;12435:19;12422:33;12397:59;:::i;:::-;12503:3;12492:9;12488:19;12475:33;12465:43;;-1:-1:-1;;;;;12551:3:39;12540:9;12536:19;12523:33;12520:57;12517:77;;;12590:1;12587;12580:12;12517:77;12629:85;12706:7;12698:3;12687:9;12683:19;12670:33;12659:9;12655:49;12629:85;:::i;:::-;12733:8;;-1:-1:-1;12760:8:39;-1:-1:-1;12788:39:39;12822:3;12807:19;;12788:39;:::i;:::-;12777:50;;12875:3;12864:9;12860:19;12847:33;12836:44;;11625:1261;;;;;;;;;;;;;;:::o;12891:180::-;12950:6;13003:2;12991:9;12982:7;12978:23;12974:32;12971:52;;;13019:1;13016;13009:12;12971:52;-1:-1:-1;13042:23:39;;12891:180;-1:-1:-1;12891:180:39:o;13258:529::-;13335:6;13343;13351;13404:2;13392:9;13383:7;13379:23;13375:32;13372:52;;;13420:1;13417;13410:12;13372:52;13459:9;13446:23;13478:31;13503:5;13478:31;:::i;:::-;13528:5;-1:-1:-1;13585:2:39;13570:18;;13557:32;13598:33;13557:32;13598:33;:::i;:::-;13650:7;-1:-1:-1;13709:2:39;13694:18;;13681:32;13722:33;13681:32;13722:33;:::i;:::-;13774:7;13764:17;;;13258:529;;;;;:::o;13792:393::-;13868:6;13876;13884;13937:2;13925:9;13916:7;13912:23;13908:32;13905:52;;;13953:1;13950;13943:12;13905:52;13976:28;13994:9;13976:28;:::i;:::-;13966:38;;14054:2;14043:9;14039:18;14026:32;14067:31;14092:5;14067:31;:::i;:::-;14117:5;-1:-1:-1;14141:38:39;14175:2;14160:18;;14141:38;:::i;:::-;14131:48;;13792:393;;;;;:::o;14416:1062::-;14568:6;14576;14584;14592;14600;14608;14616;14624;14677:3;14665:9;14656:7;14652:23;14648:33;14645:53;;;14694:1;14691;14684:12;14645:53;14733:9;14720:23;14752:31;14777:5;14752:31;:::i;:::-;14802:5;-1:-1:-1;14854:2:39;14839:18;;14826:32;;-1:-1:-1;14905:2:39;14890:18;;14877:32;;-1:-1:-1;14961:2:39;14946:18;;14933:32;14974:33;14933:32;14974:33;:::i;:::-;15026:7;-1:-1:-1;15084:3:39;15069:19;;15056:33;-1:-1:-1;;;;;15101:30:39;;15098:50;;;15144:1;15141;15134:12;15098:50;15183:58;15233:7;15224:6;15213:9;15209:22;15183:58;:::i;:::-;15260:8;;-1:-1:-1;15157:84:39;-1:-1:-1;;15347:3:39;15332:19;;15319:33;15361;15319;15361;:::i;:::-;15413:7;15403:17;;;15467:3;15456:9;15452:19;15439:33;15429:43;;14416:1062;;;;;;;;;;;:::o;15868:772::-;15978:6;15986;15994;16002;16010;16063:3;16051:9;16042:7;16038:23;16034:33;16031:53;;;16080:1;16077;16070:12;16031:53;16103:28;16121:9;16103:28;:::i;:::-;16093:38;;16181:2;16170:9;16166:18;16153:32;16194:31;16219:5;16194:31;:::i;:::-;16244:5;-1:-1:-1;16300:2:39;16285:18;;16272:32;-1:-1:-1;;;;;16316:30:39;;16313:50;;;16359:1;16356;16349:12;16313:50;16398:58;16448:7;16439:6;16428:9;16424:22;16398:58;:::i;:::-;16475:8;;-1:-1:-1;16372:84:39;-1:-1:-1;;16562:2:39;16547:18;;16534:32;16575:33;16534:32;16575:33;:::i;:::-;16627:7;16617:17;;;15868:772;;;;;;;;:::o;17094:235::-;17178:6;17231:2;17219:9;17210:7;17206:23;17202:32;17199:52;;;17247:1;17244;17237:12;17199:52;17270:53;17315:7;17304:9;17270:53;:::i;17334:336::-;17536:2;17518:21;;;17575:2;17555:18;;;17548:30;-1:-1:-1;;;17609:2:39;17594:18;;17587:42;17661:2;17646:18;;17334:336::o;17675:334::-;17877:2;17859:21;;;17916:2;17896:18;;;17889:30;-1:-1:-1;;;17950:2:39;17935:18;;17928:40;18000:2;17985:18;;17675:334::o;19567:184::-;19637:6;19690:2;19678:9;19669:7;19665:23;19661:32;19658:52;;;19706:1;19703;19696:12;19658:52;-1:-1:-1;19729:16:39;;19567:184;-1:-1:-1;19567:184:39:o;19756:542::-;-1:-1:-1;;;;;20085:15:39;;;20067:34;;20137:15;;;20132:2;20117:18;;20110:43;20184:2;20169:18;;20162:34;;;;20232:15;;;20227:2;20212:18;;20205:43;20279:3;20264:19;;20257:35;;;;20016:3;20001:19;;19756:542::o;20501:127::-;20562:10;20557:3;20553:20;20550:1;20543:31;20593:4;20590:1;20583:15;20617:4;20614:1;20607:15;20633:128;20700:9;;;20721:11;;;20718:37;;;20735:18;;:::i;21362:400::-;-1:-1:-1;;;;;21618:15:39;;;21600:34;;21670:15;;;;21665:2;21650:18;;21643:43;-1:-1:-1;;;;;;21722:33:39;;;21717:2;21702:18;;21695:61;21550:2;21535:18;;21362:400::o;21767:245::-;21834:6;21887:2;21875:9;21866:7;21862:23;21858:32;21855:52;;;21903:1;21900;21893:12;21855:52;21935:9;21929:16;21954:28;21976:5;21954:28;:::i;23550:171::-;23618:6;23657:10;;;23645;;;23641:27;;23680:12;;;23677:38;;;23695:18;;:::i;:::-;23677:38;23550:171;;;;:::o;23726:217::-;23764:3;-1:-1:-1;;;;;23853:2:39;23846:5;23842:14;23880:2;23871:7;23868:15;23865:41;;23886:18;;:::i;:::-;23935:1;23922:15;;23726:217;-1:-1:-1;;;23726:217:39:o;23948:125::-;24013:9;;;24034:10;;;24031:36;;;24047:18;;:::i;27569:250::-;27654:1;27664:113;27678:6;27675:1;27672:13;27664:113;;;27754:11;;;27748:18;27735:11;;;27728:39;27700:2;27693:10;27664:113;;;-1:-1:-1;;27811:1:39;27793:16;;27786:27;27569:250::o;27824:270::-;27865:3;27903:5;27897:12;27930:6;27925:3;27918:19;27946:76;28015:6;28008:4;28003:3;27999:14;27992:4;27985:5;27981:16;27946:76;:::i;:::-;28076:2;28055:15;-1:-1:-1;;28051:29:39;28042:39;;;;28083:4;28038:50;;27824:270;-1:-1:-1;;27824:270:39:o;28099:885::-;28318:2;28307:9;28300:21;28376:10;28367:6;28361:13;28357:30;28352:2;28341:9;28337:18;28330:58;28442:4;28434:6;28430:17;28424:24;28419:2;28408:9;28404:18;28397:52;28281:4;28496:2;28488:6;28484:15;28478:22;28537:4;28531:3;28520:9;28516:19;28509:33;28565:51;28611:3;28600:9;28596:19;28582:12;28565:51;:::i;:::-;28551:65;;28665:2;28657:6;28653:15;28647:22;28739:2;28735:7;28723:9;28715:6;28711:22;28707:36;28700:4;28689:9;28685:20;28678:66;28767:40;28800:6;28784:14;28767:40;:::i;:::-;28876:3;28864:16;;;;28858:23;28851:31;28844:39;28838:3;28823:19;;28816:68;-1:-1:-1;;;;;;;;28945:32:39;;;;28938:4;28923:20;;;28916:62;28753:54;28099:885::o;28989:575::-;29059:5;29107:4;29095:9;29090:3;29086:19;29082:30;29079:50;;;29125:1;29122;29115:12;29079:50;29158:4;29152:11;29202:4;29194:6;29190:17;29273:6;29261:10;29258:22;-1:-1:-1;;;;;29225:10:39;29222:34;29219:62;29216:185;;;29323:10;29318:3;29314:20;29311:1;29304:31;29358:4;29355:1;29348:15;29386:4;29383:1;29376:15;29216:185;29417:4;29410:24;29482:16;;29467:32;;29553:2;29538:18;;;29532:25;29515:15;;;29508:50;;;;-1:-1:-1;29452:6:39;28989:575;-1:-1:-1;28989:575:39:o;29569:258::-;29668:6;29721:2;29709:9;29700:7;29696:23;29692:32;29689:52;;;29737:1;29734;29727:12;29689:52;29760:61;29813:7;29802:9;29760:61;:::i;29832:779::-;29935:6;29988:3;29976:9;29967:7;29963:23;29959:33;29956:53;;;30005:1;30002;29995:12;29956:53;30038:2;30032:9;30080:4;30072:6;30068:17;30151:6;30139:10;30136:22;-1:-1:-1;;;;;30103:10:39;30100:34;30097:62;30094:185;;;30201:10;30196:3;30192:20;30189:1;30182:31;30236:4;30233:1;30226:15;30264:4;30261:1;30254:15;30094:185;30295:2;30288:22;30334:16;;30319:32;;30394:2;30379:18;;30373:25;30407:30;30373:25;30407:30;:::i;:::-;30465:2;30453:15;;30446:30;30509:70;30571:7;30566:2;30551:18;;30509:70;:::i;:::-;30504:2;30492:15;;30485:95;30496:6;29832:779;-1:-1:-1;;;29832:779:39:o;31556:168::-;31623:6;31649:10;;;31661;;;31645:27;;31684:11;;;31681:37;;;31698:18;;:::i;31729:790::-;31978:3;32016:6;32010:13;32032:66;32091:6;32086:3;32079:4;32071:6;32067:17;32032:66;:::i;:::-;-1:-1:-1;;;;;;32159:3:39;32195:16;;;32191:25;;32120:16;;;32177:40;;;-1:-1:-1;;;;;;32274:3:39;32252:16;;;32248:38;32244:1;32233:13;;32226:61;32322:16;;;32318:25;32314:1;32303:13;;32296:48;32369:13;;32391:78;32369:13;32456:1;32445:13;;32438:4;32426:17;;32391:78;:::i;:::-;32489:20;32511:1;32485:28;;31729:790;-1:-1:-1;;;;;;;31729:790:39:o;32524:251::-;32594:6;32647:2;32635:9;32626:7;32622:23;32618:32;32615:52;;;32663:1;32660;32653:12;32615:52;32695:9;32689:16;32714:31;32739:5;32714:31;:::i
Swarm Source
ipfs://cb71701720759819c3db6acbf1de0eac330b5b6a96d2a7821d79070002a95ccd
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.