Overview
ETH Balance
0 ETH
Eth Value
$0.00Token Holdings
Latest 25 from a total of 276 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Sync With Bridge... | 15885033 | 675 days ago | IN | 0 ETH | 0.00100725 | ||||
Remove Liquidity | 15000171 | 810 days ago | IN | 0 ETH | 0.00467152 | ||||
Settle Relay | 14921353 | 824 days ago | IN | 0 ETH | 0.00280513 | ||||
Relay And Speed ... | 14920822 | 824 days ago | IN | 0 ETH | 0.00562812 | ||||
Remove Liquidity | 14895961 | 828 days ago | IN | 0 ETH | 0.00436612 | ||||
Remove Liquidity | 14867629 | 833 days ago | IN | 0 ETH | 0.00295035 | ||||
Remove Liquidity | 14860504 | 834 days ago | IN | 0 ETH | 0.0022868 | ||||
Remove Liquidity | 14848538 | 836 days ago | IN | 0 ETH | 0.00380816 | ||||
Remove Liquidity | 14840687 | 837 days ago | IN | 0 ETH | 0.00184892 | ||||
Remove Liquidity | 14838329 | 837 days ago | IN | 0 ETH | 0.00251647 | ||||
Remove Liquidity | 14838308 | 837 days ago | IN | 0 ETH | 0.00186838 | ||||
Remove Liquidity | 14838288 | 837 days ago | IN | 0 ETH | 0.00171201 | ||||
Remove Liquidity | 14838261 | 837 days ago | IN | 0 ETH | 0.00190164 | ||||
Remove Liquidity | 14838235 | 837 days ago | IN | 0 ETH | 0.00194723 | ||||
Remove Liquidity | 14838215 | 837 days ago | IN | 0 ETH | 0.00265844 | ||||
Remove Liquidity | 14838183 | 837 days ago | IN | 0 ETH | 0.0023294 | ||||
Remove Liquidity | 14838148 | 837 days ago | IN | 0 ETH | 0.00255415 | ||||
Remove Liquidity | 14838118 | 837 days ago | IN | 0 ETH | 0.00281587 | ||||
Remove Liquidity | 14835436 | 838 days ago | IN | 0 ETH | 0.00191653 | ||||
Remove Liquidity | 14833551 | 838 days ago | IN | 0 ETH | 0.00141716 | ||||
Remove Liquidity | 14831652 | 838 days ago | IN | 0 ETH | 0.00183926 | ||||
Remove Liquidity | 14830284 | 839 days ago | IN | 0 ETH | 0.00230343 | ||||
Remove Liquidity | 14829780 | 839 days ago | IN | 0 ETH | 0.00255629 | ||||
Add Liquidity | 14829738 | 839 days ago | IN | 0 ETH | 0.00401771 | ||||
Settle Relay | 14823909 | 840 days ago | IN | 0 ETH | 0.00299728 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
BridgePoolProd
Compiler Version
v0.8.9+commit.e5eed63a
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2022-01-13 */ // Sources flattened with hardhat v2.5.0 https://hardhat.org // File contracts/insured-bridge/interfaces/BridgeAdminInterface.sol // SPDX-License-Identifier: AGPL-3.0-only pragma solidity ^0.8.0; /** * @notice Helper view methods designed to be called by BridgePool contracts. */ interface BridgeAdminInterface { event SetDepositContracts( uint256 indexed chainId, address indexed l2DepositContract, address indexed l2MessengerContract ); event SetCrossDomainAdmin(uint256 indexed chainId, address indexed newAdmin); event SetRelayIdentifier(bytes32 indexed identifier); event SetOptimisticOracleLiveness(uint32 indexed liveness); event SetProposerBondPct(uint64 indexed proposerBondPct); event WhitelistToken(uint256 chainId, address indexed l1Token, address indexed l2Token, address indexed bridgePool); event SetMinimumBridgingDelay(uint256 indexed chainId, uint64 newMinimumBridgingDelay); event DepositsEnabled(uint256 indexed chainId, address indexed l2Token, bool depositsEnabled); event BridgePoolsAdminTransferred(address[] bridgePools, address indexed newAdmin); event SetLpFeeRate(address indexed bridgePool, uint64 newLpFeeRatePerSecond); function finder() external view returns (address); struct DepositUtilityContracts { address depositContract; // L2 deposit contract where cross-chain relays originate. address messengerContract; // L1 helper contract that can send a message to the L2 with the mapped network ID. } function depositContracts(uint256) external view returns (DepositUtilityContracts memory); struct L1TokenRelationships { mapping(uint256 => address) l2Tokens; // L2 Chain Id to l2Token address. address bridgePool; } function whitelistedTokens(address, uint256) external view returns (address l2Token, address bridgePool); function optimisticOracleLiveness() external view returns (uint32); function proposerBondPct() external view returns (uint64); function identifier() external view returns (bytes32); } // File @openzeppelin/contracts/token/ERC20/[email protected] // OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol) /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); } // File contracts/insured-bridge/interfaces/BridgePoolInterface.sol interface BridgePoolInterface { function l1Token() external view returns (IERC20); function changeAdmin(address newAdmin) external; function setLpFeeRatePerSecond(uint64 _newLpFeeRatePerSecond) external; function setRelaysEnabled(bool _relaysEnabled) external; } // File contracts/oracle/interfaces/OptimisticOracleInterface.sol /** * @title Financial contract facing Oracle interface. * @dev Interface used by financial contracts to interact with the Oracle. Voters will use a different interface. */ abstract contract OptimisticOracleInterface { // Struct representing the state of a price request. enum State { Invalid, // Never requested. Requested, // Requested, no other actions taken. Proposed, // Proposed, but not expired or disputed yet. Expired, // Proposed, not disputed, past liveness. Disputed, // Disputed, but no DVM price returned yet. Resolved, // Disputed and DVM price is available. Settled // Final price has been set in the contract (can get here from Expired or Resolved). } // Struct representing a price request. struct Request { address proposer; // Address of the proposer. address disputer; // Address of the disputer. IERC20 currency; // ERC20 token used to pay rewards and fees. bool settled; // True if the request is settled. bool refundOnDispute; // True if the requester should be refunded their reward on dispute. int256 proposedPrice; // Price that the proposer submitted. int256 resolvedPrice; // Price resolved once the request is settled. uint256 expirationTime; // Time at which the request auto-settles without a dispute. uint256 reward; // Amount of the currency to pay to the proposer on settlement. uint256 finalFee; // Final fee to pay to the Store upon request to the DVM. uint256 bond; // Bond that the proposer and disputer must pay on top of the final fee. uint256 customLiveness; // Custom liveness value set by the requester. } // This value must be <= the Voting contract's `ancillaryBytesLimit` value otherwise it is possible // that a price can be requested to this contract successfully, but cannot be disputed because the DVM refuses // to accept a price request made with ancillary data length over a certain size. uint256 public constant ancillaryBytesLimit = 8192; /** * @notice Requests a new price. * @param identifier price identifier being requested. * @param timestamp timestamp of the price being requested. * @param ancillaryData ancillary data representing additional args being passed with the price request. * @param currency ERC20 token used for payment of rewards and fees. Must be approved for use with the DVM. * @param reward reward offered to a successful proposer. Will be pulled from the caller. Note: this can be 0, * which could make sense if the contract requests and proposes the value in the same call or * provides its own reward system. * @return totalBond default bond (final fee) + final fee that the proposer and disputer will be required to pay. * This can be changed with a subsequent call to setBond(). */ function requestPrice( bytes32 identifier, uint256 timestamp, bytes memory ancillaryData, IERC20 currency, uint256 reward ) external virtual returns (uint256 totalBond); /** * @notice Set the proposal bond associated with a price request. * @param identifier price identifier to identify the existing request. * @param timestamp timestamp to identify the existing request. * @param ancillaryData ancillary data of the price being requested. * @param bond custom bond amount to set. * @return totalBond new bond + final fee that the proposer and disputer will be required to pay. This can be * changed again with a subsequent call to setBond(). */ function setBond( bytes32 identifier, uint256 timestamp, bytes memory ancillaryData, uint256 bond ) external virtual returns (uint256 totalBond); /** * @notice Sets the request to refund the reward if the proposal is disputed. This can help to "hedge" the caller * in the event of a dispute-caused delay. Note: in the event of a dispute, the winner still receives the other's * bond, so there is still profit to be made even if the reward is refunded. * @param identifier price identifier to identify the existing request. * @param timestamp timestamp to identify the existing request. * @param ancillaryData ancillary data of the price being requested. */ function setRefundOnDispute( bytes32 identifier, uint256 timestamp, bytes memory ancillaryData ) external virtual; /** * @notice Sets a custom liveness value for the request. Liveness is the amount of time a proposal must wait before * being auto-resolved. * @param identifier price identifier to identify the existing request. * @param timestamp timestamp to identify the existing request. * @param ancillaryData ancillary data of the price being requested. * @param customLiveness new custom liveness. */ function setCustomLiveness( bytes32 identifier, uint256 timestamp, bytes memory ancillaryData, uint256 customLiveness ) external virtual; /** * @notice Proposes a price value on another address' behalf. Note: this address will receive any rewards that come * from this proposal. However, any bonds are pulled from the caller. * @param proposer address to set as the proposer. * @param requester sender of the initial price request. * @param identifier price identifier to identify the existing request. * @param timestamp timestamp to identify the existing request. * @param ancillaryData ancillary data of the price being requested. * @param proposedPrice price being proposed. * @return totalBond the amount that's pulled from the caller's wallet as a bond. The bond will be returned to * the proposer once settled if the proposal is correct. */ function proposePriceFor( address proposer, address requester, bytes32 identifier, uint256 timestamp, bytes memory ancillaryData, int256 proposedPrice ) public virtual returns (uint256 totalBond); /** * @notice Proposes a price value for an existing price request. * @param requester sender of the initial price request. * @param identifier price identifier to identify the existing request. * @param timestamp timestamp to identify the existing request. * @param ancillaryData ancillary data of the price being requested. * @param proposedPrice price being proposed. * @return totalBond the amount that's pulled from the proposer's wallet as a bond. The bond will be returned to * the proposer once settled if the proposal is correct. */ function proposePrice( address requester, bytes32 identifier, uint256 timestamp, bytes memory ancillaryData, int256 proposedPrice ) external virtual returns (uint256 totalBond); /** * @notice Disputes a price request with an active proposal on another address' behalf. Note: this address will * receive any rewards that come from this dispute. However, any bonds are pulled from the caller. * @param disputer address to set as the disputer. * @param requester sender of the initial price request. * @param identifier price identifier to identify the existing request. * @param timestamp timestamp to identify the existing request. * @param ancillaryData ancillary data of the price being requested. * @return totalBond the amount that's pulled from the caller's wallet as a bond. The bond will be returned to * the disputer once settled if the dispute was value (the proposal was incorrect). */ function disputePriceFor( address disputer, address requester, bytes32 identifier, uint256 timestamp, bytes memory ancillaryData ) public virtual returns (uint256 totalBond); /** * @notice Disputes a price value for an existing price request with an active proposal. * @param requester sender of the initial price request. * @param identifier price identifier to identify the existing request. * @param timestamp timestamp to identify the existing request. * @param ancillaryData ancillary data of the price being requested. * @return totalBond the amount that's pulled from the disputer's wallet as a bond. The bond will be returned to * the disputer once settled if the dispute was valid (the proposal was incorrect). */ function disputePrice( address requester, bytes32 identifier, uint256 timestamp, bytes memory ancillaryData ) external virtual returns (uint256 totalBond); /** * @notice Retrieves a price that was previously requested by a caller. Reverts if the request is not settled * or settleable. Note: this method is not view so that this call may actually settle the price request if it * hasn't been settled. * @param identifier price identifier to identify the existing request. * @param timestamp timestamp to identify the existing request. * @param ancillaryData ancillary data of the price being requested. * @return resolved price. */ function settleAndGetPrice( bytes32 identifier, uint256 timestamp, bytes memory ancillaryData ) external virtual returns (int256); /** * @notice Attempts to settle an outstanding price request. Will revert if it isn't settleable. * @param requester sender of the initial price request. * @param identifier price identifier to identify the existing request. * @param timestamp timestamp to identify the existing request. * @param ancillaryData ancillary data of the price being requested. * @return payout the amount that the "winner" (proposer or disputer) receives on settlement. This amount includes * the returned bonds as well as additional rewards. */ function settle( address requester, bytes32 identifier, uint256 timestamp, bytes memory ancillaryData ) external virtual returns (uint256 payout); /** * @notice Gets the current data structure containing all information about a price request. * @param requester sender of the initial price request. * @param identifier price identifier to identify the existing request. * @param timestamp timestamp to identify the existing request. * @param ancillaryData ancillary data of the price being requested. * @return the Request data structure. */ function getRequest( address requester, bytes32 identifier, uint256 timestamp, bytes memory ancillaryData ) public view virtual returns (Request memory); /** * @notice Returns the state of a price request. * @param requester sender of the initial price request. * @param identifier price identifier to identify the existing request. * @param timestamp timestamp to identify the existing request. * @param ancillaryData ancillary data of the price being requested. * @return the State enum value. */ function getState( address requester, bytes32 identifier, uint256 timestamp, bytes memory ancillaryData ) public view virtual returns (State); /** * @notice Checks if a given request has resolved or been settled (i.e the optimistic oracle has a price). * @param requester sender of the initial price request. * @param identifier price identifier to identify the existing request. * @param timestamp timestamp to identify the existing request. * @param ancillaryData ancillary data of the price being requested. * @return true if price has resolved or settled, false otherwise. */ function hasPrice( address requester, bytes32 identifier, uint256 timestamp, bytes memory ancillaryData ) public view virtual returns (bool); function stampAncillaryData(bytes memory ancillaryData, address requester) public view virtual returns (bytes memory); } // File contracts/oracle/interfaces/SkinnyOptimisticOracleInterface.sol /** * @title Interface for the gas-cost-reduced version of the OptimisticOracle. * @notice Differences from normal OptimisticOracle: * - refundOnDispute: flag is removed, by default there are no refunds on disputes. * - customizing request parameters: In the OptimisticOracle, parameters like `bond` and `customLiveness` can be reset * after a request is already made via `requestPrice`. In the SkinnyOptimisticOracle, these parameters can only be * set in `requestPrice`, which has an expanded input set. * - settleAndGetPrice: Replaced by `settle`, which can only be called once per settleable request. The resolved price * can be fetched via the `Settle` event or the return value of `settle`. * - general changes to interface: Functions that interact with existing requests all require the parameters of the * request to modify to be passed as input. These parameters must match with the existing request parameters or the * function will revert. This change reflects the internal refactor to store hashed request parameters instead of the * full request struct. * @dev Interface used by financial contracts to interact with the Oracle. Voters will use a different interface. */ abstract contract SkinnyOptimisticOracleInterface { // Struct representing a price request. Note that this differs from the OptimisticOracleInterface's Request struct // in that refundOnDispute is removed. struct Request { address proposer; // Address of the proposer. address disputer; // Address of the disputer. IERC20 currency; // ERC20 token used to pay rewards and fees. bool settled; // True if the request is settled. int256 proposedPrice; // Price that the proposer submitted. int256 resolvedPrice; // Price resolved once the request is settled. uint256 expirationTime; // Time at which the request auto-settles without a dispute. uint256 reward; // Amount of the currency to pay to the proposer on settlement. uint256 finalFee; // Final fee to pay to the Store upon request to the DVM. uint256 bond; // Bond that the proposer and disputer must pay on top of the final fee. uint256 customLiveness; // Custom liveness value set by the requester. } // This value must be <= the Voting contract's `ancillaryBytesLimit` value otherwise it is possible // that a price can be requested to this contract successfully, but cannot be disputed because the DVM refuses // to accept a price request made with ancillary data length over a certain size. uint256 public constant ancillaryBytesLimit = 8192; /** * @notice Requests a new price. * @param identifier price identifier being requested. * @param timestamp timestamp of the price being requested. * @param ancillaryData ancillary data representing additional args being passed with the price request. * @param currency ERC20 token used for payment of rewards and fees. Must be approved for use with the DVM. * @param reward reward offered to a successful proposer. Will be pulled from the caller. Note: this can be 0, * which could make sense if the contract requests and proposes the value in the same call or * provides its own reward system. * @param bond custom proposal bond to set for request. If set to 0, defaults to the final fee. * @param customLiveness custom proposal liveness to set for request. * @return totalBond default bond + final fee that the proposer and disputer will be required to pay. */ function requestPrice( bytes32 identifier, uint32 timestamp, bytes memory ancillaryData, IERC20 currency, uint256 reward, uint256 bond, uint256 customLiveness ) external virtual returns (uint256 totalBond); /** * @notice Proposes a price value on another address' behalf. Note: this address will receive any rewards that come * from this proposal. However, any bonds are pulled from the caller. * @param requester sender of the initial price request. * @param identifier price identifier to identify the existing request. * @param timestamp timestamp to identify the existing request. * @param ancillaryData ancillary data of the price being requested. * @param request price request parameters whose hash must match the request that the caller wants to * propose a price for. * @param proposer address to set as the proposer. * @param proposedPrice price being proposed. * @return totalBond the amount that's pulled from the caller's wallet as a bond. The bond will be returned to * the proposer once settled if the proposal is correct. */ function proposePriceFor( address requester, bytes32 identifier, uint32 timestamp, bytes memory ancillaryData, Request memory request, address proposer, int256 proposedPrice ) public virtual returns (uint256 totalBond); /** * @notice Proposes a price value where caller is the proposer. * @param requester sender of the initial price request. * @param identifier price identifier to identify the existing request. * @param timestamp timestamp to identify the existing request. * @param ancillaryData ancillary data of the price being requested. * @param request price request parameters whose hash must match the request that the caller wants to * propose a price for. * @param proposedPrice price being proposed. * @return totalBond the amount that's pulled from the caller's wallet as a bond. The bond will be returned to * the proposer once settled if the proposal is correct. */ function proposePrice( address requester, bytes32 identifier, uint32 timestamp, bytes memory ancillaryData, Request memory request, int256 proposedPrice ) external virtual returns (uint256 totalBond); /** * @notice Combines logic of requestPrice and proposePrice while taking advantage of gas savings from not having to * overwrite Request params that a normal requestPrice() => proposePrice() flow would entail. Note: The proposer * will receive any rewards that come from this proposal. However, any bonds are pulled from the caller. * @dev The caller is the requester, but the proposer can be customized. * @param identifier price identifier to identify the existing request. * @param timestamp timestamp to identify the existing request. * @param ancillaryData ancillary data of the price being requested. * @param currency ERC20 token used for payment of rewards and fees. Must be approved for use with the DVM. * @param reward reward offered to a successful proposer. Will be pulled from the caller. Note: this can be 0, * which could make sense if the contract requests and proposes the value in the same call or * provides its own reward system. * @param bond custom proposal bond to set for request. If set to 0, defaults to the final fee. * @param customLiveness custom proposal liveness to set for request. * @param proposer address to set as the proposer. * @param proposedPrice price being proposed. * @return totalBond the amount that's pulled from the caller's wallet as a bond. The bond will be returned to * the proposer once settled if the proposal is correct. */ function requestAndProposePriceFor( bytes32 identifier, uint32 timestamp, bytes memory ancillaryData, IERC20 currency, uint256 reward, uint256 bond, uint256 customLiveness, address proposer, int256 proposedPrice ) external virtual returns (uint256 totalBond); /** * @notice Disputes a price request with an active proposal on another address' behalf. Note: this address will * receive any rewards that come from this dispute. However, any bonds are pulled from the caller. * @param identifier price identifier to identify the existing request. * @param timestamp timestamp to identify the existing request. * @param ancillaryData ancillary data of the price being requested. * @param request price request parameters whose hash must match the request that the caller wants to * dispute. * @param disputer address to set as the disputer. * @param requester sender of the initial price request. * @return totalBond the amount that's pulled from the caller's wallet as a bond. The bond will be returned to * the disputer once settled if the dispute was valid (the proposal was incorrect). */ function disputePriceFor( bytes32 identifier, uint32 timestamp, bytes memory ancillaryData, Request memory request, address disputer, address requester ) public virtual returns (uint256 totalBond); /** * @notice Disputes a price request with an active proposal where caller is the disputer. * @param requester sender of the initial price request. * @param identifier price identifier to identify the existing request. * @param timestamp timestamp to identify the existing request. * @param ancillaryData ancillary data of the price being requested. * @param request price request parameters whose hash must match the request that the caller wants to * dispute. * @return totalBond the amount that's pulled from the caller's wallet as a bond. The bond will be returned to * the disputer once settled if the dispute was valid (the proposal was incorrect). */ function disputePrice( address requester, bytes32 identifier, uint32 timestamp, bytes memory ancillaryData, Request memory request ) external virtual returns (uint256 totalBond); /** * @notice Attempts to settle an outstanding price request. Will revert if it isn't settleable. * @param requester sender of the initial price request. * @param identifier price identifier to identify the existing request. * @param timestamp timestamp to identify the existing request. * @param ancillaryData ancillary data of the price being requested. * @param request price request parameters whose hash must match the request that the caller wants to * settle. * @return payout the amount that the "winner" (proposer or disputer) receives on settlement. This amount includes * the returned bonds as well as additional rewards. * @return resolvedPrice the price that the request settled to. */ function settle( address requester, bytes32 identifier, uint32 timestamp, bytes memory ancillaryData, Request memory request ) external virtual returns (uint256 payout, int256 resolvedPrice); /** * @notice Computes the current state of a price request. See the State enum for more details. * @param requester sender of the initial price request. * @param identifier price identifier to identify the existing request. * @param timestamp timestamp to identify the existing request. * @param ancillaryData ancillary data of the price being requested. * @param request price request parameters. * @return the State. */ function getState( address requester, bytes32 identifier, uint32 timestamp, bytes memory ancillaryData, Request memory request ) external virtual returns (OptimisticOracleInterface.State); /** * @notice Checks if a given request has resolved, expired or been settled (i.e the optimistic oracle has a price). * @param requester sender of the initial price request. * @param identifier price identifier to identify the existing request. * @param timestamp timestamp to identify the existing request. * @param ancillaryData ancillary data of the price being requested. * @param request price request parameters. The hash of these parameters must match with the request hash that is * associated with the price request unique ID {requester, identifier, timestamp, ancillaryData}, or this method * will revert. * @return boolean indicating true if price exists and false if not. */ function hasPrice( address requester, bytes32 identifier, uint32 timestamp, bytes memory ancillaryData, Request memory request ) public virtual returns (bool); /** * @notice Generates stamped ancillary data in the format that it would be used in the case of a price dispute. * @param ancillaryData ancillary data of the price being requested. * @param requester sender of the initial price request. * @return the stamped ancillary bytes. */ function stampAncillaryData(bytes memory ancillaryData, address requester) public pure virtual returns (bytes memory); } // File @openzeppelin/contracts/utils/math/[email protected] // OpenZeppelin Contracts v4.4.1 (utils/math/SafeMath.sol) // CAUTION // This version of SafeMath should only be used with Solidity 0.8 or later, // because it relies on the compiler's built in overflow checks. /** * @dev Wrappers over Solidity's arithmetic operations. * * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler * now has built in overflow checking. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the substraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { return a + b; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { return a * b; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b <= a, errorMessage); return a - b; } } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a / b; } } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a % b; } } } // File @openzeppelin/contracts/utils/math/[email protected] // OpenZeppelin Contracts v4.4.1 (utils/math/SignedSafeMath.sol) /** * @dev Wrappers over Solidity's arithmetic operations. * * NOTE: `SignedSafeMath` is no longer needed starting with Solidity 0.8. The compiler * now has built in overflow checking. */ library SignedSafeMath { /** * @dev Returns the multiplication of two signed integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(int256 a, int256 b) internal pure returns (int256) { return a * b; } /** * @dev Returns the integer division of two signed integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. * * Requirements: * * - The divisor cannot be zero. */ function div(int256 a, int256 b) internal pure returns (int256) { return a / b; } /** * @dev Returns the subtraction of two signed integers, reverting on * overflow. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(int256 a, int256 b) internal pure returns (int256) { return a - b; } /** * @dev Returns the addition of two signed integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(int256 a, int256 b) internal pure returns (int256) { return a + b; } } // File contracts/common/implementation/FixedPoint.sol /** * @title Library for fixed point arithmetic on uints */ library FixedPoint { using SafeMath for uint256; using SignedSafeMath for int256; // Supports 18 decimals. E.g., 1e18 represents "1", 5e17 represents "0.5". // For unsigned values: // This can represent a value up to (2^256 - 1)/10^18 = ~10^59. 10^59 will be stored internally as uint256 10^77. uint256 private constant FP_SCALING_FACTOR = 10**18; // --------------------------------------- UNSIGNED ----------------------------------------------------------------------------- struct Unsigned { uint256 rawValue; } /** * @notice Constructs an `Unsigned` from an unscaled uint, e.g., `b=5` gets stored internally as `5*(10**18)`. * @param a uint to convert into a FixedPoint. * @return the converted FixedPoint. */ function fromUnscaledUint(uint256 a) internal pure returns (Unsigned memory) { return Unsigned(a.mul(FP_SCALING_FACTOR)); } /** * @notice Whether `a` is equal to `b`. * @param a a FixedPoint. * @param b a uint256. * @return True if equal, or False. */ function isEqual(Unsigned memory a, uint256 b) internal pure returns (bool) { return a.rawValue == fromUnscaledUint(b).rawValue; } /** * @notice Whether `a` is equal to `b`. * @param a a FixedPoint. * @param b a FixedPoint. * @return True if equal, or False. */ function isEqual(Unsigned memory a, Unsigned memory b) internal pure returns (bool) { return a.rawValue == b.rawValue; } /** * @notice Whether `a` is greater than `b`. * @param a a FixedPoint. * @param b a FixedPoint. * @return True if `a > b`, or False. */ function isGreaterThan(Unsigned memory a, Unsigned memory b) internal pure returns (bool) { return a.rawValue > b.rawValue; } /** * @notice Whether `a` is greater than `b`. * @param a a FixedPoint. * @param b a uint256. * @return True if `a > b`, or False. */ function isGreaterThan(Unsigned memory a, uint256 b) internal pure returns (bool) { return a.rawValue > fromUnscaledUint(b).rawValue; } /** * @notice Whether `a` is greater than `b`. * @param a a uint256. * @param b a FixedPoint. * @return True if `a > b`, or False. */ function isGreaterThan(uint256 a, Unsigned memory b) internal pure returns (bool) { return fromUnscaledUint(a).rawValue > b.rawValue; } /** * @notice Whether `a` is greater than or equal to `b`. * @param a a FixedPoint. * @param b a FixedPoint. * @return True if `a >= b`, or False. */ function isGreaterThanOrEqual(Unsigned memory a, Unsigned memory b) internal pure returns (bool) { return a.rawValue >= b.rawValue; } /** * @notice Whether `a` is greater than or equal to `b`. * @param a a FixedPoint. * @param b a uint256. * @return True if `a >= b`, or False. */ function isGreaterThanOrEqual(Unsigned memory a, uint256 b) internal pure returns (bool) { return a.rawValue >= fromUnscaledUint(b).rawValue; } /** * @notice Whether `a` is greater than or equal to `b`. * @param a a uint256. * @param b a FixedPoint. * @return True if `a >= b`, or False. */ function isGreaterThanOrEqual(uint256 a, Unsigned memory b) internal pure returns (bool) { return fromUnscaledUint(a).rawValue >= b.rawValue; } /** * @notice Whether `a` is less than `b`. * @param a a FixedPoint. * @param b a FixedPoint. * @return True if `a < b`, or False. */ function isLessThan(Unsigned memory a, Unsigned memory b) internal pure returns (bool) { return a.rawValue < b.rawValue; } /** * @notice Whether `a` is less than `b`. * @param a a FixedPoint. * @param b a uint256. * @return True if `a < b`, or False. */ function isLessThan(Unsigned memory a, uint256 b) internal pure returns (bool) { return a.rawValue < fromUnscaledUint(b).rawValue; } /** * @notice Whether `a` is less than `b`. * @param a a uint256. * @param b a FixedPoint. * @return True if `a < b`, or False. */ function isLessThan(uint256 a, Unsigned memory b) internal pure returns (bool) { return fromUnscaledUint(a).rawValue < b.rawValue; } /** * @notice Whether `a` is less than or equal to `b`. * @param a a FixedPoint. * @param b a FixedPoint. * @return True if `a <= b`, or False. */ function isLessThanOrEqual(Unsigned memory a, Unsigned memory b) internal pure returns (bool) { return a.rawValue <= b.rawValue; } /** * @notice Whether `a` is less than or equal to `b`. * @param a a FixedPoint. * @param b a uint256. * @return True if `a <= b`, or False. */ function isLessThanOrEqual(Unsigned memory a, uint256 b) internal pure returns (bool) { return a.rawValue <= fromUnscaledUint(b).rawValue; } /** * @notice Whether `a` is less than or equal to `b`. * @param a a uint256. * @param b a FixedPoint. * @return True if `a <= b`, or False. */ function isLessThanOrEqual(uint256 a, Unsigned memory b) internal pure returns (bool) { return fromUnscaledUint(a).rawValue <= b.rawValue; } /** * @notice The minimum of `a` and `b`. * @param a a FixedPoint. * @param b a FixedPoint. * @return the minimum of `a` and `b`. */ function min(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) { return a.rawValue < b.rawValue ? a : b; } /** * @notice The maximum of `a` and `b`. * @param a a FixedPoint. * @param b a FixedPoint. * @return the maximum of `a` and `b`. */ function max(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) { return a.rawValue > b.rawValue ? a : b; } /** * @notice Adds two `Unsigned`s, reverting on overflow. * @param a a FixedPoint. * @param b a FixedPoint. * @return the sum of `a` and `b`. */ function add(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) { return Unsigned(a.rawValue.add(b.rawValue)); } /** * @notice Adds an `Unsigned` to an unscaled uint, reverting on overflow. * @param a a FixedPoint. * @param b a uint256. * @return the sum of `a` and `b`. */ function add(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory) { return add(a, fromUnscaledUint(b)); } /** * @notice Subtracts two `Unsigned`s, reverting on overflow. * @param a a FixedPoint. * @param b a FixedPoint. * @return the difference of `a` and `b`. */ function sub(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) { return Unsigned(a.rawValue.sub(b.rawValue)); } /** * @notice Subtracts an unscaled uint256 from an `Unsigned`, reverting on overflow. * @param a a FixedPoint. * @param b a uint256. * @return the difference of `a` and `b`. */ function sub(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory) { return sub(a, fromUnscaledUint(b)); } /** * @notice Subtracts an `Unsigned` from an unscaled uint256, reverting on overflow. * @param a a uint256. * @param b a FixedPoint. * @return the difference of `a` and `b`. */ function sub(uint256 a, Unsigned memory b) internal pure returns (Unsigned memory) { return sub(fromUnscaledUint(a), b); } /** * @notice Multiplies two `Unsigned`s, reverting on overflow. * @dev This will "floor" the product. * @param a a FixedPoint. * @param b a FixedPoint. * @return the product of `a` and `b`. */ function mul(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) { // There are two caveats with this computation: // 1. Max output for the represented number is ~10^41, otherwise an intermediate value overflows. 10^41 is // stored internally as a uint256 ~10^59. // 2. Results that can't be represented exactly are truncated not rounded. E.g., 1.4 * 2e-18 = 2.8e-18, which // would round to 3, but this computation produces the result 2. // No need to use SafeMath because FP_SCALING_FACTOR != 0. return Unsigned(a.rawValue.mul(b.rawValue) / FP_SCALING_FACTOR); } /** * @notice Multiplies an `Unsigned` and an unscaled uint256, reverting on overflow. * @dev This will "floor" the product. * @param a a FixedPoint. * @param b a uint256. * @return the product of `a` and `b`. */ function mul(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory) { return Unsigned(a.rawValue.mul(b)); } /** * @notice Multiplies two `Unsigned`s and "ceil's" the product, reverting on overflow. * @param a a FixedPoint. * @param b a FixedPoint. * @return the product of `a` and `b`. */ function mulCeil(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) { uint256 mulRaw = a.rawValue.mul(b.rawValue); uint256 mulFloor = mulRaw / FP_SCALING_FACTOR; uint256 mod = mulRaw.mod(FP_SCALING_FACTOR); if (mod != 0) { return Unsigned(mulFloor.add(1)); } else { return Unsigned(mulFloor); } } /** * @notice Multiplies an `Unsigned` and an unscaled uint256 and "ceil's" the product, reverting on overflow. * @param a a FixedPoint. * @param b a FixedPoint. * @return the product of `a` and `b`. */ function mulCeil(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory) { // Since b is an uint, there is no risk of truncation and we can just mul it normally return Unsigned(a.rawValue.mul(b)); } /** * @notice Divides one `Unsigned` by an `Unsigned`, reverting on overflow or division by 0. * @dev This will "floor" the quotient. * @param a a FixedPoint numerator. * @param b a FixedPoint denominator. * @return the quotient of `a` divided by `b`. */ function div(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) { // There are two caveats with this computation: // 1. Max value for the number dividend `a` represents is ~10^41, otherwise an intermediate value overflows. // 10^41 is stored internally as a uint256 10^59. // 2. Results that can't be represented exactly are truncated not rounded. E.g., 2 / 3 = 0.6 repeating, which // would round to 0.666666666666666667, but this computation produces the result 0.666666666666666666. return Unsigned(a.rawValue.mul(FP_SCALING_FACTOR).div(b.rawValue)); } /** * @notice Divides one `Unsigned` by an unscaled uint256, reverting on overflow or division by 0. * @dev This will "floor" the quotient. * @param a a FixedPoint numerator. * @param b a uint256 denominator. * @return the quotient of `a` divided by `b`. */ function div(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory) { return Unsigned(a.rawValue.div(b)); } /** * @notice Divides one unscaled uint256 by an `Unsigned`, reverting on overflow or division by 0. * @dev This will "floor" the quotient. * @param a a uint256 numerator. * @param b a FixedPoint denominator. * @return the quotient of `a` divided by `b`. */ function div(uint256 a, Unsigned memory b) internal pure returns (Unsigned memory) { return div(fromUnscaledUint(a), b); } /** * @notice Divides one `Unsigned` by an `Unsigned` and "ceil's" the quotient, reverting on overflow or division by 0. * @param a a FixedPoint numerator. * @param b a FixedPoint denominator. * @return the quotient of `a` divided by `b`. */ function divCeil(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) { uint256 aScaled = a.rawValue.mul(FP_SCALING_FACTOR); uint256 divFloor = aScaled.div(b.rawValue); uint256 mod = aScaled.mod(b.rawValue); if (mod != 0) { return Unsigned(divFloor.add(1)); } else { return Unsigned(divFloor); } } /** * @notice Divides one `Unsigned` by an unscaled uint256 and "ceil's" the quotient, reverting on overflow or division by 0. * @param a a FixedPoint numerator. * @param b a uint256 denominator. * @return the quotient of `a` divided by `b`. */ function divCeil(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory) { // Because it is possible that a quotient gets truncated, we can't just call "Unsigned(a.rawValue.div(b))" // similarly to mulCeil with a uint256 as the second parameter. Therefore we need to convert b into an Unsigned. // This creates the possibility of overflow if b is very large. return divCeil(a, fromUnscaledUint(b)); } /** * @notice Raises an `Unsigned` to the power of an unscaled uint256, reverting on overflow. E.g., `b=2` squares `a`. * @dev This will "floor" the result. * @param a a FixedPoint numerator. * @param b a uint256 denominator. * @return output is `a` to the power of `b`. */ function pow(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory output) { output = fromUnscaledUint(1); for (uint256 i = 0; i < b; i = i.add(1)) { output = mul(output, a); } } // ------------------------------------------------- SIGNED ------------------------------------------------------------- // Supports 18 decimals. E.g., 1e18 represents "1", 5e17 represents "0.5". // For signed values: // This can represent a value up (or down) to +-(2^255 - 1)/10^18 = ~10^58. 10^58 will be stored internally as int256 10^76. int256 private constant SFP_SCALING_FACTOR = 10**18; struct Signed { int256 rawValue; } function fromSigned(Signed memory a) internal pure returns (Unsigned memory) { require(a.rawValue >= 0, "Negative value provided"); return Unsigned(uint256(a.rawValue)); } function fromUnsigned(Unsigned memory a) internal pure returns (Signed memory) { require(a.rawValue <= uint256(type(int256).max), "Unsigned too large"); return Signed(int256(a.rawValue)); } /** * @notice Constructs a `Signed` from an unscaled int, e.g., `b=5` gets stored internally as `5*(10**18)`. * @param a int to convert into a FixedPoint.Signed. * @return the converted FixedPoint.Signed. */ function fromUnscaledInt(int256 a) internal pure returns (Signed memory) { return Signed(a.mul(SFP_SCALING_FACTOR)); } /** * @notice Whether `a` is equal to `b`. * @param a a FixedPoint.Signed. * @param b a int256. * @return True if equal, or False. */ function isEqual(Signed memory a, int256 b) internal pure returns (bool) { return a.rawValue == fromUnscaledInt(b).rawValue; } /** * @notice Whether `a` is equal to `b`. * @param a a FixedPoint.Signed. * @param b a FixedPoint.Signed. * @return True if equal, or False. */ function isEqual(Signed memory a, Signed memory b) internal pure returns (bool) { return a.rawValue == b.rawValue; } /** * @notice Whether `a` is greater than `b`. * @param a a FixedPoint.Signed. * @param b a FixedPoint.Signed. * @return True if `a > b`, or False. */ function isGreaterThan(Signed memory a, Signed memory b) internal pure returns (bool) { return a.rawValue > b.rawValue; } /** * @notice Whether `a` is greater than `b`. * @param a a FixedPoint.Signed. * @param b an int256. * @return True if `a > b`, or False. */ function isGreaterThan(Signed memory a, int256 b) internal pure returns (bool) { return a.rawValue > fromUnscaledInt(b).rawValue; } /** * @notice Whether `a` is greater than `b`. * @param a an int256. * @param b a FixedPoint.Signed. * @return True if `a > b`, or False. */ function isGreaterThan(int256 a, Signed memory b) internal pure returns (bool) { return fromUnscaledInt(a).rawValue > b.rawValue; } /** * @notice Whether `a` is greater than or equal to `b`. * @param a a FixedPoint.Signed. * @param b a FixedPoint.Signed. * @return True if `a >= b`, or False. */ function isGreaterThanOrEqual(Signed memory a, Signed memory b) internal pure returns (bool) { return a.rawValue >= b.rawValue; } /** * @notice Whether `a` is greater than or equal to `b`. * @param a a FixedPoint.Signed. * @param b an int256. * @return True if `a >= b`, or False. */ function isGreaterThanOrEqual(Signed memory a, int256 b) internal pure returns (bool) { return a.rawValue >= fromUnscaledInt(b).rawValue; } /** * @notice Whether `a` is greater than or equal to `b`. * @param a an int256. * @param b a FixedPoint.Signed. * @return True if `a >= b`, or False. */ function isGreaterThanOrEqual(int256 a, Signed memory b) internal pure returns (bool) { return fromUnscaledInt(a).rawValue >= b.rawValue; } /** * @notice Whether `a` is less than `b`. * @param a a FixedPoint.Signed. * @param b a FixedPoint.Signed. * @return True if `a < b`, or False. */ function isLessThan(Signed memory a, Signed memory b) internal pure returns (bool) { return a.rawValue < b.rawValue; } /** * @notice Whether `a` is less than `b`. * @param a a FixedPoint.Signed. * @param b an int256. * @return True if `a < b`, or False. */ function isLessThan(Signed memory a, int256 b) internal pure returns (bool) { return a.rawValue < fromUnscaledInt(b).rawValue; } /** * @notice Whether `a` is less than `b`. * @param a an int256. * @param b a FixedPoint.Signed. * @return True if `a < b`, or False. */ function isLessThan(int256 a, Signed memory b) internal pure returns (bool) { return fromUnscaledInt(a).rawValue < b.rawValue; } /** * @notice Whether `a` is less than or equal to `b`. * @param a a FixedPoint.Signed. * @param b a FixedPoint.Signed. * @return True if `a <= b`, or False. */ function isLessThanOrEqual(Signed memory a, Signed memory b) internal pure returns (bool) { return a.rawValue <= b.rawValue; } /** * @notice Whether `a` is less than or equal to `b`. * @param a a FixedPoint.Signed. * @param b an int256. * @return True if `a <= b`, or False. */ function isLessThanOrEqual(Signed memory a, int256 b) internal pure returns (bool) { return a.rawValue <= fromUnscaledInt(b).rawValue; } /** * @notice Whether `a` is less than or equal to `b`. * @param a an int256. * @param b a FixedPoint.Signed. * @return True if `a <= b`, or False. */ function isLessThanOrEqual(int256 a, Signed memory b) internal pure returns (bool) { return fromUnscaledInt(a).rawValue <= b.rawValue; } /** * @notice The minimum of `a` and `b`. * @param a a FixedPoint.Signed. * @param b a FixedPoint.Signed. * @return the minimum of `a` and `b`. */ function min(Signed memory a, Signed memory b) internal pure returns (Signed memory) { return a.rawValue < b.rawValue ? a : b; } /** * @notice The maximum of `a` and `b`. * @param a a FixedPoint.Signed. * @param b a FixedPoint.Signed. * @return the maximum of `a` and `b`. */ function max(Signed memory a, Signed memory b) internal pure returns (Signed memory) { return a.rawValue > b.rawValue ? a : b; } /** * @notice Adds two `Signed`s, reverting on overflow. * @param a a FixedPoint.Signed. * @param b a FixedPoint.Signed. * @return the sum of `a` and `b`. */ function add(Signed memory a, Signed memory b) internal pure returns (Signed memory) { return Signed(a.rawValue.add(b.rawValue)); } /** * @notice Adds an `Signed` to an unscaled int, reverting on overflow. * @param a a FixedPoint.Signed. * @param b an int256. * @return the sum of `a` and `b`. */ function add(Signed memory a, int256 b) internal pure returns (Signed memory) { return add(a, fromUnscaledInt(b)); } /** * @notice Subtracts two `Signed`s, reverting on overflow. * @param a a FixedPoint.Signed. * @param b a FixedPoint.Signed. * @return the difference of `a` and `b`. */ function sub(Signed memory a, Signed memory b) internal pure returns (Signed memory) { return Signed(a.rawValue.sub(b.rawValue)); } /** * @notice Subtracts an unscaled int256 from an `Signed`, reverting on overflow. * @param a a FixedPoint.Signed. * @param b an int256. * @return the difference of `a` and `b`. */ function sub(Signed memory a, int256 b) internal pure returns (Signed memory) { return sub(a, fromUnscaledInt(b)); } /** * @notice Subtracts an `Signed` from an unscaled int256, reverting on overflow. * @param a an int256. * @param b a FixedPoint.Signed. * @return the difference of `a` and `b`. */ function sub(int256 a, Signed memory b) internal pure returns (Signed memory) { return sub(fromUnscaledInt(a), b); } /** * @notice Multiplies two `Signed`s, reverting on overflow. * @dev This will "floor" the product. * @param a a FixedPoint.Signed. * @param b a FixedPoint.Signed. * @return the product of `a` and `b`. */ function mul(Signed memory a, Signed memory b) internal pure returns (Signed memory) { // There are two caveats with this computation: // 1. Max output for the represented number is ~10^41, otherwise an intermediate value overflows. 10^41 is // stored internally as an int256 ~10^59. // 2. Results that can't be represented exactly are truncated not rounded. E.g., 1.4 * 2e-18 = 2.8e-18, which // would round to 3, but this computation produces the result 2. // No need to use SafeMath because SFP_SCALING_FACTOR != 0. return Signed(a.rawValue.mul(b.rawValue) / SFP_SCALING_FACTOR); } /** * @notice Multiplies an `Signed` and an unscaled int256, reverting on overflow. * @dev This will "floor" the product. * @param a a FixedPoint.Signed. * @param b an int256. * @return the product of `a` and `b`. */ function mul(Signed memory a, int256 b) internal pure returns (Signed memory) { return Signed(a.rawValue.mul(b)); } /** * @notice Multiplies two `Signed`s and "ceil's" the product, reverting on overflow. * @param a a FixedPoint.Signed. * @param b a FixedPoint.Signed. * @return the product of `a` and `b`. */ function mulAwayFromZero(Signed memory a, Signed memory b) internal pure returns (Signed memory) { int256 mulRaw = a.rawValue.mul(b.rawValue); int256 mulTowardsZero = mulRaw / SFP_SCALING_FACTOR; // Manual mod because SignedSafeMath doesn't support it. int256 mod = mulRaw % SFP_SCALING_FACTOR; if (mod != 0) { bool isResultPositive = isLessThan(a, 0) == isLessThan(b, 0); int256 valueToAdd = isResultPositive ? int256(1) : int256(-1); return Signed(mulTowardsZero.add(valueToAdd)); } else { return Signed(mulTowardsZero); } } /** * @notice Multiplies an `Signed` and an unscaled int256 and "ceil's" the product, reverting on overflow. * @param a a FixedPoint.Signed. * @param b a FixedPoint.Signed. * @return the product of `a` and `b`. */ function mulAwayFromZero(Signed memory a, int256 b) internal pure returns (Signed memory) { // Since b is an int, there is no risk of truncation and we can just mul it normally return Signed(a.rawValue.mul(b)); } /** * @notice Divides one `Signed` by an `Signed`, reverting on overflow or division by 0. * @dev This will "floor" the quotient. * @param a a FixedPoint numerator. * @param b a FixedPoint denominator. * @return the quotient of `a` divided by `b`. */ function div(Signed memory a, Signed memory b) internal pure returns (Signed memory) { // There are two caveats with this computation: // 1. Max value for the number dividend `a` represents is ~10^41, otherwise an intermediate value overflows. // 10^41 is stored internally as an int256 10^59. // 2. Results that can't be represented exactly are truncated not rounded. E.g., 2 / 3 = 0.6 repeating, which // would round to 0.666666666666666667, but this computation produces the result 0.666666666666666666. return Signed(a.rawValue.mul(SFP_SCALING_FACTOR).div(b.rawValue)); } /** * @notice Divides one `Signed` by an unscaled int256, reverting on overflow or division by 0. * @dev This will "floor" the quotient. * @param a a FixedPoint numerator. * @param b an int256 denominator. * @return the quotient of `a` divided by `b`. */ function div(Signed memory a, int256 b) internal pure returns (Signed memory) { return Signed(a.rawValue.div(b)); } /** * @notice Divides one unscaled int256 by an `Signed`, reverting on overflow or division by 0. * @dev This will "floor" the quotient. * @param a an int256 numerator. * @param b a FixedPoint denominator. * @return the quotient of `a` divided by `b`. */ function div(int256 a, Signed memory b) internal pure returns (Signed memory) { return div(fromUnscaledInt(a), b); } /** * @notice Divides one `Signed` by an `Signed` and "ceil's" the quotient, reverting on overflow or division by 0. * @param a a FixedPoint numerator. * @param b a FixedPoint denominator. * @return the quotient of `a` divided by `b`. */ function divAwayFromZero(Signed memory a, Signed memory b) internal pure returns (Signed memory) { int256 aScaled = a.rawValue.mul(SFP_SCALING_FACTOR); int256 divTowardsZero = aScaled.div(b.rawValue); // Manual mod because SignedSafeMath doesn't support it. int256 mod = aScaled % b.rawValue; if (mod != 0) { bool isResultPositive = isLessThan(a, 0) == isLessThan(b, 0); int256 valueToAdd = isResultPositive ? int256(1) : int256(-1); return Signed(divTowardsZero.add(valueToAdd)); } else { return Signed(divTowardsZero); } } /** * @notice Divides one `Signed` by an unscaled int256 and "ceil's" the quotient, reverting on overflow or division by 0. * @param a a FixedPoint numerator. * @param b an int256 denominator. * @return the quotient of `a` divided by `b`. */ function divAwayFromZero(Signed memory a, int256 b) internal pure returns (Signed memory) { // Because it is possible that a quotient gets truncated, we can't just call "Signed(a.rawValue.div(b))" // similarly to mulCeil with an int256 as the second parameter. Therefore we need to convert b into an Signed. // This creates the possibility of overflow if b is very large. return divAwayFromZero(a, fromUnscaledInt(b)); } /** * @notice Raises an `Signed` to the power of an unscaled uint256, reverting on overflow. E.g., `b=2` squares `a`. * @dev This will "floor" the result. * @param a a FixedPoint.Signed. * @param b a uint256 (negative exponents are not allowed). * @return output is `a` to the power of `b`. */ function pow(Signed memory a, uint256 b) internal pure returns (Signed memory output) { output = fromUnscaledInt(1); for (uint256 i = 0; i < b; i = i.add(1)) { output = mul(output, a); } } } // File contracts/oracle/interfaces/StoreInterface.sol /** * @title Interface that allows financial contracts to pay oracle fees for their use of the system. */ interface StoreInterface { /** * @notice Pays Oracle fees in ETH to the store. * @dev To be used by contracts whose margin currency is ETH. */ function payOracleFees() external payable; /** * @notice Pays oracle fees in the margin currency, erc20Address, to the store. * @dev To be used if the margin currency is an ERC20 token rather than ETH. * @param erc20Address address of the ERC20 token used to pay the fee. * @param amount number of tokens to transfer. An approval for at least this amount must exist. */ function payOracleFeesErc20(address erc20Address, FixedPoint.Unsigned calldata amount) external; /** * @notice Computes the regular oracle fees that a contract should pay for a period. * @param startTime defines the beginning time from which the fee is paid. * @param endTime end time until which the fee is paid. * @param pfc "profit from corruption", or the maximum amount of margin currency that a * token sponsor could extract from the contract through corrupting the price feed in their favor. * @return regularFee amount owed for the duration from start to end time for the given pfc. * @return latePenalty for paying the fee after the deadline. */ function computeRegularFee( uint256 startTime, uint256 endTime, FixedPoint.Unsigned calldata pfc ) external view returns (FixedPoint.Unsigned memory regularFee, FixedPoint.Unsigned memory latePenalty); /** * @notice Computes the final oracle fees that a contract should pay at settlement. * @param currency token used to pay the final fee. * @return finalFee amount due. */ function computeFinalFee(address currency) external view returns (FixedPoint.Unsigned memory); } // File contracts/oracle/interfaces/FinderInterface.sol /** * @title Provides addresses of the live contracts implementing certain interfaces. * @dev Examples are the Oracle or Store interfaces. */ interface FinderInterface { /** * @notice Updates the address of the contract that implements `interfaceName`. * @param interfaceName bytes32 encoding of the interface name that is either changed or registered. * @param implementationAddress address of the deployed contract that implements the interface. */ function changeImplementationAddress(bytes32 interfaceName, address implementationAddress) external; /** * @notice Gets the address of the contract that implements the given `interfaceName`. * @param interfaceName queried interface. * @return implementationAddress address of the deployed contract that implements the interface. */ function getImplementationAddress(bytes32 interfaceName) external view returns (address); } // File contracts/oracle/implementation/Constants.sol /** * @title Stores common interface names used throughout the DVM by registration in the Finder. */ library OracleInterfaces { bytes32 public constant Oracle = "Oracle"; bytes32 public constant IdentifierWhitelist = "IdentifierWhitelist"; bytes32 public constant Store = "Store"; bytes32 public constant FinancialContractsAdmin = "FinancialContractsAdmin"; bytes32 public constant Registry = "Registry"; bytes32 public constant CollateralWhitelist = "CollateralWhitelist"; bytes32 public constant OptimisticOracle = "OptimisticOracle"; bytes32 public constant Bridge = "Bridge"; bytes32 public constant GenericHandler = "GenericHandler"; bytes32 public constant SkinnyOptimisticOracle = "SkinnyOptimisticOracle"; bytes32 public constant ChildMessenger = "ChildMessenger"; bytes32 public constant OracleHub = "OracleHub"; bytes32 public constant OracleSpoke = "OracleSpoke"; } /** * @title Commonly re-used values for contracts associated with the OptimisticOracle. */ library OptimisticOracleConstraints { // Any price request submitted to the OptimisticOracle must contain ancillary data no larger than this value. // This value must be <= the Voting contract's `ancillaryBytesLimit` constant value otherwise it is possible // that a price can be requested to the OptimisticOracle successfully, but cannot be resolved by the DVM which // refuses to accept a price request made with ancillary data length over a certain size. uint256 public constant ancillaryBytesLimit = 8192; } // File contracts/common/implementation/AncillaryData.sol /** * @title Library for encoding and decoding ancillary data for DVM price requests. * @notice We assume that on-chain ancillary data can be formatted directly from bytes to utf8 encoding via * web3.utils.hexToUtf8, and that clients will parse the utf8-encoded ancillary data as a comma-delimitted key-value * dictionary. Therefore, this library provides internal methods that aid appending to ancillary data from Solidity * smart contracts. More details on UMA's ancillary data guidelines below: * https://docs.google.com/document/d/1zhKKjgY1BupBGPPrY_WOJvui0B6DMcd-xDR8-9-SPDw/edit */ library AncillaryData { // This converts the bottom half of a bytes32 input to hex in a highly gas-optimized way. // Source: the brilliant implementation at https://gitter.im/ethereum/solidity?at=5840d23416207f7b0ed08c9b. function toUtf8Bytes32Bottom(bytes32 bytesIn) private pure returns (bytes32) { unchecked { uint256 x = uint256(bytesIn); // Nibble interleave x = x & 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff; x = (x | (x * 2**64)) & 0x0000000000000000ffffffffffffffff0000000000000000ffffffffffffffff; x = (x | (x * 2**32)) & 0x00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff; x = (x | (x * 2**16)) & 0x0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff; x = (x | (x * 2**8)) & 0x00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff; x = (x | (x * 2**4)) & 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f; // Hex encode uint256 h = (x & 0x0808080808080808080808080808080808080808080808080808080808080808) / 8; uint256 i = (x & 0x0404040404040404040404040404040404040404040404040404040404040404) / 4; uint256 j = (x & 0x0202020202020202020202020202020202020202020202020202020202020202) / 2; x = x + (h & (i | j)) * 0x27 + 0x3030303030303030303030303030303030303030303030303030303030303030; // Return the result. return bytes32(x); } } /** * @notice Returns utf8-encoded bytes32 string that can be read via web3.utils.hexToUtf8. * @dev Will return bytes32 in all lower case hex characters and without the leading 0x. * This has minor changes from the toUtf8BytesAddress to control for the size of the input. * @param bytesIn bytes32 to encode. * @return utf8 encoded bytes32. */ function toUtf8Bytes(bytes32 bytesIn) internal pure returns (bytes memory) { return abi.encodePacked(toUtf8Bytes32Bottom(bytesIn >> 128), toUtf8Bytes32Bottom(bytesIn)); } /** * @notice Returns utf8-encoded address that can be read via web3.utils.hexToUtf8. * Source: https://ethereum.stackexchange.com/questions/8346/convert-address-to-string/8447#8447 * @dev Will return address in all lower case characters and without the leading 0x. * @param x address to encode. * @return utf8 encoded address bytes. */ function toUtf8BytesAddress(address x) internal pure returns (bytes memory) { return abi.encodePacked(toUtf8Bytes32Bottom(bytes32(bytes20(x)) >> 128), bytes8(toUtf8Bytes32Bottom(bytes20(x)))); } /** * @notice Converts a uint into a base-10, UTF-8 representation stored in a `string` type. * @dev This method is based off of this code: https://stackoverflow.com/a/65707309. */ function toUtf8BytesUint(uint256 x) internal pure returns (bytes memory) { if (x == 0) { return "0"; } uint256 j = x; uint256 len; while (j != 0) { len++; j /= 10; } bytes memory bstr = new bytes(len); uint256 k = len; while (x != 0) { k = k - 1; uint8 temp = (48 + uint8(x - (x / 10) * 10)); bytes1 b1 = bytes1(temp); bstr[k] = b1; x /= 10; } return bstr; } function appendKeyValueBytes32( bytes memory currentAncillaryData, bytes memory key, bytes32 value ) internal pure returns (bytes memory) { bytes memory prefix = constructPrefix(currentAncillaryData, key); return abi.encodePacked(currentAncillaryData, prefix, toUtf8Bytes(value)); } /** * @notice Adds "key:value" to `currentAncillaryData` where `value` is an address that first needs to be converted * to utf8 bytes. For example, if `utf8(currentAncillaryData)="k1:v1"`, then this function will return * `utf8(k1:v1,key:value)`, and if `currentAncillaryData` is blank, then this will return `utf8(key:value)`. * @param currentAncillaryData This bytes data should ideally be able to be utf8-decoded, but its OK if not. * @param key Again, this bytes data should ideally be able to be utf8-decoded, but its OK if not. * @param value An address to set as the value in the key:value pair to append to `currentAncillaryData`. * @return Newly appended ancillary data. */ function appendKeyValueAddress( bytes memory currentAncillaryData, bytes memory key, address value ) internal pure returns (bytes memory) { bytes memory prefix = constructPrefix(currentAncillaryData, key); return abi.encodePacked(currentAncillaryData, prefix, toUtf8BytesAddress(value)); } /** * @notice Adds "key:value" to `currentAncillaryData` where `value` is a uint that first needs to be converted * to utf8 bytes. For example, if `utf8(currentAncillaryData)="k1:v1"`, then this function will return * `utf8(k1:v1,key:value)`, and if `currentAncillaryData` is blank, then this will return `utf8(key:value)`. * @param currentAncillaryData This bytes data should ideally be able to be utf8-decoded, but its OK if not. * @param key Again, this bytes data should ideally be able to be utf8-decoded, but its OK if not. * @param value A uint to set as the value in the key:value pair to append to `currentAncillaryData`. * @return Newly appended ancillary data. */ function appendKeyValueUint( bytes memory currentAncillaryData, bytes memory key, uint256 value ) internal pure returns (bytes memory) { bytes memory prefix = constructPrefix(currentAncillaryData, key); return abi.encodePacked(currentAncillaryData, prefix, toUtf8BytesUint(value)); } /** * @notice Helper method that returns the left hand side of a "key:value" pair plus the colon ":" and a leading * comma "," if the `currentAncillaryData` is not empty. The return value is intended to be prepended as a prefix to * some utf8 value that is ultimately added to a comma-delimited, key-value dictionary. */ function constructPrefix(bytes memory currentAncillaryData, bytes memory key) internal pure returns (bytes memory) { if (currentAncillaryData.length > 0) { return abi.encodePacked(",", key, ":"); } else { return abi.encodePacked(key, ":"); } } } // File contracts/common/implementation/Timer.sol /** * @title Universal store of current contract time for testing environments. */ contract Timer { uint256 private currentTime; constructor() { currentTime = block.timestamp; // solhint-disable-line not-rely-on-time } /** * @notice Sets the current time. * @dev Will revert if not running in test mode. * @param time timestamp to set `currentTime` to. */ function setCurrentTime(uint256 time) external { currentTime = time; } /** * @notice Gets the currentTime variable set in the Timer. * @return uint256 for the current Testable timestamp. */ function getCurrentTime() public view returns (uint256) { return currentTime; } } // File contracts/common/implementation/Testable.sol /** * @title Base class that provides time overrides, but only if being run in test mode. */ abstract contract Testable { // If the contract is being run in production, then `timerAddress` will be the 0x0 address. // Note: this variable should be set on construction and never modified. address public timerAddress; /** * @notice Constructs the Testable contract. Called by child contracts. * @param _timerAddress Contract that stores the current time in a testing environment. * Must be set to 0x0 for production environments that use live time. */ constructor(address _timerAddress) { timerAddress = _timerAddress; } /** * @notice Reverts if not running in test mode. */ modifier onlyIfTest { require(timerAddress != address(0x0)); _; } /** * @notice Sets the current time. * @dev Will revert if not running in test mode. * @param time timestamp to set current Testable time to. */ function setCurrentTime(uint256 time) external onlyIfTest { Timer(timerAddress).setCurrentTime(time); } /** * @notice Gets the current time. Will return the last time set in `setCurrentTime` if running in test mode. * Otherwise, it will return the block timestamp. * @return uint for the current Testable timestamp. */ function getCurrentTime() public view virtual returns (uint256) { if (timerAddress != address(0x0)) { return Timer(timerAddress).getCurrentTime(); } else { return block.timestamp; // solhint-disable-line not-rely-on-time } } } // File contracts/common/implementation/Lockable.sol /** * @title A contract that provides modifiers to prevent reentrancy to state-changing and view-only methods. This contract * is inspired by https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/ReentrancyGuard.sol * and https://github.com/balancer-labs/balancer-core/blob/master/contracts/BPool.sol. */ contract Lockable { bool private _notEntered; constructor() { // Storing an initial non-zero value makes deployment a bit more expensive, but in exchange the refund on every // call to nonReentrant will be lower in amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to increase the likelihood of the full // refund coming into effect. _notEntered = true; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` function is not supported. It is possible to * prevent this from happening by making the `nonReentrant` function external, and making it call a `private` * function that does the actual state modification. */ modifier nonReentrant() { _preEntranceCheck(); _preEntranceSet(); _; _postEntranceReset(); } /** * @dev Designed to prevent a view-only method from being re-entered during a call to a `nonReentrant()` state-changing method. */ modifier nonReentrantView() { _preEntranceCheck(); _; } // Internal methods are used to avoid copying the require statement's bytecode to every `nonReentrant()` method. // On entry into a function, `_preEntranceCheck()` should always be called to check if the function is being // re-entered. Then, if the function modifies state, it should call `_postEntranceSet()`, perform its logic, and // then call `_postEntranceReset()`. // View-only methods can simply call `_preEntranceCheck()` to make sure that it is not being re-entered. function _preEntranceCheck() internal view { // On the first call to nonReentrant, _notEntered will be true require(_notEntered, "ReentrancyGuard: reentrant call"); } function _preEntranceSet() internal { // Any calls to nonReentrant after this point will fail _notEntered = false; } function _postEntranceReset() internal { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _notEntered = true; } } // File contracts/common/implementation/MultiCaller.sol // This contract is taken from Uniswaps's multi call implementation (https://github.com/Uniswap/uniswap-v3-periphery/blob/main/contracts/base/Multicall.sol) // and was modified to be solidity 0.8 compatible. Additionally, the method was restricted to only work with msg.value // set to 0 to avoid any nasty attack vectors on function calls that use value sent with deposits. /// @title MultiCaller /// @notice Enables calling multiple methods in a single call to the contract contract MultiCaller { function multicall(bytes[] calldata data) external payable returns (bytes[] memory results) { require(msg.value == 0, "Only multicall with 0 value"); results = new bytes[](data.length); for (uint256 i = 0; i < data.length; i++) { (bool success, bytes memory result) = address(this).delegatecall(data[i]); if (!success) { // Next 5 lines from https://ethereum.stackexchange.com/a/83577 if (result.length < 68) revert(); assembly { result := add(result, 0x04) } revert(abi.decode(result, (string))); } results[i] = result; } } } // File @openzeppelin/contracts/token/ERC20/extensions/[email protected] // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); } // File @openzeppelin/contracts/utils/[email protected] // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } } // File @openzeppelin/contracts/token/ERC20/[email protected] // OpenZeppelin Contracts v4.4.1 (token/ERC20/ERC20.sol) /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20, IERC20Metadata { mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * The default value of {decimals} is 18. To select a different value for * {decimals} you should overload it. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the value {ERC20} uses, unless this function is * overridden; * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual override returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `recipient` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address recipient, uint256 amount) public virtual override returns (bool) { _transfer(_msgSender(), recipient, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { _approve(_msgSender(), spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * Requirements: * * - `sender` and `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. * - the caller must have allowance for ``sender``'s tokens of at least * `amount`. */ function transferFrom( address sender, address recipient, uint256 amount ) public virtual override returns (bool) { _transfer(sender, recipient, amount); uint256 currentAllowance = _allowances[sender][_msgSender()]; require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); unchecked { _approve(sender, _msgSender(), currentAllowance - amount); } return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { uint256 currentAllowance = _allowances[_msgSender()][spender]; require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); unchecked { _approve(_msgSender(), spender, currentAllowance - subtractedValue); } return true; } /** * @dev Moves `amount` of tokens from `sender` to `recipient`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `sender` cannot be the zero address. * - `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. */ function _transfer( address sender, address recipient, uint256 amount ) internal virtual { require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(sender, recipient, amount); uint256 senderBalance = _balances[sender]; require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); unchecked { _balances[sender] = senderBalance - amount; } _balances[recipient] += amount; emit Transfer(sender, recipient, amount); _afterTokenTransfer(sender, recipient, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply += amount; _balances[account] += amount; emit Transfer(address(0), account, amount); _afterTokenTransfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); unchecked { _balances[account] = accountBalance - amount; } _totalSupply -= amount; emit Transfer(account, address(0), amount); _afterTokenTransfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve( address owner, address spender, uint256 amount ) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 amount ) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * has been transferred to `to`. * - when `from` is zero, `amount` tokens have been minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens have been burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 amount ) internal virtual {} } // File @openzeppelin/contracts/utils/[email protected] // OpenZeppelin Contracts v4.4.1 (utils/Address.sol) /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } } // File @openzeppelin/contracts/token/ERC20/utils/[email protected] // OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol) /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } } // File contracts/insured-bridge/BridgePool.sol interface WETH9Like { function withdraw(uint256 wad) external; function deposit() external payable; } /** * @notice Contract deployed on L1 that provides methods for "Relayers" to fulfill deposit orders that originated on L2. * The Relayers can either post capital to fulfill the deposit (instant relay), or request that the funds are taken out * of a passive liquidity provider pool following a challenge period (slow relay). This contract ingests liquidity from * passive liquidity providers and returns them claims to withdraw their funds. Liquidity providers are incentivized * to post collateral by earning a fee per fulfilled deposit order. * @dev A "Deposit" is an order to send capital from L2 to L1, and a "Relay" is a fulfillment attempt of that order. */ contract BridgePool is MultiCaller, Testable, BridgePoolInterface, ERC20, Lockable { using SafeERC20 for IERC20; using FixedPoint for FixedPoint.Unsigned; using Address for address; // Token that this contract receives as LP deposits. IERC20 public override l1Token; // Track the total number of relays and uniquely identifies relays. uint32 public numberOfRelays; // Reserves that are unutilized and withdrawable. uint256 public liquidReserves; // Reserves currently utilized due to L2-L1 transactions in flight. int256 public utilizedReserves; // Reserves that are not yet utilized but are pre-allocated for a pending relay. uint256 public pendingReserves; // True If this pool stores WETH. If the withdrawn token is WETH then unwrap and send ETH when finalizing // relays. Also enable LPs to receive ETH, if they choose, when withdrawing liquidity. bool public isWethPool; // Enables the Bridge Admin to enable/disable relays in this pool. Disables relayDeposit and relayAndSpeedUp. bool public relaysEnabled = true; // Exponential decay exchange rate to accumulate fees to LPs over time. This can be changed via the BridgeAdmin. uint64 public lpFeeRatePerSecond; // Last timestamp that LP fees were updated. uint32 public lastLpFeeUpdate; // Store local instances of contract params to save gas relaying. uint64 public proposerBondPct; uint32 public optimisticOracleLiveness; // Store local instance of the reserve currency final fee. This is a gas optimization to not re-call the store. uint256 l1TokenFinalFee; // Cumulative undistributed LP fees. As fees accumulate, they are subtracted from this number. uint256 public undistributedLpFees; // Total bond amount held for pending relays. Bonds are released following a successful relay or after a dispute. uint256 public bonds; // Administrative contract that deployed this contract and also houses all state variables needed to relay deposits. BridgeAdminInterface public bridgeAdmin; // Store local instances of the contract instances to save gas relaying. Can be sync with the Finder at any time via // the syncUmaEcosystemParams() public function. StoreInterface public store; SkinnyOptimisticOracleInterface public optimisticOracle; // DVM price request identifier that is resolved based on the validity of a relay attempt. bytes32 public identifier; // A Relay represents an attempt to finalize a cross-chain transfer that originated on an L2 DepositBox contract. // The flow chart between states is as follows: // - Begin at Uninitialized. // - When relayDeposit() is called, a new relay is created with state Pending and mapped to the L2 deposit hash. // - If the relay is disputed, the RelayData gets deleted and the L2 deposit hash has no relay mapped to it anymore. // - The above statements enable state to transfer between the Uninitialized and Pending states. // - When settleRelay() is successfully called, the relay state gets set to Finalized and cannot change from there. // - It is impossible for a relay to be deleted when in Finalized state (and have its state set to Uninitialized) // because the only way for settleRelay() to succeed is if the price has resolved on the OptimisticOracle. // - You cannot dispute an already resolved request on the OptimisticOracle. Moreover, the mapping from // a relay's ancillary data hash to its deposit hash is deleted after a successful settleRelay() call. enum RelayState { Uninitialized, Pending, Finalized } // Data from L2 deposit transaction. struct DepositData { uint256 chainId; uint64 depositId; address payable l1Recipient; address l2Sender; uint256 amount; uint64 slowRelayFeePct; uint64 instantRelayFeePct; uint32 quoteTimestamp; } // Each L2 Deposit can have one Relay attempt at any one time. A Relay attempt is characterized by its RelayData. struct RelayData { RelayState relayState; address slowRelayer; uint32 relayId; uint64 realizedLpFeePct; uint32 priceRequestTime; uint256 proposerBond; uint256 finalFee; } // Associate deposits with pending relay data. When the mapped relay hash is empty, new relay attempts can be made // for this deposit. The relay data contains information necessary to pay out relayers on successful relay. // Relay hashes are deleted when they are disputed on the OptimisticOracle. mapping(bytes32 => bytes32) public relays; // Map hash of deposit and realized-relay fee to instant relayers. This mapping is checked at settlement time // to determine if there was a valid instant relayer. mapping(bytes32 => address) public instantRelays; event LiquidityAdded(uint256 amount, uint256 lpTokensMinted, address indexed liquidityProvider); event LiquidityRemoved(uint256 amount, uint256 lpTokensBurnt, address indexed liquidityProvider); event DepositRelayed( bytes32 indexed depositHash, DepositData depositData, RelayData relay, bytes32 relayAncillaryDataHash ); event RelaySpedUp(bytes32 indexed depositHash, address indexed instantRelayer, RelayData relay); // Note: the difference between a dispute and a cancellation is that a cancellation happens in the case where // something changes in the OO between request and dispute that causes calls to it to fail. The most common // case would be an increase in final fee. However, things like whitelisting can also cause problems. event RelayDisputed(bytes32 indexed depositHash, bytes32 indexed relayHash, address indexed disputer); event RelayCanceled(bytes32 indexed depositHash, bytes32 indexed relayHash, address indexed disputer); event RelaySettled(bytes32 indexed depositHash, address indexed caller, RelayData relay); event BridgePoolAdminTransferred(address oldAdmin, address newAdmin); event RelaysEnabledSet(bool newRelaysEnabled); event LpFeeRateSet(uint64 newLpFeeRatePerSecond); modifier onlyBridgeAdmin() { require(msg.sender == address(bridgeAdmin), "Caller not bridge admin"); _; } modifier onlyIfRelaysEnabld() { require(relaysEnabled, "Relays are disabled"); _; } /** * @notice Construct the Bridge Pool. * @param _lpTokenName Name of the LP token to be deployed by this contract. * @param _lpTokenSymbol Symbol of the LP token to be deployed by this contract. * @param _bridgeAdmin Admin contract deployed alongside on L1. Stores global variables and has owner control. * @param _l1Token Address of the L1 token that this bridgePool holds. This is the token LPs deposit and is bridged. * @param _lpFeeRatePerSecond Interest rate payment that scales the amount of pending fees per second paid to LPs. * @param _isWethPool Toggles if this is the WETH pool. If it is then can accept ETH and wrap to WETH for the user. * @param _timer Timer used to synchronize contract time in testing. Set to 0x000... in production. */ constructor( string memory _lpTokenName, string memory _lpTokenSymbol, address _bridgeAdmin, address _l1Token, uint64 _lpFeeRatePerSecond, bool _isWethPool, address _timer ) Testable(_timer) ERC20(_lpTokenName, _lpTokenSymbol) { require(bytes(_lpTokenName).length != 0 && bytes(_lpTokenSymbol).length != 0, "Bad LP token name or symbol"); bridgeAdmin = BridgeAdminInterface(_bridgeAdmin); l1Token = IERC20(_l1Token); lastLpFeeUpdate = uint32(getCurrentTime()); lpFeeRatePerSecond = _lpFeeRatePerSecond; isWethPool = _isWethPool; syncUmaEcosystemParams(); // Fetch OptimisticOracle and Store addresses and L1Token finalFee. syncWithBridgeAdminParams(); // Fetch ProposerBondPct OptimisticOracleLiveness, Identifier from the BridgeAdmin. emit LpFeeRateSet(lpFeeRatePerSecond); } /************************************************* * LIQUIDITY PROVIDER FUNCTIONS * *************************************************/ /** * @notice Add liquidity to the bridge pool. Pulls l1Token from the caller's wallet. The caller is sent back a * commensurate number of LP tokens (minted to their address) at the prevailing exchange rate. * @dev The caller must approve this contract to transfer `l1TokenAmount` amount of l1Token if depositing ERC20. * @dev The caller can deposit ETH which is auto wrapped to WETH. This can only be done if: a) this is the Weth pool * and b) the l1TokenAmount matches to the transaction msg.value. * @dev Reentrancy guard not added to this function because this indirectly calls sync() which is guarded. * @param l1TokenAmount Number of l1Token to add as liquidity. */ function addLiquidity(uint256 l1TokenAmount) public payable nonReentrant() { // If this is the weth pool and the caller sends msg.value then the msg.value must match the l1TokenAmount. // Else, msg.value must be set to 0. require((isWethPool && msg.value == l1TokenAmount) || msg.value == 0, "Bad add liquidity Eth value"); // Since `exchangeRateCurrent()` reads this contract's balance and updates contract state using it, // we must call it first before transferring any tokens to this contract. uint256 lpTokensToMint = (l1TokenAmount * 1e18) / _exchangeRateCurrent(); _mint(msg.sender, lpTokensToMint); liquidReserves += l1TokenAmount; if (msg.value > 0 && isWethPool) WETH9Like(address(l1Token)).deposit{ value: msg.value }(); else l1Token.safeTransferFrom(msg.sender, address(this), l1TokenAmount); emit LiquidityAdded(l1TokenAmount, lpTokensToMint, msg.sender); } /** * @notice Removes liquidity from the bridge pool. Burns lpTokenAmount LP tokens from the caller's wallet. The caller * is sent back a commensurate number of l1Tokens at the prevailing exchange rate. * @dev The caller does not need to approve the spending of LP tokens as this method directly uses the burn logic. * @dev Reentrancy guard not added to this function because this indirectly calls sync() which is guarded. * @param lpTokenAmount Number of lpTokens to redeem for underlying. * @param sendEth Enable the liquidity provider to remove liquidity in ETH, if this is the WETH pool. */ function removeLiquidity(uint256 lpTokenAmount, bool sendEth) public nonReentrant() { // Can only send eth on withdrawing liquidity iff this is the WETH pool. require(!sendEth || isWethPool, "Cant send eth"); uint256 l1TokensToReturn = (lpTokenAmount * _exchangeRateCurrent()) / 1e18; // Check that there is enough liquid reserves to withdraw the requested amount. require(liquidReserves >= (pendingReserves + l1TokensToReturn), "Utilization too high to remove"); _burn(msg.sender, lpTokenAmount); liquidReserves -= l1TokensToReturn; if (sendEth) _unwrapWETHTo(payable(msg.sender), l1TokensToReturn); else l1Token.safeTransfer(msg.sender, l1TokensToReturn); emit LiquidityRemoved(l1TokensToReturn, lpTokenAmount, msg.sender); } /************************************** * RELAYER FUNCTIONS * **************************************/ /** * @notice Called by Relayer to execute a slow + fast relay from L2 to L1, fulfilling a corresponding deposit order. * @dev There can only be one pending relay for a deposit. This method is effectively the relayDeposit and * speedUpRelay methods concatenated. This could be refactored to just call each method, but there * are some gas savings in combining the transfers and hash computations. * @dev Caller must have approved this contract to spend the total bond + amount - fees for `l1Token`. * @dev This function can only be called if relays are enabled for this bridge pool. * @param depositData the deposit data struct containing all the user's deposit information. * @param realizedLpFeePct LP fee calculated off-chain considering the L1 pool liquidity at deposit time, before * quoteTimestamp. The OO acts to verify the correctness of this realized fee. Cannot exceed 50%. */ function relayAndSpeedUp(DepositData memory depositData, uint64 realizedLpFeePct) public onlyIfRelaysEnabld() nonReentrant() { // If no pending relay for this deposit, then associate the caller's relay attempt with it. uint32 priceRequestTime = uint32(getCurrentTime()); // The realizedLPFeePct should never be greater than 0.5e18 and the slow and instant relay fees should never be // more than 0.25e18 each. Therefore, the sum of all fee types can never exceed 1e18 (or 100%). require( depositData.slowRelayFeePct <= 0.25e18 && depositData.instantRelayFeePct <= 0.25e18 && realizedLpFeePct <= 0.5e18, "Invalid fees" ); // Check if there is a pending relay for this deposit. bytes32 depositHash = _getDepositHash(depositData); // Note: A disputed relay deletes the stored relay hash and enables this require statement to pass. require(relays[depositHash] == bytes32(0), "Pending relay exists"); uint256 proposerBond = _getProposerBond(depositData.amount); // Save hash of new relay attempt parameters. // Note: The liveness for this relay can be changed in the BridgeAdmin, which means that each relay has a // potentially variable liveness time. This should not provide any exploit opportunities, especially because // the BridgeAdmin state (including the liveness value) is permissioned to the cross domained owner. RelayData memory relayData = RelayData({ relayState: RelayState.Pending, slowRelayer: msg.sender, relayId: numberOfRelays++, // Note: Increment numberOfRelays at the same time as setting relayId to its current value. realizedLpFeePct: realizedLpFeePct, priceRequestTime: priceRequestTime, proposerBond: proposerBond, finalFee: l1TokenFinalFee }); bytes32 relayHash = _getRelayHash(depositData, relayData); relays[depositHash] = _getRelayDataHash(relayData); bytes32 instantRelayHash = _getInstantRelayHash(depositHash, relayData); require( // Can only speed up a pending relay without an existing instant relay associated with it. instantRelays[instantRelayHash] == address(0), "Relay cannot be sped up" ); // Sanity check that pool has enough balance to cover relay amount + proposer reward. Reward amount will be // paid on settlement after the OptimisticOracle price request has passed the challenge period. // Note: liquidReserves should always be <= balance - bonds. require(liquidReserves - pendingReserves >= depositData.amount, "Insufficient pool balance"); // Compute total proposal bond and pull from caller so that the OptimisticOracle can pull it from here. uint256 totalBond = proposerBond + l1TokenFinalFee; // Pull relay amount minus fees from caller and send to the deposit l1Recipient. The total fees paid is the sum // of the LP fees, the relayer fees and the instant relay fee. uint256 feesTotal = _getAmountFromPct( relayData.realizedLpFeePct + depositData.slowRelayFeePct + depositData.instantRelayFeePct, depositData.amount ); // If the L1 token is WETH then: a) pull WETH from instant relayer b) unwrap WETH c) send ETH to recipient. uint256 recipientAmount = depositData.amount - feesTotal; bonds += totalBond; pendingReserves += depositData.amount; // Book off maximum liquidity used by this relay in the pending reserves. instantRelays[instantRelayHash] = msg.sender; l1Token.safeTransferFrom(msg.sender, address(this), recipientAmount + totalBond); // If this is a weth pool then unwrap and send eth. if (isWethPool) { _unwrapWETHTo(depositData.l1Recipient, recipientAmount); // Else, this is a normal ERC20 token. Send to recipient. } else l1Token.safeTransfer(depositData.l1Recipient, recipientAmount); emit DepositRelayed(depositHash, depositData, relayData, relayHash); emit RelaySpedUp(depositHash, msg.sender, relayData); } /** * @notice Called by Disputer to dispute an ongoing relay. * @dev The result of this method is to always throw out the relay, providing an opportunity for another relay for * the same deposit. Between the disputer and proposer, whoever is incorrect loses their bond. Whoever is correct * gets it back + a payout. * @dev Caller must have approved this contract to spend the total bond + amount - fees for `l1Token`. * @param depositData the deposit data struct containing all the user's deposit information. * @param relayData RelayData logged in the disputed relay. */ function disputeRelay(DepositData memory depositData, RelayData memory relayData) public nonReentrant() { require(relayData.priceRequestTime + optimisticOracleLiveness > getCurrentTime(), "Past liveness"); require(relayData.relayState == RelayState.Pending, "Not disputable"); // Validate the input data. bytes32 depositHash = _getDepositHash(depositData); _validateRelayDataHash(depositHash, relayData); // Submit the proposal and dispute to the OO. bytes32 relayHash = _getRelayHash(depositData, relayData); // Note: in some cases this will fail due to changes in the OO and the method will refund the relayer. bool success = _requestProposeDispute( relayData.slowRelayer, msg.sender, relayData.proposerBond, relayData.finalFee, _getRelayAncillaryData(relayHash) ); // Drop the relay and remove the bond from the tracked bonds. bonds -= relayData.finalFee + relayData.proposerBond; pendingReserves -= depositData.amount; delete relays[depositHash]; if (success) emit RelayDisputed(depositHash, _getRelayDataHash(relayData), msg.sender); else emit RelayCanceled(depositHash, _getRelayDataHash(relayData), msg.sender); } /** * @notice Called by Relayer to execute a slow relay from L2 to L1, fulfilling a corresponding deposit order. * @dev There can only be one pending relay for a deposit. * @dev Caller must have approved this contract to spend the total bond + amount - fees for `l1Token`. * @dev This function can only be called if relays are enabled for this bridge pool. * @param depositData the deposit data struct containing all the user's deposit information. * @param realizedLpFeePct LP fee calculated off-chain considering the L1 pool liquidity at deposit time, before * quoteTimestamp. The OO acts to verify the correctness of this realized fee. Cannot exceed 50%. */ function relayDeposit(DepositData memory depositData, uint64 realizedLpFeePct) public onlyIfRelaysEnabld() nonReentrant() { // The realizedLPFeePct should never be greater than 0.5e18 and the slow and instant relay fees should never be // more than 0.25e18 each. Therefore, the sum of all fee types can never exceed 1e18 (or 100%). require( depositData.slowRelayFeePct <= 0.25e18 && depositData.instantRelayFeePct <= 0.25e18 && realizedLpFeePct <= 0.5e18, "Invalid fees" ); // Check if there is a pending relay for this deposit. bytes32 depositHash = _getDepositHash(depositData); // Note: A disputed relay deletes the stored relay hash and enables this require statement to pass. require(relays[depositHash] == bytes32(0), "Pending relay exists"); // If no pending relay for this deposit, then associate the caller's relay attempt with it. uint32 priceRequestTime = uint32(getCurrentTime()); uint256 proposerBond = _getProposerBond(depositData.amount); // Save hash of new relay attempt parameters. // Note: The liveness for this relay can be changed in the BridgeAdmin, which means that each relay has a // potentially variable liveness time. This should not provide any exploit opportunities, especially because // the BridgeAdmin state (including the liveness value) is permissioned to the cross domained owner. RelayData memory relayData = RelayData({ relayState: RelayState.Pending, slowRelayer: msg.sender, relayId: numberOfRelays++, // Note: Increment numberOfRelays at the same time as setting relayId to its current value. realizedLpFeePct: realizedLpFeePct, priceRequestTime: priceRequestTime, proposerBond: proposerBond, finalFee: l1TokenFinalFee }); relays[depositHash] = _getRelayDataHash(relayData); bytes32 relayHash = _getRelayHash(depositData, relayData); // Sanity check that pool has enough balance to cover relay amount + proposer reward. Reward amount will be // paid on settlement after the OptimisticOracle price request has passed the challenge period. // Note: liquidReserves should always be <= balance - bonds. require(liquidReserves - pendingReserves >= depositData.amount, "Insufficient pool balance"); // Compute total proposal bond and pull from caller so that the OptimisticOracle can pull it from here. uint256 totalBond = proposerBond + l1TokenFinalFee; pendingReserves += depositData.amount; // Book off maximum liquidity used by this relay in the pending reserves. bonds += totalBond; l1Token.safeTransferFrom(msg.sender, address(this), totalBond); emit DepositRelayed(depositHash, depositData, relayData, relayHash); } /** * @notice Instantly relay a deposit amount minus fees to the l1Recipient. Instant relayer earns a reward following * the pending relay challenge period. * @dev We assume that the caller has performed an off-chain check that the deposit data they are attempting to * relay is valid. If the deposit data is invalid, then the instant relayer has no recourse to receive their funds * back after the invalid deposit data is disputed. Moreover, no one will be able to resubmit a relay for the * invalid deposit data because they know it will get disputed again. On the other hand, if the deposit data is * valid, then even if it is falsely disputed, the instant relayer will eventually get reimbursed because someone * else will be incentivized to resubmit the relay to earn slow relayer rewards. Once the valid relay is finalized, * the instant relayer will be reimbursed. Therefore, the caller has the same responsibility as the disputer in * validating the relay data. * @dev Caller must have approved this contract to spend the deposit amount of L1 tokens to relay. There can only * be one instant relayer per relay attempt. You cannot speed up a relay that is past liveness. * @param depositData Unique set of L2 deposit data that caller is trying to instantly relay. * @param relayData Parameters of Relay that caller is attempting to speedup. Must hash to the stored relay hash * for this deposit or this method will revert. */ function speedUpRelay(DepositData memory depositData, RelayData memory relayData) public nonReentrant() { bytes32 depositHash = _getDepositHash(depositData); _validateRelayDataHash(depositHash, relayData); bytes32 instantRelayHash = _getInstantRelayHash(depositHash, relayData); require( // Can only speed up a pending relay without an existing instant relay associated with it. getCurrentTime() < relayData.priceRequestTime + optimisticOracleLiveness && relayData.relayState == RelayState.Pending && instantRelays[instantRelayHash] == address(0), "Relay cannot be sped up" ); instantRelays[instantRelayHash] = msg.sender; // Pull relay amount minus fees from caller and send to the deposit l1Recipient. The total fees paid is the sum // of the LP fees, the relayer fees and the instant relay fee. uint256 feesTotal = _getAmountFromPct( relayData.realizedLpFeePct + depositData.slowRelayFeePct + depositData.instantRelayFeePct, depositData.amount ); // If the L1 token is WETH then: a) pull WETH from instant relayer b) unwrap WETH c) send ETH to recipient. uint256 recipientAmount = depositData.amount - feesTotal; if (isWethPool) { l1Token.safeTransferFrom(msg.sender, address(this), recipientAmount); _unwrapWETHTo(depositData.l1Recipient, recipientAmount); // Else, this is a normal ERC20 token. Send to recipient. } else l1Token.safeTransferFrom(msg.sender, depositData.l1Recipient, recipientAmount); emit RelaySpedUp(depositHash, msg.sender, relayData); } /** * @notice Reward relayers if a pending relay price request has a price available on the OptimisticOracle. Mark * the relay as complete. * @dev We use the relayData and depositData to compute the ancillary data that the relay price request is uniquely * associated with on the OptimisticOracle. If the price request passed in does not match the pending relay price * request, then this will revert. * @param depositData Unique set of L2 deposit data that caller is trying to settle a relay for. * @param relayData Parameters of Relay that caller is attempting to settle. Must hash to the stored relay hash * for this deposit. */ function settleRelay(DepositData memory depositData, RelayData memory relayData) public nonReentrant() { bytes32 depositHash = _getDepositHash(depositData); _validateRelayDataHash(depositHash, relayData); require(relayData.relayState == RelayState.Pending, "Already settled"); uint32 expirationTime = relayData.priceRequestTime + optimisticOracleLiveness; require(expirationTime <= getCurrentTime(), "Not settleable yet"); // Note: this check is to give the relayer a small, but reasonable amount of time to complete the relay before // before it can be "stolen" by someone else. This is to ensure there is an incentive to settle relays quickly. require( msg.sender == relayData.slowRelayer || getCurrentTime() > expirationTime + 15 minutes, "Not slow relayer" ); // Update the relay state to Finalized. This prevents any re-settling of a relay. relays[depositHash] = _getRelayDataHash( RelayData({ relayState: RelayState.Finalized, slowRelayer: relayData.slowRelayer, relayId: relayData.relayId, realizedLpFeePct: relayData.realizedLpFeePct, priceRequestTime: relayData.priceRequestTime, proposerBond: relayData.proposerBond, finalFee: relayData.finalFee }) ); // Reward relayers and pay out l1Recipient. // At this point there are two possible cases: // - This was a slow relay: In this case, a) pay the slow relayer their reward and b) pay the l1Recipient of the // amount minus the realized LP fee and the slow Relay fee. The transfer was not sped up so no instant fee. // - This was an instant relay: In this case, a) pay the slow relayer their reward and b) pay the instant relayer // the full bridging amount, minus the realized LP fee and minus the slow relay fee. When the instant // relayer called speedUpRelay they were docked this same amount, minus the instant relayer fee. As a // result, they are effectively paid what they spent when speeding up the relay + the instantRelayFee. uint256 instantRelayerOrRecipientAmount = depositData.amount - _getAmountFromPct(relayData.realizedLpFeePct + depositData.slowRelayFeePct, depositData.amount); // Refund the instant relayer iff the instant relay params match the approved relay. bytes32 instantRelayHash = _getInstantRelayHash(depositHash, relayData); address instantRelayer = instantRelays[instantRelayHash]; // If this is the WETH pool and the instant relayer is is address 0x0 (i.e the relay was not sped up) then: // a) withdraw WETH to ETH and b) send the ETH to the recipient. if (isWethPool && instantRelayer == address(0)) { _unwrapWETHTo(depositData.l1Recipient, instantRelayerOrRecipientAmount); // Else, this is a normal slow relay being finalizes where the contract sends ERC20 to the recipient OR this // is the finalization of an instant relay where we need to reimburse the instant relayer in WETH. } else l1Token.safeTransfer( instantRelayer != address(0) ? instantRelayer : depositData.l1Recipient, instantRelayerOrRecipientAmount ); // There is a fee and a bond to pay out. The fee goes to whoever settles. The bond always goes back to the // slow relayer. // Note: for gas efficiency, we use an if so we can combine these transfers in the event that they are the same // address. uint256 slowRelayerReward = _getAmountFromPct(depositData.slowRelayFeePct, depositData.amount); uint256 totalBond = relayData.finalFee + relayData.proposerBond; if (relayData.slowRelayer == msg.sender) l1Token.safeTransfer(relayData.slowRelayer, slowRelayerReward + totalBond); else { l1Token.safeTransfer(relayData.slowRelayer, totalBond); l1Token.safeTransfer(msg.sender, slowRelayerReward); } uint256 totalReservesSent = instantRelayerOrRecipientAmount + slowRelayerReward; // Update reserves by amounts changed and allocated LP fees. pendingReserves -= depositData.amount; liquidReserves -= totalReservesSent; utilizedReserves += int256(totalReservesSent); bonds -= totalBond; _updateAccumulatedLpFees(); _allocateLpFees(_getAmountFromPct(relayData.realizedLpFeePct, depositData.amount)); emit RelaySettled(depositHash, msg.sender, relayData); // Clean up state storage and receive gas refund. This also prevents `priceDisputed()` from being able to reset // this newly Finalized relay state. delete instantRelays[instantRelayHash]; } /** * @notice Synchronize any balance changes in this contract with the utilized & liquid reserves. This would be done * at the conclusion of an L2 -> L1 token transfer via the canonical token bridge. */ function sync() public nonReentrant() { _sync(); } /** * @notice Computes the exchange rate between LP tokens and L1Tokens. Used when adding/removing liquidity. * @return The updated exchange rate between LP tokens and L1 tokens. */ function exchangeRateCurrent() public nonReentrant() returns (uint256) { return _exchangeRateCurrent(); } /** * @notice Computes the current liquidity utilization ratio. * @dev Used in computing realizedLpFeePct off-chain. * @return The current utilization ratio. */ function liquidityUtilizationCurrent() public nonReentrant() returns (uint256) { return _liquidityUtilizationPostRelay(0); } /** * @notice Computes the liquidity utilization ratio post a relay of known size. * @dev Used in computing realizedLpFeePct off-chain. * @param relayedAmount Size of the relayed deposit to factor into the utilization calculation. * @return The updated utilization ratio accounting for a new `relayedAmount`. */ function liquidityUtilizationPostRelay(uint256 relayedAmount) public nonReentrant() returns (uint256) { return _liquidityUtilizationPostRelay(relayedAmount); } /** * @notice Return both the current utilization value and liquidity utilization post the relay. * @dev Used in computing realizedLpFeePct off-chain. * @param relayedAmount Size of the relayed deposit to factor into the utilization calculation. * @return utilizationCurrent The current utilization ratio. * @return utilizationPostRelay The updated utilization ratio accounting for a new `relayedAmount`. */ function getLiquidityUtilization(uint256 relayedAmount) public nonReentrant() returns (uint256 utilizationCurrent, uint256 utilizationPostRelay) { return (_liquidityUtilizationPostRelay(0), _liquidityUtilizationPostRelay(relayedAmount)); } /** * @notice Updates the address stored in this contract for the OptimisticOracle and the Store to the latest versions * set in the the Finder. Also pull finalFee Store these as local variables to make relay methods gas efficient. * @dev There is no risk of leaving this function public for anyone to call as in all cases we want the addresses * in this contract to map to the latest version in the Finder and store the latest final fee. */ function syncUmaEcosystemParams() public nonReentrant() { FinderInterface finder = FinderInterface(bridgeAdmin.finder()); optimisticOracle = SkinnyOptimisticOracleInterface( finder.getImplementationAddress(OracleInterfaces.SkinnyOptimisticOracle) ); store = StoreInterface(finder.getImplementationAddress(OracleInterfaces.Store)); l1TokenFinalFee = store.computeFinalFee(address(l1Token)).rawValue; } /** * @notice Updates the values of stored constants for the proposerBondPct, optimisticOracleLiveness and identifier * to that set in the bridge Admin. We store these as local variables to make the relay methods more gas efficient. * @dev There is no risk of leaving this function public for anyone to call as in all cases we want these values * in this contract to map to the latest version set in the BridgeAdmin. */ function syncWithBridgeAdminParams() public nonReentrant() { proposerBondPct = bridgeAdmin.proposerBondPct(); optimisticOracleLiveness = bridgeAdmin.optimisticOracleLiveness(); identifier = bridgeAdmin.identifier(); } /************************************ * ADMIN FUNCTIONS * ************************************/ /** * @notice Enable the current bridge admin to transfer admin to to a new address. * @dev Caller must be BridgeAdmin contract. * @param _newAdmin Admin address of the new admin. */ function changeAdmin(address _newAdmin) public override onlyBridgeAdmin() nonReentrant() { bridgeAdmin = BridgeAdminInterface(_newAdmin); emit BridgePoolAdminTransferred(msg.sender, _newAdmin); } /** * @notice Enable the bridge admin to change the decay rate at which LP shares accumulate fees. The higher this * value, the faster LP shares realize pending fees. * @dev Caller must be BridgeAdmin contract. * @param _newLpFeeRatePerSecond The new rate to set. */ function setLpFeeRatePerSecond(uint64 _newLpFeeRatePerSecond) public override onlyBridgeAdmin() nonReentrant() { lpFeeRatePerSecond = _newLpFeeRatePerSecond; emit LpFeeRateSet(lpFeeRatePerSecond); } /** * @notice Enable the bridge admin to enable/disable relays for this pool. Acts as a pause. Only effects * relayDeposit and relayAndSpeedUp methods. ALl other contract logic remains functional after a pause. * @dev Caller must be BridgeAdmin contract. * @param _relaysEnabled The new relaysEnabled state. */ function setRelaysEnabled(bool _relaysEnabled) public override onlyBridgeAdmin() nonReentrant() { relaysEnabled = _relaysEnabled; emit RelaysEnabledSet(_relaysEnabled); } /************************************ * VIEW FUNCTIONS * ************************************/ /** * @notice Computes the current amount of unallocated fees that have accumulated from the previous time this the * contract was called. */ function getAccumulatedFees() public view nonReentrantView() returns (uint256) { return _getAccumulatedFees(); } /** * @notice Returns ancillary data containing all relevant Relay data that voters can format into UTF8 and use to * determine if the relay is valid. * @dev Helpful method to test that ancillary data is constructed properly. We should consider removing if we don't * anticipate off-chain bots or users to call this method. * @param depositData Contains L2 deposit information used by off-chain validators to validate relay. * @param relayData Contains relay information used by off-chain validators to validate relay. * @return bytes New ancillary data that can be decoded into UTF8. */ function getRelayAncillaryData(DepositData memory depositData, RelayData memory relayData) public view nonReentrantView() returns (bytes memory) { return _getRelayAncillaryData(_getRelayHash(depositData, relayData)); } /************************************** * INTERNAL & PRIVATE FUNCTIONS * **************************************/ function _liquidityUtilizationPostRelay(uint256 relayedAmount) internal returns (uint256) { _sync(); // Fetch any balance changes due to token bridging finalization and factor them in. // liquidityUtilizationRatio := // (relayedAmount + pendingReserves + max(utilizedReserves,0)) / (liquidReserves + max(utilizedReserves,0)) // UtilizedReserves has a dual meaning: if it's greater than zero then it represents funds pending in the bridge // that will flow from L2 to L1. In this case, we can use it normally in the equation. However, if it is // negative, then it is already counted in liquidReserves. This occurs if tokens are transferred directly to the // contract. In this case, ignore it as it is captured in liquid reserves and has no meaning in the numerator. uint256 flooredUtilizedReserves = utilizedReserves > 0 ? uint256(utilizedReserves) : 0; uint256 numerator = relayedAmount + pendingReserves + flooredUtilizedReserves; uint256 denominator = liquidReserves + flooredUtilizedReserves; // If the denominator equals zero, return 1e18 (max utilization). if (denominator == 0) return 1e18; // In all other cases, return the utilization ratio. return (numerator * 1e18) / denominator; } function _sync() internal { // Check if the l1Token balance of the contract is greater than the liquidReserves. If it is then the bridging // action from L2 -> L1 has concluded and the local accounting can be updated. uint256 l1TokenBalance = l1Token.balanceOf(address(this)) - bonds; if (l1TokenBalance > liquidReserves) { // utilizedReserves can go to less than zero. This will happen if the accumulated fees exceeds the current // outstanding utilization. In other words, if outstanding bridging transfers are 0 then utilizedReserves // will equal the total LP fees accumulated over all time. utilizedReserves -= int256(l1TokenBalance - liquidReserves); liquidReserves = l1TokenBalance; } } function _exchangeRateCurrent() internal returns (uint256) { if (totalSupply() == 0) return 1e18; // initial rate is 1 pre any mint action. // First, update fee counters and local accounting of finalized transfers from L2 -> L1. _updateAccumulatedLpFees(); // Accumulate all allocated fees from the last time this method was called. _sync(); // Fetch any balance changes due to token bridging finalization and factor them in. // ExchangeRate := (liquidReserves + utilizedReserves - undistributedLpFees) / lpTokenSupply // Note that utilizedReserves can be negative. If this is the case, then liquidReserves is offset by an equal // and opposite size. LiquidReserves + utilizedReserves will always be larger than undistributedLpFees so this // int will always be positive so there is no risk in underflow in type casting in the return line. int256 numerator = int256(liquidReserves) + utilizedReserves - int256(undistributedLpFees); return (uint256(numerator) * 1e18) / totalSupply(); } // Return UTF8-decodable ancillary data for relay price request associated with relay hash. function _getRelayAncillaryData(bytes32 relayHash) private pure returns (bytes memory) { return AncillaryData.appendKeyValueBytes32("", "relayHash", relayHash); } // Returns hash of unique relay and deposit event. This is added to the relay request's ancillary data. function _getRelayHash(DepositData memory depositData, RelayData memory relayData) private view returns (bytes32) { return keccak256(abi.encode(depositData, relayData.relayId, relayData.realizedLpFeePct, address(l1Token))); } // Return hash of relay data, which is stored in state and mapped to a deposit hash. function _getRelayDataHash(RelayData memory relayData) private pure returns (bytes32) { return keccak256(abi.encode(relayData)); } // Reverts if the stored relay data hash for `depositHash` does not match `_relayData`. function _validateRelayDataHash(bytes32 depositHash, RelayData memory relayData) private view { require( relays[depositHash] == _getRelayDataHash(relayData), "Hashed relay params do not match existing relay hash for deposit" ); } // Return hash of unique instant relay and deposit event. This is stored in state and mapped to a deposit hash. function _getInstantRelayHash(bytes32 depositHash, RelayData memory relayData) private pure returns (bytes32) { // Only include parameters that affect the "correctness" of an instant relay. For example, the realized LP fee // % directly affects how many tokens the instant relayer needs to send to the user, whereas the address of the // instant relayer does not matter for determining whether an instant relay is "correct". return keccak256(abi.encode(depositHash, relayData.realizedLpFeePct)); } function _getAccumulatedFees() internal view returns (uint256) { // UnallocatedLpFees := min(undistributedLpFees*lpFeeRatePerSecond*timeFromLastInteraction,undistributedLpFees) // The min acts to pay out all fees in the case the equation returns more than the remaining a fees. uint256 possibleUnpaidFees = (undistributedLpFees * lpFeeRatePerSecond * (getCurrentTime() - lastLpFeeUpdate)) / (1e18); return possibleUnpaidFees < undistributedLpFees ? possibleUnpaidFees : undistributedLpFees; } // Update internal fee counters by adding in any accumulated fees from the last time this logic was called. function _updateAccumulatedLpFees() internal { // Calculate the unallocatedAccumulatedFees from the last time the contract was called. uint256 unallocatedAccumulatedFees = _getAccumulatedFees(); // Decrement the undistributedLpFees by the amount of accumulated fees. undistributedLpFees = undistributedLpFees - unallocatedAccumulatedFees; lastLpFeeUpdate = uint32(getCurrentTime()); } // Allocate fees to the LPs by incrementing counters. function _allocateLpFees(uint256 allocatedLpFees) internal { // Add to the total undistributed LP fees and the utilized reserves. Adding it to the utilized reserves acts to // track the fees while they are in transit. undistributedLpFees += allocatedLpFees; utilizedReserves += int256(allocatedLpFees); } function _getAmountFromPct(uint64 percent, uint256 amount) private pure returns (uint256) { return (percent * amount) / 1e18; } function _getProposerBond(uint256 amount) private view returns (uint256) { return _getAmountFromPct(proposerBondPct, amount); } function _getDepositHash(DepositData memory depositData) private view returns (bytes32) { return keccak256(abi.encode(depositData, address(l1Token))); } // Proposes new price of True for relay event associated with `customAncillaryData` to optimistic oracle. If anyone // disagrees with the relay parameters and whether they map to an L2 deposit, they can dispute with the oracle. function _requestProposeDispute( address proposer, address disputer, uint256 proposerBond, uint256 finalFee, bytes memory customAncillaryData ) private returns (bool) { uint256 totalBond = finalFee + proposerBond; l1Token.safeApprove(address(optimisticOracle), totalBond); try optimisticOracle.requestAndProposePriceFor( identifier, uint32(getCurrentTime()), customAncillaryData, IERC20(l1Token), // Set reward to 0, since we'll settle proposer reward payouts directly from this contract after a relay // proposal has passed the challenge period. 0, // Set the Optimistic oracle proposer bond for the price request. proposerBond, // Set the Optimistic oracle liveness for the price request. optimisticOracleLiveness, proposer, // Canonical value representing "True"; i.e. the proposed relay is valid. int256(1e18) ) returns (uint256 bondSpent) { if (bondSpent < totalBond) { // If the OO pulls less (due to a change in final fee), refund the proposer. uint256 refund = totalBond - bondSpent; l1Token.safeTransfer(proposer, refund); l1Token.safeApprove(address(optimisticOracle), 0); totalBond = bondSpent; } } catch { // If there's an error in the OO, this means something has changed to make this request undisputable. // To ensure the request does not go through by default, refund the proposer and return early, allowing // the calling method to delete the request, but with no additional recourse by the OO. l1Token.safeTransfer(proposer, totalBond); l1Token.safeApprove(address(optimisticOracle), 0); // Return early noting that the attempt at a proposal + dispute did not succeed. return false; } SkinnyOptimisticOracleInterface.Request memory request = SkinnyOptimisticOracleInterface.Request({ proposer: proposer, disputer: address(0), currency: IERC20(l1Token), settled: false, proposedPrice: int256(1e18), resolvedPrice: 0, expirationTime: getCurrentTime() + optimisticOracleLiveness, reward: 0, finalFee: totalBond - proposerBond, bond: proposerBond, customLiveness: uint256(optimisticOracleLiveness) }); // Note: don't pull funds until here to avoid any transfers that aren't needed. l1Token.safeTransferFrom(msg.sender, address(this), totalBond); l1Token.safeApprove(address(optimisticOracle), totalBond); // Dispute the request that we just sent. optimisticOracle.disputePriceFor( identifier, uint32(getCurrentTime()), customAncillaryData, request, disputer, address(this) ); // Return true to denote that the proposal + dispute calls succeeded. return true; } // Unwraps ETH and does a transfer to a recipient address. If the recipient is a smart contract then sends WETH. function _unwrapWETHTo(address payable to, uint256 amount) internal { if (address(to).isContract()) { l1Token.safeTransfer(to, amount); } else { WETH9Like(address(l1Token)).withdraw(amount); to.transfer(amount); } } // Added to enable the BridgePool to receive ETH. used when unwrapping Weth. receive() external payable {} } /** * @notice This is the BridgePool contract that should be deployed on live networks. It is exactly the same as the * regular BridgePool contract, but it overrides getCurrentTime to make the call a simply return block.timestamp with * no branching or storage queries. This is done to save gas. */ contract BridgePoolProd is BridgePool { constructor( string memory _lpTokenName, string memory _lpTokenSymbol, address _bridgeAdmin, address _l1Token, uint64 _lpFeeRatePerSecond, bool _isWethPool, address _timer ) BridgePool(_lpTokenName, _lpTokenSymbol, _bridgeAdmin, _l1Token, _lpFeeRatePerSecond, _isWethPool, _timer) {} function getCurrentTime() public view virtual override returns (uint256) { return block.timestamp; } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"string","name":"_lpTokenName","type":"string"},{"internalType":"string","name":"_lpTokenSymbol","type":"string"},{"internalType":"address","name":"_bridgeAdmin","type":"address"},{"internalType":"address","name":"_l1Token","type":"address"},{"internalType":"uint64","name":"_lpFeeRatePerSecond","type":"uint64"},{"internalType":"bool","name":"_isWethPool","type":"bool"},{"internalType":"address","name":"_timer","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"BridgePoolAdminTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"depositHash","type":"bytes32"},{"components":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"uint64","name":"depositId","type":"uint64"},{"internalType":"address payable","name":"l1Recipient","type":"address"},{"internalType":"address","name":"l2Sender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint64","name":"slowRelayFeePct","type":"uint64"},{"internalType":"uint64","name":"instantRelayFeePct","type":"uint64"},{"internalType":"uint32","name":"quoteTimestamp","type":"uint32"}],"indexed":false,"internalType":"struct BridgePool.DepositData","name":"depositData","type":"tuple"},{"components":[{"internalType":"enum BridgePool.RelayState","name":"relayState","type":"uint8"},{"internalType":"address","name":"slowRelayer","type":"address"},{"internalType":"uint32","name":"relayId","type":"uint32"},{"internalType":"uint64","name":"realizedLpFeePct","type":"uint64"},{"internalType":"uint32","name":"priceRequestTime","type":"uint32"},{"internalType":"uint256","name":"proposerBond","type":"uint256"},{"internalType":"uint256","name":"finalFee","type":"uint256"}],"indexed":false,"internalType":"struct BridgePool.RelayData","name":"relay","type":"tuple"},{"indexed":false,"internalType":"bytes32","name":"relayAncillaryDataHash","type":"bytes32"}],"name":"DepositRelayed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lpTokensMinted","type":"uint256"},{"indexed":true,"internalType":"address","name":"liquidityProvider","type":"address"}],"name":"LiquidityAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lpTokensBurnt","type":"uint256"},{"indexed":true,"internalType":"address","name":"liquidityProvider","type":"address"}],"name":"LiquidityRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"newLpFeeRatePerSecond","type":"uint64"}],"name":"LpFeeRateSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"depositHash","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"relayHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"disputer","type":"address"}],"name":"RelayCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"depositHash","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"relayHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"disputer","type":"address"}],"name":"RelayDisputed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"depositHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"components":[{"internalType":"enum BridgePool.RelayState","name":"relayState","type":"uint8"},{"internalType":"address","name":"slowRelayer","type":"address"},{"internalType":"uint32","name":"relayId","type":"uint32"},{"internalType":"uint64","name":"realizedLpFeePct","type":"uint64"},{"internalType":"uint32","name":"priceRequestTime","type":"uint32"},{"internalType":"uint256","name":"proposerBond","type":"uint256"},{"internalType":"uint256","name":"finalFee","type":"uint256"}],"indexed":false,"internalType":"struct BridgePool.RelayData","name":"relay","type":"tuple"}],"name":"RelaySettled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"depositHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"instantRelayer","type":"address"},{"components":[{"internalType":"enum BridgePool.RelayState","name":"relayState","type":"uint8"},{"internalType":"address","name":"slowRelayer","type":"address"},{"internalType":"uint32","name":"relayId","type":"uint32"},{"internalType":"uint64","name":"realizedLpFeePct","type":"uint64"},{"internalType":"uint32","name":"priceRequestTime","type":"uint32"},{"internalType":"uint256","name":"proposerBond","type":"uint256"},{"internalType":"uint256","name":"finalFee","type":"uint256"}],"indexed":false,"internalType":"struct BridgePool.RelayData","name":"relay","type":"tuple"}],"name":"RelaySpedUp","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"newRelaysEnabled","type":"bool"}],"name":"RelaysEnabledSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"uint256","name":"l1TokenAmount","type":"uint256"}],"name":"addLiquidity","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bonds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bridgeAdmin","outputs":[{"internalType":"contract BridgeAdminInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_newAdmin","type":"address"}],"name":"changeAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"uint64","name":"depositId","type":"uint64"},{"internalType":"address payable","name":"l1Recipient","type":"address"},{"internalType":"address","name":"l2Sender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint64","name":"slowRelayFeePct","type":"uint64"},{"internalType":"uint64","name":"instantRelayFeePct","type":"uint64"},{"internalType":"uint32","name":"quoteTimestamp","type":"uint32"}],"internalType":"struct BridgePool.DepositData","name":"depositData","type":"tuple"},{"components":[{"internalType":"enum BridgePool.RelayState","name":"relayState","type":"uint8"},{"internalType":"address","name":"slowRelayer","type":"address"},{"internalType":"uint32","name":"relayId","type":"uint32"},{"internalType":"uint64","name":"realizedLpFeePct","type":"uint64"},{"internalType":"uint32","name":"priceRequestTime","type":"uint32"},{"internalType":"uint256","name":"proposerBond","type":"uint256"},{"internalType":"uint256","name":"finalFee","type":"uint256"}],"internalType":"struct BridgePool.RelayData","name":"relayData","type":"tuple"}],"name":"disputeRelay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"exchangeRateCurrent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAccumulatedFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"relayedAmount","type":"uint256"}],"name":"getLiquidityUtilization","outputs":[{"internalType":"uint256","name":"utilizationCurrent","type":"uint256"},{"internalType":"uint256","name":"utilizationPostRelay","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"uint64","name":"depositId","type":"uint64"},{"internalType":"address payable","name":"l1Recipient","type":"address"},{"internalType":"address","name":"l2Sender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint64","name":"slowRelayFeePct","type":"uint64"},{"internalType":"uint64","name":"instantRelayFeePct","type":"uint64"},{"internalType":"uint32","name":"quoteTimestamp","type":"uint32"}],"internalType":"struct BridgePool.DepositData","name":"depositData","type":"tuple"},{"components":[{"internalType":"enum BridgePool.RelayState","name":"relayState","type":"uint8"},{"internalType":"address","name":"slowRelayer","type":"address"},{"internalType":"uint32","name":"relayId","type":"uint32"},{"internalType":"uint64","name":"realizedLpFeePct","type":"uint64"},{"internalType":"uint32","name":"priceRequestTime","type":"uint32"},{"internalType":"uint256","name":"proposerBond","type":"uint256"},{"internalType":"uint256","name":"finalFee","type":"uint256"}],"internalType":"struct BridgePool.RelayData","name":"relayData","type":"tuple"}],"name":"getRelayAncillaryData","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"identifier","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"instantRelays","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isWethPool","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"l1Token","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastLpFeeUpdate","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"liquidReserves","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"liquidityUtilizationCurrent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"relayedAmount","type":"uint256"}],"name":"liquidityUtilizationPostRelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lpFeeRatePerSecond","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"numberOfRelays","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"optimisticOracle","outputs":[{"internalType":"contract SkinnyOptimisticOracleInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"optimisticOracleLiveness","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingReserves","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proposerBondPct","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"uint64","name":"depositId","type":"uint64"},{"internalType":"address payable","name":"l1Recipient","type":"address"},{"internalType":"address","name":"l2Sender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint64","name":"slowRelayFeePct","type":"uint64"},{"internalType":"uint64","name":"instantRelayFeePct","type":"uint64"},{"internalType":"uint32","name":"quoteTimestamp","type":"uint32"}],"internalType":"struct BridgePool.DepositData","name":"depositData","type":"tuple"},{"internalType":"uint64","name":"realizedLpFeePct","type":"uint64"}],"name":"relayAndSpeedUp","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"uint64","name":"depositId","type":"uint64"},{"internalType":"address payable","name":"l1Recipient","type":"address"},{"internalType":"address","name":"l2Sender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint64","name":"slowRelayFeePct","type":"uint64"},{"internalType":"uint64","name":"instantRelayFeePct","type":"uint64"},{"internalType":"uint32","name":"quoteTimestamp","type":"uint32"}],"internalType":"struct BridgePool.DepositData","name":"depositData","type":"tuple"},{"internalType":"uint64","name":"realizedLpFeePct","type":"uint64"}],"name":"relayDeposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"relays","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"relaysEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"lpTokenAmount","type":"uint256"},{"internalType":"bool","name":"sendEth","type":"bool"}],"name":"removeLiquidity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"time","type":"uint256"}],"name":"setCurrentTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_newLpFeeRatePerSecond","type":"uint64"}],"name":"setLpFeeRatePerSecond","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_relaysEnabled","type":"bool"}],"name":"setRelaysEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"uint64","name":"depositId","type":"uint64"},{"internalType":"address payable","name":"l1Recipient","type":"address"},{"internalType":"address","name":"l2Sender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint64","name":"slowRelayFeePct","type":"uint64"},{"internalType":"uint64","name":"instantRelayFeePct","type":"uint64"},{"internalType":"uint32","name":"quoteTimestamp","type":"uint32"}],"internalType":"struct BridgePool.DepositData","name":"depositData","type":"tuple"},{"components":[{"internalType":"enum BridgePool.RelayState","name":"relayState","type":"uint8"},{"internalType":"address","name":"slowRelayer","type":"address"},{"internalType":"uint32","name":"relayId","type":"uint32"},{"internalType":"uint64","name":"realizedLpFeePct","type":"uint64"},{"internalType":"uint32","name":"priceRequestTime","type":"uint32"},{"internalType":"uint256","name":"proposerBond","type":"uint256"},{"internalType":"uint256","name":"finalFee","type":"uint256"}],"internalType":"struct BridgePool.RelayData","name":"relayData","type":"tuple"}],"name":"settleRelay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"uint64","name":"depositId","type":"uint64"},{"internalType":"address payable","name":"l1Recipient","type":"address"},{"internalType":"address","name":"l2Sender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint64","name":"slowRelayFeePct","type":"uint64"},{"internalType":"uint64","name":"instantRelayFeePct","type":"uint64"},{"internalType":"uint32","name":"quoteTimestamp","type":"uint32"}],"internalType":"struct BridgePool.DepositData","name":"depositData","type":"tuple"},{"components":[{"internalType":"enum BridgePool.RelayState","name":"relayState","type":"uint8"},{"internalType":"address","name":"slowRelayer","type":"address"},{"internalType":"uint32","name":"relayId","type":"uint32"},{"internalType":"uint64","name":"realizedLpFeePct","type":"uint64"},{"internalType":"uint32","name":"priceRequestTime","type":"uint32"},{"internalType":"uint256","name":"proposerBond","type":"uint256"},{"internalType":"uint256","name":"finalFee","type":"uint256"}],"internalType":"struct BridgePool.RelayData","name":"relayData","type":"tuple"}],"name":"speedUpRelay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"store","outputs":[{"internalType":"contract StoreInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sync","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"syncUmaEcosystemParams","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"syncWithBridgeAdminParams","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"timerAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"undistributedLpFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"utilizedReserves","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
6080604052600a805461ff0019166101001790553480156200002057600080fd5b50604051620054a3380380620054a38339810160408190526200004391620008bc565b600080546001600160a01b0319166001600160a01b03831617905586518790879087908790879087908790879087906200008590600490602085019062000703565b5080516200009b90600590602084019062000703565b50506006805460ff1916600117905550865115801590620000bc5750855115155b6200010e5760405162461bcd60e51b815260206004820152601b60248201527f426164204c5020746f6b656e206e616d65206f722073796d626f6c000000000060448201526064015b60405180910390fd5b600e80546001600160a01b0319166001600160a01b038781169190911790915560068054610100600160a81b03191661010092871692909202919091179055620001554290565b600a805462010000600160701b0319166a010000000000000000000063ffffffff939093169290920262010000600160501b03191691909117620100006001600160401b038616021760ff1916831515179055620001b262000215565b620001bc6200049b565b600a54604051620100009091046001600160401b031681527f958b6b3e25d854f9e658cd5610bd9d184123d203f58f95adf261e0d7d0dd65a59060200160405180910390a1505050505050505050505050505062000a90565b6200021f620006af565b6200022f6006805460ff19169055565b600e5460408051632e68f21360e21b815290516000926001600160a01b03169163b9a3c84c916004808301926020929190829003018186803b1580156200027557600080fd5b505afa1580156200028a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002b0919062000989565b6040516302abf57960e61b81527f536b696e6e794f7074696d69737469634f7261636c650000000000000000000060048201529091506001600160a01b0382169063aafd5e409060240160206040518083038186803b1580156200031357600080fd5b505afa15801562000328573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200034e919062000989565b601080546001600160a01b0319166001600160a01b039283161790556040516302abf57960e61b81526453746f726560d81b60048201529082169063aafd5e409060240160206040518083038186803b158015620003ab57600080fd5b505afa158015620003c0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003e6919062000989565b600f80546001600160a01b0319166001600160a01b03928316908117909155600654604051635b97aadd60e01b8152610100909104909216600483015290635b97aadd9060240160206040518083038186803b1580156200044657600080fd5b505afa1580156200045b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004819190620009ae565b51600b5550620004996006805460ff19166001179055565b565b620004a5620006af565b620004b56006805460ff19169055565b600e60009054906101000a90046001600160a01b03166001600160a01b031663c73a32c36040518163ffffffff1660e01b815260040160206040518083038186803b1580156200050457600080fd5b505afa15801562000519573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200053f9190620009f3565b600a600e6101000a8154816001600160401b0302191690836001600160401b03160217905550600e60009054906101000a90046001600160a01b03166001600160a01b031663173684c56040518163ffffffff1660e01b815260040160206040518083038186803b158015620005b457600080fd5b505afa158015620005c9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005ef919062000a11565b600a60166101000a81548163ffffffff021916908363ffffffff160217905550600e60009054906101000a90046001600160a01b03166001600160a01b0316637998a1c46040518163ffffffff1660e01b815260040160206040518083038186803b1580156200065e57600080fd5b505afa15801562000673573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000699919062000a39565b601155620004996006805460ff19166001179055565b60065460ff16620004995760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640162000105565b828054620007119062000a53565b90600052602060002090601f01602090048101928262000735576000855562000780565b82601f106200075057805160ff191683800117855562000780565b8280016001018555821562000780579182015b828111156200078057825182559160200191906001019062000763565b506200078e92915062000792565b5090565b5b808211156200078e576000815560010162000793565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715620007ea57620007ea620007a9565b604052919050565b600082601f8301126200080457600080fd5b81516001600160401b03811115620008205762000820620007a9565b602062000836601f8301601f19168201620007bf565b82815285828487010111156200084b57600080fd5b60005b838110156200086b5785810183015182820184015282016200084e565b838111156200087d5760008385840101525b5095945050505050565b80516001600160a01b03811681146200089f57600080fd5b919050565b80516001600160401b03811681146200089f57600080fd5b600080600080600080600060e0888a031215620008d857600080fd5b87516001600160401b0380821115620008f057600080fd5b620008fe8b838c01620007f2565b985060208a01519150808211156200091557600080fd5b50620009248a828b01620007f2565b965050620009356040890162000887565b9450620009456060890162000887565b93506200095560808901620008a4565b925060a088015180151581146200096b57600080fd5b91506200097b60c0890162000887565b905092959891949750929550565b6000602082840312156200099c57600080fd5b620009a78262000887565b9392505050565b600060208284031215620009c157600080fd5b604051602081016001600160401b0381118282101715620009e657620009e6620007a9565b6040529151825250919050565b60006020828403121562000a0657600080fd5b620009a782620008a4565b60006020828403121562000a2457600080fd5b815163ffffffff81168114620009a757600080fd5b60006020828403121562000a4c57600080fd5b5051919050565b600181811c9082168062000a6857607f821691505b6020821081141562000a8a57634e487b7160e01b600052602260045260246000fd5b50919050565b614a038062000aa06000396000f3fe60806040526004361061031e5760003560e01c806370a08231116101ab578063b5351ee2116100f7578063cefed55f11610095578063df738fc81161006f578063df738fc814610978578063ed4de3a3146109a5578063f1d24bab146109da578063fff6cae9146109fe57600080fd5b8063cefed55f146108ee578063d412f5a41461090e578063dd62ed3e1461093257600080fd5b8063bec73ade116100d1578063bec73ade14610868578063c01e1bd614610888578063c73a32c3146108ad578063cc2c929e146108d457600080fd5b8063b5351ee21461081f578063bd6d894d14610834578063be0ba1221461084957600080fd5b8063975057e711610164578063a9059cbb1161013e578063a9059cbb14610793578063ac9650d8146107b3578063b2084202146107d3578063b454e326146107e957600080fd5b8063975057e714610733578063a457c2d714610753578063a6af2dfe1461077357600080fd5b806370a082311461067c578063753b91bb146106b25780637998a1c4146106d257806387a515d3146106e85780638f283970146106fe57806395d89b411461071e57600080fd5b806323b872dd1161026a5780633fa856c91161022357806351c6590a116101fd57806351c6590a1461061e5780635df45a371461063157806362822d341461064657806366db52401461066657600080fd5b80633fa856c9146105c85780634464fae4146105e85780634f52fd17146105fe57600080fd5b806323b872dd1461052457806327f224ca1461054457806329cb924d14610564578063313ce5671461057757806339509351146105935780633cc400b3146105b357600080fd5b8063173684c5116102d75780631bf71c38116102b15780631bf71c381461048c5780631c39c38d146104ac57806322302922146104e457806322f8e5661461050457600080fd5b8063173684c51461042957806318160ddd1461046257806319e9d8941461047757600080fd5b806306fdde031461032a57806308ed5b1414610355578063095ea7b31461037757806311cfc159146103a757806313111725146103e5578063135c404e1461040557600080fd5b3661032557005b600080fd5b34801561033657600080fd5b5061033f610a13565b60405161034c9190613d80565b60405180910390f35b34801561036157600080fd5b50610375610370366004613da1565b610aa5565b005b34801561038357600080fd5b50610397610392366004613dde565b610b44565b604051901515815260200161034c565b3480156103b357600080fd5b50600a546103cd906201000090046001600160401b031681565b6040516001600160401b03909116815260200161034c565b3480156103f157600080fd5b50610375610400366004613f43565b610b5b565b34801561041157600080fd5b5061041b600d5481565b60405190815260200161034c565b34801561043557600080fd5b50600a5461044d90600160b01b900463ffffffff1681565b60405163ffffffff909116815260200161034c565b34801561046e57600080fd5b5060035461041b565b34801561048357600080fd5b5061041b610e95565b34801561049857600080fd5b5061033f6104a7366004613f7d565b610ebe565b3480156104b857600080fd5b506000546104cc906001600160a01b031681565b6040516001600160a01b03909116815260200161034c565b3480156104f057600080fd5b506010546104cc906001600160a01b031681565b34801561051057600080fd5b5061037561051f366004614034565b610ee1565b34801561053057600080fd5b5061039761053f36600461404d565b610f57565b34801561055057600080fd5b5061037561055f36600461408e565b611001565b34801561057057600080fd5b504261041b565b34801561058357600080fd5b506040516012815260200161034c565b34801561059f57600080fd5b506103976105ae366004613dde565b611097565b3480156105bf57600080fd5b506103756110d3565b3480156105d457600080fd5b506103756105e3366004613f7d565b6112c8565b3480156105f457600080fd5b5061041b600c5481565b34801561060a57600080fd5b506103756106193660046140ab565b611725565b61037561062c366004614034565b61189e565b34801561063d57600080fd5b5061041b611a42565b34801561065257600080fd5b5061041b610661366004614034565b611a59565b34801561067257600080fd5b5061041b60085481565b34801561068857600080fd5b5061041b6106973660046140d0565b6001600160a01b031660009081526001602052604090205490565b3480156106be57600080fd5b506103756106cd366004613f43565b611a83565b3480156106de57600080fd5b5061041b60115481565b3480156106f457600080fd5b5061041b60095481565b34801561070a57600080fd5b506103756107193660046140d0565b611f1f565b34801561072a57600080fd5b5061033f611fae565b34801561073f57600080fd5b50600f546104cc906001600160a01b031681565b34801561075f57600080fd5b5061039761076e366004613dde565b611fbd565b34801561077f57600080fd5b50600e546104cc906001600160a01b031681565b34801561079f57600080fd5b506103976107ae366004613dde565b612056565b6107c66107c13660046140ed565b612063565b60405161034c9190614161565b3480156107df57600080fd5b5061041b60075481565b3480156107f557600080fd5b506104cc610804366004614034565b6013602052600090815260409020546001600160a01b031681565b34801561082b57600080fd5b50610375612208565b34801561084057600080fd5b5061041b612460565b34801561085557600080fd5b50600a5461039790610100900460ff1681565b34801561087457600080fd5b50610375610883366004613f7d565b61247a565b34801561089457600080fd5b506006546104cc9061010090046001600160a01b031681565b3480156108b957600080fd5b50600a546103cd90600160701b90046001600160401b031681565b3480156108e057600080fd5b50600a546103979060ff1681565b3480156108fa57600080fd5b50610375610909366004613f7d565b612667565b34801561091a57600080fd5b5060065461044d90600160a81b900463ffffffff1681565b34801561093e57600080fd5b5061041b61094d3660046141c3565b6001600160a01b03918216600090815260026020908152604080832093909416825291909152205490565b34801561098457600080fd5b5061041b610993366004614034565b60126020526000908152604090205481565b3480156109b157600080fd5b506109c56109c0366004614034565b61284d565b6040805192835260208301919091520161034c565b3480156109e657600080fd5b50600a5461044d90600160501b900463ffffffff1681565b348015610a0a57600080fd5b50610375612884565b606060048054610a22906141f1565b80601f0160208091040260200160405190810160405280929190818152602001828054610a4e906141f1565b8015610a9b5780601f10610a7057610100808354040283529160200191610a9b565b820191906000526020600020905b815481529060010190602001808311610a7e57829003601f168201915b5050505050905090565b600e546001600160a01b03163314610ad85760405162461bcd60e51b8152600401610acf9061422c565b60405180910390fd5b610ae06128a4565b610ae86128f6565b600a80548215156101000261ff00199091161790556040517f1d492b98217ff50d005c548e0fa3a96dc38b2bafccaf5baedf42c112bd39fdfb90610b3190831515815260200190565b60405180910390a1610b41612902565b50565b6000610b51338484612911565b5060015b92915050565b600a54610100900460ff16610ba85760405162461bcd60e51b815260206004820152601360248201527214995b185e5cc8185c9948191a5cd8589b1959606a1b6044820152606401610acf565b610bb06128a4565b610bb86128f6565b6703782dace9d900008260a001516001600160401b031611158015610bf257506703782dace9d900008260c001516001600160401b031611155b8015610c0f57506706f05b59d3b20000816001600160401b031611155b610c4a5760405162461bcd60e51b815260206004820152600c60248201526b496e76616c6964206665657360a01b6044820152606401610acf565b6000610c5583612a35565b60008181526012602052604090205490915015610cab5760405162461bcd60e51b815260206004820152601460248201527350656e64696e672072656c61792065786973747360601b6044820152606401610acf565b60004290506000610cbf8560800151612a78565b905060006040518060e0016040528060016002811115610ce157610ce1614263565b815233602082015260068054604090920191600160a81b900463ffffffff16906015610d0c8361428f565b91906101000a81548163ffffffff021916908363ffffffff16021790555063ffffffff168152602001866001600160401b031681526020018463ffffffff168152602001838152602001600b548152509050610d6781612a98565b600085815260126020526040812091909155610d838783612aab565b90508660800151600954600754610d9a91906142b3565b1015610de45760405162461bcd60e51b8152602060048201526019602482015278496e73756666696369656e7420706f6f6c2062616c616e636560381b6044820152606401610acf565b6000600b5484610df491906142ca565b9050876080015160096000828254610e0c91906142ca565b9250508190555080600d6000828254610e2591906142ca565b9091555050600654610e479061010090046001600160a01b0316333084612aff565b857fa4ca36d112520cced74325c72711f376fe4015665829d879ba21590cb8130be0898585604051610e7b939291906143ec565b60405180910390a2505050505050610e91612902565b5050565b6000610e9f6128a4565b610ea76128f6565b610eb16000612b70565b9050610ebb612902565b90565b6060610ec86128a4565b610eda610ed58484612aab565b612bfe565b9392505050565b6000546001600160a01b0316610ef657600080fd5b60005460405163117c72b360e11b8152600481018390526001600160a01b03909116906322f8e56690602401600060405180830381600087803b158015610f3c57600080fd5b505af1158015610f50573d6000803e3d6000fd5b5050505050565b6000610f64848484612c3b565b6001600160a01b038416600090815260026020908152604080832033845290915290205482811015610fe95760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e74206578636565647320616044820152676c6c6f77616e636560c01b6064820152608401610acf565b610ff68533858403612911565b506001949350505050565b600e546001600160a01b0316331461102b5760405162461bcd60e51b8152600401610acf9061422c565b6110336128a4565b61103b6128f6565b600a805469ffffffffffffffff00001916620100006001600160401b038481168202929092179283905560405192041681527f958b6b3e25d854f9e658cd5610bd9d184123d203f58f95adf261e0d7d0dd65a590602001610b31565b3360008181526002602090815260408083206001600160a01b03871684529091528120549091610b519185906110ce9086906142ca565b612911565b6110db6128a4565b6110e36128f6565b600e60009054906101000a90046001600160a01b03166001600160a01b031663c73a32c36040518163ffffffff1660e01b815260040160206040518083038186803b15801561113157600080fd5b505afa158015611145573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111699190614418565b600a600e6101000a8154816001600160401b0302191690836001600160401b03160217905550600e60009054906101000a90046001600160a01b03166001600160a01b031663173684c56040518163ffffffff1660e01b815260040160206040518083038186803b1580156111dd57600080fd5b505afa1580156111f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112159190614435565b600a60166101000a81548163ffffffff021916908363ffffffff160217905550600e60009054906101000a90046001600160a01b03166001600160a01b0316637998a1c46040518163ffffffff1660e01b815260040160206040518083038186803b15801561128357600080fd5b505afa158015611297573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112bb9190614452565b6011556112c6612902565b565b6112d06128a4565b6112d86128f6565b60006112e383612a35565b90506112ef8183612e09565b60018251600281111561130457611304614263565b146113435760405162461bcd60e51b815260206004820152600f60248201526e105b1c9958591e481cd95d1d1b1959608a1b6044820152606401610acf565b6000600a60169054906101000a900463ffffffff168360800151611367919061446b565b9050428163ffffffff1611156113b45760405162461bcd60e51b8152602060048201526012602482015271139bdd081cd95d1d1b1958589b19481e595d60721b6044820152606401610acf565b82602001516001600160a01b0316336001600160a01b031614806113e857506113df8161038461446b565b63ffffffff1642115b6114275760405162461bcd60e51b815260206004820152601060248201526f2737ba1039b637bb903932b630bcb2b960811b6044820152606401610acf565b6040805160e0810190915261149b90806002815260200185602001516001600160a01b03168152602001856040015163ffffffff16815260200185606001516001600160401b03168152602001856080015163ffffffff1681526020018560a0015181526020018560c00151815250612a98565b60008381526012602052604081209190915560a085015160608501516114ce916114c491614493565b8660800151612e96565b85608001516114dd91906142b3565b905060006114eb8486612ebe565b600081815260136020526040902054600a549192506001600160a01b03169060ff16801561152057506001600160a01b038116155b1561153857611533876040015184612ee9565b61156d565b61156d6001600160a01b038216611553578760400151611555565b815b60065461010090046001600160a01b03169085612fb2565b60006115818860a001518960800151612e96565b905060008760a001518860c0015161159991906142ca565b60208901519091506001600160a01b03163314156115e15760208801516115dc906115c483856142ca565b60065461010090046001600160a01b03169190612fb2565b61161f565b6020880151600654611603916101009091046001600160a01b03169083612fb2565b60065461161f9061010090046001600160a01b03163384612fb2565b600061162b83876142ca565b905089608001516009600082825461164391906142b3565b92505081905550806007600082825461165c91906142b3565b92505081905550806008600082825461167591906144b5565b9250508190555081600d600082825461168e91906142b3565b9091555061169c9050612fe2565b6116b66116b18a606001518c60800151612e96565b613020565b336001600160a01b0316887fcfdda74fce9fedb259e0f0a1ab1550e19b338488ece64976a4639e7fce0293a78b6040516116f091906144f6565b60405180910390a350505060009182525060136020526040902080546001600160a01b031916905550610e9191506129029050565b61172d6128a4565b6117356128f6565b8015806117445750600a5460ff165b6117805760405162461bcd60e51b815260206004820152600d60248201526c086c2dce840e6cadcc840cae8d609b1b6044820152606401610acf565b6000670de0b6b3a7640000611793613053565b61179d9085614504565b6117a79190614539565b9050806009546117b791906142ca565b60075410156118085760405162461bcd60e51b815260206004820152601e60248201527f5574696c697a6174696f6e20746f6f206869676820746f2072656d6f766500006044820152606401610acf565b61181233846130cb565b806007600082825461182491906142b3565b9091555050811561183e576118393382612ee9565b61185a565b60065461185a9061010090046001600160a01b03163383612fb2565b604080518281526020810185905233917f0c54fc223ffd1a8f36652b5e83db4fff50f5ae151b11ceb56d5499b9f6e1fa18910160405180910390a250610e91612902565b6118a66128a4565b6118ae6128f6565b600a5460ff1680156118bf57508034145b806118c8575034155b6119145760405162461bcd60e51b815260206004820152601b60248201527f42616420616464206c6971756964697479204574682076616c756500000000006044820152606401610acf565b600061191e613053565b61193083670de0b6b3a7640000614504565b61193a9190614539565b90506119463382613219565b816007600082825461195891906142ca565b9091555050341580159061196e5750600a5460ff165b156119e157600660019054906101000a90046001600160a01b03166001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b1580156119c357600080fd5b505af11580156119d7573d6000803e3d6000fd5b50505050506119fe565b6006546119fe9061010090046001600160a01b0316333085612aff565b604080518381526020810183905233917f0351f600ef1e31e5e13b4dc27bff4cbde3e9269f0ffc666629ae6cac573eb220910160405180910390a250610b41612902565b6000611a4c6128a4565b611a546132f8565b905090565b6000611a636128a4565b611a6b6128f6565b611a7482612b70565b9050611a7e612902565b919050565b600a54610100900460ff16611ad05760405162461bcd60e51b815260206004820152601360248201527214995b185e5cc8185c9948191a5cd8589b1959606a1b6044820152606401610acf565b611ad86128a4565b611ae06128f6565b60004290506703782dace9d900008360a001516001600160401b031611158015611b1f57506703782dace9d900008360c001516001600160401b031611155b8015611b3c57506706f05b59d3b20000826001600160401b031611155b611b775760405162461bcd60e51b815260206004820152600c60248201526b496e76616c6964206665657360a01b6044820152606401610acf565b6000611b8284612a35565b60008181526012602052604090205490915015611bd85760405162461bcd60e51b815260206004820152601460248201527350656e64696e672072656c61792065786973747360601b6044820152606401610acf565b6000611be78560800151612a78565b905060006040518060e0016040528060016002811115611c0957611c09614263565b815233602082015260068054604090920191600160a81b900463ffffffff16906015611c348361428f565b91906101000a81548163ffffffff021916908363ffffffff16021790555063ffffffff168152602001866001600160401b031681526020018563ffffffff168152602001838152602001600b5481525090506000611c928783612aab565b9050611c9d82612a98565b600085815260126020526040812091909155611cb98584612ebe565b6000818152601360205260409020549091506001600160a01b031615611d1b5760405162461bcd60e51b8152602060048201526017602482015276052656c61792063616e6e6f74206265207370656420757604c1b6044820152606401610acf565b8760800151600954600754611d3091906142b3565b1015611d7a5760405162461bcd60e51b8152602060048201526019602482015278496e73756666696369656e7420706f6f6c2062616c616e636560381b6044820152606401610acf565b6000600b5485611d8a91906142ca565b90506000611dbe8a60c001518b60a001518760600151611daa9190614493565b611db49190614493565b8b60800151612e96565b90506000818b60800151611dd291906142b3565b905082600d6000828254611de691906142ca565b909155505060808b015160098054600090611e029084906142ca565b9091555050600084815260136020526040902080546001600160a01b03191633908117909155611e509030611e3786856142ca565b60065461010090046001600160a01b0316929190612aff565b600a5460ff1615611e6e57611e698b6040015182612ee9565b611e90565b60408b0151600654611e90916101009091046001600160a01b03169083612fb2565b877fa4ca36d112520cced74325c72711f376fe4015665829d879ba21590cb8130be08c8888604051611ec4939291906143ec565b60405180910390a2336001600160a01b0316887ff98cddc88bc965917007822b05056cb92bc9ddf0f8bcc61678400cb78313bb4b88604051611f0691906144f6565b60405180910390a3505050505050505050610e91612902565b600e546001600160a01b03163314611f495760405162461bcd60e51b8152600401610acf9061422c565b611f516128a4565b611f596128f6565b600e80546001600160a01b0319166001600160a01b0383169081179091556040805133815260208101929092527f485a12424bd0c2c66a131c2681cb6c743b9573af3ae5f3014ef6ce7f55ab01929101610b31565b606060058054610a22906141f1565b3360009081526002602090815260408083206001600160a01b03861684529091528120548281101561203f5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610acf565b61204c3385858403612911565b5060019392505050565b6000610b51338484612c3b565b606034156120b35760405162461bcd60e51b815260206004820152601b60248201527f4f6e6c79206d756c746963616c6c207769746820302076616c756500000000006044820152606401610acf565b816001600160401b038111156120cb576120cb613e0a565b6040519080825280602002602001820160405280156120fe57816020015b60608152602001906001900390816120e95790505b50905060005b8281101561220157600080308686858181106121225761212261455b565b90506020028101906121349190614571565b6040516121429291906145be565b600060405180830381855af49150503d806000811461217d576040519150601f19603f3d011682016040523d82523d6000602084013e612182565b606091505b5091509150816121ce5760448151101561219b57600080fd5b600481019050808060200190518101906121b591906145ce565b60405162461bcd60e51b8152600401610acf9190613d80565b808484815181106121e1576121e161455b565b6020026020010181905250505080806121f99061466f565b915050612104565b5092915050565b6122106128a4565b6122186128f6565b600e5460408051632e68f21360e21b815290516000926001600160a01b03169163b9a3c84c916004808301926020929190829003018186803b15801561225d57600080fd5b505afa158015612271573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612295919061468a565b6040516302abf57960e61b815275536b696e6e794f7074696d69737469634f7261636c6560501b60048201529091506001600160a01b0382169063aafd5e409060240160206040518083038186803b1580156122f057600080fd5b505afa158015612304573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612328919061468a565b601080546001600160a01b0319166001600160a01b039283161790556040516302abf57960e61b81526453746f726560d81b60048201529082169063aafd5e409060240160206040518083038186803b15801561238457600080fd5b505afa158015612398573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123bc919061468a565b600f80546001600160a01b0319166001600160a01b03928316908117909155600654604051635b97aadd60e01b8152610100909104909216600483015290635b97aadd9060240160206040518083038186803b15801561241b57600080fd5b505afa15801561242f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061245391906146a7565b51600b55506112c6612902565b600061246a6128a4565b6124726128f6565b610eb1613053565b6124826128a4565b61248a6128f6565b600061249583612a35565b90506124a18183612e09565b60006124ad8284612ebe565b9050600a60169054906101000a900463ffffffff1683608001516124d1919061446b565b63ffffffff16421080156124f757506001835160028111156124f5576124f5614263565b145b801561251857506000818152601360205260409020546001600160a01b0316155b61255e5760405162461bcd60e51b8152602060048201526017602482015276052656c61792063616e6e6f74206265207370656420757604c1b6044820152606401610acf565b600081815260136020526040812080546001600160a01b0319163317905560c085015160a086015160608601516125a3929161259991614493565b6114c49190614493565b905060008186608001516125b791906142b3565b600a5490915060ff16156125f5576006546125e29061010090046001600160a01b0316333084612aff565b6125f0866040015182612ee9565b612619565b6040860151600654612619916101009091046001600160a01b031690339084612aff565b336001600160a01b0316847ff98cddc88bc965917007822b05056cb92bc9ddf0f8bcc61678400cb78313bb4b8760405161265391906144f6565b60405180910390a350505050610e91612902565b61266f6128a4565b6126776128f6565b42600a54608083015161269791600160b01b900463ffffffff169061446b565b63ffffffff16116126da5760405162461bcd60e51b815260206004820152600d60248201526c50617374206c6976656e65737360981b6044820152606401610acf565b6001815160028111156126ef576126ef614263565b1461272d5760405162461bcd60e51b815260206004820152600e60248201526d4e6f742064697370757461626c6560901b6044820152606401610acf565b600061273883612a35565b90506127448183612e09565b60006127508484612aab565b905060006127758460200151338660a001518760c0015161277087612bfe565b613368565b90508360a001518460c0015161278b91906142ca565b600d600082825461279c91906142b3565b90915550506080850151600980546000906127b89084906142b3565b9091555050600083815260126020526040812055801561280c57336127dc85612a98565b60405185907f29751133c2d0a0ea7a9da312248b12ef10ac4c20f4e3ab5eebbb80d853b3836790600090a4612842565b3361281685612a98565b60405185907f14173c4d3bd95e34f5c8f78729323444c9272bd21051e70045b64ed48f65818390600090a45b505050610e91612902565b6000806128586128a4565b6128606128f6565b61286a6000612b70565b61287384612b70565b9150915061287f612902565b915091565b61288c6128a4565b6128946128f6565b61289c61368d565b6112c6612902565b60065460ff166112c65760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610acf565b6006805460ff19169055565b6006805460ff19166001179055565b6001600160a01b0383166129735760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610acf565b6001600160a01b0382166129d45760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610acf565b6001600160a01b0383811660008181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b600654604051600091612a5b91849161010090046001600160a01b0316906020016146e8565b604051602081830303815290604052805190602001209050919050565b600a54600090610b5590600160701b90046001600160401b031683612e96565b600081604051602001612a5b91906144f6565b60008282604001518360600151600660019054906101000a90046001600160a01b0316604051602001612ae19493929190614710565b60405160208183030381529060405280519060200120905092915050565b6040516001600160a01b0380851660248301528316604482015260648101829052612b6a9085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613750565b50505050565b6000612b7a61368d565b60008060085413612b8c576000612b90565b6008545b905060008160095485612ba391906142ca565b612bad91906142ca565b9050600082600754612bbf91906142ca565b905080612bd85750670de0b6b3a7640000949350505050565b80612beb83670de0b6b3a7640000614504565b612bf59190614539565b95945050505050565b6060610b5560405180602001604052806000815250604051806040016040528060098152602001680e4cad8c2f290c2e6d60bb1b81525084613822565b6001600160a01b038316612c9f5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610acf565b6001600160a01b038216612d015760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610acf565b6001600160a01b03831660009081526001602052604090205481811015612d795760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610acf565b6001600160a01b03808516600090815260016020526040808220858503905591851681529081208054849290612db09084906142ca565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051612dfc91815260200190565b60405180910390a3612b6a565b612e1281612a98565b60008381526012602052604090205414610e91576040805162461bcd60e51b81526020600482015260248101919091527f4861736865642072656c617920706172616d7320646f206e6f74206d6174636860448201527f206578697374696e672072656c6179206861736820666f72206465706f7369746064820152608401610acf565b6000670de0b6b3a7640000612eb4836001600160401b038616614504565b610eda9190614539565b6000828260600151604051602001612ae19291909182526001600160401b0316602082015260400190565b6001600160a01b0382163b15612f1557600654610e919061010090046001600160a01b03168383612fb2565b600654604051632e1a7d4d60e01b8152600481018390526101009091046001600160a01b031690632e1a7d4d90602401600060405180830381600087803b158015612f5f57600080fd5b505af1158015612f73573d6000803e3d6000fd5b50506040516001600160a01b038516925083156108fc02915083906000818181858888f19350505050158015612fad573d6000803e3d6000fd5b505050565b6040516001600160a01b038316602482015260448101829052612fad90849063a9059cbb60e01b90606401612b33565b6000612fec6132f8565b905080600c54612ffc91906142b3565b600c5550600a805463ffffffff60501b1916600160501b4263ffffffff1602179055565b80600c600082825461303291906142ca565b92505081905550806008600082825461304b91906144b5565b909155505050565b600061305e60035490565b61306f5750670de0b6b3a764000090565b613077612fe2565b61307f61368d565b6000600c5460085460075461309491906144b5565b61309e9190614755565b90506130a960035490565b6130bb82670de0b6b3a7640000614504565b6130c59190614539565b91505090565b6001600160a01b03821661312b5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610acf565b6001600160a01b0382166000908152600160205260409020548181101561319f5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610acf565b6001600160a01b03831660009081526001602052604081208383039055600380548492906131ce9084906142b3565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b6001600160a01b03821661326f5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610acf565b806003600082825461328191906142ca565b90915550506001600160a01b038216600090815260016020526040812080548392906132ae9084906142ca565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b600a546000908190670de0b6b3a764000090600160501b900463ffffffff164261332291906142b3565b600a54600c54613341916201000090046001600160401b031690614504565b61334b9190614504565b6133559190614539565b9050600c548110611a7e57600c546130c5565b60008061337585856142ca565b60105460065491925061339a9161010090046001600160a01b03908116911683613868565b6010546011546001600160a01b039091169063af355d1e904286600660019054906101000a90046001600160a01b031660008b600a60169054906101000a900463ffffffff168f670de0b6b3a76400006040518a63ffffffff1660e01b815260040161340e99989796959493929190614794565b602060405180830381600087803b15801561342857600080fd5b505af1925050508015613458575060408051601f3d908101601f1916820190925261345591810190614452565b60015b6134a5576006546134789061010090046001600160a01b03168883612fb2565b60105460065461349b916001600160a01b03610100909204821691166000613868565b6000915050612bf5565b818110156135005760006134b982846142b3565b6006549091506134d89061010090046001600160a01b03168a83612fb2565b6010546006546134fb916001600160a01b03610100909204821691166000613868565b819250505b5060408051610160810182526001600160a01b03898116825260006020830181905260065461010090049091169282019290925260608101829052670de0b6b3a7640000608082015260a08101829052600a5460c0820190600160b01b900463ffffffff164261357091906142ca565b81526000602082015260400161358688856142b3565b815260208101889052600a54600160b01b900463ffffffff9081166040909201919091526006549192506135cf9161010090046001600160a01b031690339030908690612aff16565b6010546006546135f1916001600160a01b036101009092048216911684613868565b60105460115460405163139c641960e31b81526001600160a01b0390921691639ce320c89161362c914290899087908e9030906004016147ff565b602060405180830381600087803b15801561364657600080fd5b505af115801561365a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061367e9190614452565b50600198975050505050505050565b600d546006546040516370a0823160e01b81523060048201526000929161010090046001600160a01b0316906370a082319060240160206040518083038186803b1580156136da57600080fd5b505afa1580156136ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137129190614452565b61371c91906142b3565b9050600754811115610b415760075461373590826142b3565b600860008282546137469190614755565b9091555050600755565b60006137a5826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661398c9092919063ffffffff16565b805190915015612fad57808060200190518101906137c391906148f8565b612fad5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610acf565b6060600061383085856139a3565b9050848161383d856139e5565b60405160200161384f93929190614915565b6040516020818303038152906040529150509392505050565b8015806138f15750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b1580156138b757600080fd5b505afa1580156138cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138ef9190614452565b155b61395c5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608401610acf565b6040516001600160a01b038316602482015260448101829052612fad90849063095ea7b360e01b90606401612b33565b606061399b8484600085613a25565b949350505050565b8151606090156139d457816040516020016139be9190614958565b6040516020818303038152906040529050610b55565b816040516020016139be919061498c565b60606139f4608083901c613b4d565b6139fd83613b4d565b6040805160208101939093528201526060016040516020818303038152906040529050919050565b606082471015613a865760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610acf565b843b613ad45760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610acf565b600080866001600160a01b03168587604051613af091906149b1565b60006040518083038185875af1925050503d8060008114613b2d576040519150601f19603f3d011682016040523d82523d6000602084013e613b32565b606091505b5091509150613b42828286613cef565b979650505050505050565b6000808260001c9050806fffffffffffffffffffffffffffffffff169050806801000000000000000002811777ffffffffffffffff0000000000000000ffffffffffffffff169050806401000000000281177bffffffff00000000ffffffff00000000ffffffff00000000ffffffff16905080620100000281177dffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff169050806101000281177eff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff1690508060100281177f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f16905060006008827f08080808080808080808080808080808080808080808080808080808080808081681613c7157613c71614523565b0460047f040404040404040404040404040404040404040404040404040404040404040484160460027f020202020202020202020202020202020202020202020202020202020202020285160417166027029091017f3030303030303030303030303030303030303030303030303030303030303030019392505050565b60608315613cfe575081610eda565b825115613d0e5782518084602001fd5b8160405162461bcd60e51b8152600401610acf9190613d80565b60005b83811015613d43578181015183820152602001613d2b565b83811115612b6a5750506000910152565b60008151808452613d6c816020860160208601613d28565b601f01601f19169290920160200192915050565b602081526000610eda6020830184613d54565b8015158114610b4157600080fd5b600060208284031215613db357600080fd5b8135610eda81613d93565b6001600160a01b0381168114610b4157600080fd5b8035611a7e81613dbe565b60008060408385031215613df157600080fd5b8235613dfc81613dbe565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b60405160e081016001600160401b0381118282101715613e4257613e42613e0a565b60405290565b6001600160401b0381168114610b4157600080fd5b8035611a7e81613e48565b63ffffffff81168114610b4157600080fd5b8035611a7e81613e68565b6000610100808385031215613e9957600080fd5b604051908101906001600160401b0382118183101715613ebb57613ebb613e0a565b816040528092508335815260208401359150613ed682613e48565b816020820152613ee860408501613dd3565b6040820152613ef960608501613dd3565b606082015260808401356080820152613f1460a08501613e5d565b60a0820152613f2560c08501613e5d565b60c0820152613f3660e08501613e7a565b60e0820152505092915050565b6000806101208385031215613f5757600080fd5b613f618484613e85565b9150610100830135613f7281613e48565b809150509250929050565b6000808284036101e0811215613f9257600080fd5b613f9c8585613e85565b925060e060ff1982011215613fb057600080fd5b50613fb9613e20565b61010084013560038110613fcc57600080fd5b8152613fdb6101208501613dd3565b6020820152613fed6101408501613e7a565b6040820152613fff6101608501613e5d565b60608201526140116101808501613e7a565b60808201526101a084013560a08201526101c09093013560c08401525092909150565b60006020828403121561404657600080fd5b5035919050565b60008060006060848603121561406257600080fd5b833561406d81613dbe565b9250602084013561407d81613dbe565b929592945050506040919091013590565b6000602082840312156140a057600080fd5b8135610eda81613e48565b600080604083850312156140be57600080fd5b823591506020830135613f7281613d93565b6000602082840312156140e257600080fd5b8135610eda81613dbe565b6000806020838503121561410057600080fd5b82356001600160401b038082111561411757600080fd5b818501915085601f83011261412b57600080fd5b81358181111561413a57600080fd5b8660208260051b850101111561414f57600080fd5b60209290920196919550909350505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b828110156141b657603f198886030184526141a4858351613d54565b94509285019290850190600101614188565b5092979650505050505050565b600080604083850312156141d657600080fd5b82356141e181613dbe565b91506020830135613f7281613dbe565b600181811c9082168061420557607f821691505b6020821081141561422657634e487b7160e01b600052602260045260246000fd5b50919050565b60208082526017908201527f43616c6c6572206e6f74206272696467652061646d696e000000000000000000604082015260600190565b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff808316818114156142a9576142a9614279565b6001019392505050565b6000828210156142c5576142c5614279565b500390565b600082198211156142dd576142dd614279565b500190565b8051825260208101516001600160401b0380821660208501526040830151915060018060a01b03808316604086015280606085015116606086015250608083015160808501528060a08401511660a08501528060c08401511660c0850152505063ffffffff60e08201511660e08301525050565b80516003811061437657634e487b7160e01b600052602160045260246000fd5b82526020818101516001600160a01b031690830152604080820151906143a39084018263ffffffff169052565b5060608101516143be60608401826001600160401b03169052565b5060808101516143d6608084018263ffffffff169052565b5060a0818101519083015260c090810151910152565b61020081016143fb82866142e2565b614409610100830185614356565b826101e0830152949350505050565b60006020828403121561442a57600080fd5b8151610eda81613e48565b60006020828403121561444757600080fd5b8151610eda81613e68565b60006020828403121561446457600080fd5b5051919050565b600063ffffffff80831681851680830382111561448a5761448a614279565b01949350505050565b60006001600160401b0380831681851680830382111561448a5761448a614279565b600080821280156001600160ff1b03849003851316156144d7576144d7614279565b600160ff1b83900384128116156144f0576144f0614279565b50500190565b60e08101610b558284614356565b600081600019048311821515161561451e5761451e614279565b500290565b634e487b7160e01b600052601260045260246000fd5b60008261455657634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052603260045260246000fd5b6000808335601e1984360301811261458857600080fd5b8301803591506001600160401b038211156145a257600080fd5b6020019150368190038213156145b757600080fd5b9250929050565b8183823760009101908152919050565b6000602082840312156145e057600080fd5b81516001600160401b03808211156145f757600080fd5b818401915084601f83011261460b57600080fd5b81518181111561461d5761461d613e0a565b604051601f8201601f19908116603f0116810190838211818310171561464557614645613e0a565b8160405282815287602084870101111561465e57600080fd5b613b42836020830160208801613d28565b600060001982141561468357614683614279565b5060010190565b60006020828403121561469c57600080fd5b8151610eda81613dbe565b6000602082840312156146b957600080fd5b604051602081018181106001600160401b03821117156146db576146db613e0a565b6040529151825250919050565b61012081016146f782856142e2565b6001600160a01b03929092166101009190910152919050565b610160810161471f82876142e2565b63ffffffff949094166101008201526001600160401b03929092166101208301526001600160a01b031661014090910152919050565b60008083128015600160ff1b85018412161561477357614773614279565b6001600160ff1b038401831381161561478e5761478e614279565b50500390565b60006101208b835263ffffffff808c1660208501528160408501526147bb8285018c613d54565b6001600160a01b039a8b166060860152608085019990995260a084019790975250509290931660c083015290931660e0840152610100909201919091529392505050565b600061020088835263ffffffff8816602084015280604084015261482581840188613d54565b91505061483e6060830186516001600160a01b03169052565b60208501516001600160a01b03811660808401525060408501516001600160a01b03811660a084015250606085015180151560c084015250608085015160e083015260a0850151610100818185015260c08701519150610120828186015260e0880151925061014083818701528289015161016087015281890151610180870152808901516101a0870152505050506148e36101c08301856001600160a01b03169052565b6001600160a01b0383166101e0830152613b42565b60006020828403121561490a57600080fd5b8151610eda81613d93565b60008451614927818460208901613d28565b84519083019061493b818360208901613d28565b845191019061494e818360208801613d28565b0195945050505050565b600b60fa1b815260008251614974816001850160208701613d28565b601d60f91b6001939091019283015250600201919050565b6000825161499e818460208701613d28565b601d60f91b920191825250600101919050565b600082516149c3818460208701613d28565b919091019291505056fea2646970667358221220e29df9833ee712dea5e74a80725a39c21912ff9a19c010ca4afb5d0d9057d98064736f6c6343000809003300000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000030b44c676a05f1264d1de9cc31db5f2a945186b60000000000000000000000002260fac5e5542a773aa44fbcfedf7c193bc2c5990000000000000000000000000000000000000000000000000000015d3ef7980000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4163726f73732057425443204c500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009412d574254432d4c500000000000000000000000000000000000000000000000
Deployed Bytecode
0x60806040526004361061031e5760003560e01c806370a08231116101ab578063b5351ee2116100f7578063cefed55f11610095578063df738fc81161006f578063df738fc814610978578063ed4de3a3146109a5578063f1d24bab146109da578063fff6cae9146109fe57600080fd5b8063cefed55f146108ee578063d412f5a41461090e578063dd62ed3e1461093257600080fd5b8063bec73ade116100d1578063bec73ade14610868578063c01e1bd614610888578063c73a32c3146108ad578063cc2c929e146108d457600080fd5b8063b5351ee21461081f578063bd6d894d14610834578063be0ba1221461084957600080fd5b8063975057e711610164578063a9059cbb1161013e578063a9059cbb14610793578063ac9650d8146107b3578063b2084202146107d3578063b454e326146107e957600080fd5b8063975057e714610733578063a457c2d714610753578063a6af2dfe1461077357600080fd5b806370a082311461067c578063753b91bb146106b25780637998a1c4146106d257806387a515d3146106e85780638f283970146106fe57806395d89b411461071e57600080fd5b806323b872dd1161026a5780633fa856c91161022357806351c6590a116101fd57806351c6590a1461061e5780635df45a371461063157806362822d341461064657806366db52401461066657600080fd5b80633fa856c9146105c85780634464fae4146105e85780634f52fd17146105fe57600080fd5b806323b872dd1461052457806327f224ca1461054457806329cb924d14610564578063313ce5671461057757806339509351146105935780633cc400b3146105b357600080fd5b8063173684c5116102d75780631bf71c38116102b15780631bf71c381461048c5780631c39c38d146104ac57806322302922146104e457806322f8e5661461050457600080fd5b8063173684c51461042957806318160ddd1461046257806319e9d8941461047757600080fd5b806306fdde031461032a57806308ed5b1414610355578063095ea7b31461037757806311cfc159146103a757806313111725146103e5578063135c404e1461040557600080fd5b3661032557005b600080fd5b34801561033657600080fd5b5061033f610a13565b60405161034c9190613d80565b60405180910390f35b34801561036157600080fd5b50610375610370366004613da1565b610aa5565b005b34801561038357600080fd5b50610397610392366004613dde565b610b44565b604051901515815260200161034c565b3480156103b357600080fd5b50600a546103cd906201000090046001600160401b031681565b6040516001600160401b03909116815260200161034c565b3480156103f157600080fd5b50610375610400366004613f43565b610b5b565b34801561041157600080fd5b5061041b600d5481565b60405190815260200161034c565b34801561043557600080fd5b50600a5461044d90600160b01b900463ffffffff1681565b60405163ffffffff909116815260200161034c565b34801561046e57600080fd5b5060035461041b565b34801561048357600080fd5b5061041b610e95565b34801561049857600080fd5b5061033f6104a7366004613f7d565b610ebe565b3480156104b857600080fd5b506000546104cc906001600160a01b031681565b6040516001600160a01b03909116815260200161034c565b3480156104f057600080fd5b506010546104cc906001600160a01b031681565b34801561051057600080fd5b5061037561051f366004614034565b610ee1565b34801561053057600080fd5b5061039761053f36600461404d565b610f57565b34801561055057600080fd5b5061037561055f36600461408e565b611001565b34801561057057600080fd5b504261041b565b34801561058357600080fd5b506040516012815260200161034c565b34801561059f57600080fd5b506103976105ae366004613dde565b611097565b3480156105bf57600080fd5b506103756110d3565b3480156105d457600080fd5b506103756105e3366004613f7d565b6112c8565b3480156105f457600080fd5b5061041b600c5481565b34801561060a57600080fd5b506103756106193660046140ab565b611725565b61037561062c366004614034565b61189e565b34801561063d57600080fd5b5061041b611a42565b34801561065257600080fd5b5061041b610661366004614034565b611a59565b34801561067257600080fd5b5061041b60085481565b34801561068857600080fd5b5061041b6106973660046140d0565b6001600160a01b031660009081526001602052604090205490565b3480156106be57600080fd5b506103756106cd366004613f43565b611a83565b3480156106de57600080fd5b5061041b60115481565b3480156106f457600080fd5b5061041b60095481565b34801561070a57600080fd5b506103756107193660046140d0565b611f1f565b34801561072a57600080fd5b5061033f611fae565b34801561073f57600080fd5b50600f546104cc906001600160a01b031681565b34801561075f57600080fd5b5061039761076e366004613dde565b611fbd565b34801561077f57600080fd5b50600e546104cc906001600160a01b031681565b34801561079f57600080fd5b506103976107ae366004613dde565b612056565b6107c66107c13660046140ed565b612063565b60405161034c9190614161565b3480156107df57600080fd5b5061041b60075481565b3480156107f557600080fd5b506104cc610804366004614034565b6013602052600090815260409020546001600160a01b031681565b34801561082b57600080fd5b50610375612208565b34801561084057600080fd5b5061041b612460565b34801561085557600080fd5b50600a5461039790610100900460ff1681565b34801561087457600080fd5b50610375610883366004613f7d565b61247a565b34801561089457600080fd5b506006546104cc9061010090046001600160a01b031681565b3480156108b957600080fd5b50600a546103cd90600160701b90046001600160401b031681565b3480156108e057600080fd5b50600a546103979060ff1681565b3480156108fa57600080fd5b50610375610909366004613f7d565b612667565b34801561091a57600080fd5b5060065461044d90600160a81b900463ffffffff1681565b34801561093e57600080fd5b5061041b61094d3660046141c3565b6001600160a01b03918216600090815260026020908152604080832093909416825291909152205490565b34801561098457600080fd5b5061041b610993366004614034565b60126020526000908152604090205481565b3480156109b157600080fd5b506109c56109c0366004614034565b61284d565b6040805192835260208301919091520161034c565b3480156109e657600080fd5b50600a5461044d90600160501b900463ffffffff1681565b348015610a0a57600080fd5b50610375612884565b606060048054610a22906141f1565b80601f0160208091040260200160405190810160405280929190818152602001828054610a4e906141f1565b8015610a9b5780601f10610a7057610100808354040283529160200191610a9b565b820191906000526020600020905b815481529060010190602001808311610a7e57829003601f168201915b5050505050905090565b600e546001600160a01b03163314610ad85760405162461bcd60e51b8152600401610acf9061422c565b60405180910390fd5b610ae06128a4565b610ae86128f6565b600a80548215156101000261ff00199091161790556040517f1d492b98217ff50d005c548e0fa3a96dc38b2bafccaf5baedf42c112bd39fdfb90610b3190831515815260200190565b60405180910390a1610b41612902565b50565b6000610b51338484612911565b5060015b92915050565b600a54610100900460ff16610ba85760405162461bcd60e51b815260206004820152601360248201527214995b185e5cc8185c9948191a5cd8589b1959606a1b6044820152606401610acf565b610bb06128a4565b610bb86128f6565b6703782dace9d900008260a001516001600160401b031611158015610bf257506703782dace9d900008260c001516001600160401b031611155b8015610c0f57506706f05b59d3b20000816001600160401b031611155b610c4a5760405162461bcd60e51b815260206004820152600c60248201526b496e76616c6964206665657360a01b6044820152606401610acf565b6000610c5583612a35565b60008181526012602052604090205490915015610cab5760405162461bcd60e51b815260206004820152601460248201527350656e64696e672072656c61792065786973747360601b6044820152606401610acf565b60004290506000610cbf8560800151612a78565b905060006040518060e0016040528060016002811115610ce157610ce1614263565b815233602082015260068054604090920191600160a81b900463ffffffff16906015610d0c8361428f565b91906101000a81548163ffffffff021916908363ffffffff16021790555063ffffffff168152602001866001600160401b031681526020018463ffffffff168152602001838152602001600b548152509050610d6781612a98565b600085815260126020526040812091909155610d838783612aab565b90508660800151600954600754610d9a91906142b3565b1015610de45760405162461bcd60e51b8152602060048201526019602482015278496e73756666696369656e7420706f6f6c2062616c616e636560381b6044820152606401610acf565b6000600b5484610df491906142ca565b9050876080015160096000828254610e0c91906142ca565b9250508190555080600d6000828254610e2591906142ca565b9091555050600654610e479061010090046001600160a01b0316333084612aff565b857fa4ca36d112520cced74325c72711f376fe4015665829d879ba21590cb8130be0898585604051610e7b939291906143ec565b60405180910390a2505050505050610e91612902565b5050565b6000610e9f6128a4565b610ea76128f6565b610eb16000612b70565b9050610ebb612902565b90565b6060610ec86128a4565b610eda610ed58484612aab565b612bfe565b9392505050565b6000546001600160a01b0316610ef657600080fd5b60005460405163117c72b360e11b8152600481018390526001600160a01b03909116906322f8e56690602401600060405180830381600087803b158015610f3c57600080fd5b505af1158015610f50573d6000803e3d6000fd5b5050505050565b6000610f64848484612c3b565b6001600160a01b038416600090815260026020908152604080832033845290915290205482811015610fe95760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e74206578636565647320616044820152676c6c6f77616e636560c01b6064820152608401610acf565b610ff68533858403612911565b506001949350505050565b600e546001600160a01b0316331461102b5760405162461bcd60e51b8152600401610acf9061422c565b6110336128a4565b61103b6128f6565b600a805469ffffffffffffffff00001916620100006001600160401b038481168202929092179283905560405192041681527f958b6b3e25d854f9e658cd5610bd9d184123d203f58f95adf261e0d7d0dd65a590602001610b31565b3360008181526002602090815260408083206001600160a01b03871684529091528120549091610b519185906110ce9086906142ca565b612911565b6110db6128a4565b6110e36128f6565b600e60009054906101000a90046001600160a01b03166001600160a01b031663c73a32c36040518163ffffffff1660e01b815260040160206040518083038186803b15801561113157600080fd5b505afa158015611145573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111699190614418565b600a600e6101000a8154816001600160401b0302191690836001600160401b03160217905550600e60009054906101000a90046001600160a01b03166001600160a01b031663173684c56040518163ffffffff1660e01b815260040160206040518083038186803b1580156111dd57600080fd5b505afa1580156111f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112159190614435565b600a60166101000a81548163ffffffff021916908363ffffffff160217905550600e60009054906101000a90046001600160a01b03166001600160a01b0316637998a1c46040518163ffffffff1660e01b815260040160206040518083038186803b15801561128357600080fd5b505afa158015611297573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112bb9190614452565b6011556112c6612902565b565b6112d06128a4565b6112d86128f6565b60006112e383612a35565b90506112ef8183612e09565b60018251600281111561130457611304614263565b146113435760405162461bcd60e51b815260206004820152600f60248201526e105b1c9958591e481cd95d1d1b1959608a1b6044820152606401610acf565b6000600a60169054906101000a900463ffffffff168360800151611367919061446b565b9050428163ffffffff1611156113b45760405162461bcd60e51b8152602060048201526012602482015271139bdd081cd95d1d1b1958589b19481e595d60721b6044820152606401610acf565b82602001516001600160a01b0316336001600160a01b031614806113e857506113df8161038461446b565b63ffffffff1642115b6114275760405162461bcd60e51b815260206004820152601060248201526f2737ba1039b637bb903932b630bcb2b960811b6044820152606401610acf565b6040805160e0810190915261149b90806002815260200185602001516001600160a01b03168152602001856040015163ffffffff16815260200185606001516001600160401b03168152602001856080015163ffffffff1681526020018560a0015181526020018560c00151815250612a98565b60008381526012602052604081209190915560a085015160608501516114ce916114c491614493565b8660800151612e96565b85608001516114dd91906142b3565b905060006114eb8486612ebe565b600081815260136020526040902054600a549192506001600160a01b03169060ff16801561152057506001600160a01b038116155b1561153857611533876040015184612ee9565b61156d565b61156d6001600160a01b038216611553578760400151611555565b815b60065461010090046001600160a01b03169085612fb2565b60006115818860a001518960800151612e96565b905060008760a001518860c0015161159991906142ca565b60208901519091506001600160a01b03163314156115e15760208801516115dc906115c483856142ca565b60065461010090046001600160a01b03169190612fb2565b61161f565b6020880151600654611603916101009091046001600160a01b03169083612fb2565b60065461161f9061010090046001600160a01b03163384612fb2565b600061162b83876142ca565b905089608001516009600082825461164391906142b3565b92505081905550806007600082825461165c91906142b3565b92505081905550806008600082825461167591906144b5565b9250508190555081600d600082825461168e91906142b3565b9091555061169c9050612fe2565b6116b66116b18a606001518c60800151612e96565b613020565b336001600160a01b0316887fcfdda74fce9fedb259e0f0a1ab1550e19b338488ece64976a4639e7fce0293a78b6040516116f091906144f6565b60405180910390a350505060009182525060136020526040902080546001600160a01b031916905550610e9191506129029050565b61172d6128a4565b6117356128f6565b8015806117445750600a5460ff165b6117805760405162461bcd60e51b815260206004820152600d60248201526c086c2dce840e6cadcc840cae8d609b1b6044820152606401610acf565b6000670de0b6b3a7640000611793613053565b61179d9085614504565b6117a79190614539565b9050806009546117b791906142ca565b60075410156118085760405162461bcd60e51b815260206004820152601e60248201527f5574696c697a6174696f6e20746f6f206869676820746f2072656d6f766500006044820152606401610acf565b61181233846130cb565b806007600082825461182491906142b3565b9091555050811561183e576118393382612ee9565b61185a565b60065461185a9061010090046001600160a01b03163383612fb2565b604080518281526020810185905233917f0c54fc223ffd1a8f36652b5e83db4fff50f5ae151b11ceb56d5499b9f6e1fa18910160405180910390a250610e91612902565b6118a66128a4565b6118ae6128f6565b600a5460ff1680156118bf57508034145b806118c8575034155b6119145760405162461bcd60e51b815260206004820152601b60248201527f42616420616464206c6971756964697479204574682076616c756500000000006044820152606401610acf565b600061191e613053565b61193083670de0b6b3a7640000614504565b61193a9190614539565b90506119463382613219565b816007600082825461195891906142ca565b9091555050341580159061196e5750600a5460ff165b156119e157600660019054906101000a90046001600160a01b03166001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b1580156119c357600080fd5b505af11580156119d7573d6000803e3d6000fd5b50505050506119fe565b6006546119fe9061010090046001600160a01b0316333085612aff565b604080518381526020810183905233917f0351f600ef1e31e5e13b4dc27bff4cbde3e9269f0ffc666629ae6cac573eb220910160405180910390a250610b41612902565b6000611a4c6128a4565b611a546132f8565b905090565b6000611a636128a4565b611a6b6128f6565b611a7482612b70565b9050611a7e612902565b919050565b600a54610100900460ff16611ad05760405162461bcd60e51b815260206004820152601360248201527214995b185e5cc8185c9948191a5cd8589b1959606a1b6044820152606401610acf565b611ad86128a4565b611ae06128f6565b60004290506703782dace9d900008360a001516001600160401b031611158015611b1f57506703782dace9d900008360c001516001600160401b031611155b8015611b3c57506706f05b59d3b20000826001600160401b031611155b611b775760405162461bcd60e51b815260206004820152600c60248201526b496e76616c6964206665657360a01b6044820152606401610acf565b6000611b8284612a35565b60008181526012602052604090205490915015611bd85760405162461bcd60e51b815260206004820152601460248201527350656e64696e672072656c61792065786973747360601b6044820152606401610acf565b6000611be78560800151612a78565b905060006040518060e0016040528060016002811115611c0957611c09614263565b815233602082015260068054604090920191600160a81b900463ffffffff16906015611c348361428f565b91906101000a81548163ffffffff021916908363ffffffff16021790555063ffffffff168152602001866001600160401b031681526020018563ffffffff168152602001838152602001600b5481525090506000611c928783612aab565b9050611c9d82612a98565b600085815260126020526040812091909155611cb98584612ebe565b6000818152601360205260409020549091506001600160a01b031615611d1b5760405162461bcd60e51b8152602060048201526017602482015276052656c61792063616e6e6f74206265207370656420757604c1b6044820152606401610acf565b8760800151600954600754611d3091906142b3565b1015611d7a5760405162461bcd60e51b8152602060048201526019602482015278496e73756666696369656e7420706f6f6c2062616c616e636560381b6044820152606401610acf565b6000600b5485611d8a91906142ca565b90506000611dbe8a60c001518b60a001518760600151611daa9190614493565b611db49190614493565b8b60800151612e96565b90506000818b60800151611dd291906142b3565b905082600d6000828254611de691906142ca565b909155505060808b015160098054600090611e029084906142ca565b9091555050600084815260136020526040902080546001600160a01b03191633908117909155611e509030611e3786856142ca565b60065461010090046001600160a01b0316929190612aff565b600a5460ff1615611e6e57611e698b6040015182612ee9565b611e90565b60408b0151600654611e90916101009091046001600160a01b03169083612fb2565b877fa4ca36d112520cced74325c72711f376fe4015665829d879ba21590cb8130be08c8888604051611ec4939291906143ec565b60405180910390a2336001600160a01b0316887ff98cddc88bc965917007822b05056cb92bc9ddf0f8bcc61678400cb78313bb4b88604051611f0691906144f6565b60405180910390a3505050505050505050610e91612902565b600e546001600160a01b03163314611f495760405162461bcd60e51b8152600401610acf9061422c565b611f516128a4565b611f596128f6565b600e80546001600160a01b0319166001600160a01b0383169081179091556040805133815260208101929092527f485a12424bd0c2c66a131c2681cb6c743b9573af3ae5f3014ef6ce7f55ab01929101610b31565b606060058054610a22906141f1565b3360009081526002602090815260408083206001600160a01b03861684529091528120548281101561203f5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610acf565b61204c3385858403612911565b5060019392505050565b6000610b51338484612c3b565b606034156120b35760405162461bcd60e51b815260206004820152601b60248201527f4f6e6c79206d756c746963616c6c207769746820302076616c756500000000006044820152606401610acf565b816001600160401b038111156120cb576120cb613e0a565b6040519080825280602002602001820160405280156120fe57816020015b60608152602001906001900390816120e95790505b50905060005b8281101561220157600080308686858181106121225761212261455b565b90506020028101906121349190614571565b6040516121429291906145be565b600060405180830381855af49150503d806000811461217d576040519150601f19603f3d011682016040523d82523d6000602084013e612182565b606091505b5091509150816121ce5760448151101561219b57600080fd5b600481019050808060200190518101906121b591906145ce565b60405162461bcd60e51b8152600401610acf9190613d80565b808484815181106121e1576121e161455b565b6020026020010181905250505080806121f99061466f565b915050612104565b5092915050565b6122106128a4565b6122186128f6565b600e5460408051632e68f21360e21b815290516000926001600160a01b03169163b9a3c84c916004808301926020929190829003018186803b15801561225d57600080fd5b505afa158015612271573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612295919061468a565b6040516302abf57960e61b815275536b696e6e794f7074696d69737469634f7261636c6560501b60048201529091506001600160a01b0382169063aafd5e409060240160206040518083038186803b1580156122f057600080fd5b505afa158015612304573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612328919061468a565b601080546001600160a01b0319166001600160a01b039283161790556040516302abf57960e61b81526453746f726560d81b60048201529082169063aafd5e409060240160206040518083038186803b15801561238457600080fd5b505afa158015612398573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123bc919061468a565b600f80546001600160a01b0319166001600160a01b03928316908117909155600654604051635b97aadd60e01b8152610100909104909216600483015290635b97aadd9060240160206040518083038186803b15801561241b57600080fd5b505afa15801561242f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061245391906146a7565b51600b55506112c6612902565b600061246a6128a4565b6124726128f6565b610eb1613053565b6124826128a4565b61248a6128f6565b600061249583612a35565b90506124a18183612e09565b60006124ad8284612ebe565b9050600a60169054906101000a900463ffffffff1683608001516124d1919061446b565b63ffffffff16421080156124f757506001835160028111156124f5576124f5614263565b145b801561251857506000818152601360205260409020546001600160a01b0316155b61255e5760405162461bcd60e51b8152602060048201526017602482015276052656c61792063616e6e6f74206265207370656420757604c1b6044820152606401610acf565b600081815260136020526040812080546001600160a01b0319163317905560c085015160a086015160608601516125a3929161259991614493565b6114c49190614493565b905060008186608001516125b791906142b3565b600a5490915060ff16156125f5576006546125e29061010090046001600160a01b0316333084612aff565b6125f0866040015182612ee9565b612619565b6040860151600654612619916101009091046001600160a01b031690339084612aff565b336001600160a01b0316847ff98cddc88bc965917007822b05056cb92bc9ddf0f8bcc61678400cb78313bb4b8760405161265391906144f6565b60405180910390a350505050610e91612902565b61266f6128a4565b6126776128f6565b42600a54608083015161269791600160b01b900463ffffffff169061446b565b63ffffffff16116126da5760405162461bcd60e51b815260206004820152600d60248201526c50617374206c6976656e65737360981b6044820152606401610acf565b6001815160028111156126ef576126ef614263565b1461272d5760405162461bcd60e51b815260206004820152600e60248201526d4e6f742064697370757461626c6560901b6044820152606401610acf565b600061273883612a35565b90506127448183612e09565b60006127508484612aab565b905060006127758460200151338660a001518760c0015161277087612bfe565b613368565b90508360a001518460c0015161278b91906142ca565b600d600082825461279c91906142b3565b90915550506080850151600980546000906127b89084906142b3565b9091555050600083815260126020526040812055801561280c57336127dc85612a98565b60405185907f29751133c2d0a0ea7a9da312248b12ef10ac4c20f4e3ab5eebbb80d853b3836790600090a4612842565b3361281685612a98565b60405185907f14173c4d3bd95e34f5c8f78729323444c9272bd21051e70045b64ed48f65818390600090a45b505050610e91612902565b6000806128586128a4565b6128606128f6565b61286a6000612b70565b61287384612b70565b9150915061287f612902565b915091565b61288c6128a4565b6128946128f6565b61289c61368d565b6112c6612902565b60065460ff166112c65760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610acf565b6006805460ff19169055565b6006805460ff19166001179055565b6001600160a01b0383166129735760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610acf565b6001600160a01b0382166129d45760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610acf565b6001600160a01b0383811660008181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b600654604051600091612a5b91849161010090046001600160a01b0316906020016146e8565b604051602081830303815290604052805190602001209050919050565b600a54600090610b5590600160701b90046001600160401b031683612e96565b600081604051602001612a5b91906144f6565b60008282604001518360600151600660019054906101000a90046001600160a01b0316604051602001612ae19493929190614710565b60405160208183030381529060405280519060200120905092915050565b6040516001600160a01b0380851660248301528316604482015260648101829052612b6a9085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613750565b50505050565b6000612b7a61368d565b60008060085413612b8c576000612b90565b6008545b905060008160095485612ba391906142ca565b612bad91906142ca565b9050600082600754612bbf91906142ca565b905080612bd85750670de0b6b3a7640000949350505050565b80612beb83670de0b6b3a7640000614504565b612bf59190614539565b95945050505050565b6060610b5560405180602001604052806000815250604051806040016040528060098152602001680e4cad8c2f290c2e6d60bb1b81525084613822565b6001600160a01b038316612c9f5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610acf565b6001600160a01b038216612d015760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610acf565b6001600160a01b03831660009081526001602052604090205481811015612d795760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610acf565b6001600160a01b03808516600090815260016020526040808220858503905591851681529081208054849290612db09084906142ca565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051612dfc91815260200190565b60405180910390a3612b6a565b612e1281612a98565b60008381526012602052604090205414610e91576040805162461bcd60e51b81526020600482015260248101919091527f4861736865642072656c617920706172616d7320646f206e6f74206d6174636860448201527f206578697374696e672072656c6179206861736820666f72206465706f7369746064820152608401610acf565b6000670de0b6b3a7640000612eb4836001600160401b038616614504565b610eda9190614539565b6000828260600151604051602001612ae19291909182526001600160401b0316602082015260400190565b6001600160a01b0382163b15612f1557600654610e919061010090046001600160a01b03168383612fb2565b600654604051632e1a7d4d60e01b8152600481018390526101009091046001600160a01b031690632e1a7d4d90602401600060405180830381600087803b158015612f5f57600080fd5b505af1158015612f73573d6000803e3d6000fd5b50506040516001600160a01b038516925083156108fc02915083906000818181858888f19350505050158015612fad573d6000803e3d6000fd5b505050565b6040516001600160a01b038316602482015260448101829052612fad90849063a9059cbb60e01b90606401612b33565b6000612fec6132f8565b905080600c54612ffc91906142b3565b600c5550600a805463ffffffff60501b1916600160501b4263ffffffff1602179055565b80600c600082825461303291906142ca565b92505081905550806008600082825461304b91906144b5565b909155505050565b600061305e60035490565b61306f5750670de0b6b3a764000090565b613077612fe2565b61307f61368d565b6000600c5460085460075461309491906144b5565b61309e9190614755565b90506130a960035490565b6130bb82670de0b6b3a7640000614504565b6130c59190614539565b91505090565b6001600160a01b03821661312b5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610acf565b6001600160a01b0382166000908152600160205260409020548181101561319f5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610acf565b6001600160a01b03831660009081526001602052604081208383039055600380548492906131ce9084906142b3565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b6001600160a01b03821661326f5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610acf565b806003600082825461328191906142ca565b90915550506001600160a01b038216600090815260016020526040812080548392906132ae9084906142ca565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b600a546000908190670de0b6b3a764000090600160501b900463ffffffff164261332291906142b3565b600a54600c54613341916201000090046001600160401b031690614504565b61334b9190614504565b6133559190614539565b9050600c548110611a7e57600c546130c5565b60008061337585856142ca565b60105460065491925061339a9161010090046001600160a01b03908116911683613868565b6010546011546001600160a01b039091169063af355d1e904286600660019054906101000a90046001600160a01b031660008b600a60169054906101000a900463ffffffff168f670de0b6b3a76400006040518a63ffffffff1660e01b815260040161340e99989796959493929190614794565b602060405180830381600087803b15801561342857600080fd5b505af1925050508015613458575060408051601f3d908101601f1916820190925261345591810190614452565b60015b6134a5576006546134789061010090046001600160a01b03168883612fb2565b60105460065461349b916001600160a01b03610100909204821691166000613868565b6000915050612bf5565b818110156135005760006134b982846142b3565b6006549091506134d89061010090046001600160a01b03168a83612fb2565b6010546006546134fb916001600160a01b03610100909204821691166000613868565b819250505b5060408051610160810182526001600160a01b03898116825260006020830181905260065461010090049091169282019290925260608101829052670de0b6b3a7640000608082015260a08101829052600a5460c0820190600160b01b900463ffffffff164261357091906142ca565b81526000602082015260400161358688856142b3565b815260208101889052600a54600160b01b900463ffffffff9081166040909201919091526006549192506135cf9161010090046001600160a01b031690339030908690612aff16565b6010546006546135f1916001600160a01b036101009092048216911684613868565b60105460115460405163139c641960e31b81526001600160a01b0390921691639ce320c89161362c914290899087908e9030906004016147ff565b602060405180830381600087803b15801561364657600080fd5b505af115801561365a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061367e9190614452565b50600198975050505050505050565b600d546006546040516370a0823160e01b81523060048201526000929161010090046001600160a01b0316906370a082319060240160206040518083038186803b1580156136da57600080fd5b505afa1580156136ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137129190614452565b61371c91906142b3565b9050600754811115610b415760075461373590826142b3565b600860008282546137469190614755565b9091555050600755565b60006137a5826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661398c9092919063ffffffff16565b805190915015612fad57808060200190518101906137c391906148f8565b612fad5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610acf565b6060600061383085856139a3565b9050848161383d856139e5565b60405160200161384f93929190614915565b6040516020818303038152906040529150509392505050565b8015806138f15750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b1580156138b757600080fd5b505afa1580156138cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138ef9190614452565b155b61395c5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608401610acf565b6040516001600160a01b038316602482015260448101829052612fad90849063095ea7b360e01b90606401612b33565b606061399b8484600085613a25565b949350505050565b8151606090156139d457816040516020016139be9190614958565b6040516020818303038152906040529050610b55565b816040516020016139be919061498c565b60606139f4608083901c613b4d565b6139fd83613b4d565b6040805160208101939093528201526060016040516020818303038152906040529050919050565b606082471015613a865760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610acf565b843b613ad45760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610acf565b600080866001600160a01b03168587604051613af091906149b1565b60006040518083038185875af1925050503d8060008114613b2d576040519150601f19603f3d011682016040523d82523d6000602084013e613b32565b606091505b5091509150613b42828286613cef565b979650505050505050565b6000808260001c9050806fffffffffffffffffffffffffffffffff169050806801000000000000000002811777ffffffffffffffff0000000000000000ffffffffffffffff169050806401000000000281177bffffffff00000000ffffffff00000000ffffffff00000000ffffffff16905080620100000281177dffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff169050806101000281177eff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff1690508060100281177f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f16905060006008827f08080808080808080808080808080808080808080808080808080808080808081681613c7157613c71614523565b0460047f040404040404040404040404040404040404040404040404040404040404040484160460027f020202020202020202020202020202020202020202020202020202020202020285160417166027029091017f3030303030303030303030303030303030303030303030303030303030303030019392505050565b60608315613cfe575081610eda565b825115613d0e5782518084602001fd5b8160405162461bcd60e51b8152600401610acf9190613d80565b60005b83811015613d43578181015183820152602001613d2b565b83811115612b6a5750506000910152565b60008151808452613d6c816020860160208601613d28565b601f01601f19169290920160200192915050565b602081526000610eda6020830184613d54565b8015158114610b4157600080fd5b600060208284031215613db357600080fd5b8135610eda81613d93565b6001600160a01b0381168114610b4157600080fd5b8035611a7e81613dbe565b60008060408385031215613df157600080fd5b8235613dfc81613dbe565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b60405160e081016001600160401b0381118282101715613e4257613e42613e0a565b60405290565b6001600160401b0381168114610b4157600080fd5b8035611a7e81613e48565b63ffffffff81168114610b4157600080fd5b8035611a7e81613e68565b6000610100808385031215613e9957600080fd5b604051908101906001600160401b0382118183101715613ebb57613ebb613e0a565b816040528092508335815260208401359150613ed682613e48565b816020820152613ee860408501613dd3565b6040820152613ef960608501613dd3565b606082015260808401356080820152613f1460a08501613e5d565b60a0820152613f2560c08501613e5d565b60c0820152613f3660e08501613e7a565b60e0820152505092915050565b6000806101208385031215613f5757600080fd5b613f618484613e85565b9150610100830135613f7281613e48565b809150509250929050565b6000808284036101e0811215613f9257600080fd5b613f9c8585613e85565b925060e060ff1982011215613fb057600080fd5b50613fb9613e20565b61010084013560038110613fcc57600080fd5b8152613fdb6101208501613dd3565b6020820152613fed6101408501613e7a565b6040820152613fff6101608501613e5d565b60608201526140116101808501613e7a565b60808201526101a084013560a08201526101c09093013560c08401525092909150565b60006020828403121561404657600080fd5b5035919050565b60008060006060848603121561406257600080fd5b833561406d81613dbe565b9250602084013561407d81613dbe565b929592945050506040919091013590565b6000602082840312156140a057600080fd5b8135610eda81613e48565b600080604083850312156140be57600080fd5b823591506020830135613f7281613d93565b6000602082840312156140e257600080fd5b8135610eda81613dbe565b6000806020838503121561410057600080fd5b82356001600160401b038082111561411757600080fd5b818501915085601f83011261412b57600080fd5b81358181111561413a57600080fd5b8660208260051b850101111561414f57600080fd5b60209290920196919550909350505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b828110156141b657603f198886030184526141a4858351613d54565b94509285019290850190600101614188565b5092979650505050505050565b600080604083850312156141d657600080fd5b82356141e181613dbe565b91506020830135613f7281613dbe565b600181811c9082168061420557607f821691505b6020821081141561422657634e487b7160e01b600052602260045260246000fd5b50919050565b60208082526017908201527f43616c6c6572206e6f74206272696467652061646d696e000000000000000000604082015260600190565b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff808316818114156142a9576142a9614279565b6001019392505050565b6000828210156142c5576142c5614279565b500390565b600082198211156142dd576142dd614279565b500190565b8051825260208101516001600160401b0380821660208501526040830151915060018060a01b03808316604086015280606085015116606086015250608083015160808501528060a08401511660a08501528060c08401511660c0850152505063ffffffff60e08201511660e08301525050565b80516003811061437657634e487b7160e01b600052602160045260246000fd5b82526020818101516001600160a01b031690830152604080820151906143a39084018263ffffffff169052565b5060608101516143be60608401826001600160401b03169052565b5060808101516143d6608084018263ffffffff169052565b5060a0818101519083015260c090810151910152565b61020081016143fb82866142e2565b614409610100830185614356565b826101e0830152949350505050565b60006020828403121561442a57600080fd5b8151610eda81613e48565b60006020828403121561444757600080fd5b8151610eda81613e68565b60006020828403121561446457600080fd5b5051919050565b600063ffffffff80831681851680830382111561448a5761448a614279565b01949350505050565b60006001600160401b0380831681851680830382111561448a5761448a614279565b600080821280156001600160ff1b03849003851316156144d7576144d7614279565b600160ff1b83900384128116156144f0576144f0614279565b50500190565b60e08101610b558284614356565b600081600019048311821515161561451e5761451e614279565b500290565b634e487b7160e01b600052601260045260246000fd5b60008261455657634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052603260045260246000fd5b6000808335601e1984360301811261458857600080fd5b8301803591506001600160401b038211156145a257600080fd5b6020019150368190038213156145b757600080fd5b9250929050565b8183823760009101908152919050565b6000602082840312156145e057600080fd5b81516001600160401b03808211156145f757600080fd5b818401915084601f83011261460b57600080fd5b81518181111561461d5761461d613e0a565b604051601f8201601f19908116603f0116810190838211818310171561464557614645613e0a565b8160405282815287602084870101111561465e57600080fd5b613b42836020830160208801613d28565b600060001982141561468357614683614279565b5060010190565b60006020828403121561469c57600080fd5b8151610eda81613dbe565b6000602082840312156146b957600080fd5b604051602081018181106001600160401b03821117156146db576146db613e0a565b6040529151825250919050565b61012081016146f782856142e2565b6001600160a01b03929092166101009190910152919050565b610160810161471f82876142e2565b63ffffffff949094166101008201526001600160401b03929092166101208301526001600160a01b031661014090910152919050565b60008083128015600160ff1b85018412161561477357614773614279565b6001600160ff1b038401831381161561478e5761478e614279565b50500390565b60006101208b835263ffffffff808c1660208501528160408501526147bb8285018c613d54565b6001600160a01b039a8b166060860152608085019990995260a084019790975250509290931660c083015290931660e0840152610100909201919091529392505050565b600061020088835263ffffffff8816602084015280604084015261482581840188613d54565b91505061483e6060830186516001600160a01b03169052565b60208501516001600160a01b03811660808401525060408501516001600160a01b03811660a084015250606085015180151560c084015250608085015160e083015260a0850151610100818185015260c08701519150610120828186015260e0880151925061014083818701528289015161016087015281890151610180870152808901516101a0870152505050506148e36101c08301856001600160a01b03169052565b6001600160a01b0383166101e0830152613b42565b60006020828403121561490a57600080fd5b8151610eda81613d93565b60008451614927818460208901613d28565b84519083019061493b818360208901613d28565b845191019061494e818360208801613d28565b0195945050505050565b600b60fa1b815260008251614974816001850160208701613d28565b601d60f91b6001939091019283015250600201919050565b6000825161499e818460208701613d28565b601d60f91b920191825250600101919050565b600082516149c3818460208701613d28565b919091019291505056fea2646970667358221220e29df9833ee712dea5e74a80725a39c21912ff9a19c010ca4afb5d0d9057d98064736f6c63430008090033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000030b44c676a05f1264d1de9cc31db5f2a945186b60000000000000000000000002260fac5e5542a773aa44fbcfedf7c193bc2c5990000000000000000000000000000000000000000000000000000015d3ef7980000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4163726f73732057425443204c500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009412d574254432d4c500000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _lpTokenName (string): Across WBTC LP
Arg [1] : _lpTokenSymbol (string): A-WBTC-LP
Arg [2] : _bridgeAdmin (address): 0x30B44C676A05F1264d1dE9cC31dB5F2A945186b6
Arg [3] : _l1Token (address): 0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599
Arg [4] : _lpFeeRatePerSecond (uint64): 1500000000000
Arg [5] : _isWethPool (bool): False
Arg [6] : _timer (address): 0x0000000000000000000000000000000000000000
-----Encoded View---------------
11 Constructor Arguments found :
Arg [0] : 00000000000000000000000000000000000000000000000000000000000000e0
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000120
Arg [2] : 00000000000000000000000030b44c676a05f1264d1de9cc31db5f2a945186b6
Arg [3] : 0000000000000000000000002260fac5e5542a773aa44fbcfedf7c193bc2c599
Arg [4] : 0000000000000000000000000000000000000000000000000000015d3ef79800
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [7] : 000000000000000000000000000000000000000000000000000000000000000e
Arg [8] : 4163726f73732057425443204c50000000000000000000000000000000000000
Arg [9] : 0000000000000000000000000000000000000000000000000000000000000009
Arg [10] : 412d574254432d4c500000000000000000000000000000000000000000000000
Deployed Bytecode Sourcemap
165711:521:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;91985:100;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;152341:193;;;;;;;;;;-1:-1:-1;152341:193:0;;;;;:::i;:::-;;:::i;:::-;;94152:169;;;;;;;;;;-1:-1:-1;94152:169:0;;;;;:::i;:::-;;:::i;:::-;;;1990:14:1;;1983:22;1965:41;;1953:2;1938:18;94152:169:0;1825:187:1;116173:32:0;;;;;;;;;;-1:-1:-1;116173:32:0;;;;;;;-1:-1:-1;;;;;116173:32:0;;;;;;-1:-1:-1;;;;;2286:31:1;;;2268:50;;2256:2;2241:18;116173:32:0;2124:200:1;134885:3068:0;;;;;;;;;;-1:-1:-1;134885:3068:0;;;;;:::i;:::-;;:::i;116867:20::-;;;;;;;;;;;;;;;;;;;4774:25:1;;;4762:2;4747:18;116867:20:0;4628:177:1;116409:38:0;;;;;;;;;;-1:-1:-1;116409:38:0;;;;-1:-1:-1;;;116409:38:0;;;;;;;;;5083:10:1;5071:23;;;5053:42;;5041:2;5026:18;116409:38:0;4909:192:1;93105:108:0;;;;;;;;;;-1:-1:-1;93193:12:0;;93105:108;;147816:138;;;;;;;;;;;;;:::i;153614:273::-;;;;;;;;;;-1:-1:-1;153614:273:0;;;;;:::i;:::-;;:::i;82854:27::-;;;;;;;;;;-1:-1:-1;82854:27:0;;;;-1:-1:-1;;;;;82854:27:0;;;;;;-1:-1:-1;;;;;6587:32:1;;;6569:51;;6557:2;6542:18;82854:27:0;6423:203:1;117276:55:0;;;;;;;;;;-1:-1:-1;117276:55:0;;;;-1:-1:-1;;;;;117276:55:0;;;83584:117;;;;;;;;;;-1:-1:-1;83584:117:0;;;;;:::i;:::-;;:::i;94803:492::-;;;;;;;;;;-1:-1:-1;94803:492:0;;;;;:::i;:::-;;:::i;151766:221::-;;;;;;;;;;-1:-1:-1;151766:221:0;;;;;:::i;:::-;;:::i;166115:114::-;;;;;;;;;;-1:-1:-1;166206:15:0;166115:114;;92947:93;;;;;;;;;;-1:-1:-1;92947:93:0;;93030:2;7916:36:1;;7904:2;7889:18;92947:93:0;7774:184:1;95704:215:0;;;;;;;;;;-1:-1:-1;95704:215:0;;;;;:::i;:::-;;:::i;150637:249::-;;;;;;;;;;;;;:::i;141962:5025::-;;;;;;;;;;-1:-1:-1;141962:5025:0;;;;;:::i;:::-;;:::i;116705:34::-;;;;;;;;;;;;;;;;125776:830;;;;;;;;;;-1:-1:-1;125776:830:0;;;;;:::i;:::-;;:::i;124146:980::-;;;;;;:::i;:::-;;:::i;152839:126::-;;;;;;;;;;;;;:::i;148309:173::-;;;;;;;;;;-1:-1:-1;148309:173:0;;;;;:::i;:::-;;:::i;115501:30::-;;;;;;;;;;;;;;;;93276:127;;;;;;;;;;-1:-1:-1;93276:127:0;;;;;:::i;:::-;-1:-1:-1;;;;;93377:18:0;93350:7;93377:18;;;:9;:18;;;;;;;93276:127;127709:4439;;;;;;;;;;-1:-1:-1;127709:4439:0;;;;;:::i;:::-;;:::i;117436:25::-;;;;;;;;;;;;;;;;115626:30;;;;;;;;;;;;;;;;151238:218;;;;;;;;;;-1:-1:-1;151238:218:0;;;;;:::i;:::-;;:::i;92204:104::-;;;;;;;;;;;;;:::i;117242:27::-;;;;;;;;;;-1:-1:-1;117242:27:0;;;;-1:-1:-1;;;;;117242:27:0;;;96422:413;;;;;;;;;;-1:-1:-1;96422:413:0;;;;;:::i;:::-;;:::i;117018:39::-;;;;;;;;;;-1:-1:-1;117018:39:0;;;;-1:-1:-1;;;;;117018:39:0;;;93616:175;;;;;;;;;;-1:-1:-1;93616:175:0;;;;;:::i;:::-;;:::i;87553:727::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;115390:29::-;;;;;;;;;;;;;;;;119876:48;;;;;;;;;;-1:-1:-1;119876:48:0;;;;;:::i;:::-;;;;;;;;;;;;-1:-1:-1;;;;;119876:48:0;;;149709:465;;;;;;;;;;;;;:::i;147499:119::-;;;;;;;;;;;;;:::i;116014:32::-;;;;;;;;;;-1:-1:-1;116014:32:0;;;;;;;;;;;139495:1768;;;;;;;;;;-1:-1:-1;139495:1768:0;;;;;:::i;:::-;;:::i;115186:30::-;;;;;;;;;;-1:-1:-1;115186:30:0;;;;;;;-1:-1:-1;;;;;115186:30:0;;;116373:29;;;;;;;;;;-1:-1:-1;116373:29:0;;;;-1:-1:-1;;;116373:29:0;;-1:-1:-1;;;;;116373:29:0;;;115868:22;;;;;;;;;;-1:-1:-1;115868:22:0;;;;;;;;132781:1377;;;;;;;;;;-1:-1:-1;132781:1377:0;;;;;:::i;:::-;;:::i;115298:28::-;;;;;;;;;;-1:-1:-1;115298:28:0;;;;-1:-1:-1;;;115298:28:0;;;;;;93854:151;;;;;;;;;;-1:-1:-1;93854:151:0;;;;;:::i;:::-;-1:-1:-1;;;;;93970:18:0;;;93943:7;93970:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;93854:151;119652:41;;;;;;;;;;-1:-1:-1;119652:41:0;;;;;:::i;:::-;;;;;;;;;;;;;;148939:285;;;;;;;;;;-1:-1:-1;148939:285:0;;;;;:::i;:::-;;:::i;:::-;;;;11769:25:1;;;11825:2;11810:18;;11803:34;;;;11742:18;148939:285:0;11595:248:1;116264:29:0;;;;;;;;;;-1:-1:-1;116264:29:0;;;;-1:-1:-1;;;116264:29:0;;;;;;147222:64;;;;;;;;;;;;;:::i;91985:100::-;92039:13;92072:5;92065:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;91985:100;:::o;152341:193::-;121313:11;;-1:-1:-1;;;;;121313:11:0;121291:10;:34;121283:70;;;;-1:-1:-1;;;121283:70:0;;;;;;;:::i;:::-;;;;;;;;;85575:19:::1;:17;:19::i;:::-;85605:17;:15;:17::i;:::-;152448:13:::2;:30:::0;;;::::2;;;;-1:-1:-1::0;;152448:30:0;;::::2;;::::0;;152494:32:::2;::::0;::::2;::::0;::::2;::::0;152464:14;1990::1;1983:22;1965:41;;1953:2;1938:18;;1825:187;152494:32:0::2;;;;;;;;85645:20:::1;:18;:20::i;:::-;152341:193:::0;:::o;94152:169::-;94235:4;94252:39;89741:10;94275:7;94284:6;94252:8;:39::i;:::-;-1:-1:-1;94309:4:0;94152:169;;;;;:::o;134885:3068::-;121430:13;;;;;;;121422:45;;;;-1:-1:-1;;;121422:45:0;;12787:2:1;121422:45:0;;;12769:21:1;12826:2;12806:18;;;12799:30;-1:-1:-1;;;12845:18:1;;;12838:49;12904:18;;121422:45:0;12585:343:1;121422:45:0;85575:19:::1;:17;:19::i;:::-;85605:17;:15;:17::i;:::-;135329:7:::2;135298:11;:27;;;-1:-1:-1::0;;;;;135298:38:0::2;;;:100;;;;;135391:7;135357:11;:30;;;-1:-1:-1::0;;;;;135357:41:0::2;;;135298:100;:147;;;;;135439:6;135419:16;-1:-1:-1::0;;;;;135419:26:0::2;;;135298:147;135276:209;;;::::0;-1:-1:-1;;;135276:209:0;;13135:2:1;135276:209:0::2;::::0;::::2;13117:21:1::0;13174:2;13154:18;;;13147:30;-1:-1:-1;;;13193:18:1;;;13186:42;13245:18;;135276:209:0::2;12933:336:1::0;135276:209:0::2;135562:19;135584:28;135600:11;135584:15;:28::i;:::-;135773:1;135742:19:::0;;;:6:::2;:19;::::0;;;;;135562:50;;-1:-1:-1;135742:33:0;135734:66:::2;;;::::0;-1:-1:-1;;;135734:66:0;;13476:2:1;135734:66:0::2;::::0;::::2;13458:21:1::0;13515:2;13495:18;;;13488:30;-1:-1:-1;;;13534:18:1;;;13527:50;13594:18;;135734:66:0::2;13274:344:1::0;135734:66:0::2;135914:23;166206:15:::0;135914:50:::2;;135977:20;136000:36;136017:11;:18;;;136000:16;:36::i;:::-;135977:59;;136447:26;136489:448;;;;;;;;136530:18;136489:448;;;;;;;;:::i;:::-;::::0;;136580:10:::2;136489:448;::::0;::::2;::::0;136618:14:::2;:16:::0;;136489:448;;;;;-1:-1:-1;;;136618:16:0;::::2;;;::::0;:14:::2;:16;::::0;::::2;:::i;:::-;;;;;;;;;;;;;;;;;;;;;136489:448;;;;;;136763:16;-1:-1:-1::0;;;;;136489:448:0::2;;;;;136816:16;136489:448;;;;;;136865:12;136489:448;;;;136906:15;;136489:448;;::::0;136447:490:::2;;136970:28;136988:9;136970:17;:28::i;:::-;136948:19;::::0;;;:6:::2;:19;::::0;;;;:50;;;;137031:37:::2;137045:11:::0;137058:9;137031:13:::2;:37::i;:::-;137011:57;;137417:11;:18;;;137398:15;;137381:14;;:32;;;;:::i;:::-;:54;;137373:92;;;::::0;-1:-1:-1;;;137373:92:0;;14425:2:1;137373:92:0::2;::::0;::::2;14407:21:1::0;14464:2;14444:18;;;14437:30;-1:-1:-1;;;14483:18:1;;;14476:55;14548:18;;137373:92:0::2;14223:349:1::0;137373:92:0::2;137591:17;137626:15;;137611:12;:30;;;;:::i;:::-;137591:50;;137671:11;:18;;;137652:15;;:37;;;;;;;:::i;:::-;;;;;;;;137783:9;137774:5;;:18;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;137805:7:0::2;::::0;:62:::2;::::0;:7:::2;::::0;::::2;-1:-1:-1::0;;;;;137805:7:0::2;137830:10;137850:4;137857:9:::0;137805:24:::2;:62::i;:::-;137898:11;137883:62;137911:11;137924:9;137935;137883:62;;;;;;;;:::i;:::-;;;;;;;;135039:2914;;;;;;85645:20:::1;:18;:20::i;:::-;134885:3068:::0;;:::o;147816:138::-;147886:7;85575:19;:17;:19::i;:::-;85605:17;:15;:17::i;:::-;147913:33:::1;147944:1;147913:30;:33::i;:::-;147906:40;;85645:20:::0;:18;:20::i;:::-;147816:138;:::o;153614:273::-;153781:12;85871:19;:17;:19::i;:::-;153818:61:::1;153841:37;153855:11;153868:9;153841:13;:37::i;:::-;153818:22;:61::i;:::-;153811:68:::0;153614:273;-1:-1:-1;;;153614:273:0:o;83584:117::-;83377:3;83353:12;-1:-1:-1;;;;;83353:12:0;83345:37;;;;;;83659:12:::1;::::0;83653:40:::1;::::0;-1:-1:-1;;;83653:40:0;;::::1;::::0;::::1;4774:25:1::0;;;-1:-1:-1;;;;;83659:12:0;;::::1;::::0;83653:34:::1;::::0;4747:18:1;;83653:40:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;83584:117:::0;:::o;94803:492::-;94943:4;94960:36;94970:6;94978:9;94989:6;94960:9;:36::i;:::-;-1:-1:-1;;;;;95036:19:0;;95009:24;95036:19;;;:11;:19;;;;;;;;89741:10;95036:33;;;;;;;;95088:26;;;;95080:79;;;;-1:-1:-1;;;95080:79:0;;16906:2:1;95080:79:0;;;16888:21:1;16945:2;16925:18;;;16918:30;16984:34;16964:18;;;16957:62;-1:-1:-1;;;17035:18:1;;;17028:38;17083:19;;95080:79:0;16704:404:1;95080:79:0;95195:57;95204:6;89741:10;95245:6;95226:16;:25;95195:8;:57::i;:::-;-1:-1:-1;95283:4:0;;94803:492;-1:-1:-1;;;;94803:492:0:o;151766:221::-;121313:11;;-1:-1:-1;;;;;121313:11:0;121291:10;:34;121283:70;;;;-1:-1:-1;;;121283:70:0;;;;;;;:::i;:::-;85575:19:::1;:17;:19::i;:::-;85605:17;:15;:17::i;:::-;151888:18:::2;:43:::0;;-1:-1:-1;;151888:43:0::2;::::0;-1:-1:-1;;;;;151888:43:0;;::::2;::::0;::::2;::::0;;;::::2;::::0;;;;151947:32:::2;::::0;151960:18;::::2;;2268:50:1::0;;151947:32:0::2;::::0;2256:2:1;2241:18;151947:32:0::2;2124:200:1::0;95704:215:0;89741:10;95792:4;95841:25;;;:11;:25;;;;;;;;-1:-1:-1;;;;;95841:34:0;;;;;;;;;;95792:4;;95809:80;;95832:7;;95841:47;;95878:10;;95841:47;:::i;:::-;95809:8;:80::i;150637:249::-;85575:19;:17;:19::i;:::-;85605:17;:15;:17::i;:::-;150725:11:::1;;;;;;;;;-1:-1:-1::0;;;;;150725:11:0::1;-1:-1:-1::0;;;;;150725:27:0::1;;:29;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;150707:15;;:47;;;;;-1:-1:-1::0;;;;;150707:47:0::1;;;;;-1:-1:-1::0;;;;;150707:47:0::1;;;;;;150792:11;;;;;;;;;-1:-1:-1::0;;;;;150792:11:0::1;-1:-1:-1::0;;;;;150792:36:0::1;;:38;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;150765:24;;:65;;;;;;;;;;;;;;;;;;150854:11;;;;;;;;;-1:-1:-1::0;;;;;150854:11:0::1;-1:-1:-1::0;;;;;150854:22:0::1;;:24;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;150841:10;:37:::0;85645:20;:18;:20::i;:::-;150637:249::o;141962:5025::-;85575:19;:17;:19::i;:::-;85605:17;:15;:17::i;:::-;142076:19:::1;142098:28;142114:11;142098:15;:28::i;:::-;142076:50;;142137:46;142160:11;142173:9;142137:22;:46::i;:::-;142226:18;142202:20:::0;;:42:::1;::::0;::::1;;;;;;:::i;:::-;;142194:70;;;::::0;-1:-1:-1;;;142194:70:0;;18012:2:1;142194:70:0::1;::::0;::::1;17994:21:1::0;18051:2;18031:18;;;18024:30;-1:-1:-1;;;18070:18:1;;;18063:45;18125:18;;142194:70:0::1;17810:339:1::0;142194:70:0::1;142275:21;142328:24;;;;;;;;;;;142299:9;:26;;;:53;;;;:::i;:::-;142275:77:::0;-1:-1:-1;166206:15:0;142371:14:::1;:34;;;;142363:65;;;::::0;-1:-1:-1;;;142363:65:0;;18589:2:1;142363:65:0::1;::::0;::::1;18571:21:1::0;18628:2;18608:18;;;18601:30;-1:-1:-1;;;18647:18:1;;;18640:48;18705:18;;142363:65:0::1;18387:342:1::0;142363:65:0::1;142718:9;:21;;;-1:-1:-1::0;;;;;142704:35:0::1;:10;-1:-1:-1::0;;;;;142704:35:0::1;;:85;;;-1:-1:-1::0;142762:27:0::1;:14:::0;142779:10:::1;142762:27;:::i;:::-;142743:46;;166206:15:::0;142743:46:::1;142704:85;142682:151;;;::::0;-1:-1:-1;;;142682:151:0;;18936:2:1;142682:151:0::1;::::0;::::1;18918:21:1::0;18975:2;18955:18;;;18948:30;-1:-1:-1;;;18994:18:1;;;18987:46;19050:18;;142682:151:0::1;18734:340:1::0;142682:151:0::1;142991:403;::::0;;::::1;::::0;::::1;::::0;;;142959:446:::1;::::0;142991:403;143032:20:::1;142991:403;;;;143084:9;:21;;;-1:-1:-1::0;;;;;142991:403:0::1;;;;;143133:9;:17;;;142991:403;;;;;;143187:9;:26;;;-1:-1:-1::0;;;;;142991:403:0::1;;;;;143250:9;:26;;;142991:403;;;;;;143309:9;:22;;;142991:403;;;;143360:9;:18;;;142991:403;;::::0;142959:17:::1;:446::i;:::-;142937:19;::::0;;;:6:::1;:19;::::0;;;;:468;;;;144385:27:::1;::::0;::::1;::::0;144356:26:::1;::::0;::::1;::::0;144338:95:::1;::::0;144356:56:::1;::::0;::::1;:::i;:::-;144414:11;:18;;;144338:17;:95::i;:::-;144300:11;:18;;;:133;;;;:::i;:::-;144245:188;;144540:24;144567:44;144588:11;144601:9;144567:20;:44::i;:::-;144622:22;144647:31:::0;;;:13:::1;:31;::::0;;;;;144886:10:::1;::::0;144540:71;;-1:-1:-1;;;;;;144647:31:0::1;::::0;144886:10:::1;;:42:::0;::::1;;;-1:-1:-1::0;;;;;;144900:28:0;::::1;::::0;144886:42:::1;144882:574;;;144945:71;144959:11;:23;;;144984:31;144945:13;:71::i;:::-;144882:574;;;145281:175;-1:-1:-1::0;;;;;145320:28:0;::::1;:71;;145368:11;:23;;;145320:71;;;145351:14;145320:71;145281:7;::::0;::::1;::::0;::::1;-1:-1:-1::0;;;;;145281:7:0::1;::::0;145410:31;145281:20:::1;:175::i;:::-;145753:25;145781:66;145799:11;:27;;;145828:11;:18;;;145781:17;:66::i;:::-;145753:94;;145858:17;145899:9;:22;;;145878:9;:18;;;:43;;;;:::i;:::-;145936:21;::::0;::::1;::::0;145858:63;;-1:-1:-1;;;;;;145936:35:0::1;145961:10;145936:35;145932:291;;;146007:21;::::0;::::1;::::0;145986:74:::1;::::0;146030:29:::1;146050:9:::0;146030:17;:29:::1;:::i;:::-;145986:7;::::0;::::1;::::0;::::1;-1:-1:-1::0;;;;;145986:7:0::1;::::0;;:20:::1;:74::i;:::-;145932:291;;;146112:21;::::0;::::1;::::0;146091:7:::1;::::0;:54:::1;::::0;:7:::1;::::0;;::::1;-1:-1:-1::0;;;;;146091:7:0::1;::::0;146135:9;146091:20:::1;:54::i;:::-;146160:7;::::0;:51:::1;::::0;:7:::1;::::0;::::1;-1:-1:-1::0;;;;;146160:7:0::1;146181:10;146193:17:::0;146160:20:::1;:51::i;:::-;146235:25;146263:51;146297:17:::0;146263:31;:51:::1;:::i;:::-;146235:79;;146416:11;:18;;;146397:15;;:37;;;;;;;:::i;:::-;;;;;;;;146463:17;146445:14;;:35;;;;;;;:::i;:::-;;;;;;;;146518:17;146491:16;;:45;;;;;;;:::i;:::-;;;;;;;;146556:9;146547:5;;:18;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;146576:26:0::1;::::0;-1:-1:-1;146576:24:0::1;:26::i;:::-;146613:82;146629:65;146647:9;:26;;;146675:11;:18;;;146629:17;:65::i;:::-;146613:15;:82::i;:::-;146739:10;-1:-1:-1::0;;;;;146713:48:0::1;146726:11;146713:48;146751:9;146713:48;;;;;;:::i;:::-;;;;;;;;-1:-1:-1::0;;;146948:31:0::1;::::0;;;-1:-1:-1;146948:13:0::1;:31;::::0;;;;146941:38;;-1:-1:-1;;;;;;146941:38:0::1;::::0;;-1:-1:-1;85645:20:0;;-1:-1:-1;85645:18:0;;-1:-1:-1;85645:20:0:i;125776:830::-;85575:19;:17;:19::i;:::-;85605:17;:15;:17::i;:::-;125962:7:::1;125961:8;:22;;;-1:-1:-1::0;125973:10:0::1;::::0;::::1;;125961:22;125953:48;;;::::0;-1:-1:-1;;;125953:48:0;;20050:2:1;125953:48:0::1;::::0;::::1;20032:21:1::0;20089:2;20069:18;;;20062:30;-1:-1:-1;;;20108:18:1;;;20101:43;20161:18;;125953:48:0::1;19848:337:1::0;125953:48:0::1;126012:24;126082:4;126056:22;:20;:22::i;:::-;126040:38;::::0;:13;:38:::1;:::i;:::-;126039:47;;;;:::i;:::-;126012:74;;126233:16;126215:15;;:34;;;;:::i;:::-;126196:14;;:54;;126188:97;;;::::0;-1:-1:-1;;;126188:97:0;;20919:2:1;126188:97:0::1;::::0;::::1;20901:21:1::0;20958:2;20938:18;;;20931:30;20997:32;20977:18;;;20970:60;21047:18;;126188:97:0::1;20717:354:1::0;126188:97:0::1;126298:32;126304:10;126316:13;126298:5;:32::i;:::-;126359:16;126341:14;;:34;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;126388:131:0;::::1;;;126401:52;126423:10;126436:16;126401:13;:52::i;:::-;126388:131;;;126469:7;::::0;:50:::1;::::0;:7:::1;::::0;::::1;-1:-1:-1::0;;;;;126469:7:0::1;126490:10;126502:16:::0;126469:20:::1;:50::i;:::-;126537:61;::::0;;11769:25:1;;;11825:2;11810:18;;11803:34;;;126587:10:0::1;::::0;126537:61:::1;::::0;11742:18:1;126537:61:0::1;;;;;;;125860:746;85645:20:::0;:18;:20::i;124146:980::-;85575:19;:17;:19::i;:::-;85605:17;:15;:17::i;:::-;124404:10:::1;::::0;::::1;;:40:::0;::::1;;;;124431:13;124418:9;:26;124404:40;124403:60;;;-1:-1:-1::0;124449:9:0::1;:14:::0;124403:60:::1;124395:100;;;::::0;-1:-1:-1;;;124395:100:0;;21278:2:1;124395:100:0::1;::::0;::::1;21260:21:1::0;21317:2;21297:18;;;21290:30;21356:29;21336:18;;;21329:57;21403:18;;124395:100:0::1;21076:351:1::0;124395:100:0::1;124700:22;124750;:20;:22::i;:::-;124726:20;:13:::0;124742:4:::1;124726:20;:::i;:::-;124725:47;;;;:::i;:::-;124700:72;;124783:33;124789:10;124801:14;124783:5;:33::i;:::-;124845:13;124827:14;;:31;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;124875:9:0::1;:13:::0;;;;:27:::1;;-1:-1:-1::0;124892:10:0::1;::::0;::::1;;124875:27;124871:172;;;124922:7;;;;;;;;;-1:-1:-1::0;;;;;124922:7:0::1;-1:-1:-1::0;;;;;124904:35:0::1;;124948:9;124904:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;124871:172;;;124977:7;::::0;:66:::1;::::0;:7:::1;::::0;::::1;-1:-1:-1::0;;;;;124977:7:0::1;125002:10;125022:4;125029:13:::0;124977:24:::1;:66::i;:::-;125061:57;::::0;;11769:25:1;;;11825:2;11810:18;;11803:34;;;125107:10:0::1;::::0;125061:57:::1;::::0;11742:18:1;125061:57:0::1;;;;;;;124221:905;85645:20:::0;:18;:20::i;152839:126::-;152909:7;85871:19;:17;:19::i;:::-;152936:21:::1;:19;:21::i;:::-;152929:28;;152839:126:::0;:::o;148309:173::-;148402:7;85575:19;:17;:19::i;:::-;85605:17;:15;:17::i;:::-;148429:45:::1;148460:13;148429:30;:45::i;:::-;148422:52;;85645:20:::0;:18;:20::i;:::-;148309:173;;;:::o;127709:4439::-;121430:13;;;;;;;121422:45;;;;-1:-1:-1;;;121422:45:0;;12787:2:1;121422:45:0;;;12769:21:1;12826:2;12806:18;;;12799:30;-1:-1:-1;;;12845:18:1;;;12838:49;12904:18;;121422:45:0;12585:343:1;121422:45:0;85575:19:::1;:17;:19::i;:::-;85605:17;:15;:17::i;:::-;127978:23:::2;166206:15:::0;127978:50:::2;;128320:7;128289:11;:27;;;-1:-1:-1::0;;;;;128289:38:0::2;;;:100;;;;;128382:7;128348:11;:30;;;-1:-1:-1::0;;;;;128348:41:0::2;;;128289:100;:147;;;;;128430:6;128410:16;-1:-1:-1::0;;;;;128410:26:0::2;;;128289:147;128267:209;;;::::0;-1:-1:-1;;;128267:209:0;;13135:2:1;128267:209:0::2;::::0;::::2;13117:21:1::0;13174:2;13154:18;;;13147:30;-1:-1:-1;;;13193:18:1;;;13186:42;13245:18;;128267:209:0::2;12933:336:1::0;128267:209:0::2;128553:19;128575:28;128591:11;128575:15;:28::i;:::-;128764:1;128733:19:::0;;;:6:::2;:19;::::0;;;;;128553:50;;-1:-1:-1;128733:33:0;128725:66:::2;;;::::0;-1:-1:-1;;;128725:66:0;;13476:2:1;128725:66:0::2;::::0;::::2;13458:21:1::0;13515:2;13495:18;;;13488:30;-1:-1:-1;;;13534:18:1;;;13527:50;13594:18;;128725:66:0::2;13274:344:1::0;128725:66:0::2;128804:20;128827:36;128844:11;:18;;;128827:16;:36::i;:::-;128804:59;;129274:26;129316:448;;;;;;;;129357:18;129316:448;;;;;;;;:::i;:::-;::::0;;129407:10:::2;129316:448;::::0;::::2;::::0;129445:14:::2;:16:::0;;129316:448;;;;;-1:-1:-1;;;129445:16:0;::::2;;;::::0;:14:::2;:16;::::0;::::2;:::i;:::-;;;;;;;;;;;;;;;;;;;;;129316:448;;;;;;129590:16;-1:-1:-1::0;;;;;129316:448:0::2;;;;;129643:16;129316:448;;;;;;129692:12;129316:448;;;;129733:15;;129316:448;;::::0;129274:490:::2;;129775:17;129795:37;129809:11;129822:9;129795:13;:37::i;:::-;129775:57;;129865:28;129883:9;129865:17;:28::i;:::-;129843:19;::::0;;;:6:::2;:19;::::0;;;;:50;;;;129933:44:::2;129850:11:::0;129967:9;129933:20:::2;:44::i;:::-;130157:1;130114:31:::0;;;:13:::2;:31;::::0;;;;;129906:71;;-1:-1:-1;;;;;;130114:31:0::2;:45:::0;129988:222:::2;;;::::0;-1:-1:-1;;;129988:222:0;;21634:2:1;129988:222:0::2;::::0;::::2;21616:21:1::0;21673:2;21653:18;;;21646:30;-1:-1:-1;;;21692:18:1;;;21685:53;21755:18;;129988:222:0::2;21432:347:1::0;129988:222:0::2;130559:11;:18;;;130540:15;;130523:14;;:32;;;;:::i;:::-;:54;;130515:92;;;::::0;-1:-1:-1;;;130515:92:0;;14425:2:1;130515:92:0::2;::::0;::::2;14407:21:1::0;14464:2;14444:18;;;14437:30;-1:-1:-1;;;14483:18:1;;;14476:55;14548:18;;130515:92:0::2;14223:349:1::0;130515:92:0::2;130733:17;130768:15;;130753:12;:30;;;;:::i;:::-;130733:50;;130989:17;131022:177;131117:11;:30;;;131087:11;:27;;;131058:9;:26;;;:56;;;;:::i;:::-;:89;;;;:::i;:::-;131166:11;:18;;;131022:17;:177::i;:::-;130989:210;;131327:23;131374:9;131353:11;:18;;;:30;;;;:::i;:::-;131327:56;;131405:9;131396:5;;:18;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;131444:18:0::2;::::0;::::2;::::0;131425:15:::2;:37:::0;;:15:::2;::::0;:37:::2;::::0;131444:18;;131425:37:::2;:::i;:::-;::::0;;;-1:-1:-1;;131549:31:0::2;::::0;;;:13:::2;:31;::::0;;;;:44;;-1:-1:-1;;;;;;131549:44:0::2;131583:10;131549:44:::0;;::::2;::::0;;;131606:80:::2;::::0;131651:4:::2;131658:27;131676:9:::0;131658:15;:27:::2;:::i;:::-;131606:7;::::0;::::2;::::0;::::2;-1:-1:-1::0;;;;;131606:7:0::2;::::0;;:80;:24:::2;:80::i;:::-;131764:10;::::0;::::2;;131760:237;;;131791:55;131805:11;:23;;;131830:15;131791:13;:55::i;:::-;131760:237;;;131956:23;::::0;::::2;::::0;131935:7:::2;::::0;:62:::2;::::0;:7:::2;::::0;;::::2;-1:-1:-1::0;;;;;131935:7:0::2;::::0;131981:15;131935:20:::2;:62::i;:::-;132030:11;132015:62;132043:11;132056:9;132067;132015:62;;;;;;;;:::i;:::-;;;;;;;;132118:10;-1:-1:-1::0;;;;;132093:47:0::2;132105:11;132093:47;132130:9;132093:47;;;;;;:::i;:::-;;;;;;;;127866:4282;;;;;;;;;85645:20:::1;:18;:20::i;151238:218::-:0;121313:11;;-1:-1:-1;;;;;121313:11:0;121291:10;:34;121283:70;;;;-1:-1:-1;;;121283:70:0;;;;;;;:::i;:::-;85575:19:::1;:17;:19::i;:::-;85605:17;:15;:17::i;:::-;151338:11:::2;:45:::0;;-1:-1:-1;;;;;;151338:45:0::2;-1:-1:-1::0;;;;;151338:45:0;::::2;::::0;;::::2;::::0;;;151399:49:::2;::::0;;151426:10:::2;21996:34:1::0;;22061:2;22046:18;;22039:43;;;;151399:49:0::2;::::0;21931:18:1;151399:49:0::2;21784:304:1::0;92204:104:0;92260:13;92293:7;92286:14;;;;;:::i;96422:413::-;89741:10;96515:4;96559:25;;;:11;:25;;;;;;;;-1:-1:-1;;;;;96559:34:0;;;;;;;;;;96612:35;;;;96604:85;;;;-1:-1:-1;;;96604:85:0;;22295:2:1;96604:85:0;;;22277:21:1;22334:2;22314:18;;;22307:30;22373:34;22353:18;;;22346:62;-1:-1:-1;;;22424:18:1;;;22417:35;22469:19;;96604:85:0;22093:401:1;96604:85:0;96725:67;89741:10;96748:7;96776:15;96757:16;:34;96725:8;:67::i;:::-;-1:-1:-1;96823:4:0;;96422:413;-1:-1:-1;;;96422:413:0:o;93616:175::-;93702:4;93719:42;89741:10;93743:9;93754:6;93719:9;:42::i;87553:727::-;87621:22;87664:9;:14;87656:54;;;;-1:-1:-1;;;87656:54:0;;22701:2:1;87656:54:0;;;22683:21:1;22740:2;22720:18;;;22713:30;22779:29;22759:18;;;22752:57;22826:18;;87656:54:0;22499:351:1;87656:54:0;87743:4;-1:-1:-1;;;;;87731:24:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;87721:34;;87771:9;87766:507;87786:15;;;87766:507;;;87824:12;;87869:4;87888;;87893:1;87888:7;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;87861:35;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;87823:73;;;;87918:7;87913:313;;88047:2;88031:6;:13;:18;88027:32;;;88051:8;;;88027:32;88132:4;88124:6;88120:17;88110:27;;88192:6;88181:28;;;;;;;;;;;;:::i;:::-;88174:36;;-1:-1:-1;;;88174:36:0;;;;;;;;:::i;87913:313::-;88255:6;88242:7;88250:1;88242:10;;;;;;;;:::i;:::-;;;;;;:19;;;;87808:465;;87803:3;;;;;:::i;:::-;;;;87766:507;;;;87553:727;;;;:::o;149709:465::-;85575:19;:17;:19::i;:::-;85605:17;:15;:17::i;:::-;149817:11:::1;::::0;:20:::1;::::0;;-1:-1:-1;;;149817:20:0;;;;149776:22:::1;::::0;-1:-1:-1;;;;;149817:11:0::1;::::0;:18:::1;::::0;:20:::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;:11;:20;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;149914:72;::::0;-1:-1:-1;;;149914:72:0;;-1:-1:-1;;;149914:72:0::1;::::0;::::1;4774:25:1::0;149776:62:0;;-1:-1:-1;;;;;;149914:31:0;::::1;::::0;::::1;::::0;4747:18:1;;149914:72:0::1;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;149849:16;:148:::0;;-1:-1:-1;;;;;;149849:148:0::1;-1:-1:-1::0;;;;;149849:148:0;;::::1;;::::0;;150033:55:::1;::::0;-1:-1:-1;;;150033:55:0;;-1:-1:-1;;;150033:55:0::1;::::0;::::1;4774:25:1::0;150033:31:0;;::::1;::::0;::::1;::::0;4747:18:1;;150033:55:0::1;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;150010:5;:79:::0;;-1:-1:-1;;;;;;150010:79:0::1;-1:-1:-1::0;;;;;150010:79:0;;::::1;::::0;;::::1;::::0;;;150148:7:::1;::::0;150118:39:::1;::::0;-1:-1:-1;;;150118:39:0;;150010:79:::1;150148:7:::0;;::::1;::::0;;::::1;150118:39;::::0;::::1;6569:51:1::0;150010:79:0;150118:21:::1;::::0;6542:18:1;;150118:39:0::1;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:48:::0;150100:15:::1;:66:::0;-1:-1:-1;85645:20:0;:18;:20::i;147499:119::-;147561:7;85575:19;:17;:19::i;:::-;85605:17;:15;:17::i;:::-;147588:22:::1;:20;:22::i;139495:1768::-:0;85575:19;:17;:19::i;:::-;85605:17;:15;:17::i;:::-;139610:19:::1;139632:28;139648:11;139632:15;:28::i;:::-;139610:50;;139671:46;139694:11;139707:9;139671:22;:46::i;:::-;139728:24;139755:44;139776:11;139789:9;139755:20;:44::i;:::-;139728:71;;139984:24;;;;;;;;;;;139955:9;:26;;;:53;;;;:::i;:::-;139936:72;;166206:15:::0;139936:72:::1;:135;;;;-1:-1:-1::0;140053:18:0::1;140029:20:::0;;:42:::1;::::0;::::1;;;;;;:::i;:::-;;139936:135;:201;;;;-1:-1:-1::0;140135:1:0::1;140092:31:::0;;;:13:::1;:31;::::0;;;;;-1:-1:-1;;;;;140092:31:0::1;:45:::0;139936:201:::1;139810:378;;;::::0;-1:-1:-1;;;139810:378:0;;21634:2:1;139810:378:0::1;::::0;::::1;21616:21:1::0;21673:2;21653:18;;;21646:30;-1:-1:-1;;;21692:18:1;;;21685:53;21755:18;;139810:378:0::1;21432:347:1::0;139810:378:0::1;140199:31;::::0;;;:13:::1;:31;::::0;;;;:44;;-1:-1:-1;;;;;;140199:44:0::1;140233:10;140199:44;::::0;;140577:30:::1;::::0;::::1;::::0;140547:27:::1;::::0;::::1;::::0;140518:26:::1;::::0;::::1;::::0;140482:177:::1;::::0;140577:30;140518:56:::1;::::0;::::1;:::i;:::-;:89;;;;:::i;140482:177::-;140449:210;;140787:23;140834:9;140813:11;:18;;;:30;;;;:::i;:::-;140858:10;::::0;140787:56;;-1:-1:-1;140858:10:0::1;;140854:336;;;140885:7;::::0;:68:::1;::::0;:7:::1;::::0;::::1;-1:-1:-1::0;;;;;140885:7:0::1;140910:10;140930:4;140937:15:::0;140885:24:::1;:68::i;:::-;140968:55;140982:11;:23;;;141007:15;140968:13;:55::i;:::-;140854:336;;;141149:23;::::0;::::1;::::0;141112:7:::1;::::0;:78:::1;::::0;:7:::1;::::0;;::::1;-1:-1:-1::0;;;;;141112:7:0::1;::::0;141137:10:::1;::::0;141174:15;141112:24:::1;:78::i;:::-;141233:10;-1:-1:-1::0;;;;;141208:47:0::1;141220:11;141208:47;141245:9;141208:47;;;;;;:::i;:::-;;;;;;;;139599:1664;;;;85645:20:::0;:18;:20::i;132781:1377::-;85575:19;:17;:19::i;:::-;85605:17;:15;:17::i;:::-;166206:15;132933:24:::1;::::0;132904:26:::1;::::0;::::1;::::0;:53:::1;::::0;-1:-1:-1;;;132933:24:0;::::1;;;::::0;132904:53:::1;:::i;:::-;:72;;;132896:98;;;::::0;-1:-1:-1;;;132896:98:0;;25724:2:1;132896:98:0::1;::::0;::::1;25706:21:1::0;25763:2;25743:18;;;25736:30;-1:-1:-1;;;25782:18:1;;;25775:43;25835:18;;132896:98:0::1;25522:337:1::0;132896:98:0::1;133037:18;133013:20:::0;;:42:::1;::::0;::::1;;;;;;:::i;:::-;;133005:69;;;::::0;-1:-1:-1;;;133005:69:0;;26066:2:1;133005:69:0::1;::::0;::::1;26048:21:1::0;26105:2;26085:18;;;26078:30;-1:-1:-1;;;26124:18:1;;;26117:44;26178:18;;133005:69:0::1;25864:338:1::0;133005:69:0::1;133122:19;133144:28;133160:11;133144:15;:28::i;:::-;133122:50;;133183:46;133206:11;133219:9;133183:22;:46::i;:::-;133297:17;133317:37;133331:11;133344:9;133317:13;:37::i;:::-;133297:57;;133479:12;133507:236;133548:9;:21;;;133588:10;133617:9;:22;;;133658:9;:18;;;133695:33;133718:9;133695:22;:33::i;:::-;133507:22;:236::i;:::-;133479:264;;133857:9;:22;;;133836:9;:18;;;:43;;;;:::i;:::-;133827:5;;:52;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;133909:18:0::1;::::0;::::1;::::0;133890:15:::1;:37:::0;;:15:::1;::::0;:37:::1;::::0;133909:18;;133890:37:::1;:::i;:::-;::::0;;;-1:-1:-1;;133945:19:0::1;::::0;;;:6:::1;:19;::::0;;;;133938:26;133975:175;::::1;;;134050:10;134020:28;134038:9:::0;134020:17:::1;:28::i;:::-;133993:68;::::0;134007:11;;133993:68:::1;::::0;;;::::1;133975:175;;;134139:10;134109:28;134127:9:::0;134109:17:::1;:28::i;:::-;134082:68;::::0;134096:11;;134082:68:::1;::::0;;;::::1;133975:175;132885:1273;;;85645:20:::0;:18;:20::i;148939:285::-;149053:26;149081:28;85575:19;:17;:19::i;:::-;85605:17;:15;:17::i;:::-;149135:33:::1;149166:1;149135:30;:33::i;:::-;149170:45;149201:13;149170:30;:45::i;:::-;149127:89;;;;85645:20:::0;:18;:20::i;:::-;148939:285;;;:::o;147222:64::-;85575:19;:17;:19::i;:::-;85605:17;:15;:17::i;:::-;147271:7:::1;:5;:7::i;:::-;85645:20:::0;:18;:20::i;86420:189::-;86554:11;;;;86546:55;;;;-1:-1:-1;;;86546:55:0;;26409:2:1;86546:55:0;;;26391:21:1;26448:2;26428:18;;;26421:30;26487:33;26467:18;;;26460:61;26538:18;;86546:55:0;26207:355:1;86617:139:0;86729:11;:19;;-1:-1:-1;;86729:19:0;;;86617:139::o;86764:210::-;86948:11;:18;;-1:-1:-1;;86948:18:0;86962:4;86948:18;;;86764:210::o;100106:380::-;-1:-1:-1;;;;;100242:19:0;;100234:68;;;;-1:-1:-1;;;100234:68:0;;26769:2:1;100234:68:0;;;26751:21:1;26808:2;26788:18;;;26781:30;26847:34;26827:18;;;26820:62;-1:-1:-1;;;26898:18:1;;;26891:34;26942:19;;100234:68:0;26567:400:1;100234:68:0;-1:-1:-1;;;;;100321:21:0;;100313:68;;;;-1:-1:-1;;;100313:68:0;;27174:2:1;100313:68:0;;;27156:21:1;27213:2;27193:18;;;27186:30;27252:34;27232:18;;;27225:62;-1:-1:-1;;;27303:18:1;;;27296:32;27345:19;;100313:68:0;26972:398:1;100313:68:0;-1:-1:-1;;;;;100394:18:0;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;:36;;;100446:32;;4774:25:1;;;100446:32:0;;4747:18:1;100446:32:0;;;;;;;100106:380;;;:::o;161024:166::-;161172:7;;161140:41;;161103:7;;161140:41;;161151:11;;161172:7;;;-1:-1:-1;;;;;161172:7:0;;161140:41;;;:::i;:::-;;;;;;;;;;;;;161130:52;;;;;;161123:59;;161024:166;;;:::o;160875:141::-;160984:15;;160939:7;;160966:42;;-1:-1:-1;;;160984:15:0;;-1:-1:-1;;;;;160984:15:0;161001:6;160966:17;:42::i;158007:144::-;158084:7;158132:9;158121:21;;;;;;;;:::i;157670:239::-;157775:7;157823:11;157836:9;:17;;;157855:9;:26;;;157891:7;;;;;;;;;-1:-1:-1;;;;;157891:7:0;157812:88;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;157802:99;;;;;;157795:106;;157670:239;;;;:::o;110973:248::-;111144:68;;-1:-1:-1;;;;;28539:15:1;;;111144:68:0;;;28521:34:1;28591:15;;28571:18;;;28564:43;28623:18;;;28616:34;;;111117:96:0;;111137:5;;-1:-1:-1;;;111167:27:0;28456:18:1;;111144:68:0;;;;-1:-1:-1;;111144:68:0;;;;;;;;;;;;;;-1:-1:-1;;;;;111144:68:0;-1:-1:-1;;;;;;111144:68:0;;;;;;;;;;111117:19;:96::i;:::-;110973:248;;;;:::o;154033:1331::-;154114:7;154134;:5;:7::i;:::-;154874:31;154927:1;154908:16;;:20;:52;;154959:1;154908:52;;;154939:16;;154908:52;154874:86;;154971:17;155025:23;155007:15;;154991:13;:31;;;;:::i;:::-;:57;;;;:::i;:::-;154971:77;;155059:19;155098:23;155081:14;;:40;;;;:::i;:::-;155059:62;-1:-1:-1;155213:16:0;155209:33;;-1:-1:-1;155238:4:0;;154033:1331;-1:-1:-1;;;;154033:1331:0:o;155209:33::-;155345:11;155325:16;:9;155337:4;155325:16;:::i;:::-;155324:32;;;;:::i;:::-;155317:39;154033:1331;-1:-1:-1;;;;;154033:1331:0:o;157377:176::-;157450:12;157482:63;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;157482:63:0;;;157535:9;157482:35;:63::i;97325:733::-;-1:-1:-1;;;;;97465:20:0;;97457:70;;;;-1:-1:-1;;;97457:70:0;;28863:2:1;97457:70:0;;;28845:21:1;28902:2;28882:18;;;28875:30;28941:34;28921:18;;;28914:62;-1:-1:-1;;;28992:18:1;;;28985:35;29037:19;;97457:70:0;28661:401:1;97457:70:0;-1:-1:-1;;;;;97546:23:0;;97538:71;;;;-1:-1:-1;;;97538:71:0;;29269:2:1;97538:71:0;;;29251:21:1;29308:2;29288:18;;;29281:30;29347:34;29327:18;;;29320:62;-1:-1:-1;;;29398:18:1;;;29391:33;29441:19;;97538:71:0;29067:399:1;97538:71:0;-1:-1:-1;;;;;97706:17:0;;97682:21;97706:17;;;:9;:17;;;;;;97742:23;;;;97734:74;;;;-1:-1:-1;;;97734:74:0;;29673:2:1;97734:74:0;;;29655:21:1;29712:2;29692:18;;;29685:30;29751:34;29731:18;;;29724:62;-1:-1:-1;;;29802:18:1;;;29795:36;29848:19;;97734:74:0;29471:402:1;97734:74:0;-1:-1:-1;;;;;97844:17:0;;;;;;;:9;:17;;;;;;97864:22;;;97844:42;;97908:20;;;;;;;;:30;;97880:6;;97844:17;97908:30;;97880:6;;97908:30;:::i;:::-;;;;;;;;97973:9;-1:-1:-1;;;;;97956:35:0;97965:6;-1:-1:-1;;;;;97956:35:0;;97984:6;97956:35;;;;4774:25:1;;4762:2;4747:18;;4628:177;97956:35:0;;;;;;;;98004:46;164991:286;158252:278;158402:28;158420:9;158402:17;:28::i;:::-;158379:19;;;;:6;:19;;;;;;:51;158357:165;;;;;-1:-1:-1;;;158357:165:0;;30080:2:1;158357:165:0;;;30062:21:1;30099:18;;;30092:30;;;;30158:34;30138:18;;;30131:62;30229:34;30209:18;;;30202:62;30281:19;;158357:165:0;29878:428:1;160726:141:0;160807:7;160855:4;160835:16;160845:6;-1:-1:-1;;;;;160835:16:0;;;:::i;:::-;160834:25;;;;:::i;158655:538::-;158756:7;159144:11;159157:9;:26;;;159133:51;;;;;;;;30483:25:1;;;-1:-1:-1;;;;;30544:31:1;30539:2;30524:18;;30517:59;30471:2;30456:18;;30311:271;164991:286:0;-1:-1:-1;;;;;165074:22:0;;103070:20;103118:8;165070:200;;165115:7;;:32;;:7;;;-1:-1:-1;;;;;165115:7:0;165136:2;165140:6;165115:20;:32::i;165070:200::-;165198:7;;165180:44;;-1:-1:-1;;;165180:44:0;;;;;4774:25:1;;;165198:7:0;;;;-1:-1:-1;;;;;165198:7:0;;165180:36;;4747:18:1;;165180:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;165239:19:0;;-1:-1:-1;;;;;165239:11:0;;;-1:-1:-1;165239:19:0;;;;;-1:-1:-1;165251:6:0;;165239:19;;;;165251:6;165239:11;:19;;;;;;;;;;;;;;;;;;;;;164991:286;;:::o;110754:211::-;110898:58;;-1:-1:-1;;;;;30779:32:1;;110898:58:0;;;30761:51:1;30828:18;;;30821:34;;;110871:86:0;;110891:5;;-1:-1:-1;;;110921:23:0;30734:18:1;;110898:58:0;30587:274:1;159868:438:0;160021:34;160058:21;:19;:21::i;:::-;160021:58;;160217:26;160195:19;;:48;;;;:::i;:::-;160173:19;:70;-1:-1:-1;160256:15:0;:42;;-1:-1:-1;;;;160256:42:0;-1:-1:-1;;;166206:15:0;160256:42;;;;;;159868:438::o;160373:345::-;160641:15;160618:19;;:38;;;;;;;:::i;:::-;;;;;;;;160694:15;160667:16;;:43;;;;;;;:::i;:::-;;;;-1:-1:-1;;;160373:345:0:o;156188:1084::-;156238:7;156262:13;93193:12;;;93105:108;156262:13;156258:35;;-1:-1:-1;156289:4:0;;156188:1084::o;156258:35::-;156446:26;:24;:26::i;:::-;156559:7;:5;:7::i;:::-;157113:16;157183:19;;157157:16;;157139:14;;157132:41;;;;:::i;:::-;:71;;;;:::i;:::-;157113:90;;157251:13;93193:12;;;93105:108;157251:13;157222:25;157230:9;157243:4;157222:25;:::i;:::-;157221:43;;;;:::i;:::-;157214:50;;;156188:1084;:::o;99077:591::-;-1:-1:-1;;;;;99161:21:0;;99153:67;;;;-1:-1:-1;;;99153:67:0;;31340:2:1;99153:67:0;;;31322:21:1;31379:2;31359:18;;;31352:30;31418:34;31398:18;;;31391:62;-1:-1:-1;;;31469:18:1;;;31462:31;31510:19;;99153:67:0;31138:397:1;99153:67:0;-1:-1:-1;;;;;99320:18:0;;99295:22;99320:18;;;:9;:18;;;;;;99357:24;;;;99349:71;;;;-1:-1:-1;;;99349:71:0;;31742:2:1;99349:71:0;;;31724:21:1;31781:2;31761:18;;;31754:30;31820:34;31800:18;;;31793:62;-1:-1:-1;;;31871:18:1;;;31864:32;31913:19;;99349:71:0;31540:398:1;99349:71:0;-1:-1:-1;;;;;99456:18:0;;;;;;:9;:18;;;;;99477:23;;;99456:44;;99522:12;:22;;99494:6;;99456:18;99522:22;;99494:6;;99522:22;:::i;:::-;;;;-1:-1:-1;;99562:37:0;;4774:25:1;;;99588:1:0;;-1:-1:-1;;;;;99562:37:0;;;;;4762:2:1;4747:18;99562:37:0;;;;;;;165239:19;164991:286;;:::o;98345:399::-;-1:-1:-1;;;;;98429:21:0;;98421:65;;;;-1:-1:-1;;;98421:65:0;;32145:2:1;98421:65:0;;;32127:21:1;32184:2;32164:18;;;32157:30;32223:33;32203:18;;;32196:61;32274:18;;98421:65:0;31943:355:1;98421:65:0;98577:6;98561:12;;:22;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;;;98594:18:0;;;;;;:9;:18;;;;;:28;;98616:6;;98594:18;:28;;98616:6;;98594:28;:::i;:::-;;;;-1:-1:-1;;98638:37:0;;4774:25:1;;;-1:-1:-1;;;;;98638:37:0;;;98655:1;;98638:37;;4762:2:1;4747:18;98638:37:0;;;;;;;134885:3068;;:::o;159201:546::-;159612:15;;159255:7;;;;159633:4;;-1:-1:-1;;;159612:15:0;;;;166206;159593:34;;;;:::i;:::-;159571:18;;159549:19;;:40;;159571:18;;;-1:-1:-1;;;;;159571:18:0;;159549:40;:::i;:::-;:79;;;;:::i;:::-;159548:90;;;;:::i;:::-;159506:132;;159677:19;;159656:18;:40;:83;;159720:19;;159656:83;;161436:3429;161647:4;;161684:23;161695:12;161684:8;:23;:::i;:::-;161746:16;;161718:7;;161664:43;;-1:-1:-1;161718:57:0;;161746:16;161718:7;;-1:-1:-1;;;;;161718:7:0;;;;161746:16;161664:43;161718:19;:57::i;:::-;161803:16;;161864:10;;-1:-1:-1;;;;;161803:16:0;;;;:42;;166206:15;161936:19;161981:7;;;;;;;;;-1:-1:-1;;;;;161981:7:0;162192:1;162295:12;162404:24;;;;;;;;;;;162447:8;162572:4;161803:789;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;161803:789:0;;;;;;;;-1:-1:-1;;161803:789:0;;;;;;;;;;;;:::i;:::-;;;161786:1824;;163370:7;;:41;;:7;;;-1:-1:-1;;;;;163370:7:0;163391:8;163401:9;163370:20;:41::i;:::-;163454:16;;163426:7;;:49;;-1:-1:-1;;;;;163454:16:0;163426:7;;;;;;163454:16;;163426:19;:49::i;:::-;163593:5;163586:12;;;;;161786:1824;162661:9;162649;:21;162645:359;;;162785:14;162802:21;162814:9;162802;:21;:::i;:::-;162842:7;;162785:38;;-1:-1:-1;162842:38:0;;:7;;;-1:-1:-1;;;;;162842:7:0;162863:8;162785:38;162842:20;:38::i;:::-;162927:16;;162899:7;;:49;;-1:-1:-1;;;;;162927:16:0;162899:7;;;;;;162927:16;;162899:19;:49::i;:::-;162979:9;162967:21;;162672:332;162645:359;-1:-1:-1;163692:554:0;;;;;;;;-1:-1:-1;;;;;163692:554:0;;;;;-1:-1:-1;163692:554:0;;;;;;163844:7;;;;;;;;163692:554;;;;;;;;;;;;;163926:4;163692:554;;;;;;;;;;164020:24;;163692:554;;;;-1:-1:-1;;;164020:24:0;;;;166206:15;164001:43;;;;:::i;:::-;163692:554;;164071:1;163692:554;;;;;;164101:24;164113:12;164101:9;:24;:::i;:::-;163692:554;;;;;;;;164205:24;;-1:-1:-1;;;164205:24:0;;;;;;163692:554;;;;;;;;164348:7;;163622:624;;-1:-1:-1;164348:62:0;;164205:24;164348:7;;-1:-1:-1;;;;;164348:7:0;;164373:10;;164393:4;;164400:9;;164348:24;:62;:::i;:::-;164449:16;;164421:7;;:57;;-1:-1:-1;;;;;164449:16:0;164421:7;;;;;;164449:16;164468:9;164421:19;:57::i;:::-;164540:16;;164587:10;;164540:214;;-1:-1:-1;;;164540:214:0;;-1:-1:-1;;;;;164540:16:0;;;;:32;;:214;;166206:15;;164651:19;;164685:7;;164707:8;;164738:4;;164540:214;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;164853:4:0;;161436:3429;-1:-1:-1;;;;;;;;161436:3429:0:o;155372:808::-;155677:5;;155642:7;;:32;;-1:-1:-1;;;155642:32:0;;155668:4;155642:32;;;6569:51:1;155617:22:0;;155677:5;155642:7;;;-1:-1:-1;;;;;155642:7:0;;:17;;6542:18:1;;155642:32:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:40;;;;:::i;:::-;155617:65;;155714:14;;155697;:31;155693:480;;;156100:14;;156083:31;;:14;:31;:::i;:::-;156056:16;;:59;;;;;;;:::i;:::-;;;;-1:-1:-1;;156130:14:0;:31;155372:808::o;113327:716::-;113751:23;113777:69;113805:4;113777:69;;;;;;;;;;;;;;;;;113785:5;-1:-1:-1;;;;;113777:27:0;;;:69;;;;;:::i;:::-;113861:17;;113751:95;;-1:-1:-1;113861:21:0;113857:179;;113958:10;113947:30;;;;;;;;;;;;:::i;:::-;113939:85;;;;-1:-1:-1;;;113939:85:0;;35484:2:1;113939:85:0;;;35466:21:1;35523:2;35503:18;;;35496:30;35562:34;35542:18;;;35535:62;-1:-1:-1;;;35613:18:1;;;35606:40;35663:19;;113939:85:0;35282:406:1;78508:337:0;78664:12;78689:19;78711:42;78727:20;78749:3;78711:15;:42::i;:::-;78689:64;;78788:20;78810:6;78818:18;78830:5;78818:11;:18::i;:::-;78771:66;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;78764:73;;;78508:337;;;;;:::o;111490:616::-;111854:10;;;111853:62;;-1:-1:-1;111870:39:0;;-1:-1:-1;;;111870:39:0;;111894:4;111870:39;;;21996:34:1;-1:-1:-1;;;;;22066:15:1;;;22046:18;;;22039:43;111870:15:0;;;;;21931:18:1;;111870:39:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:44;111853:62;111831:166;;;;-1:-1:-1;;;111831:166:0;;36558:2:1;111831:166:0;;;36540:21:1;36597:2;36577:18;;;36570:30;36636:34;36616:18;;;36609:62;-1:-1:-1;;;36687:18:1;;;36680:52;36749:19;;111831:166:0;36356:418:1;111831:166:0;112035:62;;-1:-1:-1;;;;;30779:32:1;;112035:62:0;;;30761:51:1;30828:18;;;30821:34;;;112008:90:0;;112028:5;;-1:-1:-1;;;112058:22:0;30734:18:1;;112035:62:0;30587:274:1;105553:229:0;105690:12;105722:52;105744:6;105752:4;105758:1;105761:12;105722:21;:52::i;:::-;105715:59;105553:229;-1:-1:-1;;;;105553:229:0:o;81365:301::-;81495:27;;81466:12;;81495:31;81491:168;;81572:3;81550:31;;;;;;;;:::i;:::-;;;;;;;;;;;;;81543:38;;;;81491:168;81638:3;81621:26;;;;;;;;:::i;76931:184::-;76992:12;77041:35;77072:3;77061:7;:14;;77041:19;:35::i;:::-;77078:28;77098:7;77078:19;:28::i;:::-;77024:83;;;;;;37953:19:1;;;;37988:12;;37981:28;38025:12;;77024:83:0;;;;;;;;;;;;77017:90;;76931:184;;;:::o;106673:510::-;106843:12;106901:5;106876:21;:30;;106868:81;;;;-1:-1:-1;;;106868:81:0;;38250:2:1;106868:81:0;;;38232:21:1;38289:2;38269:18;;;38262:30;38328:34;38308:18;;;38301:62;-1:-1:-1;;;38379:18:1;;;38372:36;38425:19;;106868:81:0;38048:402:1;106868:81:0;103070:20;;106960:60;;;;-1:-1:-1;;;106960:60:0;;38657:2:1;106960:60:0;;;38639:21:1;38696:2;38676:18;;;38669:30;38735:31;38715:18;;;38708:59;38784:18;;106960:60:0;38455:353:1;106960:60:0;107034:12;107048:23;107075:6;-1:-1:-1;;;;;107075:11:0;107094:5;107101:4;107075:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;107033:73;;;;107124:51;107141:7;107150:10;107162:12;107124:16;:51::i;:::-;107117:58;106673:510;-1:-1:-1;;;;;;;106673:510:0:o;75212:1327::-;75280:7;75325:9;75345:7;75337:16;;75325:28;;75408:1;75412:66;75408:70;75404:74;;75503:1;75507:5;75503:9;75498:1;:15;75517:66;75497:86;75493:90;;75608:1;75612:5;75608:9;75603:1;:15;75622:66;75602:86;75598:90;;75713:1;75717:5;75713:9;75708:1;:15;75727:66;75707:86;75703:90;;75818:1;75822:4;75818:8;75813:1;:14;75831:66;75812:85;75808:89;;75922:1;75926:4;75922:8;75917:1;:14;75935:66;75916:85;75912:89;;76045:9;76132:1;76058;76062:66;76058:70;76057:76;;;;;:::i;:::-;;76235:1;76165:66;76161:70;;76160:76;76338:1;76268:66;76264:70;;76263:76;76368:5;76363:11;76378:4;76362:20;76358:24;;;76385:66;76358:93;;;-1:-1:-1;;;75212:1327:0:o;109359:712::-;109509:12;109538:7;109534:530;;;-1:-1:-1;109569:10:0;109562:17;;109534:530;109683:17;;:21;109679:374;;109881:10;109875:17;109942:15;109929:10;109925:2;109921:19;109914:44;109679:374;110024:12;110017:20;;-1:-1:-1;;;110017:20:0;;;;;;;;:::i;14:258:1:-;86:1;96:113;110:6;107:1;104:13;96:113;;;186:11;;;180:18;167:11;;;160:39;132:2;125:10;96:113;;;227:6;224:1;221:13;218:48;;;-1:-1:-1;;262:1:1;244:16;;237:27;14:258::o;277:::-;319:3;357:5;351:12;384:6;379:3;372:19;400:63;456:6;449:4;444:3;440:14;433:4;426:5;422:16;400:63;:::i;:::-;517:2;496:15;-1:-1:-1;;492:29:1;483:39;;;;524:4;479:50;;277:258;-1:-1:-1;;277:258:1:o;540:220::-;689:2;678:9;671:21;652:4;709:45;750:2;739:9;735:18;727:6;709:45;:::i;765:118::-;851:5;844:13;837:21;830:5;827:32;817:60;;873:1;870;863:12;888:241;944:6;997:2;985:9;976:7;972:23;968:32;965:52;;;1013:1;1010;1003:12;965:52;1052:9;1039:23;1071:28;1093:5;1071:28;:::i;1134:131::-;-1:-1:-1;;;;;1209:31:1;;1199:42;;1189:70;;1255:1;1252;1245:12;1270:134;1338:20;;1367:31;1338:20;1367:31;:::i;1409:315::-;1477:6;1485;1538:2;1526:9;1517:7;1513:23;1509:32;1506:52;;;1554:1;1551;1544:12;1506:52;1593:9;1580:23;1612:31;1637:5;1612:31;:::i;:::-;1662:5;1714:2;1699:18;;;;1686:32;;-1:-1:-1;;;1409:315:1:o;2329:127::-;2390:10;2385:3;2381:20;2378:1;2371:31;2421:4;2418:1;2411:15;2445:4;2442:1;2435:15;2461:248;2528:2;2522:9;2570:4;2558:17;;-1:-1:-1;;;;;2590:34:1;;2626:22;;;2587:62;2584:88;;;2652:18;;:::i;:::-;2688:2;2681:22;2461:248;:::o;2714:129::-;-1:-1:-1;;;;;2792:5:1;2788:30;2781:5;2778:41;2768:69;;2833:1;2830;2823:12;2848:132;2915:20;;2944:30;2915:20;2944:30;:::i;2985:121::-;3070:10;3063:5;3059:22;3052:5;3049:33;3039:61;;3096:1;3093;3086:12;3111:132;3178:20;;3207:30;3178:20;3207:30;:::i;3248:1000::-;3306:5;3336:6;3379:2;3367:9;3362:3;3358:19;3354:28;3351:48;;;3395:1;3392;3385:12;3351:48;3428:2;3422:9;3458:15;;;;-1:-1:-1;;;;;3488:34:1;;3524:22;;;3485:62;3482:88;;;3550:18;;:::i;:::-;3590:10;3586:2;3579:22;3619:6;3610:15;;3662:9;3649:23;3641:6;3634:39;3725:2;3714:9;3710:18;3697:32;3682:47;;3738:32;3762:7;3738:32;:::i;:::-;3803:7;3798:2;3790:6;3786:15;3779:32;3844:38;3878:2;3867:9;3863:18;3844:38;:::i;:::-;3839:2;3831:6;3827:15;3820:63;3916:38;3950:2;3939:9;3935:18;3916:38;:::i;:::-;3911:2;3903:6;3899:15;3892:63;4017:3;4006:9;4002:19;3989:33;3983:3;3975:6;3971:16;3964:59;4057:38;4090:3;4079:9;4075:19;4057:38;:::i;:::-;4051:3;4043:6;4039:16;4032:64;4130:38;4163:3;4152:9;4148:19;4130:38;:::i;:::-;4124:3;4116:6;4112:16;4105:64;4203:38;4236:3;4225:9;4221:19;4203:38;:::i;:::-;4197:3;4189:6;4185:16;4178:64;;;3248:1000;;;;:::o;4253:370::-;4349:6;4357;4410:3;4398:9;4389:7;4385:23;4381:33;4378:53;;;4427:1;4424;4417:12;4378:53;4450:49;4491:7;4480:9;4450:49;:::i;:::-;4440:59;;4549:3;4538:9;4534:19;4521:33;4563:30;4587:5;4563:30;:::i;:::-;4612:5;4602:15;;;4253:370;;;;;:::o;5106:980::-;5230:6;5238;5282:9;5273:7;5269:23;5312:3;5308:2;5304:12;5301:32;;;5329:1;5326;5319:12;5301:32;5352:49;5393:7;5382:9;5352:49;:::i;:::-;5342:59;-1:-1:-1;5436:4:1;-1:-1:-1;;5417:17:1;;5413:28;5410:48;;;5454:1;5451;5444:12;5410:48;;5480:17;;:::i;:::-;5549:3;5538:9;5534:19;5521:33;5585:1;5576:7;5573:14;5563:42;;5601:1;5598;5591:12;5563:42;5614:22;;5668:39;5702:3;5687:19;;5668:39;:::i;:::-;5663:2;5656:5;5652:14;5645:63;5740:38;5773:3;5762:9;5758:19;5740:38;:::i;:::-;5735:2;5728:5;5724:14;5717:62;5811:38;5844:3;5833:9;5829:19;5811:38;:::i;:::-;5806:2;5799:5;5795:14;5788:62;5883:38;5916:3;5905:9;5901:19;5883:38;:::i;:::-;5877:3;5866:15;;5859:63;5983:3;5968:19;;5955:33;5949:3;5938:15;;5931:58;6050:3;6035:19;;;6022:33;6016:3;6005:15;;5998:58;-1:-1:-1;5106:980:1;5870:5;;-1:-1:-1;5106:980:1:o;6878:180::-;6937:6;6990:2;6978:9;6969:7;6965:23;6961:32;6958:52;;;7006:1;7003;6996:12;6958:52;-1:-1:-1;7029:23:1;;6878:180;-1:-1:-1;6878:180:1:o;7063:456::-;7140:6;7148;7156;7209:2;7197:9;7188:7;7184:23;7180:32;7177:52;;;7225:1;7222;7215:12;7177:52;7264:9;7251:23;7283:31;7308:5;7283:31;:::i;:::-;7333:5;-1:-1:-1;7390:2:1;7375:18;;7362:32;7403:33;7362:32;7403:33;:::i;:::-;7063:456;;7455:7;;-1:-1:-1;;;7509:2:1;7494:18;;;;7481:32;;7063:456::o;7524:245::-;7582:6;7635:2;7623:9;7614:7;7610:23;7606:32;7603:52;;;7651:1;7648;7641:12;7603:52;7690:9;7677:23;7709:30;7733:5;7709:30;:::i;7963:309::-;8028:6;8036;8089:2;8077:9;8068:7;8064:23;8060:32;8057:52;;;8105:1;8102;8095:12;8057:52;8141:9;8128:23;8118:33;;8201:2;8190:9;8186:18;8173:32;8214:28;8236:5;8214:28;:::i;8457:247::-;8516:6;8569:2;8557:9;8548:7;8544:23;8540:32;8537:52;;;8585:1;8582;8575:12;8537:52;8624:9;8611:23;8643:31;8668:5;8643:31;:::i;9358:626::-;9455:6;9463;9516:2;9504:9;9495:7;9491:23;9487:32;9484:52;;;9532:1;9529;9522:12;9484:52;9572:9;9559:23;-1:-1:-1;;;;;9642:2:1;9634:6;9631:14;9628:34;;;9658:1;9655;9648:12;9628:34;9696:6;9685:9;9681:22;9671:32;;9741:7;9734:4;9730:2;9726:13;9722:27;9712:55;;9763:1;9760;9753:12;9712:55;9803:2;9790:16;9829:2;9821:6;9818:14;9815:34;;;9845:1;9842;9835:12;9815:34;9898:7;9893:2;9883:6;9880:1;9876:14;9872:2;9868:23;9864:32;9861:45;9858:65;;;9919:1;9916;9909:12;9858:65;9950:2;9942:11;;;;;9972:6;;-1:-1:-1;9358:626:1;;-1:-1:-1;;;;9358:626:1:o;9989:801::-;10149:4;10178:2;10218;10207:9;10203:18;10248:2;10237:9;10230:21;10271:6;10306;10300:13;10337:6;10329;10322:22;10375:2;10364:9;10360:18;10353:25;;10437:2;10427:6;10424:1;10420:14;10409:9;10405:30;10401:39;10387:53;;10475:2;10467:6;10463:15;10496:1;10506:255;10520:6;10517:1;10514:13;10506:255;;;10613:2;10609:7;10597:9;10589:6;10585:22;10581:36;10576:3;10569:49;10641:40;10674:6;10665;10659:13;10641:40;:::i;:::-;10631:50;-1:-1:-1;10739:12:1;;;;10704:15;;;;10542:1;10535:9;10506:255;;;-1:-1:-1;10778:6:1;;9989:801;-1:-1:-1;;;;;;;9989:801:1:o;11202:388::-;11270:6;11278;11331:2;11319:9;11310:7;11306:23;11302:32;11299:52;;;11347:1;11344;11337:12;11299:52;11386:9;11373:23;11405:31;11430:5;11405:31;:::i;:::-;11455:5;-1:-1:-1;11512:2:1;11497:18;;11484:32;11525:33;11484:32;11525:33;:::i;11848:380::-;11927:1;11923:12;;;;11970;;;11991:61;;12045:4;12037:6;12033:17;12023:27;;11991:61;12098:2;12090:6;12087:14;12067:18;12064:38;12061:161;;;12144:10;12139:3;12135:20;12132:1;12125:31;12179:4;12176:1;12169:15;12207:4;12204:1;12197:15;12061:161;;11848:380;;;:::o;12233:347::-;12435:2;12417:21;;;12474:2;12454:18;;;12447:30;12513:25;12508:2;12493:18;;12486:53;12571:2;12556:18;;12233:347::o;13623:127::-;13684:10;13679:3;13675:20;13672:1;13665:31;13715:4;13712:1;13705:15;13739:4;13736:1;13729:15;13755:127;13816:10;13811:3;13807:20;13804:1;13797:31;13847:4;13844:1;13837:15;13871:4;13868:1;13861:15;13887:201;13925:3;13953:10;13998:2;13991:5;13987:14;14025:2;14016:7;14013:15;14010:41;;;14031:18;;:::i;:::-;14080:1;14067:15;;13887:201;-1:-1:-1;;;13887:201:1:o;14093:125::-;14133:4;14161:1;14158;14155:8;14152:34;;;14166:18;;:::i;:::-;-1:-1:-1;14203:9:1;;14093:125::o;14577:128::-;14617:3;14648:1;14644:6;14641:1;14638:13;14635:39;;;14654:18;;:::i;:::-;-1:-1:-1;14690:9:1;;14577:128::o;14710:711::-;14793:5;14787:12;14782:3;14775:25;14846:4;14839:5;14835:16;14829:23;-1:-1:-1;;;;;14939:2:1;14925:12;14921:21;14914:4;14909:3;14905:14;14898:45;14991:4;14984:5;14980:16;14974:23;14952:45;;15033:1;15029;15024:3;15020:11;15016:19;15087:2;15071:14;15067:23;15060:4;15055:3;15051:14;15044:47;15152:2;15144:4;15137:5;15133:16;15127:23;15123:32;15116:4;15111:3;15107:14;15100:56;;15205:4;15198:5;15194:16;15188:23;15181:4;15176:3;15172:14;15165:47;15273:2;15265:4;15258:5;15254:16;15248:23;15244:32;15237:4;15232:3;15228:14;15221:56;15338:2;15330:4;15323:5;15319:16;15313:23;15309:32;15302:4;15297:3;15293:14;15286:56;;;15403:10;15395:4;15388:5;15384:16;15378:23;15374:40;15367:4;15362:3;15358:14;15351:64;14710:711;;:::o;15426:790::-;15505:5;15499:12;15537:1;15533:2;15530:9;15520:140;;15582:10;15577:3;15573:20;15570:1;15563:31;15617:4;15614:1;15607:15;15645:4;15642:1;15635:15;15520:140;15669:15;;15737:4;15726:16;;;15720:23;-1:-1:-1;;;;;15716:49:1;15700:14;;;15693:73;15812:4;15801:16;;;15795:23;;15827:47;;15859:14;;15795:23;4886:10;4875:22;4863:35;;4810:94;15827:47;;15922:4;15915:5;15911:16;15905:23;15937:49;15980:4;15975:3;15971:14;15955;-1:-1:-1;;;;;2082:30:1;2070:43;;2017:102;15937:49;;16034:4;16027:5;16023:16;16017:23;16049:49;16092:4;16087:3;16083:14;16067;4886:10;4875:22;4863:35;;4810:94;16049:49;-1:-1:-1;16147:4:1;16136:16;;;16130:23;16114:14;;;16107:47;16203:4;16192:16;;;16186:23;16170:14;;16163:47;15426:790::o;16221:478::-;16523:3;16508:19;;16536:48;16512:9;16566:6;16536:48;:::i;:::-;16593:56;16644:3;16633:9;16629:19;16621:6;16593:56;:::i;:::-;16686:6;16680:3;16669:9;16665:19;16658:35;16221:478;;;;;;:::o;17113:249::-;17182:6;17235:2;17223:9;17214:7;17210:23;17206:32;17203:52;;;17251:1;17248;17241:12;17203:52;17283:9;17277:16;17302:30;17326:5;17302:30;:::i;17367:249::-;17436:6;17489:2;17477:9;17468:7;17464:23;17460:32;17457:52;;;17505:1;17502;17495:12;17457:52;17537:9;17531:16;17556:30;17580:5;17556:30;:::i;17621:184::-;17691:6;17744:2;17732:9;17723:7;17719:23;17715:32;17712:52;;;17760:1;17757;17750:12;17712:52;-1:-1:-1;17783:16:1;;17621:184;-1:-1:-1;17621:184:1:o;18154:228::-;18193:3;18221:10;18258:2;18255:1;18251:10;18288:2;18285:1;18281:10;18319:3;18315:2;18311:12;18306:3;18303:21;18300:47;;;18327:18;;:::i;:::-;18363:13;;18154:228;-1:-1:-1;;;;18154:228:1:o;19079:236::-;19118:3;-1:-1:-1;;;;;19191:2:1;19188:1;19184:10;19221:2;19218:1;19214:10;19252:3;19248:2;19244:12;19239:3;19236:21;19233:47;;;19260:18;;:::i;19320:265::-;19359:3;19387:9;;;19412:10;;-1:-1:-1;;;;;19431:27:1;;;19424:35;;19408:52;19405:78;;;19463:18;;:::i;:::-;-1:-1:-1;;;19510:19:1;;;19503:27;;19495:36;;19492:62;;;19534:18;;:::i;:::-;-1:-1:-1;;19570:9:1;;19320:265::o;19590:253::-;19778:3;19763:19;;19791:46;19767:9;19819:6;19791:46;:::i;20190:168::-;20230:7;20296:1;20292;20288:6;20284:14;20281:1;20278:21;20273:1;20266:9;20259:17;20255:45;20252:71;;;20303:18;;:::i;:::-;-1:-1:-1;20343:9:1;;20190:168::o;20363:127::-;20424:10;20419:3;20415:20;20412:1;20405:31;20455:4;20452:1;20445:15;20479:4;20476:1;20469:15;20495:217;20535:1;20561;20551:132;;20605:10;20600:3;20596:20;20593:1;20586:31;20640:4;20637:1;20630:15;20668:4;20665:1;20658:15;20551:132;-1:-1:-1;20697:9:1;;20495:217::o;22855:127::-;22916:10;22911:3;22907:20;22904:1;22897:31;22947:4;22944:1;22937:15;22971:4;22968:1;22961:15;22987:521;23064:4;23070:6;23130:11;23117:25;23224:2;23220:7;23209:8;23193:14;23189:29;23185:43;23165:18;23161:68;23151:96;;23243:1;23240;23233:12;23151:96;23270:33;;23322:20;;;-1:-1:-1;;;;;;23354:30:1;;23351:50;;;23397:1;23394;23387:12;23351:50;23430:4;23418:17;;-1:-1:-1;23461:14:1;23457:27;;;23447:38;;23444:58;;;23498:1;23495;23488:12;23444:58;22987:521;;;;;:::o;23513:271::-;23696:6;23688;23683:3;23670:33;23652:3;23722:16;;23747:13;;;23722:16;23513:271;-1:-1:-1;23513:271:1:o;23789:884::-;23869:6;23922:2;23910:9;23901:7;23897:23;23893:32;23890:52;;;23938:1;23935;23928:12;23890:52;23971:9;23965:16;-1:-1:-1;;;;;24041:2:1;24033:6;24030:14;24027:34;;;24057:1;24054;24047:12;24027:34;24095:6;24084:9;24080:22;24070:32;;24140:7;24133:4;24129:2;24125:13;24121:27;24111:55;;24162:1;24159;24152:12;24111:55;24191:2;24185:9;24213:2;24209;24206:10;24203:36;;;24219:18;;:::i;:::-;24294:2;24288:9;24262:2;24348:13;;-1:-1:-1;;24344:22:1;;;24368:2;24340:31;24336:40;24324:53;;;24392:18;;;24412:22;;;24389:46;24386:72;;;24438:18;;:::i;:::-;24478:10;24474:2;24467:22;24513:2;24505:6;24498:18;24553:7;24548:2;24543;24539;24535:11;24531:20;24528:33;24525:53;;;24574:1;24571;24564:12;24525:53;24587:55;24639:2;24634;24626:6;24622:15;24617:2;24613;24609:11;24587:55;:::i;24678:135::-;24717:3;-1:-1:-1;;24738:17:1;;24735:43;;;24758:18;;:::i;:::-;-1:-1:-1;24805:1:1;24794:13;;24678:135::o;24818:251::-;24888:6;24941:2;24929:9;24920:7;24916:23;24912:32;24909:52;;;24957:1;24954;24947:12;24909:52;24989:9;24983:16;25008:31;25033:5;25008:31;:::i;25074:443::-;25170:6;25223:2;25211:9;25202:7;25198:23;25194:32;25191:52;;;25239:1;25236;25229:12;25191:52;25272:2;25266:9;25314:2;25306:6;25302:15;25383:6;25371:10;25368:22;-1:-1:-1;;;;;25335:10:1;25332:34;25329:62;25326:88;;;25394:18;;:::i;:::-;25430:2;25423:22;25469:16;;25454:32;;-1:-1:-1;25461:6:1;25074:443;-1:-1:-1;25074:443:1:o;27375:357::-;27595:3;27580:19;;27608:48;27584:9;27638:6;27608:48;:::i;:::-;-1:-1:-1;;;;;27693:32:1;;;;27687:3;27672:19;;;;27665:61;27375:357;;-1:-1:-1;27375:357:1:o;27737:539::-;28009:3;27994:19;;28022:48;27998:9;28052:6;28022:48;:::i;:::-;28119:10;28107:23;;;;28101:3;28086:19;;28079:52;-1:-1:-1;;;;;28168:31:1;;;;28162:3;28147:19;;28140:60;-1:-1:-1;;;;;28237:32:1;28231:3;28216:19;;;28209:61;27737:539;;-1:-1:-1;27737:539:1:o;30866:267::-;30905:4;30934:9;;;30959:10;;-1:-1:-1;;;30978:19:1;;30971:27;;30955:44;30952:70;;;31002:18;;:::i;:::-;-1:-1:-1;;;;;31049:27:1;;31042:35;;31034:44;;31031:70;;;31081:18;;:::i;:::-;-1:-1:-1;;31118:9:1;;30866:267::o;32303:933::-;32654:4;32683:3;32713:6;32702:9;32695:25;32739:10;32797:2;32789:6;32785:15;32780:2;32769:9;32765:18;32758:43;32837:2;32832;32821:9;32817:18;32810:30;32857:45;32898:2;32887:9;32883:18;32875:6;32857:45;:::i;:::-;-1:-1:-1;;;;;32976:15:1;;;32971:2;32956:18;;32949:43;33023:3;33008:19;;33001:35;;;;32929:3;33052:19;;33045:35;;;;-1:-1:-1;;33117:15:1;;;;33111:3;33096:19;;33089:44;33170:15;;;33164:3;33149:19;;33142:44;33217:3;33202:19;;;33195:35;;;;32849:53;32303:933;-1:-1:-1;;;32303:933:1:o;33430:1597::-;33726:4;33755:3;33785:6;33774:9;33767:25;33840:10;33832:6;33828:23;33823:2;33812:9;33808:18;33801:51;33888:2;33883;33872:9;33868:18;33861:30;33908:45;33949:2;33938:9;33934:18;33926:6;33908:45;:::i;:::-;33900:53;;;33962;34011:2;34000:9;33996:18;33987:6;33981:13;-1:-1:-1;;;;;6380:31:1;6368:44;;6314:104;33962:53;34062:2;34050:15;;34044:22;-1:-1:-1;;;;;6380:31:1;;34123:3;34108:19;;6368:44;-1:-1:-1;34177:2:1;34165:15;;34159:22;-1:-1:-1;;;;;6380:31:1;;34240:3;34225:19;;6368:44;-1:-1:-1;34294:2:1;34282:15;;34276:22;1799:13;;1792:21;34354:3;34339:19;;1780:34;34307:52;34414:3;34406:6;34402:16;34396:23;34390:3;34379:9;34375:19;34368:52;34457:3;34449:6;34445:16;34439:23;34481:3;34520:2;34515;34504:9;34500:18;34493:30;34560:3;34552:6;34548:16;34542:23;34532:33;;34584:3;34623:2;34618;34607:9;34603:18;34596:30;34663:3;34655:6;34651:16;34645:23;34635:33;;34687:3;34726:2;34721;34710:9;34706:18;34699:30;34784:2;34776:6;34772:15;34766:22;34760:3;34749:9;34745:19;34738:51;34844:2;34836:6;34832:15;34826:22;34820:3;34809:9;34805:19;34798:51;34904:2;34896:6;34892:15;34886:22;34880:3;34869:9;34865:19;34858:51;;;;;34918:47;34960:3;34949:9;34945:19;34937:6;-1:-1:-1;;;;;6380:31:1;6368:44;;6314:104;34918:47;-1:-1:-1;;;;;6380:31:1;;35016:3;35001:19;;6368:44;34974:47;6314:104;35032:245;35099:6;35152:2;35140:9;35131:7;35127:23;35123:32;35120:52;;;35168:1;35165;35158:12;35120:52;35200:9;35194:16;35219:28;35241:5;35219:28;:::i;35693:658::-;35914:3;35952:6;35946:13;35968:53;36014:6;36009:3;36002:4;35994:6;35990:17;35968:53;:::i;:::-;36084:13;;36043:16;;;;36106:57;36084:13;36043:16;36140:4;36128:17;;36106:57;:::i;:::-;36230:13;;36185:20;;;36252:57;36230:13;36185:20;36286:4;36274:17;;36252:57;:::i;:::-;36325:20;;35693:658;-1:-1:-1;;;;;35693:658:1:o;36779:570::-;-1:-1:-1;;;37135:3:1;37128:16;37110:3;37173:6;37167:13;37189:61;37243:6;37239:1;37234:3;37230:11;37223:4;37215:6;37211:17;37189:61;:::i;:::-;-1:-1:-1;;;37309:1:1;37269:16;;;;37301:10;;;37294:23;-1:-1:-1;37341:1:1;37333:10;;36779:570;-1:-1:-1;36779:570:1:o;37354:437::-;37584:3;37622:6;37616:13;37638:53;37684:6;37679:3;37672:4;37664:6;37660:17;37638:53;:::i;:::-;-1:-1:-1;;;37713:16:1;;37738:18;;;-1:-1:-1;37783:1:1;37772:13;;37354:437;-1:-1:-1;37354:437:1:o;38813:274::-;38942:3;38980:6;38974:13;38996:53;39042:6;39037:3;39030:4;39022:6;39018:17;38996:53;:::i;:::-;39065:16;;;;;38813:274;-1:-1:-1;;38813:274:1:o
Swarm Source
ipfs://e29df9833ee712dea5e74a80725a39c21912ff9a19c010ca4afb5d0d9057d980
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | 100.00% | $54,394 | 9.0143 | $490,325.65 |
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.