Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Multi Chain
Multichain Addresses
0 address found via
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
Value | ||||
---|---|---|---|---|---|---|---|---|---|
0x60a06040 | 15884956 | 214 days 6 hrs ago | IN | Create: MiltonUsdt | 0 ETH | 0.09625232 |
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:
MiltonUsdt
Compiler Version
v0.8.16+commit.07a7930e
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2022-11-03 */ // File: contracts/libraries/PaginationUtils.sol pragma solidity 0.8.16; library PaginationUtils { function resolveResultSetSize( uint256 totalSwapNumber, uint256 offset, uint256 chunkSize ) internal pure returns (uint256) { uint256 resultSetSize; if (offset > totalSwapNumber) { resultSetSize = 0; } else if (offset + chunkSize < totalSwapNumber) { resultSetSize = chunkSize; } else { resultSetSize = totalSwapNumber - offset; } return resultSetSize; } } // File: contracts/interfaces/types/MiltonStorageTypes.sol pragma solidity 0.8.16; /// @title Types used in MiltonStorage smart contract library MiltonStorageTypes { /// @notice struct representing swap's ID and direction /// @dev direction = 0 - Pay Fixed - Receive Floating, direction = 1 - Receive Fixed - Pay Floating struct IporSwapId { /// @notice Swap ID uint256 id; /// @notice Swap direction, 0 - Pay Fixed Receive Floating, 1 - Receive Fixed Pay Floating uint8 direction; } /// @notice Struct containing extended balance information. /// @dev extended information includes: opening fee balance, liquidation deposit balance, /// IPOR publication fee balance, treasury balance, all balances are in 18 decimals struct ExtendedBalancesMemory { /// @notice Swap's balance for Pay Fixed leg uint256 totalCollateralPayFixed; /// @notice Swap's balance for Receive Fixed leg uint256 totalCollateralReceiveFixed; /// @notice Liquidity Pool's Balance uint256 liquidityPool; /// @notice Stanley's (Asset Management) balance uint256 vault; /// @notice IPOR publication fee balance. This balance is used to subsidise the oracle operations uint256 iporPublicationFee; /// @notice Balance of the DAO's treasury. Fed by portion of the opening and income fees set by the DAO uint256 treasury; } } // File: @openzeppelin/contracts/token/ERC20/IERC20.sol // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); } // File: contracts/interfaces/IIpToken.sol pragma solidity 0.8.16; /// @title Interface of ipToken - Liquidity Pool Token managed by Joseph in IPOR Protocol for a given asset. /// For more information refer to the documentation https://ipor-labs.gitbook.io/ipor-labs/automated-market-maker/liquidity-provisioning#liquidity-tokens interface IIpToken is IERC20 { /// @notice Gets the asset / stablecoin address which is assocciated with particular ipToken smart contract instance /// @return asset / stablecoin address function getAsset() external view returns (address); /// @notice Sets Joseph's address. Owner only /// @dev only Joseph can mint or burn ipTokens. Function emits `JosephChanged` event. /// @param newJoseph Joseph's address function setJoseph(address newJoseph) external; /// @notice Creates the ipTokens in the `amount` given and assigns them to the `account` /// @dev Emits {Transfer} from ERC20 asset and {Mint} event from ipToken /// @param account to which the created ipTokens were assigned /// @param amount volume of ipTokens created function mint(address account, uint256 amount) external; /// @notice Burns the `amount` of ipTokens from `account`, reducing the total supply /// @dev Emits {Transfer} from ERC20 asset and {Burn} event from ipToken /// @param account from which burned ipTokens are taken /// @param amount volume of ipTokens that will be burned, represented in 18 decimals function burn(address account, uint256 amount) external; /// @notice Emmited after the `amount` ipTokens were mint and transferred to `account`. /// @param account address where ipTokens are transferred after minting /// @param amount of ipTokens minted, represented in 18 decimals event Mint(address indexed account, uint256 amount); /// @notice Emmited after `amount` ipTokens were transferred from `account` and burnt. /// @param account address from which ipTokens are transferred to be burned /// @param amount volume of ipTokens burned event Burn(address indexed account, uint256 amount); /// @notice Emmited when Joseph address is changed by its owner. /// @param changedBy account address that changed Joseph's address /// @param oldJoseph old address of Joseph /// @param newJoseph new address of Joseph event JosephChanged( address indexed changedBy, address indexed oldJoseph, address indexed newJoseph ); } // File: contracts/libraries/Constants.sol pragma solidity 0.8.16; library Constants { uint256 public constant MAX_VALUE = 115792089237316195423570985008687907853269984665640564039457584007913129639935; uint256 public constant D18 = 1e18; int256 public constant D18_INT = 1e18; uint256 public constant D36 = 1e36; uint256 public constant D54 = 1e54; uint256 public constant YEAR_IN_SECONDS = 365 days; uint256 public constant WAD_YEAR_IN_SECONDS = D18 * YEAR_IN_SECONDS; int256 public constant WAD_YEAR_IN_SECONDS_INT = int256(WAD_YEAR_IN_SECONDS); uint256 public constant WAD_P2_YEAR_IN_SECONDS = D18 * D18 * YEAR_IN_SECONDS; int256 public constant WAD_P2_YEAR_IN_SECONDS_INT = int256(WAD_P2_YEAR_IN_SECONDS); uint256 public constant MAX_CHUNK_SIZE = 50; //@notice By default every swap takes 28 days, this variable show this value in seconds uint256 public constant SWAP_DEFAULT_PERIOD_IN_SECONDS = 60 * 60 * 24 * 28; } // File: contracts/libraries/errors/MiltonErrors.sol pragma solidity 0.8.16; /// @title Errors which occur inside Milton's method execution. library MiltonErrors { // 300-399-milton /// @notice Liquidity Pool balance is equal 0. string public constant LIQUIDITY_POOL_IS_EMPTY = "IPOR_300"; /// @notice Liquidity Pool balance is too low, should be equal or higher than 0. string public constant LIQUIDITY_POOL_AMOUNT_TOO_LOW = "IPOR_301"; /// @notice Liquidity Pool Utilization exceeded. Liquidity Pool utilization is higher than configured in Milton maximum liquidity pool utilization. string public constant LP_UTILIZATION_EXCEEDED = "IPOR_302"; /// @notice Liquidity Pool Utilization Per Leg exceeded. Liquidity Pool utilization per leg is higher than configured in Milton maximu liquidity pool utilization per leg. string public constant LP_UTILIZATION_PER_LEG_EXCEEDED = "IPOR_303"; /// @notice Liquidity Pool Balance is too high string public constant LIQUIDITY_POOL_BALANCE_IS_TOO_HIGH = "IPOR_304"; /// @notice Liquidity Pool account contribution is too high. string public constant LP_ACCOUNT_CONTRIBUTION_IS_TOO_HIGH = "IPOR_305"; /// @notice Swap id used in input has incorrect value (like 0) or not exists. string public constant INCORRECT_SWAP_ID = "IPOR_306"; /// @notice Swap has incorrect status. string public constant INCORRECT_SWAP_STATUS = "IPOR_307"; /// @notice Leverage given as a parameter when opening swap is lower than configured in Milton minimum leverage. string public constant LEVERAGE_TOO_LOW = "IPOR_308"; /// @notice Leverage given as a parameter when opening swap is higher than configured in Milton maxumum leverage. string public constant LEVERAGE_TOO_HIGH = "IPOR_309"; /// @notice Total amount given as a parameter when opening swap is too low. Cannot be equal zero. string public constant TOTAL_AMOUNT_TOO_LOW = "IPOR_310"; /// @notice Total amount given as a parameter when opening swap is lower than sum of liquidation deposit amount and ipor publication fee. string public constant TOTAL_AMOUNT_LOWER_THAN_FEE = "IPOR_311"; /// @notice Amount of collateral used to open swap is higher than configured in Milton max swap collateral amount string public constant COLLATERAL_AMOUNT_TOO_HIGH = "IPOR_312"; /// @notice Acceptable fixed interest rate defined by traded exceeded. string public constant ACCEPTABLE_FIXED_INTEREST_RATE_EXCEEDED = "IPOR_313"; /// @notice Swap Notional Amount is higher than Total Notional for specific leg. string public constant SWAP_NOTIONAL_HIGHER_THAN_TOTAL_NOTIONAL = "IPOR_314"; /// @notice Number of swaps per leg which are going to be liquidated is too high, is higher than configured in Milton liquidation leg limit. string public constant LIQUIDATION_LEG_LIMIT_EXCEEDED = "IPOR_315"; /// @notice Sum of SOAP and Liquidity Pool Balance is lower than zero. /// @dev SOAP can be negative, Sum of SOAP and Liquidity Pool Balance can be negative, but this is undesirable. string public constant SOAP_AND_LP_BALANCE_SUM_IS_TOO_LOW = "IPOR_316"; /// @notice Calculation timestamp is earlier than last SOAP rebalance timestamp. string public constant CALC_TIMESTAMP_LOWER_THAN_SOAP_REBALANCE_TIMESTAMP = "IPOR_317"; /// @notice Calculation timestamp is lower than Swap's open timestamp. string public constant CALC_TIMESTAMP_LOWER_THAN_SWAP_OPEN_TIMESTAMP = "IPOR_318"; /// @notice Closing timestamp is lower than Swap's open timestamp. string public constant CLOSING_TIMESTAMP_LOWER_THAN_SWAP_OPEN_TIMESTAMP = "IPOR_319"; /// @notice Swap cannot be closed because liquidity pool is too low for payid out cash. Situation should never happen where Liquidity Pool is insolvent. string public constant CANNOT_CLOSE_SWAP_LP_IS_TOO_LOW = "IPOR_320"; /// @notice Swap cannot be closed because sender is not an owner of derivative and derivative maturity not achieved. string public constant CANNOT_CLOSE_SWAP_SENDER_IS_NOT_BUYER_AND_NO_MATURITY = "IPOR_321"; /// @notice Interest from Strategy is below zero. string public constant INTEREST_FROM_STRATEGY_BELOW_ZERO = "IPOR_322"; /// @notice Accrued Liquidity Pool is equal zero. string public constant LIQUIDITY_POOL_ACCRUED_IS_EQUAL_ZERO = "IPOR_323"; /// @notice During spread calculation - Exponential Weighted Moving Variance cannot be higher than 1. string public constant SPREAD_EMVAR_CANNOT_BE_HIGHER_THAN_ONE = "IPOR_324"; /// @notice During spread calculation - Alpha param cannot be higher than 1. string public constant SPREAD_ALPHA_CANNOT_BE_HIGHER_THAN_ONE = "IPOR_325"; /// @notice IPOR publication fee balance is too low. string public constant PUBLICATION_FEE_BALANCE_IS_TOO_LOW = "IPOR_326"; /// @notice The caller must be the Joseph (Smart Contract responsible for managing Milton's tokens and balances). string public constant CALLER_NOT_JOSEPH = "IPOR_327"; /// @notice Deposit amount is too low. string public constant DEPOSIT_AMOUNT_IS_TOO_LOW = "IPOR_328"; /// @notice Vault balance is lower than deposit value. string public constant VAULT_BALANCE_LOWER_THAN_DEPOSIT_VALUE = "IPOR_329"; /// @notice Treasury balance is too low. string public constant TREASURY_BALANCE_IS_TOO_LOW = "IPOR_330"; } // File: contracts/libraries/errors/IporErrors.sol pragma solidity 0.8.16; library IporErrors { // 000-199 - general codes /// @notice General problem, address is wrong string public constant WRONG_ADDRESS = "IPOR_000"; /// @notice General problem. Wrong decimals string public constant WRONG_DECIMALS = "IPOR_001"; string public constant ADDRESSES_MISMATCH = "IPOR_002"; //@notice Trader doesnt have enought tokens to execute transaction string public constant ASSET_BALANCE_TOO_LOW = "IPOR_003"; string public constant VALUE_NOT_GREATER_THAN_ZERO = "IPOR_004"; string public constant INPUT_ARRAYS_LENGTH_MISMATCH = "IPOR_005"; //@notice Amount is too low to transfer string public constant NOT_ENOUGH_AMOUNT_TO_TRANSFER = "IPOR_006"; //@notice msg.sender is not an appointed owner, so cannot confirm his appointment to be an owner of a specific smart contract string public constant SENDER_NOT_APPOINTED_OWNER = "IPOR_007"; //only milton can have access to function string public constant CALLER_NOT_MILTON = "IPOR_008"; string public constant CHUNK_SIZE_EQUAL_ZERO = "IPOR_009"; string public constant CHUNK_SIZE_TOO_BIG = "IPOR_010"; } // File: @openzeppelin/contracts-upgradeable/utils/StorageSlotUpgradeable.sol // OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol) pragma solidity ^0.8.0; /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC1967 implementation slot: * ``` * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` * * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._ */ library StorageSlotUpgradeable { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } } // File: @openzeppelin/contracts-upgradeable/proxy/beacon/IBeaconUpgradeable.sol // OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol) pragma solidity ^0.8.0; /** * @dev This is the interface that {BeaconProxy} expects of its beacon. */ interface IBeaconUpgradeable { /** * @dev Must return an address that can be used as a delegate call target. * * {BeaconProxy} will check that this address is a contract. */ function implementation() external view returns (address); } // File: @openzeppelin/contracts-upgradeable/interfaces/draft-IERC1822Upgradeable.sol // OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol) pragma solidity ^0.8.0; /** * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified * proxy whose upgrades are fully controlled by the current implementation. */ interface IERC1822ProxiableUpgradeable { /** * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation * address. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. */ function proxiableUUID() external view returns (bytes32); } // File: @openzeppelin/contracts-upgradeable/token/ERC20/extensions/draft-IERC20PermitUpgradeable.sol // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20PermitUpgradeable { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); } // File: @openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol // OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } } // File: @openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol // OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ``` * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original * initialization step. This is essential to configure modules that are added through upgrades and that require * initialization. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized < type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } } // File: @openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol // OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol) pragma solidity ^0.8.2; /** * @dev This abstract contract provides getters and event emitting update functions for * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots. * * _Available since v4.1._ * * @custom:oz-upgrades-unsafe-allow delegatecall */ abstract contract ERC1967UpgradeUpgradeable is Initializable { function __ERC1967Upgrade_init() internal onlyInitializing { } function __ERC1967Upgrade_init_unchained() internal onlyInitializing { } // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1 bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143; /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Returns the current implementation address. */ function _getImplementation() internal view returns (address) { return StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value; } /** * @dev Stores a new address in the EIP1967 implementation slot. */ function _setImplementation(address newImplementation) private { require(AddressUpgradeable.isContract(newImplementation), "ERC1967: new implementation is not a contract"); StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; } /** * @dev Perform implementation upgrade * * Emits an {Upgraded} event. */ function _upgradeTo(address newImplementation) internal { _setImplementation(newImplementation); emit Upgraded(newImplementation); } /** * @dev Perform implementation upgrade with additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCall( address newImplementation, bytes memory data, bool forceCall ) internal { _upgradeTo(newImplementation); if (data.length > 0 || forceCall) { _functionDelegateCall(newImplementation, data); } } /** * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCallUUPS( address newImplementation, bytes memory data, bool forceCall ) internal { // Upgrades from old implementations will perform a rollback test. This test requires the new // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing // this special case will break upgrade paths from old UUPS implementation to new ones. if (StorageSlotUpgradeable.getBooleanSlot(_ROLLBACK_SLOT).value) { _setImplementation(newImplementation); } else { try IERC1822ProxiableUpgradeable(newImplementation).proxiableUUID() returns (bytes32 slot) { require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID"); } catch { revert("ERC1967Upgrade: new implementation is not UUPS"); } _upgradeToAndCall(newImplementation, data, forceCall); } } /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Returns the current admin. */ function _getAdmin() internal view returns (address) { return StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value; } /** * @dev Stores a new address in the EIP1967 admin slot. */ function _setAdmin(address newAdmin) private { require(newAdmin != address(0), "ERC1967: new admin is the zero address"); StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value = newAdmin; } /** * @dev Changes the admin of the proxy. * * Emits an {AdminChanged} event. */ function _changeAdmin(address newAdmin) internal { emit AdminChanged(_getAdmin(), newAdmin); _setAdmin(newAdmin); } /** * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy. * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor. */ bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; /** * @dev Emitted when the beacon is upgraded. */ event BeaconUpgraded(address indexed beacon); /** * @dev Returns the current beacon. */ function _getBeacon() internal view returns (address) { return StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value; } /** * @dev Stores a new beacon in the EIP1967 beacon slot. */ function _setBeacon(address newBeacon) private { require(AddressUpgradeable.isContract(newBeacon), "ERC1967: new beacon is not a contract"); require( AddressUpgradeable.isContract(IBeaconUpgradeable(newBeacon).implementation()), "ERC1967: beacon implementation is not a contract" ); StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value = newBeacon; } /** * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that). * * Emits a {BeaconUpgraded} event. */ function _upgradeBeaconToAndCall( address newBeacon, bytes memory data, bool forceCall ) internal { _setBeacon(newBeacon); emit BeaconUpgraded(newBeacon); if (data.length > 0 || forceCall) { _functionDelegateCall(IBeaconUpgradeable(newBeacon).implementation(), data); } } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function _functionDelegateCall(address target, bytes memory data) private returns (bytes memory) { require(AddressUpgradeable.isContract(target), "Address: delegate call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.delegatecall(data); return AddressUpgradeable.verifyCallResult(success, returndata, "Address: low-level delegate call failed"); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; } // File: @openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol // OpenZeppelin Contracts (last updated v4.5.0) (proxy/utils/UUPSUpgradeable.sol) pragma solidity ^0.8.0; /** * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy. * * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing * `UUPSUpgradeable` with a custom implementation of upgrades. * * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism. * * _Available since v4.1._ */ abstract contract UUPSUpgradeable is Initializable, IERC1822ProxiableUpgradeable, ERC1967UpgradeUpgradeable { function __UUPSUpgradeable_init() internal onlyInitializing { } function __UUPSUpgradeable_init_unchained() internal onlyInitializing { } /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment address private immutable __self = address(this); /** * @dev Check that the execution is being performed through a delegatecall call and that the execution context is * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to * fail. */ modifier onlyProxy() { require(address(this) != __self, "Function must be called through delegatecall"); require(_getImplementation() == __self, "Function must be called through active proxy"); _; } /** * @dev Check that the execution is not being performed through a delegate call. This allows a function to be * callable on the implementing contract but not through proxies. */ modifier notDelegated() { require(address(this) == __self, "UUPSUpgradeable: must not be called through delegatecall"); _; } /** * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the * implementation. It is used to validate that the this implementation remains valid after an upgrade. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier. */ function proxiableUUID() external view virtual override notDelegated returns (bytes32) { return _IMPLEMENTATION_SLOT; } /** * @dev Upgrade the implementation of the proxy to `newImplementation`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. */ function upgradeTo(address newImplementation) external virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, new bytes(0), false); } /** * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call * encoded in `data`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. */ function upgradeToAndCall(address newImplementation, bytes memory data) external payable virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, data, true); } /** * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by * {upgradeTo} and {upgradeToAndCall}. * * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}. * * ```solidity * function _authorizeUpgrade(address) internal override onlyOwner {} * ``` */ function _authorizeUpgrade(address newImplementation) internal virtual; /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; } // File: @openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol // OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuardUpgradeable is Initializable { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being 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. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; function __ReentrancyGuard_init() internal onlyInitializing { __ReentrancyGuard_init_unchained(); } function __ReentrancyGuard_init_unchained() internal onlyInitializing { _status = _NOT_ENTERED; } /** * @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 work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; } // File: @openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; } // File: @openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable_init_unchained() internal onlyInitializing { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; } // File: contracts/security/IporOwnableUpgradeable.sol pragma solidity 0.8.16; contract IporOwnableUpgradeable is OwnableUpgradeable { address private _appointedOwner; event AppointedToTransferOwnership(address indexed appointedOwner); function transferOwnership(address appointedOwner) public override onlyOwner { require(appointedOwner != address(0), IporErrors.WRONG_ADDRESS); _appointedOwner = appointedOwner; emit AppointedToTransferOwnership(appointedOwner); } function confirmTransferOwnership() public onlyAppointedOwner { _appointedOwner = address(0); _transferOwnership(_msgSender()); } modifier onlyAppointedOwner() { require(_appointedOwner == _msgSender(), IporErrors.SENDER_NOT_APPOINTED_OWNER); _; } } // File: @openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol // OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol) pragma solidity ^0.8.0; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract PausableUpgradeable is Initializable, ContextUpgradeable { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ function __Pausable_init() internal onlyInitializing { __Pausable_init_unchained(); } function __Pausable_init_unchained() internal onlyInitializing { _paused = false; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { _requireNotPaused(); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { _requirePaused(); _; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view virtual { require(!paused(), "Pausable: paused"); } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { require(paused(), "Pausable: not paused"); } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; } // File: @openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20Upgradeable { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); } // File: @openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; /** * @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 SafeERC20Upgradeable { using AddressUpgradeable for address; function safeTransfer( IERC20Upgradeable token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20Upgradeable 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( IERC20Upgradeable 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( IERC20Upgradeable 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( IERC20Upgradeable 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)); } } function safePermit( IERC20PermitUpgradeable token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @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(IERC20Upgradeable 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: @openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20MetadataUpgradeable is IERC20Upgradeable { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); } // File: @openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.0; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable, IERC20MetadataUpgradeable { mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * The default value of {decimals} is 18. To select a different value for * {decimals} you should overload it. * * All two of these values are immutable: they can only be set once during * construction. */ function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing { __ERC20_init_unchained(name_, symbol_); } function __ERC20_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the value {ERC20} uses, unless this function is * overridden; * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual override returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address to, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _transfer(owner, to, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _approve(owner, spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. * - the caller must have allowance for ``from``'s tokens of at least * `amount`. */ function transferFrom( address from, address to, uint256 amount ) public virtual override returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, amount); _transfer(from, to, amount); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, allowance(owner, spender) + addedValue); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { address owner = _msgSender(); uint256 currentAllowance = allowance(owner, spender); require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); unchecked { _approve(owner, spender, currentAllowance - subtractedValue); } return true; } /** * @dev Moves `amount` of tokens from `from` to `to`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. */ function _transfer( address from, address to, uint256 amount ) internal virtual { require(from != address(0), "ERC20: transfer from the zero address"); require(to != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(from, to, amount); uint256 fromBalance = _balances[from]; require(fromBalance >= amount, "ERC20: transfer amount exceeds balance"); unchecked { _balances[from] = fromBalance - amount; } _balances[to] += amount; emit Transfer(from, to, amount); _afterTokenTransfer(from, to, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply += amount; _balances[account] += amount; emit Transfer(address(0), account, amount); _afterTokenTransfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); unchecked { _balances[account] = accountBalance - amount; } _totalSupply -= amount; emit Transfer(account, address(0), amount); _afterTokenTransfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve( address owner, address spender, uint256 amount ) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Updates `owner` s allowance for `spender` based on spent `amount`. * * Does not update the allowance amount in case of infinite allowance. * Revert if not enough allowance is available. * * Might emit an {Approval} event. */ function _spendAllowance( address owner, address spender, uint256 amount ) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { require(currentAllowance >= amount, "ERC20: insufficient allowance"); unchecked { _approve(owner, spender, currentAllowance - amount); } } } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 amount ) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * has been transferred to `to`. * - when `from` is zero, `amount` tokens have been minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens have been burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 amount ) internal virtual {} /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[45] private __gap; } // File: @openzeppelin/contracts/utils/math/SafeCast.sol // OpenZeppelin Contracts (last updated v4.7.0) (utils/math/SafeCast.sol) pragma solidity ^0.8.0; /** * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow * checks. * * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such an operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. * * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing * all math on `uint256` and `int256` and then downcasting. */ library SafeCast { /** * @dev Returns the downcasted uint248 from uint256, reverting on * overflow (when the input is greater than largest uint248). * * Counterpart to Solidity's `uint248` operator. * * Requirements: * * - input must fit into 248 bits * * _Available since v4.7._ */ function toUint248(uint256 value) internal pure returns (uint248) { require(value <= type(uint248).max, "SafeCast: value doesn't fit in 248 bits"); return uint248(value); } /** * @dev Returns the downcasted uint240 from uint256, reverting on * overflow (when the input is greater than largest uint240). * * Counterpart to Solidity's `uint240` operator. * * Requirements: * * - input must fit into 240 bits * * _Available since v4.7._ */ function toUint240(uint256 value) internal pure returns (uint240) { require(value <= type(uint240).max, "SafeCast: value doesn't fit in 240 bits"); return uint240(value); } /** * @dev Returns the downcasted uint232 from uint256, reverting on * overflow (when the input is greater than largest uint232). * * Counterpart to Solidity's `uint232` operator. * * Requirements: * * - input must fit into 232 bits * * _Available since v4.7._ */ function toUint232(uint256 value) internal pure returns (uint232) { require(value <= type(uint232).max, "SafeCast: value doesn't fit in 232 bits"); return uint232(value); } /** * @dev Returns the downcasted uint224 from uint256, reverting on * overflow (when the input is greater than largest uint224). * * Counterpart to Solidity's `uint224` operator. * * Requirements: * * - input must fit into 224 bits * * _Available since v4.2._ */ function toUint224(uint256 value) internal pure returns (uint224) { require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits"); return uint224(value); } /** * @dev Returns the downcasted uint216 from uint256, reverting on * overflow (when the input is greater than largest uint216). * * Counterpart to Solidity's `uint216` operator. * * Requirements: * * - input must fit into 216 bits * * _Available since v4.7._ */ function toUint216(uint256 value) internal pure returns (uint216) { require(value <= type(uint216).max, "SafeCast: value doesn't fit in 216 bits"); return uint216(value); } /** * @dev Returns the downcasted uint208 from uint256, reverting on * overflow (when the input is greater than largest uint208). * * Counterpart to Solidity's `uint208` operator. * * Requirements: * * - input must fit into 208 bits * * _Available since v4.7._ */ function toUint208(uint256 value) internal pure returns (uint208) { require(value <= type(uint208).max, "SafeCast: value doesn't fit in 208 bits"); return uint208(value); } /** * @dev Returns the downcasted uint200 from uint256, reverting on * overflow (when the input is greater than largest uint200). * * Counterpart to Solidity's `uint200` operator. * * Requirements: * * - input must fit into 200 bits * * _Available since v4.7._ */ function toUint200(uint256 value) internal pure returns (uint200) { require(value <= type(uint200).max, "SafeCast: value doesn't fit in 200 bits"); return uint200(value); } /** * @dev Returns the downcasted uint192 from uint256, reverting on * overflow (when the input is greater than largest uint192). * * Counterpart to Solidity's `uint192` operator. * * Requirements: * * - input must fit into 192 bits * * _Available since v4.7._ */ function toUint192(uint256 value) internal pure returns (uint192) { require(value <= type(uint192).max, "SafeCast: value doesn't fit in 192 bits"); return uint192(value); } /** * @dev Returns the downcasted uint184 from uint256, reverting on * overflow (when the input is greater than largest uint184). * * Counterpart to Solidity's `uint184` operator. * * Requirements: * * - input must fit into 184 bits * * _Available since v4.7._ */ function toUint184(uint256 value) internal pure returns (uint184) { require(value <= type(uint184).max, "SafeCast: value doesn't fit in 184 bits"); return uint184(value); } /** * @dev Returns the downcasted uint176 from uint256, reverting on * overflow (when the input is greater than largest uint176). * * Counterpart to Solidity's `uint176` operator. * * Requirements: * * - input must fit into 176 bits * * _Available since v4.7._ */ function toUint176(uint256 value) internal pure returns (uint176) { require(value <= type(uint176).max, "SafeCast: value doesn't fit in 176 bits"); return uint176(value); } /** * @dev Returns the downcasted uint168 from uint256, reverting on * overflow (when the input is greater than largest uint168). * * Counterpart to Solidity's `uint168` operator. * * Requirements: * * - input must fit into 168 bits * * _Available since v4.7._ */ function toUint168(uint256 value) internal pure returns (uint168) { require(value <= type(uint168).max, "SafeCast: value doesn't fit in 168 bits"); return uint168(value); } /** * @dev Returns the downcasted uint160 from uint256, reverting on * overflow (when the input is greater than largest uint160). * * Counterpart to Solidity's `uint160` operator. * * Requirements: * * - input must fit into 160 bits * * _Available since v4.7._ */ function toUint160(uint256 value) internal pure returns (uint160) { require(value <= type(uint160).max, "SafeCast: value doesn't fit in 160 bits"); return uint160(value); } /** * @dev Returns the downcasted uint152 from uint256, reverting on * overflow (when the input is greater than largest uint152). * * Counterpart to Solidity's `uint152` operator. * * Requirements: * * - input must fit into 152 bits * * _Available since v4.7._ */ function toUint152(uint256 value) internal pure returns (uint152) { require(value <= type(uint152).max, "SafeCast: value doesn't fit in 152 bits"); return uint152(value); } /** * @dev Returns the downcasted uint144 from uint256, reverting on * overflow (when the input is greater than largest uint144). * * Counterpart to Solidity's `uint144` operator. * * Requirements: * * - input must fit into 144 bits * * _Available since v4.7._ */ function toUint144(uint256 value) internal pure returns (uint144) { require(value <= type(uint144).max, "SafeCast: value doesn't fit in 144 bits"); return uint144(value); } /** * @dev Returns the downcasted uint136 from uint256, reverting on * overflow (when the input is greater than largest uint136). * * Counterpart to Solidity's `uint136` operator. * * Requirements: * * - input must fit into 136 bits * * _Available since v4.7._ */ function toUint136(uint256 value) internal pure returns (uint136) { require(value <= type(uint136).max, "SafeCast: value doesn't fit in 136 bits"); return uint136(value); } /** * @dev Returns the downcasted uint128 from uint256, reverting on * overflow (when the input is greater than largest uint128). * * Counterpart to Solidity's `uint128` operator. * * Requirements: * * - input must fit into 128 bits * * _Available since v2.5._ */ function toUint128(uint256 value) internal pure returns (uint128) { require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits"); return uint128(value); } /** * @dev Returns the downcasted uint120 from uint256, reverting on * overflow (when the input is greater than largest uint120). * * Counterpart to Solidity's `uint120` operator. * * Requirements: * * - input must fit into 120 bits * * _Available since v4.7._ */ function toUint120(uint256 value) internal pure returns (uint120) { require(value <= type(uint120).max, "SafeCast: value doesn't fit in 120 bits"); return uint120(value); } /** * @dev Returns the downcasted uint112 from uint256, reverting on * overflow (when the input is greater than largest uint112). * * Counterpart to Solidity's `uint112` operator. * * Requirements: * * - input must fit into 112 bits * * _Available since v4.7._ */ function toUint112(uint256 value) internal pure returns (uint112) { require(value <= type(uint112).max, "SafeCast: value doesn't fit in 112 bits"); return uint112(value); } /** * @dev Returns the downcasted uint104 from uint256, reverting on * overflow (when the input is greater than largest uint104). * * Counterpart to Solidity's `uint104` operator. * * Requirements: * * - input must fit into 104 bits * * _Available since v4.7._ */ function toUint104(uint256 value) internal pure returns (uint104) { require(value <= type(uint104).max, "SafeCast: value doesn't fit in 104 bits"); return uint104(value); } /** * @dev Returns the downcasted uint96 from uint256, reverting on * overflow (when the input is greater than largest uint96). * * Counterpart to Solidity's `uint96` operator. * * Requirements: * * - input must fit into 96 bits * * _Available since v4.2._ */ function toUint96(uint256 value) internal pure returns (uint96) { require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits"); return uint96(value); } /** * @dev Returns the downcasted uint88 from uint256, reverting on * overflow (when the input is greater than largest uint88). * * Counterpart to Solidity's `uint88` operator. * * Requirements: * * - input must fit into 88 bits * * _Available since v4.7._ */ function toUint88(uint256 value) internal pure returns (uint88) { require(value <= type(uint88).max, "SafeCast: value doesn't fit in 88 bits"); return uint88(value); } /** * @dev Returns the downcasted uint80 from uint256, reverting on * overflow (when the input is greater than largest uint80). * * Counterpart to Solidity's `uint80` operator. * * Requirements: * * - input must fit into 80 bits * * _Available since v4.7._ */ function toUint80(uint256 value) internal pure returns (uint80) { require(value <= type(uint80).max, "SafeCast: value doesn't fit in 80 bits"); return uint80(value); } /** * @dev Returns the downcasted uint72 from uint256, reverting on * overflow (when the input is greater than largest uint72). * * Counterpart to Solidity's `uint72` operator. * * Requirements: * * - input must fit into 72 bits * * _Available since v4.7._ */ function toUint72(uint256 value) internal pure returns (uint72) { require(value <= type(uint72).max, "SafeCast: value doesn't fit in 72 bits"); return uint72(value); } /** * @dev Returns the downcasted uint64 from uint256, reverting on * overflow (when the input is greater than largest uint64). * * Counterpart to Solidity's `uint64` operator. * * Requirements: * * - input must fit into 64 bits * * _Available since v2.5._ */ function toUint64(uint256 value) internal pure returns (uint64) { require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits"); return uint64(value); } /** * @dev Returns the downcasted uint56 from uint256, reverting on * overflow (when the input is greater than largest uint56). * * Counterpart to Solidity's `uint56` operator. * * Requirements: * * - input must fit into 56 bits * * _Available since v4.7._ */ function toUint56(uint256 value) internal pure returns (uint56) { require(value <= type(uint56).max, "SafeCast: value doesn't fit in 56 bits"); return uint56(value); } /** * @dev Returns the downcasted uint48 from uint256, reverting on * overflow (when the input is greater than largest uint48). * * Counterpart to Solidity's `uint48` operator. * * Requirements: * * - input must fit into 48 bits * * _Available since v4.7._ */ function toUint48(uint256 value) internal pure returns (uint48) { require(value <= type(uint48).max, "SafeCast: value doesn't fit in 48 bits"); return uint48(value); } /** * @dev Returns the downcasted uint40 from uint256, reverting on * overflow (when the input is greater than largest uint40). * * Counterpart to Solidity's `uint40` operator. * * Requirements: * * - input must fit into 40 bits * * _Available since v4.7._ */ function toUint40(uint256 value) internal pure returns (uint40) { require(value <= type(uint40).max, "SafeCast: value doesn't fit in 40 bits"); return uint40(value); } /** * @dev Returns the downcasted uint32 from uint256, reverting on * overflow (when the input is greater than largest uint32). * * Counterpart to Solidity's `uint32` operator. * * Requirements: * * - input must fit into 32 bits * * _Available since v2.5._ */ function toUint32(uint256 value) internal pure returns (uint32) { require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits"); return uint32(value); } /** * @dev Returns the downcasted uint24 from uint256, reverting on * overflow (when the input is greater than largest uint24). * * Counterpart to Solidity's `uint24` operator. * * Requirements: * * - input must fit into 24 bits * * _Available since v4.7._ */ function toUint24(uint256 value) internal pure returns (uint24) { require(value <= type(uint24).max, "SafeCast: value doesn't fit in 24 bits"); return uint24(value); } /** * @dev Returns the downcasted uint16 from uint256, reverting on * overflow (when the input is greater than largest uint16). * * Counterpart to Solidity's `uint16` operator. * * Requirements: * * - input must fit into 16 bits * * _Available since v2.5._ */ function toUint16(uint256 value) internal pure returns (uint16) { require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits"); return uint16(value); } /** * @dev Returns the downcasted uint8 from uint256, reverting on * overflow (when the input is greater than largest uint8). * * Counterpart to Solidity's `uint8` operator. * * Requirements: * * - input must fit into 8 bits * * _Available since v2.5._ */ function toUint8(uint256 value) internal pure returns (uint8) { require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits"); return uint8(value); } /** * @dev Converts a signed int256 into an unsigned uint256. * * Requirements: * * - input must be greater than or equal to 0. * * _Available since v3.0._ */ function toUint256(int256 value) internal pure returns (uint256) { require(value >= 0, "SafeCast: value must be positive"); return uint256(value); } /** * @dev Returns the downcasted int248 from int256, reverting on * overflow (when the input is less than smallest int248 or * greater than largest int248). * * Counterpart to Solidity's `int248` operator. * * Requirements: * * - input must fit into 248 bits * * _Available since v4.7._ */ function toInt248(int256 value) internal pure returns (int248) { require(value >= type(int248).min && value <= type(int248).max, "SafeCast: value doesn't fit in 248 bits"); return int248(value); } /** * @dev Returns the downcasted int240 from int256, reverting on * overflow (when the input is less than smallest int240 or * greater than largest int240). * * Counterpart to Solidity's `int240` operator. * * Requirements: * * - input must fit into 240 bits * * _Available since v4.7._ */ function toInt240(int256 value) internal pure returns (int240) { require(value >= type(int240).min && value <= type(int240).max, "SafeCast: value doesn't fit in 240 bits"); return int240(value); } /** * @dev Returns the downcasted int232 from int256, reverting on * overflow (when the input is less than smallest int232 or * greater than largest int232). * * Counterpart to Solidity's `int232` operator. * * Requirements: * * - input must fit into 232 bits * * _Available since v4.7._ */ function toInt232(int256 value) internal pure returns (int232) { require(value >= type(int232).min && value <= type(int232).max, "SafeCast: value doesn't fit in 232 bits"); return int232(value); } /** * @dev Returns the downcasted int224 from int256, reverting on * overflow (when the input is less than smallest int224 or * greater than largest int224). * * Counterpart to Solidity's `int224` operator. * * Requirements: * * - input must fit into 224 bits * * _Available since v4.7._ */ function toInt224(int256 value) internal pure returns (int224) { require(value >= type(int224).min && value <= type(int224).max, "SafeCast: value doesn't fit in 224 bits"); return int224(value); } /** * @dev Returns the downcasted int216 from int256, reverting on * overflow (when the input is less than smallest int216 or * greater than largest int216). * * Counterpart to Solidity's `int216` operator. * * Requirements: * * - input must fit into 216 bits * * _Available since v4.7._ */ function toInt216(int256 value) internal pure returns (int216) { require(value >= type(int216).min && value <= type(int216).max, "SafeCast: value doesn't fit in 216 bits"); return int216(value); } /** * @dev Returns the downcasted int208 from int256, reverting on * overflow (when the input is less than smallest int208 or * greater than largest int208). * * Counterpart to Solidity's `int208` operator. * * Requirements: * * - input must fit into 208 bits * * _Available since v4.7._ */ function toInt208(int256 value) internal pure returns (int208) { require(value >= type(int208).min && value <= type(int208).max, "SafeCast: value doesn't fit in 208 bits"); return int208(value); } /** * @dev Returns the downcasted int200 from int256, reverting on * overflow (when the input is less than smallest int200 or * greater than largest int200). * * Counterpart to Solidity's `int200` operator. * * Requirements: * * - input must fit into 200 bits * * _Available since v4.7._ */ function toInt200(int256 value) internal pure returns (int200) { require(value >= type(int200).min && value <= type(int200).max, "SafeCast: value doesn't fit in 200 bits"); return int200(value); } /** * @dev Returns the downcasted int192 from int256, reverting on * overflow (when the input is less than smallest int192 or * greater than largest int192). * * Counterpart to Solidity's `int192` operator. * * Requirements: * * - input must fit into 192 bits * * _Available since v4.7._ */ function toInt192(int256 value) internal pure returns (int192) { require(value >= type(int192).min && value <= type(int192).max, "SafeCast: value doesn't fit in 192 bits"); return int192(value); } /** * @dev Returns the downcasted int184 from int256, reverting on * overflow (when the input is less than smallest int184 or * greater than largest int184). * * Counterpart to Solidity's `int184` operator. * * Requirements: * * - input must fit into 184 bits * * _Available since v4.7._ */ function toInt184(int256 value) internal pure returns (int184) { require(value >= type(int184).min && value <= type(int184).max, "SafeCast: value doesn't fit in 184 bits"); return int184(value); } /** * @dev Returns the downcasted int176 from int256, reverting on * overflow (when the input is less than smallest int176 or * greater than largest int176). * * Counterpart to Solidity's `int176` operator. * * Requirements: * * - input must fit into 176 bits * * _Available since v4.7._ */ function toInt176(int256 value) internal pure returns (int176) { require(value >= type(int176).min && value <= type(int176).max, "SafeCast: value doesn't fit in 176 bits"); return int176(value); } /** * @dev Returns the downcasted int168 from int256, reverting on * overflow (when the input is less than smallest int168 or * greater than largest int168). * * Counterpart to Solidity's `int168` operator. * * Requirements: * * - input must fit into 168 bits * * _Available since v4.7._ */ function toInt168(int256 value) internal pure returns (int168) { require(value >= type(int168).min && value <= type(int168).max, "SafeCast: value doesn't fit in 168 bits"); return int168(value); } /** * @dev Returns the downcasted int160 from int256, reverting on * overflow (when the input is less than smallest int160 or * greater than largest int160). * * Counterpart to Solidity's `int160` operator. * * Requirements: * * - input must fit into 160 bits * * _Available since v4.7._ */ function toInt160(int256 value) internal pure returns (int160) { require(value >= type(int160).min && value <= type(int160).max, "SafeCast: value doesn't fit in 160 bits"); return int160(value); } /** * @dev Returns the downcasted int152 from int256, reverting on * overflow (when the input is less than smallest int152 or * greater than largest int152). * * Counterpart to Solidity's `int152` operator. * * Requirements: * * - input must fit into 152 bits * * _Available since v4.7._ */ function toInt152(int256 value) internal pure returns (int152) { require(value >= type(int152).min && value <= type(int152).max, "SafeCast: value doesn't fit in 152 bits"); return int152(value); } /** * @dev Returns the downcasted int144 from int256, reverting on * overflow (when the input is less than smallest int144 or * greater than largest int144). * * Counterpart to Solidity's `int144` operator. * * Requirements: * * - input must fit into 144 bits * * _Available since v4.7._ */ function toInt144(int256 value) internal pure returns (int144) { require(value >= type(int144).min && value <= type(int144).max, "SafeCast: value doesn't fit in 144 bits"); return int144(value); } /** * @dev Returns the downcasted int136 from int256, reverting on * overflow (when the input is less than smallest int136 or * greater than largest int136). * * Counterpart to Solidity's `int136` operator. * * Requirements: * * - input must fit into 136 bits * * _Available since v4.7._ */ function toInt136(int256 value) internal pure returns (int136) { require(value >= type(int136).min && value <= type(int136).max, "SafeCast: value doesn't fit in 136 bits"); return int136(value); } /** * @dev Returns the downcasted int128 from int256, reverting on * overflow (when the input is less than smallest int128 or * greater than largest int128). * * Counterpart to Solidity's `int128` operator. * * Requirements: * * - input must fit into 128 bits * * _Available since v3.1._ */ function toInt128(int256 value) internal pure returns (int128) { require(value >= type(int128).min && value <= type(int128).max, "SafeCast: value doesn't fit in 128 bits"); return int128(value); } /** * @dev Returns the downcasted int120 from int256, reverting on * overflow (when the input is less than smallest int120 or * greater than largest int120). * * Counterpart to Solidity's `int120` operator. * * Requirements: * * - input must fit into 120 bits * * _Available since v4.7._ */ function toInt120(int256 value) internal pure returns (int120) { require(value >= type(int120).min && value <= type(int120).max, "SafeCast: value doesn't fit in 120 bits"); return int120(value); } /** * @dev Returns the downcasted int112 from int256, reverting on * overflow (when the input is less than smallest int112 or * greater than largest int112). * * Counterpart to Solidity's `int112` operator. * * Requirements: * * - input must fit into 112 bits * * _Available since v4.7._ */ function toInt112(int256 value) internal pure returns (int112) { require(value >= type(int112).min && value <= type(int112).max, "SafeCast: value doesn't fit in 112 bits"); return int112(value); } /** * @dev Returns the downcasted int104 from int256, reverting on * overflow (when the input is less than smallest int104 or * greater than largest int104). * * Counterpart to Solidity's `int104` operator. * * Requirements: * * - input must fit into 104 bits * * _Available since v4.7._ */ function toInt104(int256 value) internal pure returns (int104) { require(value >= type(int104).min && value <= type(int104).max, "SafeCast: value doesn't fit in 104 bits"); return int104(value); } /** * @dev Returns the downcasted int96 from int256, reverting on * overflow (when the input is less than smallest int96 or * greater than largest int96). * * Counterpart to Solidity's `int96` operator. * * Requirements: * * - input must fit into 96 bits * * _Available since v4.7._ */ function toInt96(int256 value) internal pure returns (int96) { require(value >= type(int96).min && value <= type(int96).max, "SafeCast: value doesn't fit in 96 bits"); return int96(value); } /** * @dev Returns the downcasted int88 from int256, reverting on * overflow (when the input is less than smallest int88 or * greater than largest int88). * * Counterpart to Solidity's `int88` operator. * * Requirements: * * - input must fit into 88 bits * * _Available since v4.7._ */ function toInt88(int256 value) internal pure returns (int88) { require(value >= type(int88).min && value <= type(int88).max, "SafeCast: value doesn't fit in 88 bits"); return int88(value); } /** * @dev Returns the downcasted int80 from int256, reverting on * overflow (when the input is less than smallest int80 or * greater than largest int80). * * Counterpart to Solidity's `int80` operator. * * Requirements: * * - input must fit into 80 bits * * _Available since v4.7._ */ function toInt80(int256 value) internal pure returns (int80) { require(value >= type(int80).min && value <= type(int80).max, "SafeCast: value doesn't fit in 80 bits"); return int80(value); } /** * @dev Returns the downcasted int72 from int256, reverting on * overflow (when the input is less than smallest int72 or * greater than largest int72). * * Counterpart to Solidity's `int72` operator. * * Requirements: * * - input must fit into 72 bits * * _Available since v4.7._ */ function toInt72(int256 value) internal pure returns (int72) { require(value >= type(int72).min && value <= type(int72).max, "SafeCast: value doesn't fit in 72 bits"); return int72(value); } /** * @dev Returns the downcasted int64 from int256, reverting on * overflow (when the input is less than smallest int64 or * greater than largest int64). * * Counterpart to Solidity's `int64` operator. * * Requirements: * * - input must fit into 64 bits * * _Available since v3.1._ */ function toInt64(int256 value) internal pure returns (int64) { require(value >= type(int64).min && value <= type(int64).max, "SafeCast: value doesn't fit in 64 bits"); return int64(value); } /** * @dev Returns the downcasted int56 from int256, reverting on * overflow (when the input is less than smallest int56 or * greater than largest int56). * * Counterpart to Solidity's `int56` operator. * * Requirements: * * - input must fit into 56 bits * * _Available since v4.7._ */ function toInt56(int256 value) internal pure returns (int56) { require(value >= type(int56).min && value <= type(int56).max, "SafeCast: value doesn't fit in 56 bits"); return int56(value); } /** * @dev Returns the downcasted int48 from int256, reverting on * overflow (when the input is less than smallest int48 or * greater than largest int48). * * Counterpart to Solidity's `int48` operator. * * Requirements: * * - input must fit into 48 bits * * _Available since v4.7._ */ function toInt48(int256 value) internal pure returns (int48) { require(value >= type(int48).min && value <= type(int48).max, "SafeCast: value doesn't fit in 48 bits"); return int48(value); } /** * @dev Returns the downcasted int40 from int256, reverting on * overflow (when the input is less than smallest int40 or * greater than largest int40). * * Counterpart to Solidity's `int40` operator. * * Requirements: * * - input must fit into 40 bits * * _Available since v4.7._ */ function toInt40(int256 value) internal pure returns (int40) { require(value >= type(int40).min && value <= type(int40).max, "SafeCast: value doesn't fit in 40 bits"); return int40(value); } /** * @dev Returns the downcasted int32 from int256, reverting on * overflow (when the input is less than smallest int32 or * greater than largest int32). * * Counterpart to Solidity's `int32` operator. * * Requirements: * * - input must fit into 32 bits * * _Available since v3.1._ */ function toInt32(int256 value) internal pure returns (int32) { require(value >= type(int32).min && value <= type(int32).max, "SafeCast: value doesn't fit in 32 bits"); return int32(value); } /** * @dev Returns the downcasted int24 from int256, reverting on * overflow (when the input is less than smallest int24 or * greater than largest int24). * * Counterpart to Solidity's `int24` operator. * * Requirements: * * - input must fit into 24 bits * * _Available since v4.7._ */ function toInt24(int256 value) internal pure returns (int24) { require(value >= type(int24).min && value <= type(int24).max, "SafeCast: value doesn't fit in 24 bits"); return int24(value); } /** * @dev Returns the downcasted int16 from int256, reverting on * overflow (when the input is less than smallest int16 or * greater than largest int16). * * Counterpart to Solidity's `int16` operator. * * Requirements: * * - input must fit into 16 bits * * _Available since v3.1._ */ function toInt16(int256 value) internal pure returns (int16) { require(value >= type(int16).min && value <= type(int16).max, "SafeCast: value doesn't fit in 16 bits"); return int16(value); } /** * @dev Returns the downcasted int8 from int256, reverting on * overflow (when the input is less than smallest int8 or * greater than largest int8). * * Counterpart to Solidity's `int8` operator. * * Requirements: * * - input must fit into 8 bits * * _Available since v3.1._ */ function toInt8(int256 value) internal pure returns (int8) { require(value >= type(int8).min && value <= type(int8).max, "SafeCast: value doesn't fit in 8 bits"); return int8(value); } /** * @dev Converts an unsigned uint256 into a signed int256. * * Requirements: * * - input must be less than or equal to maxInt256. * * _Available since v3.0._ */ function toInt256(uint256 value) internal pure returns (int256) { // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256"); return int256(value); } } // File: contracts/interfaces/IStanley.sol pragma solidity 0.8.16; /// @title Interface for interaction with Stanley smart contract. /// @notice Stanley is reposnsible for delegating assets stored in Milton to money markets where they can earn interest. interface IStanley { /// @notice Gets total balance of account `who`, transferred assets to Stanley. /// @param who Account for which total balance is returned. /// @return Total balance for specific account given as a parameter, represented in 18 decimals. function totalBalance(address who) external view returns (uint256); /// @notice Calculated exchange rate between ivToken and the underlying asset. Asset is specific to Stanley's intance (ex. USDC, USDT, DAI, etc.) /// @return Current exchange rate between ivToken and the underlying asset, represented in 18 decimals. function calculateExchangeRate() external view returns (uint256); /// @notice Deposits ERC20 underlying assets to Stanley. Function available only for Milton. /// @dev Emits {Deposit} event from Stanley, emits {Mint} event from ivToken, emits {Transfer} event from ERC20 asset. /// Input and output values are represented in 18 decimals. /// @param amount amount deposited by Milton to Stanley. /// @return vaultBalance current balance including amount deposited on Stanley. /// @return depositedAmount final deposited amount. function deposit(uint256 amount) external returns (uint256 vaultBalance, uint256 depositedAmount); /// @notice Withdraws declared amount of asset from Stanley to Milton. Function available only for Milton. /// @dev Emits {Withdraw} event from Stanley, emits {Burn} event from ivToken, emits {Transfer} event from ERC20 asset. /// Input and output values are represented in 18 decimals. /// @param amount deposited amount of underlying asset /// @return withdrawnAmount final withdrawn amount of asset from Stanley, can be different than input amount due to passing time. /// @return vaultBalance current asset balance on Stanley function withdraw(uint256 amount) external returns (uint256 withdrawnAmount, uint256 vaultBalance); /// @notice Withdraws all of the asset from Stanley to Milton. Function available only for Milton. /// @dev Emits {Withdraw} event from Stanley, emits {Burn} event from ivToken, emits {Transfer} event from ERC20 asset. /// Output values are represented in 18 decimals. /// @return withdrawnAmount final withdrawn amount of the asset. /// @return vaultBalance current asset's balance on Stanley function withdrawAll() external returns (uint256 withdrawnAmount, uint256 vaultBalance); /// @notice Emmited after Milton has executed deposit function. /// @param timestamp moment when deposit function was executed /// @param from account address from which assets are transferred /// @param to account address where assets are transferred to /// @param exchangeRate exchange rate of ivToken, represented in 18 decimals /// @param amount of asset transferred from Milton to Stanley, represented in 18 decimals /// @param ivTokenAmount amount calculated based on `exchangeRate` and `amount`, represented in 18 decimals. event Deposit( uint256 timestamp, address from, address to, uint256 exchangeRate, uint256 amount, uint256 ivTokenAmount ); /// @notice Emmited when Milton executes withdraw function. /// @param timestamp moment when deposit was executed /// @param from account address from which assets are transferred /// @param to account address where assets are transferred to /// @param exchangeRate exchange rate of ivToken, represented in 18 decimals /// @param amount of asset transferred from Milton to Stanley, represented in 18 decimals /// @param ivTokenAmount amount of ivToken calculated based on `exchangeRate` and `amount`, represented in 18 decimals. event Withdraw( uint256 timestamp, address from, address to, uint256 exchangeRate, uint256 amount, uint256 ivTokenAmount ); } // File: contracts/interfaces/IJoseph.sol pragma solidity 0.8.16; /// @title Interface for interaction with Joseph - smart contract responsible /// for managing ipTokens and ERC20 tokens in IPOR Protocol. interface IJoseph { /// @notice Calculates ipToken exchange rate /// @dev exchange rate is a ratio between Liqudity Pool Balance and ipToken total supply /// @return ipToken exchange rate for a specific asset, represented in 18 decimals. function calculateExchangeRate() external view returns (uint256); /// @notice Function invoked to provide asset to Liquidity Pool in amount `assetValue` /// @dev Emits {ProvideLiquidity} event and transfers ERC20 tokens from sender to Milton, /// emits {Transfer} event from ERC20 asset, emits {Mint} event from ipToken. /// Transfers minted ipTokens to the sender. Amount of transferred ipTokens is based on current ipToken exchange rate /// @param assetAmount Amount of ERC20 tokens which are transferred from sender to Milton. Represented in decimals specific for asset. function provideLiquidity(uint256 assetAmount) external; /// @notice Redeems `ipTokenAmount` IpTokens for underlying asset /// @dev Emits {Redeem} event, emits {Transfer} event from ERC20 asset, emits {Burn} event from ipToken. /// Transfers asser ERC20 tokens from Milton to sender based on current exchange rate. /// @param ipTokenAmount redeem amount, represented in 18 decimals. function redeem(uint256 ipTokenAmount) external; /// @notice Returns reserve ratio of Milton Asset Balance / (Milton Asset Balance + Stanley Asset Balance) for a given asset. /// Resere ratio is the ratio between ERC20 asset kept on hand by Milton, not delegated to Stanley and total amount of asset. /// @return reserves ratio, represented in 18 decimals function checkVaultReservesRatio() external view returns (uint256); /// @notice Emitted when `from` account provides liquidity (ERC20 token supported by IPOR Protocol) to Milton Liquidity Pool event ProvideLiquidity( /// @notice moment when liquidity is provided by `from` account uint256 timestamp, /// @notice address that provides liquidity address from, /// @notice Milton's address where liquidity is received address to, /// @notice current ipToken exchange rate /// @dev value represented in 18 decimals uint256 exchangeRate, /// @notice amount of asset provided by user to Milton's liquidity pool /// @dev value represented in 18 decimals uint256 assetAmount, /// @notice amount of ipToken issued to represent user's share in the liquidity pool. /// @dev value represented in 18 decimals uint256 ipTokenAmount ); /// @notice Emitted when `to` accound executes redeem ipTokens event Redeem( /// @notice moment in which ipTokens were redeemed by `to` account uint256 timestamp, /// @notice Milton's address from which underlying asset - ERC20 Tokens, are transferred to `to` account address from, /// @notice account where underlying asset tokens are transferred after redeem address to, /// @notice ipToken exchange rate used for calculating `assetAmount` /// @dev value represented in 18 decimals uint256 exchangeRate, /// @notice underlying asset value calculated based on `exchangeRate` and `ipTokenAmount` /// @dev value represented in 18 decimals uint256 assetAmount, /// @notice redeemed IP Token value /// @dev value represented in 18 decimals uint256 ipTokenAmount, /// @notice underlying asset fee deducted when redeeming ipToken. /// @dev value represented in 18 decimals uint256 redeemFee, /// @notice net asset amount transferred from Milton to `to`/sender's account, reduced by the redeem fee /// @dev value represented in 18 decimals uint256 redeemAmount ); } // File: contracts/interfaces/types/IporTypes.sol pragma solidity 0.8.16; /// @title Struct used across various interfaces in IPOR Protocol. library IporTypes { /// @notice The struct describing the IPOR and its params calculated for the time when it was most recently updated and the change that took place since the update. /// Namely, the interest that would be computed into IBT should the rebalance occur. struct AccruedIpor { /// @notice IPOR Index Value /// @dev value represented in 18 decimals uint256 indexValue; /// @notice IBT Price (IBT - Interest Bearing Token). For more information reffer to the documentation: /// https://ipor-labs.gitbook.io/ipor-labs/interest-rate-derivatives/ibt /// @dev value represented in 18 decimals uint256 ibtPrice; /// @notice Exponential Moving Average /// @dev value represented in 18 decimals uint256 exponentialMovingAverage; /// @notice Exponential Weighted Moving Variance /// @dev value represented in 18 decimals uint256 exponentialWeightedMovingVariance; } /// @notice Struct representing swap item, used for listing and in internal calculations struct IporSwapMemory { /// @notice Swap's unique ID uint256 id; /// @notice Swap's buyer address buyer; /// @notice Swap opening epoch timestamp uint256 openTimestamp; /// @notice Epoch when the swap will reach its maturity uint256 endTimestamp; /// @notice Index position of this Swap in an array of swaps' identification associated to swap buyer /// @dev Field used for gas optimization purposes, it allows for quick removal by id in the array. /// During removal the last item in the array is switched with the one that just has been removed. uint256 idsIndex; /// @notice Swap's collateral /// @dev value represented in 18 decimals uint256 collateral; /// @notice Swap's notional amount /// @dev value represented in 18 decimals uint256 notional; /// @notice Swap's notional amount denominated in the Interest Bearing Token (IBT) /// @dev value represented in 18 decimals uint256 ibtQuantity; /// @notice Fixed interest rate at which the position has been opened /// @dev value represented in 18 decimals uint256 fixedInterestRate; /// @notice Liquidation deposit amount /// @dev value represented in 18 decimals uint256 liquidationDepositAmount; /// @notice State of the swap /// @dev 0 - INACTIVE, 1 - ACTIVE uint256 state; } /// @notice Struct representing balances used internally for asset calculations /// @dev all balances in 18 decimals struct MiltonBalancesMemory { /// @notice Sum of all collateral put forward by the derivative buyer's on Pay Fixed & Receive Floating leg. uint256 totalCollateralPayFixed; /// @notice Sum of all collateral put forward by the derivative buyer's on Pay Floating & Receive Fixed leg. uint256 totalCollateralReceiveFixed; /// @notice Liquidity Pool Balance. This balance is where the liquidity from liquidity providers and the opening fee are accounted for, /// @dev Amount of opening fee accounted in this balance is defined by _OPENING_FEE_FOR_TREASURY_PORTION_RATE param. uint256 liquidityPool; /// @notice Vault's balance, describes how much asset has been transfered to Asset Management Vault (Stanley) uint256 vault; } } // File: contracts/amm/libraries/types/AmmMiltonTypes.sol pragma solidity 0.8.16; /// @notice The types used in Milton's interface. /// @dev All values, where applicable, are represented in 18 decimals. library AmmMiltonTypes { struct BeforeOpenSwapStruct { /// @notice Sum of all asset transfered when opening swap. It includes the collateral, fees and desposits. /// @dev The amount is represented in 18 decimals regardless of the decimals of the asset. uint256 wadTotalAmount; /// @notice Swap's collateral. uint256 collateral; /// @notice Swap's notional amount. uint256 notional; /// @notice The part of the opening fee that will be added to the liquidity pool balance. uint256 openingFeeLPAmount; /// @notice Part of the opening fee that will be added to the treasury balance. uint256 openingFeeTreasuryAmount; /// @notice Amount of asset set aside for the oracle subsidization. uint256 iporPublicationFeeAmount; /// @notice Refundable deposit blocked for the entity that will close the swap. /// For more information on how the liquidations work refer to the documentation. /// https://ipor-labs.gitbook.io/ipor-labs/automated-market-maker/liquidations /// @dev value represented without decimals, as an integer uint256 liquidationDepositAmount; /// @notice The struct describing the IPOR and its params calculated for the time when it was most recently updated and the change that took place since the update. /// Namely, the interest that would be computed into IBT should the rebalance occur. IporTypes.AccruedIpor accruedIpor; } } // File: contracts/interfaces/IMiltonSpreadModel.sol pragma solidity 0.8.16; /// @title Interface for interaction with Milton Spread Model smart contract. interface IMiltonSpreadModel { /// @notice Calculates the quote for Pay-Fixed leg. /// @param accruedIpor - interest accrued by IPOR at the moment of calculation /// @param accruedBalance - Milton balance including Stanley's interest and collateral if present /// @return quoteValue calculated quote for Pay Fixed leg function calculateQuotePayFixed( IporTypes.AccruedIpor memory accruedIpor, IporTypes.MiltonBalancesMemory memory accruedBalance ) external view returns (uint256 quoteValue); /// @notice Calculates the quote for Receive-Fixed leg. /// @param accruedIpor - accrued IPOR at moment of calculation /// @param accruedBalance - Milton's balance including Stanley's interest and collateral if present /// @return quoteValue calculated quote for Receive-Fixed leg function calculateQuoteReceiveFixed( IporTypes.AccruedIpor memory accruedIpor, IporTypes.MiltonBalancesMemory memory accruedBalance ) external view returns (uint256 quoteValue); /// @notice Calculates the spread for Pay-Fixed leg. /// @param accruedIpor - interest accrued by IPOR at the moment of calculation /// @param accruedBalance - Milton's balance including Stanley's interest and collateral if present /// @return spreadValue calculated spread for Pay-Fixed leg function calculateSpreadPayFixed( IporTypes.AccruedIpor memory accruedIpor, IporTypes.MiltonBalancesMemory memory accruedBalance ) external view returns (int256 spreadValue); /// @notice Calculates the spread for Receive-Fixed leg. /// @param accruedIpor - interest accrued by IPOR at the moment of calculation /// @param accruedBalance - Milton's balance including Stanley's interest and collateral if present /// @return spreadValue calculated spread for Receive-Fixed leg function calculateSpreadReceiveFixed( IporTypes.AccruedIpor memory accruedIpor, IporTypes.MiltonBalancesMemory memory accruedBalance ) external view returns (int256 spreadValue); } // File: contracts/interfaces/types/MiltonTypes.sol pragma solidity 0.8.16; /// @title Structs used in Milton smart contract library MiltonTypes { /// @notice Swap direction (long = Pay Fixed and Receive a Floating or short = receive fixed and pay a floating) enum SwapDirection { /// @notice When taking the "long" position the trader will pay a fixed rate and receive a floating rate. /// for more information refer to the documentation https://ipor-labs.gitbook.io/ipor-labs/automated-market-maker/ipor-swaps PAY_FIXED_RECEIVE_FLOATING, /// @notice When taking the "short" position the trader will pay a floating rate and receive a fixed rate. PAY_FLOATING_RECEIVE_FIXED } /// @notice Collection of swap attributes connected with IPOR Index /// @dev all values are in 18 decimals struct IporSwapIndicator { /// @notice IPOR Index value at the time of swap opening uint256 iporIndexValue; /// @notice IPOR Interest Bearing Token (IBT) price at the time of swap opening uint256 ibtPrice; /// @notice Swap's notional denominated in IBT uint256 ibtQuantity; /// @notice Fixed interest rate at which the position has been opened, /// it is quote from spread documentation uint256 fixedInterestRate; } /// @notice Structure describes one swap processed by closeSwaps method, information about swap ID and flag if this swap was closed during execution closeSwaps method. struct IporSwapClosingResult { /// @notice Swap ID uint256 swapId; /// @notice Flag describe if swap was closed during this execution bool closed; } } // File: contracts/interfaces/IIporOracle.sol pragma solidity 0.8.16; /// @title Interface for interaction with IporOracle, smart contract responsible for managing IPOR Index. interface IIporOracle { /// @notice Returns current version of IporOracle's /// @dev Increase number when implementation inside source code is different that implementation deployed on Mainnet /// @return current IporOracle version function getVersion() external pure returns (uint256); /// @notice Gets IPOR Index indicators for a given asset /// @dev all returned values represented in 18 decimals /// @param asset underlying / stablecoin address supported in Ipor Protocol /// @return value IPOR Index value for a given asset /// @return ibtPrice Interest Bearing Token Price for a given IPOR Index /// @return exponentialMovingAverage Exponential moving average for a given IPOR Index /// @return exponentialWeightedMovingVariance Exponential weighted movien variance for a given IPOR Index /// @return lastUpdateTimestamp Last IPOR Index update done by Charlie off-chain service function getIndex(address asset) external view returns ( uint256 value, uint256 ibtPrice, uint256 exponentialMovingAverage, uint256 exponentialWeightedMovingVariance, uint256 lastUpdateTimestamp ); /// @notice Gets accrued IPOR Index indicators for a given timestamp and asset . /// @param calculateTimestamp time of accrued IPOR Index calculation /// @param asset underlying / stablecoin address supported by IPOR Protocol. /// @return accruedIpor structure {IporTypes.AccruedIpor} function getAccruedIndex(uint256 calculateTimestamp, address asset) external view returns (IporTypes.AccruedIpor memory accruedIpor); /// @notice Calculates accrued Interest Bearing Token price for a given asset and timestamp. /// @param asset underlying / stablecoin address supported by IPOR Protocol. /// @param calculateTimestamp time of accrued Interest Bearing Token price calculation /// @return accrued IBT price, represented in 18 decimals function calculateAccruedIbtPrice(address asset, uint256 calculateTimestamp) external view returns (uint256); /// @notice Updates IPOR Index for a given asset. Function available only for Updater /// @dev Emmits {IporIndexUpdate} event. /// @param asset underlying / stablecoin address supported by IPOR Protocol /// @param indexValue new IPOR Index value represented in 18 decimals function updateIndex(address asset, uint256 indexValue) external; /// @notice Updates IPOR indexes for a given assets. Function available only for Updater /// @dev Emmits {IporIndexUpdate} event. /// @param assets underlying / stablecoin addresses supported by IPOR Protocol /// @param indexValues new IPOR Index values function updateIndexes(address[] memory assets, uint256[] memory indexValues) external; /// @notice Adds new Updater. Updater has right to update IPOR Index. Function available only for Owner. /// @param newUpdater new updater address function addUpdater(address newUpdater) external; /// @notice Removes Updater. Function available only for Owner. /// @param updater updater address function removeUpdater(address updater) external; /// @notice Checks if given account is an Updater. /// @param account account for checking /// @return 0 if account is not updater, 1 if account is updater. function isUpdater(address account) external view returns (uint256); /// @notice Adds new asset which IPOR Protocol will support. Function available only for Owner. /// @param newAsset new asset address /// @param updateTimestamp Time for which exponential moving average and exponential weighted moving variance was calculated /// @param exponentialMovingAverage initial Exponential Moving Average for this asset /// @param exponentialWeightedMovingVariance initial Exponential Weighted Moving Variance for asset. function addAsset( address newAsset, uint256 updateTimestamp, uint256 exponentialMovingAverage, uint256 exponentialWeightedMovingVariance ) external; /// @notice Removes asset which IPOR Protocol will not support. Function available only for Owner. /// @param asset underlying / stablecoin address which currenlty is supported by IPOR Protocol. function removeAsset(address asset) external; /// @notice Pauses current smart contract, it can be executed only by the Owner /// @dev Emits {Paused} event from IporOracle. function pause() external; /// @notice Unpauses current smart contract, it can be executed only by the Owner /// @dev Emits {Unpaused} event from IporOracle. function unpause() external; /// @notice Emmited when Charlie update IPOR Index. /// @param asset underlying / stablecoin address /// @param indexValue IPOR Index value represented in 18 decimals /// @param quasiIbtPrice quasi Interest Bearing Token price represented in 18 decimals. /// @param exponentialMovingAverage Exponential Moving Average represented in 18 decimals. /// @param exponentialWeightedMovingVariance Exponential Weighted Moving Variance /// @param updateTimestamp moment when IPOR Index was updated. event IporIndexUpdate( address asset, uint256 indexValue, uint256 quasiIbtPrice, uint256 exponentialMovingAverage, uint256 exponentialWeightedMovingVariance, uint256 updateTimestamp ); /// @notice event emitted when IPOR Index Updater is added by Owner /// @param newUpdater new Updater address event IporIndexAddUpdater(address newUpdater); /// @notice event emitted when IPOR Index Updater is removed by Owner /// @param updater updater address event IporIndexRemoveUpdater(address updater); /// @notice event emitted when new asset is added by Owner to list of assets supported in IPOR Protocol. /// @param newAsset new asset address /// @param updateTimestamp update timestamp /// @param exponentialMovingAverage Exponential Moving Average for asset /// @param exponentialWeightedMovingVariance Exponential Weighted Moving Variance for asset event IporIndexAddAsset( address newAsset, uint256 updateTimestamp, uint256 exponentialMovingAverage, uint256 exponentialWeightedMovingVariance ); /// @notice event emitted when asset is removed by Owner from list of assets supported in IPOR Protocol. /// @param asset asset address event IporIndexRemoveAsset(address asset); } // File: contracts/libraries/math/IporMath.sol pragma solidity 0.8.16; library IporMath { //@notice Division with rounding up on last position, x, and y is with MD function division(uint256 x, uint256 y) internal pure returns (uint256 z) { z = (x + (y / 2)) / y; } function divisionInt(int256 x, int256 y) internal pure returns (int256 z) { z = (x + (y / 2)) / y; } function divisionWithoutRound(uint256 x, uint256 y) internal pure returns (uint256 z) { z = x / y; } function convertWadToAssetDecimals(uint256 value, uint256 assetDecimals) internal pure returns (uint256) { if (assetDecimals == 18) { return value; } else if (assetDecimals > 18) { return value * 10**(assetDecimals - 18); } else { return division(value, 10**(18 - assetDecimals)); } } function convertWadToAssetDecimalsWithoutRound(uint256 value, uint256 assetDecimals) internal pure returns (uint256) { if (assetDecimals == 18) { return value; } else if (assetDecimals > 18) { return value * 10**(assetDecimals - 18); } else { return divisionWithoutRound(value, 10**(18 - assetDecimals)); } } function convertToWad(uint256 value, uint256 assetDecimals) internal pure returns (uint256) { if (value > 0) { if (assetDecimals == 18) { return value; } else if (assetDecimals > 18) { return division(value, 10**(assetDecimals - 18)); } else { return value * 10**(18 - assetDecimals); } } else { return value; } } function absoluteValue(int256 value) internal pure returns (uint256) { return (uint256)(value < 0 ? -value : value); } function percentOf(uint256 value, uint256 rate) internal pure returns (uint256) { return division(value * rate, 1e18); } } // File: contracts/amm/libraries/IporSwapLogic.sol pragma solidity 0.8.16; library IporSwapLogic { using SafeCast for uint256; /// @param totalAmount total amount represented in 18 decimals /// @param leverage swap leverage, represented in 18 decimals /// @param liquidationDepositAmount liquidation deposit amount, represented in 18 decimals /// @param iporPublicationFeeAmount IPOR publication fee amount, represented in 18 decimals /// @param openingFeeRate opening fee rate, represented in 18 decimals function calculateSwapAmount( uint256 totalAmount, uint256 leverage, uint256 liquidationDepositAmount, uint256 iporPublicationFeeAmount, uint256 openingFeeRate ) internal pure returns ( uint256 collateral, uint256 notional, uint256 openingFee ) { collateral = IporMath.division( (totalAmount - liquidationDepositAmount - iporPublicationFeeAmount) * Constants.D18, Constants.D18 + openingFeeRate ); notional = IporMath.division(leverage * collateral, Constants.D18); openingFee = IporMath.division(collateral * openingFeeRate, Constants.D18); } function calculatePayoffPayFixed( IporTypes.IporSwapMemory memory swap, uint256 closingTimestamp, uint256 mdIbtPrice ) internal pure returns (int256 swapValue) { (uint256 quasiIFixed, uint256 quasiIFloating) = calculateQuasiInterest( swap, closingTimestamp, mdIbtPrice ); swapValue = _normalizeSwapValue( swap.collateral, IporMath.divisionInt( quasiIFloating.toInt256() - quasiIFixed.toInt256(), Constants.WAD_YEAR_IN_SECONDS_INT ) ); } function calculatePayoffReceiveFixed( IporTypes.IporSwapMemory memory swap, uint256 closingTimestamp, uint256 mdIbtPrice ) internal pure returns (int256 swapValue) { (uint256 quasiIFixed, uint256 quasiIFloating) = calculateQuasiInterest( swap, closingTimestamp, mdIbtPrice ); swapValue = _normalizeSwapValue( swap.collateral, IporMath.divisionInt( quasiIFixed.toInt256() - quasiIFloating.toInt256(), Constants.WAD_YEAR_IN_SECONDS_INT ) ); } /// @notice Calculates interests fixed and floating without division by Constants.D18 * Constants.YEAR_IN_SECONDS function calculateQuasiInterest( IporTypes.IporSwapMemory memory swap, uint256 closingTimestamp, uint256 mdIbtPrice ) internal pure returns (uint256 quasiIFixed, uint256 quasiIFloating) { require( closingTimestamp >= swap.openTimestamp, MiltonErrors.CLOSING_TIMESTAMP_LOWER_THAN_SWAP_OPEN_TIMESTAMP ); quasiIFixed = calculateQuasiInterestFixed( swap.notional, swap.fixedInterestRate, closingTimestamp - swap.openTimestamp ); quasiIFloating = calculateQuasiInterestFloating(swap.ibtQuantity, mdIbtPrice); } /// @notice Calculates interest fixed without division by Constants.D18 * Constants.YEAR_IN_SECONDS function calculateQuasiInterestFixed( uint256 notional, uint256 swapFixedInterestRate, uint256 swapPeriodInSeconds ) internal pure returns (uint256) { return notional * Constants.WAD_YEAR_IN_SECONDS + notional * swapFixedInterestRate * swapPeriodInSeconds; } /// @notice Calculates interest floating without division by Constants.D18 * Constants.YEAR_IN_SECONDS function calculateQuasiInterestFloating(uint256 ibtQuantity, uint256 ibtCurrentPrice) internal pure returns (uint256) { //IBTQ * IBTPtc (IBTPtc - interest bearing token price in time when swap is closed) return ibtQuantity * ibtCurrentPrice * Constants.YEAR_IN_SECONDS; } function _normalizeSwapValue(uint256 collateral, int256 swapValue) private pure returns (int256) { int256 intCollateral = collateral.toInt256(); if (swapValue > 0) { if (swapValue < intCollateral) { return swapValue; } else { return intCollateral; } } else { if (swapValue < -intCollateral) { return -intCollateral; } else { return swapValue; } } } } // File: contracts/interfaces/types/AmmTypes.sol pragma solidity 0.8.16; /// @title Types used in interfaces strictly related to AMM (Automated Market Maker). /// @dev Used by IMilton and IMiltonStorage interfaces. library AmmTypes { /// @notice enum describing Swap's state, ACTIVE - when the swap is opened, INACTIVE when it's closed enum SwapState { INACTIVE, ACTIVE } /// @notice Structure which represents Swap's data that will be saved in the storage. /// Refer to the documentation https://ipor-labs.gitbook.io/ipor-labs/automated-market-maker/ipor-swaps for more information. struct NewSwap { /// @notice Account / trader who opens the Swap address buyer; /// @notice Epoch timestamp of when position was opened by the trader. uint256 openTimestamp; /// @notice Swap's collateral amount. /// @dev value represented in 18 decimals uint256 collateral; /// @notice Swap's notional amount. /// @dev value represented in 18 decimals uint256 notional; /// @notice Quantity of Interest Bearing Token (IBT) at moment when position was opened. /// @dev value represented in 18 decimals uint256 ibtQuantity; /// @notice Fixed interest rate at which the position has been opened. /// @dev value represented in 18 decimals uint256 fixedInterestRate; /// @notice Liquidation deposit is retained when the swap is opened. It is then paid back to agent who closes the derivative at maturity. /// It can be both trader or community member. Trader receives the deposit back when he chooses to close the derivative before maturity. /// @dev value represented in 18 decimals uint256 liquidationDepositAmount; /// @notice Opening fee amount part which is allocated in Liquidity Pool Balance. This fee is calculated as a rate of the swap's collateral. /// @dev value represented in 18 decimals uint256 openingFeeLPAmount; /// @notice Opening fee amount part which is allocated in Treasury Balance. This fee is calculated as a rate of the swap's collateral. /// @dev value represented in 18 decimals uint256 openingFeeTreasuryAmount; } /// @notice Struct representing assets (ie. stablecoin) related to Swap that is presently being opened. /// @dev all values represented in 18 decimals struct OpenSwapMoney { /// @notice Total Amount of asset that is sent from buyer to Milton when opening swap. uint256 totalAmount; /// @notice Swap's collateral uint256 collateral; /// @notice Swap's notional uint256 notional; /// @notice Opening Fee - part allocated as a profit of the Liquidity Pool uint256 openingFeeLPAmount; /// @notice Part of the fee set aside for subsidizing the oracle that publishes IPOR rate. Flat fee set by the DAO. /// @notice Opening Fee - part allocated in Treasury balance. Part of the fee set asside for subsidising the oracle that publishes IPOR rate. Flat fee set by the DAO. uint256 openingFeeTreasuryAmount; /// @notice Fee set aside for subsidizing the oracle that publishes IPOR rate. Flat fee set by the DAO. uint256 iporPublicationFee; /// @notice Liquidation deposit is retained when the swap is opened. Value represented in 18 decimals. uint256 liquidationDepositAmount; } } // File: contracts/amm/libraries/types/AmmMiltonStorageTypes.sol pragma solidity 0.8.16; /// @notice Structs used in the MiltonStorage interface library AmmMiltonStorageTypes { struct IporSwap { /// @notice Swap's ID uint32 id; /// @notice Address of swap's Buyer address buyer; /// @notice Starting EPOCH timestamp of this swap. uint32 openTimestamp; /// @notice Index position of this Swap in an array of swaps' identification associated to swap's buyer /// @dev Field used for gas optimization purposes, it allows for quick removal by id in the array. /// During removal the last item in the array is switched with the one that just has been removed. uint32 idsIndex; /// @notice Swap's collateral /// @dev value represented in 18 decimals uint128 collateral; /// @notice Swap's notional amount /// @dev value represented in 18 decimals uint128 notional; /// @notice Swap's notional amount denominated in the Interest Bearing Token (IBT) /// @dev value represented in 18 decimals uint128 ibtQuantity; /// @notice Fixed interest rate at which the position has been opened /// @dev value represented in 18 decimals uint64 fixedInterestRate; /// @notice Liquidation deposit amount /// @dev value represented WITHOUT decimals uint32 liquidationDepositAmount; /// @notice State of the swap /// @dev 0 - INACTIVE, 1 - ACTIVE AmmTypes.SwapState state; } /// @notice All active swaps available in Milton with information on swaps belong to the account. /// It describes swaps for a given leg. struct IporSwapContainer { /// @notice Swap details, key in the map is a swapId mapping(uint32 => IporSwap) swaps; /// @notice List of swap IDs for every account, key in the list is the account's address, and the value is a list of swap IDs mapping(address => uint32[]) ids; } /// @notice A struct containing balances that Milton keeps track of. It acts as a Milton's accounting book. /// Those balances are used in various calculations across the protocol. /// @dev All balances are in 18 decimals struct Balances { /// @notice Sum of all collateral put forward by the derivative buyer's on Pay Fixed & Receive Floating leg. uint128 totalCollateralPayFixed; /// @notice Sum of all collateral put forward by the derivative buyer's on Pay Floating & Receive Fixed leg. uint128 totalCollateralReceiveFixed; /// @notice Liquidity Pool Balance. This balance is where the liquidity from liquidity providers and the opening fee are accounted for, /// @dev Amount of opening fee accounted in this balance is defined by _OPENING_FEE_FOR_TREASURY_PORTION_RATE param. uint128 liquidityPool; /// @notice Stanley's current balance. It includes interest accrued until Stanley's most recent state change. uint128 vault; /// @notice This balance is used to track the funds accounted for IporOracle subsidization. uint128 iporPublicationFee; /// @notice Tresury is the balance that belongs to IPOR DAO and funds up to this amount can be transfered to the DAO-appinted multi-sig wallet. /// this ballance is fed by the income fee and part of the opening fee appointed by the DAO. For more information refer to the documentation: /// https://ipor-labs.gitbook.io/ipor-labs/automated-market-maker/ipor-swaps#fees uint128 treasury; } /// @notice A struct with parameters required to calculate SOAP for pay fixed and receive fixed legs. /// @dev Saved to the databse. struct SoapIndicators { /// @notice Value of interest accrued on a fixed leg of all derivatives for this particular type of swap. /// @dev Value without division by D36 * Constants.YEAR_IN_SECONDS. Is represented in 18 decimals. uint256 quasiHypotheticalInterestCumulative; /// @notice Sum of all swaps' notional amounts for a given leg. /// @dev Is represented in 18 decimals. uint128 totalNotional; /// @notice Sum of all IBTs on a given leg. /// @dev Is represented in 18 decimals. uint128 totalIbtQuantity; /// @notice The notional-weighted average interest rate of all swaps on a given leg combined. /// @dev Is represented in 18 decimals. uint64 averageInterestRate; /// @notice EPOCH timestamp of when the most recent rebalancing took place uint32 rebalanceTimestamp; } /// @notice A struct with parameters required to calculate SOAP for pay fixed and receive fixed legs. /// @dev Committed to the memory. struct SoapIndicatorsMemory { /// @notice Value of interest accrued on a fixed leg of all derivatives for this particular type of swap. /// @dev Value without division by D36 * Constants.YEAR_IN_SECONDS. Is represented in 18 decimals. uint256 quasiHypotheticalInterestCumulative; /// @notice Sum of all swaps' notional amounts for a given leg. /// @dev Is represented in 18 decimals. uint256 totalNotional; /// @notice Sum of all IBTs on a given leg. /// @dev Is represented in 18 decimals. uint256 totalIbtQuantity; /// @notice The notional-weighted average interest rate of all swaps on a given leg combined. /// @dev Is represented in 18 decimals. uint256 averageInterestRate; /// @notice EPOCH timestamp of when the most recent rebalancing took place uint256 rebalanceTimestamp; } } // File: contracts/amm/libraries/SoapIndicatorLogic.sol pragma solidity 0.8.16; library SoapIndicatorLogic { using SafeCast for uint256; function calculateQuasiSoapPayFixed( AmmMiltonStorageTypes.SoapIndicatorsMemory memory si, uint256 calculateTimestamp, uint256 ibtPrice ) internal pure returns (int256) { return (si.totalIbtQuantity * ibtPrice * Constants.WAD_YEAR_IN_SECONDS).toInt256() - (si.totalNotional * Constants.WAD_P2_YEAR_IN_SECONDS + calculateQuasiHyphoteticalInterestTotal(si, calculateTimestamp)).toInt256(); } /// @notice For highest precision there is no division by D18 * D18 * Constants.YEAR_IN_SECONDS function calculateQuasiSoapReceiveFixed( AmmMiltonStorageTypes.SoapIndicatorsMemory memory si, uint256 calculateTimestamp, uint256 ibtPrice ) internal pure returns (int256) { return (si.totalNotional * Constants.WAD_P2_YEAR_IN_SECONDS + calculateQuasiHyphoteticalInterestTotal(si, calculateTimestamp)).toInt256() - (si.totalIbtQuantity * ibtPrice * Constants.WAD_YEAR_IN_SECONDS).toInt256(); } function rebalanceWhenOpenSwap( AmmMiltonStorageTypes.SoapIndicatorsMemory memory si, uint256 rebalanceTimestamp, uint256 derivativeNotional, uint256 swapFixedInterestRate, uint256 derivativeIbtQuantity ) internal pure returns (AmmMiltonStorageTypes.SoapIndicatorsMemory memory) { uint256 averageInterestRate = calculateAverageInterestRateWhenOpenSwap( si.totalNotional, si.averageInterestRate, derivativeNotional, swapFixedInterestRate ); uint256 quasiHypotheticalInterestTotal = calculateQuasiHyphoteticalInterestTotal( si, rebalanceTimestamp ); si.rebalanceTimestamp = rebalanceTimestamp; si.totalNotional = si.totalNotional + derivativeNotional; si.totalIbtQuantity = si.totalIbtQuantity + derivativeIbtQuantity; si.averageInterestRate = averageInterestRate; si.quasiHypotheticalInterestCumulative = quasiHypotheticalInterestTotal; return si; } function rebalanceWhenCloseSwap( AmmMiltonStorageTypes.SoapIndicatorsMemory memory si, uint256 rebalanceTimestamp, uint256 derivativeOpenTimestamp, uint256 derivativeNotional, uint256 swapFixedInterestRate, uint256 derivativeIbtQuantity ) internal pure returns (AmmMiltonStorageTypes.SoapIndicatorsMemory memory) { uint256 newAverageInterestRate = calculateAverageInterestRateWhenCloseSwap( si.totalNotional, si.averageInterestRate, derivativeNotional, swapFixedInterestRate ); if (newAverageInterestRate > 0) { uint256 currentQuasiHypoteticalInterestTotal = calculateQuasiHyphoteticalInterestTotal( si, rebalanceTimestamp ); uint256 quasiInterestPaidOut = calculateQuasiInterestPaidOut( rebalanceTimestamp, derivativeOpenTimestamp, derivativeNotional, swapFixedInterestRate ); uint256 quasiHypotheticalInterestTotal = currentQuasiHypoteticalInterestTotal - quasiInterestPaidOut; si.rebalanceTimestamp = rebalanceTimestamp; si.quasiHypotheticalInterestCumulative = quasiHypotheticalInterestTotal; si.totalNotional = si.totalNotional - derivativeNotional; si.totalIbtQuantity = si.totalIbtQuantity - derivativeIbtQuantity; si.averageInterestRate = newAverageInterestRate; } else { /// @dev when newAverageInterestRate = 0 it means in IPOR Protocol is closing the LAST derivative on this leg. si.rebalanceTimestamp = rebalanceTimestamp; si.quasiHypotheticalInterestCumulative = 0; si.totalNotional = 0; si.totalIbtQuantity = 0; si.averageInterestRate = 0; } return si; } function calculateQuasiInterestPaidOut( uint256 calculateTimestamp, uint256 derivativeOpenTimestamp, uint256 derivativeNotional, uint256 swapFixedInterestRate ) internal pure returns (uint256) { require( calculateTimestamp >= derivativeOpenTimestamp, MiltonErrors.CALC_TIMESTAMP_LOWER_THAN_SWAP_OPEN_TIMESTAMP ); return derivativeNotional * swapFixedInterestRate * (calculateTimestamp - derivativeOpenTimestamp) * Constants.D18; } function calculateQuasiHyphoteticalInterestTotal( AmmMiltonStorageTypes.SoapIndicatorsMemory memory si, uint256 calculateTimestamp ) internal pure returns (uint256) { return si.quasiHypotheticalInterestCumulative + calculateQuasiHypotheticalInterestDelta( calculateTimestamp, si.rebalanceTimestamp, si.totalNotional, si.averageInterestRate ); } /// @dev division by Constants.YEAR_IN_SECONDS * 1e36 postponed at the end of calculation function calculateQuasiHypotheticalInterestDelta( uint256 calculateTimestamp, uint256 lastRebalanceTimestamp, uint256 totalNotional, uint256 averageInterestRate ) internal pure returns (uint256) { require( calculateTimestamp >= lastRebalanceTimestamp, MiltonErrors.CALC_TIMESTAMP_LOWER_THAN_SOAP_REBALANCE_TIMESTAMP ); return totalNotional * averageInterestRate * (calculateTimestamp - lastRebalanceTimestamp) * Constants.D18; } function calculateAverageInterestRateWhenOpenSwap( uint256 totalNotional, uint256 averageInterestRate, uint256 derivativeNotional, uint256 swapFixedInterestRate ) internal pure returns (uint256) { return IporMath.division( (totalNotional * averageInterestRate + derivativeNotional * swapFixedInterestRate), (totalNotional + derivativeNotional) ); } function calculateAverageInterestRateWhenCloseSwap( uint256 totalNotional, uint256 averageInterestRate, uint256 derivativeNotional, uint256 swapFixedInterestRate ) internal pure returns (uint256) { require( derivativeNotional <= totalNotional, MiltonErrors.SWAP_NOTIONAL_HIGHER_THAN_TOTAL_NOTIONAL ); if (derivativeNotional == totalNotional) { return 0; } else { return IporMath.division( (totalNotional * averageInterestRate - derivativeNotional * swapFixedInterestRate), (totalNotional - derivativeNotional) ); } } } // File: contracts/interfaces/IMiltonStorage.sol pragma solidity 0.8.16; /// @title Interface for interaction with Milton Storage smart contract, reposnsible for managing AMM storage. interface IMiltonStorage { /// @notice Returns current version of Milton Storage /// @dev Increase number when implementation inside source code is different that implementation deployed on Mainnet /// @return current Milton Storage version, integer function getVersion() external pure returns (uint256); /// @notice Gets last swap ID. /// @dev swap ID is incremented when new position is opened, last swap ID is used in Pay Fixed and Receive Fixed swaps. /// @return last swap ID, integer function getLastSwapId() external view returns (uint256); /// @notice Gets balance struct /// @dev Balance contains: /// # Pay Fixed Total Collateral /// # Receive Fixed Total Collateral /// # Liquidity Pool and Vault balances. /// @return balance structure {IporTypes.MiltonBalancesMemory} function getBalance() external view returns (IporTypes.MiltonBalancesMemory memory); /// @notice Gets balance with extended information: IPOR publication fee balance and Treasury balance. /// @return balance structure {MiltonStorageTypes.ExtendedBalancesMemory} function getExtendedBalance() external view returns (MiltonStorageTypes.ExtendedBalancesMemory memory); /// @notice Gets total outstanding notional. /// @return totalNotionalPayFixed Sum of notional amount of all swaps for Pay-Fixed leg, represented in 18 decimals /// @return totalNotionalReceiveFixed Sum of notional amount of all swaps for Receive-Fixed leg, represented in 18 decimals function getTotalOutstandingNotional() external view returns (uint256 totalNotionalPayFixed, uint256 totalNotionalReceiveFixed); /// @notice Gets Pay-Fixed swap for a given swap ID /// @param swapId swap ID. /// @return swap structure {IporTypes.IporSwapMemory} function getSwapPayFixed(uint256 swapId) external view returns (IporTypes.IporSwapMemory memory); /// @notice Gets Receive-Fixed swap for a given swap ID /// @param swapId swap ID. /// @return swap structure {IporTypes.IporSwapMemory} function getSwapReceiveFixed(uint256 swapId) external view returns (IporTypes.IporSwapMemory memory); /// @notice Gets active Pay-Fixed swaps for a given account address. /// @param account account address /// @param offset offset for paging /// @param chunkSize page size for paging /// @return totalCount total number of active Pay-Fixed swaps /// @return swaps array where each element has structure {IporTypes.IporSwapMemory} function getSwapsPayFixed( address account, uint256 offset, uint256 chunkSize ) external view returns (uint256 totalCount, IporTypes.IporSwapMemory[] memory swaps); /// @notice Gets active Receive-Fixed swaps for a given account address. /// @param account account address /// @param offset offset for paging /// @param chunkSize page size for paging /// @return totalCount total number of active Receive Fixed swaps /// @return swaps array where each element has structure {IporTypes.IporSwapMemory} function getSwapsReceiveFixed( address account, uint256 offset, uint256 chunkSize ) external view returns (uint256 totalCount, IporTypes.IporSwapMemory[] memory swaps); /// @notice Gets active Pay-Fixed swaps IDs for a given account address. /// @param account account address /// @param offset offset for paging /// @param chunkSize page size for paging /// @return totalCount total number of active Pay-Fixed IDs /// @return ids list of IDs function getSwapPayFixedIds( address account, uint256 offset, uint256 chunkSize ) external view returns (uint256 totalCount, uint256[] memory ids); /// @notice Gets active Receive-Fixed swaps IDs for a given account address. /// @param account account address /// @param offset offset for paging /// @param chunkSize page size for paging /// @return totalCount total number of active Receive-Fixed IDs /// @return ids list of IDs function getSwapReceiveFixedIds( address account, uint256 offset, uint256 chunkSize ) external view returns (uint256 totalCount, uint256[] memory ids); /// @notice Gets active Pay-Fixed and Receive-Fixed swaps IDs for a given account address. /// @param account account address /// @param offset offset for paging /// @param chunkSize page size for paging /// @return totalCount total number of active Pay-Fixed and Receive-Fixed IDs. /// @return ids array where each element has structure {MiltonStorageTypes.IporSwapId} function getSwapIds( address account, uint256 offset, uint256 chunkSize ) external view returns (uint256 totalCount, MiltonStorageTypes.IporSwapId[] memory ids); /// @notice Calculates SOAP for a given IBT price and timestamp. For more information refer to the documentation: https://ipor-labs.gitbook.io/ipor-labs/automated-market-maker/soap /// @param ibtPrice IBT (Interest Bearing Token) price /// @param calculateTimestamp epoch timestamp, the time for which SOAP is calculated /// @return soapPayFixed SOAP for Pay-Fixed and Receive-Floating leg, represented in 18 decimals /// @return soapReceiveFixed SOAP for Receive-Fixed and Pay-Floating leg, represented in 18 decimals /// @return soap Sum of SOAP for Pay-Fixed leg and Receive-Fixed leg , represented in 18 decimals function calculateSoap(uint256 ibtPrice, uint256 calculateTimestamp) external view returns ( int256 soapPayFixed, int256 soapReceiveFixed, int256 soap ); /// @notice Calculates SOAP for Pay-Fixed leg at given IBT price and time. /// @param ibtPrice IBT (Interest Bearing Token) price /// @param calculateTimestamp epoch timestamp, the time for which SOAP is calculated /// @return soapPayFixed SOAP for Pay-Fixed leg, represented in 18 decimals function calculateSoapPayFixed(uint256 ibtPrice, uint256 calculateTimestamp) external view returns (int256 soapPayFixed); /// @notice Calculates SOAP for Receive-Fixed leg at given IBT price and time. /// @param ibtPrice IBT (Interest Bearing Token) price /// @param calculateTimestamp epoch timestamp, the time for which SOAP is calculated /// @return soapReceiveFixed SOAP for Receive-Fixed leg, represented in 18 decimals function calculateSoapReceiveFixed(uint256 ibtPrice, uint256 calculateTimestamp) external view returns (int256 soapReceiveFixed); /// @notice add liquidity to the Liquidity Pool. Function available only to Joseph. /// @param account account address who execute request for redeem asset amount /// @param assetAmount amount of asset added to balance of Liquidity Pool, represented in 18 decimals /// @param cfgMaxLiquidityPoolBalance max liquidity pool balance taken from Joseph configuration, represented in 18 decimals. /// @param cfgMaxLpAccountContribution max liquidity pool account contribution taken from Joseph configuration, represented in 18 decimals. function addLiquidity( address account, uint256 assetAmount, uint256 cfgMaxLiquidityPoolBalance, uint256 cfgMaxLpAccountContribution ) external; /// @notice subtract liquidity from the Liquidity Pool. Function available only to Joseph. /// @param assetAmount amount of asset subtracted from Liquidity Pool, represented in 18 decimals function subtractLiquidity(uint256 assetAmount) external; /// @notice Updates structures in storage: balance, swaps, SOAP indicators when new Pay-Fixed swap is opened. Function available only to Milton. /// @param newSwap new swap structure {AmmTypes.NewSwap} /// @param cfgIporPublicationFee publication fee amount taken from Milton configuration, represented in 18 decimals. /// @return new swap ID function updateStorageWhenOpenSwapPayFixed( AmmTypes.NewSwap memory newSwap, uint256 cfgIporPublicationFee ) external returns (uint256); /// @notice Updates structures in the storage: balance, swaps, SOAP indicators when new Receive-Fixed swap is opened. Function is only available to Milton. /// @param newSwap new swap structure {AmmTypes.NewSwap} /// @param cfgIporPublicationFee publication fee amount taken from Milton configuration, represented in 18 decimals. /// @return new swap ID function updateStorageWhenOpenSwapReceiveFixed( AmmTypes.NewSwap memory newSwap, uint256 cfgIporPublicationFee ) external returns (uint256); /// @notice Updates structures in the storage: balance, swaps, SOAP indicators when closing Pay-Fixed swap. Function is only available to Milton. /// @param liquidator account address that closes the swap /// @param iporSwap swap structure {IporTypes.IporSwapMemory} /// @param payoff amount that trader has earned or lost on the swap, represented in 18 decimals, it can be negative. /// @param closingTimestamp moment when the swap was closed /// @param cfgIncomeFeeRate income fee rate used to calculate the income fee deducted from trader profit payoff, configuration param represented in 18 decimals /// @param cfgMinLiquidationThresholdToCloseBeforeMaturity configuration param for closing swap validation, describes minimal change in /// position value required to close swap before maturity. Value represented in 18 decimals. /// @param cfgSecondsToMaturityWhenPositionCanBeClosed configuration param for closing swap validation, describes number of seconds before swap /// maturity after which swap can be closed by anybody not only by swap's buyer. function updateStorageWhenCloseSwapPayFixed( address liquidator, IporTypes.IporSwapMemory memory iporSwap, int256 payoff, uint256 closingTimestamp, uint256 cfgIncomeFeeRate, uint256 cfgMinLiquidationThresholdToCloseBeforeMaturity, uint256 cfgSecondsToMaturityWhenPositionCanBeClosed ) external; /// @notice Updates structures in the storage: balance, swaps, SOAP indicators when closing Receive-Fixed swap. /// Function is only available to Milton. /// @param liquidator address of account closing the swap /// @param iporSwap swap structure {IporTypes.IporSwapMemory} /// @param payoff amount that trader has earned or lost, represented in 18 decimals, can be negative. /// @param incomeFeeValue amount of fee calculated based on payoff. /// @param closingTimestamp moment when swap was closed /// @param cfgMinLiquidationThresholdToCloseBeforeMaturity configuration param for closing swap validation, describes minimal change in /// position value required to close swap before maturity. Value represented in 18 decimals. /// @param cfgSecondsToMaturityWhenPositionCanBeClosed configuration param for closing swap validation, describes number of seconds before swap /// maturity after which swap can be closed by anybody not only by swap's buyer. function updateStorageWhenCloseSwapReceiveFixed( address liquidator, IporTypes.IporSwapMemory memory iporSwap, int256 payoff, uint256 incomeFeeValue, uint256 closingTimestamp, uint256 cfgMinLiquidationThresholdToCloseBeforeMaturity, uint256 cfgSecondsToMaturityWhenPositionCanBeClosed ) external; /// @notice Updates the balance when Joseph withdraws Milton's assets from Stanley. Function is only available to Milton. /// @param withdrawnAmount asset amount that was withdrawn from Stanley to Milton by Joseph, represented in 18 decimals. /// @param vaultBalance Asset Management Vault (Stanley) balance, represented in 18 decimals function updateStorageWhenWithdrawFromStanley(uint256 withdrawnAmount, uint256 vaultBalance) external; /// @notice Updates the balance when Joseph deposits Milton's assets to Stanley. Function is only available to Milton. /// @param depositAmount asset amount deposited from Milton to Stanley by Joseph, represented in 18 decimals. /// @param vaultBalance actual Asset Management Vault(Stanley) balance , represented in 18 decimals function updateStorageWhenDepositToStanley(uint256 depositAmount, uint256 vaultBalance) external; /// @notice Updates the balance when Joseph transfers Milton's assets to Charlie Treasury's multisig wallet. Function is only available to Joseph. /// @param transferredAmount asset amount transferred to Charlie Treasury multisig wallet. function updateStorageWhenTransferToCharlieTreasury(uint256 transferredAmount) external; /// @notice Updates the balance when Joseph transfers Milton's assets to Treasury's multisig wallet. Function is only available to Joseph. /// @param transferredAmount asset amount transferred to Treasury's multisig wallet. function updateStorageWhenTransferToTreasury(uint256 transferredAmount) external; /// @notice Sets Milton's address. Function is only available to the smart contract Owner. /// @param milton Milton's address function setMilton(address milton) external; /// @notice Sets Joseph's address. Function is only available to smart contract Owner. /// @param joseph Joseph's address function setJoseph(address joseph) external; /// @notice Pauses current smart contract, it can be executed only by the Owner /// @dev Emits {Paused} event from Milton. function pause() external; /// @notice Unpauses current smart contract, it can be executed only by the Owner /// @dev Emits {Unpaused} event from Milton. function unpause() external; /// @notice Emmited when Milton address has changed by the smart contract Owner. /// @param changedBy account address that has changed Milton's address /// @param oldMilton old Milton's address /// @param newMilton new Milton's address event MiltonChanged(address changedBy, address oldMilton, address newMilton); /// @notice Emmited when Joseph address has been changed by smart contract Owner. /// @param changedBy account address that has changed Jospeh's address /// @param oldJoseph old Joseph's address /// @param newJoseph new Joseph's address event JosephChanged(address changedBy, address oldJoseph, address newJoseph); } // File: contracts/amm/MiltonStorage.sol pragma solidity 0.8.16; //@dev all stored valuse related with money are in 18 decimals. contract MiltonStorage is Initializable, PausableUpgradeable, UUPSUpgradeable, IporOwnableUpgradeable, IMiltonStorage { using SafeCast for uint256; using SoapIndicatorLogic for AmmMiltonStorageTypes.SoapIndicatorsMemory; uint32 private _lastSwapId; address private _milton; address private _joseph; AmmMiltonStorageTypes.Balances internal _balances; AmmMiltonStorageTypes.SoapIndicators internal _soapIndicatorsPayFixed; AmmMiltonStorageTypes.SoapIndicators internal _soapIndicatorsReceiveFixed; AmmMiltonStorageTypes.IporSwapContainer internal _swapsPayFixed; AmmMiltonStorageTypes.IporSwapContainer internal _swapsReceiveFixed; mapping(address => uint128) private _liquidityPoolAccountContribution; modifier onlyMilton() { require(_msgSender() == _milton, IporErrors.CALLER_NOT_MILTON); _; } modifier onlyJoseph() { require(_msgSender() == _joseph, MiltonErrors.CALLER_NOT_JOSEPH); _; } /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } function initialize() public initializer { __Pausable_init(); __Ownable_init(); __UUPSUpgradeable_init(); } function getVersion() external pure virtual override returns (uint256) { return 2; } function getLastSwapId() external view override returns (uint256) { return _lastSwapId; } function getBalance() external view virtual override returns (IporTypes.MiltonBalancesMemory memory) { return IporTypes.MiltonBalancesMemory( _balances.totalCollateralPayFixed, _balances.totalCollateralReceiveFixed, _balances.liquidityPool, _balances.vault ); } function getExtendedBalance() external view override returns (MiltonStorageTypes.ExtendedBalancesMemory memory) { return MiltonStorageTypes.ExtendedBalancesMemory( _balances.totalCollateralPayFixed, _balances.totalCollateralReceiveFixed, _balances.liquidityPool, _balances.vault, _balances.iporPublicationFee, _balances.treasury ); } function getTotalOutstandingNotional() external view override returns (uint256 totalNotionalPayFixed, uint256 totalNotionalReceiveFixed) { totalNotionalPayFixed = _soapIndicatorsPayFixed.totalNotional; totalNotionalReceiveFixed = _soapIndicatorsReceiveFixed.totalNotional; } function getSwapPayFixed(uint256 swapId) external view override returns (IporTypes.IporSwapMemory memory) { uint32 id = swapId.toUint32(); AmmMiltonStorageTypes.IporSwap storage swap = _swapsPayFixed.swaps[id]; return IporTypes.IporSwapMemory( swap.id, swap.buyer, swap.openTimestamp, swap.openTimestamp + Constants.SWAP_DEFAULT_PERIOD_IN_SECONDS, swap.idsIndex, swap.collateral, swap.notional, swap.ibtQuantity, swap.fixedInterestRate, swap.liquidationDepositAmount * Constants.D18, uint256(swap.state) ); } function getSwapReceiveFixed(uint256 swapId) external view override returns (IporTypes.IporSwapMemory memory) { uint32 id = swapId.toUint32(); AmmMiltonStorageTypes.IporSwap storage swap = _swapsReceiveFixed.swaps[id]; return IporTypes.IporSwapMemory( swap.id, swap.buyer, swap.openTimestamp, swap.openTimestamp + Constants.SWAP_DEFAULT_PERIOD_IN_SECONDS, swap.idsIndex, swap.collateral, swap.notional, swap.ibtQuantity, swap.fixedInterestRate, swap.liquidationDepositAmount * Constants.D18, uint256(swap.state) ); } function getSwapsPayFixed( address account, uint256 offset, uint256 chunkSize ) external view override returns (uint256 totalCount, IporTypes.IporSwapMemory[] memory swaps) { uint32[] storage ids = _swapsPayFixed.ids[account]; return (ids.length, _getPositions(_swapsPayFixed.swaps, ids, offset, chunkSize)); } function getSwapsReceiveFixed( address account, uint256 offset, uint256 chunkSize ) external view override returns (uint256 totalCount, IporTypes.IporSwapMemory[] memory swaps) { uint32[] storage ids = _swapsReceiveFixed.ids[account]; return (ids.length, _getPositions(_swapsReceiveFixed.swaps, ids, offset, chunkSize)); } function getSwapPayFixedIds( address account, uint256 offset, uint256 chunkSize ) external view override returns (uint256 totalCount, uint256[] memory ids) { require(chunkSize > 0, IporErrors.CHUNK_SIZE_EQUAL_ZERO); require(chunkSize <= Constants.MAX_CHUNK_SIZE, IporErrors.CHUNK_SIZE_TOO_BIG); uint32[] storage idsRef = _swapsPayFixed.ids[account]; totalCount = idsRef.length; uint256 resultSetSize = PaginationUtils.resolveResultSetSize(totalCount, offset, chunkSize); ids = new uint256[](resultSetSize); for (uint256 i = 0; i != resultSetSize; i++) { ids[i] = idsRef[offset + i]; } } function getSwapReceiveFixedIds( address account, uint256 offset, uint256 chunkSize ) external view override returns (uint256 totalCount, uint256[] memory ids) { require(chunkSize > 0, IporErrors.CHUNK_SIZE_EQUAL_ZERO); require(chunkSize <= Constants.MAX_CHUNK_SIZE, IporErrors.CHUNK_SIZE_TOO_BIG); uint32[] storage idsRef = _swapsReceiveFixed.ids[account]; totalCount = idsRef.length; uint256 resultSetSize = PaginationUtils.resolveResultSetSize(totalCount, offset, chunkSize); ids = new uint256[](resultSetSize); for (uint256 i = 0; i != resultSetSize; i++) { ids[i] = idsRef[offset + i]; } } function getSwapIds( address account, uint256 offset, uint256 chunkSize ) external view override returns (uint256 totalCount, MiltonStorageTypes.IporSwapId[] memory ids) { require(chunkSize > 0, IporErrors.CHUNK_SIZE_EQUAL_ZERO); require(chunkSize <= Constants.MAX_CHUNK_SIZE, IporErrors.CHUNK_SIZE_TOO_BIG); uint32[] storage payFixedIdsRef = _swapsPayFixed.ids[account]; uint256 payFixedLength = payFixedIdsRef.length; uint32[] storage receiveFixedIdsRef = _swapsReceiveFixed.ids[account]; uint256 receiveFixedLength = receiveFixedIdsRef.length; totalCount = payFixedLength + receiveFixedLength; uint256 resultSetSize = PaginationUtils.resolveResultSetSize(totalCount, offset, chunkSize); ids = new MiltonStorageTypes.IporSwapId[](resultSetSize); for (uint256 i = 0; i != resultSetSize; i++) { if (offset + i < payFixedLength) { ids[i] = MiltonStorageTypes.IporSwapId(payFixedIdsRef[offset + i], 0); } else { ids[i] = MiltonStorageTypes.IporSwapId( receiveFixedIdsRef[offset + i - payFixedLength], 1 ); } } } function calculateSoap(uint256 ibtPrice, uint256 calculateTimestamp) external view override returns ( int256 soapPayFixed, int256 soapReceiveFixed, int256 soap ) { (int256 qSoapPf, int256 qSoapRf, int256 qSoap) = _calculateQuasiSoap( ibtPrice, calculateTimestamp ); return ( soapPayFixed = IporMath.divisionInt(qSoapPf, Constants.WAD_P2_YEAR_IN_SECONDS_INT), soapReceiveFixed = IporMath.divisionInt(qSoapRf, Constants.WAD_P2_YEAR_IN_SECONDS_INT), soap = IporMath.divisionInt(qSoap, Constants.WAD_P2_YEAR_IN_SECONDS_INT) ); } function calculateSoapPayFixed(uint256 ibtPrice, uint256 calculateTimestamp) external view override returns (int256 soapPayFixed) { int256 qSoapPf = _calculateQuasiSoapPayFixed(ibtPrice, calculateTimestamp); soapPayFixed = IporMath.divisionInt(qSoapPf, Constants.WAD_P2_YEAR_IN_SECONDS_INT); } function calculateSoapReceiveFixed(uint256 ibtPrice, uint256 calculateTimestamp) external view override returns (int256 soapReceiveFixed) { int256 qSoapRf = _calculateQuasiSoapReceiveFixed(ibtPrice, calculateTimestamp); soapReceiveFixed = IporMath.divisionInt(qSoapRf, Constants.WAD_P2_YEAR_IN_SECONDS_INT); } function addLiquidity( address account, uint256 assetAmount, uint256 cfgMaxLiquidityPoolBalance, uint256 cfgMaxLpAccountContribution ) external override onlyJoseph { require(assetAmount > 0, MiltonErrors.DEPOSIT_AMOUNT_IS_TOO_LOW); uint128 newLiquidityPoolBalance = _balances.liquidityPool + assetAmount.toUint128(); require( newLiquidityPoolBalance <= cfgMaxLiquidityPoolBalance, MiltonErrors.LIQUIDITY_POOL_BALANCE_IS_TOO_HIGH ); uint128 newLiquidityPoolAccountContribution = _liquidityPoolAccountContribution[account] + assetAmount.toUint128(); require( newLiquidityPoolAccountContribution <= cfgMaxLpAccountContribution, MiltonErrors.LP_ACCOUNT_CONTRIBUTION_IS_TOO_HIGH ); _balances.liquidityPool = newLiquidityPoolBalance; _liquidityPoolAccountContribution[account] = newLiquidityPoolAccountContribution; } function subtractLiquidity(uint256 assetAmount) external override onlyJoseph { _balances.liquidityPool = _balances.liquidityPool - assetAmount.toUint128(); } function updateStorageWhenOpenSwapPayFixed( AmmTypes.NewSwap memory newSwap, uint256 cfgIporPublicationFee ) external override onlyMilton returns (uint256) { uint256 id = _updateSwapsWhenOpenPayFixed(newSwap); _updateBalancesWhenOpenSwapPayFixed( newSwap.collateral, newSwap.openingFeeLPAmount, newSwap.openingFeeTreasuryAmount, cfgIporPublicationFee ); _updateSoapIndicatorsWhenOpenSwapPayFixed( newSwap.openTimestamp, newSwap.notional, newSwap.fixedInterestRate, newSwap.ibtQuantity ); return id; } function updateStorageWhenOpenSwapReceiveFixed( AmmTypes.NewSwap memory newSwap, uint256 cfgIporPublicationFee ) external override onlyMilton returns (uint256) { uint256 id = _updateSwapsWhenOpenReceiveFixed(newSwap); _updateBalancesWhenOpenSwapReceiveFixed( newSwap.collateral, newSwap.openingFeeLPAmount, newSwap.openingFeeTreasuryAmount, cfgIporPublicationFee ); _updateSoapIndicatorsWhenOpenSwapReceiveFixed( newSwap.openTimestamp, newSwap.notional, newSwap.fixedInterestRate, newSwap.ibtQuantity ); return id; } function updateStorageWhenCloseSwapPayFixed( address liquidator, IporTypes.IporSwapMemory memory iporSwap, int256 payoff, uint256 incomeFeeValue, uint256 closingTimestamp, uint256 cfgMinLiquidationThresholdToCloseBeforeMaturity, uint256 cfgSecondsBeforeMaturityWhenPositionCanBeClosed ) external override onlyMilton { _updateSwapsWhenClosePayFixed(iporSwap); _updateBalancesWhenCloseSwapPayFixed( liquidator, iporSwap, payoff, incomeFeeValue, closingTimestamp, cfgMinLiquidationThresholdToCloseBeforeMaturity, cfgSecondsBeforeMaturityWhenPositionCanBeClosed ); _updateSoapIndicatorsWhenCloseSwapPayFixed(iporSwap, closingTimestamp); } function updateStorageWhenCloseSwapReceiveFixed( address liquidator, IporTypes.IporSwapMemory memory iporSwap, int256 payoff, uint256 incomeFeeValue, uint256 closingTimestamp, uint256 cfgMinLiquidationThresholdToCloseBeforeMaturity, uint256 cfgSecondsBeforeMaturityWhenPositionCanBeClosed ) external override onlyMilton { _updateSwapsWhenCloseReceiveFixed(iporSwap); _updateBalancesWhenCloseSwapReceiveFixed( liquidator, iporSwap, payoff, incomeFeeValue, closingTimestamp, cfgMinLiquidationThresholdToCloseBeforeMaturity, cfgSecondsBeforeMaturityWhenPositionCanBeClosed ); _updateSoapIndicatorsWhenCloseSwapReceiveFixed(iporSwap, closingTimestamp); } function updateStorageWhenWithdrawFromStanley(uint256 withdrawnAmount, uint256 vaultBalance) external override onlyMilton { uint256 currentVaultBalance = _balances.vault; // We nedd this because for compound if we deposit and withdraw we could get negative intrest based on rounds require( vaultBalance + withdrawnAmount >= currentVaultBalance, MiltonErrors.INTEREST_FROM_STRATEGY_BELOW_ZERO ); uint256 interest = vaultBalance + withdrawnAmount - currentVaultBalance; uint256 liquidityPoolBalance = _balances.liquidityPool + interest; _balances.liquidityPool = liquidityPoolBalance.toUint128(); _balances.vault = vaultBalance.toUint128(); } function updateStorageWhenDepositToStanley(uint256 depositAmount, uint256 vaultBalance) external override onlyMilton { require(vaultBalance >= depositAmount, MiltonErrors.VAULT_BALANCE_LOWER_THAN_DEPOSIT_VALUE); uint256 currentVaultBalance = _balances.vault; require( currentVaultBalance <= (vaultBalance - depositAmount), MiltonErrors.INTEREST_FROM_STRATEGY_BELOW_ZERO ); uint256 interest = currentVaultBalance > 0 ? (vaultBalance - currentVaultBalance - depositAmount) : 0; _balances.vault = vaultBalance.toUint128(); uint256 liquidityPoolBalance = _balances.liquidityPool + interest; _balances.liquidityPool = liquidityPoolBalance.toUint128(); } function updateStorageWhenTransferToCharlieTreasury(uint256 transferredAmount) external override onlyJoseph { require(transferredAmount > 0, IporErrors.NOT_ENOUGH_AMOUNT_TO_TRANSFER); uint256 balance = _balances.iporPublicationFee; require(transferredAmount <= balance, MiltonErrors.PUBLICATION_FEE_BALANCE_IS_TOO_LOW); balance = balance - transferredAmount; _balances.iporPublicationFee = balance.toUint128(); } function updateStorageWhenTransferToTreasury(uint256 transferredAmount) external override onlyJoseph { require(transferredAmount > 0, IporErrors.NOT_ENOUGH_AMOUNT_TO_TRANSFER); uint256 balance = _balances.treasury; require(transferredAmount <= balance, MiltonErrors.TREASURY_BALANCE_IS_TOO_LOW); balance = balance - transferredAmount; _balances.treasury = balance.toUint128(); } function setMilton(address newMilton) external override onlyOwner { require(newMilton != address(0), IporErrors.WRONG_ADDRESS); address oldMilton = _milton; _milton = newMilton; emit MiltonChanged(_msgSender(), oldMilton, newMilton); } function setJoseph(address newJoseph) external override onlyOwner { require(newJoseph != address(0), IporErrors.WRONG_ADDRESS); address oldJoseph = _joseph; _joseph = newJoseph; emit JosephChanged(_msgSender(), oldJoseph, newJoseph); } function pause() external override onlyOwner { _pause(); } function unpause() external override onlyOwner { _unpause(); } function getLiquidityPoolAccountContribution(address account) external view returns (uint256) { return _liquidityPoolAccountContribution[account]; } function _getPositions( mapping(uint32 => AmmMiltonStorageTypes.IporSwap) storage swaps, uint32[] storage ids, uint256 offset, uint256 chunkSize ) internal view returns (IporTypes.IporSwapMemory[] memory) { require(chunkSize > 0, IporErrors.CHUNK_SIZE_EQUAL_ZERO); require(chunkSize <= Constants.MAX_CHUNK_SIZE, IporErrors.CHUNK_SIZE_TOO_BIG); uint256 swapsIdsLength = PaginationUtils.resolveResultSetSize( ids.length, offset, chunkSize ); IporTypes.IporSwapMemory[] memory derivatives = new IporTypes.IporSwapMemory[]( swapsIdsLength ); for (uint256 i = 0; i != swapsIdsLength; i++) { uint32 id = ids[i + offset]; AmmMiltonStorageTypes.IporSwap storage swap = swaps[id]; derivatives[i] = IporTypes.IporSwapMemory( swap.id, swap.buyer, swap.openTimestamp, swap.openTimestamp + Constants.SWAP_DEFAULT_PERIOD_IN_SECONDS, swap.idsIndex, swap.collateral, swap.notional, swap.ibtQuantity, swap.fixedInterestRate, swap.liquidationDepositAmount * Constants.D18, uint256(swaps[id].state) ); } return derivatives; } function _calculateQuasiSoap(uint256 ibtPrice, uint256 calculateTimestamp) internal view returns ( int256 soapPayFixed, int256 soapReceiveFixed, int256 soap ) { AmmMiltonStorageTypes.SoapIndicatorsMemory memory spf = AmmMiltonStorageTypes .SoapIndicatorsMemory( _soapIndicatorsPayFixed.quasiHypotheticalInterestCumulative, _soapIndicatorsPayFixed.totalNotional, _soapIndicatorsPayFixed.totalIbtQuantity, _soapIndicatorsPayFixed.averageInterestRate, _soapIndicatorsPayFixed.rebalanceTimestamp ); int256 _soapPayFixed = spf.calculateQuasiSoapPayFixed(calculateTimestamp, ibtPrice); AmmMiltonStorageTypes.SoapIndicatorsMemory memory srf = AmmMiltonStorageTypes .SoapIndicatorsMemory( _soapIndicatorsReceiveFixed.quasiHypotheticalInterestCumulative, _soapIndicatorsReceiveFixed.totalNotional, _soapIndicatorsReceiveFixed.totalIbtQuantity, _soapIndicatorsReceiveFixed.averageInterestRate, _soapIndicatorsReceiveFixed.rebalanceTimestamp ); int256 _soapReceiveFixed = srf.calculateQuasiSoapReceiveFixed(calculateTimestamp, ibtPrice); return ( soapPayFixed = _soapPayFixed, soapReceiveFixed = _soapReceiveFixed, soap = _soapPayFixed + _soapReceiveFixed ); } function _calculateQuasiSoapPayFixed(uint256 ibtPrice, uint256 calculateTimestamp) internal view returns (int256 soapPayFixed) { AmmMiltonStorageTypes.SoapIndicatorsMemory memory spf = AmmMiltonStorageTypes .SoapIndicatorsMemory( _soapIndicatorsPayFixed.quasiHypotheticalInterestCumulative, _soapIndicatorsPayFixed.totalNotional, _soapIndicatorsPayFixed.totalIbtQuantity, _soapIndicatorsPayFixed.averageInterestRate, _soapIndicatorsPayFixed.rebalanceTimestamp ); soapPayFixed = spf.calculateQuasiSoapPayFixed(calculateTimestamp, ibtPrice); } function _calculateQuasiSoapReceiveFixed(uint256 ibtPrice, uint256 calculateTimestamp) internal view returns (int256 soapReceiveFixed) { AmmMiltonStorageTypes.SoapIndicatorsMemory memory srf = AmmMiltonStorageTypes .SoapIndicatorsMemory( _soapIndicatorsReceiveFixed.quasiHypotheticalInterestCumulative, _soapIndicatorsReceiveFixed.totalNotional, _soapIndicatorsReceiveFixed.totalIbtQuantity, _soapIndicatorsReceiveFixed.averageInterestRate, _soapIndicatorsReceiveFixed.rebalanceTimestamp ); soapReceiveFixed = srf.calculateQuasiSoapReceiveFixed(calculateTimestamp, ibtPrice); } function _updateBalancesWhenOpenSwapPayFixed( uint256 collateral, uint256 openingFeeLPAmount, uint256 openingFeeTreasuryAmount, uint256 cfgIporPublicationFee ) internal { _balances.totalCollateralPayFixed = _balances.totalCollateralPayFixed + collateral.toUint128(); _balances.iporPublicationFee = _balances.iporPublicationFee + cfgIporPublicationFee.toUint128(); _balances.liquidityPool = _balances.liquidityPool + openingFeeLPAmount.toUint128(); _balances.treasury = _balances.treasury + openingFeeTreasuryAmount.toUint128(); } function _updateBalancesWhenOpenSwapReceiveFixed( uint256 collateral, uint256 openingFeeLPAmount, uint256 openingFeeTreasuryAmount, uint256 cfgIporPublicationFee ) internal { _balances.totalCollateralReceiveFixed = _balances.totalCollateralReceiveFixed + collateral.toUint128(); _balances.iporPublicationFee = _balances.iporPublicationFee + cfgIporPublicationFee.toUint128(); _balances.liquidityPool = _balances.liquidityPool + openingFeeLPAmount.toUint128(); _balances.treasury = _balances.treasury + openingFeeTreasuryAmount.toUint128(); } function _updateBalancesWhenCloseSwapPayFixed( address liquidator, IporTypes.IporSwapMemory memory swap, int256 payoff, uint256 incomeFeeValue, uint256 closingTimestamp, uint256 cfgMinLiquidationThresholdToCloseBeforeMaturity, uint256 cfgSecondsBeforeMaturityWhenPositionCanBeClosed ) internal { _updateBalancesWhenCloseSwap( liquidator, swap, payoff, incomeFeeValue, closingTimestamp, cfgMinLiquidationThresholdToCloseBeforeMaturity, cfgSecondsBeforeMaturityWhenPositionCanBeClosed ); _balances.totalCollateralPayFixed = _balances.totalCollateralPayFixed - swap.collateral.toUint128(); } function _updateBalancesWhenCloseSwapReceiveFixed( address liquidator, IporTypes.IporSwapMemory memory swap, int256 payoff, uint256 incomeFeeValue, uint256 closingTimestamp, uint256 cfgMinLiquidationThresholdToCloseBeforeMaturity, uint256 cfgSecondsBeforeMaturityWhenPositionCanBeClosed ) internal { _updateBalancesWhenCloseSwap( liquidator, swap, payoff, incomeFeeValue, closingTimestamp, cfgMinLiquidationThresholdToCloseBeforeMaturity, cfgSecondsBeforeMaturityWhenPositionCanBeClosed ); _balances.totalCollateralReceiveFixed = _balances.totalCollateralReceiveFixed - swap.collateral.toUint128(); } function _updateBalancesWhenCloseSwap( address liquidator, IporTypes.IporSwapMemory memory swap, int256 payoff, uint256 incomeFeeValue, uint256 closingTimestamp, uint256 cfgMinLiquidationThresholdToCloseBeforeMaturity, uint256 cfgSecondsBeforeMaturityWhenPositionCanBeClosed ) internal { uint256 absPayoff = IporMath.absoluteValue(payoff); uint256 minPayoffToCloseBeforeMaturity = IporMath.percentOf( swap.collateral, cfgMinLiquidationThresholdToCloseBeforeMaturity ); if (absPayoff < minPayoffToCloseBeforeMaturity) { //verify if sender is an owner of swap if not then check if maturity - if not then reject, //if yes then close even if not an owner if (liquidator != swap.buyer) { require( closingTimestamp >= swap.endTimestamp - cfgSecondsBeforeMaturityWhenPositionCanBeClosed, MiltonErrors.CANNOT_CLOSE_SWAP_SENDER_IS_NOT_BUYER_AND_NO_MATURITY ); } } _balances.treasury = _balances.treasury + incomeFeeValue.toUint128(); if (payoff > 0) { /// @dev Buyer earns, Milton (LP) looses require( _balances.liquidityPool >= absPayoff, MiltonErrors.CANNOT_CLOSE_SWAP_LP_IS_TOO_LOW ); /// @dev When Milton (LP) looses, then always substract all payoff, /// income fee is added in separate balance - treasury _balances.liquidityPool = _balances.liquidityPool - absPayoff.toUint128(); } else { /// @dev Milton earns, Buyer looses, _balances.liquidityPool = _balances.liquidityPool + (absPayoff - incomeFeeValue).toUint128(); } } function _updateSwapsWhenOpenPayFixed(AmmTypes.NewSwap memory newSwap) internal returns (uint256) { _lastSwapId++; uint32 id = _lastSwapId; AmmMiltonStorageTypes.IporSwap storage swap = _swapsPayFixed.swaps[id]; swap.id = id; swap.buyer = newSwap.buyer; swap.openTimestamp = newSwap.openTimestamp.toUint32(); swap.idsIndex = _swapsPayFixed.ids[newSwap.buyer].length.toUint32(); swap.collateral = newSwap.collateral.toUint128(); swap.notional = newSwap.notional.toUint128(); swap.ibtQuantity = newSwap.ibtQuantity.toUint128(); swap.fixedInterestRate = newSwap.fixedInterestRate.toUint64(); swap.liquidationDepositAmount = newSwap.liquidationDepositAmount.toUint32(); swap.state = AmmTypes.SwapState.ACTIVE; _swapsPayFixed.ids[newSwap.buyer].push(id); _lastSwapId = id; return id; } function _updateSwapsWhenOpenReceiveFixed(AmmTypes.NewSwap memory newSwap) internal returns (uint256) { _lastSwapId++; uint32 id = _lastSwapId; AmmMiltonStorageTypes.IporSwap storage swap = _swapsReceiveFixed.swaps[id]; swap.id = id; swap.buyer = newSwap.buyer; swap.openTimestamp = newSwap.openTimestamp.toUint32(); swap.idsIndex = _swapsReceiveFixed.ids[newSwap.buyer].length.toUint32(); swap.collateral = newSwap.collateral.toUint128(); swap.notional = newSwap.notional.toUint128(); swap.ibtQuantity = newSwap.ibtQuantity.toUint128(); swap.fixedInterestRate = newSwap.fixedInterestRate.toUint64(); swap.liquidationDepositAmount = newSwap.liquidationDepositAmount.toUint32(); swap.state = AmmTypes.SwapState.ACTIVE; _swapsReceiveFixed.ids[newSwap.buyer].push(id); _lastSwapId = id; return id; } function _updateSwapsWhenClosePayFixed(IporTypes.IporSwapMemory memory iporSwap) internal { require(iporSwap.id > 0, MiltonErrors.INCORRECT_SWAP_ID); require( iporSwap.state != uint256(AmmTypes.SwapState.INACTIVE), MiltonErrors.INCORRECT_SWAP_STATUS ); uint32 idsIndexToDelete = iporSwap.idsIndex.toUint32(); address buyer = iporSwap.buyer; uint256 idsLength = _swapsPayFixed.ids[buyer].length - 1; if (idsIndexToDelete < idsLength) { uint32 accountDerivativeIdToMove = _swapsPayFixed.ids[buyer][idsLength]; _swapsPayFixed.swaps[accountDerivativeIdToMove].idsIndex = idsIndexToDelete; _swapsPayFixed.ids[buyer][idsIndexToDelete] = accountDerivativeIdToMove; } _swapsPayFixed.swaps[iporSwap.id.toUint32()].state = AmmTypes.SwapState.INACTIVE; _swapsPayFixed.ids[buyer].pop(); } function _updateSwapsWhenCloseReceiveFixed(IporTypes.IporSwapMemory memory iporSwap) internal { require(iporSwap.id > 0, MiltonErrors.INCORRECT_SWAP_ID); require( iporSwap.state != uint256(AmmTypes.SwapState.INACTIVE), MiltonErrors.INCORRECT_SWAP_STATUS ); uint32 idsIndexToDelete = iporSwap.idsIndex.toUint32(); address buyer = iporSwap.buyer; uint256 idsLength = _swapsReceiveFixed.ids[buyer].length - 1; if (idsIndexToDelete < idsLength) { uint32 accountDerivativeIdToMove = _swapsReceiveFixed.ids[buyer][idsLength]; _swapsReceiveFixed.swaps[accountDerivativeIdToMove].idsIndex = idsIndexToDelete; _swapsReceiveFixed.ids[buyer][idsIndexToDelete] = accountDerivativeIdToMove; } _swapsReceiveFixed.swaps[iporSwap.id.toUint32()].state = AmmTypes.SwapState.INACTIVE; _swapsReceiveFixed.ids[buyer].pop(); } function _updateSoapIndicatorsWhenOpenSwapPayFixed( uint256 openTimestamp, uint256 notional, uint256 fixedInterestRate, uint256 ibtQuantity ) internal { AmmMiltonStorageTypes.SoapIndicatorsMemory memory pf = AmmMiltonStorageTypes .SoapIndicatorsMemory( _soapIndicatorsPayFixed.quasiHypotheticalInterestCumulative, _soapIndicatorsPayFixed.totalNotional, _soapIndicatorsPayFixed.totalIbtQuantity, _soapIndicatorsPayFixed.averageInterestRate, _soapIndicatorsPayFixed.rebalanceTimestamp ); pf.rebalanceWhenOpenSwap(openTimestamp, notional, fixedInterestRate, ibtQuantity); _soapIndicatorsPayFixed.rebalanceTimestamp = pf.rebalanceTimestamp.toUint32(); _soapIndicatorsPayFixed.totalNotional = pf.totalNotional.toUint128(); _soapIndicatorsPayFixed.averageInterestRate = pf.averageInterestRate.toUint64(); _soapIndicatorsPayFixed.totalIbtQuantity = pf.totalIbtQuantity.toUint128(); _soapIndicatorsPayFixed.quasiHypotheticalInterestCumulative = pf .quasiHypotheticalInterestCumulative; } function _updateSoapIndicatorsWhenOpenSwapReceiveFixed( uint256 openTimestamp, uint256 notional, uint256 fixedInterestRate, uint256 ibtQuantity ) internal { AmmMiltonStorageTypes.SoapIndicatorsMemory memory rf = AmmMiltonStorageTypes .SoapIndicatorsMemory( _soapIndicatorsReceiveFixed.quasiHypotheticalInterestCumulative, _soapIndicatorsReceiveFixed.totalNotional, _soapIndicatorsReceiveFixed.totalIbtQuantity, _soapIndicatorsReceiveFixed.averageInterestRate, _soapIndicatorsReceiveFixed.rebalanceTimestamp ); rf.rebalanceWhenOpenSwap(openTimestamp, notional, fixedInterestRate, ibtQuantity); _soapIndicatorsReceiveFixed.rebalanceTimestamp = rf.rebalanceTimestamp.toUint32(); _soapIndicatorsReceiveFixed.totalNotional = rf.totalNotional.toUint128(); _soapIndicatorsReceiveFixed.averageInterestRate = rf.averageInterestRate.toUint64(); _soapIndicatorsReceiveFixed.totalIbtQuantity = rf.totalIbtQuantity.toUint128(); _soapIndicatorsReceiveFixed.quasiHypotheticalInterestCumulative = rf .quasiHypotheticalInterestCumulative; } function _updateSoapIndicatorsWhenCloseSwapPayFixed( IporTypes.IporSwapMemory memory swap, uint256 closingTimestamp ) internal { AmmMiltonStorageTypes.SoapIndicatorsMemory memory pf = AmmMiltonStorageTypes .SoapIndicatorsMemory( _soapIndicatorsPayFixed.quasiHypotheticalInterestCumulative, _soapIndicatorsPayFixed.totalNotional, _soapIndicatorsPayFixed.totalIbtQuantity, _soapIndicatorsPayFixed.averageInterestRate, _soapIndicatorsPayFixed.rebalanceTimestamp ); pf.rebalanceWhenCloseSwap( closingTimestamp, swap.openTimestamp, swap.notional, swap.fixedInterestRate, swap.ibtQuantity ); _soapIndicatorsPayFixed = AmmMiltonStorageTypes.SoapIndicators( pf.quasiHypotheticalInterestCumulative, pf.totalNotional.toUint128(), pf.totalIbtQuantity.toUint128(), pf.averageInterestRate.toUint64(), pf.rebalanceTimestamp.toUint32() ); } function _updateSoapIndicatorsWhenCloseSwapReceiveFixed( IporTypes.IporSwapMemory memory swap, uint256 closingTimestamp ) internal { AmmMiltonStorageTypes.SoapIndicatorsMemory memory rf = AmmMiltonStorageTypes .SoapIndicatorsMemory( _soapIndicatorsReceiveFixed.quasiHypotheticalInterestCumulative, _soapIndicatorsReceiveFixed.totalNotional, _soapIndicatorsReceiveFixed.totalIbtQuantity, _soapIndicatorsReceiveFixed.averageInterestRate, _soapIndicatorsReceiveFixed.rebalanceTimestamp ); rf.rebalanceWhenCloseSwap( closingTimestamp, swap.openTimestamp, swap.notional, swap.fixedInterestRate, swap.ibtQuantity ); _soapIndicatorsReceiveFixed = AmmMiltonStorageTypes.SoapIndicators( rf.quasiHypotheticalInterestCumulative, rf.totalNotional.toUint128(), rf.totalIbtQuantity.toUint128(), rf.averageInterestRate.toUint64(), rf.rebalanceTimestamp.toUint32() ); } //solhint-disable no-empty-blocks function _authorizeUpgrade(address) internal override onlyOwner {} } contract MiltonStorageUsdt is MiltonStorage {} contract MiltonStorageUsdc is MiltonStorage {} contract MiltonStorageDai is MiltonStorage {} // File: contracts/interfaces/IMiltonInternal.sol pragma solidity 0.8.16; /// @title Interface for interaction with Milton, smart contract resposnible for issuing and closing interest rate swaps also known as Automated Market Maker - administrative part. interface IMiltonInternal { /// @notice Returns current version of Milton /// @dev Increase number when implementation inside source code is different that implementation deployed on Mainnet /// @return Current Milton's version function getVersion() external pure returns (uint256); /// @notice Gets asset assocciated with this Milton instance. (each Milton instance is scoped per asset) /// @return asset's address function getAsset() external view returns (address); /// @notice Gets max swap's collateral amount value. /// @dev Param used in swap validation. /// @return max swap's collateral amount represented in 18 decimals function getMaxSwapCollateralAmount() external view returns (uint256); /// @notice Gets max allowed liquidity pool utilization rate. /// @dev Param used in swap validation. /// @return max liquidity pool utilization rate represented in 18 decimals function getMaxLpUtilizationRate() external view returns (uint256); /// @notice Gets max liquidity pool utilization per leg. /// @dev Param used in swap validation. /// @return max Liquidity Pool Utilization Per Leg rate represented in 18 decimals function getMaxLpUtilizationPerLegRate() external view returns (uint256); /// @notice Gets income fee rate. /// @dev Param used when closing the swap. When trader earns then fee is deducted from accrued profit. /// @return income fee rate param value represented in 18 decimals function getIncomeFeeRate() external view returns (uint256); /// @notice Gets opening fee rate. When the trader opens swap position then fee is charged from the amount used to open the swap. /// Opening fee amount is split and transfered in part to Liquidity Pool and to Milton Treasury /// @dev Param is used during swap opening. /// @return opening fee rate represented in 18 decimals function getOpeningFeeRate() external view returns (uint256); /// @notice Gets opening fee rate used to calculate the part of the fee transferred to the Treasury. When the trader opens a position then fee is deducted from the collateral. /// Opening fee amount is split and transfered in part to Liquidity Pool and to Milton Treasury /// This param defines the proportion how the fee is divided and distributed to either liquidity pool or threasury /// @dev Param used in swap opening. /// @return opening fee for treasury rate is represented in 18 decimals function getOpeningFeeTreasuryPortionRate() external view returns (uint256); /// @notice Gets IPOR publication fee. When swap is opened then publication fee is charged. This fee is intended to subsidize the publication of IPOR. /// IPOR publication fee is deducted from the total amount used to open the swap. /// @dev Param used in swap opening. /// @return IPOR publication fee is represented in 18 decimals function getIporPublicationFee() external view returns (uint256); /// @notice Gets liquidation deposit. When the swap is opened then liquidation deposit is deducted from the amount used to open the swap. /// Deposit is refunded to whoever closes the swap: either the buyer or the liquidator. /// @return liquidation deposit is represented without decimals function getLiquidationDepositAmount() external view returns (uint256); /// @notice Gets liquidation deposit. When the swap is opened then liquidation deposit is deducted from the amount used to open the swap. /// Deposit is refunded to whoever closes the swap: either the buyer or the liquidator. /// @return liquidation deposit is represented in 18 decimals function getWadLiquidationDepositAmount() external view returns (uint256); /// @notice Gets max leverage value. /// @dev Param used in swap validation. /// @return max leverage value represented in 18 decimals function getMaxLeverage() external view returns (uint256); /// @notice Gets min leverage value. /// @dev Param used in swap validation. /// @return min leverage value represented in 18 decimals function getMinLeverage() external view returns (uint256); /// @notice Gets Milton's balances including balance held by Stanley in external protocols. /// @dev Balances including sum of all collateral for Pay-Fixed and Receive-Fixed legs, /// liquidity pool balance, and vault balance held by Stanley. /// @return Milton Balance structure `IporTypes.MiltonBalancesMemory`. function getAccruedBalance() external view returns (IporTypes.MiltonBalancesMemory memory); /// @notice Calculates SOAP at given timestamp. /// @dev returned values represented in 18 decimals /// @param calculateTimestamp epoch timestamp at which SOAP is computed. /// @return soapPayFixed SOAP for Pay-Fixed leg. /// @return soapReceiveFixed SOAP for Receive-Fixed leg. /// @return soap total SOAP, sum of Pay Fixed and Receive Fixed SOAP. function calculateSoapAtTimestamp(uint256 calculateTimestamp) external view returns ( int256 soapPayFixed, int256 soapReceiveFixed, int256 soap ); /// @notice Calculats Pay-Fixed Swap payoff for a given Swap structure. /// @param swap `IporTypes.IporSwapMemory` structure /// @return Pay-Fixed Swap payoff, can be negative, represented in 18 decimals. /// @dev absolute value cannot be higher than the collateral function calculatePayoffPayFixed(IporTypes.IporSwapMemory memory swap) external view returns (int256); /// @notice Calculats Receive-Fixed swap payoff for a given Swap structure. /// @param swap `IporTypes.IporSwapMemory` structure /// @return Receive Fixed Swap payoff, can be negative, represented in 18 decimals. /// @dev absolute value cannot be higher than the collateral function calculatePayoffReceiveFixed(IporTypes.IporSwapMemory memory swap) external view returns (int256); /// @notice Transfers the assets from Milton to Stanley. Action available only to Joseph. /// @dev Milton balance in storage is not changing after this deposit, balance of ERC20 assets on Milton is changing as they get transfered to Stanley. /// @dev Emits {Deposit} event from Stanley, emits {Transfer} event from ERC20, emits {Mint} event from ivToken /// @param assetAmount amount of asset function depositToStanley(uint256 assetAmount) external; /// @notice Transfers the assets from Stanley to Milton. Action available only for Joseph. /// @dev Milton balance in storage is not changing, balance of ERC20 assets of Milton is changing. /// @dev Emits {Withdraw} event from Stanley, emits {Transfer} event from ERC20 asset, emits {Burn} event from ivToken /// @param assetAmount amount of assets function withdrawFromStanley(uint256 assetAmount) external; /// @notice Transfers assets (underlying tokens / stablecoins) from Stanley to Milton. Action available only for Joseph. /// @dev Milton Balance in storage is not changing after this wi, balance of ERC20 assets on Milton is changing. /// @dev Emits {Withdraw} event from Stanley, emits {Transfer} event from ERC20 asset, emits {Burn} event from ivToken function withdrawAllFromStanley() external; /// @notice Closes Pay-Fixed swap for a given ID in "emergency mode". Action available only to the Owner. /// @dev Emits {CloseSwap} event from Milton, {Transfer} event from ERC20 asset. /// @param swapId Pay-Fixed swap ID function emergencyCloseSwapPayFixed(uint256 swapId) external; /// @notice Closes Receive-Fixed swap for a given ID in emergency mode. Action available only to the Owner. /// @dev Emits {CloseSwap} event from Milton, {Transfer} event from ERC20 asset. /// @param swapId Receive Fixed Swap ID function emergencyCloseSwapReceiveFixed(uint256 swapId) external; /// @notice Closes Pay-Fixed swaps for a given list of IDs in emergency mode. Action available only to the Owner. /// @dev Emits {CloseSwap} events from Milton, {Transfer} events from ERC20 asset. /// @param swapIds List of Pay Fixed swaps. /// @return closedSwaps list of structures with information if particular swapId was closed in this execution (isClosed = true) or not (isClosed = false) function emergencyCloseSwapsPayFixed(uint256[] memory swapIds) external returns (MiltonTypes.IporSwapClosingResult[] memory closedSwaps); /// @notice Closes Receive-Fixed swaps for given list of IDs in emergency mode. Action available only to the Owner. /// @dev Emits {CloseSwap} events from Milton, {Transfer} events from ERC20 asset. /// @param swapIds List of Receive-Fixed swap IDs. /// @return closedSwaps list of structures with information if particular swapId was closed in this execution (isClosed = true) or not (isClosed = false) function emergencyCloseSwapsReceiveFixed(uint256[] memory swapIds) external returns (MiltonTypes.IporSwapClosingResult[] memory closedSwaps); /// @notice Pauses current smart contract, it can be executed only by the Owner /// @dev Emits {Paused} event from Milton. function pause() external; /// @notice Unpauses current smart contract, it can be executed only by the Owner /// @dev Emits {Unpaused} event from Milton. function unpause() external; /// @notice sets max allowance for a given spender. Action available only for Owner. /// @param spender account which will have rights to transfer ERC20 underlying assets on behalf of Milton function setupMaxAllowanceForAsset(address spender) external; /// @notice Gets Joseph's address. /// @return Joseph address function getJoseph() external view returns (address); /// @notice Sets Joseph address. Function available only to the Owner. /// @param newJoseph new Joseph address function setJoseph(address newJoseph) external; /// @notice Gets Milton Spread Model smart contract address (contract responsible for spread calculation). /// @return Milton Spread model smart contract address function getMiltonSpreadModel() external view returns (address); /// @notice Sets Milton Spread Model smart contract address (contract responsible for spread calculation). /// @param newMiltonSpreadModel new Milton Spread Model address function setMiltonSpreadModel(address newMiltonSpreadModel) external; /// @notice Emmited when Joseph's address is changed by its owner. /// @param changedBy account address that has changed Joseph's address /// @param oldJoseph Joseph's old address /// @param newJoseph Joseph's new address event JosephChanged( address indexed changedBy, address indexed oldJoseph, address indexed newJoseph ); /// @notice Emmited when MiltonSpreadModel's address is changed by its owner. /// @param changedBy account address that has changed Joseph's address /// @param oldMiltonSpreadModel MiltonSpreadModel's old address /// @param newMiltonSpreadModel MiltonSpreadModel's new address event MiltonSpreadModelChanged( address indexed changedBy, address indexed oldMiltonSpreadModel, address indexed newMiltonSpreadModel ); } // File: contracts/amm/MiltonInternal.sol pragma solidity 0.8.16; abstract contract MiltonInternal is Initializable, PausableUpgradeable, ReentrancyGuardUpgradeable, UUPSUpgradeable, IporOwnableUpgradeable, IMiltonInternal { using SafeERC20Upgradeable for IERC20Upgradeable; using SafeCast for uint256; using SafeCast for uint128; using SafeCast for int256; using IporSwapLogic for IporTypes.IporSwapMemory; //@notice max total amount used when opening position uint256 internal constant _MAX_SWAP_COLLATERAL_AMOUNT = 1e23; uint256 internal constant _MAX_LP_UTILIZATION_RATE = 8 * 1e17; uint256 internal constant _MAX_LP_UTILIZATION_PER_LEG_RATE = 48 * 1e16; uint256 internal constant _INCOME_TAX_RATE = 1e17; uint256 internal constant _OPENING_FEE_RATE = 1e16; /// @notice Opening Fee is divided between Treasury Balance and Liquidity Pool Balance, /// below value define how big pie going to Treasury Balance uint256 internal constant _OPENING_FEE_FOR_TREASURY_PORTION_RATE = 0; uint256 internal constant _IPOR_PUBLICATION_FEE = 10 * 1e18; uint256 internal constant _LIQUIDATION_DEPOSIT_AMOUNT = 25; uint256 internal constant _MAX_LEVERAGE = 1000 * 1e18; uint256 internal constant _MIN_LEVERAGE = 10 * 1e18; uint256 internal constant _MIN_LIQUIDATION_THRESHOLD_TO_CLOSE_BEFORE_MATURITY = 99 * 1e16; uint256 internal constant _SECONDS_BEFORE_MATURITY_WHEN_POSITION_CAN_BE_CLOSED = 6 hours; uint256 internal constant _LIQUIDATION_LEG_LIMIT = 10; address internal _asset; address internal _joseph; IStanley internal _stanley; IIporOracle internal _iporOracle; IMiltonStorage internal _miltonStorage; IMiltonSpreadModel internal _miltonSpreadModel; modifier onlyJoseph() { require(_msgSender() == _getJoseph(), MiltonErrors.CALLER_NOT_JOSEPH); _; } function getVersion() external pure virtual override returns (uint256) { return 2; } function getAsset() external view override returns (address) { return _asset; } function getMaxSwapCollateralAmount() external view override returns (uint256) { return _getMaxSwapCollateralAmount(); } function getMaxLpUtilizationRate() external view override returns (uint256) { return _getMaxLpUtilizationRate(); } function getMaxLpUtilizationPerLegRate() external view override returns (uint256) { return _getMaxLpUtilizationPerLegRate(); } function getIncomeFeeRate() external view override returns (uint256) { return _getIncomeFeeRate(); } function getOpeningFeeRate() external view override returns (uint256) { return _getOpeningFeeRate(); } function getOpeningFeeTreasuryPortionRate() external view override returns (uint256) { return _getOpeningFeeTreasuryPortionRate(); } function getIporPublicationFee() external view override returns (uint256) { return _getIporPublicationFee(); } /// @notice Returns configured liquidation deposit amount /// @return liquidation deposit amount, value represented WITHOUT decimals function getLiquidationDepositAmount() external view override returns (uint256) { return _getLiquidationDepositAmount(); } function getWadLiquidationDepositAmount() external view override returns (uint256) { return _getLiquidationDepositAmount() * Constants.D18; } function getMaxLeverage() external view override returns (uint256) { return _getMaxLeverage(); } function getMinLeverage() external view override returns (uint256) { return _getMinLeverage(); } function getAccruedBalance() external view override returns (IporTypes.MiltonBalancesMemory memory) { return _getAccruedBalance(); } function calculateSoapAtTimestamp(uint256 calculateTimestamp) external view override returns ( int256 soapPayFixed, int256 soapReceiveFixed, int256 soap ) { (int256 _soapPayFixed, int256 _soapReceiveFixed, int256 _soap) = _calculateSoap( calculateTimestamp ); return (soapPayFixed = _soapPayFixed, soapReceiveFixed = _soapReceiveFixed, soap = _soap); } function calculatePayoffPayFixed(IporTypes.IporSwapMemory memory swap) external view override returns (int256) { return _calculatePayoffPayFixed(block.timestamp, swap); } function calculatePayoffReceiveFixed(IporTypes.IporSwapMemory memory swap) external view override returns (int256) { return _calculatePayoffReceiveFixed(block.timestamp, swap); } /// @notice Joseph deposits to Stanley asset amount from Milton. /// @param assetAmount underlying token amount represented in 18 decimals function depositToStanley(uint256 assetAmount) external onlyJoseph nonReentrant whenNotPaused { (uint256 vaultBalance, uint256 depositedAmount) = _getStanley().deposit(assetAmount); _getMiltonStorage().updateStorageWhenDepositToStanley(depositedAmount, vaultBalance); } //@param assetAmount underlying token amount represented in 18 decimals function withdrawFromStanley(uint256 assetAmount) external nonReentrant onlyJoseph whenNotPaused { (uint256 withdrawnAmount, uint256 vaultBalance) = _getStanley().withdraw(assetAmount); _getMiltonStorage().updateStorageWhenWithdrawFromStanley(withdrawnAmount, vaultBalance); } function withdrawAllFromStanley() external nonReentrant onlyJoseph whenNotPaused { (uint256 withdrawnAmount, uint256 vaultBalance) = _getStanley().withdrawAll(); _getMiltonStorage().updateStorageWhenWithdrawFromStanley(withdrawnAmount, vaultBalance); } function pause() external override onlyOwner { _pause(); } function unpause() external override onlyOwner { _unpause(); } function setupMaxAllowanceForAsset(address spender) external override onlyOwner whenNotPaused { IERC20Upgradeable(_asset).safeIncreaseAllowance(spender, Constants.MAX_VALUE); } function setJoseph(address newJoseph) external override onlyOwner whenNotPaused { require(newJoseph != address(0), IporErrors.WRONG_ADDRESS); address oldJoseph = _getJoseph(); _joseph = newJoseph; emit JosephChanged(_msgSender(), oldJoseph, newJoseph); } function getJoseph() external view override returns (address) { return _getJoseph(); } function setMiltonSpreadModel(address newMiltonSpreadModel) external override onlyOwner whenNotPaused { require(newMiltonSpreadModel != address(0), IporErrors.WRONG_ADDRESS); address oldMiltonSpreadModel = _getJoseph(); _miltonSpreadModel = IMiltonSpreadModel(newMiltonSpreadModel); emit MiltonSpreadModelChanged(_msgSender(), oldMiltonSpreadModel, newMiltonSpreadModel); } function getMiltonSpreadModel() external view override returns (address) { return address(_miltonSpreadModel); } function _getDecimals() internal pure virtual returns (uint256); function _getMaxSwapCollateralAmount() internal view virtual returns (uint256) { return _MAX_SWAP_COLLATERAL_AMOUNT; } function _getMaxLpUtilizationRate() internal view virtual returns (uint256) { return _MAX_LP_UTILIZATION_RATE; } function _getMaxLpUtilizationPerLegRate() internal view virtual returns (uint256) { return _MAX_LP_UTILIZATION_PER_LEG_RATE; } function _getIncomeFeeRate() internal view virtual returns (uint256) { return _INCOME_TAX_RATE; } function _getOpeningFeeRate() internal view virtual returns (uint256) { return _OPENING_FEE_RATE; } function _getOpeningFeeTreasuryPortionRate() internal view virtual returns (uint256) { return _OPENING_FEE_FOR_TREASURY_PORTION_RATE; } function _getIporPublicationFee() internal view virtual returns (uint256) { return _IPOR_PUBLICATION_FEE; } function _getLiquidationDepositAmount() internal view virtual returns (uint256) { return _LIQUIDATION_DEPOSIT_AMOUNT; } function _getMaxLeverage() internal view virtual returns (uint256) { return _MAX_LEVERAGE; } function _getMinLeverage() internal view virtual returns (uint256) { return _MIN_LEVERAGE; } function _getMinLiquidationThresholdToCloseBeforeMaturity() internal view virtual returns (uint256) { return _MIN_LIQUIDATION_THRESHOLD_TO_CLOSE_BEFORE_MATURITY; } function _getSecondsBeforeMaturityWhenPositionCanBeClosed() internal view virtual returns (uint256) { return _SECONDS_BEFORE_MATURITY_WHEN_POSITION_CAN_BE_CLOSED; } function _getLiquidationLegLimit() internal view virtual returns (uint256) { return _LIQUIDATION_LEG_LIMIT; } function _getJoseph() internal view virtual returns (address) { return _joseph; } function _getIporOracle() internal view virtual returns (IIporOracle) { return _iporOracle; } function _getMiltonStorage() internal view virtual returns (IMiltonStorage) { return _miltonStorage; } function _getStanley() internal view virtual returns (IStanley) { return _stanley; } function _getAccruedBalance() internal view returns (IporTypes.MiltonBalancesMemory memory) { IporTypes.MiltonBalancesMemory memory accruedBalance = _getMiltonStorage().getBalance(); uint256 actualVaultBalance = _getStanley().totalBalance(address(this)); int256 liquidityPool = accruedBalance.liquidityPool.toInt256() + actualVaultBalance.toInt256() - accruedBalance.vault.toInt256(); require(liquidityPool >= 0, MiltonErrors.LIQUIDITY_POOL_AMOUNT_TOO_LOW); accruedBalance.liquidityPool = liquidityPool.toUint256(); accruedBalance.vault = actualVaultBalance; return accruedBalance; } function _calculateSoap(uint256 calculateTimestamp) internal view returns ( int256 soapPayFixed, int256 soapReceiveFixed, int256 soap ) { uint256 accruedIbtPrice = _getIporOracle().calculateAccruedIbtPrice( _asset, calculateTimestamp ); (int256 _soapPayFixed, int256 _soapReceiveFixed, int256 _soap) = _getMiltonStorage() .calculateSoap(accruedIbtPrice, calculateTimestamp); return (soapPayFixed = _soapPayFixed, soapReceiveFixed = _soapReceiveFixed, soap = _soap); } function _calculatePayoffPayFixed(uint256 timestamp, IporTypes.IporSwapMemory memory swap) internal view returns (int256) { return swap.calculatePayoffPayFixed( timestamp, _getIporOracle().calculateAccruedIbtPrice(_asset, timestamp) ); } function _calculatePayoffReceiveFixed(uint256 timestamp, IporTypes.IporSwapMemory memory swap) internal view returns (int256) { return swap.calculatePayoffReceiveFixed( timestamp, _getIporOracle().calculateAccruedIbtPrice(_asset, timestamp) ); } } // File: contracts/interfaces/IMilton.sol pragma solidity 0.8.16; /// @title Interface for interaction with Milton. interface IMilton { /// @notice Calculates spread for the current block. /// @dev All values represented in 18 decimals. /// @return spreadPayFixed spread for Pay-Fixed leg. /// @return spreadReceiveFixed spread for Receive-Fixed leg. function calculateSpread() external view returns (int256 spreadPayFixed, int256 spreadReceiveFixed); /// @notice Calculates the SOAP for the current block /// @dev All values represented in 18 decimals. /// @return soapPayFixed SOAP for Pay-Fixed leg. /// @return soapReceiveFixed SOAP for Receive-Fixed leg. /// @return soap total SOAP - sum of Pay-Fixed and Receive-Fixed SOAP. function calculateSoap() external view returns ( int256 soapPayFixed, int256 soapReceiveFixed, int256 soap ); /// @notice Opens Pay-Fixed (and Receive-Floating) swap with given parameters. /// @dev Emits `OpenSwap` event from Milton, {Transfer} event from ERC20 asset. /// @param totalAmount Total amount transferred from the buyer to Milton for the purpose of opening a swap. Represented in decimals specific for asset. /// @param acceptableFixedInterestRate Max quote value which trader accepts in case of rate slippage. Value represented in 18 decimals. /// @param leverage Leverage used in this posistion. Value represented in 18 decimals. /// @return Swap ID in Pay-Fixed swaps list function openSwapPayFixed( uint256 totalAmount, uint256 acceptableFixedInterestRate, uint256 leverage ) external returns (uint256); /// @notice Opens Receive-Fixed (and Pay Floating) swap with given parameters. /// @dev Emits `OpenSwap` event from Milton, {Transfer} event from ERC20 asset. /// @param totalAmount Total amount transferred from the buyer to Milton for the purpose of opening a swap. Represented in decimals specific for asset. /// @param acceptableFixedInterestRate Max quote value which trader accept in case of rate slippage. Value represented in 18 decimals. /// @param leverage Leverage used in this posisiton. Value represented in 18 decimals. /// @return Swap ID in Pay-Fixed swaps list function openSwapReceiveFixed( uint256 totalAmount, uint256 acceptableFixedInterestRate, uint256 leverage ) external returns (uint256); /// @notice Closes Pay-Fixed swap for given ID. /// @dev Emits {CloseSwap} event from Milton, {Transfer} event from ERC20 asset. /// @dev Rejects transaction and returns error code IPOR_307 if swapId doesn't have AmmTypes.SwapState.ACTIVE status. /// @param swapId Pay-Fixed Swap ID. function closeSwapPayFixed(uint256 swapId) external; /// @notice Closes Receive-Fixed swap for given ID. /// @dev Emits {CloseSwap} event from Milton, {Transfer} event from ERC20 asset. /// @dev Rejects transaction and returns error code IPOR_307 if swapId doesn't have AmmTypes.SwapState.ACTIVE status. /// @param swapId Receive-Fixed swap ID. function closeSwapReceiveFixed(uint256 swapId) external; /// @notice Closes list of pay fixed and receive fixed swaps in one transaction. /// @dev Emits {CloseSwap} events from Milton, {Transfer} events from ERC20 asset for every swap which was closed within this transaction. /// @param payFixedSwapIds list of pay fixed swap ids /// @param receiveFixedSwapIds list of receive fixed swap ids /// @return closedPayFixedSwaps list of pay fixed swaps with information which one was closed during this particular transaction. /// @return closedReceiveFixedSwaps list of receive fixed swaps with information which one was closed during this particular transaction. function closeSwaps(uint256[] memory payFixedSwapIds, uint256[] memory receiveFixedSwapIds) external returns ( MiltonTypes.IporSwapClosingResult[] memory closedPayFixedSwaps, MiltonTypes.IporSwapClosingResult[] memory closedReceiveFixedSwaps ); /// @notice Emmited when trader opens new swap. event OpenSwap( /// @notice swap ID. uint256 indexed swapId, /// @notice trader that opened the swap address indexed buyer, /// @notice underlying asset address asset, /// @notice swap direction MiltonTypes.SwapDirection direction, /// @notice money structure related with this swap AmmTypes.OpenSwapMoney money, /// @notice the moment when swap was opened uint256 openTimestamp, /// @notice the moment when swap will achieve maturity uint256 endTimestamp, /// @notice attributes taken from IPOR Index indicators. MiltonTypes.IporSwapIndicator indicator ); /// @notice Emmited when trader closes Swap. event CloseSwap( /// @notice swap ID. uint256 indexed swapId, /// @notice underlying asset address asset, /// @notice the moment when swap was closed uint256 closeTimestamp, /// @notice account that liquidated the swap address liquidator, /// @notice asset amount after closing swap that has been transferred from Milton to the Buyer. Value represented in 18 decimals. uint256 transferredToBuyer, /// @notice asset amount after closing swap that has been transferred from Milton to the Liquidator. Value represented in 18 decimals. uint256 transferredToLiquidator, /// @notice incomeFeeValue value transferred to treasury uint256 incomeFeeValue ); } // File: contracts/amm/Milton.sol pragma solidity 0.8.16; /** * @title Milton - Automated Market Maker for trading Interest Rate Swaps derivatives based on IPOR Index. * @dev Milton is scoped per asset (USDT, USDC, DAI or other type of ERC20 asset included by the DAO) * Users can: * # open and close own interest rate swaps * # liquidate other's swaps at maturity * # calculate the SOAP * # calculate spread * @author IPOR Labs */ abstract contract Milton is MiltonInternal, IMilton { using SafeERC20Upgradeable for IERC20Upgradeable; using SafeCast for uint256; using SafeCast for uint128; using SafeCast for int256; using IporSwapLogic for IporTypes.IporSwapMemory; /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } /** * @param paused - Initial flag to determine if smart contract is paused or not * @param asset - Instance of Milton is initialised in the context of the given ERC20 asset. Every trasaction is by the default scoped to that ERC20. * @param iporOracle - Address of Oracle treated as the source of true IPOR rate. * @param miltonStorage - Address of contract responsible for managing the state of Milton. * @param miltonSpreadModel - Address of smart contract responsible for calculating spreads on the interst rate swaps. * @param stanley - Address of smart contract responsible for asset management. * For more details refer to the documentation: https://ipor-labs.gitbook.io/ipor-labs/automated-market-maker/asset-management **/ function initialize( bool paused, address asset, address iporOracle, address miltonStorage, address miltonSpreadModel, address stanley ) public initializer { __Pausable_init(); __Ownable_init(); __UUPSUpgradeable_init(); require(asset != address(0), IporErrors.WRONG_ADDRESS); require(iporOracle != address(0), IporErrors.WRONG_ADDRESS); require(miltonStorage != address(0), IporErrors.WRONG_ADDRESS); require(miltonSpreadModel != address(0), IporErrors.WRONG_ADDRESS); require(stanley != address(0), IporErrors.WRONG_ADDRESS); require(_getDecimals() == ERC20Upgradeable(asset).decimals(), IporErrors.WRONG_DECIMALS); if (paused) { _pause(); } _miltonStorage = IMiltonStorage(miltonStorage); _miltonSpreadModel = IMiltonSpreadModel(miltonSpreadModel); _iporOracle = IIporOracle(iporOracle); _asset = asset; _stanley = IStanley(stanley); } function calculateSpread() external view override returns (int256 spreadPayFixed, int256 spreadReceiveFixed) { (spreadPayFixed, spreadReceiveFixed) = _calculateSpread(block.timestamp); } function calculateSoap() external view override returns ( int256 soapPayFixed, int256 soapReceiveFixed, int256 soap ) { (int256 _soapPayFixed, int256 _soapReceiveFixed, int256 _soap) = _calculateSoap( block.timestamp ); return (soapPayFixed = _soapPayFixed, soapReceiveFixed = _soapReceiveFixed, soap = _soap); } function openSwapPayFixed( uint256 totalAmount, uint256 acceptableFixedInterestRate, uint256 leverage ) external override nonReentrant whenNotPaused returns (uint256) { return _openSwapPayFixed(block.timestamp, totalAmount, acceptableFixedInterestRate, leverage); } function openSwapReceiveFixed( uint256 totalAmount, uint256 acceptableFixedInterestRate, uint256 leverage ) external override nonReentrant whenNotPaused returns (uint256) { return _openSwapReceiveFixed( block.timestamp, totalAmount, acceptableFixedInterestRate, leverage ); } function closeSwapPayFixed(uint256 swapId) external override nonReentrant whenNotPaused { _closeSwapPayFixedWithTransferLiquidationDeposit(swapId, block.timestamp); } function closeSwapReceiveFixed(uint256 swapId) external override nonReentrant whenNotPaused { _closeSwapReceiveFixedWithTransferLiquidationDeposit(swapId, block.timestamp); } function closeSwaps(uint256[] memory payFixedSwapIds, uint256[] memory receiveFixedSwapIds) external override nonReentrant whenNotPaused returns ( MiltonTypes.IporSwapClosingResult[] memory closedPayFixedSwaps, MiltonTypes.IporSwapClosingResult[] memory closedReceiveFixedSwaps ) { (closedPayFixedSwaps, closedReceiveFixedSwaps) = _closeSwaps( payFixedSwapIds, receiveFixedSwapIds, block.timestamp ); } function emergencyCloseSwapPayFixed(uint256 swapId) external override onlyOwner whenPaused { _closeSwapPayFixedWithTransferLiquidationDeposit(swapId, block.timestamp); } function emergencyCloseSwapReceiveFixed(uint256 swapId) external override onlyOwner whenPaused { _closeSwapReceiveFixedWithTransferLiquidationDeposit(swapId, block.timestamp); } function emergencyCloseSwapsPayFixed(uint256[] memory swapIds) external override onlyOwner whenPaused returns (MiltonTypes.IporSwapClosingResult[] memory closedSwaps) { closedSwaps = _closeSwapsPayFixedWithTransferLiquidationDeposit(swapIds, block.timestamp); } function emergencyCloseSwapsReceiveFixed(uint256[] memory swapIds) external override onlyOwner whenPaused returns (MiltonTypes.IporSwapClosingResult[] memory closedSwaps) { closedSwaps = _closeSwapsReceiveFixedWithTransferLiquidationDeposit( swapIds, block.timestamp ); } function _closeSwaps( uint256[] memory payFixedSwapIds, uint256[] memory receiveFixedSwapIds, uint256 closeTimestamp ) internal returns ( MiltonTypes.IporSwapClosingResult[] memory closedPayFixedSwaps, MiltonTypes.IporSwapClosingResult[] memory closedReceiveFixedSwaps ) { require( payFixedSwapIds.length <= _getLiquidationLegLimit() && receiveFixedSwapIds.length <= _getLiquidationLegLimit(), MiltonErrors.LIQUIDATION_LEG_LIMIT_EXCEEDED ); uint256 payoutForLiquidatorPayFixed; uint256 payoutForLiquidatorReceiveFixed; (payoutForLiquidatorPayFixed, closedPayFixedSwaps) = _closeSwapsPayFixed( payFixedSwapIds, closeTimestamp ); (payoutForLiquidatorReceiveFixed, closedReceiveFixedSwaps) = _closeSwapsReceiveFixed( receiveFixedSwapIds, closeTimestamp ); _transferLiquidationDepositAmount( _msgSender(), payoutForLiquidatorPayFixed + payoutForLiquidatorReceiveFixed ); } function _closeSwapPayFixedWithTransferLiquidationDeposit( uint256 swapId, uint256 closeTimestamp ) internal { require(swapId > 0, MiltonErrors.INCORRECT_SWAP_ID); IporTypes.IporSwapMemory memory iporSwap = _getMiltonStorage().getSwapPayFixed(swapId); _transferLiquidationDepositAmount( _msgSender(), _closeSwapPayFixed(iporSwap, closeTimestamp) ); } function _closeSwapReceiveFixedWithTransferLiquidationDeposit( uint256 swapId, uint256 closeTimestamp ) internal { require(swapId > 0, MiltonErrors.INCORRECT_SWAP_ID); IporTypes.IporSwapMemory memory iporSwap = _getMiltonStorage().getSwapReceiveFixed(swapId); _transferLiquidationDepositAmount( _msgSender(), _closeSwapReceiveFixed(iporSwap, closeTimestamp) ); } function _closeSwapsPayFixedWithTransferLiquidationDeposit( uint256[] memory swapIds, uint256 closeTimestamp ) internal returns (MiltonTypes.IporSwapClosingResult[] memory closedSwaps) { uint256 payoutForLiquidator; (payoutForLiquidator, closedSwaps) = _closeSwapsPayFixed(swapIds, closeTimestamp); _transferLiquidationDepositAmount(_msgSender(), payoutForLiquidator); } function _closeSwapsReceiveFixedWithTransferLiquidationDeposit( uint256[] memory swapIds, uint256 closeTimestamp ) internal returns (MiltonTypes.IporSwapClosingResult[] memory closedSwaps) { uint256 payoutForLiquidator; (payoutForLiquidator, closedSwaps) = _closeSwapsReceiveFixed(swapIds, closeTimestamp); _transferLiquidationDepositAmount(_msgSender(), payoutForLiquidator); } function _calculateIncomeFeeValue(int256 payoff) internal view returns (uint256) { return IporMath.division(IporMath.absoluteValue(payoff) * _getIncomeFeeRate(), Constants.D18); } function _calculateSpread(uint256 calculateTimestamp) internal view returns (int256 spreadPayFixed, int256 spreadReceiveFixed) { IporTypes.AccruedIpor memory accruedIpor = _iporOracle.getAccruedIndex( calculateTimestamp, _asset ); IporTypes.MiltonBalancesMemory memory balance = _getAccruedBalance(); IMiltonSpreadModel miltonSpreadModel = _miltonSpreadModel; spreadPayFixed = miltonSpreadModel.calculateSpreadPayFixed(accruedIpor, balance); spreadReceiveFixed = miltonSpreadModel.calculateSpreadReceiveFixed(accruedIpor, balance); } function _beforeOpenSwap( uint256 openTimestamp, uint256 totalAmount, uint256 leverage ) internal view returns (AmmMiltonTypes.BeforeOpenSwapStruct memory bosStruct) { require(totalAmount > 0, MiltonErrors.TOTAL_AMOUNT_TOO_LOW); require( IERC20Upgradeable(_asset).balanceOf(_msgSender()) >= totalAmount, IporErrors.ASSET_BALANCE_TOO_LOW ); uint256 wadTotalAmount = IporMath.convertToWad(totalAmount, _getDecimals()); require(leverage >= _getMinLeverage(), MiltonErrors.LEVERAGE_TOO_LOW); require(leverage <= _getMaxLeverage(), MiltonErrors.LEVERAGE_TOO_HIGH); uint256 liquidationDepositAmount = _getLiquidationDepositAmount(); uint256 wadLiquidationDepositAmount = liquidationDepositAmount * Constants.D18; require( wadTotalAmount > wadLiquidationDepositAmount + _getIporPublicationFee(), MiltonErrors.TOTAL_AMOUNT_LOWER_THAN_FEE ); (uint256 collateral, uint256 notional, uint256 openingFeeAmount) = IporSwapLogic .calculateSwapAmount( wadTotalAmount, leverage, wadLiquidationDepositAmount, _getIporPublicationFee(), _getOpeningFeeRate() ); (uint256 openingFeeLPAmount, uint256 openingFeeTreasuryAmount) = _splitOpeningFeeAmount( openingFeeAmount, _getOpeningFeeTreasuryPortionRate() ); require( collateral <= _getMaxSwapCollateralAmount(), MiltonErrors.COLLATERAL_AMOUNT_TOO_HIGH ); require( wadTotalAmount > wadLiquidationDepositAmount + _getIporPublicationFee() + openingFeeAmount, MiltonErrors.TOTAL_AMOUNT_LOWER_THAN_FEE ); return AmmMiltonTypes.BeforeOpenSwapStruct( wadTotalAmount, collateral, notional, openingFeeLPAmount, openingFeeTreasuryAmount, _getIporPublicationFee(), liquidationDepositAmount, _iporOracle.getAccruedIndex(openTimestamp, _asset) ); } function _splitOpeningFeeAmount(uint256 openingFeeAmount, uint256 openingFeeForTreasureRate) internal pure returns (uint256 liquidityPoolAmount, uint256 treasuryAmount) { treasuryAmount = IporMath.division( openingFeeAmount * openingFeeForTreasureRate, Constants.D18 ); liquidityPoolAmount = openingFeeAmount - treasuryAmount; } //@param totalAmount underlying tokens transferred from buyer to Milton, represented in decimals specific for asset function _openSwapPayFixed( uint256 openTimestamp, uint256 totalAmount, uint256 acceptableFixedInterestRate, uint256 leverage ) internal returns (uint256) { AmmMiltonTypes.BeforeOpenSwapStruct memory bosStruct = _beforeOpenSwap( openTimestamp, totalAmount, leverage ); IporTypes.MiltonBalancesMemory memory balance = _getMiltonStorage().getBalance(); balance.liquidityPool = balance.liquidityPool + bosStruct.openingFeeLPAmount; balance.totalCollateralPayFixed = balance.totalCollateralPayFixed + bosStruct.collateral; _validateLiqudityPoolUtylization( balance.liquidityPool, balance.totalCollateralPayFixed, balance.totalCollateralPayFixed + balance.totalCollateralReceiveFixed ); uint256 quoteValue = _miltonSpreadModel.calculateQuotePayFixed( bosStruct.accruedIpor, balance ); require( acceptableFixedInterestRate > 0 && quoteValue <= acceptableFixedInterestRate, MiltonErrors.ACCEPTABLE_FIXED_INTEREST_RATE_EXCEEDED ); MiltonTypes.IporSwapIndicator memory indicator = _calculateSwapIndicators( openTimestamp, bosStruct.notional, quoteValue ); AmmTypes.NewSwap memory newSwap = AmmTypes.NewSwap( _msgSender(), openTimestamp, bosStruct.collateral, bosStruct.notional, indicator.ibtQuantity, indicator.fixedInterestRate, bosStruct.liquidationDepositAmount, bosStruct.openingFeeLPAmount, bosStruct.openingFeeTreasuryAmount ); uint256 newSwapId = _getMiltonStorage().updateStorageWhenOpenSwapPayFixed( newSwap, _getIporPublicationFee() ); IERC20Upgradeable(_asset).safeTransferFrom(_msgSender(), address(this), totalAmount); _emitOpenSwapEvent( newSwapId, bosStruct.wadTotalAmount, newSwap, indicator, 0, bosStruct.iporPublicationFeeAmount ); return newSwapId; } //@param totalAmount underlying tokens transferred from buyer to Milton, represented in decimals specific for asset function _openSwapReceiveFixed( uint256 openTimestamp, uint256 totalAmount, uint256 acceptableFixedInterestRate, uint256 leverage ) internal returns (uint256) { AmmMiltonTypes.BeforeOpenSwapStruct memory bosStruct = _beforeOpenSwap( openTimestamp, totalAmount, leverage ); IporTypes.MiltonBalancesMemory memory balance = _getMiltonStorage().getBalance(); balance.liquidityPool = balance.liquidityPool + bosStruct.openingFeeLPAmount; balance.totalCollateralReceiveFixed = balance.totalCollateralReceiveFixed + bosStruct.collateral; _validateLiqudityPoolUtylization( balance.liquidityPool, balance.totalCollateralReceiveFixed, balance.totalCollateralPayFixed + balance.totalCollateralReceiveFixed ); uint256 quoteValue = _miltonSpreadModel.calculateQuoteReceiveFixed( bosStruct.accruedIpor, balance ); require( acceptableFixedInterestRate <= quoteValue, MiltonErrors.ACCEPTABLE_FIXED_INTEREST_RATE_EXCEEDED ); MiltonTypes.IporSwapIndicator memory indicator = _calculateSwapIndicators( openTimestamp, bosStruct.notional, quoteValue ); AmmTypes.NewSwap memory newSwap = AmmTypes.NewSwap( _msgSender(), openTimestamp, bosStruct.collateral, bosStruct.notional, indicator.ibtQuantity, indicator.fixedInterestRate, bosStruct.liquidationDepositAmount, bosStruct.openingFeeLPAmount, bosStruct.openingFeeTreasuryAmount ); uint256 newSwapId = _getMiltonStorage().updateStorageWhenOpenSwapReceiveFixed( newSwap, _getIporPublicationFee() ); IERC20Upgradeable(_asset).safeTransferFrom(_msgSender(), address(this), totalAmount); _emitOpenSwapEvent( newSwapId, bosStruct.wadTotalAmount, newSwap, indicator, 1, bosStruct.iporPublicationFeeAmount ); return newSwapId; } function _validateLiqudityPoolUtylization( uint256 totalLiquidityPoolBalance, uint256 collateralPerLegBalance, uint256 totalCollateralBalance ) internal view { uint256 utilizationRate; uint256 utilizationRatePerLeg; if (totalLiquidityPoolBalance > 0) { utilizationRate = IporMath.division( totalCollateralBalance * Constants.D18, totalLiquidityPoolBalance ); utilizationRatePerLeg = IporMath.division( collateralPerLegBalance * Constants.D18, totalLiquidityPoolBalance ); } else { utilizationRate = Constants.MAX_VALUE; utilizationRatePerLeg = Constants.MAX_VALUE; } require( utilizationRate <= _getMaxLpUtilizationRate(), MiltonErrors.LP_UTILIZATION_EXCEEDED ); require( utilizationRatePerLeg <= _getMaxLpUtilizationPerLegRate(), MiltonErrors.LP_UTILIZATION_PER_LEG_EXCEEDED ); } function _emitOpenSwapEvent( uint256 newSwapId, uint256 wadTotalAmount, AmmTypes.NewSwap memory newSwap, MiltonTypes.IporSwapIndicator memory indicator, uint256 direction, uint256 iporPublicationFee ) internal { emit OpenSwap( newSwapId, newSwap.buyer, _asset, MiltonTypes.SwapDirection(direction), AmmTypes.OpenSwapMoney( wadTotalAmount, newSwap.collateral, newSwap.notional, newSwap.openingFeeLPAmount, newSwap.openingFeeTreasuryAmount, iporPublicationFee, newSwap.liquidationDepositAmount * Constants.D18 ), newSwap.openTimestamp, newSwap.openTimestamp + Constants.SWAP_DEFAULT_PERIOD_IN_SECONDS, indicator ); } function _calculateSwapIndicators( uint256 calculateTimestamp, uint256 notional, uint256 quoteValue ) internal view returns (MiltonTypes.IporSwapIndicator memory indicator) { IporTypes.AccruedIpor memory accruedIpor = _iporOracle.getAccruedIndex( calculateTimestamp, _asset ); indicator = MiltonTypes.IporSwapIndicator( accruedIpor.indexValue, accruedIpor.ibtPrice, IporMath.division(notional * Constants.D18, accruedIpor.ibtPrice), quoteValue ); } function _closeSwapPayFixed(IporTypes.IporSwapMemory memory iporSwap, uint256 closeTimestamp) internal returns (uint256 payoutForLiquidator) { require( iporSwap.state == uint256(AmmTypes.SwapState.ACTIVE), MiltonErrors.INCORRECT_SWAP_STATUS ); int256 payoff = _calculatePayoffPayFixed(closeTimestamp, iporSwap); uint256 incomeFeeValue = _calculateIncomeFeeValue(payoff); _getMiltonStorage().updateStorageWhenCloseSwapPayFixed( _msgSender(), iporSwap, payoff, incomeFeeValue, closeTimestamp, _getMinLiquidationThresholdToCloseBeforeMaturity(), _getSecondsBeforeMaturityWhenPositionCanBeClosed() ); uint256 transferredToBuyer; (transferredToBuyer, payoutForLiquidator) = _transferTokensBasedOnPayoff( iporSwap, payoff, incomeFeeValue, closeTimestamp, _getMinLiquidationThresholdToCloseBeforeMaturity(), _getSecondsBeforeMaturityWhenPositionCanBeClosed() ); emit CloseSwap( iporSwap.id, _asset, closeTimestamp, _msgSender(), transferredToBuyer, payoutForLiquidator, incomeFeeValue ); } function _closeSwapReceiveFixed( IporTypes.IporSwapMemory memory iporSwap, uint256 closeTimestamp ) internal returns (uint256 payoutForLiquidator) { require( iporSwap.state == uint256(AmmTypes.SwapState.ACTIVE), MiltonErrors.INCORRECT_SWAP_STATUS ); int256 payoff = _calculatePayoffReceiveFixed(closeTimestamp, iporSwap); uint256 incomeFeeValue = _calculateIncomeFeeValue(payoff); _getMiltonStorage().updateStorageWhenCloseSwapReceiveFixed( _msgSender(), iporSwap, payoff, incomeFeeValue, closeTimestamp, _getMinLiquidationThresholdToCloseBeforeMaturity(), _getSecondsBeforeMaturityWhenPositionCanBeClosed() ); uint256 transferredToBuyer; (transferredToBuyer, payoutForLiquidator) = _transferTokensBasedOnPayoff( iporSwap, payoff, incomeFeeValue, closeTimestamp, _getMinLiquidationThresholdToCloseBeforeMaturity(), _getSecondsBeforeMaturityWhenPositionCanBeClosed() ); emit CloseSwap( iporSwap.id, _asset, closeTimestamp, _msgSender(), transferredToBuyer, payoutForLiquidator, incomeFeeValue ); } function _closeSwapsPayFixed(uint256[] memory swapIds, uint256 closeTimestamp) internal returns ( uint256 payoutForLiquidator, MiltonTypes.IporSwapClosingResult[] memory closedSwaps ) { require( swapIds.length <= _getLiquidationLegLimit(), MiltonErrors.LIQUIDATION_LEG_LIMIT_EXCEEDED ); closedSwaps = new MiltonTypes.IporSwapClosingResult[](swapIds.length); for (uint256 i = 0; i < swapIds.length; i++) { uint256 swapId = swapIds[i]; require(swapId > 0, MiltonErrors.INCORRECT_SWAP_ID); IporTypes.IporSwapMemory memory iporSwap = _getMiltonStorage().getSwapPayFixed(swapId); if (iporSwap.state == uint256(AmmTypes.SwapState.ACTIVE)) { payoutForLiquidator += _closeSwapPayFixed(iporSwap, closeTimestamp); closedSwaps[i] = MiltonTypes.IporSwapClosingResult(swapId, true); } else { closedSwaps[i] = MiltonTypes.IporSwapClosingResult(swapId, false); } } } function _closeSwapsReceiveFixed(uint256[] memory swapIds, uint256 closeTimestamp) internal returns ( uint256 payoutForLiquidator, MiltonTypes.IporSwapClosingResult[] memory closedSwaps ) { require( swapIds.length <= _getLiquidationLegLimit(), MiltonErrors.LIQUIDATION_LEG_LIMIT_EXCEEDED ); closedSwaps = new MiltonTypes.IporSwapClosingResult[](swapIds.length); for (uint256 i = 0; i < swapIds.length; i++) { uint256 swapId = swapIds[i]; require(swapId > 0, MiltonErrors.INCORRECT_SWAP_ID); IporTypes.IporSwapMemory memory iporSwap = _getMiltonStorage().getSwapReceiveFixed( swapId ); if (iporSwap.state == uint256(AmmTypes.SwapState.ACTIVE)) { payoutForLiquidator += _closeSwapReceiveFixed(iporSwap, closeTimestamp); closedSwaps[i] = MiltonTypes.IporSwapClosingResult(swapId, true); } else { closedSwaps[i] = MiltonTypes.IporSwapClosingResult(swapId, false); } } } /** * @notice Function that transfers payout of the swap to the owner. * @dev Function: * # checks if swap profit, loss or maturity allows for liquidataion * # checks if swap's payout is larger than the collateral used to open it * # should the payout be larger than the collateral then it transfers payout to the buyer * @param derivativeItem - Derivative struct * @param payoff - Net earnings of the derivative. Can be positive (swap has a possitive earnings) or negative (swap looses) * @param incomeFeeValue - amount of fee calculated based on payoff. * @param calculationTimestamp - Time for which the calculations in this funciton are run * @param cfgMinLiquidationThresholdToCloseBeforeMaturity - Minimal profit to loss required to put the swap up for the liquidation by non-byer regardless of maturity * @param cfgSecondsBeforeMaturityWhenPositionCanBeClosed - Time before the appointed maturity allowing the liquidation of the swap * for more information on liquidations refer to the documentation https://ipor-labs.gitbook.io/ipor-labs/automated-market-maker/liquidations **/ function _transferTokensBasedOnPayoff( IporTypes.IporSwapMemory memory derivativeItem, int256 payoff, uint256 incomeFeeValue, uint256 calculationTimestamp, uint256 cfgMinLiquidationThresholdToCloseBeforeMaturity, uint256 cfgSecondsBeforeMaturityWhenPositionCanBeClosed ) internal returns (uint256 transferredToBuyer, uint256 payoutForLiquidator) { uint256 absPayoff = IporMath.absoluteValue(payoff); uint256 minPayoffToCloseBeforeMaturity = IporMath.percentOf( derivativeItem.collateral, cfgMinLiquidationThresholdToCloseBeforeMaturity ); if (absPayoff < minPayoffToCloseBeforeMaturity) { //verify if sender is an owner of swap. If not then check if maturity has been reached - if not then reject, if yes then close even if not an owner if (_msgSender() != derivativeItem.buyer) { require( calculationTimestamp >= derivativeItem.endTimestamp - cfgSecondsBeforeMaturityWhenPositionCanBeClosed, MiltonErrors.CANNOT_CLOSE_SWAP_SENDER_IS_NOT_BUYER_AND_NO_MATURITY ); } } if (payoff > 0) { //Buyer earns, Milton looses (transferredToBuyer, payoutForLiquidator) = _transferDerivativeAmount( derivativeItem.buyer, derivativeItem.liquidationDepositAmount, derivativeItem.collateral + absPayoff - incomeFeeValue ); } else { //Milton earns, Buyer looses (transferredToBuyer, payoutForLiquidator) = _transferDerivativeAmount( derivativeItem.buyer, derivativeItem.liquidationDepositAmount, derivativeItem.collateral - absPayoff ); } } /** * @notice Function that transfers the assets at the time of derivative closing * @dev It trasfers the asset to the swap buyer and the liquidator. * Should buyer and the liquidator are the same entity it performs only one transfer. * @param buyer - address that opened the swap * @param liquidationDepositAmount - amount of asset transfered to the liquidator, value represented in 18 decimals * @param transferAmount - amount of asset transfered to the swap owner **/ function _transferDerivativeAmount( address buyer, uint256 liquidationDepositAmount, uint256 transferAmount ) internal returns (uint256 transferredToBuyer, uint256 payoutForLiquidator) { uint256 decimals = _getDecimals(); if (_msgSender() == buyer) { transferAmount = transferAmount + liquidationDepositAmount; } else { //transfer liquidation deposit amount from Milton to Liquidator, // transfer to be made outside this function, to avoid multiple transfers payoutForLiquidator = liquidationDepositAmount; } if (transferAmount > 0) { uint256 transferAmountAssetDecimals = IporMath.convertWadToAssetDecimals( transferAmount, decimals ); //transfer from Milton to Trader IERC20Upgradeable(_asset).safeTransfer(buyer, transferAmountAssetDecimals); transferredToBuyer = IporMath.convertToWad(transferAmountAssetDecimals, decimals); } } //Transfer sum of all liquidation deposits to liquidator /// @param liquidator address of liquidator /// @param liquidationDepositAmount liquidation deposit amount, value represented in 18 decimals function _transferLiquidationDepositAmount(address liquidator, uint256 liquidationDepositAmount) internal { if (liquidationDepositAmount > 0) { IERC20Upgradeable(_asset).safeTransfer( liquidator, IporMath.convertWadToAssetDecimals(liquidationDepositAmount, _getDecimals()) ); } } /** * @notice Function run at the time of the contract upgrade via proxy. Available only to the contract's owner. **/ //solhint-disable no-empty-blocks function _authorizeUpgrade(address) internal override onlyOwner {} } // File: contracts/amm/MiltonUsdt.sol pragma solidity 0.8.16; contract MiltonUsdt is Milton { function _getDecimals() internal pure virtual override returns (uint256) { return 6; } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"appointedOwner","type":"address"}],"name":"AppointedToTransferOwnership","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"swapId","type":"uint256"},{"indexed":false,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"closeTimestamp","type":"uint256"},{"indexed":false,"internalType":"address","name":"liquidator","type":"address"},{"indexed":false,"internalType":"uint256","name":"transferredToBuyer","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"transferredToLiquidator","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"incomeFeeValue","type":"uint256"}],"name":"CloseSwap","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"changedBy","type":"address"},{"indexed":true,"internalType":"address","name":"oldJoseph","type":"address"},{"indexed":true,"internalType":"address","name":"newJoseph","type":"address"}],"name":"JosephChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"changedBy","type":"address"},{"indexed":true,"internalType":"address","name":"oldMiltonSpreadModel","type":"address"},{"indexed":true,"internalType":"address","name":"newMiltonSpreadModel","type":"address"}],"name":"MiltonSpreadModelChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"swapId","type":"uint256"},{"indexed":true,"internalType":"address","name":"buyer","type":"address"},{"indexed":false,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"enum MiltonTypes.SwapDirection","name":"direction","type":"uint8"},{"components":[{"internalType":"uint256","name":"totalAmount","type":"uint256"},{"internalType":"uint256","name":"collateral","type":"uint256"},{"internalType":"uint256","name":"notional","type":"uint256"},{"internalType":"uint256","name":"openingFeeLPAmount","type":"uint256"},{"internalType":"uint256","name":"openingFeeTreasuryAmount","type":"uint256"},{"internalType":"uint256","name":"iporPublicationFee","type":"uint256"},{"internalType":"uint256","name":"liquidationDepositAmount","type":"uint256"}],"indexed":false,"internalType":"struct AmmTypes.OpenSwapMoney","name":"money","type":"tuple"},{"indexed":false,"internalType":"uint256","name":"openTimestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"iporIndexValue","type":"uint256"},{"internalType":"uint256","name":"ibtPrice","type":"uint256"},{"internalType":"uint256","name":"ibtQuantity","type":"uint256"},{"internalType":"uint256","name":"fixedInterestRate","type":"uint256"}],"indexed":false,"internalType":"struct MiltonTypes.IporSwapIndicator","name":"indicator","type":"tuple"}],"name":"OpenSwap","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"buyer","type":"address"},{"internalType":"uint256","name":"openTimestamp","type":"uint256"},{"internalType":"uint256","name":"endTimestamp","type":"uint256"},{"internalType":"uint256","name":"idsIndex","type":"uint256"},{"internalType":"uint256","name":"collateral","type":"uint256"},{"internalType":"uint256","name":"notional","type":"uint256"},{"internalType":"uint256","name":"ibtQuantity","type":"uint256"},{"internalType":"uint256","name":"fixedInterestRate","type":"uint256"},{"internalType":"uint256","name":"liquidationDepositAmount","type":"uint256"},{"internalType":"uint256","name":"state","type":"uint256"}],"internalType":"struct IporTypes.IporSwapMemory","name":"swap","type":"tuple"}],"name":"calculatePayoffPayFixed","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"buyer","type":"address"},{"internalType":"uint256","name":"openTimestamp","type":"uint256"},{"internalType":"uint256","name":"endTimestamp","type":"uint256"},{"internalType":"uint256","name":"idsIndex","type":"uint256"},{"internalType":"uint256","name":"collateral","type":"uint256"},{"internalType":"uint256","name":"notional","type":"uint256"},{"internalType":"uint256","name":"ibtQuantity","type":"uint256"},{"internalType":"uint256","name":"fixedInterestRate","type":"uint256"},{"internalType":"uint256","name":"liquidationDepositAmount","type":"uint256"},{"internalType":"uint256","name":"state","type":"uint256"}],"internalType":"struct IporTypes.IporSwapMemory","name":"swap","type":"tuple"}],"name":"calculatePayoffReceiveFixed","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"calculateSoap","outputs":[{"internalType":"int256","name":"soapPayFixed","type":"int256"},{"internalType":"int256","name":"soapReceiveFixed","type":"int256"},{"internalType":"int256","name":"soap","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"calculateTimestamp","type":"uint256"}],"name":"calculateSoapAtTimestamp","outputs":[{"internalType":"int256","name":"soapPayFixed","type":"int256"},{"internalType":"int256","name":"soapReceiveFixed","type":"int256"},{"internalType":"int256","name":"soap","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"calculateSpread","outputs":[{"internalType":"int256","name":"spreadPayFixed","type":"int256"},{"internalType":"int256","name":"spreadReceiveFixed","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"swapId","type":"uint256"}],"name":"closeSwapPayFixed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"swapId","type":"uint256"}],"name":"closeSwapReceiveFixed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"payFixedSwapIds","type":"uint256[]"},{"internalType":"uint256[]","name":"receiveFixedSwapIds","type":"uint256[]"}],"name":"closeSwaps","outputs":[{"components":[{"internalType":"uint256","name":"swapId","type":"uint256"},{"internalType":"bool","name":"closed","type":"bool"}],"internalType":"struct MiltonTypes.IporSwapClosingResult[]","name":"closedPayFixedSwaps","type":"tuple[]"},{"components":[{"internalType":"uint256","name":"swapId","type":"uint256"},{"internalType":"bool","name":"closed","type":"bool"}],"internalType":"struct MiltonTypes.IporSwapClosingResult[]","name":"closedReceiveFixedSwaps","type":"tuple[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"confirmTransferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"assetAmount","type":"uint256"}],"name":"depositToStanley","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"swapId","type":"uint256"}],"name":"emergencyCloseSwapPayFixed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"swapId","type":"uint256"}],"name":"emergencyCloseSwapReceiveFixed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"swapIds","type":"uint256[]"}],"name":"emergencyCloseSwapsPayFixed","outputs":[{"components":[{"internalType":"uint256","name":"swapId","type":"uint256"},{"internalType":"bool","name":"closed","type":"bool"}],"internalType":"struct MiltonTypes.IporSwapClosingResult[]","name":"closedSwaps","type":"tuple[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"swapIds","type":"uint256[]"}],"name":"emergencyCloseSwapsReceiveFixed","outputs":[{"components":[{"internalType":"uint256","name":"swapId","type":"uint256"},{"internalType":"bool","name":"closed","type":"bool"}],"internalType":"struct MiltonTypes.IporSwapClosingResult[]","name":"closedSwaps","type":"tuple[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAccruedBalance","outputs":[{"components":[{"internalType":"uint256","name":"totalCollateralPayFixed","type":"uint256"},{"internalType":"uint256","name":"totalCollateralReceiveFixed","type":"uint256"},{"internalType":"uint256","name":"liquidityPool","type":"uint256"},{"internalType":"uint256","name":"vault","type":"uint256"}],"internalType":"struct IporTypes.MiltonBalancesMemory","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAsset","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getIncomeFeeRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getIporPublicationFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getJoseph","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLiquidationDepositAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMaxLeverage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMaxLpUtilizationPerLegRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMaxLpUtilizationRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMaxSwapCollateralAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMiltonSpreadModel","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMinLeverage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOpeningFeeRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOpeningFeeTreasuryPortionRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVersion","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getWadLiquidationDepositAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"address","name":"iporOracle","type":"address"},{"internalType":"address","name":"miltonStorage","type":"address"},{"internalType":"address","name":"miltonSpreadModel","type":"address"},{"internalType":"address","name":"stanley","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"totalAmount","type":"uint256"},{"internalType":"uint256","name":"acceptableFixedInterestRate","type":"uint256"},{"internalType":"uint256","name":"leverage","type":"uint256"}],"name":"openSwapPayFixed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"totalAmount","type":"uint256"},{"internalType":"uint256","name":"acceptableFixedInterestRate","type":"uint256"},{"internalType":"uint256","name":"leverage","type":"uint256"}],"name":"openSwapReceiveFixed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newJoseph","type":"address"}],"name":"setJoseph","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newMiltonSpreadModel","type":"address"}],"name":"setMiltonSpreadModel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"setupMaxAllowanceForAsset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"appointedOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"withdrawAllFromStanley","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"assetAmount","type":"uint256"}],"name":"withdrawFromStanley","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60a0604052306080523480156200001557600080fd5b506200002062000026565b620000e8565b600054610100900460ff1615620000935760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff9081161015620000e6576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b6080516155bb6200012060003960008181610b2e01528181610bb301528181610cf301528181610d780152610e6201526155bb6000f3fe6080604052600436106103085760003560e01c80637b2875171161019a578063aff7079d116100e1578063e14f5e6a1161008a578063f72c51af11610064578063f72c51af1461082b578063f79bcf951461084b578063fe86b6121461086b57600080fd5b8063e14f5e6a146107d1578063ea692f20146107eb578063f2fde38b1461080b57600080fd5b8063cc29516a116100bb578063cc29516a1461079c578063d3893ca114610543578063dd64d8e1146107b157600080fd5b8063aff7079d1461073e578063b456923614610768578063c7ec170c1461077c57600080fd5b80638da5cb5b116101435780639e9456571161011d5780639e945657146106e9578063a9ad627c146106fe578063acd50b841461071e57600080fd5b80638da5cb5b1461068b57806395716ef0146106a95780639a0e88cc146106c957600080fd5b806383b7cbf71161017457806383b7cbf71461063b5780638456cb591461065b5780638ad700991461067057600080fd5b80637b287517146105d25780637d8c6c89146105ed57806381434f491461061b57600080fd5b80633659cfe61161025e57806352d1902d116102075780635c975abb116101e15780635c975abb1461057d5780636cfa7788146105a0578063715018a6146105bd57600080fd5b806352d1902d1461052e57806355b1ce61146105435780635c222bad1461055e57600080fd5b806342ed62391161023857806342ed6239146104e75780634b987d3c146105065780634f1ef2861461051b57600080fd5b80633659cfe6146104925780633f4ba83a146104b257806342c7294c146104c757600080fd5b806312dbd190116102c05780631f8338f21161029a5780631f8338f21461040a57806321f0eb5d146104375780632ed543411461047257600080fd5b806312dbd190146103b357806314f559fb146103c85780631f5d06b7146103e857600080fd5b80630d8e6e2c116102f15780630d8e6e2c146103655780630ea8b3bf14610383578063104f20731461039f57600080fd5b806304a566271461030d5780630c1b06e614610338575b600080fd5b34801561031957600080fd5b50610322610886565b60405161032f9190614a81565b60405180910390f35b34801561034457600080fd5b50610358610353366004614b92565b6108be565b60405161032f9190614c0f565b34801561037157600080fd5b5060025b60405190815260200161032f565b34801561038f57600080fd5b50683635c9adc5dea00000610375565b3480156103ab57600080fd5b506000610375565b3480156103bf57600080fd5b506103756108e0565b3480156103d457600080fd5b506103586103e3366004614b92565b6108f5565b3480156103f457600080fd5b50610408610403366004614c22565b610911565b005b34801561041657600080fd5b5061041f61092e565b6040516001600160a01b03909116815260200161032f565b34801561044357600080fd5b50610457610452366004614c22565b610943565b6040805193845260208401929092529082015260600161032f565b34801561047e57600080fd5b5061040861048d366004614c22565b610965565b34801561049e57600080fd5b506104086104ad366004614c60565b610b24565b3480156104be57600080fd5b50610408610c9c565b3480156104d357600080fd5b506104086104e2366004614c22565b610cae565b3480156104f357600080fd5b50610133546001600160a01b031661041f565b34801561051257600080fd5b50610457610cc8565b610408610529366004614c7d565b610ce9565b34801561053a57600080fd5b50610375610e55565b34801561054f57600080fd5b50678ac7230489e80000610375565b34801561056a57600080fd5b5061012e546001600160a01b031661041f565b34801561058957600080fd5b5060335460ff16604051901515815260200161032f565b3480156105ac57600080fd5b5069152d02c7e14af6800000610375565b3480156105c957600080fd5b50610408610f1a565b3480156105de57600080fd5b506706a94d74f4300000610375565b3480156105f957600080fd5b5061060d610608366004614d25565b610f2c565b60405161032f929190614d89565b34801561062757600080fd5b50610408610636366004614c22565b610fa9565b34801561064757600080fd5b50610375610656366004614dae565b61101a565b34801561066757600080fd5b50610408611094565b34801561067c57600080fd5b5067016345785d8a0000610375565b34801561069757600080fd5b5060fb546001600160a01b031661041f565b3480156106b557600080fd5b506104086106c4366004614c60565b6110a4565b3480156106d557600080fd5b506104086106e4366004614c22565b61116f565b3480156106f557600080fd5b506104086112ed565b34801561070a57600080fd5b50610408610719366004614c60565b611494565b34801561072a57600080fd5b50610375610739366004614dae565b61155f565b34801561074a57600080fd5b506107536115cc565b6040805192835260208301919091520161032f565b34801561077457600080fd5b506019610375565b34801561078857600080fd5b50610375610797366004614dda565b6115e1565b3480156107a857600080fd5b506104086115ed565b3480156107bd57600080fd5b506104086107cc366004614e82565b611669565b3480156107dd57600080fd5b50662386f26fc10000610375565b3480156107f757600080fd5b50610408610806366004614c22565b611a28565b34801561081757600080fd5b50610408610826366004614c60565b611a91565b34801561083757600080fd5b50610375610846366004614dda565b611b2b565b34801561085757600080fd5b50610408610866366004614c60565b611b37565b34801561087757600080fd5b50670b1a2bc2ec500000610375565b6108b16040518060800160405280600081526020016000815260200160008152602001600081525090565b6108b9611b61565b905090565b60606108c8611d33565b6108d0611d8d565b6108da8242611ddf565b92915050565b60006108b9670de0b6b3a76400006019614f1a565b60606108ff611d33565b610907611d8d565b6108da8242611e02565b610919611d33565b610921611d8d565b61092b8142611e10565b50565b60006108b961012f546001600160a01b031690565b60008060008060008061095587611eec565b9199909850909650945050505050565b61012f5460408051808201909152600881526749504f525f33323760c01b6020820152906001600160a01b031633146109ba5760405162461bcd60e51b81526004016109b19190614f5d565b60405180910390fd5b50600260655403610a0d5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016109b1565b6002606555610a1a612017565b600080610a30610130546001600160a01b031690565b6001600160a01b031663b6b55f25846040518263ffffffff1660e01b8152600401610a5d91815260200190565b60408051808303816000875af1158015610a7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a9f9190614f90565b91509150610ab6610132546001600160a01b031690565b604051630ea3e11d60e41b815260048101839052602481018490526001600160a01b03919091169063ea3e11d0906044015b600060405180830381600087803b158015610b0257600080fd5b505af1158015610b16573d6000803e3d6000fd5b505060016065555050505050565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610bb15760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201526b19195b1959d85d1958d85b1b60a21b60648201526084016109b1565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610c0c7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b031614610c775760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201526b6163746976652070726f787960a01b60648201526084016109b1565b610c808161206a565b6040805160008082526020820190925261092b91839190612072565b610ca4611d33565b610cac612212565b565b610cb6611d33565b610cbe611d8d565b61092b8142612264565b600080600080600080610cda42611eec565b91989097509095509350505050565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610d765760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201526b19195b1959d85d1958d85b1b60a21b60648201526084016109b1565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610dd17f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b031614610e3c5760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201526b6163746976652070726f787960a01b60648201526084016109b1565b610e458261206a565b610e5182826001612072565b5050565b6000306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610ef55760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c000000000000000060648201526084016109b1565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b610f22611d33565b610cac6000612336565b606080600260655403610f815760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016109b1565b6002606555610f8e612017565b610f99848442612388565b6001606555909590945092505050565b600260655403610ffb5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016109b1565b6002606555611008612017565b6110128142611e10565b506001606555565b600060026065540361106e5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016109b1565b600260655561107b612017565b61108742858585612416565b6001606555949350505050565b61109c611d33565b610cac612767565b6110ac611d33565b6110b4612017565b604080518082019091526008815267049504f525f3030360c41b60208201526001600160a01b0382166110fa5760405162461bcd60e51b81526004016109b19190614f5d565b50600061111061012f546001600160a01b031690565b61013380546001600160a01b0319166001600160a01b038581169182179092559192508216336001600160a01b03167fb7debb5296f100d248b04d5797aa5c2bec5a0f4df0fb2322d89200d186876fee60405160405180910390a45050565b6002606554036111c15760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016109b1565b600260655561012f5460408051808201909152600881526749504f525f33323760c01b6020820152906001600160a01b031633146112125760405162461bcd60e51b81526004016109b19190614f5d565b5061121b612017565b600080611231610130546001600160a01b031690565b6001600160a01b0316632e1a7d4d846040518263ffffffff1660e01b815260040161125e91815260200190565b60408051808303816000875af115801561127c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112a09190614f90565b915091506112b7610132546001600160a01b031690565b604051638093495360e01b815260048101849052602481018390526001600160a01b039190911690638093495390604401610ae8565b60026065540361133f5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016109b1565b600260655561012f5460408051808201909152600881526749504f525f33323760c01b6020820152906001600160a01b031633146113905760405162461bcd60e51b81526004016109b19190614f5d565b50611399612017565b6000806113af610130546001600160a01b031690565b6001600160a01b031663853828b66040518163ffffffff1660e01b815260040160408051808303816000875af11580156113ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114119190614f90565b91509150611428610132546001600160a01b031690565b604051638093495360e01b815260048101849052602481018390526001600160a01b039190911690638093495390604401600060405180830381600087803b15801561147357600080fd5b505af1158015611487573d6000803e3d6000fd5b5050600160655550505050565b61149c611d33565b6114a4612017565b604080518082019091526008815267049504f525f3030360c41b60208201526001600160a01b0382166114ea5760405162461bcd60e51b81526004016109b19190614f5d565b50600061150061012f546001600160a01b031690565b61012f80546001600160a01b0319166001600160a01b038581169182179092559192508216336001600160a01b03167f06ea73dbb4731e0e49efac50d8fc99a6c33ba25502ad309407268874309fc95960405160405180910390a45050565b60006002606554036115b35760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016109b1565b60026065556115c0612017565b611087428585856127a4565b6000806115d842612aca565b90939092509050565b60006108da4283612c49565b61012d5460408051808201909152600881527f49504f525f3030370000000000000000000000000000000000000000000000006020820152906001600160a01b0316331461164e5760405162461bcd60e51b81526004016109b19190614f5d565b5061012d80546001600160a01b0319169055610cac33612336565b600054610100900460ff16158080156116895750600054600160ff909116105b806116a35750303b1580156116a3575060005460ff166001145b6117155760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016109b1565b6000805460ff191660011790558015611738576000805461ff0019166101001790555b611740612ce6565b611748612d59565b611750612dcc565b604080518082019091526008815267049504f525f3030360c41b60208201526001600160a01b0387166117965760405162461bcd60e51b81526004016109b19190614f5d565b50604080518082019091526008815267049504f525f3030360c41b60208201526001600160a01b0386166117dd5760405162461bcd60e51b81526004016109b19190614f5d565b50604080518082019091526008815267049504f525f3030360c41b60208201526001600160a01b0385166118245760405162461bcd60e51b81526004016109b19190614f5d565b50604080518082019091526008815267049504f525f3030360c41b60208201526001600160a01b03841661186b5760405162461bcd60e51b81526004016109b19190614f5d565b50604080518082019091526008815267049504f525f3030360c41b60208201526001600160a01b0383166118b25760405162461bcd60e51b81526004016109b19190614f5d565b50856001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119159190614fb4565b60ff166006146040518060400160405280600881526020017f49504f525f3030310000000000000000000000000000000000000000000000008152509061196f5760405162461bcd60e51b81526004016109b19190614f5d565b50861561197e5761197e612767565b61013280546001600160a01b03199081166001600160a01b0387811691909117909255610133805482168684161790556101318054821688841617905561012e8054821689841617905561013080549091169184169190911790558015611a1f576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b600260655403611a7a5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016109b1565b6002606555611a87612017565b6110128142612264565b611a99611d33565b604080518082019091526008815267049504f525f3030360c41b60208201526001600160a01b038216611adf5760405162461bcd60e51b81526004016109b19190614f5d565b5061012d80546001600160a01b0319166001600160a01b0383169081179091556040517f3ec7bb1d452f3c36260fa8ef678a597fd97574d8ec42f6dc98ffce3dbc91228f90600090a250565b60006108da4283612e37565b611b3f611d33565b611b47612017565b61012e5461092b906001600160a01b031682600019612ecd565b611b8c6040518060800160405280600081526020016000815260200160008152602001600081525090565b6000611ba1610132546001600160a01b031690565b6001600160a01b03166312065fe06040518163ffffffff1660e01b8152600401608060405180830381865afa158015611bde573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c02919061503d565b90506000611c19610130546001600160a01b031690565b604051630dd59a7360e31b81523060048201526001600160a01b039190911690636eacd39890602401602060405180830381865afa158015611c5f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c839190615059565b90506000611c948360600151612fcd565b611c9d83612fcd565b611caa8560400151612fcd565b611cb49190615072565b611cbe919061509a565b905060008112156040518060400160405280600881526020017f49504f525f33303100000000000000000000000000000000000000000000000081525090611d195760405162461bcd60e51b81526004016109b19190614f5d565b50611d2381613069565b6040840152506060820152919050565b60fb546001600160a01b03163314610cac5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016109b1565b60335460ff16610cac5760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f742070617573656400000000000000000000000060448201526064016109b1565b60606000611ded84846130bb565b92509050611dfb338261330b565b5092915050565b60606000611ded8484613334565b60408051808201909152600881526724a827a92f99981b60c11b602082015282611e4d5760405162461bcd60e51b81526004016109b19190614f5d565b506000611e63610132546001600160a01b031690565b6001600160a01b0316638ec2bcfa846040518263ffffffff1660e01b8152600401611e9091815260200190565b61016060405180830381865afa158015611eae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ed291906150c5565b9050611ee733611ee2838561357c565b61330b565b505050565b600080600080611f05610131546001600160a01b031690565b61012e54604051630e5c712960e01b81526001600160a01b03918216600482015260248101889052911690630e5c712990604401602060405180830381865afa158015611f56573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f7a9190615059565b90506000806000611f94610132546001600160a01b031690565b60405163068d2af760e01b815260048101869052602481018a90526001600160a01b03919091169063068d2af790604401606060405180830381865afa158015611fe2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612006919061515f565b919a90995090975095505050505050565b60335460ff1615610cac5760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a207061757365640000000000000000000000000000000060448201526064016109b1565b61092b611d33565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff16156120a557611ee7836136fd565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156120ff575060408051601f3d908101601f191682019092526120fc91810190615059565b60015b6121715760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201527f6f6e206973206e6f74205555505300000000000000000000000000000000000060648201526084016109b1565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81146122065760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f7860448201527f6961626c6555554944000000000000000000000000000000000000000000000060648201526084016109b1565b50611ee78383836137bb565b61221a611d8d565b6033805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b60408051808201909152600881526724a827a92f99981b60c11b6020820152826122a15760405162461bcd60e51b81526004016109b19190614f5d565b5060006122b7610132546001600160a01b031690565b6001600160a01b0316632dae1d9b846040518263ffffffff1660e01b81526004016122e491815260200190565b61016060405180830381865afa158015612302573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061232691906150c5565b9050611ee733611ee283856137e0565b60fb80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b606080600a85511115801561239f5750600a845111155b6040518060400160405280600881526020016749504f525f33313560c01b815250906123de5760405162461bcd60e51b81526004016109b19190614f5d565b506000806123ec8786613334565b945091506123fa86866130bb565b9350905061240c33611ee2838561518d565b5050935093915050565b60008061242486868561386d565b9050600061243b610132546001600160a01b031690565b6001600160a01b03166312065fe06040518163ffffffff1660e01b8152600401608060405180830381865afa158015612478573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061249c919061503d565b9050816060015181604001516124b2919061518d565b6040820152602082015181516124c8919061518d565b808252604082015160208301516124e992906124e4908261518d565b613ce0565b6101335460e083015160405163b1b0ce9f60e01b81526000926001600160a01b03169163b1b0ce9f91612521919086906004016151a0565b602060405180830381865afa15801561253e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125629190615059565b90506000861180156125745750858111155b6040518060400160405280600881526020016749504f525f33313360c01b815250906125b35760405162461bcd60e51b81526004016109b19190614f5d565b5060006125c589856040015184613ded565b905060006040518061012001604052806125dc3390565b6001600160a01b031681526020018b8152602001866020015181526020018660400151815260200183604001518152602001836060015181526020018660c0015181526020018660600151815260200186608001518152509050600061264b610132546001600160a01b031690565b6001600160a01b031663bd612fa783678ac7230489e800006040805160e085811b6001600160e01b031916825284516001600160a01b0316600483015260208501516024830152918401516044820152606084015160648201526080840151608482015260a084015160a482015260c084015160c48201529083015160e482015261010090920151610104830152610124820152610144016020604051808303816000875af1158015612702573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127269190615059565b9050612742335b61012e546001600160a01b031690308d613ee4565b612759818760000151848660008b60a00151613f1c565b9a9950505050505050505050565b61276f612017565b6033805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586122473390565b6000806127b286868561386d565b905060006127c9610132546001600160a01b031690565b6001600160a01b03166312065fe06040518163ffffffff1660e01b8152600401608060405180830381865afa158015612806573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061282a919061503d565b905081606001518160400151612840919061518d565b604082015260208083015190820151612859919061518d565b602082018190526040820151825161287792906124e490829061518d565b6101335460e0830151604051630232bd5760e01b81526000926001600160a01b031691630232bd57916128af919086906004016151a0565b602060405180830381865afa1580156128cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128f09190615059565b9050808611156040518060400160405280600881526020016749504f525f33313360c01b815250906129355760405162461bcd60e51b81526004016109b19190614f5d565b50600061294789856040015184613ded565b9050600060405180610120016040528061295e3390565b6001600160a01b031681526020018b8152602001866020015181526020018660400151815260200183604001518152602001836060015181526020018660c001518152602001866060015181526020018660800151815250905060006129cd610132546001600160a01b031690565b6001600160a01b031663ba32677583678ac7230489e800006040805160e085811b6001600160e01b031916825284516001600160a01b0316600483015260208501516024830152918401516044820152606084015160648201526080840151608482015260a084015160a482015260c084015160c48201529083015160e482015261010090920151610104830152610124820152610144016020604051808303816000875af1158015612a84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612aa89190615059565b9050612ab33361272d565b612759818760000151848660018b60a00151613f1c565b6101315461012e54604051635491ab6f60e01b8152600481018490526001600160a01b03918216602482015260009283928392911690635491ab6f90604401608060405180830381865afa158015612b26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b4a919061503d565b90506000612b56611b61565b6101335460405163134cfb6f60e21b81529192506001600160a01b0316908190634d33edbc90612b8c90869086906004016151a0565b602060405180830381865afa158015612ba9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bcd9190615059565b60405163040b162160e01b81529095506001600160a01b0382169063040b162190612bfe90869086906004016151a0565b602060405180830381865afa158015612c1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c3f9190615059565b9350505050915091565b6000612cdf83612c62610131546001600160a01b031690565b61012e54604051630e5c712960e01b81526001600160a01b03918216600482015260248101889052911690630e5c712990604401602060405180830381865afa158015612cb3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cd79190615059565b849190613ff4565b9392505050565b600054610100900460ff16612d515760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b60648201526084016109b1565b610cac614059565b600054610100900460ff16612dc45760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b60648201526084016109b1565b610cac6140d0565b600054610100900460ff16610cac5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b60648201526084016109b1565b6000612cdf83612e50610131546001600160a01b031690565b61012e54604051630e5c712960e01b81526001600160a01b03918216600482015260248101889052911690630e5c712990604401602060405180830381865afa158015612ea1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ec59190615059565b849190614144565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa158015612f1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f429190615059565b612f4c919061518d565b6040516001600160a01b038516602482015260448101829052909150612fc790859063095ea7b360e01b906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b031990931692909217909152614175565b50505050565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8211156130655760405162461bcd60e51b815260206004820152602860248201527f53616665436173743a2076616c756520646f65736e27742066697420696e206160448201527f6e20696e7432353600000000000000000000000000000000000000000000000060648201526084016109b1565b5090565b6000808212156130655760405162461bcd60e51b815260206004820181905260248201527f53616665436173743a2076616c7565206d75737420626520706f73697469766560448201526064016109b1565b60006060600a845111156040518060400160405280600881526020016749504f525f33313560c01b815250906131045760405162461bcd60e51b81526004016109b19190614f5d565b50835167ffffffffffffffff81111561311f5761311f614aac565b60405190808252806020026020018201604052801561316457816020015b604080518082019091526000808252602082015281526020019060019003908161313d5790505b50905060005b8451811015613303576000858281518110613187576131876151ec565b60200260200101519050600081116040518060400160405280600881526020016724a827a92f99981b60c11b815250906131d45760405162461bcd60e51b81526004016109b19190614f5d565b5060006131ea610132546001600160a01b031690565b6001600160a01b0316638ec2bcfa836040518263ffffffff1660e01b815260040161321791815260200190565b61016060405180830381865afa158015613235573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061325991906150c5565b90506001816101400151036132b857613272818761357c565b61327c908661518d565b94506040518060400160405280838152602001600115158152508484815181106132a8576132a86151ec565b60200260200101819052506132ee565b6040518060400160405280838152602001600015158152508484815181106132e2576132e26151ec565b60200260200101819052505b505080806132fb90615218565b91505061316a565b509250929050565b8015610e5157610e518261332083600661425a565b61012e546001600160a01b031691906142ba565b60006060600a845111156040518060400160405280600881526020016749504f525f33313560c01b8152509061337d5760405162461bcd60e51b81526004016109b19190614f5d565b50835167ffffffffffffffff81111561339857613398614aac565b6040519080825280602002602001820160405280156133dd57816020015b60408051808201909152600080825260208201528152602001906001900390816133b65790505b50905060005b8451811015613303576000858281518110613400576134006151ec565b60200260200101519050600081116040518060400160405280600881526020016724a827a92f99981b60c11b8152509061344d5760405162461bcd60e51b81526004016109b19190614f5d565b506000613463610132546001600160a01b031690565b6001600160a01b0316632dae1d9b836040518263ffffffff1660e01b815260040161349091815260200190565b61016060405180830381865afa1580156134ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134d291906150c5565b9050600181610140015103613531576134eb81876137e0565b6134f5908661518d565b9450604051806040016040528083815260200160011515815250848481518110613521576135216151ec565b6020026020010181905250613567565b60405180604001604052808381526020016000151581525084848151811061355b5761355b6151ec565b60200260200101819052505b5050808061357490615218565b9150506133e3565b60006001836101400151146040518060400160405280600881526020016749504f525f33303760c01b815250906135c65760405162461bcd60e51b81526004016109b19190614f5d565b5060006135d38385612c49565b905060006135e0826142ea565b90506135f5610132546001600160a01b031690565b6001600160a01b0316631c2d5acf335b87858589670dbd2fc137a300006154606040518863ffffffff1660e01b81526004016136379796959493929190615231565b600060405180830381600087803b15801561365157600080fd5b505af1158015613665573d6000803e3d6000fd5b50505050600061368986848488613681670dbd2fc137a3000090565b615460614319565b875161012e54604080516001600160a01b039092168252602082018a90523382820152606082018590526080820184905260a0820187905251929750929350917f419c5630beff01fc1dac4344c91200ab09a9c8883e550a75e31a391e4142dcc1919081900360c00190a250505092915050565b6001600160a01b0381163b61377a5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e74726163740000000000000000000000000000000000000060648201526084016109b1565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b6137c48361443b565b6000825111806137d15750805b15611ee757612fc7838361447b565b60006001836101400151146040518060400160405280600881526020016749504f525f33303760c01b8152509061382a5760405162461bcd60e51b81526004016109b19190614f5d565b5060006138378385612e37565b90506000613844826142ea565b9050613859610132546001600160a01b031690565b6001600160a01b031663f2980a1833613605565b613875614a14565b60408051808201909152600881527f49504f525f3331300000000000000000000000000000000000000000000000006020820152836138c75760405162461bcd60e51b81526004016109b19190614f5d565b5061012e5483906001600160a01b03166370a08231336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015613921573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139459190615059565b10156040518060400160405280600881526020017f49504f525f3030330000000000000000000000000000000000000000000000008152509061399b5760405162461bcd60e51b81526004016109b19190614f5d565b5060006139a9846006614586565b9050678ac7230489e800008310156040518060400160405280600881526020017f49504f525f33303800000000000000000000000000000000000000000000000081525090613a0b5760405162461bcd60e51b81526004016109b19190614f5d565b5060408051808201909152600881527f49504f525f3330390000000000000000000000000000000000000000000000006020820152683635c9adc5dea00000841115613a6a5760405162461bcd60e51b81526004016109b19190614f5d565b5060196000613a81670de0b6b3a764000083614f1a565b9050613a95678ac7230489e800008261518d565b83116040518060400160405280600881526020016749504f525f33313160c01b81525090613ad65760405162461bcd60e51b81526004016109b19190614f5d565b5060008080613af7868986678ac7230489e80000662386f26fc100006145c7565b925092509250600080613b1183613b0c600090565b614633565b91509150613b2669152d02c7e14af680000090565b8511156040518060400160405280600881526020017f49504f525f33313200000000000000000000000000000000000000000000000081525090613b7d5760405162461bcd60e51b81526004016109b19190614f5d565b5082613b91678ac7230489e800008861518d565b613b9b919061518d565b88116040518060400160405280600881526020016749504f525f33313160c01b81525090613bdc5760405162461bcd60e51b81526004016109b19190614f5d565b50604051806101000160405280898152602001868152602001858152602001838152602001828152602001613c16678ac7230489e8000090565b815260200188815260200161013160009054906101000a90046001600160a01b03166001600160a01b0316635491ab6f8f61012e60009054906101000a90046001600160a01b03166040518363ffffffff1660e01b8152600401613c8d9291909182526001600160a01b0316602082015260400190565b608060405180830381865afa158015613caa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cce919061503d565b90529c9b505050505050505050505050565b6000808415613d2257613d04613cfe670de0b6b3a764000085614f1a565b86614658565b9150613d1b613cfe670de0b6b3a764000086614f1a565b9050613d2a565b506000199050805b60408051808201909152600881527f49504f525f3330320000000000000000000000000000000000000000000000006020820152670b1a2bc2ec500000831115613d875760405162461bcd60e51b81526004016109b19190614f5d565b5060408051808201909152600881527f49504f525f33303300000000000000000000000000000000000000000000000060208201526706a94d74f4300000821115613de55760405162461bcd60e51b81526004016109b19190614f5d565b505050505050565b613e186040518060800160405280600081526020016000815260200160008152602001600081525090565b6101315461012e54604051635491ab6f60e01b8152600481018790526001600160a01b0391821660248201526000929190911690635491ab6f90604401608060405180830381865afa158015613e72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e96919061503d565b6040805160808101825282518152602080840151908201529192508101613ed2613ec8670de0b6b3a764000088614f1a565b8460200151614658565b81526020019390935250909392505050565b6040516001600160a01b0380851660248301528316604482015260648101829052612fc79085906323b872dd60e01b90608401612f7b565b835161012e546001600160a01b039182169188917f29267df9e90ec6126925ee936b6dc88a7da741b06bcd364f02acf9d38a7b97f79116856001811115613f6557613f65615202565b6040518060e001604052808b81526020018a6040015181526020018a6060015181526020018a60e0015181526020018a61010001518152602001878152602001670de0b6b3a76400008b60c00151613fbd9190614f1a565b905260208a0151613fd16224ea008261518d565b8a604051613fe496959493929190615300565b60405180910390a3505050505050565b600080600061400486868661467a565b9150915061404f8660a0015161404a61401c84612fcd565b61402586612fcd565b61402f919061509a565b6140456301e13380670de0b6b3a7640000614f1a565b614717565b614739565b9695505050505050565b600054610100900460ff166140c45760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b60648201526084016109b1565b6033805460ff19169055565b600054610100900460ff1661413b5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b60648201526084016109b1565b610cac33612336565b600080600061415486868661467a565b9150915061404f8660a0015161404a61416c85612fcd565b61402585612fcd565b60006141ca826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661478b9092919063ffffffff16565b805190915015611ee757808060200190518101906141e891906153b6565b611ee75760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016109b1565b60008160120361426b5750816108da565b601282111561429b5761427f6012836153d3565b61428a90600a6154c2565b6142949084614f1a565b90506108da565b614294836142aa8460126153d3565b6142b590600a6154c2565b614658565b6040516001600160a01b038316602482015260448101829052611ee790849063a9059cbb60e01b90606401612f7b565b60006108da67016345785d8a0000614301846147a2565b61430b9190614f1a565b670de0b6b3a7640000614658565b6000806000614327886147a2565b905060006143398a60a00151876147ba565b9050808210156143c95760208a01516001600160a01b0316336001600160a01b0316146143c957848a6060015161437091906153d3565b8710156040518060400160405280600881526020017f49504f525f333231000000000000000000000000000000000000000000000000815250906143c75760405162461bcd60e51b81526004016109b19190614f5d565b505b600089131561440a576144008a602001518b61012001518a858e60a001516143f1919061518d565b6143fb91906153d3565b6147c9565b909450925061442e565b6144288a602001518b6101200151848d60a001516143fb91906153d3565b90945092505b5050965096945050505050565b614444816136fd565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606001600160a01b0383163b6144fa5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084016109b1565b600080846001600160a01b03168460405161451591906154ce565b600060405180830381855af49150503d8060008114614550576040519150601f19603f3d011682016040523d82523d6000602084013e614555565b606091505b509150915061457d828260405180606001604052806027815260200161555f60279139614837565b95945050505050565b600082156145c0578160120361459d5750816108da565b60128211156145b557614294836142aa6012856153d3565b61427f8260126153d3565b50816108da565b60008080614608670de0b6b3a7640000866145e2898c6153d3565b6145ec91906153d3565b6145f69190614f1a565b6142b586670de0b6b3a764000061518d565b925061461761430b8489614f1a565b915061462661430b8585614f1a565b9050955095509592505050565b60008061464361430b8486614f1a565b905061464f81856153d3565b91509250929050565b600081614666600282615500565b614670908561518d565b612cdf9190615500565b60008084604001518410156040518060400160405280600881526020017f49504f525f333139000000000000000000000000000000000000000000000000815250906146d95760405162461bcd60e51b81526004016109b19190614f5d565b506146fd8560c001518661010001518760400151876146f891906153d3565b614870565b915061470d8560e00151846148b1565b9050935093915050565b600081614725600282615514565b61472f9085615072565b612cdf9190615514565b60008061474584612fcd565b90506000831315614761578083121561429457829150506108da565b61476a81615542565b8312156147825761477a81615542565b9150506108da565b829150506108da565b606061479a84846000856148cc565b949350505050565b60008082126147b157816108da565b6108da82615542565b6000612cdf61430b8385614f1a565b60008060066001600160a01b03861633036147ef576147e8858561518d565b93506147f3565b8491505b831561482e576000614805858361425a565b61012e54909150614820906001600160a01b031688836142ba565b61482a8183614586565b9350505b50935093915050565b60608315614846575081612cdf565b8251156148565782518084602001fd5b8160405162461bcd60e51b81526004016109b19190614f5d565b60008161487d8486614f1a565b6148879190614f1a565b61489d6301e13380670de0b6b3a7640000614f1a565b6148a79086614f1a565b61479a919061518d565b60006301e133806148c28385614f1a565b612cdf9190614f1a565b6060824710156149445760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016109b1565b6001600160a01b0385163b61499b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109b1565b600080866001600160a01b031685876040516149b791906154ce565b60006040518083038185875af1925050503d80600081146149f4576040519150601f19603f3d011682016040523d82523d6000602084013e6149f9565b606091505b5091509150614a09828286614837565b979650505050505050565b60405180610100016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001614a7c6040518060800160405280600081526020016000815260200160008152602001600081525090565b905290565b81518152602080830151908201526040808301519082015260608083015190820152608081016108da565b634e487b7160e01b600052604160045260246000fd5b604051610160810167ffffffffffffffff81118282101715614ae657614ae6614aac565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715614b1557614b15614aac565b604052919050565b600082601f830112614b2e57600080fd5b8135602067ffffffffffffffff821115614b4a57614b4a614aac565b8160051b614b59828201614aec565b9283528481018201928281019087851115614b7357600080fd5b83870192505b84831015614a0957823582529183019190830190614b79565b600060208284031215614ba457600080fd5b813567ffffffffffffffff811115614bbb57600080fd5b61479a84828501614b1d565b600081518084526020808501945080840160005b83811015614c045781518051885283015115158388015260409096019590820190600101614bdb565b509495945050505050565b602081526000612cdf6020830184614bc7565b600060208284031215614c3457600080fd5b5035919050565b6001600160a01b038116811461092b57600080fd5b8035614c5b81614c3b565b919050565b600060208284031215614c7257600080fd5b8135612cdf81614c3b565b60008060408385031215614c9057600080fd5b8235614c9b81614c3b565b915060208381013567ffffffffffffffff80821115614cb957600080fd5b818601915086601f830112614ccd57600080fd5b813581811115614cdf57614cdf614aac565b614cf1601f8201601f19168501614aec565b91508082528784828501011115614d0757600080fd5b80848401858401376000848284010152508093505050509250929050565b60008060408385031215614d3857600080fd5b823567ffffffffffffffff80821115614d5057600080fd5b614d5c86838701614b1d565b93506020850135915080821115614d7257600080fd5b50614d7f85828601614b1d565b9150509250929050565b604081526000614d9c6040830185614bc7565b828103602084015261457d8185614bc7565b600080600060608486031215614dc357600080fd5b505081359360208301359350604090920135919050565b60006101608284031215614ded57600080fd5b614df5614ac2565b82358152614e0560208401614c50565b602082015260408301356040820152606083013560608201526080830135608082015260a083013560a082015260c083013560c082015260e083013560e08201526101008084013581830152506101208084013581830152506101408084013581830152508091505092915050565b801515811461092b57600080fd5b60008060008060008060c08789031215614e9b57600080fd5b8635614ea681614e74565b95506020870135614eb681614c3b565b94506040870135614ec681614c3b565b93506060870135614ed681614c3b565b92506080870135614ee681614c3b565b915060a0870135614ef681614c3b565b809150509295509295509295565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615614f3457614f34614f04565b500290565b60005b83811015614f54578181015183820152602001614f3c565b50506000910152565b6020815260008251806020840152614f7c816040850160208701614f39565b601f01601f19169190910160400192915050565b60008060408385031215614fa357600080fd5b505080516020909101519092909150565b600060208284031215614fc657600080fd5b815160ff81168114612cdf57600080fd5b600060808284031215614fe957600080fd5b6040516080810181811067ffffffffffffffff8211171561500c5761500c614aac565b8060405250809150825181526020830151602082015260408301516040820152606083015160608201525092915050565b60006080828403121561504f57600080fd5b612cdf8383614fd7565b60006020828403121561506b57600080fd5b5051919050565b808201828112600083128015821682158216171561509257615092614f04565b505092915050565b8181036000831280158383131683831282161715611dfb57611dfb614f04565b8051614c5b81614c3b565b600061016082840312156150d857600080fd5b6150e0614ac2565b825181526150f0602084016150ba565b602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e08201526101008084015181830152506101208084015181830152506101408084015181830152508091505092915050565b60008060006060848603121561517457600080fd5b8351925060208401519150604084015190509250925092565b808201808211156108da576108da614f04565b82518152602080840151818301526040808501518184015260608086015181850152845160808501529184015160a084015283015160c083015282015160e08201526101008101612cdf565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b60006001820161522a5761522a614f04565b5060010190565b6000610220820190506001600160a01b038916825287516020830152602088015161526760408401826001600160a01b03169052565b506040880151606083015260608801516080830152608088015160a083015260a088015160c083015260c088015160e083015260e08801516101008181850152808a01519150506101208181850152808a01519150506101408181850152808a0151610160850152505086610180830152856101a0830152846101c0830152836101e08301528261020083015298975050505050505050565b6001600160a01b03871681526101e081016002871061532f57634e487b7160e01b600052602160045260246000fd5b866020830152855160408301526020860151606083015260408601516080830152606086015160a0830152608086015160c083015260a086015160e083015260c08601516101008301528461012083015283610140830152614a09610160830184805182526020810151602083015260408101516040830152606081015160608301525050565b6000602082840312156153c857600080fd5b8151612cdf81614e74565b818103818111156108da576108da614f04565b600181815b8085111561330357816000190482111561540757615407614f04565b8085161561541457918102915b93841c93908002906153eb565b600082615430575060016108da565b8161543d575060006108da565b8160018114615453576002811461545d57615479565b60019150506108da565b60ff84111561546e5761546e614f04565b50506001821b6108da565b5060208310610133831016604e8410600b841016171561549c575081810a6108da565b6154a683836153e6565b80600019048211156154ba576154ba614f04565b029392505050565b6000612cdf8383615421565b600082516154e0818460208701614f39565b9190910192915050565b634e487b7160e01b600052601260045260246000fd5b60008261550f5761550f6154ea565b500490565b600082615523576155236154ea565b600160ff1b82146000198414161561553d5761553d614f04565b500590565b6000600160ff1b820161555757615557614f04565b506000039056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220dbaceeacf51b7c7336371ab738d16f97debb294cb15449cddd29e764f2a56afe64736f6c63430008100033
Deployed ByteCode Sourcemap
278799:140:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;233647:187;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;253508:370;;;;;;;;;;-1:-1:-1;253508:370:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;231796:98::-;;;;;;;;;;-1:-1:-1;231885:1:0;231796:98;;;3397:25:1;;;3385:2;3370:18;231796:98:0;3251:177:1;233411:110:0;;;;;;;;;;-1:-1:-1;231096:11:0;233411:110;233647:187;232675:146;;;;;;;;;;-1:-1:-1;232751:7:0;232675:146;233647:187;233248:155;;;;;;;;;;;;;:::i;253175:325::-;;;;;;;;;;-1:-1:-1;253175:325:0;;;;;:::i;:::-;;:::i;252976:191::-;;;;;;;;;;-1:-1:-1;252976:191:0;;;;;:::i;:::-;;:::i;:::-;;236632:100;;;;;;;;;;;;;:::i;:::-;;;-1:-1:-1;;;;;3914:55:1;;;3896:74;;3884:2;3869:18;236632:100:0;3750:226:1;233842:486:0;;;;;;;;;;-1:-1:-1;233842:486:0;;;;;:::i;:::-;;:::i;:::-;;;;4177:25:1;;;4233:2;4218:18;;4211:34;;;;4261:18;;;4254:34;4165:2;4150:18;233842:486:0;3981:313:1;234959:292:0;;;;;;;;;;-1:-1:-1;234959:292:0;;;;;:::i;:::-;;:::i;46653:200::-;;;;;;;;;;-1:-1:-1;46653:200:0;;;;;:::i;:::-;;:::i;236047:76::-;;;;;;;;;;;;;:::i;252785:183::-;;;;;;;;;;-1:-1:-1;252785:183:0;;;;;:::i;:::-;;:::i;237203:126::-;;;;;;;;;;-1:-1:-1;237302:18:0;;-1:-1:-1;;;;;237302:18:0;237203:126;;250635:446;;;;;;;;;;;;;:::i;47112:225::-;;;;;;:::i;:::-;;:::i;46331:133::-;;;;;;;;;;;;;:::i;233529:110::-;;;;;;;;;;-1:-1:-1;231158:9:0;233529:110;233647:187;231902:93;;;;;;;;;;-1:-1:-1;231981:6:0;;-1:-1:-1;;;;;231981:6:0;231902:93;;58756:86;;;;;;;;;;-1:-1:-1;58827:7:0;;;;58756:86;;6099:14:1;;6092:22;6074:41;;6062:2;6047:18;58756:86:0;5934:187:1;232003:134:0;;;;;;;;;;-1:-1:-1;230404:4:0;232003:134;233647:187;54906:103;;;;;;;;;;;;;:::i;232281:140::-;;;;;;;;;;-1:-1:-1;230548:9:0;232281:140;233647:187;252228:549;;;;;;;;;;-1:-1:-1;252228:549:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;252032:188::-;;;;;;;;;;-1:-1:-1;252032:188:0;;;;;:::i;:::-;;:::i;251089:324::-;;;;;;;;;;-1:-1:-1;251089:324:0;;;;;:::i;:::-;;:::i;235967:72::-;;;;;;;;;;;;;:::i;232429:114::-;;;;;;;;;;-1:-1:-1;230611:4:0;232429:114;233647:187;54258:87;;;;;;;;;;-1:-1:-1;54331:6:0;;-1:-1:-1;;;;;54331:6:0;54258:87;;236740:455;;;;;;;;;;-1:-1:-1;236740:455:0;;;;;:::i;:::-;;:::i;235336:340::-;;;;;;;;;;-1:-1:-1;235336:340:0;;;;;:::i;:::-;;:::i;235684:275::-;;;;;;;;;;;;;:::i;236329:295::-;;;;;;;;;;-1:-1:-1;236329:295:0;;;;;:::i;:::-;;:::i;251421:415::-;;;;;;;;;;-1:-1:-1;251421:415:0;;;;;:::i;:::-;;:::i;250386:241::-;;;;;;;;;;;;;:::i;:::-;;;;7885:25:1;;;7941:2;7926:18;;7919:34;;;;7858:18;250386:241:0;7715:244:1;233104:136:0;;;;;;;;;;-1:-1:-1;231043:2:0;233104:136;233647:187;234569:233;;;;;;;;;;-1:-1:-1;234569:233:0;;;;;:::i;:::-;;:::i;56558:152::-;;;;;;;;;;;;;:::i;249313:1065::-;;;;;;;;;;-1:-1:-1;249313:1065:0;;;;;:::i;:::-;;:::i;232551:116::-;;;;;;;;;;-1:-1:-1;230670:4:0;232551:116;233647:187;251844:180;;;;;;;;;;-1:-1:-1;251844:180:0;;;;;:::i;:::-;;:::i;56288:262::-;;;;;;;;;;-1:-1:-1;56288:262:0;;;;;:::i;:::-;;:::i;234336:225::-;;;;;;;;;;-1:-1:-1;234336:225:0;;;;;:::i;:::-;;:::i;236131:190::-;;;;;;;;;;-1:-1:-1;236131:190:0;;;;;:::i;:::-;;:::i;232145:128::-;;;;;;;;;;-1:-1:-1;230470:8:0;232145:128;233647:187;;233744:37;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;233744:37:0;233806:20;:18;:20::i;:::-;233799:27;;233647:187;:::o;253508:370::-;253668:54;54144:13;:11;:13::i;:::-;58620:16:::1;:14;:16::i;:::-;253754:116:::2;253822:7;253844:15;253754:53;:116::i;:::-;253740:130:::0;253508:370;-1:-1:-1;;253508:370:0:o;233248:155::-;233322:7;233349:46;7783:4;231043:2;233349:46;:::i;253175:325::-;253331:54;54144:13;:11;:13::i;:::-;58620:16:::1;:14;:16::i;:::-;253417:75:::2;253467:7;253476:15;253417:49;:75::i;252976:191::-:0;54144:13;:11;:13::i;:::-;58620:16:::1;:14;:16::i;:::-;253082:77:::2;253135:6;253143:15;253082:52;:77::i;:::-;252976:191:::0;:::o;236632:100::-;236685:7;236712:12;239390:7;;-1:-1:-1;;;;;239390:7:0;;239310:95;233842:486;233986:19;234020:23;234058:11;234098:20;234120:24;234146:12;234162:58;234191:18;234162:14;:58::i;:::-;234097:123;;;;-1:-1:-1;234097:123:0;;-1:-1:-1;233842:486:0;-1:-1:-1;;;;;233842:486:0:o;234959:292::-;239390:7;;231737:30;;;;;;;;;;;;-1:-1:-1;;;231737:30:0;;;;;-1:-1:-1;;;;;239390:7:0;52376:10;231707:28;231699:69;;;;-1:-1:-1;;;231699:69:0;;;;;;;;:::i;:::-;;;;;;;;;;49998:1:::1;50773:7;;:19:::0;50765:63:::1;;;::::0;-1:-1:-1;;;50765:63:0;;11405:2:1;50765:63:0::1;::::0;::::1;11387:21:1::0;11444:2;11424:18;;;11417:30;11483:33;11463:18;;;11456:61;11534:18;;50765:63:0::1;11203:355:1::0;50765:63:0::1;49998:1;50906:7;:18:::0;58361:19:::2;:17;:19::i;:::-;235065:20:::3;235087:23:::0;235114:13:::3;239734:8:::0;;-1:-1:-1;;;;;239734:8:0;;239652:98;235114:13:::3;-1:-1:-1::0;;;;;235114:21:0::3;;235136:11;235114:34;;;;;;;;;;;;;3397:25:1::0;;3385:2;3370:18;;3251:177;235114:34:0::3;;::::0;::::3;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;235064:84;;;;235159:19;239622:14:::0;;-1:-1:-1;;;;;239622:14:0;;239528:116;235159:19:::3;:84;::::0;-1:-1:-1;;;235159:84:0;;::::3;::::0;::::3;7885:25:1::0;;;7926:18;;;7919:34;;;-1:-1:-1;;;;;235159:53:0;;;::::3;::::0;::::3;::::0;7858:18:1;;235159:84:0::3;;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;::::0;::::3;;;;;-1:-1:-1::0;;49954:1:0::1;51085:7;:22:::0;-1:-1:-1;;;;;234959:292:0:o;46653:200::-;-1:-1:-1;;;;;45203:6:0;45186:23;45194:4;45186:23;45178:80;;;;-1:-1:-1;;;45178:80:0;;12268:2:1;45178:80:0;;;12250:21:1;12307:2;12287:18;;;12280:30;12346:34;12326:18;;;12319:62;-1:-1:-1;;;12397:18:1;;;12390:42;12449:19;;45178:80:0;12066:408:1;45178:80:0;45301:6;-1:-1:-1;;;;;45277:30:0;:20;36629:66;36990:65;-1:-1:-1;;;;;36990:65:0;;36910:153;45277:20;-1:-1:-1;;;;;45277:30:0;;45269:87;;;;-1:-1:-1;;;45269:87:0;;12681:2:1;45269:87:0;;;12663:21:1;12720:2;12700:18;;;12693:30;12759:34;12739:18;;;12732:62;-1:-1:-1;;;12810:18:1;;;12803:42;12862:19;;45269:87:0;12479:408:1;45269:87:0;46737:36:::1;46755:17;46737;:36::i;:::-;46825:12;::::0;;46835:1:::1;46825:12:::0;;;::::1;::::0;::::1;::::0;;;46784:61:::1;::::0;46806:17;;46825:12;46784:21:::1;:61::i;236047:76::-:0;54144:13;:11;:13::i;:::-;236105:10:::1;:8;:10::i;:::-;236047:76::o:0;252785:183::-;54144:13;:11;:13::i;:::-;58620:16:::1;:14;:16::i;:::-;252887:73:::2;252936:6;252944:15;252887:48;:73::i;250635:446::-:0;250742:19;250776:23;250814:11;250854:20;250876:24;250902:12;250918:55;250947:15;250918:14;:55::i;:::-;250853:120;;;;-1:-1:-1;250853:120:0;;-1:-1:-1;250635:446:0;-1:-1:-1;;;;250635:446:0:o;47112:225::-;-1:-1:-1;;;;;45203:6:0;45186:23;45194:4;45186:23;45178:80;;;;-1:-1:-1;;;45178:80:0;;12268:2:1;45178:80:0;;;12250:21:1;12307:2;12287:18;;;12280:30;12346:34;12326:18;;;12319:62;-1:-1:-1;;;12397:18:1;;;12390:42;12449:19;;45178:80:0;12066:408:1;45178:80:0;45301:6;-1:-1:-1;;;;;45277:30:0;:20;36629:66;36990:65;-1:-1:-1;;;;;36990:65:0;;36910:153;45277:20;-1:-1:-1;;;;;45277:30:0;;45269:87;;;;-1:-1:-1;;;45269:87:0;;12681:2:1;45269:87:0;;;12663:21:1;12720:2;12700:18;;;12693:30;12759:34;12739:18;;;12732:62;-1:-1:-1;;;12810:18:1;;;12803:42;12862:19;;45269:87:0;12479:408:1;45269:87:0;47230:36:::1;47248:17;47230;:36::i;:::-;47277:52;47299:17;47318:4;47324;47277:21;:52::i;:::-;47112:225:::0;;:::o;46331:133::-;46409:7;45639:4;-1:-1:-1;;;;;45648:6:0;45631:23;;45623:92;;;;-1:-1:-1;;;45623:92:0;;13094:2:1;45623:92:0;;;13076:21:1;13133:2;13113:18;;;13106:30;13172:34;13152:18;;;13145:62;13243:26;13223:18;;;13216:54;13287:19;;45623:92:0;12892:420:1;45623:92:0;-1:-1:-1;36629:66:0::1;46331:133:::0;:::o;54906:103::-;54144:13;:11;:13::i;:::-;54971:30:::1;54998:1;54971:18;:30::i;252228:549::-:0;252433:62;252510:66;49998:1;50773:7;;:19;50765:63;;;;-1:-1:-1;;;50765:63:0;;11405:2:1;50765:63:0;;;11387:21:1;11444:2;11424:18;;;11417:30;11483:33;11463:18;;;11456:61;11534:18;;50765:63:0;11203:355:1;50765:63:0;49998:1;50906:7;:18;58361:19:::1;:17;:19::i;:::-;252653:116:::2;252679:15;252709:19;252743:15;252653:11;:116::i;:::-;49954:1:::0;51085:7;:22;252604:165;;;;-1:-1:-1;252228:549:0;-1:-1:-1;;;252228:549:0:o;252032:188::-;49998:1;50773:7;;:19;50765:63;;;;-1:-1:-1;;;50765:63:0;;11405:2:1;50765:63:0;;;11387:21:1;11444:2;11424:18;;;11417:30;11483:33;11463:18;;;11456:61;11534:18;;50765:63:0;11203:355:1;50765:63:0;49998:1;50906:7;:18;58361:19:::1;:17;:19::i;:::-;252135:77:::2;252188:6;252196:15;252135:52;:77::i;:::-;-1:-1:-1::0;49954:1:0;51085:7;:22;252032:188::o;251089:324::-;251279:7;49998:1;50773:7;;:19;50765:63;;;;-1:-1:-1;;;50765:63:0;;11405:2:1;50765:63:0;;;11387:21:1;11444:2;11424:18;;;11417:30;11483:33;11463:18;;;11456:61;11534:18;;50765:63:0;11203:355:1;50765:63:0;49998:1;50906:7;:18;58361:19:::1;:17;:19::i;:::-;251319:86:::2;251337:15;251354:11;251367:27;251396:8;251319:17;:86::i;:::-;49954:1:::0;51085:7;:22;251299:106;251089:324;-1:-1:-1;;;;251089:324:0:o;235967:72::-;54144:13;:11;:13::i;:::-;236023:8:::1;:6;:8::i;236740:455::-:0;54144:13;:11;:13::i;:::-;58361:19:::1;:17;:19::i;:::-;236938:24:::2;::::0;;;;::::2;::::0;;;::::2;::::0;;-1:-1:-1;;;236938:24:0::2;::::0;::::2;::::0;-1:-1:-1;;;;;236902:34:0;::::2;236894:69;;;;-1:-1:-1::0;;;236894:69:0::2;;;;;;;;:::i;:::-;;236974:28;237005:12;239390:7:::0;;-1:-1:-1;;;;;239390:7:0;;239310:95;237005:12:::2;237028:18;:61:::0;;-1:-1:-1;;;;;;237028:61:0::2;-1:-1:-1::0;;;;;237028:61:0;;::::2;::::0;;::::2;::::0;;;236974:43;;-1:-1:-1;237105:82:0;::::2;52376:10:::0;-1:-1:-1;;;;;237105:82:0::2;;;;;;;;;;;236883:312;236740:455:::0;:::o;235336:340::-;49998:1;50773:7;;:19;50765:63;;;;-1:-1:-1;;;50765:63:0;;11405:2:1;50765:63:0;;;11387:21:1;11444:2;11424:18;;;11417:30;11483:33;11463:18;;;11456:61;11534:18;;50765:63:0;11203:355:1;50765:63:0;49998:1;50906:7;:18;239390:7;;231737:30:::1;::::0;;;;::::1;::::0;;;::::1;::::0;;-1:-1:-1;;;231737:30:0::1;::::0;::::1;::::0;;-1:-1:-1;;;;;239390:7:0;52376:10;231707:28:::1;231699:69;;;;-1:-1:-1::0;;;231699:69:0::1;;;;;;;;:::i;:::-;;58361:19:::2;:17;:19::i;:::-;235486:23:::3;235511:20:::0;235535:13:::3;239734:8:::0;;-1:-1:-1;;;;;239734:8:0;;239652:98;235535:13:::3;-1:-1:-1::0;;;;;235535:22:0::3;;235558:11;235535:35;;;;;;;;;;;;;3397:25:1::0;;3385:2;3370:18;;3251:177;235535:35:0::3;;::::0;::::3;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;235485:85;;;;235581:19;239622:14:::0;;-1:-1:-1;;;;;239622:14:0;;239528:116;235581:19:::3;:87;::::0;-1:-1:-1;;;235581:87:0;;::::3;::::0;::::3;7885:25:1::0;;;7926:18;;;7919:34;;;-1:-1:-1;;;;;235581:56:0;;;::::3;::::0;::::3;::::0;7858:18:1;;235581:87:0::3;7715:244:1::0;235684:275:0;49998:1;50773:7;;:19;50765:63;;;;-1:-1:-1;;;50765:63:0;;11405:2:1;50765:63:0;;;11387:21:1;11444:2;11424:18;;;11417:30;11483:33;11463:18;;;11456:61;11534:18;;50765:63:0;11203:355:1;50765:63:0;49998:1;50906:7;:18;239390:7;;231737:30:::1;::::0;;;;::::1;::::0;;;::::1;::::0;;-1:-1:-1;;;231737:30:0::1;::::0;::::1;::::0;;-1:-1:-1;;;;;239390:7:0;52376:10;231707:28:::1;231699:69;;;;-1:-1:-1::0;;;231699:69:0::1;;;;;;;;:::i;:::-;;58361:19:::2;:17;:19::i;:::-;235777:23:::3;235802:20:::0;235826:13:::3;239734:8:::0;;-1:-1:-1;;;;;239734:8:0;;239652:98;235826:13:::3;-1:-1:-1::0;;;;;235826:25:0::3;;:27;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;235776:77;;;;235864:19;239622:14:::0;;-1:-1:-1;;;;;239622:14:0;;239528:116;235864:19:::3;:87;::::0;-1:-1:-1;;;235864:87:0;;::::3;::::0;::::3;7885:25:1::0;;;7926:18;;;7919:34;;;-1:-1:-1;;;;;235864:56:0;;;::::3;::::0;::::3;::::0;7858:18:1;;235864:87:0::3;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;::::0;::::3;;;;;-1:-1:-1::0;;49954:1:0;51085:7;:22;-1:-1:-1;;;;235684:275:0:o;236329:295::-;54144:13;:11;:13::i;:::-;58361:19:::1;:17;:19::i;:::-;236453:24:::2;::::0;;;;::::2;::::0;;;::::2;::::0;;-1:-1:-1;;;236453:24:0::2;::::0;::::2;::::0;-1:-1:-1;;;;;236428:23:0;::::2;236420:58;;;;-1:-1:-1::0;;;236420:58:0::2;;;;;;;;:::i;:::-;;236489:17;236509:12;239390:7:::0;;-1:-1:-1;;;;;239390:7:0;;239310:95;236509:12:::2;236532:7;:19:::0;;-1:-1:-1;;;;;;236532:19:0::2;-1:-1:-1::0;;;;;236532:19:0;;::::2;::::0;;::::2;::::0;;;236489:32;;-1:-1:-1;236567:49:0;::::2;52376:10:::0;-1:-1:-1;;;;;236567:49:0::2;;;;;;;;;;;236409:215;236329:295:::0;:::o;251421:415::-;251615:7;49998:1;50773:7;;:19;50765:63;;;;-1:-1:-1;;;50765:63:0;;11405:2:1;50765:63:0;;;11387:21:1;11444:2;11424:18;;;11417:30;11483:33;11463:18;;;11456:61;11534:18;;50765:63:0;11203:355:1;50765:63:0;49998:1;50906:7;:18;58361:19:::1;:17;:19::i;:::-;251655:173:::2;251695:15;251729:11;251759:27;251805:8;251655:21;:173::i;250386:241::-:0;250481:21;250504:25;250586:33;250603:15;250586:16;:33::i;:::-;250547:72;;;;-1:-1:-1;250386:241:0;-1:-1:-1;250386:241:0:o;234569:233::-;234712:6;234743:51;234772:15;234789:4;234743:28;:51::i;56558:152::-;56767:15;;56800:37;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;56767:15:0;52376:10;56767:31;56759:79;;;;-1:-1:-1;;;56759:79:0;;;;;;;;:::i;:::-;-1:-1:-1;56631:15:0::1;:28:::0;;-1:-1:-1;;;;;;56631:28:0::1;::::0;;56670:32:::1;52376:10:::0;56670:18:::1;:32::i;249313:1065::-:0;32850:19;32873:13;;;;;;32872:14;;32920:34;;;;-1:-1:-1;32938:12:0;;32953:1;32938:12;;;;:16;32920:34;32919:108;;;-1:-1:-1;32999:4:0;23612:19;:23;;;32960:66;;-1:-1:-1;33009:12:0;;;;;:17;32960:66;32897:204;;;;-1:-1:-1;;;32897:204:0;;13519:2:1;32897:204:0;;;13501:21:1;13558:2;13538:18;;;13531:30;13597:34;13577:18;;;13570:62;13668:16;13648:18;;;13641:44;13702:19;;32897:204:0;13317:410:1;32897:204:0;33112:12;:16;;-1:-1:-1;;33112:16:0;33127:1;33112:16;;;33139:67;;;;33174:13;:20;;-1:-1:-1;;33174:20:0;;;;;33139:67;249539:17:::1;:15;:17::i;:::-;249567:16;:14;:16::i;:::-;249594:24;:22;:24::i;:::-;249660;::::0;;;;::::1;::::0;;;::::1;::::0;;-1:-1:-1;;;249660:24:0::1;::::0;::::1;::::0;-1:-1:-1;;;;;249639:19:0;::::1;249631:54;;;;-1:-1:-1::0;;;249631:54:0::1;;;;;;;;:::i;:::-;-1:-1:-1::0;249730:24:0::1;::::0;;;;::::1;::::0;;;::::1;::::0;;-1:-1:-1;;;249730:24:0::1;::::0;::::1;::::0;-1:-1:-1;;;;;249704:24:0;::::1;249696:59;;;;-1:-1:-1::0;;;249696:59:0::1;;;;;;;;:::i;:::-;-1:-1:-1::0;249803:24:0::1;::::0;;;;::::1;::::0;;;::::1;::::0;;-1:-1:-1;;;249803:24:0::1;::::0;::::1;::::0;-1:-1:-1;;;;;249774:27:0;::::1;249766:62;;;;-1:-1:-1::0;;;249766:62:0::1;;;;;;;;:::i;:::-;-1:-1:-1::0;249880:24:0::1;::::0;;;;::::1;::::0;;;::::1;::::0;;-1:-1:-1;;;249880:24:0::1;::::0;::::1;::::0;-1:-1:-1;;;;;249847:31:0;::::1;249839:66;;;;-1:-1:-1::0;;;249839:66:0::1;;;;;;;;:::i;:::-;-1:-1:-1::0;249947:24:0::1;::::0;;;;::::1;::::0;;;::::1;::::0;;-1:-1:-1;;;249947:24:0::1;::::0;::::1;::::0;-1:-1:-1;;;;;249924:21:0;::::1;249916:56;;;;-1:-1:-1::0;;;249916:56:0::1;;;;;;;;:::i;:::-;;250026:5;-1:-1:-1::0;;;;;250009:32:0::1;;:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;249991:52;;278927:1:::0;249991:52:::1;250045:25;;;;;;;;;;;;;;;;::::0;249983:88:::1;;;;;-1:-1:-1::0;;;249983:88:0::1;;;;;;;;:::i;:::-;;250088:6;250084:47;;;250111:8;:6;:8::i;:::-;250143:14;:46:::0;;-1:-1:-1;;;;;;250143:46:0;;::::1;-1:-1:-1::0;;;;;250143:46:0;;::::1;::::0;;;::::1;::::0;;;250200:18:::1;:58:::0;;;::::1;::::0;;::::1;;::::0;;250269:11:::1;:37:::0;;;::::1;::::0;;::::1;;::::0;;250317:6:::1;:14:::0;;;::::1;::::0;;::::1;;::::0;;250342:8:::1;:28:::0;;;;::::1;::::0;;::::1;::::0;;;::::1;::::0;;33228:102;;;;33279:5;33263:21;;-1:-1:-1;;33263:21:0;;;33304:14;;-1:-1:-1;14162:36:1;;33304:14:0;;14150:2:1;14135:18;33304:14:0;;;;;;;33228:102;32839:498;249313:1065;;;;;;:::o;251844:180::-;49998:1;50773:7;;:19;50765:63;;;;-1:-1:-1;;;50765:63:0;;11405:2:1;50765:63:0;;;11387:21:1;11444:2;11424:18;;;11417:30;11483:33;11463:18;;;11456:61;11534:18;;50765:63:0;11203:355:1;50765:63:0;49998:1;50906:7;:18;58361:19:::1;:17;:19::i;:::-;251943:73:::2;251992:6;252000:15;251943:48;:73::i;56288:262::-:0;54144:13;:11;:13::i;:::-;56414:24:::1;::::0;;;;::::1;::::0;;;::::1;::::0;;-1:-1:-1;;;56414:24:0::1;::::0;::::1;::::0;-1:-1:-1;;;;;56384:28:0;::::1;56376:63;;;;-1:-1:-1::0;;;56376:63:0::1;;;;;;;;:::i;:::-;-1:-1:-1::0;56450:15:0::1;:32:::0;;-1:-1:-1;;;;;;56450:32:0::1;-1:-1:-1::0;;;;;56450:32:0;::::1;::::0;;::::1;::::0;;;56498:44:::1;::::0;::::1;::::0;-1:-1:-1;;56498:44:0::1;56288:262:::0;:::o;234336:225::-;234475:6;234506:47;234531:15;234548:4;234506:24;:47::i;236131:190::-;54144:13;:11;:13::i;:::-;58361:19:::1;:17;:19::i;:::-;236254:6:::2;::::0;236236:77:::2;::::0;-1:-1:-1;;;;;236254:6:0::2;236284:7:::0;-1:-1:-1;;236236:47:0::2;:77::i;239758:685::-:0;239811:37;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;239811:37:0;239861:52;239916:19;239622:14;;-1:-1:-1;;;;;239622:14:0;;239528:116;239916:19;-1:-1:-1;;;;;239916:30:0;;:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;239861:87;;239961:26;239990:13;239734:8;;-1:-1:-1;;;;;239734:8:0;;239652:98;239990:13;:41;;-1:-1:-1;;;239990:41:0;;240025:4;239990:41;;;3896:74:1;-1:-1:-1;;;;;239990:26:0;;;;;;;3869:18:1;;239990:41:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;239961:70;;240044:20;240167:31;:14;:20;;;:29;:31::i;:::-;240122:29;:18;:27;:29::i;:::-;240067:39;:14;:28;;;:37;:39::i;:::-;:84;;;;:::i;:::-;:131;;;;:::i;:::-;240044:154;;240236:1;240219:13;:18;;240239:42;;;;;;;;;;;;;;;;;240211:71;;;;;-1:-1:-1;;;240211:71:0;;;;;;;;:::i;:::-;;240324:25;:13;:23;:25::i;:::-;240293:28;;;:56;-1:-1:-1;240362:20:0;;;:41;240293:14;239758:685;-1:-1:-1;239758:685:0:o;54423:132::-;54331:6;;-1:-1:-1;;;;;54331:6:0;52376:10;54487:23;54479:68;;;;-1:-1:-1;;;54479:68:0;;15912:2:1;54479:68:0;;;15894:21:1;;;15931:18;;;15924:30;15990:34;15970:18;;;15963:62;16042:18;;54479:68:0;15710:356:1;59100:108:0;58827:7;;;;59159:41;;;;-1:-1:-1;;;59159:41:0;;16273:2:1;59159:41:0;;;16255:21:1;16312:2;16292:18;;;16285:30;16351:22;16331:18;;;16324:50;16391:18;;59159:41:0;16071:344:1;256425:433:0;256581:54;256648:27;256723:48;256747:7;256756:14;256723:23;:48::i;:::-;256686:85;-1:-1:-1;256686:85:0;-1:-1:-1;256782:68:0;52376:10;256830:19;256782:33;:68::i;:::-;256637:221;256425:433;;;;:::o;255992:425::-;256144:54;256211:27;256286:44;256306:7;256315:14;256286:19;:44::i;255528:456::-;255695:30;;;;;;;;;;;;-1:-1:-1;;;255695:30:0;;;;255683:10;255675:51;;;;-1:-1:-1;;;255675:51:0;;;;;;;;:::i;:::-;;255739:40;255782:19;239622:14;;-1:-1:-1;;;;;239622:14:0;;239528:116;255782:19;-1:-1:-1;;;;;255782:39:0;;255822:6;255782:47;;;;;;;;;;;;;3397:25:1;;3385:2;3370:18;;3251:177;255782:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;255739:90;-1:-1:-1;255842:134:0;52376:10;255917:48;255940:8;255950:14;255917:22;:48::i;:::-;255842:33;:134::i;:::-;255664:320;255528:456;;:::o;240451:627::-;240567:19;240601:23;240639:11;240678:23;240704:16;239501:11;;-1:-1:-1;;;;;239501:11:0;;239413:107;240704:16;240760:6;;240704:106;;-1:-1:-1;;;240704:106:0;;-1:-1:-1;;;;;240760:6:0;;;240704:106;;;17710:74:1;17800:18;;;17793:34;;;240704:41:0;;;;;17683:18:1;;240704:106:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;240678:132;;240822:20;240844:24;240870:12;240886:19;239622:14;;-1:-1:-1;;;;;239622:14:0;;239528:116;240886:19;:84;;-1:-1:-1;;;240886:84:0;;;;;7885:25:1;;;7926:18;;;7919:34;;;-1:-1:-1;;;;;240886:47:0;;;;;;;7858:18:1;;240886:84:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;240821:149;;;;-1:-1:-1;240821:149:0;;-1:-1:-1;240451:627:0;-1:-1:-1;;;;;;240451:627:0:o;58915:108::-;58827:7;;;;58985:9;58977:38;;;;-1:-1:-1;;;58977:38:0;;18348:2:1;58977:38:0;;;18330:21:1;18387:2;18367:18;;;18360:30;18426:18;18406;;;18399:46;18462:18;;58977:38:0;18146:340:1;278654:66:0;54144:13;:11;:13::i;38328:992::-;36281:66;38782:59;;;38778:535;;;38858:37;38877:17;38858:18;:37::i;38778:535::-;38961:17;-1:-1:-1;;;;;38932:61:0;;:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;38932:63:0;;;;;;;;-1:-1:-1;;38932:63:0;;;;;;;;;;;;:::i;:::-;;;38928:306;;39162:56;;-1:-1:-1;;;39162:56:0;;18882:2:1;39162:56:0;;;18864:21:1;18921:2;18901:18;;;18894:30;18960:34;18940:18;;;18933:62;19031:16;19011:18;;;19004:44;19065:19;;39162:56:0;18680:410:1;38928:306:0;36629:66;39046:28;;39038:82;;;;-1:-1:-1;;;39038:82:0;;19297:2:1;39038:82:0;;;19279:21:1;19336:2;19316:18;;;19309:30;19375:34;19355:18;;;19348:62;19446:11;19426:18;;;19419:39;19475:19;;39038:82:0;19095:405:1;39038:82:0;38996:140;39248:53;39266:17;39285:4;39291:9;39248:17;:53::i;59611:120::-;58620:16;:14;:16::i;:::-;59670:7:::1;:15:::0;;-1:-1:-1;;59670:15:0::1;::::0;;59701:22:::1;52376:10:::0;59710:12:::1;59701:22;::::0;-1:-1:-1;;;;;3914:55:1;;;3896:74;;3884:2;3869:18;59701:22:0::1;;;;;;;59611:120::o:0;255076:444::-;255239:30;;;;;;;;;;;;-1:-1:-1;;;255239:30:0;;;;255227:10;255219:51;;;;-1:-1:-1;;;255219:51:0;;;;;;;;:::i;:::-;;255283:40;255326:19;239622:14;;-1:-1:-1;;;;;239622:14:0;;239528:116;255326:19;-1:-1:-1;;;;;255326:35:0;;255362:6;255326:43;;;;;;;;;;;;;3397:25:1;;3385:2;3370:18;;3251:177;255326:43:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;255283:86;-1:-1:-1;255382:130:0;52376:10;255457:44;255476:8;255486:14;255457:18;:44::i;55525:191::-;55618:6;;;-1:-1:-1;;;;;55635:17:0;;;-1:-1:-1;;;;;;55635:17:0;;;;;;;55668:40;;55618:6;;;55635:17;55618:6;;55668:40;;55599:16;;55668:40;55588:128;55525:191;:::o;253886:1182::-;254087:62;;231422:2;254280:15;:22;:51;;:127;;;;-1:-1:-1;231422:2:0;254352:19;:26;:55;;254280:127;254422:43;;;;;;;;;;;;;-1:-1:-1;;;254422:43:0;;;254258:218;;;;;-1:-1:-1;;;254258:218:0;;;;;;;;:::i;:::-;;254489:35;254535:39;254640:89;254674:15;254704:14;254640:19;:89::i;:::-;254587:142;-1:-1:-1;254587:142:0;-1:-1:-1;254803:97:0;254841:19;254875:14;254803:23;:97::i;:::-;254742:158;-1:-1:-1;254742:158:0;-1:-1:-1;254913:147:0;52376:10;254988:61;255018:31;254988:27;:61;:::i;254913:147::-;254247:821;;253886:1182;;;;;;:::o;260602:2304::-;260789:7;260809:52;260864:103;260894:13;260922:11;260948:8;260864:15;:103::i;:::-;260809:158;;260980:45;261028:19;239622:14;;-1:-1:-1;;;;;239622:14:0;;239528:116;261028:19;-1:-1:-1;;;;;261028:30:0;;:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;260980:80;;261119:9;:28;;;261095:7;:21;;;:52;;;;:::i;:::-;261071:21;;;:76;261226:20;;;;261192:31;;:54;;261226:20;261192:54;:::i;:::-;261158:88;;;261306:21;;;;261422:35;;;;261259:209;;261158:88;261388:69;;261158:88;261388:69;:::i;:::-;261259:32;:209::i;:::-;261502:18;;261558:21;;;;261502:110;;-1:-1:-1;;;261502:110:0;;261481:18;;-1:-1:-1;;;;;261502:18:0;;:41;;:110;;261558:21;261594:7;;261502:110;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;261481:131;;261677:1;261647:27;:31;:76;;;;;261696:27;261682:10;:41;;261647:76;261738:52;;;;;;;;;;;;;-1:-1:-1;;;261738:52:0;;;261625:176;;;;;-1:-1:-1;;;261625:176:0;;;;;;;;:::i;:::-;;261814:46;261863:121;261902:13;261930:9;:18;;;261963:10;261863:24;:121::i;:::-;261814:170;;261997:31;262031:369;;;;;;;;262062:12;52376:10;;52296:98;262062:12;-1:-1:-1;;;;;262031:369:0;;;;;262089:13;262031:369;;;;262117:9;:20;;;262031:369;;;;262152:9;:18;;;262031:369;;;;262185:9;:21;;;262031:369;;;;262221:9;:27;;;262031:369;;;;262263:9;:34;;;262031:369;;;;262312:9;:28;;;262031:369;;;;262355:9;:34;;;262031:369;;;261997:403;;262413:17;262433:19;239622:14;;-1:-1:-1;;;;;239622:14:0;;239528:116;262433:19;-1:-1:-1;;;;;262433:53:0;;262501:7;231158:9;262433:125;;;;;;;-1:-1:-1;;;;;;262433:125:0;;;20335:13:1;;-1:-1:-1;;;;;20331:62:1;262433:125:0;;;20313:81:1;20450:4;20438:17;;20432:24;20410:20;;;20403:54;20501:17;;;20495:24;20473:20;;;20466:54;20576:4;20564:17;;20558:24;20536:20;;;20529:54;20639:4;20627:17;;20621:24;20599:20;;;20592:54;20702:4;20690:17;;20684:24;20662:20;;;20655:54;20765:4;20753:17;;20747:24;20725:20;;;20718:54;20816:17;;;20810:24;20788:20;;;20781:54;20854:6;20902:15;;;20896:22;20876:18;;;20869:50;20935:19;;;20928:35;20285:19;;262433:125:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;262413:145;-1:-1:-1;262569:84:0;52376:10;262612:12;262587:6;;-1:-1:-1;;;;;262587:6:0;;262634:4;262641:11;262569:42;:84::i;:::-;262666:203;262699:9;262723;:24;;;262762:7;262784:9;262808:1;262824:9;:34;;;262666:18;:203::i;:::-;262889:9;260602:2304;-1:-1:-1;;;;;;;;;;260602:2304:0:o;59352:118::-;58361:19;:17;:19::i;:::-;59412:7:::1;:14:::0;;-1:-1:-1;;59412:14:0::1;59422:4;59412:14;::::0;;59442:20:::1;59449:12;52376:10:::0;;52296:98;263035:2321;263226:7;263246:52;263301:103;263331:13;263359:11;263385:8;263301:15;:103::i;:::-;263246:158;;263417:45;263465:19;239622:14;;-1:-1:-1;;;;;239622:14:0;;239528:116;263465:19;-1:-1:-1;;;;;263465:30:0;;:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;263417:80;;263558:9;:28;;;263534:7;:21;;;:52;;;;:::i;:::-;263510:21;;;:76;263699:20;;;;;263648:35;;;;:71;;263699:20;263648:71;:::i;:::-;263597:35;;;:122;;;263779:21;;;;263865:31;;263732:213;;263597:122;263865:69;;263597:122;;263865:69;:::i;263732:213::-;263979:18;;264039:21;;;;263979:114;;-1:-1:-1;;;263979:114:0;;263958:18;;-1:-1:-1;;;;;263979:18:0;;:45;;:114;;264039:21;264075:7;;263979:114;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;263958:135;;264157:10;264126:27;:41;;264182:52;;;;;;;;;;;;;-1:-1:-1;;;264182:52:0;;;264104:141;;;;;-1:-1:-1;;;264104:141:0;;;;;;;;:::i;:::-;;264258:46;264307:121;264346:13;264374:9;:18;;;264407:10;264307:24;:121::i;:::-;264258:170;;264441:31;264475:369;;;;;;;;264506:12;52376:10;;52296:98;264506:12;-1:-1:-1;;;;;264475:369:0;;;;;264533:13;264475:369;;;;264561:9;:20;;;264475:369;;;;264596:9;:18;;;264475:369;;;;264629:9;:21;;;264475:369;;;;264665:9;:27;;;264475:369;;;;264707:9;:34;;;264475:369;;;;264756:9;:28;;;264475:369;;;;264799:9;:34;;;264475:369;;;264441:403;;264857:17;264877:19;239622:14;;-1:-1:-1;;;;;239622:14:0;;239528:116;264877:19;-1:-1:-1;;;;;264877:57:0;;264949:7;231158:9;264877:129;;;;;;;-1:-1:-1;;;;;;264877:129:0;;;20335:13:1;;-1:-1:-1;;;;;20331:62:1;264877:129:0;;;20313:81:1;20450:4;20438:17;;20432:24;20410:20;;;20403:54;20501:17;;;20495:24;20473:20;;;20466:54;20576:4;20564:17;;20558:24;20536:20;;;20529:54;20639:4;20627:17;;20621:24;20599:20;;;20592:54;20702:4;20690:17;;20684:24;20662:20;;;20655:54;20765:4;20753:17;;20747:24;20725:20;;;20718:54;20816:17;;;20810:24;20788:20;;;20781:54;20854:6;20902:15;;;20896:22;20876:18;;;20869:50;20935:19;;;20928:35;20285:19;;264877:129:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;264857:149;-1:-1:-1;265019:84:0;52376:10;265062:12;52296:98;265019:84;265116:203;265149:9;265173;:24;;;265212:7;265234:9;265258:1;265274:9;:34;;;265116:18;:203::i;257080:656::-;257293:11;;257368:6;;257293:92;;-1:-1:-1;;;257293:92:0;;;;;21148:25:1;;;-1:-1:-1;;;;;257368:6:0;;;21189:18:1;;;21182:83;257184:21:0;;;;;;257293:11;;;:27;;21121:18:1;;257293:92:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;257250:135;;257398:45;257446:20;:18;:20::i;:::-;257518:18;;257566:63;;-1:-1:-1;;;257566:63:0;;257398:68;;-1:-1:-1;;;;;;257518:18:0;;;;257566:41;;:63;;257608:11;;257398:68;;257566:63;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;257661:67;;-1:-1:-1;;;257661:67:0;;257549:80;;-1:-1:-1;;;;;;257661:45:0;;;;;:67;;257707:11;;257720:7;;257661:67;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;257640:88;;257239:497;;;257080:656;;;:::o;241437:351::-;241582:6;241626:154;241677:9;241705:16;239501:11;;-1:-1:-1;;;;;239501:11:0;;239413:107;241705:16;241747:6;;241705:60;;-1:-1:-1;;;241705:60:0;;-1:-1:-1;;;;;241747:6:0;;;241705:60;;;17710:74:1;17800:18;;;17793:34;;;241705:41:0;;;;;17683:18:1;;241705:60:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;241626:4;;:154;:32;:154::i;:::-;241606:174;241437:351;-1:-1:-1;;;241437:351:0:o;57926:99::-;34691:13;;;;;;;34683:69;;;;-1:-1:-1;;;34683:69:0;;21938:2:1;34683:69:0;;;21920:21:1;21977:2;21957:18;;;21950:30;22016:34;21996:18;;;21989:62;-1:-1:-1;;;22067:18:1;;;22060:41;22118:19;;34683:69:0;21736:407:1;34683:69:0;57990:27:::1;:25;:27::i;53801:97::-:0;34691:13;;;;;;;34683:69;;;;-1:-1:-1;;;34683:69:0;;21938:2:1;34683:69:0;;;21920:21:1;21977:2;21957:18;;;21950:30;22016:34;21996:18;;;21989:62;-1:-1:-1;;;22067:18:1;;;22060:41;22118:19;;34683:69:0;21736:407:1;34683:69:0;53864:26:::1;:24;:26::i;44331:68::-:0;34691:13;;;;;;;34683:69;;;;-1:-1:-1;;;34683:69:0;;21938:2:1;34683:69:0;;;21920:21:1;21977:2;21957:18;;;21950:30;22016:34;21996:18;;;21989:62;-1:-1:-1;;;22067:18:1;;;22060:41;22118:19;;34683:69:0;21736:407:1;241086:343:0;241227:6;241271:150;241318:9;241346:16;239501:11;;-1:-1:-1;;;;;239501:11:0;;239413:107;241346:16;241388:6;;241346:60;;-1:-1:-1;;;241346:60:0;;-1:-1:-1;;;;;241388:6:0;;;241346:60;;;17710:74:1;17800:18;;;17793:34;;;241346:41:0;;;;;17683:18:1;;241346:60:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;241271:4;;:150;:28;:150::i;65101:328::-;65266:39;;-1:-1:-1;;;65266:39:0;;65290:4;65266:39;;;22383:34:1;-1:-1:-1;;;;;22453:15:1;;;22433:18;;;22426:43;65243:20:0;;65308:5;;65266:15;;;;;22295:18:1;;65266:39:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:47;;;;:::i;:::-;65351:69;;-1:-1:-1;;;;;17728:55:1;;65351:69:0;;;17710:74:1;17800:18;;;17793:34;;;65243:70:0;;-1:-1:-1;65324:97:0;;65344:5;;-1:-1:-1;;;65374:22:0;17683:18:1;;65351:69:0;;;;-1:-1:-1;;65351:69:0;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;65351:69:0;;;;;;;;;;65324:19;:97::i;:::-;65232:197;65101:328;;;:::o;118258:301::-;118314:6;118458:16;118441:5;:34;;118433:87;;;;-1:-1:-1;;;118433:87:0;;22682:2:1;118433:87:0;;;22664:21:1;22721:2;22701:18;;;22694:30;22760:34;22740:18;;;22733:62;22831:10;22811:18;;;22804:38;22859:19;;118433:87:0;22480:404:1;118433:87:0;-1:-1:-1;118545:5:0;118258:301::o;99560:171::-;99616:7;99653:1;99644:5;:10;;99636:55;;;;-1:-1:-1;;;99636:55:0;;23091:2:1;99636:55:0;;;23073:21:1;;;23110:18;;;23103:30;23169:34;23149:18;;;23142:62;23221:18;;99636:55:0;22889:356:1;271987:1166:0;272120:27;272162:54;231422:2;272266:7;:14;:43;;272324;;;;;;;;;;;;;-1:-1:-1;;;272324:43:0;;;272244:134;;;;;-1:-1:-1;;;272244:134:0;;;;;;;;:::i;:::-;;272445:7;:14;272405:55;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;272405:55:0;;;;;;;;;;;;;;;;272391:69;;272478:9;272473:673;272497:7;:14;272493:1;:18;272473:673;;;272533:14;272550:7;272558:1;272550:10;;;;;;;;:::i;:::-;;;;;;;272533:27;;272592:1;272583:6;:10;272595:30;;;;;;;;;;;;;-1:-1:-1;;;272595:30:0;;;272575:51;;;;;-1:-1:-1;;;272575:51:0;;;;;;;;:::i;:::-;;272643:40;272686:19;239622:14;;-1:-1:-1;;;;;239622:14:0;;239528:116;272686:19;-1:-1:-1;;;;;272686:39:0;;272744:6;272686:79;;;;;;;;;;;;;3397:25:1;;3385:2;3370:18;;3251:177;272686:79:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;272643:122;-1:-1:-1;272812:25:0;272786:8;:14;;;:52;272782:353;;272882:48;272905:8;272915:14;272882:22;:48::i;:::-;272859:71;;;;:::i;:::-;;;272966:47;;;;;;;;273000:6;272966:47;;;;273008:4;272966:47;;;;;272949:11;272961:1;272949:14;;;;;;;;:::i;:::-;;;;;;:64;;;;272782:353;;;273071:48;;;;;;;;273105:6;273071:48;;;;273113:5;273071:48;;;;;273054:11;273066:1;273054:14;;;;;;;;:::i;:::-;;;;;;:65;;;;272782:353;272518:628;;272513:3;;;;;:::i;:::-;;;;272473:673;;;;271987:1166;;;;;:::o;278096:376::-;278231:28;;278227:238;;278276:177;278333:10;278362:76;278397:24;278927:1;278362:34;:76::i;:::-;278294:6;;-1:-1:-1;;;;;278294:6:0;;278276:177;:38;:177::i;270857:1122::-;270986:27;271028:54;231422:2;271132:7;:14;:43;;271190;;;;;;;;;;;;;-1:-1:-1;;;271190:43:0;;;271110:134;;;;;-1:-1:-1;;;271110:134:0;;;;;;;;:::i;:::-;;271311:7;:14;271271:55;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;271271:55:0;;;;;;;;;;;;;;;;271257:69;;271344:9;271339:633;271363:7;:14;271359:1;:18;271339:633;;;271399:14;271416:7;271424:1;271416:10;;;;;;;;:::i;:::-;;;;;;;271399:27;;271458:1;271449:6;:10;271461:30;;;;;;;;;;;;;-1:-1:-1;;;271461:30:0;;;271441:51;;;;;-1:-1:-1;;;271441:51:0;;;;;;;;:::i;:::-;;271509:40;271552:19;239622:14;;-1:-1:-1;;;;;239622:14:0;;239528:116;271552:19;-1:-1:-1;;;;;271552:35:0;;271588:6;271552:43;;;;;;;;;;;;;3397:25:1;;3385:2;3370:18;;3251:177;271552:43:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;271509:86;-1:-1:-1;271642:25:0;271616:8;:14;;;:52;271612:349;;271712:44;271731:8;271741:14;271712:18;:44::i;:::-;271689:67;;;;:::i;:::-;;;271792:47;;;;;;;;271826:6;271792:47;;;;271834:4;271792:47;;;;;271775:11;271787:1;271775:14;;;;;;;;:::i;:::-;;;;;;:64;;;;271612:349;;;271897:48;;;;;;;;271931:6;271897:48;;;;271939:5;271897:48;;;;;271880:11;271892:1;271880:14;;;;;;;;:::i;:::-;;;;;;:65;;;;271612:349;271384:588;;271379:3;;;;;:::i;:::-;;;;271339:633;;269434:1415;269575:27;269663:25;269637:8;:14;;;:52;269704:34;;;;;;;;;;;;;-1:-1:-1;;;269704:34:0;;;269615:134;;;;;-1:-1:-1;;;269615:134:0;;;;;;;;:::i;:::-;;269762:13;269778:54;269807:14;269823:8;269778:28;:54::i;:::-;269762:70;;269843:22;269868:32;269893:6;269868:24;:32::i;:::-;269843:57;;269913:19;239622:14;;-1:-1:-1;;;;;239622:14:0;;239528:116;269913:19;-1:-1:-1;;;;;269913:58:0;;52376:10;269986:12;270013:8;270036:6;270057:14;270086;231256:9;231355:7;269913:328;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;270254:26;270335:271;270378:8;270401:6;270422:14;270451;270480:50;231256:9;;238726:218;270480:50;231355:7;270335:28;:271::i;:::-;270646:11;;270672:6;;270622:219;;;-1:-1:-1;;;;;270672:6:0;;;25515:34:1;;25580:2;25565:18;;25558:34;;;52376:10:0;25608:18:1;;;25601:43;25675:2;25660:18;;25653:34;;;25718:3;25703:19;;25696:35;;;25762:3;25747:19;;25740:35;;;270622:219:0;270291:315;;-1:-1:-1;270291:315:0;;-1:-1:-1;270646:11:0;270622:219;;;;;;25441:3:1;270622:219:0;;;269604:1245;;;269434:1415;;;;:::o;37159:284::-;-1:-1:-1;;;;;23612:19:0;;;37233:106;;;;-1:-1:-1;;;37233:106:0;;25988:2:1;37233:106:0;;;25970:21:1;26027:2;26007:18;;;26000:30;26066:34;26046:18;;;26039:62;26137:15;26117:18;;;26110:43;26170:19;;37233:106:0;25786:409:1;37233:106:0;36629:66;37350:85;;-1:-1:-1;;;;;;37350:85:0;-1:-1:-1;;;;;37350:85:0;;;;;;;;;;37159:284::o;37852:297::-;37995:29;38006:17;37995:10;:29::i;:::-;38053:1;38039:4;:11;:15;:28;;;;38058:9;38039:28;38035:107;;;38084:46;38106:17;38125:4;38084:21;:46::i;268025:1401::-;268155:27;268248:25;268222:8;:14;;;:52;268289:34;;;;;;;;;;;;;-1:-1:-1;;;268289:34:0;;;268200:134;;;;;-1:-1:-1;;;268200:134:0;;;;;;;;:::i;:::-;;268347:13;268363:50;268388:14;268404:8;268363:24;:50::i;:::-;268347:66;;268424:22;268449:32;268474:6;268449:24;:32::i;:::-;268424:57;;268492:19;239622:14;;-1:-1:-1;;;;;239622:14:0;;239528:116;268492:19;-1:-1:-1;;;;;268492:54:0;;52376:10;268561:12;52296:98;257744:2303;257888:52;;:::i;:::-;257978:33;;;;;;;;;;;;;;;;;257961:15;257953:59;;;;-1:-1:-1;;;257953:59:0;;;;;;;;:::i;:::-;-1:-1:-1;258065:6:0;;258100:11;;-1:-1:-1;;;;;258065:6:0;258047:35;52376:10;258047:49;;-1:-1:-1;;;;;;258047:49:0;;;;;;;-1:-1:-1;;;;;3914:55:1;;;258047:49:0;;;3896:74:1;3869:18;;258047:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:64;;258126:32;;;;;;;;;;;;;;;;;258025:144;;;;;-1:-1:-1;;;258025:144:0;;;;;;;;:::i;:::-;-1:-1:-1;258182:22:0;258207:50;258229:11;278927:1;258207:21;:50::i;:::-;258182:75;-1:-1:-1;231158:9:0;258278:8;:29;;258309;;;;;;;;;;;;;;;;;258270:69;;;;;-1:-1:-1;;;258270:69:0;;;;;;;;:::i;:::-;-1:-1:-1;258389:30:0;;;;;;;;;;;;;;;;;231096:11;258358:29;;;258350:70;;;;-1:-1:-1;;;258350:70:0;;;;;;;;:::i;:::-;-1:-1:-1;231043:2:0;258433:32;258547:40;7783:4;231043:2;258547:40;:::i;:::-;258509:78;-1:-1:-1;258639:54:0;231158:9;258509:78;258639:54;:::i;:::-;258622:14;:71;258708:40;;;;;;;;;;;;;-1:-1:-1;;;258708:40:0;;;258600:159;;;;;-1:-1:-1;;;258600:159:0;;;;;;;;:::i;:::-;-1:-1:-1;258773:18:0;;;258839:250;258905:14;258938:8;258965:27;231158:9;230670:4;258839:47;:250::i;:::-;258772:317;;;;;;259103:26;259131:32;259167:114;259204:16;259235:35;238147:7;238071:149;;259235:35;259167:22;:114::i;:::-;259102:179;;;;259330:29;230404:4;;237409:132;259330:29;259316:10;:43;;259374:39;;;;;;;;;;;;;;;;;259294:130;;;;;-1:-1:-1;;;259294:130:0;;;;;;;;:::i;:::-;-1:-1:-1;259550:16:0;259493:54;231158:9;259493:27;:54;:::i;:::-;:73;;;;:::i;:::-;259459:14;:107;259581:40;;;;;;;;;;;;;-1:-1:-1;;;259581:40:0;;;259437:195;;;;;-1:-1:-1;;;259437:195:0;;;;;;;;:::i;:::-;;259665:374;;;;;;;;259719:14;259665:374;;;;259752:10;259665:374;;;;259781:8;259665:374;;;;259808:18;259665:374;;;;259845:24;259665:374;;;;259888:24;231158:9;;238612:106;259888:24;259665:374;;;;259931:24;259665:374;;;;259974:11;;;;;;;;;-1:-1:-1;;;;;259974:11:0;-1:-1:-1;;;;;259974:27:0;;260002:13;260017:6;;;;;;;;;-1:-1:-1;;;;;260017:6:0;259974:50;;;;;;;;;;;;;;;21148:25:1;;;-1:-1:-1;;;;;21209:55:1;21204:2;21189:18;;21182:83;21136:2;21121:18;;20974:297;259974:50:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;259665:374;;259645:394;257744:2303;-1:-1:-1;;;;;;;;;;;;257744:2303:0:o;265364:1104::-;265565:23;;265645:29;;265641:516;;265709:133;265745:38;7783:4;265745:22;:38;:::i;:::-;265802:25;265709:17;:133::i;:::-;265691:151;-1:-1:-1;265883:134:0;265919:39;7783:4;265919:23;:39;:::i;265883:134::-;265859:158;;265641:516;;;-1:-1:-1;;;7666:78:0;-1:-1:-1;7666:78:0;265641:516;266251:36;;;;;;;;;;;;;;;;;230470:8;266191:45;;;266169:129;;;;-1:-1:-1;;;266169:129:0;;;;;;;;:::i;:::-;-1:-1:-1;266405:44:0;;;;;;;;;;;;;;;;;230548:9;266333:57;;;266311:149;;;;-1:-1:-1;;;266311:149:0;;;;;;;;:::i;:::-;;265554:914;;265364:1104;;;:::o;267416:601::-;267573:46;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;267573:46:0;267675:11;;267750:6;;267675:92;;-1:-1:-1;;;267675:92:0;;;;;21148:25:1;;;-1:-1:-1;;;;;267750:6:0;;;21189:18:1;;;21182:83;267632:40:0;;267675:11;;;;;:27;;21121:18:1;;267675:92:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;267792:217;;;;;;;;267836:22;;267792:217;;;267873:20;;;;267792:217;;;;267632:135;;-1:-1:-1;267792:217:0;;267908:65;267926:24;7783:4;267926:8;:24;:::i;:::-;267952:11;:20;;;267908:17;:65::i;:::-;267792:217;;;;;;;;-1:-1:-1;267780:229:0;;267416:601;-1:-1:-1;;;267416:601:0:o;63938:259::-;64120:68;;-1:-1:-1;;;;;26481:15:1;;;64120:68:0;;;26463:34:1;26533:15;;26513:18;;;26506:43;26565:18;;;26558:34;;;64093:96:0;;64113:5;;-1:-1:-1;;;64143:27:0;26375:18:1;;64120:68:0;26200:398:1;266476:932:0;266808:13;;266836:6;;-1:-1:-1;;;;;266761:639:0;;;;266784:9;;266761:639;;266836:6;266883:9;266836:6;266857:36;;;;;;;:::i;:::-;266908:342;;;;;;;;266949:14;266908:342;;;;266982:7;:18;;;266908:342;;;;267019:7;:16;;;266908:342;;;;267054:7;:26;;;266908:342;;;;267099:7;:32;;;266908:342;;;;267150:18;266908:342;;;;7783:4;267187:7;:32;;;:48;;;;:::i;:::-;266908:342;;267265:21;;;;267301:64;8512:17;267265:21;267301:64;:::i;:::-;267380:9;266761:639;;;;;;;;;;;:::i;:::-;;;;;;;;266476:932;;;;;;:::o;147430:627::-;147608:16;147638:19;147659:22;147685:108;147722:4;147741:16;147772:10;147685:22;:108::i;:::-;147637:156;;;;147818:231;147852:4;:15;;;147882:156;147946:25;:14;:23;:25::i;:::-;147921:22;:11;:20;:22::i;:::-;:50;;;;:::i;:::-;8025:21;7964:8;7783:4;8025:21;:::i;:::-;147882:20;:156::i;:::-;147818:19;:231::i;:::-;147806:243;147430:627;-1:-1:-1;;;;;;147430:627:0:o;58033:97::-;34691:13;;;;;;;34683:69;;;;-1:-1:-1;;;34683:69:0;;21938:2:1;34683:69:0;;;21920:21:1;21977:2;21957:18;;;21950:30;22016:34;21996:18;;;21989:62;-1:-1:-1;;;22067:18:1;;;22060:41;22118:19;;34683:69:0;21736:407:1;34683:69:0;58107:7:::1;:15:::0;;-1:-1:-1;;58107:15:0::1;::::0;;58033:97::o;53906:113::-;34691:13;;;;;;;34683:69;;;;-1:-1:-1;;;34683:69:0;;21938:2:1;34683:69:0;;;21920:21:1;21977:2;21957:18;;;21950:30;22016:34;21996:18;;;21989:62;-1:-1:-1;;;22067:18:1;;;22060:41;22118:19;;34683:69:0;21736:407:1;34683:69:0;53979:32:::1;52376:10:::0;56670:18:::1;:32::i;146799:623::-:0;146973:16;147003:19;147024:22;147050:108;147087:4;147106:16;147137:10;147050:22;:108::i;:::-;147002:156;;;;147183:231;147217:4;:15;;;147247:156;147314:22;:11;:20;:22::i;:::-;147286:25;:14;:23;:25::i;66841:727::-;67276:23;67302:69;67330:4;67302:69;;;;;;;;;;;;;;;;;67310:5;-1:-1:-1;;;;;67302:27:0;;;:69;;;;;:::i;:::-;67386:17;;67276:95;;-1:-1:-1;67386:21:0;67382:179;;67483:10;67472:30;;;;;;;;;;;;:::i;:::-;67464:85;;;;-1:-1:-1;;;67464:85:0;;28347:2:1;67464:85:0;;;28329:21:1;28386:2;28366:18;;;28359:30;28425:34;28405:18;;;28398:62;28496:12;28476:18;;;28469:40;28526:19;;67464:85:0;28145:406:1;143908:396:0;144031:7;144060:13;144077:2;144060:19;144056:241;;-1:-1:-1;144103:5:0;144096:12;;144056:241;144146:2;144130:13;:18;144126:171;;;144185:18;144201:2;144185:13;:18;:::i;:::-;144180:24;;:2;:24;:::i;:::-;144172:32;;:5;:32;:::i;:::-;144165:39;;;;144126:171;144244:41;144253:5;144265:18;144270:13;144265:2;:18;:::i;:::-;144260:24;;:2;:24;:::i;:::-;144244:8;:41::i;63708:222::-;63863:58;;-1:-1:-1;;;;;17728:55:1;;63863:58:0;;;17710:74:1;17800:18;;;17793:34;;;63836:86:0;;63856:5;;-1:-1:-1;;;63886:23:0;17683:18:1;;63863:58:0;17536:297:1;256866:206:0;256938:7;256978:86;230611:4;256996:30;257019:6;256996:22;:30::i;:::-;:52;;;;:::i;:::-;7783:4;256978:17;:86::i;274332:1937::-;274680:26;274708:27;274748:17;274768:30;274791:6;274768:22;:30::i;:::-;274748:50;;274809:38;274850:131;274883:14;:25;;;274923:47;274850:18;:131::i;:::-;274809:172;;275010:30;274998:9;:42;274994:605;;;275238:20;;;;-1:-1:-1;;;;;275222:36:0;52376:10;-1:-1:-1;;;;;275222:36:0;;275218:370;;275417:47;275358:14;:27;;;:106;;;;:::i;:::-;275309:20;:155;;275487:66;;;;;;;;;;;;;;;;;275279:293;;;;;-1:-1:-1;;;275279:293:0;;;;;;;;:::i;:::-;;275218:370;275624:1;275615:6;:10;275611:651;;;275728:210;275772:14;:20;;;275811:14;:39;;;275909:14;275897:9;275869:14;:25;;;:37;;;;:::i;:::-;:54;;;;:::i;:::-;275728:25;:210::i;:::-;275684:254;;-1:-1:-1;275684:254:0;-1:-1:-1;275611:651:0;;;276057:193;276101:14;:20;;;276140:14;:39;;;276226:9;276198:14;:25;;;:37;;;;:::i;276057:193::-;276013:237;;-1:-1:-1;276013:237:0;-1:-1:-1;275611:651:0;274737:1532;;274332:1937;;;;;;;;;:::o;37556:155::-;37623:37;37642:17;37623:18;:37::i;:::-;37676:27;;-1:-1:-1;;;;;37676:27:0;;;;;;;;37556:155;:::o;42589:461::-;42672:12;-1:-1:-1;;;;;23612:19:0;;;42697:88;;;;-1:-1:-1;;;42697:88:0;;30265:2:1;42697:88:0;;;30247:21:1;30304:2;30284:18;;;30277:30;30343:34;30323:18;;;30316:62;30414:8;30394:18;;;30387:36;30440:19;;42697:88:0;30063:402:1;42697:88:0;42859:12;42873:23;42900:6;-1:-1:-1;;;;;42900:19:0;42920:4;42900:25;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;42858:67;;;;42943:99;42979:7;42988:10;42943:99;;;;;;;;;;;;;;;;;:35;:99::i;:::-;42936:106;42589:461;-1:-1:-1;;;;;42589:461:0:o;144740:::-;144823:7;144847:9;;144843:351;;144877:13;144894:2;144877:19;144873:265;;-1:-1:-1;144924:5:0;144917:12;;144873:265;144971:2;144955:13;:18;144951:187;;;145001:41;145010:5;145022:18;145038:2;145022:13;:18;:::i;144951:187::-;145103:18;145108:13;145103:2;:18;:::i;144843:351::-;-1:-1:-1;145177:5:0;145170:12;;146051:740;146327:18;;;146450:171;7783:4;146524:24;146483:38;146497:24;146483:11;:38;:::i;:::-;:65;;;;:::i;:::-;146482:83;;;;:::i;:::-;146580:30;146596:14;7783:4;146580:30;:::i;146450:171::-;146437:184;-1:-1:-1;146643:55:0;146661:21;146437:184;146661:8;:21;:::i;146643:55::-;146632:66;-1:-1:-1;146722:61:0;146740:27;146753:14;146740:10;:27;:::i;146722:61::-;146709:74;;146051:740;;;;;;;;;:::o;260055:418::-;260198:27;;260284:115;260316:44;260335:25;260316:16;:44;:::i;260284:115::-;260267:132;-1:-1:-1;260432:33:0;260267:132;260432:16;:33;:::i;:::-;260410:55;;260055:418;;;;;:::o;143542:114::-;143605:9;143647:1;143637:5;143641:1;143647;143637:5;:::i;:::-;143632:11;;:1;:11;:::i;:::-;143631:17;;;;:::i;148184:656::-;148357:19;148378:22;148455:4;:18;;;148435:16;:38;;148488:61;;;;;;;;;;;;;;;;;148413:147;;;;;-1:-1:-1;;;148413:147:0;;;;;;;;:::i;:::-;;148587:155;148629:4;:13;;;148657:4;:22;;;148713:4;:18;;;148694:16;:37;;;;:::i;:::-;148587:27;:155::i;:::-;148573:169;;148772:60;148803:4;:16;;;148821:10;148772:30;:60::i;:::-;148755:77;;148184:656;;;;;;:::o;143664:114::-;143728:8;143769:1;143759:5;143763:1;143769;143759:5;:::i;:::-;143754:11;;:1;:11;:::i;:::-;143753:17;;;;:::i;149772:569::-;149888:6;149912:20;149935:21;:10;:19;:21::i;:::-;149912:44;;149985:1;149973:9;:13;149969:365;;;150019:13;150007:9;:25;150003:143;;;150060:9;150053:16;;;;;149969:365;150194:14;150195:13;150194:14;:::i;:::-;150182:9;:26;150178:145;;;150236:14;150237:13;150236:14;:::i;:::-;150229:21;;;;;150178:145;150298:9;150291:16;;;;;26062:229;26199:12;26231:52;26253:6;26261:4;26267:1;26270:12;26231:21;:52::i;:::-;26224:59;26062:229;-1:-1:-1;;;;26062:229:0:o;145209:132::-;145269:7;145314:1;145306:5;:9;:26;;145327:5;145306:26;;;145318:6;145319:5;145318:6;:::i;145349:134::-;145420:7;145447:28;145456:12;145464:4;145456:5;:12;:::i;276795:1080::-;276955:26;;278927:1;-1:-1:-1;;;;;277073:21:0;;52376:10;277073:21;277069:356;;277128:41;277145:24;277128:14;:41;:::i;:::-;277111:58;;277069:356;;;277389:24;277367:46;;277069:356;277441:18;;277437:431;;277476:35;277514:109;277567:14;277600:8;277514:34;:109::i;:::-;277702:6;;277476:147;;-1:-1:-1;277684:74:0;;-1:-1:-1;;;;;277702:6:0;277723:5;277476:147;277684:38;:74::i;:::-;277796:60;277818:27;277847:8;277796:21;:60::i;:::-;277775:81;;277461:407;277437:431;277012:863;276795:1080;;;;;;:::o;28891:762::-;29041:12;29070:7;29066:580;;;-1:-1:-1;29101:10:0;29094:17;;29066:580;29215:17;;:21;29211:424;;29463:10;29457:17;29524:15;29511:10;29507:2;29503:19;29496:44;29211:424;29606:12;29599:20;;-1:-1:-1;;;29599:20:0;;;;;;;;:::i;148953:369::-;149125:7;149295:19;149234:45;149258:21;149234:8;:45;:::i;:::-;:80;;;;:::i;:::-;8025:21;7964:8;7783:4;8025:21;:::i;:::-;149165:53;;:8;:53;:::i;:::-;:149;;;;:::i;149438:326::-;149574:7;7964:8;149699:29;149713:15;149699:11;:29;:::i;:::-;:57;;;;:::i;27182:510::-;27352:12;27410:5;27385:21;:30;;27377:81;;;;-1:-1:-1;;;27377:81:0;;31560:2:1;27377:81:0;;;31542:21:1;31599:2;31579:18;;;31572:30;31638:34;31618:18;;;31611:62;31709:8;31689:18;;;31682:36;31735:19;;27377:81:0;31358:402:1;27377:81:0;-1:-1:-1;;;;;23612:19:0;;;27469:60;;;;-1:-1:-1;;;27469:60:0;;31967:2:1;27469:60:0;;;31949:21:1;32006:2;31986:18;;;31979:30;32045:31;32025:18;;;32018:59;32094:18;;27469:60:0;31765:353:1;27469:60:0;27543:12;27557:23;27584:6;-1:-1:-1;;;;;27584:11:0;27603:5;27610:4;27584:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27542:73;;;;27633:51;27650:7;27659:10;27671:12;27633:16;:51::i;:::-;27626:58;27182:510;-1:-1:-1;;;;;;;27182:510:0:o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;292:286:1:-;100:12;;88:25;;162:4;151:16;;;145:23;129:14;;;122:47;218:4;207:16;;;201:23;185:14;;;178:47;274:4;263:16;;;257:23;241:14;;;234:47;502:3;487:19;;515:57;14:273;583:127;644:10;639:3;635:20;632:1;625:31;675:4;672:1;665:15;699:4;696:1;689:15;715:252;787:2;781:9;829:3;817:16;;863:18;848:34;;884:22;;;845:62;842:88;;;910:18;;:::i;:::-;946:2;939:22;715:252;:::o;972:275::-;1043:2;1037:9;1108:2;1089:13;;-1:-1:-1;;1085:27:1;1073:40;;1143:18;1128:34;;1164:22;;;1125:62;1122:88;;;1190:18;;:::i;:::-;1226:2;1219:22;972:275;;-1:-1:-1;972:275:1:o;1252:712::-;1306:5;1359:3;1352:4;1344:6;1340:17;1336:27;1326:55;;1377:1;1374;1367:12;1326:55;1413:6;1400:20;1439:4;1462:18;1458:2;1455:26;1452:52;;;1484:18;;:::i;:::-;1530:2;1527:1;1523:10;1553:28;1577:2;1573;1569:11;1553:28;:::i;:::-;1615:15;;;1685;;;1681:24;;;1646:12;;;;1717:15;;;1714:35;;;1745:1;1742;1735:12;1714:35;1781:2;1773:6;1769:15;1758:26;;1793:142;1809:6;1804:3;1801:15;1793:142;;;1875:17;;1863:30;;1826:12;;;;1913;;;;1793:142;;1969:348;2053:6;2106:2;2094:9;2085:7;2081:23;2077:32;2074:52;;;2122:1;2119;2112:12;2074:52;2162:9;2149:23;2195:18;2187:6;2184:30;2181:50;;;2227:1;2224;2217:12;2181:50;2250:61;2303:7;2294:6;2283:9;2279:22;2250:61;:::i;2322:559::-;2396:3;2434:5;2428:12;2461:6;2456:3;2449:19;2487:4;2516:2;2511:3;2507:12;2500:19;;2553:2;2546:5;2542:14;2574:1;2584:272;2598:6;2595:1;2592:13;2584:272;;;2657:13;;2695:9;;2683:22;;2759:11;;2753:18;2746:26;2739:34;2725:12;;;2718:56;2803:4;2794:14;;;;2831:15;;;;2620:1;2613:9;2584:272;;;-1:-1:-1;2872:3:1;;2322:559;-1:-1:-1;;;;;2322:559:1:o;2886:360::-;3143:2;3132:9;3125:21;3106:4;3163:77;3236:2;3225:9;3221:18;3213:6;3163:77;:::i;3433:180::-;3492:6;3545:2;3533:9;3524:7;3520:23;3516:32;3513:52;;;3561:1;3558;3551:12;3513:52;-1:-1:-1;3584:23:1;;3433:180;-1:-1:-1;3433:180:1:o;4299:154::-;-1:-1:-1;;;;;4378:5:1;4374:54;4367:5;4364:65;4354:93;;4443:1;4440;4433:12;4458:134;4526:20;;4555:31;4526:20;4555:31;:::i;:::-;4458:134;;;:::o;4597:247::-;4656:6;4709:2;4697:9;4688:7;4684:23;4680:32;4677:52;;;4725:1;4722;4715:12;4677:52;4764:9;4751:23;4783:31;4808:5;4783:31;:::i;4849:898::-;4926:6;4934;4987:2;4975:9;4966:7;4962:23;4958:32;4955:52;;;5003:1;5000;4993:12;4955:52;5042:9;5029:23;5061:31;5086:5;5061:31;:::i;:::-;5111:5;-1:-1:-1;5135:2:1;5173:18;;;5160:32;5211:18;5241:14;;;5238:34;;;5268:1;5265;5258:12;5238:34;5306:6;5295:9;5291:22;5281:32;;5351:7;5344:4;5340:2;5336:13;5332:27;5322:55;;5373:1;5370;5363:12;5322:55;5409:2;5396:16;5431:2;5427;5424:10;5421:36;;;5437:18;;:::i;:::-;5479:53;5522:2;5503:13;;-1:-1:-1;;5499:27:1;5495:36;;5479:53;:::i;:::-;5466:66;;5555:2;5548:5;5541:17;5595:7;5590:2;5585;5581;5577:11;5573:20;5570:33;5567:53;;;5616:1;5613;5606:12;5567:53;5671:2;5666;5662;5658:11;5653:2;5646:5;5642:14;5629:45;5715:1;5710:2;5705;5698:5;5694:14;5690:23;5683:34;;5736:5;5726:15;;;;;4849:898;;;;;:::o;6126:595::-;6244:6;6252;6305:2;6293:9;6284:7;6280:23;6276:32;6273:52;;;6321:1;6318;6311:12;6273:52;6361:9;6348:23;6390:18;6431:2;6423:6;6420:14;6417:34;;;6447:1;6444;6437:12;6417:34;6470:61;6523:7;6514:6;6503:9;6499:22;6470:61;:::i;:::-;6460:71;;6584:2;6573:9;6569:18;6556:32;6540:48;;6613:2;6603:8;6600:16;6597:36;;;6629:1;6626;6619:12;6597:36;;6652:63;6707:7;6696:8;6685:9;6681:24;6652:63;:::i;:::-;6642:73;;;6126:595;;;;;:::o;6726:663::-;7139:2;7128:9;7121:21;7102:4;7165:77;7238:2;7227:9;7223:18;7215:6;7165:77;:::i;:::-;7290:9;7282:6;7278:22;7273:2;7262:9;7258:18;7251:50;7318:65;7376:6;7368;7318:65;:::i;7394:316::-;7471:6;7479;7487;7540:2;7528:9;7519:7;7515:23;7511:32;7508:52;;;7556:1;7553;7546:12;7508:52;-1:-1:-1;;7579:23:1;;;7649:2;7634:18;;7621:32;;-1:-1:-1;7700:2:1;7685:18;;;7672:32;;7394:316;-1:-1:-1;7394:316:1:o;7964:1016::-;8055:6;8108:3;8096:9;8087:7;8083:23;8079:33;8076:53;;;8125:1;8122;8115:12;8076:53;8151:22;;:::i;:::-;8209:9;8196:23;8189:5;8182:38;8252;8286:2;8275:9;8271:18;8252:38;:::i;:::-;8247:2;8240:5;8236:14;8229:62;8351:2;8340:9;8336:18;8323:32;8318:2;8311:5;8307:14;8300:56;8416:2;8405:9;8401:18;8388:32;8383:2;8376:5;8372:14;8365:56;8482:3;8471:9;8467:19;8454:33;8448:3;8441:5;8437:15;8430:58;8549:3;8538:9;8534:19;8521:33;8515:3;8508:5;8504:15;8497:58;8616:3;8605:9;8601:19;8588:33;8582:3;8575:5;8571:15;8564:58;8683:3;8672:9;8668:19;8655:33;8649:3;8642:5;8638:15;8631:58;8708:3;8771:2;8760:9;8756:18;8743:32;8738:2;8731:5;8727:14;8720:56;;8795:3;8858:2;8847:9;8843:18;8830:32;8825:2;8818:5;8814:14;8807:56;;8882:3;8945:2;8934:9;8930:18;8917:32;8912:2;8905:5;8901:14;8894:56;;8969:5;8959:15;;;7964:1016;;;;:::o;9165:118::-;9251:5;9244:13;9237:21;9230:5;9227:32;9217:60;;9273:1;9270;9263:12;9288:949;9389:6;9397;9405;9413;9421;9429;9482:3;9470:9;9461:7;9457:23;9453:33;9450:53;;;9499:1;9496;9489:12;9450:53;9538:9;9525:23;9557:28;9579:5;9557:28;:::i;:::-;9604:5;-1:-1:-1;9661:2:1;9646:18;;9633:32;9674:33;9633:32;9674:33;:::i;:::-;9726:7;-1:-1:-1;9785:2:1;9770:18;;9757:32;9798:33;9757:32;9798:33;:::i;:::-;9850:7;-1:-1:-1;9909:2:1;9894:18;;9881:32;9922:33;9881:32;9922:33;:::i;:::-;9974:7;-1:-1:-1;10033:3:1;10018:19;;10005:33;10047;10005;10047;:::i;:::-;10099:7;-1:-1:-1;10158:3:1;10143:19;;10130:33;10172;10130;10172;:::i;:::-;10224:7;10214:17;;;9288:949;;;;;;;;:::o;10242:127::-;10303:10;10298:3;10294:20;10291:1;10284:31;10334:4;10331:1;10324:15;10358:4;10355:1;10348:15;10374:168;10414:7;10480:1;10476;10472:6;10468:14;10465:1;10462:21;10457:1;10450:9;10443:17;10439:45;10436:71;;;10487:18;;:::i;:::-;-1:-1:-1;10527:9:1;;10374:168::o;10547:250::-;10632:1;10642:113;10656:6;10653:1;10650:13;10642:113;;;10732:11;;;10726:18;10713:11;;;10706:39;10678:2;10671:10;10642:113;;;-1:-1:-1;;10789:1:1;10771:16;;10764:27;10547:250::o;10802:396::-;10951:2;10940:9;10933:21;10914:4;10983:6;10977:13;11026:6;11021:2;11010:9;11006:18;10999:34;11042:79;11114:6;11109:2;11098:9;11094:18;11089:2;11081:6;11077:15;11042:79;:::i;:::-;11182:2;11161:15;-1:-1:-1;;11157:29:1;11142:45;;;;11189:2;11138:54;;10802:396;-1:-1:-1;;10802:396:1:o;11563:245::-;11642:6;11650;11703:2;11691:9;11682:7;11678:23;11674:32;11671:52;;;11719:1;11716;11709:12;11671:52;-1:-1:-1;;11742:16:1;;11798:2;11783:18;;;11777:25;11742:16;;11777:25;;-1:-1:-1;11563:245:1:o;13732:273::-;13800:6;13853:2;13841:9;13832:7;13828:23;13824:32;13821:52;;;13869:1;13866;13859:12;13821:52;13901:9;13895:16;13951:4;13944:5;13940:16;13933:5;13930:27;13920:55;;13971:1;13968;13961:12;14209:600;14287:5;14335:4;14323:9;14318:3;14314:19;14310:30;14307:50;;;14353:1;14350;14343:12;14307:50;14386:2;14380:9;14428:4;14420:6;14416:17;14499:6;14487:10;14484:22;14463:18;14451:10;14448:34;14445:62;14442:88;;;14510:18;;:::i;:::-;14550:10;14546:2;14539:22;;14579:6;14570:15;;14615:9;14609:16;14601:6;14594:32;14680:2;14669:9;14665:18;14659:25;14654:2;14646:6;14642:15;14635:50;14739:2;14728:9;14724:18;14718:25;14713:2;14705:6;14701:15;14694:50;14798:2;14787:9;14783:18;14777:25;14772:2;14764:6;14760:15;14753:50;;14209:600;;;;:::o;14814:276::-;14922:6;14975:3;14963:9;14954:7;14950:23;14946:33;14943:53;;;14992:1;14989;14982:12;14943:53;15015:69;15076:7;15065:9;15015:69;:::i;15095:184::-;15165:6;15218:2;15206:9;15197:7;15193:23;15189:32;15186:52;;;15234:1;15231;15224:12;15186:52;-1:-1:-1;15257:16:1;;15095:184;-1:-1:-1;15095:184:1:o;15284:216::-;15348:9;;;15376:11;;;15323:3;15406:9;;15434:10;;15430:19;;15459:10;;15451:19;;15427:44;15424:70;;;15474:18;;:::i;:::-;15424:70;;15284:216;;;;:::o;15505:200::-;15571:9;;;15544:4;15599:9;;15627:10;;15639:12;;;15623:29;15662:12;;;15654:21;;15620:56;15617:82;;;15679:18;;:::i;16420:138::-;16499:13;;16521:31;16499:13;16521:31;:::i;16563:968::-;16665:6;16718:3;16706:9;16697:7;16693:23;16689:33;16686:53;;;16735:1;16732;16725:12;16686:53;16761:22;;:::i;:::-;16812:9;16806:16;16799:5;16792:31;16855:49;16900:2;16889:9;16885:18;16855:49;:::i;:::-;16850:2;16843:5;16839:14;16832:73;16958:2;16947:9;16943:18;16937:25;16932:2;16925:5;16921:14;16914:49;17016:2;17005:9;17001:18;16995:25;16990:2;16983:5;16979:14;16972:49;17075:3;17064:9;17060:19;17054:26;17048:3;17041:5;17037:15;17030:51;17135:3;17124:9;17120:19;17114:26;17108:3;17101:5;17097:15;17090:51;17195:3;17184:9;17180:19;17174:26;17168:3;17161:5;17157:15;17150:51;17255:3;17244:9;17240:19;17234:26;17228:3;17221:5;17217:15;17210:51;17280:3;17336:2;17325:9;17321:18;17315:25;17310:2;17303:5;17299:14;17292:49;;17360:3;17416:2;17405:9;17401:18;17395:25;17390:2;17383:5;17379:14;17372:49;;17440:3;17496:2;17485:9;17481:18;17475:25;17470:2;17463:5;17459:14;17452:49;;17520:5;17510:15;;;16563:968;;;;:::o;17838:303::-;17923:6;17931;17939;17992:2;17980:9;17971:7;17967:23;17963:32;17960:52;;;18008:1;18005;17998:12;17960:52;18037:9;18031:16;18021:26;;18087:2;18076:9;18072:18;18066:25;18056:35;;18131:2;18120:9;18116:18;18110:25;18100:35;;17838:303;;;;;:::o;19505:125::-;19570:9;;;19591:10;;;19588:36;;;19604:18;;:::i;19635:448::-;100:12;;88:25;;162:4;151:16;;;145:23;129:14;;;122:47;218:4;207:16;;;201:23;185:14;;;178:47;274:4;263:16;;;257:23;241:14;;;234:47;100:12;;20072:3;20057:19;;88:25;151:16;;;145:23;129:14;;;122:47;207:16;;201:23;185:14;;;178:47;263:16;;257:23;241:14;;;234:47;19931:3;19916:19;;20010:67;14:273;23250:127;23311:10;23306:3;23302:20;23299:1;23292:31;23342:4;23339:1;23332:15;23366:4;23363:1;23356:15;23382:127;23443:10;23438:3;23434:20;23431:1;23424:31;23474:4;23471:1;23464:15;23498:4;23495:1;23488:15;23514:135;23553:3;23574:17;;;23571:43;;23594:18;;:::i;:::-;-1:-1:-1;23641:1:1;23630:13;;23514:135::o;23654:1508::-;23976:4;24018:3;24007:9;24003:19;23995:27;;-1:-1:-1;;;;;24053:6:1;24049:55;24038:9;24031:74;24147:6;24141:13;24136:2;24125:9;24121:18;24114:41;24202:2;24194:6;24190:15;24184:22;24215:52;24263:2;24252:9;24248:18;24234:12;-1:-1:-1;;;;;3684:54:1;3672:67;;3618:127;24215:52;;24321:2;24313:6;24309:15;24303:22;24298:2;24287:9;24283:18;24276:50;24381:2;24373:6;24369:15;24363:22;24357:3;24346:9;24342:19;24335:51;24441:3;24433:6;24429:16;24423:23;24417:3;24406:9;24402:19;24395:52;24502:3;24494:6;24490:16;24484:23;24478:3;24467:9;24463:19;24456:52;24563:3;24555:6;24551:16;24545:23;24539:3;24528:9;24524:19;24517:52;24606:3;24598:6;24594:16;24588:23;24630:3;24669:2;24664;24653:9;24649:18;24642:30;24709:2;24701:6;24697:15;24691:22;24681:32;;;24732:3;24771:2;24766;24755:9;24751:18;24744:30;24811:2;24803:6;24799:15;24793:22;24783:32;;;24834:3;24873:2;24868;24857:9;24853:18;24846:30;24931:2;24923:6;24919:15;24913:22;24907:3;24896:9;24892:19;24885:51;;;24973:6;24967:3;24956:9;24952:19;24945:35;25017:6;25011:3;25000:9;24996:19;24989:35;25061:6;25055:3;25044:9;25040:19;25033:35;25105:6;25099:3;25088:9;25084:19;25077:35;25149:6;25143:3;25132:9;25128:19;25121:35;23654:1508;;;;;;;;;;:::o;26603:1287::-;-1:-1:-1;;;;;27056:55:1;;27038:74;;27025:3;27010:19;;27142:1;27131:13;;27121:144;;27187:10;27182:3;27178:20;27175:1;27168:31;27222:4;27219:1;27212:15;27250:4;27247:1;27240:15;27121:144;27301:6;27296:2;27285:9;27281:18;27274:34;27350:6;27344:13;27339:2;27328:9;27324:18;27317:41;27412:2;27404:6;27400:15;27394:22;27389:2;27378:9;27374:18;27367:50;27472:2;27464:6;27460:15;27454:22;27448:3;27437:9;27433:19;27426:51;27532:2;27524:6;27520:15;27514:22;27508:3;27497:9;27493:19;27486:51;27592:3;27584:6;27580:16;27574:23;27568:3;27557:9;27553:19;27546:52;27653:3;27645:6;27641:16;27635:23;27629:3;27618:9;27614:19;27607:52;27714:3;27706:6;27702:16;27696:23;27690:3;27679:9;27675:19;27668:52;27757:6;27751:3;27740:9;27736:19;27729:35;27801:6;27795:3;27784:9;27780:19;27773:35;27817:67;27879:3;27868:9;27864:19;27856:6;106:5;100:12;95:3;88:25;162:4;155:5;151:16;145:23;138:4;133:3;129:14;122:47;218:4;211:5;207:16;201:23;194:4;189:3;185:14;178:47;274:4;267:5;263:16;257:23;250:4;245:3;241:14;234:47;;;14:273;27895:245;27962:6;28015:2;28003:9;27994:7;27990:23;27986:32;27983:52;;;28031:1;28028;28021:12;27983:52;28063:9;28057:16;28082:28;28104:5;28082:28;:::i;28556:128::-;28623:9;;;28644:11;;;28641:37;;;28658:18;;:::i;28689:422::-;28778:1;28821:5;28778:1;28835:270;28856:7;28846:8;28843:21;28835:270;;;28915:4;28911:1;28907:6;28903:17;28897:4;28894:27;28891:53;;;28924:18;;:::i;:::-;28974:7;28964:8;28960:22;28957:55;;;28994:16;;;;28957:55;29073:22;;;;29033:15;;;;28835:270;;29116:806;29165:5;29195:8;29185:80;;-1:-1:-1;29236:1:1;29250:5;;29185:80;29284:4;29274:76;;-1:-1:-1;29321:1:1;29335:5;;29274:76;29366:4;29384:1;29379:59;;;;29452:1;29447:130;;;;29359:218;;29379:59;29409:1;29400:10;;29423:5;;;29447:130;29484:3;29474:8;29471:17;29468:43;;;29491:18;;:::i;:::-;-1:-1:-1;;29547:1:1;29533:16;;29562:5;;29359:218;;29661:2;29651:8;29648:16;29642:3;29636:4;29633:13;29629:36;29623:2;29613:8;29610:16;29605:2;29599:4;29596:12;29592:35;29589:77;29586:159;;;-1:-1:-1;29698:19:1;;;29730:5;;29586:159;29777:34;29802:8;29796:4;29777:34;:::i;:::-;29847:6;29843:1;29839:6;29835:19;29826:7;29823:32;29820:58;;;29858:18;;:::i;:::-;29896:20;;29116:806;-1:-1:-1;;;29116:806:1:o;29927:131::-;29987:5;30016:36;30043:8;30037:4;30016:36;:::i;30470:287::-;30599:3;30637:6;30631:13;30653:66;30712:6;30707:3;30700:4;30692:6;30688:17;30653:66;:::i;:::-;30735:16;;;;;30470:287;-1:-1:-1;;30470:287:1:o;30762:127::-;30823:10;30818:3;30814:20;30811:1;30804:31;30854:4;30851:1;30844:15;30878:4;30875:1;30868:15;30894:120;30934:1;30960;30950:35;;30965:18;;:::i;:::-;-1:-1:-1;30999:9:1;;30894:120::o;31019:193::-;31058:1;31084;31074:35;;31089:18;;:::i;:::-;-1:-1:-1;;;31125:18:1;;-1:-1:-1;;31145:13:1;;31121:38;31118:64;;;31162:18;;:::i;:::-;-1:-1:-1;31196:10:1;;31019:193::o;31217:136::-;31252:3;-1:-1:-1;;;31273:22:1;;31270:48;;31298:18;;:::i;:::-;-1:-1:-1;31338:1:1;31334:13;;31217:136::o
Swarm Source
ipfs://dbaceeacf51b7c7336371ab738d16f97debb294cb15449cddd29e764f2a56afe
Loading...
Loading
Loading...
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.
[ 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.