Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00| Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 5432796 | 130 days ago | Contract Creation | 0 ETH |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
LayerZeroTeller
Compiler Version
v0.8.21+commit.d9974bed
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: 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 { 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: 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);
}
}// 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;
}
/**
* @param denyFrom bool indicating whether or not the user is on the deny from list.
* @param denyTo bool indicating whether or not the user is on the deny to list.
* @param denyOperator bool indicating whether or not the user is on the deny operator list.
* @param permissionedOperator bool indicating whether or not the user is a permissioned operator, only applies when permissionedTransfers is true.
* @param shareUnlockTime uint256 indicating the time at which the shares will be unlocked.
*/
struct BeforeTransferData {
bool denyFrom;
bool denyTo;
bool denyOperator;
bool permissionedOperator;
uint256 shareUnlockTime;
}
// ========================================= 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 = 1_000;
// ========================================= STATE =========================================
/**
* @notice Mapping ERC20s to their assetData.
*/
mapping(ERC20 => Asset) public assetData;
/**
* @notice The deposit nonce used to map to a deposit hash.
*/
uint64 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;
/**
* @notice If true, only permissioned operators can transfer shares.
*/
bool public permissionedTransfers;
/**
* @notice The global deposit cap of the vault.
* @dev If the cap is reached, no new deposits are accepted. No partial fills.
*/
uint112 public depositCap = type(uint112).max;
/**
* @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 address to BeforeTransferData struct to check if shares are locked and if the address is on any allow or deny list.
*/
mapping(address => BeforeTransferData) public beforeTransferData;
//============================== 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();
error TellerWithMultiAssetSupport__DepositExceedsCap();
//============================== 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);
event PermissionedTransfersSet(bool permissionedTransfers);
event AllowPermissionedOperator(address indexed operator);
event DenyPermissionedOperator(address indexed operator);
event DepositCapSet(uint112 cap);
// =============================== 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));
permissionedTransfers = false;
}
// ========================================= 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 {
beforeTransferData[user].denyFrom = true;
beforeTransferData[user].denyTo = true;
beforeTransferData[user].denyOperator = 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 {
beforeTransferData[user].denyFrom = false;
beforeTransferData[user].denyTo = false;
beforeTransferData[user].denyOperator = 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 {
beforeTransferData[user].denyFrom = 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 {
beforeTransferData[user].denyFrom = 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 {
beforeTransferData[user].denyTo = 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 {
beforeTransferData[user].denyTo = 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 {
beforeTransferData[user].denyOperator = 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 {
beforeTransferData[user].denyOperator = false;
emit AllowOperator(user);
}
/**
* @notice Set the permissioned transfers flag.
* @dev Callable by OWNER_ROLE.
*/
function setPermissionedTransfers(bool _permissionedTransfers) external requiresAuth {
permissionedTransfers = _permissionedTransfers;
emit PermissionedTransfersSet(_permissionedTransfers);
}
/**
* @notice Give permission to an operator to transfer shares when permissioned transfers flag is true.
* @dev Callable by OWNER_ROLE.
*/
function allowPermissionedOperator(address operator) external requiresAuth {
beforeTransferData[operator].permissionedOperator = true;
emit AllowPermissionedOperator(operator);
}
/**
* @notice Revoke permission from an operator to transfer shares when permissioned transfers flag is true.
* @dev Callable by OWNER_ROLE, and DENIER_.
*/
function denyPermissionedOperator(address operator) external requiresAuth {
beforeTransferData[operator].permissionedOperator = false;
emit DenyPermissionedOperator(operator);
}
/**
* @notice Set the deposit cap of the vault.
* @dev Callable by OWNER_ROLE
*/
function setDepositCap(uint112 cap) external requiresAuth {
depositCap = cap;
emit DepositCapSet(cap);
}
// ========================================= BeforeTransferHook FUNCTIONS =========================================
/**
* @notice Implement beforeTransfer hook to check if shares are locked, or if `from`, `to`, or `operator` are denied in beforeTransferData.
* @notice If permissionedTransfers is true, then only operators on the allow list can transfer shares.
* @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 (
beforeTransferData[from].denyFrom || beforeTransferData[to].denyTo
|| beforeTransferData[operator].denyOperator
|| (permissionedTransfers && !beforeTransferData[operator].permissionedOperator)
) {
revert TellerWithMultiAssetSupport__TransferDenied(from, to, operator);
}
if (beforeTransferData[from].shareUnlockTime > block.timestamp) {
revert TellerWithMultiAssetSupport__SharesAreLocked();
}
}
/**
* @notice Implement legacy beforeTransfer hook to check if shares are locked, or if `from`is on the deny list.
*/
function beforeTransfer(address from) public view virtual {
if (beforeTransferData[from].denyFrom) {
revert TellerWithMultiAssetSupport__TransferDenied(from, address(0), address(0));
}
if (beforeTransferData[from].shareUnlockTime > 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) {
uint112 cap = depositCap;
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();
if (cap != type(uint112).max) {
if (shares + vault.totalSupply() > cap) revert TellerWithMultiAssetSupport__DepositExceedsCap();
}
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) {
beforeTransferData[user].shareUnlockTime = 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: 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: UNLICENSED
pragma solidity 0.8.21;
interface BeforeTransferHook {
function beforeTransfer(address from, address to, address operator) external view;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.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 ERC1155 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 {
/**
* @dev See {IERC165-supportsInterface}.
*/
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
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: 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: 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
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* 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[EIP 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: 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;
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 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
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: 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: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721Receiver.sol)
pragma solidity ^0.8.20;
/**
* @title ERC721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC721 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: 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 {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: 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: 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: MIT
// OpenZeppelin Contracts (last updated v5.0.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 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);
}
}// 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: UNLICENSED
pragma solidity 0.8.21;
interface IPausable {
function pause() external;
function unpause() external;
}// 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: 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: 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.
/// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller.
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.
success := and(
// 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.
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
// 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.
// Counterintuitively, this call must be positioned second to the or() call in the
// surrounding and() call or else returndatasize() will be zero during the computation.
call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)
)
}
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.
success := and(
// 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.
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
// 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.
// Counterintuitively, this call must be positioned second to the or() call in the
// surrounding and() call or else returndatasize() will be zero during the computation.
call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
)
}
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.
success := and(
// 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.
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
// 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.
// Counterintuitively, this call must be positioned second to the or() call in the
// surrounding and() call or else returndatasize() will be zero during the computation.
call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
)
}
require(success, "APPROVE_FAILED");
}
}// 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: 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
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;
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.0.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 ERC165 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 {
/**
* @dev See {IERC165-supportsInterface}.
*/
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 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: 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: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)
pragma solidity ^0.8.20;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev The ETH balance of the account is not enough to perform the operation.
*/
error AddressInsufficientBalance(address account);
/**
* @dev There's no code at `target` (it is not a contract).
*/
error AddressEmptyCode(address target);
/**
* @dev A call to an address target failed. The target may have reverted.
*/
error FailedInnerCall();
/**
* @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 AddressInsufficientBalance(address(this));
}
(bool success, ) = recipient.call{value: amount}("");
if (!success) {
revert FailedInnerCall();
}
}
/**
* @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
* {FailedInnerCall} 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 AddressInsufficientBalance(address(this));
}
(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 {FailedInnerCall}) 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 {FailedInnerCall} 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 {FailedInnerCall}.
*/
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
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert FailedInnerCall();
}
}
}// 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
// OpenZeppelin Contracts (last updated v5.0.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 ERC1155 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 ERC1155 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);
}{
"evmVersion": "shanghai",
"metadata": {
"appendCBOR": true,
"bytecodeHash": "ipfs",
"useLiteralContent": false
},
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"abi"
]
}
},
"remappings": [
"@solmate/=lib/solmate/src/",
"@forge-std/=lib/forge-std/src/",
"@ds-test/=lib/forge-std/lib/ds-test/src/",
"ds-test/=lib/forge-std/lib/ds-test/src/",
"@openzeppelin/=lib/openzeppelin-contracts/",
"@ccip/=lib/ccip/",
"@oapp-auth/=lib/OAppAuth/src/",
"@devtools-oapp-evm/=lib/OAppAuth/lib/devtools/packages/oapp-evm/contracts/oapp/",
"@layerzerolabs/lz-evm-messagelib-v2/=lib/OAppAuth/node_modules/@layerzerolabs/lz-evm-messagelib-v2/",
"@layerzerolabs/lz-evm-protocol-v2/=lib/OAppAuth/lib/LayerZero-V2/packages/layerzero-v2/evm/protocol/",
"@layerzerolabs/oapp-evm/=lib/OAppAuth/lib/devtools/packages/oapp-evm/",
"@lz-oapp-evm/=lib/OAppAuth/lib/LayerZero-V2/packages/layerzero-v2/evm/oapp/contracts/oapp/",
"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
"@sbu/=lib/OAppAuth/lib/solidity-bytes-utils/",
"LayerZero-V2/=lib/OAppAuth/lib/",
"OAppAuth/=lib/OAppAuth/",
"ccip/=lib/ccip/contracts/",
"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
"forge-std/=lib/forge-std/src/",
"halmos-cheatcodes/=lib/OAppAuth/lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/",
"solidity-bytes-utils/=lib/OAppAuth/node_modules/solidity-bytes-utils/",
"solmate/=lib/solmate/src/"
],
"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__DepositExceedsCap","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":"operator","type":"address"}],"name":"AllowPermissionedOperator","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":"operator","type":"address"}],"name":"DenyPermissionedOperator","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":false,"internalType":"uint112","name":"cap","type":"uint112"}],"name":"DepositCapSet","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":[{"indexed":false,"internalType":"bool","name":"permissionedTransfers","type":"bool"}],"name":"PermissionedTransfersSet","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":"operator","type":"address"}],"name":"allowPermissionedOperator","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":"address","name":"from","type":"address"}],"name":"beforeTransfer","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"beforeTransferData","outputs":[{"internalType":"bool","name":"denyFrom","type":"bool"},{"internalType":"bool","name":"denyTo","type":"bool"},{"internalType":"bool","name":"denyOperator","type":"bool"},{"internalType":"bool","name":"permissionedOperator","type":"bool"},{"internalType":"uint256","name":"shareUnlockTime","type":"uint256"}],"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":"operator","type":"address"}],"name":"denyPermissionedOperator","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":"depositCap","outputs":[{"internalType":"uint112","name":"","type":"uint112"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"depositNonce","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"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":"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":[],"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":[],"name":"permissionedTransfers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":"uint112","name":"cap","type":"uint112"}],"name":"setDepositCap","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":"bool","name":"_permissionedTransfers","type":"bool"}],"name":"setPermissionedTransfers","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":"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":"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
6101406040526001600255600480546001600160901b03166001600160901b03191790553480156200002f575f80fd5b506040516200505f3803806200505f83398101604081905262000052916200025d565b5f80546001600160a01b0389166001600160a01b0319918216811783556001805490921690915560405185928592849284928d928d928d928d9286928692869286928692919033907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908490a36040516001600160a01b0382169033907fa3396fd7f6e0a21b50e5089d2da70d5ac0a3bbbd1f617a93f134b76389980198905f90a350506001600160a01b03831660808190526040805163313ce56760e01b8152905163313ce567916004808201926020929091908290030181865afa1580156200013f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620001659190620002ed565b6200017290600a62000425565b60c0526001600160a01b0391821660a052811660e0526004805460ff60881b191690558881166101005287169550620001c494505050505057604051632d618d8160e21b815260040160405180910390fd5b6101005160405163ca5eb5e160e01b81526001600160a01b0383811660048301529091169063ca5eb5e1906024015f604051808303815f87803b1580156200020a575f80fd5b505af11580156200021d573d5f803e3d5ffd5b5050506001600160a01b039095166101205250620004359950505050505050505050565b80516001600160a01b038116811462000258575f80fd5b919050565b5f805f805f805f60e0888a03121562000274575f80fd5b6200027f8862000241565b96506200028f6020890162000241565b95506200029f6040890162000241565b9450620002af6060890162000241565b9350620002bf6080890162000241565b9250620002cf60a0890162000241565b9150620002df60c0890162000241565b905092959891949750929550565b5f60208284031215620002fe575f80fd5b815160ff811681146200030f575f80fd5b9392505050565b634e487b7160e01b5f52601160045260245ffd5b600181815b808511156200036a57815f19048211156200034e576200034e62000316565b808516156200035c57918102915b93841c93908002906200032f565b509250929050565b5f8262000382575060016200041f565b816200039057505f6200041f565b8160018114620003a95760028114620003b457620003d4565b60019150506200041f565b60ff841115620003c857620003c862000316565b50506001821b6200041f565b5060208310610133831016604e8410600b8410161715620003f9575081810a6200041f565b6200040583836200032a565b805f19048211156200041b576200041b62000316565b0290505b92915050565b5f6200030f60ff84168362000372565b60805160a05160c05160e0516101005161012051614b416200051e5f395f818161359201526138a901525f818161077c01528181610f68015281816127f801528181613abf01528181613bb901528181613df60152613ead01525f81816103db01528181610d7901528181610df601528181610e440152611b9f01525f81816118820152612ef701525f81816106a5015281816118130152612f1901525f8181610be601528181610e1a015281816118e001528181611bd901528181612c6b01528181613003015281816130c1015281816133ca0152818161346a015261398c0152614b415ff3fe60806040526004361061037c575f3560e01c80637d25a05e116101d3578063bb0b6a53116100fd578063d555f3681161009d578063e83931af1161006d578063e83931af14610b97578063f2fde38b14610bb6578063fbfa77cf14610bd5578063ff7bd03d14610c08575f80fd5b8063d555f36814610afc578063d7424e3314610b1b578063dbd5edc714610b3a578063de35f5cb14610b78575f80fd5b8063c29d2f10116100d8578063c29d2f1014610a3c578063ca5eb5e114610a5b578063cab716e814610a7a578063d182221614610a8d575f80fd5b8063bb0b6a53146109d3578063bf671384146109fe578063bf7e214f14610a1d575f80fd5b80639ac4f42d11610173578063abd626b011610143578063abd626b014610963578063b187bd2614610982578063b5ba6182146109a2578063b92d0eff146109c1575f80fd5b80639ac4f42d146108e05780639d574420146108ff5780639fdb11b61461091e578063a924bf6114610944575f80fd5b80638da5cb5b116101ae5780638da5cb5b146108655780638dfd8ba11461088357806394f51289146108a25780639a94d3d0146108b5575f80fd5b80637d25a05e146107fb5780638456cb59146108325780638a6733f914610846575f80fd5b806334dafd6b116102b457806346b563f4116102545780635e280f11116102245780635e280f111461076b5780635f45bac81461079e5780637a9e5e4b146107bd5780637bd876b6146107dc575f80fd5b806346b563f4146106755780634fb3ccc51461069457806355a2d64d146106c75780635c465430146106e6575f80fd5b80633e64ce991161028f5780633e64ce99146105be5780633f4ba83a146105dd57806341fee44a146105f157806345ad606314610656575f80fd5b806334dafd6b146105615780633b575407146105805780633d935d9e1461059f575f80fd5b806317442b701161031f5780631ba9a458116102fa5780631ba9a458146104e5578063202eac57146105045780632c524c42146105235780633400288b14610542575f80fd5b806317442b701461048757806318aed921146104a75780631b62636c146104c6575f80fd5b80630efe6a8b1161035a5780630efe6a8b1461041557806312056e2d1461043657806313137d65146104555780631568fc5814610468575f80fd5b80630511ef431461038057806305921740146103b55780630b48a8b8146103ca575b5f80fd5b34801561038b575f80fd5b506004546103a090600160881b900460ff1681565b60405190151581526020015b60405180910390f35b6103c86103c336600461404d565b610c27565b005b3480156103d5575f80fd5b506103fd7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016103ac565b6104286104233660046140ca565b610ccd565b6040519081526020016103ac565b348015610441575f80fd5b506103c8610450366004614110565b610ed6565b6103c8610463366004614141565b610f66565b348015610473575f80fd5b506103c8610482366004614202565b611021565b348015610492575f80fd5b506040805160018082526020820152016103ac565b3480156104b2575f80fd5b506103c86104c1366004614233565b6110f6565b3480156104d1575f80fd5b506103c86104e0366004614233565b6111dc565b3480156104f0575f80fd5b506103c86104ff366004614233565b61125c565b34801561050f575f80fd5b506103c861051e36600461424e565b6112d7565b34801561052e575f80fd5b506103c861053d366004614233565b61137e565b34801561054d575f80fd5b506103c861055c366004614283565b6113fa565b34801561056c575f80fd5b506103c861057b3660046142b8565b611439565b34801561058b575f80fd5b506103c861059a366004614233565b61158d565b3480156105aa575f80fd5b506104286105b936600461432f565b61160b565b3480156105c9575f80fd5b506104286105d836600461438f565b611709565b3480156105e8575f80fd5b506103c8611996565b3480156105fc575f80fd5b5061063561060b366004614233565b60036020525f908152604090205460ff8082169161010081049091169062010000900461ffff1683565b604080519315158452911515602084015261ffff16908201526060016103ac565b348015610661575f80fd5b506103c86106703660046143d6565b6119fe565b348015610680575f80fd5b506103c861068f3660046143ef565b611a87565b34801561069f575f80fd5b506103fd7f000000000000000000000000000000000000000000000000000000000000000081565b3480156106d2575f80fd5b506103c86106e13660046143d6565b611c91565b3480156106f1575f80fd5b5061073b610700366004614233565b60066020525f90815260409020805460019091015460ff80831692610100810482169262010000820483169263010000009092049091169085565b6040805195151586529315156020860152911515928401929092529015156060830152608082015260a0016103ac565b348015610776575f80fd5b506103fd7f000000000000000000000000000000000000000000000000000000000000000081565b3480156107a9575f80fd5b506103c86107b8366004614233565b611d37565b3480156107c8575f80fd5b506103c86107d7366004614233565b611db1565b3480156107e7575f80fd5b506103c86107f636600461444f565b611e95565b348015610806575f80fd5b5061081a610815366004614283565b611f27565b6040516001600160401b0390911681526020016103ac565b34801561083d575f80fd5b506103c8611f2f565b348015610851575f80fd5b506103c8610860366004614475565b611f9d565b348015610870575f80fd5b505f546103fd906001600160a01b031681565b34801561088e575f80fd5b506103c861089d366004614490565b61201b565b6104286108b03660046144e4565b612134565b3480156108c0575f80fd5b506104286108cf3660046145a8565b60056020525f908152604090205481565b3480156108eb575f80fd5b506103c86108fa366004614233565b61226d565b34801561090a575f80fd5b5061042861091936600461438f565b6122ef565b348015610929575f80fd5b5060045461081a90600160401b90046001600160401b031681565b34801561094f575f80fd5b506103c861095e366004614233565b6123b4565b34801561096e575f80fd5b506103c861097d3660046145bf565b61242d565b34801561098d575f80fd5b506004546103a090600160801b900460ff1681565b3480156109ad575f80fd5b506103c86109bc366004614607565b61254e565b3480156109cc575f80fd5b50306103fd565b3480156109de575f80fd5b506104286109ed3660046143d6565b60076020525f908152604090205481565b348015610a09575f80fd5b506103c8610a18366004614233565b61264b565b348015610a28575f80fd5b506001546103fd906001600160a01b031681565b348015610a47575f80fd5b506103c8610a56366004614233565b6126c7565b348015610a66575f80fd5b506103c8610a75366004614233565b6127a8565b610428610a88366004614649565b612852565b348015610a98575f80fd5b50610ad6610aa73660046143d6565b60086020525f908152604090205460ff808216916101008104909116906201000090046001600160801b031683565b60408051931515845291151560208401526001600160801b0316908201526060016103ac565b348015610b07575f80fd5b506103c8610b163660046143d6565b612979565b348015610b26575f80fd5b50610428610b353660046146db565b6129f9565b348015610b45575f80fd5b50600454610b6090600160901b90046001600160701b031681565b6040516001600160701b0390911681526020016103ac565b348015610b83575f80fd5b5060045461081a906001600160401b031681565b348015610ba2575f80fd5b506103c8610bb1366004614233565b612a44565b348015610bc1575f80fd5b506103c8610bd0366004614233565b612ad3565b348015610be0575f80fd5b506103fd7f000000000000000000000000000000000000000000000000000000000000000081565b348015610c13575f80fd5b506103a0610c22366004614750565b612b4e565b610c3c335f356001600160e01b031916612b82565b610c615760405162461bcd60e51b8152600401610c589061476a565b60405180910390fd5b600254600114610c835760405162461bcd60e51b8152600401610c5890614790565b60028055600454600160801b900460ff1615610cb25760405163e0f9e71d60e01b815260040160405180910390fd5b610cc0868686868686612c28565b5050600160025550505050565b5f610ce3335f356001600160e01b031916612b82565b610cff5760405162461bcd60e51b8152600401610c589061476a565b600254600114610d215760405162461bcd60e51b8152600401610c5890614790565b600280555f610d2f85612d62565b90505f73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03871601610e6b57345f03610d775760405163259be69560e11b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004015f604051808303818588803b158015610dd0575f80fd5b505af1158015610de2573d5f803e3d5ffd5b50349850610e419350506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691507f0000000000000000000000000000000000000000000000000000000000000000905087612e1d565b507f0000000000000000000000000000000000000000000000000000000000000000945030610e8d565b3415610e8a57604051631cf02cf960e21b815260040160405180910390fd5b50335b610e9b868686843387612e9f565b9250610ec833878786600460089054906101000a90046001600160401b03166001600160401b0316613136565b505060016002559392505050565b610eeb335f356001600160e01b031916612b82565b610f075760405162461bcd60e51b8152600401610c589061476a565b6203f480816001600160401b03161115610f3457604051631fac010160e21b815260040160405180910390fd5b600480546001600160401b03909216600160401b026fffffffffffffffff000000000000000019909216919091179055565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163314610fb1576040516391ac5e4f60e01b8152336004820152602401610c58565b60208701803590610fcb90610fc6908a6143d6565b613268565b1461100957610fdd60208801886143d6565b60405163309afaf360e21b815263ffffffff909116600482015260208801356024820152604401610c58565b611018878787878787876132a3565b50505050505050565b611036335f356001600160e01b031916612b82565b6110525760405162461bcd60e51b8152600401610c589061476a565b806001600160801b03165f0361107b5760405163c80ed59560e01b815260040160405180910390fd5b63ffffffff82165f81815260086020908152604091829020805462010000600160901b031916620100006001600160801b038716908102919091178255835194855291840191909152917f0aa48359f83e8464fda3f4ea4bd3f2d6af01e90b46ab9464aa7d538e1772947a91015b60405180910390a1505050565b61110b335f356001600160e01b031916612b82565b6111275760405162461bcd60e51b8152600401610c589061476a565b6001600160a01b0381165f81815260066020526040808220805462ffffff191662010101179055517fd658022b1a3aaf6ad3b3c615253712807f21a8f7bc3e4996e10618175d4afb2b9190a26040516001600160a01b038216907f79fc685a7dbabb75a67df5e69a90602cef1f19bc465b060eab1ac56685e04a13905f90a26040516001600160a01b038216907f3afb02134e37f7205acf470adc2fc4ebb70614b1599a602d069790915380e2aa905f90a250565b6111f1335f356001600160e01b031916612b82565b61120d5760405162461bcd60e51b8152600401610c589061476a565b6001600160a01b0381165f81815260066020526040808220805462ff0000191662010000179055517f3afb02134e37f7205acf470adc2fc4ebb70614b1599a602d069790915380e2aa9190a250565b611271335f356001600160e01b031916612b82565b61128d5760405162461bcd60e51b8152600401610c589061476a565b6001600160a01b0381165f81815260066020526040808220805462ff000019169055517f77cb944c14da76928795279d1519ce9150085a06e0a53c61d5a86fc4e0fd57c69190a250565b6112ec335f356001600160e01b031916612b82565b6113085760405162461bcd60e51b8152600401610c589061476a565b63ffffffff82165f908152600860205260409020805460ff1916600117815561133a836001600160a01b038416613360565b6040805163ffffffff851681526001600160a01b03841660208201527fe925de263dcdbdc20307c9ab92758ed8cc0edf3d173dad4a3aa54c070f27a54391016110e9565b611393335f356001600160e01b031916612b82565b6113af5760405162461bcd60e51b8152600401610c589061476a565b6001600160a01b0381165f81815260066020526040808220805460ff19166001179055517fd658022b1a3aaf6ad3b3c615253712807f21a8f7bc3e4996e10618175d4afb2b9190a250565b61140f335f356001600160e01b031916612b82565b61142b5760405162461bcd60e51b8152600401610c589061476a565b6114358282613360565b5050565b61144e335f356001600160e01b031916612b82565b61146a5760405162461bcd60e51b8152600401610c589061476a565b82801561147e57506001600160801b038116155b1561149c5760405163c80ed59560e01b815260040160405180910390fd5b60408051606081018252851515815284151560208083019182526001600160801b0385811684860190815263ffffffff8b165f908152600890935294909120925183549251945161ffff1990931690151561ff00191617610100941515949094029390931762010000600160901b03191662010000919093160291909117905561152f856001600160a01b038416613360565b6040805163ffffffff871681528515156020820152841515818301526001600160a01b038416606082015290517f5dbe727bffd24a6d61a5aeef919510389c66c0deeaa82634862cf4f098961fb89181900360800190a15050505050565b6115a2335f356001600160e01b031916612b82565b6115be5760405162461bcd60e51b8152600401610c589061476a565b6001600160a01b0381165f81815260066020526040808220805461ff001916610100179055517f79fc685a7dbabb75a67df5e69a90602cef1f19bc465b060eab1ac56685e04a139190a250565b5f611621335f356001600160e01b031916612b82565b61163d5760405162461bcd60e51b8152600401610c589061476a565b60025460011461165f5760405162461bcd60e51b8152600401610c5890614790565b600280558773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b038216016116a2576040516316df5df960e31b815260040160405180910390fd5b5f6116ac8a612d62565b90506116bc8a8a898989896133ad565b6116ca8a8a8a333386612e9f565b92506116f7338b8b86600460089054906101000a90046001600160401b03166001600160401b0316613136565b50506001600255979650505050505050565b5f61171f335f356001600160e01b031916612b82565b61173b5760405162461bcd60e51b8152600401610c589061476a565b600454600160801b900460ff16156117665760405163e0f9e71d60e01b815260040160405180910390fd5b6001600160a01b0385165f908152600360209081526040918290208251606081018452905460ff80821615158352610100820416151592820183905262010000900461ffff16928101929092526117d05760405163645fd19f60e11b815260040160405180910390fd5b845f036117f057604051630ea3153160e21b815260040160405180910390fd5b604051634104b9ed60e11b81526001600160a01b0387811660048301526118a6917f00000000000000000000000000000000000000000000000000000000000000009091169063820973da90602401602060405180830381865afa15801561185a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061187e91906147b4565b86907f0000000000000000000000000000000000000000000000000000000000000000613505565b9150838210156118c9576040516302620f6160e61b815260040160405180910390fd5b6040516318457e6160e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906318457e619061191d9086908a90879033908c906004016147cb565b5f604051808303815f87803b158015611934575f80fd5b505af1158015611946573d5f803e3d5ffd5b50505050856001600160a01b03167fdcc60b41ff1c604459e6aa4a7299817416b19fc586a392f111646e26597c4af98660405161198591815260200190565b60405180910390a250949350505050565b6119ab335f356001600160e01b031916612b82565b6119c75760405162461bcd60e51b8152600401610c589061476a565b6004805460ff60801b191690556040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d16933905f90a1565b611a13335f356001600160e01b031916612b82565b611a2f5760405162461bcd60e51b8152600401610c589061476a565b63ffffffff81165f81815260086020908152604091829020805461ff0019168155915192835290917fc45af64a13a09ef916a1114c59589294ec9c3095f2bfbbb093a7a96656858ded91015b60405180910390a15050565b611a9c335f356001600160e01b031916612b82565b611ab85760405162461bcd60e51b8152600401610c589061476a565b80611ac38342614812565b10611ae157604051634c1eef1760e11b815260040160405180910390fd5b604080516001600160a01b038089166020830152871691810191909152606081018590526080810184905260a0810183905260c081018290525f9060e00160408051601f1981840301815291815281516020928301205f8b815260059093529120549091508114611b655760405163fa174ecb60e01b815260040160405180910390fd5b5f888152600560205260408120556001600160a01b03861673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611b9d5785611bbf565b7f00000000000000000000000000000000000000000000000000000000000000005b6040516318457e6160e01b81529096506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906318457e6190611c16908a908a908a9083908b906004016147cb565b5f604051808303815f87803b158015611c2d575f80fd5b505af1158015611c3f573d5f803e3d5ffd5b50505050866001600160a01b0316887faf98ea774275cadfa3e477a7b52cba03e01197445a76bd5d0d561608708c362483604051611c7f91815260200190565b60405180910390a35050505050505050565b611ca6335f356001600160e01b031916612b82565b611cc25760405162461bcd60e51b8152600401610c589061476a565b63ffffffff81165f908152600860205260408120805471ffffffffffffffffffffffffffffffffffff19169055611cfa908290613360565b60405163ffffffff821681527f11a9d1a77f76361ed131c19b1dc5758504c51dbde2e49fc973a0ef9577ad13d5906020015b60405180910390a150565b611d4c335f356001600160e01b031916612b82565b611d685760405162461bcd60e51b8152600401610c589061476a565b6001600160a01b0381165f81815260066020526040808220805461ff0019169055517f039bcf51833310242b8b7c6aa0fbabf1bf2b5e5270807ee020f1920ef200666b9190a250565b5f546001600160a01b0316331480611e42575060015460405163b700961360e01b81526001600160a01b039091169063b700961390611e0390339030906001600160e01b03195f351690600401614825565b602060405180830381865afa158015611e1e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e429190614852565b611e4a575f80fd5b600180546001600160a01b0319166001600160a01b03831690811790915560405133907fa3396fd7f6e0a21b50e5089d2da70d5ac0a3bbbd1f617a93f134b76389980198905f90a350565b611eaa335f356001600160e01b031916612b82565b611ec65760405162461bcd60e51b8152600401610c589061476a565b6004805471ffffffffffffffffffffffffffffffffffff16600160901b6001600160701b038416908102919091179091556040519081527f752cd3d8df6864142257fa3a2e02aedf2dc09f1875c2a25b4f117d45c7334d5d90602001611d2c565b5f5b92915050565b611f44335f356001600160e01b031916612b82565b611f605760405162461bcd60e51b8152600401610c589061476a565b6004805460ff60801b1916600160801b1790556040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e752905f90a1565b611fb2335f356001600160e01b031916612b82565b611fce5760405162461bcd60e51b8152600401610c589061476a565b60048054821515600160881b0260ff60881b199091161790556040517fa3fe47e2502292ca20854524008d366d3cad5da2426cfb2484099f06f328e4a090611d2c90831515815260200190565b612030335f356001600160e01b031916612b82565b61204c5760405162461bcd60e51b8152600401610c589061476a565b6103e861ffff8216111561207357604051636c5cde8760e01b815260040160405180910390fd5b6040805160608082018352851515808352851515602080850182815261ffff8881168789018181526001600160a01b038e165f818152600387528b902099518a549551925161ffff1990961690151561ff00191617610100921515929092029190911763ffff0000191662010000949093169390930291909117909655865193845290830191909152938101929092527fe08301321781ac43935a2099b2c3fd42de0a0ee87a519cac00e8c9cecd26ff12910160405180910390a250505050565b5f61214a335f356001600160e01b031916612b82565b6121665760405162461bcd60e51b8152600401610c589061476a565b6002546001146121885760405162461bcd60e51b8152600401610c5890614790565b600280558c73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b038216016121cb576040516316df5df960e31b815260040160405180910390fd5b5f6121d58f612d62565b90506121e58f8f8e8e8e8e6133ad565b6121f38f8f8f333386612e9f565b925050612221338f8f85600460089054906101000a90046001600160401b03166001600160401b0316613136565b6001600160601b03821115612249576040516389588ab360e01b815260040160405180910390fd5b612257828888888888612c28565b5060016002559c9b505050505050505050505050565b612282335f356001600160e01b031916612b82565b61229e5760405162461bcd60e51b8152600401610c589061476a565b6001600160a01b0381165f81815260066020526040808220805463ff00000019166301000000179055517f5e92c085dffcb69d025c31c9ed03d1869e4737ba81e8649c623398caa1b72f159190a250565b5f612305335f356001600160e01b031916612b82565b6123215760405162461bcd60e51b8152600401610c589061476a565b6002546001146123435760405162461bcd60e51b8152600401610c5890614790565b600280555f61235186612d62565b9050612361868686338786612e9f565b9150856001600160a01b03167f6f9b974223f85a1ae805c33b8b519039e2435481d949db1110de151a94d587af8660405161239e91815260200190565b60405180910390a2506001600255949350505050565b6123c9335f356001600160e01b031916612b82565b6123e55760405162461bcd60e51b8152600401610c589061476a565b6001600160a01b0381165f81815260066020526040808220805460ff19169055517fae893dda71e2eee548f8291f458cceae4bd22b56a79906928591e4420444c0e99190a250565b6001600160a01b0383165f9081526006602052604090205460ff168061246f57506001600160a01b0382165f90815260066020526040902054610100900460ff165b8061249757506001600160a01b0381165f9081526006602052604090205462010000900460ff165b806124d55750600454600160881b900460ff1680156124d557506001600160a01b0381165f908152600660205260409020546301000000900460ff16155b1561250e57604051632821264f60e01b81526001600160a01b038085166004830152808416602483015282166044820152606401610c58565b6001600160a01b0383165f908152600660205260409020600101544210156125495760405163f64059db60e01b815260040160405180910390fd5b505050565b612563335f356001600160e01b031916612b82565b61257f5760405162461bcd60e51b8152600401610c589061476a565b806001600160801b03165f036125a85760405163c80ed59560e01b815260040160405180910390fd5b63ffffffff83165f908152600860205260409020805461010071ffffffffffffffffffffffffffffffffff0019909116620100006001600160801b03851602171781556125fe846001600160a01b038516613360565b6040805163ffffffff861681526001600160a01b03851660208201527f34fe916485e02ec88e487b0e611e5c9bacabba9e3eaae7a900aa08be8197d419910160405180910390a150505050565b612660335f356001600160e01b031916612b82565b61267c5760405162461bcd60e51b8152600401610c589061476a565b6001600160a01b0381165f81815260066020526040808220805463ff00000019169055517f1c2a701d65e1c6e2860263c884eae0b10db82e3ddd60640d53c7d53c6c998e799190a250565b6126dc335f356001600160e01b031916612b82565b6126f85760405162461bcd60e51b8152600401610c589061476a565b6001600160a01b0381165f81815260066020526040808220805462ffffff19169055517fae893dda71e2eee548f8291f458cceae4bd22b56a79906928591e4420444c0e99190a26040516001600160a01b038216907f039bcf51833310242b8b7c6aa0fbabf1bf2b5e5270807ee020f1920ef200666b905f90a26040516001600160a01b038216907f77cb944c14da76928795279d1519ce9150085a06e0a53c61d5a86fc4e0fd57c6905f90a250565b6127bd335f356001600160e01b031916612b82565b6127d95760405162461bcd60e51b8152600401610c589061476a565b60405163ca5eb5e160e01b81526001600160a01b0382811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063ca5eb5e1906024015f604051808303815f87803b158015612839575f80fd5b505af115801561284b573d5f803e3d5ffd5b5050505050565b5f612868335f356001600160e01b031916612b82565b6128845760405162461bcd60e51b8152600401610c589061476a565b6002546001146128a65760405162461bcd60e51b8152600401610c5890614790565b600280558873eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b038216016128e9576040516316df5df960e31b815260040160405180910390fd5b5f6128f38b612d62565b90506129038b8b8b333386612e9f565b9250612930338c8c86600460089054906101000a90046001600160401b03166001600160401b0316613136565b6001600160601b03831115612958576040516389588ab360e01b815260040160405180910390fd5b612966838989898989612c28565b5050600160025598975050505050505050565b61298e335f356001600160e01b031916612b82565b6129aa5760405162461bcd60e51b8152600401610c589061476a565b63ffffffff81165f81815260086020908152604091829020805460ff19168155915192835290917f1cb867ed6a020e020ea220d4f48bb8e36552abf9095e093e377d33933f2b31e49101611a7b565b604080518082019091526001600160601b03861681526001600160a01b03851660208201525f9081612a2a82613520565b9050612a3881878787613567565b98975050505050505050565b6001600160a01b0381165f9081526006602052604090205460ff1615612a9557604051632821264f60e01b81526001600160a01b03821660048201525f602482018190526044820152606401610c58565b6001600160a01b0381165f90815260066020526040902060010154421015612ad05760405163f64059db60e01b815260040160405180910390fd5b50565b612ae8335f356001600160e01b031916612b82565b612b045760405162461bcd60e51b8152600401610c589061476a565b5f80546001600160a01b0319166001600160a01b0383169081178255604051909133917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a350565b5f602082018035906007908390612b6590866143d6565b63ffffffff16815260208101919091526040015f20541492915050565b6001545f906001600160a01b03168015801590612c09575060405163b700961360e01b81526001600160a01b0382169063b700961390612bca90879030908890600401614825565b602060405180830381865afa158015612be5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612c099190614852565b80612c2057505f546001600160a01b038581169116145b949350505050565b612c33335f3361242d565b6040516318457e6160e01b81525f600482018190526024820181905260448201523360648201526001600160601b03871660848201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906318457e619060a4015f604051808303815f87803b158015612cb4575f80fd5b505af1158015612cc6573d5f803e3d5ffd5b5050604080518082019091526001600160601b03891681526001600160a01b038816602082015291505f9050612cfb82613520565b90505f612d0b8288888888613736565b6040516001600160601b038b1681529091506001600160a01b0389169082907fe0ec62d39b054dc2fd626dbc271483735df6e6fa1ef8389754bf8ab27a75eab29060200160405180910390a3505050505050505050565b604080516060810182525f8082526020820181905291810191909152600454600160801b900460ff1615612da95760405163e0f9e71d60e01b815260040160405180910390fd5b506001600160a01b0381165f908152600360209081526040918290208251606081018452905460ff8082161515808452610100830490911615159383019390935262010000900461ffff1692810192909252612e185760405163645fd19f60e11b815260040160405180910390fd5b919050565b5f60405163095ea7b360e01b81526001600160a01b038416600482015282602482015260205f6044835f895af13d15601f3d1160015f511416171691505080612e995760405162461bcd60e51b815260206004820152600e60248201526d1054141493d59157d1905253115160921b6044820152606401610c58565b50505050565b6004545f90600160901b90046001600160701b0316868203612ed45760405163259be69560e11b815260040160405180910390fd5b604051634104b9ed60e11b81526001600160a01b038981166004830152612f8a917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000169063820973da90602401602060405180830381865afa158015612f5e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612f8291906147b4565b899190613505565b91505f836040015161ffff1611612fa15781612fc4565b612fc48360400151612710612fb6919061486d565b839061ffff16612710613505565b915085821015612fe75760405163097b2ad560e31b815260040160405180910390fd5b6001600160701b03818116146130aa57806001600160701b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561305d573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061308191906147b4565b61308b908461488f565b11156130aa5760405163ed32f3bb60e01b815260040160405180910390fd5b604051631ceb5d1960e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906339d6ba32906130fe9088908c908c908a9089906004016147cb565b5f604051808303815f87803b158015613115575f80fd5b505af1158015613127573d5f803e3d5ffd5b50505050509695505050505050565b600480545f91908290613151906001600160401b03166148a2565b82546001600160401b039182166101009390930a8381029202191617909155905081156131f857613182824261488f565b6001600160a01b038781165f81815260066020908152604091829020600101949094558051938401919091529087169082015260608101859052608081018490524260a082015260c0810183905260e00160408051601f1981840301815291815281516020928301205f84815260059093529120555b846001600160a01b0316866001600160a01b0316827fe96d7872363f475d18b2f5390caaa5eaa96b2d38e42c62afe4ac08ebd2b13c3a87874288604051613258949392919093845260208401929092526040830152606082015260800190565b60405180910390a4505050505050565b63ffffffff81165f9081526007602052604081205480611f295760405163f6ff4fb760e01b815263ffffffff84166004820152602401610c58565b5f6008816132b460208b018b6143d6565b63ffffffff16815260208082019290925260409081015f208151606081018352905460ff808216151580845261010083049091161515948301949094526201000090046001600160801b031691810191909152915061333c5761331a60208901896143d6565b6040516315b73a2960e21b815263ffffffff9091166004820152602401610c58565b5f613349868801886145a8565b90506133558882613959565b505050505050505050565b63ffffffff82165f81815260076020908152604091829020849055815192835282018390527f238399d427b947898edb290f5ff0f9109849b1c3ba196a42e35f00c50a54b98b9101611a7b565b60405163d505accf60e01b81523360048201526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166024830152604482018790526064820186905260ff8516608483015260a4820184905260c4820183905287169063d505accf9060e4015f604051808303815f87803b158015613438575f80fd5b505af1925050508015613449575060015b6134fd57604051636eb1769f60e11b81523360048201526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116602483015286919088169063dd62ed3e90604401602060405180830381865afa1580156134ba573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906134de91906147b4565b10156134fd576040516301b8851f60e41b815260040160405180910390fd5b505050505050565b5f825f190484118302158202613519575f80fd5b5091020490565b80515f906001600160601b03101561354b57604051633524486360e01b815260040160405180910390fd5b81516020909201516001600160a01b031660a09290921b171790565b5f6001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee148015906135c757507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031614155b156135e557604051637f3cd08160e11b815260040160405180910390fd5b5f6135f2848601866143d6565b63ffffffff81165f908152600860209081526040918290208251606081018452905460ff8082161515835261010082041615159282018390526201000090046001600160801b0316928101929092529192509061366a5760405163420eae3760e01b815263ffffffff83166004820152602401610c58565b5f8760405160200161367e91815260200190565b60405160208183030381529060405290505f6136c683604001515f6136bf60408051600360f01b602082015281516002818303018152602290910190915290565b9190613a45565b90505f6136f58584846001600160a01b038b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613aaa565b90506001600160a01b03871673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14613725578060200151613728565b80515b9a9950505050505050505050565b5f80613744858701876143d6565b63ffffffff81165f908152600860209081526040918290208251606081018452905460ff8082161515835261010082041615159282018390526201000090046001600160801b031692810192909252919250906137bc5760405163420eae3760e01b815263ffffffff83166004820152602401610c58565b5f886040516020016137d091815260200190565b60405160208183030381529060405290505f61381183604001515f6136bf60408051600360f01b602082015281516002818303018152602290910190915290565b90505f6138408584846001600160a01b038c1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613aaa565b905073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b038916016138a75780518710156138a257805160405163f5ac3fa760e01b815263ffffffff87166004820152602481019190915260448101889052606401610c58565b61393a565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316886001600160a01b0316036139215786816020015111156138a257602081015160405163f5ac3fa760e01b815263ffffffff87166004820152602481019190915260448101889052606401610c58565b604051637f3cd08160e11b815260040160405180910390fd5b5f6139488685858533613b88565b519c9b505050505050505050505050565b60408051808201825260a083901c8082526001600160a01b03808516602084018190529351631ceb5d1960e11b815292937f0000000000000000000000000000000000000000000000000000000000000000909116926339d6ba32926139c8925f9283928392916004016147cb565b5f604051808303815f87803b1580156139df575f80fd5b505af11580156139f1573d5f803e3d5ffd5b5050505080602001516001600160a01b0316837fb944fddc61d7fedb8b736790454ba972000703b0d21c7481d6dbf95b7c2cc2f1835f0151604051613a3891815260200190565b60405180910390a3505050565b6060836003613a54825f613c8e565b61ffff1614613a8757613a67815f613c8e565b604051633a51740d60e01b815261ffff9091166004820152602401610c58565b5f613a928585613cea565b9050613aa086600183613d63565b9695505050505050565b604080518082019091525f80825260208201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ddc28c586040518060a001604052808863ffffffff168152602001613b0c89613268565b8152602001878152602001868152602001851515815250306040518363ffffffff1660e01b8152600401613b41929190614914565b6040805180830381865afa158015613b5b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613b7f91906149e4565b95945050505050565b613b90613f91565b5f613b9d845f0151613dcc565b602085015190915015613bb757613bb78460200151613df3565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632637a450826040518060a001604052808b63ffffffff168152602001613c078c613268565b81526020018a81526020018981526020015f8960200151111515815250866040518463ffffffff1660e01b8152600401613c42929190614914565b60806040518083038185885af1158015613c5e573d5f803e3d5ffd5b50505050506040513d601f19601f82011682018060405250810190613c8391906149fe565b979650505050505050565b5f613c9a82600261488f565b83511015613ce15760405162461bcd60e51b8152602060048201526014602482015273746f55696e7431365f6f75744f66426f756e647360601b6044820152606401610c58565b50016002015190565b60606001600160801b03821615613d3257604080516001600160801b0319608086811b8216602084015285901b16603082015201604051602081830303815290604052613d5c565b6040516001600160801b0319608085901b1660208201526030016040516020818303038152906040525b9392505050565b6060836003613d72825f613c8e565b61ffff1614613d8557613a67815f613c8e565b846001613d928551613ed2565b613d9d906001614a6f565b8686604051602001613db3959493929190614a8a565b6040516020818303038152906040529150509392505050565b5f813414613def576040516304fb820960e51b8152346004820152602401610c58565b5090565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e4fe1d946040518163ffffffff1660e01b8152600401602060405180830381865afa158015613e50573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613e749190614af0565b90506001600160a01b038116613e9d576040516329b99a9560e11b815260040160405180910390fd5b6114356001600160a01b038216337f000000000000000000000000000000000000000000000000000000000000000085613f00565b5f61ffff821115613def576040516306dfcc6560e41b81526010600482015260248101839052604401610c58565b5f6040516323b872dd60e01b81526001600160a01b03851660048201526001600160a01b038416602482015282604482015260205f6064835f8a5af13d15601f3d1160015f51141617169150508061284b5760405162461bcd60e51b81526020600482015260146024820152731514905394d1915497d19493d357d1905253115160621b6044820152606401610c58565b60405180606001604052805f80191681526020015f6001600160401b03168152602001613fcf60405180604001604052805f81526020015f81525090565b905290565b80356001600160601b0381168114612e18575f80fd5b6001600160a01b0381168114612ad0575f80fd5b8035612e1881613fea565b5f8083601f840112614019575f80fd5b5081356001600160401b0381111561402f575f80fd5b602083019150836020828501011115614046575f80fd5b9250929050565b5f805f805f8060a08789031215614062575f80fd5b61406b87613fd4565b9550602087013561407b81613fea565b945060408701356001600160401b03811115614095575f80fd5b6140a189828a01614009565b90955093505060608701356140b581613fea565b80925050608087013590509295509295509295565b5f805f606084860312156140dc575f80fd5b83356140e781613fea565b95602085013595506040909401359392505050565b6001600160401b0381168114612ad0575f80fd5b5f60208284031215614120575f80fd5b8135613d5c816140fc565b5f6060828403121561413b575f80fd5b50919050565b5f805f805f805f60e0888a031215614157575f80fd5b614161898961412b565b96506060880135955060808801356001600160401b0380821115614183575f80fd5b61418f8b838c01614009565b909750955060a08a013591506141a482613fea565b90935060c089013590808211156141b9575f80fd5b506141c68a828b01614009565b989b979a50959850939692959293505050565b803563ffffffff81168114612e18575f80fd5b80356001600160801b0381168114612e18575f80fd5b5f8060408385031215614213575f80fd5b61421c836141d9565b915061422a602084016141ec565b90509250929050565b5f60208284031215614243575f80fd5b8135613d5c81613fea565b5f806040838503121561425f575f80fd5b614268836141d9565b9150602083013561427881613fea565b809150509250929050565b5f8060408385031215614294575f80fd5b61429d836141d9565b946020939093013593505050565b8015158114612ad0575f80fd5b5f805f805f60a086880312156142cc575f80fd5b6142d5866141d9565b945060208601356142e5816142ab565b935060408601356142f5816142ab565b9250606086013561430581613fea565b9150614313608087016141ec565b90509295509295909350565b803560ff81168114612e18575f80fd5b5f805f805f805f60e0888a031215614345575f80fd5b873561435081613fea565b96506020880135955060408801359450606088013593506143736080890161431f565b925060a0880135915060c0880135905092959891949750929550565b5f805f80608085870312156143a2575f80fd5b84356143ad81613fea565b9350602085013592506040850135915060608501356143cb81613fea565b939692955090935050565b5f602082840312156143e6575f80fd5b613d5c826141d9565b5f805f805f805f60e0888a031215614405575f80fd5b87359650602088013561441781613fea565b9550604088013561442781613fea565b969995985095966060810135965060808101359560a0820135955060c0909101359350915050565b5f6020828403121561445f575f80fd5b81356001600160701b0381168114613d5c575f80fd5b5f60208284031215614485575f80fd5b8135613d5c816142ab565b5f805f80608085870312156144a3575f80fd5b84356144ae81613fea565b935060208501356144be816142ab565b925060408501356144ce816142ab565b9150606085013561ffff811681146143cb575f80fd5b5f805f805f805f805f805f806101608d8f031215614500575f80fd5b61450a8d35613fea565b8c359b5060208d01359a5060408d0135995060608d0135985061452f60808e0161431f565b975060a08d0135965060c08d0135955061454c60e08e0135613fea565b60e08d013594506001600160401b036101008e0135111561456b575f80fd5b61457c8e6101008f01358f01614009565b909450925061458e6101208e01613ffe565b91506101408d013590509295989b509295989b509295989b565b5f602082840312156145b8575f80fd5b5035919050565b5f805f606084860312156145d1575f80fd5b83356145dc81613fea565b925060208401356145ec81613fea565b915060408401356145fc81613fea565b809150509250925092565b5f805f60608486031215614619575f80fd5b614622846141d9565b9250602084013561463281613fea565b9150614640604085016141ec565b90509250925092565b5f805f805f805f8060e0898b031215614660575f80fd5b883561466b81613fea565b97506020890135965060408901359550606089013561468981613fea565b945060808901356001600160401b038111156146a3575f80fd5b6146af8b828c01614009565b90955093505060a08901356146c381613fea565b8092505060c089013590509295985092959890939650565b5f805f805f608086880312156146ef575f80fd5b6146f886613fd4565b9450602086013561470881613fea565b935060408601356001600160401b03811115614722575f80fd5b61472e88828901614009565b909450925050606086013561474281613fea565b809150509295509295909350565b5f60608284031215614760575f80fd5b613d5c838361412b565b6020808252600c908201526b15539055551213d49256915160a21b604082015260600190565b6020808252600a90820152695245454e5452414e435960b01b604082015260600190565b5f602082840312156147c4575f80fd5b5051919050565b6001600160a01b039586168152938516602085015260408401929092529092166060820152608081019190915260a00190565b634e487b7160e01b5f52601160045260245ffd5b81810381811115611f2957611f296147fe565b6001600160a01b0393841681529190921660208201526001600160e01b0319909116604082015260600190565b5f60208284031215614862575f80fd5b8151613d5c816142ab565b61ffff828116828216039080821115614888576148886147fe565b5092915050565b80820180821115611f2957611f296147fe565b5f6001600160401b038083168181036148bd576148bd6147fe565b6001019392505050565b5f5b838110156148e15781810151838201526020016148c9565b50505f910152565b5f81518084526149008160208601602086016148c7565b601f01601f19169290920160200192915050565b6040815263ffffffff8351166040820152602083015160608201525f604084015160a0608084015261494960e08401826148e9565b90506060850151603f198483030160a085015261496682826148e9565b60809690960151151560c08501525050506001600160a01b039190911660209091015290565b5f6040828403121561499c575f80fd5b604051604081018181106001600160401b03821117156149ca57634e487b7160e01b5f52604160045260245ffd5b604052825181526020928301519281019290925250919050565b5f604082840312156149f4575f80fd5b613d5c838361498c565b5f60808284031215614a0e575f80fd5b604051606081018181106001600160401b0382111715614a3c57634e487b7160e01b5f52604160045260245ffd5b604052825181526020830151614a51816140fc565b6020820152614a63846040850161498c565b60408201529392505050565b61ffff818116838216019080821115614888576148886147fe565b5f8651614a9b818460208b016148c7565b6001600160f81b031960f888811b82169285019283526001600160f01b031960f089901b16600184015286901b1660038201528351614ae18160048401602088016148c7565b01600401979650505050505050565b5f60208284031215614b00575f80fd5b8151613d5c81613fea56fea264697066735822122046a8bb17c7e9a6c35e6267420a3c8a2a80e232243e6573906cc1c2c0ddfe667a64736f6c634300081500330000000000000000000000005f2f11ad8656439d5c14d9b351f8b09cdac2a02d000000000000000000000000f0bb20865277abd641a307ece5ee04e79073416c0000000000000000000000000d05d94a5f1e76c18fbeb7a13d17c8a314088198000000000000000000000000ee7d8bcfb72bc1880d0cf19822eb0a2e6577ab620000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b0000000000000000000000005f2f11ad8656439d5c14d9b351f8b09cdac2a02d0000000000000000000000000000000000000000000000000000000000000001
Deployed Bytecode
0x60806040526004361061037c575f3560e01c80637d25a05e116101d3578063bb0b6a53116100fd578063d555f3681161009d578063e83931af1161006d578063e83931af14610b97578063f2fde38b14610bb6578063fbfa77cf14610bd5578063ff7bd03d14610c08575f80fd5b8063d555f36814610afc578063d7424e3314610b1b578063dbd5edc714610b3a578063de35f5cb14610b78575f80fd5b8063c29d2f10116100d8578063c29d2f1014610a3c578063ca5eb5e114610a5b578063cab716e814610a7a578063d182221614610a8d575f80fd5b8063bb0b6a53146109d3578063bf671384146109fe578063bf7e214f14610a1d575f80fd5b80639ac4f42d11610173578063abd626b011610143578063abd626b014610963578063b187bd2614610982578063b5ba6182146109a2578063b92d0eff146109c1575f80fd5b80639ac4f42d146108e05780639d574420146108ff5780639fdb11b61461091e578063a924bf6114610944575f80fd5b80638da5cb5b116101ae5780638da5cb5b146108655780638dfd8ba11461088357806394f51289146108a25780639a94d3d0146108b5575f80fd5b80637d25a05e146107fb5780638456cb59146108325780638a6733f914610846575f80fd5b806334dafd6b116102b457806346b563f4116102545780635e280f11116102245780635e280f111461076b5780635f45bac81461079e5780637a9e5e4b146107bd5780637bd876b6146107dc575f80fd5b806346b563f4146106755780634fb3ccc51461069457806355a2d64d146106c75780635c465430146106e6575f80fd5b80633e64ce991161028f5780633e64ce99146105be5780633f4ba83a146105dd57806341fee44a146105f157806345ad606314610656575f80fd5b806334dafd6b146105615780633b575407146105805780633d935d9e1461059f575f80fd5b806317442b701161031f5780631ba9a458116102fa5780631ba9a458146104e5578063202eac57146105045780632c524c42146105235780633400288b14610542575f80fd5b806317442b701461048757806318aed921146104a75780631b62636c146104c6575f80fd5b80630efe6a8b1161035a5780630efe6a8b1461041557806312056e2d1461043657806313137d65146104555780631568fc5814610468575f80fd5b80630511ef431461038057806305921740146103b55780630b48a8b8146103ca575b5f80fd5b34801561038b575f80fd5b506004546103a090600160881b900460ff1681565b60405190151581526020015b60405180910390f35b6103c86103c336600461404d565b610c27565b005b3480156103d5575f80fd5b506103fd7f000000000000000000000000ee7d8bcfb72bc1880d0cf19822eb0a2e6577ab6281565b6040516001600160a01b0390911681526020016103ac565b6104286104233660046140ca565b610ccd565b6040519081526020016103ac565b348015610441575f80fd5b506103c8610450366004614110565b610ed6565b6103c8610463366004614141565b610f66565b348015610473575f80fd5b506103c8610482366004614202565b611021565b348015610492575f80fd5b506040805160018082526020820152016103ac565b3480156104b2575f80fd5b506103c86104c1366004614233565b6110f6565b3480156104d1575f80fd5b506103c86104e0366004614233565b6111dc565b3480156104f0575f80fd5b506103c86104ff366004614233565b61125c565b34801561050f575f80fd5b506103c861051e36600461424e565b6112d7565b34801561052e575f80fd5b506103c861053d366004614233565b61137e565b34801561054d575f80fd5b506103c861055c366004614283565b6113fa565b34801561056c575f80fd5b506103c861057b3660046142b8565b611439565b34801561058b575f80fd5b506103c861059a366004614233565b61158d565b3480156105aa575f80fd5b506104286105b936600461432f565b61160b565b3480156105c9575f80fd5b506104286105d836600461438f565b611709565b3480156105e8575f80fd5b506103c8611996565b3480156105fc575f80fd5b5061063561060b366004614233565b60036020525f908152604090205460ff8082169161010081049091169062010000900461ffff1683565b604080519315158452911515602084015261ffff16908201526060016103ac565b348015610661575f80fd5b506103c86106703660046143d6565b6119fe565b348015610680575f80fd5b506103c861068f3660046143ef565b611a87565b34801561069f575f80fd5b506103fd7f0000000000000000000000000d05d94a5f1e76c18fbeb7a13d17c8a31408819881565b3480156106d2575f80fd5b506103c86106e13660046143d6565b611c91565b3480156106f1575f80fd5b5061073b610700366004614233565b60066020525f90815260409020805460019091015460ff80831692610100810482169262010000820483169263010000009092049091169085565b6040805195151586529315156020860152911515928401929092529015156060830152608082015260a0016103ac565b348015610776575f80fd5b506103fd7f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b81565b3480156107a9575f80fd5b506103c86107b8366004614233565b611d37565b3480156107c8575f80fd5b506103c86107d7366004614233565b611db1565b3480156107e7575f80fd5b506103c86107f636600461444f565b611e95565b348015610806575f80fd5b5061081a610815366004614283565b611f27565b6040516001600160401b0390911681526020016103ac565b34801561083d575f80fd5b506103c8611f2f565b348015610851575f80fd5b506103c8610860366004614475565b611f9d565b348015610870575f80fd5b505f546103fd906001600160a01b031681565b34801561088e575f80fd5b506103c861089d366004614490565b61201b565b6104286108b03660046144e4565b612134565b3480156108c0575f80fd5b506104286108cf3660046145a8565b60056020525f908152604090205481565b3480156108eb575f80fd5b506103c86108fa366004614233565b61226d565b34801561090a575f80fd5b5061042861091936600461438f565b6122ef565b348015610929575f80fd5b5060045461081a90600160401b90046001600160401b031681565b34801561094f575f80fd5b506103c861095e366004614233565b6123b4565b34801561096e575f80fd5b506103c861097d3660046145bf565b61242d565b34801561098d575f80fd5b506004546103a090600160801b900460ff1681565b3480156109ad575f80fd5b506103c86109bc366004614607565b61254e565b3480156109cc575f80fd5b50306103fd565b3480156109de575f80fd5b506104286109ed3660046143d6565b60076020525f908152604090205481565b348015610a09575f80fd5b506103c8610a18366004614233565b61264b565b348015610a28575f80fd5b506001546103fd906001600160a01b031681565b348015610a47575f80fd5b506103c8610a56366004614233565b6126c7565b348015610a66575f80fd5b506103c8610a75366004614233565b6127a8565b610428610a88366004614649565b612852565b348015610a98575f80fd5b50610ad6610aa73660046143d6565b60086020525f908152604090205460ff808216916101008104909116906201000090046001600160801b031683565b60408051931515845291151560208401526001600160801b0316908201526060016103ac565b348015610b07575f80fd5b506103c8610b163660046143d6565b612979565b348015610b26575f80fd5b50610428610b353660046146db565b6129f9565b348015610b45575f80fd5b50600454610b6090600160901b90046001600160701b031681565b6040516001600160701b0390911681526020016103ac565b348015610b83575f80fd5b5060045461081a906001600160401b031681565b348015610ba2575f80fd5b506103c8610bb1366004614233565b612a44565b348015610bc1575f80fd5b506103c8610bd0366004614233565b612ad3565b348015610be0575f80fd5b506103fd7f000000000000000000000000f0bb20865277abd641a307ece5ee04e79073416c81565b348015610c13575f80fd5b506103a0610c22366004614750565b612b4e565b610c3c335f356001600160e01b031916612b82565b610c615760405162461bcd60e51b8152600401610c589061476a565b60405180910390fd5b600254600114610c835760405162461bcd60e51b8152600401610c5890614790565b60028055600454600160801b900460ff1615610cb25760405163e0f9e71d60e01b815260040160405180910390fd5b610cc0868686868686612c28565b5050600160025550505050565b5f610ce3335f356001600160e01b031916612b82565b610cff5760405162461bcd60e51b8152600401610c589061476a565b600254600114610d215760405162461bcd60e51b8152600401610c5890614790565b600280555f610d2f85612d62565b90505f73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03871601610e6b57345f03610d775760405163259be69560e11b815260040160405180910390fd5b7f000000000000000000000000ee7d8bcfb72bc1880d0cf19822eb0a2e6577ab626001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004015f604051808303818588803b158015610dd0575f80fd5b505af1158015610de2573d5f803e3d5ffd5b50349850610e419350506001600160a01b037f000000000000000000000000ee7d8bcfb72bc1880d0cf19822eb0a2e6577ab621691507f000000000000000000000000f0bb20865277abd641a307ece5ee04e79073416c905087612e1d565b507f000000000000000000000000ee7d8bcfb72bc1880d0cf19822eb0a2e6577ab62945030610e8d565b3415610e8a57604051631cf02cf960e21b815260040160405180910390fd5b50335b610e9b868686843387612e9f565b9250610ec833878786600460089054906101000a90046001600160401b03166001600160401b0316613136565b505060016002559392505050565b610eeb335f356001600160e01b031916612b82565b610f075760405162461bcd60e51b8152600401610c589061476a565b6203f480816001600160401b03161115610f3457604051631fac010160e21b815260040160405180910390fd5b600480546001600160401b03909216600160401b026fffffffffffffffff000000000000000019909216919091179055565b7f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b03163314610fb1576040516391ac5e4f60e01b8152336004820152602401610c58565b60208701803590610fcb90610fc6908a6143d6565b613268565b1461100957610fdd60208801886143d6565b60405163309afaf360e21b815263ffffffff909116600482015260208801356024820152604401610c58565b611018878787878787876132a3565b50505050505050565b611036335f356001600160e01b031916612b82565b6110525760405162461bcd60e51b8152600401610c589061476a565b806001600160801b03165f0361107b5760405163c80ed59560e01b815260040160405180910390fd5b63ffffffff82165f81815260086020908152604091829020805462010000600160901b031916620100006001600160801b038716908102919091178255835194855291840191909152917f0aa48359f83e8464fda3f4ea4bd3f2d6af01e90b46ab9464aa7d538e1772947a91015b60405180910390a1505050565b61110b335f356001600160e01b031916612b82565b6111275760405162461bcd60e51b8152600401610c589061476a565b6001600160a01b0381165f81815260066020526040808220805462ffffff191662010101179055517fd658022b1a3aaf6ad3b3c615253712807f21a8f7bc3e4996e10618175d4afb2b9190a26040516001600160a01b038216907f79fc685a7dbabb75a67df5e69a90602cef1f19bc465b060eab1ac56685e04a13905f90a26040516001600160a01b038216907f3afb02134e37f7205acf470adc2fc4ebb70614b1599a602d069790915380e2aa905f90a250565b6111f1335f356001600160e01b031916612b82565b61120d5760405162461bcd60e51b8152600401610c589061476a565b6001600160a01b0381165f81815260066020526040808220805462ff0000191662010000179055517f3afb02134e37f7205acf470adc2fc4ebb70614b1599a602d069790915380e2aa9190a250565b611271335f356001600160e01b031916612b82565b61128d5760405162461bcd60e51b8152600401610c589061476a565b6001600160a01b0381165f81815260066020526040808220805462ff000019169055517f77cb944c14da76928795279d1519ce9150085a06e0a53c61d5a86fc4e0fd57c69190a250565b6112ec335f356001600160e01b031916612b82565b6113085760405162461bcd60e51b8152600401610c589061476a565b63ffffffff82165f908152600860205260409020805460ff1916600117815561133a836001600160a01b038416613360565b6040805163ffffffff851681526001600160a01b03841660208201527fe925de263dcdbdc20307c9ab92758ed8cc0edf3d173dad4a3aa54c070f27a54391016110e9565b611393335f356001600160e01b031916612b82565b6113af5760405162461bcd60e51b8152600401610c589061476a565b6001600160a01b0381165f81815260066020526040808220805460ff19166001179055517fd658022b1a3aaf6ad3b3c615253712807f21a8f7bc3e4996e10618175d4afb2b9190a250565b61140f335f356001600160e01b031916612b82565b61142b5760405162461bcd60e51b8152600401610c589061476a565b6114358282613360565b5050565b61144e335f356001600160e01b031916612b82565b61146a5760405162461bcd60e51b8152600401610c589061476a565b82801561147e57506001600160801b038116155b1561149c5760405163c80ed59560e01b815260040160405180910390fd5b60408051606081018252851515815284151560208083019182526001600160801b0385811684860190815263ffffffff8b165f908152600890935294909120925183549251945161ffff1990931690151561ff00191617610100941515949094029390931762010000600160901b03191662010000919093160291909117905561152f856001600160a01b038416613360565b6040805163ffffffff871681528515156020820152841515818301526001600160a01b038416606082015290517f5dbe727bffd24a6d61a5aeef919510389c66c0deeaa82634862cf4f098961fb89181900360800190a15050505050565b6115a2335f356001600160e01b031916612b82565b6115be5760405162461bcd60e51b8152600401610c589061476a565b6001600160a01b0381165f81815260066020526040808220805461ff001916610100179055517f79fc685a7dbabb75a67df5e69a90602cef1f19bc465b060eab1ac56685e04a139190a250565b5f611621335f356001600160e01b031916612b82565b61163d5760405162461bcd60e51b8152600401610c589061476a565b60025460011461165f5760405162461bcd60e51b8152600401610c5890614790565b600280558773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b038216016116a2576040516316df5df960e31b815260040160405180910390fd5b5f6116ac8a612d62565b90506116bc8a8a898989896133ad565b6116ca8a8a8a333386612e9f565b92506116f7338b8b86600460089054906101000a90046001600160401b03166001600160401b0316613136565b50506001600255979650505050505050565b5f61171f335f356001600160e01b031916612b82565b61173b5760405162461bcd60e51b8152600401610c589061476a565b600454600160801b900460ff16156117665760405163e0f9e71d60e01b815260040160405180910390fd5b6001600160a01b0385165f908152600360209081526040918290208251606081018452905460ff80821615158352610100820416151592820183905262010000900461ffff16928101929092526117d05760405163645fd19f60e11b815260040160405180910390fd5b845f036117f057604051630ea3153160e21b815260040160405180910390fd5b604051634104b9ed60e11b81526001600160a01b0387811660048301526118a6917f0000000000000000000000000d05d94a5f1e76c18fbeb7a13d17c8a3140881989091169063820973da90602401602060405180830381865afa15801561185a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061187e91906147b4565b86907f0000000000000000000000000000000000000000000000000de0b6b3a7640000613505565b9150838210156118c9576040516302620f6160e61b815260040160405180910390fd5b6040516318457e6160e01b81526001600160a01b037f000000000000000000000000f0bb20865277abd641a307ece5ee04e79073416c16906318457e619061191d9086908a90879033908c906004016147cb565b5f604051808303815f87803b158015611934575f80fd5b505af1158015611946573d5f803e3d5ffd5b50505050856001600160a01b03167fdcc60b41ff1c604459e6aa4a7299817416b19fc586a392f111646e26597c4af98660405161198591815260200190565b60405180910390a250949350505050565b6119ab335f356001600160e01b031916612b82565b6119c75760405162461bcd60e51b8152600401610c589061476a565b6004805460ff60801b191690556040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d16933905f90a1565b611a13335f356001600160e01b031916612b82565b611a2f5760405162461bcd60e51b8152600401610c589061476a565b63ffffffff81165f81815260086020908152604091829020805461ff0019168155915192835290917fc45af64a13a09ef916a1114c59589294ec9c3095f2bfbbb093a7a96656858ded91015b60405180910390a15050565b611a9c335f356001600160e01b031916612b82565b611ab85760405162461bcd60e51b8152600401610c589061476a565b80611ac38342614812565b10611ae157604051634c1eef1760e11b815260040160405180910390fd5b604080516001600160a01b038089166020830152871691810191909152606081018590526080810184905260a0810183905260c081018290525f9060e00160408051601f1981840301815291815281516020928301205f8b815260059093529120549091508114611b655760405163fa174ecb60e01b815260040160405180910390fd5b5f888152600560205260408120556001600160a01b03861673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611b9d5785611bbf565b7f000000000000000000000000ee7d8bcfb72bc1880d0cf19822eb0a2e6577ab625b6040516318457e6160e01b81529096506001600160a01b037f000000000000000000000000f0bb20865277abd641a307ece5ee04e79073416c16906318457e6190611c16908a908a908a9083908b906004016147cb565b5f604051808303815f87803b158015611c2d575f80fd5b505af1158015611c3f573d5f803e3d5ffd5b50505050866001600160a01b0316887faf98ea774275cadfa3e477a7b52cba03e01197445a76bd5d0d561608708c362483604051611c7f91815260200190565b60405180910390a35050505050505050565b611ca6335f356001600160e01b031916612b82565b611cc25760405162461bcd60e51b8152600401610c589061476a565b63ffffffff81165f908152600860205260408120805471ffffffffffffffffffffffffffffffffffff19169055611cfa908290613360565b60405163ffffffff821681527f11a9d1a77f76361ed131c19b1dc5758504c51dbde2e49fc973a0ef9577ad13d5906020015b60405180910390a150565b611d4c335f356001600160e01b031916612b82565b611d685760405162461bcd60e51b8152600401610c589061476a565b6001600160a01b0381165f81815260066020526040808220805461ff0019169055517f039bcf51833310242b8b7c6aa0fbabf1bf2b5e5270807ee020f1920ef200666b9190a250565b5f546001600160a01b0316331480611e42575060015460405163b700961360e01b81526001600160a01b039091169063b700961390611e0390339030906001600160e01b03195f351690600401614825565b602060405180830381865afa158015611e1e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e429190614852565b611e4a575f80fd5b600180546001600160a01b0319166001600160a01b03831690811790915560405133907fa3396fd7f6e0a21b50e5089d2da70d5ac0a3bbbd1f617a93f134b76389980198905f90a350565b611eaa335f356001600160e01b031916612b82565b611ec65760405162461bcd60e51b8152600401610c589061476a565b6004805471ffffffffffffffffffffffffffffffffffff16600160901b6001600160701b038416908102919091179091556040519081527f752cd3d8df6864142257fa3a2e02aedf2dc09f1875c2a25b4f117d45c7334d5d90602001611d2c565b5f5b92915050565b611f44335f356001600160e01b031916612b82565b611f605760405162461bcd60e51b8152600401610c589061476a565b6004805460ff60801b1916600160801b1790556040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e752905f90a1565b611fb2335f356001600160e01b031916612b82565b611fce5760405162461bcd60e51b8152600401610c589061476a565b60048054821515600160881b0260ff60881b199091161790556040517fa3fe47e2502292ca20854524008d366d3cad5da2426cfb2484099f06f328e4a090611d2c90831515815260200190565b612030335f356001600160e01b031916612b82565b61204c5760405162461bcd60e51b8152600401610c589061476a565b6103e861ffff8216111561207357604051636c5cde8760e01b815260040160405180910390fd5b6040805160608082018352851515808352851515602080850182815261ffff8881168789018181526001600160a01b038e165f818152600387528b902099518a549551925161ffff1990961690151561ff00191617610100921515929092029190911763ffff0000191662010000949093169390930291909117909655865193845290830191909152938101929092527fe08301321781ac43935a2099b2c3fd42de0a0ee87a519cac00e8c9cecd26ff12910160405180910390a250505050565b5f61214a335f356001600160e01b031916612b82565b6121665760405162461bcd60e51b8152600401610c589061476a565b6002546001146121885760405162461bcd60e51b8152600401610c5890614790565b600280558c73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b038216016121cb576040516316df5df960e31b815260040160405180910390fd5b5f6121d58f612d62565b90506121e58f8f8e8e8e8e6133ad565b6121f38f8f8f333386612e9f565b925050612221338f8f85600460089054906101000a90046001600160401b03166001600160401b0316613136565b6001600160601b03821115612249576040516389588ab360e01b815260040160405180910390fd5b612257828888888888612c28565b5060016002559c9b505050505050505050505050565b612282335f356001600160e01b031916612b82565b61229e5760405162461bcd60e51b8152600401610c589061476a565b6001600160a01b0381165f81815260066020526040808220805463ff00000019166301000000179055517f5e92c085dffcb69d025c31c9ed03d1869e4737ba81e8649c623398caa1b72f159190a250565b5f612305335f356001600160e01b031916612b82565b6123215760405162461bcd60e51b8152600401610c589061476a565b6002546001146123435760405162461bcd60e51b8152600401610c5890614790565b600280555f61235186612d62565b9050612361868686338786612e9f565b9150856001600160a01b03167f6f9b974223f85a1ae805c33b8b519039e2435481d949db1110de151a94d587af8660405161239e91815260200190565b60405180910390a2506001600255949350505050565b6123c9335f356001600160e01b031916612b82565b6123e55760405162461bcd60e51b8152600401610c589061476a565b6001600160a01b0381165f81815260066020526040808220805460ff19169055517fae893dda71e2eee548f8291f458cceae4bd22b56a79906928591e4420444c0e99190a250565b6001600160a01b0383165f9081526006602052604090205460ff168061246f57506001600160a01b0382165f90815260066020526040902054610100900460ff165b8061249757506001600160a01b0381165f9081526006602052604090205462010000900460ff165b806124d55750600454600160881b900460ff1680156124d557506001600160a01b0381165f908152600660205260409020546301000000900460ff16155b1561250e57604051632821264f60e01b81526001600160a01b038085166004830152808416602483015282166044820152606401610c58565b6001600160a01b0383165f908152600660205260409020600101544210156125495760405163f64059db60e01b815260040160405180910390fd5b505050565b612563335f356001600160e01b031916612b82565b61257f5760405162461bcd60e51b8152600401610c589061476a565b806001600160801b03165f036125a85760405163c80ed59560e01b815260040160405180910390fd5b63ffffffff83165f908152600860205260409020805461010071ffffffffffffffffffffffffffffffffff0019909116620100006001600160801b03851602171781556125fe846001600160a01b038516613360565b6040805163ffffffff861681526001600160a01b03851660208201527f34fe916485e02ec88e487b0e611e5c9bacabba9e3eaae7a900aa08be8197d419910160405180910390a150505050565b612660335f356001600160e01b031916612b82565b61267c5760405162461bcd60e51b8152600401610c589061476a565b6001600160a01b0381165f81815260066020526040808220805463ff00000019169055517f1c2a701d65e1c6e2860263c884eae0b10db82e3ddd60640d53c7d53c6c998e799190a250565b6126dc335f356001600160e01b031916612b82565b6126f85760405162461bcd60e51b8152600401610c589061476a565b6001600160a01b0381165f81815260066020526040808220805462ffffff19169055517fae893dda71e2eee548f8291f458cceae4bd22b56a79906928591e4420444c0e99190a26040516001600160a01b038216907f039bcf51833310242b8b7c6aa0fbabf1bf2b5e5270807ee020f1920ef200666b905f90a26040516001600160a01b038216907f77cb944c14da76928795279d1519ce9150085a06e0a53c61d5a86fc4e0fd57c6905f90a250565b6127bd335f356001600160e01b031916612b82565b6127d95760405162461bcd60e51b8152600401610c589061476a565b60405163ca5eb5e160e01b81526001600160a01b0382811660048301527f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b169063ca5eb5e1906024015f604051808303815f87803b158015612839575f80fd5b505af115801561284b573d5f803e3d5ffd5b5050505050565b5f612868335f356001600160e01b031916612b82565b6128845760405162461bcd60e51b8152600401610c589061476a565b6002546001146128a65760405162461bcd60e51b8152600401610c5890614790565b600280558873eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b038216016128e9576040516316df5df960e31b815260040160405180910390fd5b5f6128f38b612d62565b90506129038b8b8b333386612e9f565b9250612930338c8c86600460089054906101000a90046001600160401b03166001600160401b0316613136565b6001600160601b03831115612958576040516389588ab360e01b815260040160405180910390fd5b612966838989898989612c28565b5050600160025598975050505050505050565b61298e335f356001600160e01b031916612b82565b6129aa5760405162461bcd60e51b8152600401610c589061476a565b63ffffffff81165f81815260086020908152604091829020805460ff19168155915192835290917f1cb867ed6a020e020ea220d4f48bb8e36552abf9095e093e377d33933f2b31e49101611a7b565b604080518082019091526001600160601b03861681526001600160a01b03851660208201525f9081612a2a82613520565b9050612a3881878787613567565b98975050505050505050565b6001600160a01b0381165f9081526006602052604090205460ff1615612a9557604051632821264f60e01b81526001600160a01b03821660048201525f602482018190526044820152606401610c58565b6001600160a01b0381165f90815260066020526040902060010154421015612ad05760405163f64059db60e01b815260040160405180910390fd5b50565b612ae8335f356001600160e01b031916612b82565b612b045760405162461bcd60e51b8152600401610c589061476a565b5f80546001600160a01b0319166001600160a01b0383169081178255604051909133917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a350565b5f602082018035906007908390612b6590866143d6565b63ffffffff16815260208101919091526040015f20541492915050565b6001545f906001600160a01b03168015801590612c09575060405163b700961360e01b81526001600160a01b0382169063b700961390612bca90879030908890600401614825565b602060405180830381865afa158015612be5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612c099190614852565b80612c2057505f546001600160a01b038581169116145b949350505050565b612c33335f3361242d565b6040516318457e6160e01b81525f600482018190526024820181905260448201523360648201526001600160601b03871660848201527f000000000000000000000000f0bb20865277abd641a307ece5ee04e79073416c6001600160a01b0316906318457e619060a4015f604051808303815f87803b158015612cb4575f80fd5b505af1158015612cc6573d5f803e3d5ffd5b5050604080518082019091526001600160601b03891681526001600160a01b038816602082015291505f9050612cfb82613520565b90505f612d0b8288888888613736565b6040516001600160601b038b1681529091506001600160a01b0389169082907fe0ec62d39b054dc2fd626dbc271483735df6e6fa1ef8389754bf8ab27a75eab29060200160405180910390a3505050505050505050565b604080516060810182525f8082526020820181905291810191909152600454600160801b900460ff1615612da95760405163e0f9e71d60e01b815260040160405180910390fd5b506001600160a01b0381165f908152600360209081526040918290208251606081018452905460ff8082161515808452610100830490911615159383019390935262010000900461ffff1692810192909252612e185760405163645fd19f60e11b815260040160405180910390fd5b919050565b5f60405163095ea7b360e01b81526001600160a01b038416600482015282602482015260205f6044835f895af13d15601f3d1160015f511416171691505080612e995760405162461bcd60e51b815260206004820152600e60248201526d1054141493d59157d1905253115160921b6044820152606401610c58565b50505050565b6004545f90600160901b90046001600160701b0316868203612ed45760405163259be69560e11b815260040160405180910390fd5b604051634104b9ed60e11b81526001600160a01b038981166004830152612f8a917f0000000000000000000000000000000000000000000000000de0b6b3a7640000917f0000000000000000000000000d05d94a5f1e76c18fbeb7a13d17c8a314088198169063820973da90602401602060405180830381865afa158015612f5e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612f8291906147b4565b899190613505565b91505f836040015161ffff1611612fa15781612fc4565b612fc48360400151612710612fb6919061486d565b839061ffff16612710613505565b915085821015612fe75760405163097b2ad560e31b815260040160405180910390fd5b6001600160701b03818116146130aa57806001600160701b03167f000000000000000000000000f0bb20865277abd641a307ece5ee04e79073416c6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561305d573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061308191906147b4565b61308b908461488f565b11156130aa5760405163ed32f3bb60e01b815260040160405180910390fd5b604051631ceb5d1960e11b81526001600160a01b037f000000000000000000000000f0bb20865277abd641a307ece5ee04e79073416c16906339d6ba32906130fe9088908c908c908a9089906004016147cb565b5f604051808303815f87803b158015613115575f80fd5b505af1158015613127573d5f803e3d5ffd5b50505050509695505050505050565b600480545f91908290613151906001600160401b03166148a2565b82546001600160401b039182166101009390930a8381029202191617909155905081156131f857613182824261488f565b6001600160a01b038781165f81815260066020908152604091829020600101949094558051938401919091529087169082015260608101859052608081018490524260a082015260c0810183905260e00160408051601f1981840301815291815281516020928301205f84815260059093529120555b846001600160a01b0316866001600160a01b0316827fe96d7872363f475d18b2f5390caaa5eaa96b2d38e42c62afe4ac08ebd2b13c3a87874288604051613258949392919093845260208401929092526040830152606082015260800190565b60405180910390a4505050505050565b63ffffffff81165f9081526007602052604081205480611f295760405163f6ff4fb760e01b815263ffffffff84166004820152602401610c58565b5f6008816132b460208b018b6143d6565b63ffffffff16815260208082019290925260409081015f208151606081018352905460ff808216151580845261010083049091161515948301949094526201000090046001600160801b031691810191909152915061333c5761331a60208901896143d6565b6040516315b73a2960e21b815263ffffffff9091166004820152602401610c58565b5f613349868801886145a8565b90506133558882613959565b505050505050505050565b63ffffffff82165f81815260076020908152604091829020849055815192835282018390527f238399d427b947898edb290f5ff0f9109849b1c3ba196a42e35f00c50a54b98b9101611a7b565b60405163d505accf60e01b81523360048201526001600160a01b037f000000000000000000000000f0bb20865277abd641a307ece5ee04e79073416c81166024830152604482018790526064820186905260ff8516608483015260a4820184905260c4820183905287169063d505accf9060e4015f604051808303815f87803b158015613438575f80fd5b505af1925050508015613449575060015b6134fd57604051636eb1769f60e11b81523360048201526001600160a01b037f000000000000000000000000f0bb20865277abd641a307ece5ee04e79073416c8116602483015286919088169063dd62ed3e90604401602060405180830381865afa1580156134ba573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906134de91906147b4565b10156134fd576040516301b8851f60e41b815260040160405180910390fd5b505050505050565b5f825f190484118302158202613519575f80fd5b5091020490565b80515f906001600160601b03101561354b57604051633524486360e01b815260040160405180910390fd5b81516020909201516001600160a01b031660a09290921b171790565b5f6001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee148015906135c757507f00000000000000000000000000000000000000000000000000000000000000016001600160a01b0316826001600160a01b031614155b156135e557604051637f3cd08160e11b815260040160405180910390fd5b5f6135f2848601866143d6565b63ffffffff81165f908152600860209081526040918290208251606081018452905460ff8082161515835261010082041615159282018390526201000090046001600160801b0316928101929092529192509061366a5760405163420eae3760e01b815263ffffffff83166004820152602401610c58565b5f8760405160200161367e91815260200190565b60405160208183030381529060405290505f6136c683604001515f6136bf60408051600360f01b602082015281516002818303018152602290910190915290565b9190613a45565b90505f6136f58584846001600160a01b038b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613aaa565b90506001600160a01b03871673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14613725578060200151613728565b80515b9a9950505050505050505050565b5f80613744858701876143d6565b63ffffffff81165f908152600860209081526040918290208251606081018452905460ff8082161515835261010082041615159282018390526201000090046001600160801b031692810192909252919250906137bc5760405163420eae3760e01b815263ffffffff83166004820152602401610c58565b5f886040516020016137d091815260200190565b60405160208183030381529060405290505f61381183604001515f6136bf60408051600360f01b602082015281516002818303018152602290910190915290565b90505f6138408584846001600160a01b038c1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613aaa565b905073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b038916016138a75780518710156138a257805160405163f5ac3fa760e01b815263ffffffff87166004820152602481019190915260448101889052606401610c58565b61393a565b7f00000000000000000000000000000000000000000000000000000000000000016001600160a01b0316886001600160a01b0316036139215786816020015111156138a257602081015160405163f5ac3fa760e01b815263ffffffff87166004820152602481019190915260448101889052606401610c58565b604051637f3cd08160e11b815260040160405180910390fd5b5f6139488685858533613b88565b519c9b505050505050505050505050565b60408051808201825260a083901c8082526001600160a01b03808516602084018190529351631ceb5d1960e11b815292937f000000000000000000000000f0bb20865277abd641a307ece5ee04e79073416c909116926339d6ba32926139c8925f9283928392916004016147cb565b5f604051808303815f87803b1580156139df575f80fd5b505af11580156139f1573d5f803e3d5ffd5b5050505080602001516001600160a01b0316837fb944fddc61d7fedb8b736790454ba972000703b0d21c7481d6dbf95b7c2cc2f1835f0151604051613a3891815260200190565b60405180910390a3505050565b6060836003613a54825f613c8e565b61ffff1614613a8757613a67815f613c8e565b604051633a51740d60e01b815261ffff9091166004820152602401610c58565b5f613a928585613cea565b9050613aa086600183613d63565b9695505050505050565b604080518082019091525f80825260208201527f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b031663ddc28c586040518060a001604052808863ffffffff168152602001613b0c89613268565b8152602001878152602001868152602001851515815250306040518363ffffffff1660e01b8152600401613b41929190614914565b6040805180830381865afa158015613b5b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613b7f91906149e4565b95945050505050565b613b90613f91565b5f613b9d845f0151613dcc565b602085015190915015613bb757613bb78460200151613df3565b7f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b0316632637a450826040518060a001604052808b63ffffffff168152602001613c078c613268565b81526020018a81526020018981526020015f8960200151111515815250866040518463ffffffff1660e01b8152600401613c42929190614914565b60806040518083038185885af1158015613c5e573d5f803e3d5ffd5b50505050506040513d601f19601f82011682018060405250810190613c8391906149fe565b979650505050505050565b5f613c9a82600261488f565b83511015613ce15760405162461bcd60e51b8152602060048201526014602482015273746f55696e7431365f6f75744f66426f756e647360601b6044820152606401610c58565b50016002015190565b60606001600160801b03821615613d3257604080516001600160801b0319608086811b8216602084015285901b16603082015201604051602081830303815290604052613d5c565b6040516001600160801b0319608085901b1660208201526030016040516020818303038152906040525b9392505050565b6060836003613d72825f613c8e565b61ffff1614613d8557613a67815f613c8e565b846001613d928551613ed2565b613d9d906001614a6f565b8686604051602001613db3959493929190614a8a565b6040516020818303038152906040529150509392505050565b5f813414613def576040516304fb820960e51b8152346004820152602401610c58565b5090565b5f7f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b031663e4fe1d946040518163ffffffff1660e01b8152600401602060405180830381865afa158015613e50573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613e749190614af0565b90506001600160a01b038116613e9d576040516329b99a9560e11b815260040160405180910390fd5b6114356001600160a01b038216337f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b85613f00565b5f61ffff821115613def576040516306dfcc6560e41b81526010600482015260248101839052604401610c58565b5f6040516323b872dd60e01b81526001600160a01b03851660048201526001600160a01b038416602482015282604482015260205f6064835f8a5af13d15601f3d1160015f51141617169150508061284b5760405162461bcd60e51b81526020600482015260146024820152731514905394d1915497d19493d357d1905253115160621b6044820152606401610c58565b60405180606001604052805f80191681526020015f6001600160401b03168152602001613fcf60405180604001604052805f81526020015f81525090565b905290565b80356001600160601b0381168114612e18575f80fd5b6001600160a01b0381168114612ad0575f80fd5b8035612e1881613fea565b5f8083601f840112614019575f80fd5b5081356001600160401b0381111561402f575f80fd5b602083019150836020828501011115614046575f80fd5b9250929050565b5f805f805f8060a08789031215614062575f80fd5b61406b87613fd4565b9550602087013561407b81613fea565b945060408701356001600160401b03811115614095575f80fd5b6140a189828a01614009565b90955093505060608701356140b581613fea565b80925050608087013590509295509295509295565b5f805f606084860312156140dc575f80fd5b83356140e781613fea565b95602085013595506040909401359392505050565b6001600160401b0381168114612ad0575f80fd5b5f60208284031215614120575f80fd5b8135613d5c816140fc565b5f6060828403121561413b575f80fd5b50919050565b5f805f805f805f60e0888a031215614157575f80fd5b614161898961412b565b96506060880135955060808801356001600160401b0380821115614183575f80fd5b61418f8b838c01614009565b909750955060a08a013591506141a482613fea565b90935060c089013590808211156141b9575f80fd5b506141c68a828b01614009565b989b979a50959850939692959293505050565b803563ffffffff81168114612e18575f80fd5b80356001600160801b0381168114612e18575f80fd5b5f8060408385031215614213575f80fd5b61421c836141d9565b915061422a602084016141ec565b90509250929050565b5f60208284031215614243575f80fd5b8135613d5c81613fea565b5f806040838503121561425f575f80fd5b614268836141d9565b9150602083013561427881613fea565b809150509250929050565b5f8060408385031215614294575f80fd5b61429d836141d9565b946020939093013593505050565b8015158114612ad0575f80fd5b5f805f805f60a086880312156142cc575f80fd5b6142d5866141d9565b945060208601356142e5816142ab565b935060408601356142f5816142ab565b9250606086013561430581613fea565b9150614313608087016141ec565b90509295509295909350565b803560ff81168114612e18575f80fd5b5f805f805f805f60e0888a031215614345575f80fd5b873561435081613fea565b96506020880135955060408801359450606088013593506143736080890161431f565b925060a0880135915060c0880135905092959891949750929550565b5f805f80608085870312156143a2575f80fd5b84356143ad81613fea565b9350602085013592506040850135915060608501356143cb81613fea565b939692955090935050565b5f602082840312156143e6575f80fd5b613d5c826141d9565b5f805f805f805f60e0888a031215614405575f80fd5b87359650602088013561441781613fea565b9550604088013561442781613fea565b969995985095966060810135965060808101359560a0820135955060c0909101359350915050565b5f6020828403121561445f575f80fd5b81356001600160701b0381168114613d5c575f80fd5b5f60208284031215614485575f80fd5b8135613d5c816142ab565b5f805f80608085870312156144a3575f80fd5b84356144ae81613fea565b935060208501356144be816142ab565b925060408501356144ce816142ab565b9150606085013561ffff811681146143cb575f80fd5b5f805f805f805f805f805f806101608d8f031215614500575f80fd5b61450a8d35613fea565b8c359b5060208d01359a5060408d0135995060608d0135985061452f60808e0161431f565b975060a08d0135965060c08d0135955061454c60e08e0135613fea565b60e08d013594506001600160401b036101008e0135111561456b575f80fd5b61457c8e6101008f01358f01614009565b909450925061458e6101208e01613ffe565b91506101408d013590509295989b509295989b509295989b565b5f602082840312156145b8575f80fd5b5035919050565b5f805f606084860312156145d1575f80fd5b83356145dc81613fea565b925060208401356145ec81613fea565b915060408401356145fc81613fea565b809150509250925092565b5f805f60608486031215614619575f80fd5b614622846141d9565b9250602084013561463281613fea565b9150614640604085016141ec565b90509250925092565b5f805f805f805f8060e0898b031215614660575f80fd5b883561466b81613fea565b97506020890135965060408901359550606089013561468981613fea565b945060808901356001600160401b038111156146a3575f80fd5b6146af8b828c01614009565b90955093505060a08901356146c381613fea565b8092505060c089013590509295985092959890939650565b5f805f805f608086880312156146ef575f80fd5b6146f886613fd4565b9450602086013561470881613fea565b935060408601356001600160401b03811115614722575f80fd5b61472e88828901614009565b909450925050606086013561474281613fea565b809150509295509295909350565b5f60608284031215614760575f80fd5b613d5c838361412b565b6020808252600c908201526b15539055551213d49256915160a21b604082015260600190565b6020808252600a90820152695245454e5452414e435960b01b604082015260600190565b5f602082840312156147c4575f80fd5b5051919050565b6001600160a01b039586168152938516602085015260408401929092529092166060820152608081019190915260a00190565b634e487b7160e01b5f52601160045260245ffd5b81810381811115611f2957611f296147fe565b6001600160a01b0393841681529190921660208201526001600160e01b0319909116604082015260600190565b5f60208284031215614862575f80fd5b8151613d5c816142ab565b61ffff828116828216039080821115614888576148886147fe565b5092915050565b80820180821115611f2957611f296147fe565b5f6001600160401b038083168181036148bd576148bd6147fe565b6001019392505050565b5f5b838110156148e15781810151838201526020016148c9565b50505f910152565b5f81518084526149008160208601602086016148c7565b601f01601f19169290920160200192915050565b6040815263ffffffff8351166040820152602083015160608201525f604084015160a0608084015261494960e08401826148e9565b90506060850151603f198483030160a085015261496682826148e9565b60809690960151151560c08501525050506001600160a01b039190911660209091015290565b5f6040828403121561499c575f80fd5b604051604081018181106001600160401b03821117156149ca57634e487b7160e01b5f52604160045260245ffd5b604052825181526020928301519281019290925250919050565b5f604082840312156149f4575f80fd5b613d5c838361498c565b5f60808284031215614a0e575f80fd5b604051606081018181106001600160401b0382111715614a3c57634e487b7160e01b5f52604160045260245ffd5b604052825181526020830151614a51816140fc565b6020820152614a63846040850161498c565b60408201529392505050565b61ffff818116838216019080821115614888576148886147fe565b5f8651614a9b818460208b016148c7565b6001600160f81b031960f888811b82169285019283526001600160f01b031960f089901b16600184015286901b1660038201528351614ae18160048401602088016148c7565b01600401979650505050505050565b5f60208284031215614b00575f80fd5b8151613d5c81613fea56fea264697066735822122046a8bb17c7e9a6c35e6267420a3c8a2a80e232243e6573906cc1c2c0ddfe667a64736f6c63430008150033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000005f2f11ad8656439d5c14d9b351f8b09cdac2a02d000000000000000000000000f0bb20865277abd641a307ece5ee04e79073416c0000000000000000000000000d05d94a5f1e76c18fbeb7a13d17c8a314088198000000000000000000000000ee7d8bcfb72bc1880d0cf19822eb0a2e6577ab620000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b0000000000000000000000005f2f11ad8656439d5c14d9b351f8b09cdac2a02d0000000000000000000000000000000000000000000000000000000000000001
-----Decoded View---------------
Arg [0] : _owner (address): 0x5F2F11ad8656439d5C14d9B351f8b09cDaC2A02d
Arg [1] : _vault (address): 0xf0bb20865277aBd641a307eCe5Ee04E79073416C
Arg [2] : _accountant (address): 0x0d05D94a5F1E76C18fbeB7A13d17C8a314088198
Arg [3] : _weth (address): 0xEE7D8BCFb72bC1880D0Cf19822eB0A2e6577aB62
Arg [4] : _lzEndPoint (address): 0x6F475642a6e85809B1c36Fa62763669b1b48DD5B
Arg [5] : _delegate (address): 0x5F2F11ad8656439d5C14d9B351f8b09cDaC2A02d
Arg [6] : _lzToken (address): 0x0000000000000000000000000000000000000001
-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 0000000000000000000000005f2f11ad8656439d5c14d9b351f8b09cdac2a02d
Arg [1] : 000000000000000000000000f0bb20865277abd641a307ece5ee04e79073416c
Arg [2] : 0000000000000000000000000d05d94a5f1e76c18fbeb7a13d17c8a314088198
Arg [3] : 000000000000000000000000ee7d8bcfb72bc1880d0cf19822eb0a2e6577ab62
Arg [4] : 0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b
Arg [5] : 0000000000000000000000005f2f11ad8656439d5c14d9b351f8b09cdac2a02d
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000001
Deployed Bytecode Sourcemap
485:10166:30:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3647:33:33;;;;;;;;;;-1:-1:-1;3647:33:33;;;;-1:-1:-1;;;3647:33:33;;;;;;;;;179:14:38;;172:22;154:41;;142:2;127:18;3647:33:33;;;;;;;;4458:333:31;;;;;;:::i;:::-;;:::i;:::-;;7509:35:33;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;2048:32:38;;;2030:51;;2018:2;2003:18;7509:35:33;1863:224:38;17922:1156:33;;;;;;:::i;:::-;;:::i;:::-;;;2640:25:38;;;2628:2;2613:18;17922:1156:33;2494:177:38;9901:242:33;;;;;;;;;;-1:-1:-1;9901:242:33;;;;;:::i;:::-;;:::i;3998:708:11:-;;;;;;:::i;:::-;;:::i;6209:359:30:-;;;;;;;;;;-1:-1:-1;6209:359:30;;;;;:::i;:::-;;:::i;1321:243:9:-;;;;;;;;;;-1:-1:-1;1321:243:9;;;856:1:12;5102:34:38;;;5167:2;5152:18;;5145:43;5038:18;1321:243:9;4895:299:38;10284:301:33;;;;;;;;;;-1:-1:-1;10284:301:33;;;;;:::i;:::-;;:::i;12212:152::-;;;;;;;;;;-1:-1:-1;12212:152:33;;;;;:::i;:::-;;:::i;12492:155::-;;;;;;;;;;-1:-1:-1;12492:155:33;;;;;:::i;:::-;;:::i;4564:304:30:-;;;;;;;;;;-1:-1:-1;4564:304:30;;;;;:::i;:::-;;:::i;11155:140:33:-;;;;;;;;;;-1:-1:-1;11155:140:33;;;;;:::i;:::-;;:::i;1720:111:10:-;;;;;;;;;;-1:-1:-1;1720:111:10;;;;;:::i;:::-;;:::i;3622:554:30:-;;;;;;;;;;-1:-1:-1;3622:554:30;;;;;:::i;:::-;;:::i;11686:134:33:-;;;;;;;;;;-1:-1:-1;11686:134:33;;;;;:::i;:::-;;:::i;19201:646::-;;;;;;;;;;-1:-1:-1;19201:646:33;;;;;:::i;:::-;;:::i;20566:818::-;;;;;;;;;;-1:-1:-1;20566:818:33;;;;;:::i;:::-;;:::i;8452:99::-;;;;;;;;;;;;;:::i;3002:40::-;;;;;;;;;;-1:-1:-1;3002:40:33;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8689:14:38;;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;3002:40:33;8476:350:38;5885:208:30;;;;;;;;;;-1:-1:-1;5885:208:30;;;;;:::i;:::-;;:::i;16367:1302:33:-;;;;;;;;;;-1:-1:-1;16367:1302:33;;;;;:::i;:::-;;:::i;7283:55::-;;;;;;;;;;;;;;;4284:178:30;;;;;;;;;;-1:-1:-1;4284:178:30;;;;;:::i;:::-;;:::i;4296:64:33:-;;;;;;;;;;-1:-1:-1;4296:64:33;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10261:14:38;;10254:22;10236:41;;10320:14;;10313:22;10308:2;10293:18;;10286:50;10379:14;;10372:22;10352:18;;;10345:50;;;;10438:14;;10431:22;10426:2;10411:18;;10404:50;10485:3;10470:19;;10463:35;10223:3;10208:19;4296:64:33;10001:503:38;442:46:10;;;;;;;;;;;;;;;11942:137:33;;;;;;;;;;-1:-1:-1;11942:137:33;;;;;:::i;:::-;;:::i;1523:434:22:-;;;;;;;;;;-1:-1:-1;1523:434:22;;;;;:::i;:::-;;:::i;13817:126:33:-;;;;;;;;;;-1:-1:-1;13817:126:33;;;;;:::i;:::-;;:::i;3136:129:11:-;;;;;;;;;;-1:-1:-1;3136:129:11;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;11479:31:38;;;11461:50;;11449:2;11434:18;3136:129:11;11317:200:38;8195:94:33;;;;;;;;;;;;;:::i;12757:211::-;;;;;;;;;;-1:-1:-1;12757:211:33;;;;;:::i;:::-;;:::i;562:20:22:-;;;;;;;;;;-1:-1:-1;562:20:22;;;;-1:-1:-1;;;;;562:20:22;;;8768:426:33;;;;;;;;;;-1:-1:-1;8768:426:33;;;;;:::i;:::-;;:::i;2956:1113:31:-;;;;;;:::i;:::-;;:::i;4082:55:33:-;;;;;;;;;;-1:-1:-1;4082:55:33;;;;;:::i;:::-;;;;;;;;;;;;;;13133:198;;;;;;;;;;-1:-1:-1;13133:198:33;;;;;:::i;:::-;;:::i;20018:421::-;;;;;;;;;;-1:-1:-1;20018:421:33;;;;;:::i;:::-;;:::i;3406:29::-;;;;;;;;;;-1:-1:-1;3406:29:33;;;;-1:-1:-1;;;3406:29:33;;-1:-1:-1;;;;;3406:29:33;;;11418:143;;;;;;;;;;-1:-1:-1;11418:143:33;;;;;:::i;:::-;;:::i;14546:602::-;;;;;;;;;;-1:-1:-1;14546:602:33;;;;;:::i;:::-;;:::i;3531:20::-;;;;;;;;;;-1:-1:-1;3531:20:33;;;;-1:-1:-1;;;3531:20:33;;;;;;4968:497:30;;;;;;;;;;-1:-1:-1;4968:497:30;;;;;:::i;:::-;;:::i;1748:110:11:-;;;;;;;;;;-1:-1:-1;1846:4:11;1748:110;;565:48:10;;;;;;;;;;-1:-1:-1;565:48:10;;;;;:::i;:::-;;;;;;;;;;;;;;13513:197:33;;;;;;;;;;-1:-1:-1;13513:197:33;;;;;:::i;:::-;;:::i;589:26:22:-;;;;;;;;;;-1:-1:-1;589:26:22;;;;-1:-1:-1;;;;;589:26:22;;;10719:308:33;;;;;;;;;;-1:-1:-1;10719:308:33;;;;;:::i;:::-;;:::i;3251:108:10:-;;;;;;;;;;-1:-1:-1;3251:108:10;;;;;:::i;:::-;;:::i;1569:912:31:-;;;;;;:::i;:::-;;:::i;1459:42:30:-;;;;;;;;;;-1:-1:-1;1459:42:30;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1459:42:30;;;;;;;16754:14:38;;16747:22;16729:41;;16813:14;;16806:22;16801:2;16786:18;;16779:50;-1:-1:-1;;;;;16865:47:38;16845:18;;;16838:75;16717:2;16702:18;1459:42:30;16539:380:38;5569:214:30;;;;;;;;;;-1:-1:-1;5569:214:30;;;;;:::i;:::-;;:::i;4887:357:31:-;;;;;;;;;;-1:-1:-1;4887:357:31;;;;;:::i;:::-;;:::i;3840:45:33:-;;;;;;;;;;-1:-1:-1;3840:45:33;;;;-1:-1:-1;;;3840:45:33;;-1:-1:-1;;;;;3840:45:33;;;;;;-1:-1:-1;;;;;17865:43:38;;;17847:62;;17835:2;17820:18;3840:45:33;17701:214:38;3129:26:33;;;;;;;;;;-1:-1:-1;3129:26:33;;;;-1:-1:-1;;;;;3129:26:33;;;15286:369;;;;;;;;;;-1:-1:-1;15286:369:33;;;;;:::i;:::-;;:::i;1963:164:22:-;;;;;;;;;;-1:-1:-1;1963:164:22;;;;;:::i;:::-;;:::i;7148:34:33:-;;;;;;;;;;;;;;;2400:149:11;;;;;;;;;;-1:-1:-1;2400:149:11;;;;;:::i;:::-;;:::i;4458:333:31:-;902:33:22;915:10;927:7;;-1:-1:-1;;;;;;927:7:22;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:22;;;;;;;:::i;:::-;;;;;;;;;512:6:26::1;;522:1;512:11;504:34;;;;-1:-1:-1::0;;;504:34:26::1;;;;;;;:::i;:::-;558:1;549:10:::0;;4662:8:31::2;::::0;-1:-1:-1;;;4662:8:31;::::2;;;4658:58;;;4679:37;;-1:-1:-1::0;;;4679:37:31::2;;;;;;;;;;;4658:58;4726;4734:11;4747:2;4751:14;;4767:8;4777:6;4726:7;:58::i;:::-;-1:-1:-1::0;;591:1:26::1;582:6;:10:::0;-1:-1:-1;;;;4458:333:31:o;17922:1156:33:-;18095:14;902:33:22;915:10;927:7;;-1:-1:-1;;;;;;927:7:22;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:22;;;;;;;:::i;:::-;512:6:26::1;;522:1;512:11;504:34;;;;-1:-1:-1::0;;;504:34:26::1;;;;;;;:::i;:::-;558:1;549:10:::0;;18125:18:33::2;18146:28;18161:12:::0;18146:14:::2;:28::i;:::-;18125:49:::0;-1:-1:-1;18185:12:33::2;-1:-1:-1::0;;;;;;;18211:31:33;::::2;::::0;18207:670:::2;;18262:9;18275:1;18262:14:::0;18258:68:::2;;18285:41;;-1:-1:-1::0;;;18285:41:33::2;;;;;;;;;;;18258:68;18340:13;-1:-1:-1::0;;;;;18340:21:33::2;;18369:9;18340:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;-1:-1:-1::0;18458:9:33::2;::::0;-1:-1:-1;18481:56:33::2;::::0;-1:-1:-1;;;;;;;18481:13:33::2;:25;::::0;-1:-1:-1;18515:5:33::2;::::0;-1:-1:-1;18458:9:33;18481:25:::2;:56::i;:::-;-1:-1:-1::0;18619:13:33::2;::::0;-1:-1:-1;18731:4:33::2;18207:670;;;18771:9;:13:::0;18767:68:::2;;18793:42;;-1:-1:-1::0;;;18793:42:33::2;;;;;;;;;;;18767:68;-1:-1:-1::0;18856:10:33::2;18207:670;18896:80;18910:12;18924:13;18939:11;18952:4;18958:10;18970:5;18896:13;:80::i;:::-;18887:89;;18986:85;19006:10;19018:12;19032:13;19047:6;19055:15;;;;;;;;;-1:-1:-1::0;;;;;19055:15:33::2;-1:-1:-1::0;;;;;18986:85:33::2;:19;:85::i;:::-;-1:-1:-1::0;;591:1:26::1;582:6;:10:::0;17922:1156:33;;-1:-1:-1;;;17922:1156:33:o;9901:242::-;902:33:22;915:10;927:7;;-1:-1:-1;;;;;;927:7:22;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:22;;;;;;;:::i;:::-;2636:6:33::1;9990:16;-1:-1:-1::0;;;;;9990:40:33::1;;9986:106;;;10039:53;;-1:-1:-1::0;;;10039:53:33::1;;;;;;;;;;;9986:106;10102:15;:34:::0;;-1:-1:-1;;;;;10102:34:33;;::::1;-1:-1:-1::0;;;10102:34:33::1;-1:-1:-1::0;;10102:34:33;;::::1;::::0;;;::::1;::::0;;9901: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;;;2030:51:38;2003:18;;4343:24:11;1863:224:38;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;;19278:10:38;19266:23;;;4526:40:11;;;19248:42:38;4551:14:11;;;;19306:18:38;;;19299:34;19221:18;;4526:40:11;19076:263:38;4463:103:11;4640:59;4651:7;4660:5;4667:8;;4677:9;4688:10;;4640;:59::i;:::-;3998:708;;;;;;;:::o;6209:359:30:-;902:33:22;915:10;927:7;;-1:-1:-1;;;;;;927:7:22;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:22;;;;;;;:::i;:::-;6312:15:30::1;-1:-1:-1::0;;;;;6312:20:30::1;6331:1;6312:20:::0;6308:96:::1;;6355:38;;-1:-1:-1::0;;;6355:38:30::1;;;;;;;;;;;6308:96;6435:19;::::0;::::1;6413;6435::::0;;;:10:::1;:19;::::0;;;;;;;;6464:39;;-1:-1:-1;;;;;;6464:39:30::1;::::0;-1:-1:-1;;;;;6464:39:30;::::1;::::0;;::::1;::::0;;;::::1;::::0;;6519:42;;19517::38;;;19575:18;;;19568:75;;;;6435:19:30;6519:42:::1;::::0;19490:18:38;6519:42:30::1;;;;;;;;6298:270;6209:359:::0;;:::o;10284:301:33:-;902:33:22;915:10;927:7;;-1:-1:-1;;;;;;927:7:22;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:22;;;;;;;:::i;:::-;-1:-1:-1;;;;;10347:24:33;::::1;;::::0;;;:18:::1;:24;::::0;;;;;:40;;-1:-1:-1;;10445:44:33;;;;;10504:14;::::1;::::0;10347:24;10504:14:::1;10533:12;::::0;-1:-1:-1;;;;;10533:12:33;::::1;::::0;::::1;::::0;;;::::1;10560:18;::::0;-1:-1:-1;;;;;10560:18:33;::::1;::::0;::::1;::::0;;;::::1;10284:301:::0;:::o;12212:152::-;902:33:22;915:10;927:7;;-1:-1:-1;;;;;;927:7:22;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:22;;;;;;;:::i;:::-;-1:-1:-1;;;;;12280:24:33;::::1;;::::0;;;:18:::1;:24;::::0;;;;;:44;;-1:-1:-1;;12280:44:33::1;::::0;::::1;::::0;;12339:18;::::1;::::0;12280:24;12339:18:::1;12212:152:::0;:::o;12492:155::-;902:33:22;915:10;927:7;;-1:-1:-1;;;;;;927:7:22;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:22;;;;;;;:::i;:::-;-1:-1:-1;;;;;12561:24:33;::::1;12601:5;12561:24:::0;;;:18:::1;:24;::::0;;;;;:45;;-1:-1:-1;;12561:45:33::1;::::0;;12621:19;::::1;::::0;12601:5;12621:19:::1;12492:155:::0;:::o;4564:304:30:-;902:33:22;915:10;927:7;;-1:-1:-1;;;;;;927:7:22;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:22;;;;;;;:::i;:::-;4688:19:30::1;::::0;::::1;4666;4688::::0;;;:10:::1;:19;::::0;;;;4717:30;;-1:-1:-1;;4717:30:30::1;4743:4;4717:30;::::0;;4757:43:::1;4688:19:::0;-1:-1:-1;;;;;4775:22:30;::::1;4757:8;:43::i;:::-;4816:45;::::0;;19857:10:38;19845:23;;19827:42;;-1:-1:-1;;;;;19905:32:38;;19900:2;19885:18;;19878:60;4816:45:30::1;::::0;19800:18:38;4816:45:30::1;19654:290:38::0;11155:140:33;902:33:22;915:10;927:7;;-1:-1:-1;;;;;;927:7:22;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:22;;;;;;;:::i;:::-;-1:-1:-1;;;;;11219:24:33;::::1;;::::0;;;:18:::1;:24;::::0;;;;;:40;;-1:-1:-1;;11219:40:33::1;11255:4;11219:40;::::0;;11274:14;::::1;::::0;11219:24;11274:14:::1;11155:140:::0;:::o;1720:111:10:-;902:33:22;915:10;927:7;;-1:-1:-1;;;;;;927:7:22;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:22;;;;;;;:::i;:::-;1803:21:10::1;1812:4;1818:5;1803:8;:21::i;:::-;1720:111:::0;;:::o;3622:554:30:-;902:33:22;915:10;927:7;;-1:-1:-1;;;;;;927:7:22;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:22;;;;;;;:::i;:::-;3831:15:30::1;:39;;;;-1:-1:-1::0;;;;;;3850:20:30;::::1;::::0;3831:39:::1;3827:115;;;3893:38;;-1:-1:-1::0;;;3893:38:30::1;;;;;;;;;;;3827:115;3973:58;::::0;;::::1;::::0;::::1;::::0;;;::::1;;::::0;;;::::1;;;::::0;;::::1;::::0;;;-1:-1:-1;;;;;3973:58:30;;::::1;::::0;;;;;;3951:19:::1;::::0;::::1;-1:-1:-1::0;3951:19:30;;;:10:::1;:19:::0;;;;;;;:80;;;;;;;;-1:-1:-1;;3951:80:30;;;;::::1;;-1:-1:-1::0;;3951:80:30;;::::1;::::0;::::1;;::::0;;;::::1;::::0;;;::::1;-1:-1:-1::0;;;;;;3951:80:30::1;::::0;;;;::::1;;::::0;;;::::1;::::0;;4041:43:::1;3951:19:::0;-1:-1:-1;;;;;4059:22:30;::::1;4757:8;:43::i;4041:::-;4100:69;::::0;;20197:10:38;20185:23;;20167:42;;20252:14;;20245:22;20240:2;20225:18;;20218:50;20311:14;;20304:22;20284:18;;;20277:50;-1:-1:-1;;;;;20363:32:38;;20358:2;20343:18;;20336:60;4100:69:30;;::::1;::::0;;;;20154:3:38;4100:69:30;;::::1;3622:554:::0;;;;;:::o;11686:134:33:-;902:33:22;915:10;927:7;;-1:-1:-1;;;;;;927:7:22;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:22;;;;;;;:::i;:::-;-1:-1:-1;;;;;11748:24:33;::::1;;::::0;;;:18:::1;:24;::::0;;;;;:38;;-1:-1:-1;;11748:38:33::1;;;::::0;;11801:12;::::1;::::0;11748:24;11801:12:::1;11686:134:::0;:::o;19201:646::-;19492:14;902:33:22;915:10;927:7;;-1:-1:-1;;;;;;927:7:22;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:22;;;;;;;:::i;:::-;512:6:26::1;;522:1;512:11;504:34;;;;-1:-1:-1::0;;;504:34:26::1;;;;;;;:::i;:::-;558:1;549:10:::0;;19468:12:33;-1:-1:-1;;;;;;;6884:22:33;::::2;::::0;6880:85:::2;;6915:50;;-1:-1:-1::0;;;6915:50:33::2;;;;;;;;;;;6880:85;19518:18:::3;19539:28;19554:12;19539:14;:28::i;:::-;19518:49;;19578:61;19592:12;19606:13;19621:8;19631:1;19634;19637;19578:13;:61::i;:::-;19659:86;19673:12;19687:13;19702:11;19715:10;19727;19739:5;19659:13;:86::i;:::-;19650:95;;19755:85;19775:10;19787:12;19801:13;19816:6;19824:15;;;;;;;;;-1:-1:-1::0;;;;;19824:15:33::3;-1:-1:-1::0;;;;;19755:85:33::3;:19;:85::i;:::-;-1:-1:-1::0;;591:1:26::1;582:6;:10:::0;19201:646:33;;-1:-1:-1;;;;;;;19201:646:33:o;20566:818::-;20720:17;902:33:22;915:10;927:7;;-1:-1:-1;;;;;;927:7:22;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:22;;;;;;;:::i;:::-;20757:8:33::1;::::0;-1:-1:-1;;;20757:8:33;::::1;;;20753:58;;;20774:37;;-1:-1:-1::0;;;20774:37:33::1;;;;;;;;;;;20753:58;-1:-1:-1::0;;;;;20842:24:33;::::1;20821:18;20842:24:::0;;;:9:::1;:24;::::0;;;;;;;;20821:45;;::::1;::::0;::::1;::::0;;;;::::1;::::0;;::::1;;;::::0;;::::1;::::0;::::1;;;;::::0;;::::1;::::0;;;;;::::1;;;::::0;;;;;;;20876:82:::1;;20910:48;;-1:-1:-1::0;;;20910:48:33::1;;;;;;;;;;;20876:82;20973:11;20988:1;20973:16:::0;20969:70:::1;;20998:41;;-1:-1:-1::0;;;20998:41:33::1;;;;;;;;;;;20969:70;21084:44;::::0;-1:-1:-1;;;21084:44:33;;-1:-1:-1;;;;;2048:32:38;;;21084:44:33::1;::::0;::::1;2030:51:38::0;21061:79:33::1;::::0;21084:10:::1;:29:::0;;::::1;::::0;::::1;::::0;2003:18:38;;21084:44:33::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;21061:11:::0;;21130:9:::1;21061:22;:79::i;:::-;21049:91;;21166:13;21154:9;:25;21150:88;;;21188:50;;-1:-1:-1::0;;;21188:50:33::1;;;;;;;;;;;21150:88;21248:65;::::0;-1:-1:-1;;;21248:65:33;;-1:-1:-1;;;;;21248:5:33::1;:10;::::0;::::1;::::0;:65:::1;::::0;21259:2;;21263:13;;21278:9;;21289:10:::1;::::0;21301:11;;21248:65:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;21349:13;-1:-1:-1::0;;;;;21328:49:33::1;;21365:11;21328:49;;;;2640:25:38::0;;2628:2;2613:18;;2494:177;21328:49:33::1;;;;;;;;20743:641;20566:818:::0;;;;;;:::o;8452:99::-;902:33:22;915:10;927:7;;-1:-1:-1;;;;;;927:7:22;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:22;;;;;;;:::i;:::-;8503:8:33::1;:16:::0;;-1:-1:-1;;;;8503:16:33::1;::::0;;8534:10:::1;::::0;::::1;::::0;8514:5:::1;::::0;8534:10:::1;8452:99::o:0;5885:208:30:-;902:33:22;915:10;927:7;;-1:-1:-1;;;;;;927:7:22;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:22;;;;;;;:::i;:::-;5984:19:30::1;::::0;::::1;5962;5984::::0;;;:10:::1;:19;::::0;;;;;;;;6013:29;;-1:-1:-1;;6013:29:30::1;::::0;;6058:28;;21510:42:38;;;5984:19:30;;6058:28:::1;::::0;21483:18:38;6058:28:30::1;;;;;;;;5952:141;5885:208:::0;:::o;16367:1302:33:-;902:33:22;915:10;927:7;;-1:-1:-1;;;;;;927:7:22;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:22;;;;;;;:::i;:::-;16695:32:33;16656:34:::1;16674:16:::0;16656:15:::1;:34;:::i;:::-;16655:72;16651:232;;16824:48;;-1:-1:-1::0;;;16824:48:33::1;;;;;;;;;;;16651:232;16937:144;::::0;;-1:-1:-1;;;;;22171:15:38;;;16937:144:33::1;::::0;::::1;22153:34:38::0;22223:15;;22203:18;;;22196:43;;;;22255:18;;;22248:34;;;22298:18;;;22291:34;;;22341:19;;;22334:35;;;22385:19;;;22378:35;;;16892:19:33::1;::::0;22087::38;;16937:144:33::1;::::0;;-1:-1:-1;;16937:144:33;;::::1;::::0;;;;;;16914:177;;16937:144:::1;16914:177:::0;;::::1;::::0;17105:27:::1;::::0;;;:20:::1;:27:::0;;;;;;16914:177;;-1:-1:-1;17105:42:33;::::1;17101:100;;17156:45;;-1:-1:-1::0;;;17156:45:33::1;;;;;;;;;;;17101:100;17265:27;::::0;;;:20:::1;:27;::::0;;;;17258:34;-1:-1:-1;;;;;17396:22:33;::::1;2466:42;17396:22;:62;;17446:12;17396:62;;;17429:13;17396:62;17522:79;::::0;-1:-1:-1;;;17522:79:33;;17381:77;;-1:-1:-1;;;;;;17522:5:33::1;:10;::::0;::::1;::::0;:79:::1;::::0;17533:8;;17381:77;;17564:13;;17533:8;;17589:11;;17522:79:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;17653:8;-1:-1:-1::0;;;;;17617:45:33::1;17633:5;17617:45;17640:11;17617:45;;;;2640:25:38::0;;2628:2;2613:18;;2494:177;17617:45:33::1;;;;;;;;16641:1028;16367:1302:::0;;;;;;;:::o;4284:178:30:-;902:33:22;915:10;927:7;;-1:-1:-1;;;;;;927:7:22;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:22;;;;;;;:::i;:::-;4360:19:30::1;::::0;::::1;;::::0;;;:10:::1;:19;::::0;;;;4353:26;;-1:-1:-1;;4353:26:30;;;4389:29:::1;::::0;4371:7;;4389:8:::1;:29::i;:::-;4434:21;::::0;21540:10:38;21528:23;;21510:42;;4434:21:30::1;::::0;21498:2:38;21483:18;4434:21:30::1;;;;;;;;4284:178:::0;:::o;11942:137:33:-;902:33:22;915:10;927:7;;-1:-1:-1;;;;;;927:7:22;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:22;;;;;;;:::i;:::-;-1:-1:-1;;;;;12005:24:33;::::1;12039:5;12005:24:::0;;;:18:::1;:24;::::0;;;;;:39;;-1:-1:-1;;12005:39:33::1;::::0;;12059:13;::::1;::::0;12039:5;12059:13:::1;11942:137:::0;:::o;1523:434:22:-;1794:5;;-1:-1:-1;;;;;1794:5:22;1780:10;:19;;:76;;-1:-1:-1;1803:9:22;;:53;;-1:-1:-1;;;1803:53:22;;-1:-1:-1;;;;;1803:9:22;;;;:17;;:53;;1821:10;;1841:4;;-1:-1:-1;;;;;;1803:9:22;1848:7;;;1803:53;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1772:85;;;;;;1868:9;:24;;-1:-1:-1;;;;;;1868:24:22;-1:-1:-1;;;;;1868:24:22;;;;;;;;1908:42;;1925:10;;1908:42;;-1:-1:-1;;1908:42:22;1523:434;:::o;13817:126:33:-;902:33:22;915:10;927:7;;-1:-1:-1;;;;;;927:7:22;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:22;;;;;;;:::i;:::-;13885:10:33::1;:16:::0;;;::::1;-1:-1:-1::0;;;;;;;;13885:16:33;::::1;::::0;;::::1;::::0;;;::::1;::::0;;;13917:18:::1;::::0;17847:62:38;;;13917:18:33::1;::::0;17835:2:38;17820:18;13917::33::1;17701:214:38::0;3136:129:11;3226:12;3136:129;;;;;:::o;8195:94:33:-;902:33:22;915:10;927:7;;-1:-1:-1;;;;;;927:7:22;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:22;;;;;;;:::i;:::-;8244:8:33::1;:15:::0;;-1:-1:-1;;;;8244:15:33::1;-1:-1:-1::0;;;8244:15:33::1;::::0;;8274:8:::1;::::0;::::1;::::0;8244:15;;8274:8:::1;8195:94::o:0;12757:211::-;902:33:22;915:10;927:7;;-1:-1:-1;;;;;;927:7:22;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:22;;;;;;;:::i;:::-;12852:21:33::1;:46:::0;;;::::1;;-1:-1:-1::0;;;12852:46:33::1;-1:-1:-1::0;;;;12852:46:33;;::::1;;::::0;;12913:48:::1;::::0;::::1;::::0;::::1;::::0;12876:22;179:14:38;172:22;154:41;;142:2;127:18;;14:187;8768:426:33;902:33:22;915:10;927:7;;-1:-1:-1;;;;;;927:7:22;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:22;;;;;;;:::i;:::-;2826:5:33::1;8924:32;::::0;::::1;;8920:96;;;8965:51;;-1:-1:-1::0;;;8965:51:33::1;;;;;;;;;;;8920:96;9045:50;::::0;;::::1;::::0;;::::1;::::0;;;::::1;;::::0;;;;::::1;;;::::0;;::::1;::::0;;;::::1;::::0;;::::1;::::0;;;;;;-1:-1:-1;;;;;9026:16:33;::::1;-1:-1:-1::0;9026:16:33;;;:9:::1;:16:::0;;;;;:69;;;;;;;;-1:-1:-1;;9026:69:33;;;;::::1;;-1:-1:-1::0;;9026:69:33;;::::1;::::0;::::1;;::::0;;;::::1;::::0;;;::::1;-1:-1:-1::0;;9026:69:33::1;::::0;;;;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;;9110:77;;8664:41:38;;;8721:18;;;8714:50;;;;8780:18;;;8773:47;;;;9110:77:33::1;::::0;8637:18:38;9110:77:33::1;;;;;;;8768:426:::0;;;;:::o;2956:1113:31:-;3419:21;902:33:22;915:10;927:7;;-1:-1:-1;;;;;;927:7:22;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:22;;;;;;;:::i;:::-;512:6:26::1;;522:1;512:11;504:34;;;;-1:-1:-1::0;;;504:34:26::1;;;;;;;:::i;:::-;558:1;549:10:::0;;3387:12:31;-1:-1:-1;;;;;;;6884:22:33;::::2;::::0;6880:85:::2;;6915:50;;-1:-1:-1::0;;;6915:50:33::2;;;;;;;;;;;6880:85;3496:18:31::3;3517:28;3532:12;3517:14;:28::i;:::-;3496:49;;3559:61;3573:12;3587:13;3602:8;3612:1;3615;3618;3559:13;:61::i;:::-;3650:86;3664:12;3678:13;3693:11;3706:10;3718;3730:5;3650:13;:86::i;:::-;3634:102;;3482:265;3756:92;3776:10;3788:12;3802:13;3817;3832:15;;;;;;;;;-1:-1:-1::0;;;;;3832:15:31::3;-1:-1:-1::0;;;;;3756:92:31::3;:19;:92::i;:::-;-1:-1:-1::0;;;;;3888:32:31;::::3;3884:100;;;3929:55;;-1:-1:-1::0;;;3929:55:31::3;;;;;;;;;;;3884:100;3994:68;4009:13;4025:2;4029:14;;4045:8;4055:6;3994:7;:68::i;:::-;-1:-1:-1::0;591:1:26::1;582:6;:10:::0;2956:1113:31;;-1:-1:-1;;;;;;;;;;;;2956:1113:31:o;13133:198:33:-;902:33:22;915:10;927:7;;-1:-1:-1;;;;;;927:7:22;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:22;;;;;;;:::i;:::-;-1:-1:-1;;;;;13218:28:33;::::1;;::::0;;;:18:::1;:28;::::0;;;;;:56;;-1:-1:-1;;13218:56:33::1;::::0;::::1;::::0;;13289:35;::::1;::::0;13218:28;13289:35:::1;13133:198:::0;:::o;20018:421::-;20191:14;902:33:22;915:10;927:7;;-1:-1:-1;;;;;;927:7:22;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:22;;;;;;;:::i;:::-;512:6:26::1;;522:1;512:11;504:34;;;;-1:-1:-1::0;;;504:34:26::1;;;;;;;:::i;:::-;558:1;549:10:::0;;20221:18:33::2;20242:28;20257:12:::0;20242:14:::2;:28::i;:::-;20221:49;;20290:78;20304:12;20318:13;20333:11;20346:10;20358:2;20362:5;20290:13;:78::i;:::-;20281:87;;20403:12;-1:-1:-1::0;;;;;20383:49:33::2;;20418:13;20383:49;;;;2640:25:38::0;;2628:2;2613:18;;2494:177;20383:49:33::2;;;;;;;;-1:-1:-1::0;591:1:26::1;582:6;:10:::0;20018:421:33;;-1:-1:-1;;;;20018:421:33:o;11418:143::-;902:33:22;915:10;927:7;;-1:-1:-1;;;;;;927:7:22;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:22;;;;;;;:::i;:::-;-1:-1:-1;;;;;11483:24:33;::::1;11519:5;11483:24:::0;;;:18:::1;:24;::::0;;;;;:41;;-1:-1:-1;;11483:41:33::1;::::0;;11539:15;::::1;::::0;11519:5;11539:15:::1;11418:143:::0;:::o;14546:602::-;-1:-1:-1;;;;;14661:24:33;;;;;;:18;:24;;;;;:33;;;;:66;;-1:-1:-1;;;;;;14698:22:33;;;;;;:18;:22;;;;;:29;;;;;;14661:66;:127;;;-1:-1:-1;;;;;;14747:28:33;;;;;;:18;:28;;;;;:41;;;;;;14661:127;:224;;;-1:-1:-1;14809:21:33;;-1:-1:-1;;;14809:21:33;;;;:75;;;;-1:-1:-1;;;;;;14835:28:33;;;;;;:18;:28;;;;;:49;;;;;;14834:50;14809:75;14644:347;;;14917:63;;-1:-1:-1;;;14917:63:33;;-1:-1:-1;;;;;23337:15:38;;;14917:63:33;;;23319:34:38;23389:15;;;23369:18;;;23362:43;23441:15;;23421:18;;;23414:43;23254:18;;14917:63:33;23079:384:38;14644:347:33;-1:-1:-1;;;;;15004:24:33;;;;;;:18;:24;;;;;:40;;;15047:15;-1:-1:-1;15000:142:33;;;15085:46;;-1:-1:-1;;;15085:46:33;;;;;;;;;;;15000:142;14546:602;;;:::o;4968:497:30:-;902:33:22;915:10;927:7;;-1:-1:-1;;;;;;927:7:22;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:22;;;;;;;:::i;:::-;5117:15:30::1;-1:-1:-1::0;;;;;5117:20:30::1;5136:1;5117:20:::0;5113:96:::1;;5160:38;;-1:-1:-1::0;;;5160:38:30::1;;;;;;;;;;;5113:96;5240:19;::::0;::::1;5218;5240::::0;;;:10:::1;:19;::::0;;;;5269:28;;::::1;-1:-1:-1::0;;5307:39:30;;;;-1:-1:-1;;;;;5307:39:30;::::1;;::::0;;;;5356:43:::1;5240:19:::0;-1:-1:-1;;;;;5374:22:30;::::1;4757:8;:43::i;5356:::-;5415;::::0;;19857:10:38;19845:23;;19827:42;;-1:-1:-1;;;;;19905:32:38;;19900:2;19885:18;;19878:60;5415:43:30::1;::::0;19800:18:38;5415:43:30::1;;;;;;;5103:362;4968:497:::0;;;:::o;13513:197:33:-;902:33:22;915:10;927:7;;-1:-1:-1;;;;;;927:7:22;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:22;;;;;;;:::i;:::-;-1:-1:-1;;;;;13597:28:33;::::1;13649:5;13597:28:::0;;;:18:::1;:28;::::0;;;;;:57;;-1:-1:-1;;13597:57:33::1;::::0;;13669:34;::::1;::::0;13649:5;13669:34:::1;13513:197:::0;:::o;10719:308::-;902:33:22;915:10;927:7;;-1:-1:-1;;;;;;927:7:22;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:22;;;;;;;:::i;:::-;-1:-1:-1;;;;;10783:24:33;::::1;10819:5;10783:24:::0;;;:18:::1;:24;::::0;;;;;:41;;-1:-1:-1;;10883:45:33;;;10943:15;::::1;::::0;10819:5;10943:15:::1;10973:13;::::0;-1:-1:-1;;;;;10973:13:33;::::1;::::0;::::1;::::0;;;::::1;11001:19;::::0;-1:-1:-1;;;;;11001:19:33;::::1;::::0;::::1;::::0;;;::::1;10719:308:::0;:::o;3251:108:10:-;902:33:22;915:10;927:7;;-1:-1:-1;;;;;;927:7:22;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:22;;;;;;;:::i;:::-;3321:31:10::1;::::0;-1:-1:-1;;;3321:31:10;;-1:-1:-1;;;;;2048:32:38;;;3321:31:10::1;::::0;::::1;2030:51:38::0;3321:8:10::1;:20;::::0;::::1;::::0;2003:18:38;;3321:31:10::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;3251:108:::0;:::o;1569:912:31:-;1941:21;902:33:22;915:10;927:7;;-1:-1:-1;;;;;;927:7:22;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:22;;;;;;;:::i;:::-;512:6:26::1;;522:1;512:11;504:34;;;;-1:-1:-1::0;;;504:34:26::1;;;;;;;:::i;:::-;558:1;549:10:::0;;1909:12:31;-1:-1:-1;;;;;;;6884:22:33;::::2;::::0;6880:85:::2;;6915:50;;-1:-1:-1::0;;;6915:50:33::2;;;;;;;;;;;6880:85;1997:18:31::3;2018:28;2033:12;2018:14;:28::i;:::-;1997:49;;2072:86;2086:12;2100:13;2115:11;2128:10;2140;2152:5;2072:13;:86::i;:::-;2056:102;;2168:92;2188:10;2200:12;2214:13;2229;2244:15;;;;;;;;;-1:-1:-1::0;;;;;2244:15:31::3;-1:-1:-1::0;;;;;2168:92:31::3;:19;:92::i;:::-;-1:-1:-1::0;;;;;2300:32:31;::::3;2296:100;;;2341:55;;-1:-1:-1::0;;;2341:55:31::3;;;;;;;;;;;2296:100;2406:68;2421:13;2437:2;2441:14;;2457:8;2467:6;2406:7;:68::i;:::-;-1:-1:-1::0;;591:1:26::1;582:6;:10:::0;1569:912:31;;-1:-1:-1;;;;;;;;1569:912:31:o;5569:214:30:-;902:33:22;915:10;927:7;;-1:-1:-1;;;;;;927:7:22;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:22;;;;;;;:::i;:::-;5670:19:30::1;::::0;::::1;5648;5670::::0;;;:10:::1;:19;::::0;;;;;;;;5699:31;;-1:-1:-1;;5699:31:30::1;::::0;;5746:30;;21510:42:38;;;5670:19:30;;5746:30:::1;::::0;21483:18:38;5746:30:30::1;21365:193:38::0;4887:357:31;5090:35;;;;;;;;;-1:-1:-1;;;;;5090:35:31;;;;-1:-1:-1;;;;;5090:35:31;;;;;;5033:11;;;5153:20;5090:35;5153:18;:20::i;:::-;5135:38;;5191:46;5203:7;5212:14;;5228:8;5191:11;:46::i;:::-;5184:53;4887:357;-1:-1:-1;;;;;;;;4887:357:31:o;15286:369:33:-;-1:-1:-1;;;;;15358:24:33;;;;;;:18;:24;;;;;:33;;;15354:144;;;15414:73;;-1:-1:-1;;;15414:73:33;;-1:-1:-1;;;;;23337:15:38;;15414:73:33;;;23319:34:38;15472:1:33;23369:18:38;;;23362:43;;;23421:18;;;23414:43;23254:18;;15414:73:33;23079:384:38;15354:144:33;-1:-1:-1;;;;;15511:24:33;;;;;;:18;:24;;;;;:40;;;15554:15;-1:-1:-1;15507:142:33;;;15592:46;;-1:-1:-1;;;15592:46:33;;;;;;;;;;;15507:142;15286:369;:::o;1963:164:22:-;902:33;915:10;927:7;;-1:-1:-1;;;;;;927:7:22;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:22;;;;;;;:::i;:::-;2046:5:::1;:16:::0;;-1:-1:-1;;;;;;2046:16:22::1;-1:-1:-1::0;;;;;2046:16:22;::::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:22:-;1097:9;;1064:4;;-1:-1:-1;;;;;1097:9:22;1415:27;;;;;:77;;-1:-1:-1;1446:46:22;;-1:-1:-1;;;1446:46:22;;-1:-1:-1;;;;;1446:12:22;;;;;:46;;1459:4;;1473;;1480:11;;1446:46;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1414:96;;;-1:-1:-1;1505:5:22;;-1:-1:-1;;;;;1497:13:22;;;1505:5;;1497:13;1414:96;1407:103;977:540;-1:-1:-1;;;;977:540:22:o;5427:850:31:-;5671:50;5686:10;5706:1;5710:10;5671:14;:50::i;:::-;5767:69;;-1:-1:-1;;;5767:69:31;;5786:1;5767:69;;;23786:34:38;;;23836:18;;;23829:43;;;23888:18;;;23881:34;5812:10:31;23931:18:38;;;23924:43;-1:-1:-1;;;;;24004:39:38;;23983:19;;;23976:68;5767:5:31;-1:-1:-1;;;;;5767:10:31;;;;23720:19:38;;5767:69:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;5906:35:31;;;;;;;;;-1:-1:-1;;;;;5906:35:31;;;;-1:-1:-1;;;;;5906:35:31;;;;;;;-1:-1:-1;5876:27:31;;-1:-1:-1;6109:20:31;5906:35;6109:18;:20::i;:::-;6091:38;;6140:17;6160:55;6173:7;6182:14;;6198:8;6208:6;6160:12;:55::i;:::-;6231:39;;-1:-1:-1;;;;;24218:39:38;;24200:58;;6140:75:31;;-1:-1:-1;;;;;;6231:39:31;;;6140:75;;6231:39;;24188:2:38;24173:18;6231:39:31;;;;;;;5560:717;;;5427:850;;;;;;:::o;22518:294:33:-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;22619:8:33;;-1:-1:-1;;;22619:8:33;;;;22615:58;;;22636:37;;-1:-1:-1;;;22636:37:33;;;;;;;;;;;22615:58;-1:-1:-1;;;;;;22691:23:33;;;;;;:9;:23;;;;;;;;;22683:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;22724:81;;22757:48;;-1:-1:-1;;;22757:48:33;;;;;;;;;;;22724:81;22518:294;;;:::o;4729:1605:27:-;4840:12;5010:4;5004:11;-1:-1:-1;;;5133:17:27;5126:93;-1:-1:-1;;;;;5270:2:27;5266:51;5262:1;5243:17;5239:25;5232:86;5404:6;5399:2;5380:17;5376:26;5369:42;6256:2;6253:1;6249:2;6230:17;6227:1;6220:5;6213;6208:51;5777:16;5770:24;5764:2;5746:16;5743:24;5739:1;5735;5729:8;5726:15;5722:46;5719:76;5519:754;5508:765;;;6301:7;6293:34;;;;-1:-1:-1;;;6293:34:27;;24471:2:38;6293:34:27;;;24453:21:38;24510:2;24490:18;;;24483:30;-1:-1:-1;;;24529:18:38;;;24522:44;24583:18;;6293:34:27;24269:338:38;6293:34:27;4830:1504;4729:1605;;;:::o;21591:863:33:-;21836:10;;21796:14;;-1:-1:-1;;;21836:10:33;;-1:-1:-1;;;;;21836:10:33;21860:18;;;21856:72;;21887:41;;-1:-1:-1;;;21887:41:33;;;;;;;;;;;21856:72;21983:43;;-1:-1:-1;;;21983:43:33;;-1:-1:-1;;;;;2048:32:38;;;21983:43:33;;;2030:51:38;21947:80:33;;21972:9;;21983:10;:29;;;;2003:18:38;;21983:43:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;21947:13;;:80;:24;:80::i;:::-;21938:89;;22067:1;22046:5;:18;;;:22;;;:82;;22122:6;22046:82;;;22071:48;22095:5;:18;;;22089:3;:24;;;;:::i;:::-;22071:6;;:48;;22115:3;22071:17;:48::i;:::-;22037:91;;22151:11;22142:6;:20;22138:81;;;22171:48;;-1:-1:-1;;;22171:48:33;;;;;;;;;;;22138:81;-1:-1:-1;;;;;22233:24:33;;;;22229:151;;22308:3;-1:-1:-1;;;;;22277:34:33;22286:5;-1:-1:-1;;;;;22286:17:33;;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;22277:28;;:6;:28;:::i;:::-;:34;22273:95;;;22320:48;;-1:-1:-1;;;22320:48:33;;;;;;;;;;;22273:95;22389:58;;-1:-1:-1;;;22389:58:33;;-1:-1:-1;;;;;22389:5:33;:11;;;;:58;;22401:4;;22407:12;;22421:13;;22436:2;;22440:6;;22389:58;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21812:642;21591:863;;;;;;;;:::o;22885:845::-;23171:12;23169:14;;23153:13;;23171:12;23153:13;;23169:14;;-1:-1:-1;;;;;23169:14:33;;:::i;:::-;;;-1:-1:-1;;;;;23169:14:33;;;;;;;;;;;;;;;;;;;;-1:-1:-1;23287:26:33;;23283:319;;23372:40;23390:22;23372:15;:40;:::i;:::-;-1:-1:-1;;;;;23329:24:33;;;;;;;:18;:24;;;;;;;;;:40;;:83;;;;23483:94;;;;;22153:34:38;;;;22223:15;;;22203:18;;;22196:43;22255:18;;;22248:34;;;22298:18;;;22291:34;;;23537:15:33;22341:19:38;;;22334:35;22385:19;;;22378:35;;;22087:19;;23483:94:33;;;-1:-1:-1;;23483:94:33;;;;;;;;;23456:135;;23483:94;23456:135;;;;23426:27;;;;:20;:27;;;;;:165;23283:319;23645:12;-1:-1:-1;;;;;23616:107:33;23631:4;-1:-1:-1;;;;;23616:107:33;23624:5;23616:107;23660:13;23675:6;23683:15;23700:22;23616:107;;;;;;;;25973:25:38;;;26029:2;26014:18;;26007:34;;;;26072:2;26057:18;;26050:34;26115:2;26100:18;;26093:34;25960:3;25945:19;;25742:391;23616:107:33;;;;;;;;23074:656;22885:845;;;;;:::o;2717:196:10:-;2821:11;;;2787:7;2821:11;;;:5;:11;;;;;;;2842:43;;2873:12;;-1:-1:-1;;;2873:12:10;;21540:10:38;21528:23;;2873:12:10;;;21510:42:38;21483:18;;2873:12:10;21365:193:38;6909:479:30;7122:19;7144:10;7122:19;7155:14;;;;:7;:14;:::i;:::-;7144:26;;;;;;;;;;;;;;;;-1:-1:-1;7144:26:30;7122:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;7122:48:30;;;;;;;;;-1:-1:-1;7180:93:30;;7258:14;;;;:7;:14;:::i;:::-;7218:55;;-1:-1:-1;;;7218:55:30;;21540:10:38;21528:23;;;7218:55:30;;;21510:42:38;21483:18;;7218:55:30;21365:193:38;7180:93:30;7283:15;7301:31;;;;7312:8;7301:31;:::i;:::-;7283:49;;7342:39;7366:5;7373:7;7342:23;:39::i;:::-;7112:276;;6909:479;;;;;;;:::o;2285:134:10:-;2358:11;;;;;;;:5;:11;;;;;;;;;:19;;;2392:20;;19248:42:38;;;19306:18;;19299:34;;;2392:20:10;;19221:18:38;2392:20:10;19076:263:38;23788:452:33;23938:81;;-1:-1:-1;;;23938:81:33;;23958:10;23938:81;;;26684:34:38;-1:-1:-1;;;;;23978:5:33;26754:15:38;;26734:18;;;26727:43;26786:18;;;26779:34;;;26829:18;;;26822:34;;;26905:4;26893:17;;26872:19;;;26865:46;26927:19;;;26920:35;;;26971:19;;;26964:35;;;23938:19:33;;;;;26618::38;;23938:81:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23934:300;;24055:50;;-1:-1:-1;;;24055:50:33;;24078:10;24055:50;;;27222:34:38;-1:-1:-1;;;;;24098:5:33;27292:15:38;;27272:18;;;27265:43;24108:13:33;;24055:22;;;;;;27157:18:38;;24055:50:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:66;24051:173;;;24148:61;;-1:-1:-1;;;24148:61:33;;;;;;;;;;;24051:173;23788:452;;;;;;:::o;1564:526:25:-;1680:9;1928:1;-1:-1:-1;;1911:19:25;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:25;;2047:27;;1564:526::o;1009:237:32:-;1101:13;;1076:9;;-1:-1:-1;;;;;;1097:78:32;;;1142:33;;-1:-1:-1;;;1142:33:32;;;;;;;;;;;1097:78;1191:13;;1234:4;;;;;-1:-1:-1;;;;;1221:18:32;1208:3;1191:20;;;;1186:25;1221:18;;1009:237::o;9680:969:30:-;9829:11;-1:-1:-1;;;;;9919:27:30;;2466:42:33;9919:27:30;;;;:59;;;9971:7;-1:-1:-1;;;;;9950:28:30;9958:8;-1:-1:-1;;;;;9950:28:30;;;9919:59;9915:127;;;10001:30;;-1:-1:-1;;;10001:30:30;;;;;;;;;;;9915:127;10051:20;10074:36;;;;10085:14;10074:36;:::i;:::-;10141:25;;;10120:18;10141:25;;;:10;:25;;;;;;;;;10120:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;10120:46:30;;;;;;;;10141:25;;-1:-1:-1;10120:46:30;10176:112;;10225:52;;-1:-1:-1;;;10225:52:30;;21540:10:38;21528:23;;10225:52:30;;;21510:42:38;21483:18;;10225:52:30;21365:193:38;10176:112:30;10297:14;10325:7;10314:19;;;;;;2640:25:38;;2628:2;2613:18;;2494:177;10314:19:30;;;;;;;;;;;;;10297:36;;10343:20;10366:80;10421:5;:21;;;10444:1;10366:27;936:24:13;;;-1:-1:-1;;;936:24:13;;;28341:51:38;936:24:13;;;;;;;;;28408:11:38;;;;936:24:13;;;;860:107;10366:27:30;:54;:80;:54;:80::i;:::-;10343:103;-1:-1:-1;10456:30:30;10489:62;10496:13;10511:1;10343:103;-1:-1:-1;;;;;10523:27:30;;2466:42:33;10523:27:30;;10489:6;:62::i;:::-;10456:95;-1:-1:-1;;;;;;10568:27:30;;2466:42:33;10568:27:30;:74;;10621:10;:21;;;10568:74;;;10598:20;;10568:74;10562:80;9680:969;-1:-1:-1;;;;;;;;;;9680:969:30:o;8106:1288::-;8259:17;;8315:36;;;;8326:14;8315:36;:::i;:::-;8382:25;;;8361:18;8382:25;;;:10;:25;;;;;;;;;8361:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;8361:46:30;;;;;;;;8382:25;;-1:-1:-1;8361:46:30;8417:112;;8466:52;;-1:-1:-1;;;8466:52:30;;21540:10:38;21528:23;;8466:52:30;;;21510:42:38;21483:18;;8466:52:30;21365:193:38;8417:112:30;8538:14;8566:7;8555:19;;;;;;2640:25:38;;2628:2;2613:18;;2494:177;8555:19:30;;;;;;;;;;;;;8538:36;;8584:20;8607:80;8662:5;:21;;;8685:1;8607:27;936:24:13;;;-1:-1:-1;;;936:24:13;;;28341:51:38;936:24:13;;;;;;;;;28408:11:38;;;;936:24:13;;;;860:107;8607:80:30;8584:103;-1:-1:-1;8697:23:30;8723:62;8730:13;8745:1;8584:103;-1:-1:-1;;;;;8757:27:30;;2466:42:33;8757:27:30;;8723:6;:62::i;:::-;8697:88;-1:-1:-1;;;;;;;;8799:27:30;;;8795:463;;8846:13;;:22;-1:-1:-1;8842:136:30;;;8941:13;;8895:68;;-1:-1:-1;;;8895:68:30;;27550:10:38;27538:23;;8895:68:30;;;27520:42:38;27578:18;;;27571:34;;;;27621:18;;;27614:34;;;27493:18;;8895:68:30;27319:335:38;8842:136:30;8795:463;;;9019:7;-1:-1:-1;;;;;8998:28:30;9006:8;-1:-1:-1;;;;;8998:28:30;;8994:264;;9063:6;9046:3;:14;;;:23;9042:138;;;9142:14;;;;9096:69;;-1:-1:-1;;;9096:69:30;;27550:10:38;27538:23;;9096:69:30;;;27520:42:38;27578:18;;;27571:34;;;;27621:18;;;27614:34;;;27493:18;;9096:69:30;27319:335:38;8994:264:30;9217:30;;-1:-1:-1;;;9217:30:30;;;;;;;;;;;8994:264;9267:31;9301:51;9309:13;9324:1;9327:7;9336:3;9341:10;9301:7;:51::i;:::-;9375:12;;8106:1288;-1:-1:-1;;;;;;;;;;;;8106:1288:30:o;6445:328:31:-;-1:-1:-1;;;;;;;;893:3:32;888:8;;;865:32;;;-1:-1:-1;;;;;907:26:32;;;-1:-1:-1;;;907:26:32;;;6637:66:31;;-1:-1:-1;;;6637:66:31;;-1:-1:-1;;6637:5:31;:11;;;;;;:66;;-1:-1:-1;;;;;;907:26:32;6637:66:31;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6761:1;:4;;;-1:-1:-1;;;;;6719:47:31;6735:9;6719:47;6746:1;:13;;;6719:47;;;;2640:25:38;;2628:2;2613:18;;2494:177;6719:47:31;;;;;;;;6523:250;6445: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;;28604:6:38;28592:19;;;664:39:13;;;28574:38:38;28547:18;;664:39:13;28430:188:38;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;;31872:2:38;13031:60:8;;;31854:21:38;31911:2;31891:18;;;31884:30;-1:-1:-1;;;31930:18:38;;;31923:50;31990:18;;13031:60:8;31670:344:38;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;;;;;;32254:3:38;32250:16;;;32246:25;;2853:30:13;;;32234:38:38;32306:16;;;32302:25;32288:12;;;32281:47;32344:12;2853:30:13;;;;;;;;;;;;2814:69;;;2828:22;;-1:-1:-1;;;;;;32516:3:38;32512:16;;;32508:62;2828:22:13;;;32496:75:38;32587: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;;;2640:25:38;2613:18;;4731:26:12;2494:177:38;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;16291:213:21:-;16347:6;16377:16;16369:24;;16365:103;;;16416:41;;-1:-1:-1;;;16416:41:21;;16447:2;16416:41;;;34015:36:38;34067:18;;;34060:34;;;33988:18;;16416:41:21;33834:266:38;1328:1782:27;1466:12;1636:4;1630:11;-1:-1:-1;;;1759:17:27;1752:93;-1:-1:-1;;;;;1896:4:27;1892:53;1888:1;1869:17;1865:25;1858:88;-1:-1:-1;;;;;2038:2:27;2034:51;2029:2;2010:17;2006:26;1999:87;2172:6;2167:2;2148:17;2144:26;2137:42;3026:2;3023:1;3018:3;2999:17;2996:1;2989:5;2982;2977:52;2545:16;2538:24;2532:2;2514:16;2511:24;2507:1;2503;2497:8;2494:15;2490:46;2487:76;2287:756;2276:767;;;3071:7;3063:40;;;;-1:-1:-1;;;3063:40:27;;34307:2:38;3063:40:27;;;34289:21:38;34346:2;34326:18;;;34319:30;-1:-1:-1;;;34365:18:38;;;34358:50;34425:18;;3063:40:27;34105:344:38;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;206:179:38:-;273:20;;-1:-1:-1;;;;;322:38:38;;312:49;;302:77;;375:1;372;365:12;390:131;-1:-1:-1;;;;;465:31:38;;455:42;;445:70;;511:1;508;501:12;526:134;594:20;;623:31;594:20;623:31;:::i;665:347::-;716:8;726:6;780:3;773:4;765:6;761:17;757:27;747:55;;798:1;795;788:12;747:55;-1:-1:-1;821:20:38;;-1:-1:-1;;;;;853:30:38;;850:50;;;896:1;893;886:12;850:50;933:4;925:6;921:17;909:29;;985:3;978:4;969:6;961;957:19;953:30;950:39;947:59;;;1002:1;999;992:12;947:59;665:347;;;;;:::o;1017:841::-;1136:6;1144;1152;1160;1168;1176;1229:3;1217:9;1208:7;1204:23;1200:33;1197:53;;;1246:1;1243;1236:12;1197:53;1269:28;1287:9;1269:28;:::i;:::-;1259:38;;1347:2;1336:9;1332:18;1319:32;1360:31;1385:5;1360:31;:::i;:::-;1410:5;-1:-1:-1;1466:2:38;1451:18;;1438:32;-1:-1:-1;;;;;1482:30:38;;1479:50;;;1525:1;1522;1515:12;1479:50;1564:58;1614:7;1605:6;1594:9;1590:22;1564:58;:::i;:::-;1641:8;;-1:-1:-1;1538:84:38;-1:-1:-1;;1728:2:38;1713:18;;1700:32;1741:33;1700:32;1741:33;:::i;:::-;1793:7;1783:17;;;1847:3;1836:9;1832:19;1819:33;1809:43;;1017:841;;;;;;;;:::o;2092:397::-;2183:6;2191;2199;2252:2;2240:9;2231:7;2227:23;2223:32;2220:52;;;2268:1;2265;2258:12;2220:52;2307:9;2294:23;2326:31;2351:5;2326:31;:::i;:::-;2376:5;2428:2;2413:18;;2400:32;;-1:-1:-1;2479:2:38;2464:18;;;2451:32;;2092:397;-1:-1:-1;;;2092:397:38:o;2676:129::-;-1:-1:-1;;;;;2754:5:38;2750:30;2743:5;2740:41;2730:69;;2795:1;2792;2785:12;2810:245;2868:6;2921:2;2909:9;2900:7;2896:23;2892:32;2889:52;;;2937:1;2934;2927:12;2889:52;2976:9;2963:23;2995:30;3019:5;2995:30;:::i;3060:154::-;3119:5;3164:2;3155:6;3150:3;3146:16;3142:25;3139:45;;;3180:1;3177;3170:12;3139:45;-1:-1:-1;3202:6:38;3060:154;-1:-1:-1;3060:154:38:o;3219:1047::-;3361:6;3369;3377;3385;3393;3401;3409;3462:3;3450:9;3441:7;3437:23;3433:33;3430:53;;;3479:1;3476;3469:12;3430:53;3502;3547:7;3536:9;3502:53;:::i;:::-;3492:63;;3602:2;3591:9;3587:18;3574:32;3564:42;;3657:3;3646:9;3642:19;3629:33;-1:-1:-1;;;;;3722:2:38;3714:6;3711:14;3708:34;;;3738:1;3735;3728:12;3708:34;3777:58;3827:7;3818:6;3807:9;3803:22;3777:58;:::i;:::-;3854:8;;-1:-1:-1;3751:84:38;-1:-1:-1;3939:3:38;3924:19;;3911:33;;-1:-1:-1;3953:31:38;3911:33;3953:31;:::i;:::-;4003:5;;-1:-1:-1;4061:3:38;4046:19;;4033:33;;4078:16;;;4075:36;;;4107:1;4104;4097:12;4075:36;;4146:60;4198:7;4187:8;4176:9;4172:24;4146:60;:::i;:::-;3219:1047;;;;-1:-1:-1;3219:1047:38;;-1:-1:-1;3219:1047:38;;;;4120:86;;-1:-1:-1;;;3219:1047:38:o;4271:163::-;4338:20;;4398:10;4387:22;;4377:33;;4367:61;;4424:1;4421;4414:12;4439:188;4507:20;;-1:-1:-1;;;;;4556:46:38;;4546:57;;4536:85;;4617:1;4614;4607:12;4632:258;4699:6;4707;4760:2;4748:9;4739:7;4735:23;4731:32;4728:52;;;4776:1;4773;4766:12;4728:52;4799:28;4817:9;4799:28;:::i;:::-;4789:38;;4846;4880:2;4869:9;4865:18;4846:38;:::i;:::-;4836:48;;4632:258;;;;;:::o;5199:247::-;5258:6;5311:2;5299:9;5290:7;5286:23;5282:32;5279:52;;;5327:1;5324;5317:12;5279:52;5366:9;5353:23;5385:31;5410:5;5385:31;:::i;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:38: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:38;6548:18;;6535:32;6576:30;6535:32;6576:30;:::i;:::-;6625:7;-1:-1:-1;6684:2:38;6669:18;;6656:32;6697:33;6656:32;6697:33;:::i;:::-;6749:7;-1:-1:-1;6775:39:38;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:38;7374:18;;7361:32;;-1:-1:-1;7440:2:38;7425:18;;7412:32;;-1:-1:-1;7491:2:38;7476:18;;7463:32;;-1:-1:-1;7514:37:38;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:38;8005:18;;7992:32;;-1:-1:-1;8071:2:38;8056:18;;8043:32;;-1:-1:-1;8127:2:38;8112:18;;8099:32;8140:33;8099:32;8140:33;:::i;:::-;7666:539;;;;-1:-1:-1;7666:539:38;;-1:-1:-1;;7666:539:38: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:38;9452:18;;9439:32;9480:33;9439:32;9480:33;:::i;:::-;9020:732;;;;-1:-1:-1;9532:7:38;;9586:2;9571:18;;9558:32;;-1:-1:-1;9637:3:38;9622:19;;9609:33;;9689:3;9674:19;;9661:33;;-1:-1:-1;9741:3:38;9726:19;;;9713:33;;-1:-1:-1;9020:732:38;-1:-1:-1;;9020:732:38:o;11015:297::-;11074:6;11127:2;11115:9;11106:7;11102:23;11098:32;11095:52;;;11143:1;11140;11133:12;11095:52;11182:9;11169:23;-1:-1:-1;;;;;11225:5:38;11221:42;11214:5;11211:53;11201:81;;11278:1;11275;11268:12;11522:241;11578:6;11631:2;11619:9;11610:7;11606:23;11602:32;11599:52;;;11647:1;11644;11637:12;11599:52;11686:9;11673:23;11705:28;11727:5;11705:28;:::i;11976:700::-;12069:6;12077;12085;12093;12146:3;12134:9;12125:7;12121:23;12117:33;12114:53;;;12163:1;12160;12153:12;12114:53;12202:9;12189:23;12221:31;12246:5;12221:31;:::i;:::-;12271:5;-1:-1:-1;12328:2:38;12313:18;;12300:32;12341:30;12300:32;12341:30;:::i;:::-;12390:7;-1:-1:-1;12449:2:38;12434:18;;12421:32;12462:30;12421:32;12462:30;:::i;:::-;12511:7;-1:-1:-1;12570:2:38;12555:18;;12542:32;12618:6;12605:20;;12593:33;;12583:61;;12640:1;12637;12630:12;12681:1261;12867:6;12875;12883;12891;12899;12907;12915;12923;12931;12939;12947:7;12956;13010:3;12998:9;12989:7;12985:23;12981:33;12978:53;;;13027:1;13024;13017:12;12978:53;13040:49;13078:9;13065:23;13040:49;:::i;:::-;13121:9;13108:23;13098:33;;13178:2;13167:9;13163:18;13150:32;13140:42;;13229:2;13218:9;13214:18;13201:32;13191:42;;13280:2;13269:9;13265:18;13252:32;13242:42;;13303:37;13335:3;13324:9;13320:19;13303:37;:::i;:::-;13293:47;;13387:3;13376:9;13372:19;13359:33;13349:43;;13439:3;13428:9;13424:19;13411:33;13401:43;;13453:59;13506:3;13495:9;13491:19;13478:33;13453:59;:::i;:::-;13559:3;13548:9;13544:19;13531:33;13521:43;;-1:-1:-1;;;;;13607:3:38;13596:9;13592:19;13579:33;13576:57;13573:77;;;13646:1;13643;13636:12;13573:77;13685:85;13762:7;13754:3;13743:9;13739:19;13726:33;13715:9;13711:49;13685:85;:::i;:::-;13789:8;;-1:-1:-1;13816:8:38;-1:-1:-1;13844:39:38;13878:3;13863:19;;13844:39;:::i;:::-;13833:50;;13931:3;13920:9;13916:19;13903:33;13892:44;;12681:1261;;;;;;;;;;;;;;:::o;13947:180::-;14006:6;14059:2;14047:9;14038:7;14034:23;14030:32;14027:52;;;14075:1;14072;14065:12;14027:52;-1:-1:-1;14098:23:38;;13947:180;-1:-1:-1;13947:180:38:o;14314:529::-;14391:6;14399;14407;14460:2;14448:9;14439:7;14435:23;14431:32;14428:52;;;14476:1;14473;14466:12;14428:52;14515:9;14502:23;14534:31;14559:5;14534:31;:::i;:::-;14584:5;-1:-1:-1;14641:2:38;14626:18;;14613:32;14654:33;14613:32;14654:33;:::i;:::-;14706:7;-1:-1:-1;14765:2:38;14750:18;;14737:32;14778:33;14737:32;14778:33;:::i;:::-;14830:7;14820:17;;;14314:529;;;;;:::o;14848:393::-;14924:6;14932;14940;14993:2;14981:9;14972:7;14968:23;14964:32;14961:52;;;15009:1;15006;14999:12;14961:52;15032:28;15050:9;15032:28;:::i;:::-;15022:38;;15110:2;15099:9;15095:18;15082:32;15123:31;15148:5;15123:31;:::i;:::-;15173:5;-1:-1:-1;15197:38:38;15231:2;15216:18;;15197:38;:::i;:::-;15187:48;;14848:393;;;;;:::o;15472:1062::-;15624:6;15632;15640;15648;15656;15664;15672;15680;15733:3;15721:9;15712:7;15708:23;15704:33;15701:53;;;15750:1;15747;15740:12;15701:53;15789:9;15776:23;15808:31;15833:5;15808:31;:::i;:::-;15858:5;-1:-1:-1;15910:2:38;15895:18;;15882:32;;-1:-1:-1;15961:2:38;15946:18;;15933:32;;-1:-1:-1;16017:2:38;16002:18;;15989:32;16030:33;15989:32;16030:33;:::i;:::-;16082:7;-1:-1:-1;16140:3:38;16125:19;;16112:33;-1:-1:-1;;;;;16157:30:38;;16154:50;;;16200:1;16197;16190:12;16154:50;16239:58;16289:7;16280:6;16269:9;16265:22;16239:58;:::i;:::-;16316:8;;-1:-1:-1;16213:84:38;-1:-1:-1;;16403:3:38;16388:19;;16375:33;16417;16375;16417;:::i;:::-;16469:7;16459:17;;;16523:3;16512:9;16508:19;16495:33;16485:43;;15472:1062;;;;;;;;;;;:::o;16924:772::-;17034:6;17042;17050;17058;17066;17119:3;17107:9;17098:7;17094:23;17090:33;17087:53;;;17136:1;17133;17126:12;17087:53;17159:28;17177:9;17159:28;:::i;:::-;17149:38;;17237:2;17226:9;17222:18;17209:32;17250:31;17275:5;17250:31;:::i;:::-;17300:5;-1:-1:-1;17356:2:38;17341:18;;17328:32;-1:-1:-1;;;;;17372:30:38;;17369:50;;;17415:1;17412;17405:12;17369:50;17454:58;17504:7;17495:6;17484:9;17480:22;17454:58;:::i;:::-;17531:8;;-1:-1:-1;17428:84:38;-1:-1:-1;;17618:2:38;17603:18;;17590:32;17631:33;17590:32;17631:33;:::i;:::-;17683:7;17673:17;;;16924:772;;;;;;;;:::o;18156:235::-;18240:6;18293:2;18281:9;18272:7;18268:23;18264:32;18261:52;;;18309:1;18306;18299:12;18261:52;18332:53;18377:7;18366:9;18332:53;:::i;18396:336::-;18598:2;18580:21;;;18637:2;18617:18;;;18610:30;-1:-1:-1;;;18671:2:38;18656:18;;18649:42;18723:2;18708:18;;18396:336::o;18737:334::-;18939:2;18921:21;;;18978:2;18958:18;;;18951:30;-1:-1:-1;;;19012:2:38;18997:18;;18990:40;19062:2;19047:18;;18737:334::o;20629:184::-;20699:6;20752:2;20740:9;20731:7;20727:23;20723:32;20720:52;;;20768:1;20765;20758:12;20720:52;-1:-1:-1;20791:16:38;;20629:184;-1:-1:-1;20629:184:38:o;20818:542::-;-1:-1:-1;;;;;21147:15:38;;;21129:34;;21199:15;;;21194:2;21179:18;;21172:43;21246:2;21231:18;;21224:34;;;;21294:15;;;21289:2;21274:18;;21267:43;21341:3;21326:19;;21319:35;;;;21078:3;21063:19;;20818:542::o;21563:127::-;21624:10;21619:3;21615:20;21612:1;21605:31;21655:4;21652:1;21645:15;21679:4;21676:1;21669:15;21695:128;21762:9;;;21783:11;;;21780:37;;;21797:18;;:::i;22424:400::-;-1:-1:-1;;;;;22680:15:38;;;22662:34;;22732:15;;;;22727:2;22712:18;;22705:43;-1:-1:-1;;;;;;22784:33:38;;;22779:2;22764:18;;22757:61;22612:2;22597:18;;22424:400::o;22829:245::-;22896:6;22949:2;22937:9;22928:7;22924:23;22920:32;22917:52;;;22965:1;22962;22955:12;22917:52;22997:9;22991:16;23016:28;23038:5;23016:28;:::i;24612:171::-;24680:6;24719:10;;;24707;;;24703:27;;24742:12;;;24739:38;;;24757:18;;:::i;:::-;24739:38;24612:171;;;;:::o;24788:125::-;24853:9;;;24874:10;;;24871:36;;;24887:18;;:::i;24918:209::-;24956:3;-1:-1:-1;;;;;25037:2:38;25030:5;25026:14;25064:2;25055:7;25052:15;25049:41;;25070:18;;:::i;:::-;25119:1;25106:15;;24918:209;-1:-1:-1;;;24918:209:38:o;28623:250::-;28708:1;28718:113;28732:6;28729:1;28726:13;28718:113;;;28808:11;;;28802:18;28789:11;;;28782:39;28754:2;28747:10;28718:113;;;-1:-1:-1;;28865:1:38;28847:16;;28840:27;28623:250::o;28878:270::-;28919:3;28957:5;28951:12;28984:6;28979:3;28972:19;29000:76;29069:6;29062:4;29057:3;29053:14;29046:4;29039:5;29035:16;29000:76;:::i;:::-;29130:2;29109:15;-1:-1:-1;;29105:29:38;29096:39;;;;29137:4;29092:50;;28878:270;-1:-1:-1;;28878:270:38:o;29153:885::-;29372:2;29361:9;29354:21;29430:10;29421:6;29415:13;29411:30;29406:2;29395:9;29391:18;29384:58;29496:4;29488:6;29484:17;29478:24;29473:2;29462:9;29458:18;29451:52;29335:4;29550:2;29542:6;29538:15;29532:22;29591:4;29585:3;29574:9;29570:19;29563:33;29619:51;29665:3;29654:9;29650:19;29636:12;29619:51;:::i;:::-;29605:65;;29719:2;29711:6;29707:15;29701:22;29793:2;29789:7;29777:9;29769:6;29765:22;29761:36;29754:4;29743:9;29739:20;29732:66;29821:40;29854:6;29838:14;29821:40;:::i;:::-;29930:3;29918:16;;;;29912:23;29905:31;29898:39;29892:3;29877:19;;29870:68;-1:-1:-1;;;;;;;;29999:32:38;;;;29992:4;29977:20;;;29970:62;29807:54;29153:885::o;30043:575::-;30113:5;30161:4;30149:9;30144:3;30140:19;30136:30;30133:50;;;30179:1;30176;30169:12;30133:50;30212:4;30206:11;30256:4;30248:6;30244:17;30327:6;30315:10;30312:22;-1:-1:-1;;;;;30279:10:38;30276:34;30273:62;30270:185;;;30377:10;30372:3;30368:20;30365:1;30358:31;30412:4;30409:1;30402:15;30440:4;30437:1;30430:15;30270:185;30471:4;30464:24;30536:16;;30521:32;;30607:2;30592:18;;;30586:25;30569:15;;;30562:50;;;;-1:-1:-1;30506:6:38;30043:575;-1:-1:-1;30043:575:38:o;30623:258::-;30722:6;30775:2;30763:9;30754:7;30750:23;30746:32;30743:52;;;30791:1;30788;30781:12;30743:52;30814:61;30867:7;30856:9;30814:61;:::i;30886:779::-;30989:6;31042:3;31030:9;31021:7;31017:23;31013:33;31010:53;;;31059:1;31056;31049:12;31010:53;31092:2;31086:9;31134:4;31126:6;31122:17;31205:6;31193:10;31190:22;-1:-1:-1;;;;;31157:10:38;31154:34;31151:62;31148:185;;;31255:10;31250:3;31246:20;31243:1;31236:31;31290:4;31287:1;31280:15;31318:4;31315:1;31308:15;31148:185;31349:2;31342:22;31388:16;;31373:32;;31448:2;31433:18;;31427:25;31461:30;31427:25;31461:30;:::i;:::-;31519:2;31507:15;;31500:30;31563:70;31625:7;31620:2;31605:18;;31563:70;:::i;:::-;31558:2;31546:15;;31539:95;31550:6;30886:779;-1:-1:-1;;;30886:779:38:o;32610:168::-;32677:6;32703:10;;;32715;;;32699:27;;32738:11;;;32735:37;;;32752:18;;:::i;32783:790::-;33032:3;33070:6;33064:13;33086:66;33145:6;33140:3;33133:4;33125:6;33121:17;33086:66;:::i;:::-;-1:-1:-1;;;;;;33213:3:38;33249:16;;;33245:25;;33174:16;;;33231:40;;;-1:-1:-1;;;;;;33328:3:38;33306:16;;;33302:38;33298:1;33287:13;;33280:61;33376:16;;;33372:25;33368:1;33357:13;;33350:48;33423:13;;33445:78;33423:13;33510:1;33499:13;;33492:4;33480:17;;33445:78;:::i;:::-;33543:20;33565:1;33539:28;;32783:790;-1:-1:-1;;;;;;;32783:790:38:o;33578:251::-;33648:6;33701:2;33689:9;33680:7;33676:23;33672:32;33669:52;;;33717:1;33714;33707:12;33669:52;33749:9;33743:16;33768:31;33793:5;33768:31;:::i
Swarm Source
ipfs://46a8bb17c7e9a6c35e6267420a3c8a2a80e232243e6573906cc1c2c0ddfe667a
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.