Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00
Cross-Chain Transactions
Loading...
Loading
Contract Name:
TokenManager
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1
// Last deployed from commit: cf8bbafabd8de8d87a8723e937bf51d2a52d40da;
pragma solidity 0.8.17;
import "./lib/Bytes32EnumerableMap.sol";
import "./interfaces/IBorrowersRegistry.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
contract TokenManager is OwnableUpgradeable {
/**
* For adding supported assets
**/
struct Asset {
bytes32 asset;
address assetAddress;
uint256 debtCoverage;
}
/**
* For adding supported lending pools
**/
struct poolAsset {
bytes32 asset;
address poolAddress;
}
struct Exposure {
uint256 current;
uint256 max; // Setting max to 0 means no exposure limitations.
}
using EnumerableMap for EnumerableMap.Bytes32ToAddressMap;
uint256 private constant _NOT_SUPPORTED = 0;
uint256 private constant _INACTIVE = 1;
uint256 private constant _ACTIVE = 2;
// Stores an asset's bytes32 symbol representation to pool's address mapping
EnumerableMap.Bytes32ToAddressMap private assetToPoolAddress;
// Stores an asset's bytes32 symbol representation to asset's address mapping
EnumerableMap.Bytes32ToAddressMap private assetToTokenAddress;
mapping(address => bytes32) public tokenAddressToSymbol;
mapping(address => uint256) private tokenPositionInList;
// used for defining different leverage ratios for tokens
mapping(address => uint256) public debtCoverage;
address[] public supportedTokensList;
mapping(address => uint256) public tokenToStatus;
// used for defining different leverage ratios for staked assets
mapping(bytes32 => uint256) public debtCoverageStaked;
mapping(bytes32 => bytes32) public identifierToExposureGroup;
mapping(bytes32 => Exposure) public groupToExposure;
function initialize(Asset[] memory tokenAssets, poolAsset[] memory poolAssets) external initializer {
__Ownable_init();
addTokenAssets(tokenAssets);
addPoolAssets(poolAssets);
}
function getAllPoolAssets() public view returns (bytes32[] memory result) {
return assetToPoolAddress._inner._keys._inner._values;
}
function getSupportedTokensAddresses() public view returns (address[] memory) {
return supportedTokensList;
}
function getAllTokenAssets() public view returns (bytes32[] memory result) {
return assetToTokenAddress._inner._keys._inner._values;
}
/**
* Returns address of an asset
**/
function getAssetAddress(bytes32 _asset, bool allowInactive) public view returns (address) {
(, address assetAddress) = assetToTokenAddress.tryGet(_asset);
require(assetAddress != address(0), "Asset not supported.");
if (!allowInactive) {
require(tokenToStatus[assetAddress] == _ACTIVE, "Asset inactive");
}
return assetAddress;
}
/**
* Returns address of an asset's lending pool
**/
function getPoolAddress(bytes32 _asset) public view returns (address) {
(, address assetAddress) = assetToPoolAddress.tryGet(_asset);
require(assetAddress != address(0), "Pool asset not supported.");
return assetAddress;
}
function increaseProtocolExposure(bytes32 assetIdentifier, uint256 exposureIncrease) public onlyPrimeAccountOrOwner {
bytes32 group = identifierToExposureGroup[assetIdentifier];
if(group != ""){
Exposure storage exposure = groupToExposure[group];
if(exposure.max != 0){
exposure.current += exposureIncrease;
require(exposure.current <= exposure.max, "Max asset exposure breached");
emit ProtocolExposureChanged(msg.sender, group, exposureIncrease, block.timestamp);
}
}
}
function decreaseProtocolExposure(bytes32 assetIdentifier, uint256 exposureDecrease) public onlyPrimeAccountOrOwner {
bytes32 group = identifierToExposureGroup[assetIdentifier];
if(group != ""){
Exposure storage exposure = groupToExposure[group];
if(exposure.max != 0){
exposure.current = exposure.current <= exposureDecrease ? 0 : exposure.current - exposureDecrease;
emit ProtocolExposureChanged(msg.sender, group, exposureDecrease, block.timestamp);
}
}
}
function setCurrentProtocolExposure(bytes32[] memory groupIdentifiers, uint256[] memory currentExposures) external onlyOwner {
require(groupIdentifiers.length == currentExposures.length, "Arrays lengths mismatch");
for (uint256 i = 0; i < groupIdentifiers.length; i++) {
_setCurrentProtocolExposure(groupIdentifiers[i], currentExposures[i]);
}
}
function setMaxProtocolsExposure(bytes32[] memory groupIdentifiers, uint256[] memory maxExposures) public onlyOwner {
require(groupIdentifiers.length == maxExposures.length, "Arrays lengths mismatch");
for (uint256 i = 0; i < groupIdentifiers.length; i++) {
_setMaxProtocolExposure(groupIdentifiers[i], maxExposures[i]);
}
}
function _setMaxProtocolExposure(bytes32 groupIdentifier, uint256 maxExposure) internal {
require(groupIdentifier != "", "Cannot set an empty string asset.");
uint256 prevExposure = groupToExposure[groupIdentifier].max;
groupToExposure[groupIdentifier].max = maxExposure;
emit ProtocolExposureSet(msg.sender, groupIdentifier, prevExposure, maxExposure, groupToExposure[groupIdentifier].current , block.timestamp);
}
function _setCurrentProtocolExposure(bytes32 groupIdentifier, uint256 currentExposure) internal {
require(groupIdentifier != "", "Cannot set an empty string asset.");
uint256 prevExposure = groupToExposure[groupIdentifier].current;
groupToExposure[groupIdentifier].current = currentExposure;
emit ProtocolCurrentExposureSet(msg.sender, groupIdentifier, prevExposure, currentExposure, block.timestamp);
}
function setIdentifiersToExposureGroups(bytes32[] memory identifiers, bytes32[] memory exposureGroups) public onlyOwner {
require(identifiers.length == exposureGroups.length, "Arrays lengths mismatch");
for(uint i=0; i<identifiers.length; i++){
identifierToExposureGroup[identifiers[i]] = exposureGroups[i];
emit IdentifierToExposureGroupSet(msg.sender, identifiers[i], exposureGroups[i], block.timestamp);
}
}
function addPoolAssets(poolAsset[] memory poolAssets) public onlyOwner {
for (uint256 i = 0; i < poolAssets.length; i++) {
_addPoolAsset(poolAssets[i].asset, poolAssets[i].poolAddress);
}
}
function _addPoolAsset(bytes32 _asset, address _poolAddress) internal {
require(Address.isContract(_poolAddress), "TokenManager: Pool must be a contract");
require(!assetToPoolAddress.contains(_asset), "Asset's pool already exists");
assetToPoolAddress.set(_asset, _poolAddress);
emit PoolAssetAdded(msg.sender, _asset, _poolAddress, block.timestamp);
}
function addTokenAssets(Asset[] memory tokenAssets) public onlyOwner {
for (uint256 i = 0; i < tokenAssets.length; i++) {
_addTokenAsset(tokenAssets[i].asset, tokenAssets[i].assetAddress, tokenAssets[i].debtCoverage);
}
}
function isTokenAssetActive(address token) external view returns(bool) {
return tokenToStatus[token] == _ACTIVE;
}
function activateToken(address token) public onlyOwner {
require(tokenToStatus[token] == _INACTIVE, "Must be inactive");
tokenToStatus[token] = _ACTIVE;
emit TokenAssetActivated(msg.sender, token, block.timestamp);
}
function deactivateToken(address token) public onlyOwner {
require(tokenToStatus[token] == _ACTIVE, "Must be active");
tokenToStatus[token] = _INACTIVE;
emit TokenAssetDeactivated(msg.sender, token, block.timestamp);
}
function _addTokenAsset(bytes32 _asset, address _tokenAddress, uint256 _debtCoverage) internal {
require(_asset != "", "Cannot set an empty string asset.");
require(_tokenAddress != address(0), "Cannot set an empty address.");
require(!assetToTokenAddress.contains(_asset), "Asset's token already exists");
require(tokenAddressToSymbol[_tokenAddress] == 0, "Asset address is already in use");
setDebtCoverage(_tokenAddress, _debtCoverage);
assetToTokenAddress.set(_asset, _tokenAddress);
tokenAddressToSymbol[_tokenAddress] = _asset;
tokenToStatus[_tokenAddress] = _ACTIVE;
supportedTokensList.push(_tokenAddress);
tokenPositionInList[_tokenAddress] = supportedTokensList.length - 1;
emit TokenAssetAdded(msg.sender, _asset, _tokenAddress, block.timestamp);
}
function _removeTokenFromList(address tokenToRemove) internal {
// Move last address token to the `tokenToRemoveIndex` position (index of an asset that is being removed) in the address[] supportedTokensList
// and update map(address=>uint256) tokenPostitionInList if the token is not already the last element
uint256 tokenToRemoveIndex = tokenPositionInList[tokenToRemove];
if (tokenToRemoveIndex != (supportedTokensList.length - 1)) {
address currentLastToken = supportedTokensList[supportedTokensList.length - 1];
tokenPositionInList[currentLastToken] = tokenToRemoveIndex;
supportedTokensList[tokenToRemoveIndex] = currentLastToken;
}
// Remove last element - that is either the token that is being removed (if was already at the end)
// or some other asset that at this point was already copied to the `index` positon
supportedTokensList.pop();
tokenPositionInList[tokenToRemove] = 0;
}
function removeTokenAssets(bytes32[] memory _tokenAssets) public onlyOwner {
for (uint256 i = 0; i < _tokenAssets.length; i++) {
_removeTokenAsset(_tokenAssets[i]);
}
}
function _removeTokenAsset(bytes32 _tokenAsset) internal {
address tokenAddress = getAssetAddress(_tokenAsset, true);
EnumerableMap.remove(assetToTokenAddress, _tokenAsset);
tokenAddressToSymbol[tokenAddress] = 0;
tokenToStatus[tokenAddress] = _NOT_SUPPORTED;
debtCoverage[tokenAddress] = 0;
_removeTokenFromList(tokenAddress);
emit TokenAssetRemoved(msg.sender, _tokenAsset, block.timestamp);
}
function removePoolAssets(bytes32[] memory _poolAssets) public onlyOwner {
for (uint256 i = 0; i < _poolAssets.length; i++) {
_removePoolAsset(_poolAssets[i]);
}
}
function _removePoolAsset(bytes32 _poolAsset) internal {
address poolAddress = getPoolAddress(_poolAsset);
EnumerableMap.remove(assetToPoolAddress, _poolAsset);
emit PoolAssetRemoved(msg.sender, _poolAsset, poolAddress, block.timestamp);
}
function setDebtCoverage(address token, uint256 coverage) public onlyOwner {
//LTV must be lower than 5
require(coverage <= 0.833333333333333333e18, 'Debt coverage higher than maximum acceptable');
debtCoverage[token] = coverage;
}
function setDebtCoverageStaked(bytes32 stakedAsset, uint256 coverage) public onlyOwner {
//LTV must be lower than 5
require(coverage <= 0.833333333333333333e18, 'Debt coverage higher than maximum acceptable');
debtCoverageStaked[stakedAsset] = coverage;
}
function getSmartLoansFactoryAddress() public view virtual returns (address) {
return 0xFf5e3dDaefF411a1dC6CcE00014e4Bca39265c20;
}
/* ========== OVERRIDDEN FUNCTIONS ========== */
function renounceOwnership() public virtual override {}
/* ========== MODIFIERS ========== */
modifier onlyPrimeAccountOrOwner() {
IBorrowersRegistry borrowersRegistry = IBorrowersRegistry(getSmartLoansFactoryAddress());
require(borrowersRegistry.canBorrow(msg.sender) || owner() == _msgSender(), "Only PrimeAccount or owner can change protocol exposure");
_;
}
/**
* @dev emitted after changing current protocol exposure
* @param performer an address of the wallet changing the exposure
* @param identifier group identifier
* @param newExposure new current protocol exposure
* @param timestamp time of associating identifier with a exposure group
**/
event ProtocolExposureChanged(address indexed performer, bytes32 indexed identifier, uint256 newExposure, uint256 timestamp);
/**
* @dev emitted after associating identifier with a exposure group
* @param performer an address of the wallet setting max exposure
* @param identifier asset identifier
* @param exposureGroup exposure group identifier
* @param timestamp time of associating identifier with a exposure group
**/
event IdentifierToExposureGroupSet(address indexed performer, bytes32 indexed identifier, bytes32 indexed exposureGroup, uint256 timestamp);
/**
* @dev emitted after setting max exposure for a given protocol.
* @param performer an address of the wallet setting max exposure
* @param groupIdentifier exposure group identifier
* @param prevMaxExposure previous max protocol exposure
* @param newMaxExposure new max protocol exposure
* @param currentExposure current protocol exposure
* @param timestamp time of setting max exposure
**/
event ProtocolExposureSet(address indexed performer, bytes32 indexed groupIdentifier, uint256 prevMaxExposure, uint256 newMaxExposure, uint256 currentExposure, uint256 timestamp);
/**
* @dev emitted after setting max exposure for a given protocol.
* @param performer an address of the wallet setting max exposure
* @param groupIdentifier exposure group identifier
* @param prevCurrentExposure previous max protocol exposure
* @param newCurrentExposure new max protocol exposure
* @param timestamp time of setting max exposure
**/
event ProtocolCurrentExposureSet(address indexed performer, bytes32 indexed groupIdentifier, uint256 prevCurrentExposure, uint256 newCurrentExposure, uint256 timestamp);
/**
* @dev emitted after adding a token asset
* @param performer an address of the wallet adding a token asset
* @param tokenAsset token asset
* @param assetAddress an address of the token asset
* @param timestamp time of adding a token asset
**/
event TokenAssetAdded(address indexed performer, bytes32 indexed tokenAsset, address assetAddress, uint256 timestamp);
/**
* @dev emitted after activating a token asset
* @param performer an address of the wallet activating a token asset
* @param assetAddress an address of the token asset
* @param timestamp time of activating a token asset
**/
event TokenAssetActivated(address indexed performer, address assetAddress, uint256 timestamp);
/**
* @dev emitted after deactivating a token asset
* @param performer an address of the wallet deactivating a token asset
* @param assetAddress an address of the token asset
* @param timestamp time of deactivating a token asset
**/
event TokenAssetDeactivated(address indexed performer, address assetAddress, uint256 timestamp);
/**
* @dev emitted after removing a token asset
* @param performer an address of the wallet removing a token asset
* @param tokenAsset token asset
* @param timestamp time a token asset removal
**/
event TokenAssetRemoved(address indexed performer, bytes32 indexed tokenAsset, uint256 timestamp);
/**
* @dev emitted after adding a pool asset
* @param performer an address of wallet adding the pool asset
* @param poolAsset pool asset
* @param poolAddress an address of the pool asset
* @param timestamp time of the pool asset addition
**/
event PoolAssetAdded(address indexed performer, bytes32 indexed poolAsset, address poolAddress, uint256 timestamp);
/**
* @dev emitted after removing a pool asset
* @param performer an address of wallet removing the pool asset
* @param poolAsset pool asset
* @param poolAddress an address of the pool asset
* @param timestamp time of a pool asset removal
**/
event PoolAssetRemoved(address indexed performer, bytes32 indexed poolAsset, address poolAddress, uint256 timestamp);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/ContextUpgradeable.sol";
import "../proxy/utils/Initializable.sol";
/**
* @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 Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
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);
}
/**
* 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;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.0;
import "../../utils/AddressUpgradeable.sol";
/**
* @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.
*
* 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 initialize the implementation contract, you can either invoke the
* initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() initializer {}
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
*/
bool private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Modifier to protect an initializer function from being invoked twice.
*/
modifier initializer() {
// If the contract is initializing we ignore whether _initialized is set in order to support multiple
// inheritance patterns, but we only do this in the context of a constructor, because in other contexts the
// contract may have been reentered.
require(_initializing ? _isConstructor() : !_initialized, "Initializable: contract is already initialized");
bool isTopLevelCall = !_initializing;
if (isTopLevelCall) {
_initializing = true;
_initialized = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
}
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} modifier, directly or indirectly.
*/
modifier onlyInitializing() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
function _isConstructor() private view returns (bool) {
return !AddressUpgradeable.isContract(address(this));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.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
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract 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;
}
/**
* 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;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/structs/EnumerableSet.sol)
pragma solidity ^0.8.0;
/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
*
* ```
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*/
library EnumerableSet {
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Set type with
// bytes32 values.
// The Set implementation uses private functions, and user-facing
// implementations (such as AddressSet) are just wrappers around the
// underlying Set.
// This means that we can only create new EnumerableSets for types that fit
// in bytes32.
struct Set {
// Storage of set values
bytes32[] _values;
// Position of the value in the `values` array, plus 1 because index 0
// means a value is not in the set.
mapping(bytes32 => uint256) _indexes;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes
// and use 0 as a sentinel value
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function _remove(Set storage set, bytes32 value) private returns (bool) {
// We read and store the value's index to prevent multiple reads from the same storage slot
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) {
// Equivalent to contains(set, value)
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in
// the array, and then remove the last element (sometimes called as 'swap and pop').
// This modifies the order of the array, as noted in {at}.
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
if (lastIndex != toDeleteIndex) {
bytes32 lastvalue = set._values[lastIndex];
// Move the last value to the index where the value to delete is
set._values[toDeleteIndex] = lastvalue;
// Update the index for the moved value
set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex
}
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the index for the deleted slot
delete set._indexes[value];
return true;
} else {
return false;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[value] != 0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function _at(Set storage set, uint256 index) private view returns (bytes32) {
return set._values[index];
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function _values(Set storage set) private view returns (bytes32[] memory) {
return set._values;
}
// Bytes32Set
struct Bytes32Set {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
return _values(set._inner);
}
// AddressSet
struct AddressSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
assembly {
result := store
}
return result;
}
// UintSet
struct UintSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
assembly {
result := store
}
return result;
}
}// SPDX-License-Identifier: BUSL-1.1
// Last deployed from commit: ;
pragma solidity 0.8.17;
/**
* @title IBorrowersRegistry
* Keeps a registry of created trading accounts to verify their borrowing rights
*/
interface IBorrowersRegistry {
function canBorrow(address _account) external view returns (bool);
function getLoanForOwner(address _owner) external view returns (address);
function getOwnerOfLoan(address _loan) external view returns (address);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
//It's Open Zeppelin EnumerableMap library modified to accept bytes32 type as a key
/**
* @dev Library for managing an enumerable variant of Solidity's
* https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]
* type.
*
* Maps have the following properties:
*
* - Entries are added, removed, and checked for existence in constant time
* (O(1)).
* - Entries are enumerated in O(n). No guarantees are made on the ordering.
*
*/
library EnumerableMap {
using EnumerableSet for EnumerableSet.Bytes32Set;
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Map type with
// bytes32 keys and values.
// The Map implementation uses private functions, and user-facing
// implementations (such as Bytes32ToAddressMap) are just wrappers around
// the underlying Map.
// This means that we can only create new EnumerableMaps for types that fit
// in bytes32.
struct Map {
// Storage of keys
EnumerableSet.Bytes32Set _keys;
mapping(bytes32 => bytes32) _values;
}
/**
* @dev Adds a key-value pair to a map, or updates the value for an existing
* key. O(1).
*
* Returns true if the key was added to the map, that is if it was not
* already present.
*/
function _set(
Map storage map,
bytes32 key,
bytes32 value
) private returns (bool) {
map._values[key] = value;
return map._keys.add(key);
}
/**
* @dev Removes a key-value pair from a map. O(1).
*
* Returns true if the key was removed from the map, that is if it was present.
*/
function _remove(Map storage map, bytes32 key) private returns (bool) {
delete map._values[key];
return map._keys.remove(key);
}
/**
* @dev Returns true if the key is in the map. O(1).
*/
function _contains(Map storage map, bytes32 key) private view returns (bool) {
return map._keys.contains(key);
}
/**
* @dev Returns the number of key-value pairs in the map. O(1).
*/
function _length(Map storage map) private view returns (uint256) {
return map._keys.length();
}
/**
* @dev Returns the key-value pair stored at position `index` in the map. O(1).
*
* Note that there are no guarantees on the ordering of entries inside the
* array, and it may change when more entries are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {
bytes32 key = map._keys.at(index);
return (key, map._values[key]);
}
/**
* @dev Tries to returns the value associated with `key`. O(1).
* Does not revert if `key` is not in the map.
*/
function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {
bytes32 value = map._values[key];
if (value == bytes32(0)) {
return (_contains(map, key), bytes32(0));
} else {
return (true, value);
}
}
/**
* @dev Returns the value associated with `key`. O(1).
*
* Requirements:
*
* - `key` must be in the map.
*/
function _get(Map storage map, bytes32 key) private view returns (bytes32) {
bytes32 value = map._values[key];
require(value != 0 || _contains(map, key), "EnumerableMap: nonexistent key");
return value;
}
/**
* @dev Same as {_get}, with a custom error message when `key` is not in the map.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {_tryGet}.
*/
function _get(
Map storage map,
bytes32 key,
string memory errorMessage
) private view returns (bytes32) {
bytes32 value = map._values[key];
require(value != 0 || _contains(map, key), errorMessage);
return value;
}
// Bytes32ToAddressMap
struct Bytes32ToAddressMap {
Map _inner;
}
/**
* @dev Adds a key-value pair to a map, or updates the value for an existing
* key. O(1).
*
* Returns true if the key was added to the map, that is if it was not
* already present.
*/
function set(
Bytes32ToAddressMap storage map,
bytes32 key,
address value
) internal returns (bool) {
return _set(map._inner, key, bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the key was removed from the map, that is if it was present.
*/
function remove(Bytes32ToAddressMap storage map, bytes32 key) internal returns (bool) {
return _remove(map._inner, key);
}
/**
* @dev Returns true if the key is in the map. O(1).
*/
function contains(Bytes32ToAddressMap storage map, bytes32 key) internal view returns (bool) {
return _contains(map._inner, key);
}
/**
* @dev Returns the number of elements in the map. O(1).
*/
function length(Bytes32ToAddressMap storage map) internal view returns (uint256) {
return _length(map._inner);
}
/**
* @dev Returns the element stored at position `index` in the set. O(1).
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32ToAddressMap storage map, uint256 index) internal view returns (bytes32, address) {
(bytes32 key, bytes32 value) = _at(map._inner, index);
return (key, address(uint160(uint256(value))));
}
/**
* @dev Tries to returns the value associated with `key`. O(1).
* Does not revert if `key` is not in the map.
*
* _Available since v3.4._
*/
function tryGet(Bytes32ToAddressMap storage map, bytes32 key) internal view returns (bool, address) {
(bool success, bytes32 value) = _tryGet(map._inner, key);
return (success, address(uint160(uint256(value))));
}
/**
* @dev Returns the value associated with `key`. O(1).
*
* Requirements:
*
* - `key` must be in the map.
*/
function get(Bytes32ToAddressMap storage map, bytes32 key) internal view returns (address) {
return address(uint160(uint256(_get(map._inner, key))));
}
/**
* @dev Same as {get}, with a custom error message when `key` is not in the map.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryGet}.
*/
function get(
Bytes32ToAddressMap storage map,
bytes32 key,
string memory errorMessage
) internal view returns (address) {
return address(uint160(uint256(_get(map._inner, key, errorMessage))));
}
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"metadata": {
"useLiteralContent": true
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"performer","type":"address"},{"indexed":true,"internalType":"bytes32","name":"identifier","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"exposureGroup","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"IdentifierToExposureGroupSet","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":true,"internalType":"address","name":"performer","type":"address"},{"indexed":true,"internalType":"bytes32","name":"poolAsset","type":"bytes32"},{"indexed":false,"internalType":"address","name":"poolAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"PoolAssetAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"performer","type":"address"},{"indexed":true,"internalType":"bytes32","name":"poolAsset","type":"bytes32"},{"indexed":false,"internalType":"address","name":"poolAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"PoolAssetRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"performer","type":"address"},{"indexed":true,"internalType":"bytes32","name":"groupIdentifier","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"prevCurrentExposure","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newCurrentExposure","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"ProtocolCurrentExposureSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"performer","type":"address"},{"indexed":true,"internalType":"bytes32","name":"identifier","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"newExposure","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"ProtocolExposureChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"performer","type":"address"},{"indexed":true,"internalType":"bytes32","name":"groupIdentifier","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"prevMaxExposure","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newMaxExposure","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"currentExposure","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"ProtocolExposureSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"performer","type":"address"},{"indexed":false,"internalType":"address","name":"assetAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"TokenAssetActivated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"performer","type":"address"},{"indexed":true,"internalType":"bytes32","name":"tokenAsset","type":"bytes32"},{"indexed":false,"internalType":"address","name":"assetAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"TokenAssetAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"performer","type":"address"},{"indexed":false,"internalType":"address","name":"assetAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"TokenAssetDeactivated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"performer","type":"address"},{"indexed":true,"internalType":"bytes32","name":"tokenAsset","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"TokenAssetRemoved","type":"event"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"activateToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"asset","type":"bytes32"},{"internalType":"address","name":"poolAddress","type":"address"}],"internalType":"struct TokenManager.poolAsset[]","name":"poolAssets","type":"tuple[]"}],"name":"addPoolAssets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"asset","type":"bytes32"},{"internalType":"address","name":"assetAddress","type":"address"},{"internalType":"uint256","name":"debtCoverage","type":"uint256"}],"internalType":"struct TokenManager.Asset[]","name":"tokenAssets","type":"tuple[]"}],"name":"addTokenAssets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"deactivateToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"debtCoverage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"debtCoverageStaked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"assetIdentifier","type":"bytes32"},{"internalType":"uint256","name":"exposureDecrease","type":"uint256"}],"name":"decreaseProtocolExposure","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAllPoolAssets","outputs":[{"internalType":"bytes32[]","name":"result","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllTokenAssets","outputs":[{"internalType":"bytes32[]","name":"result","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_asset","type":"bytes32"},{"internalType":"bool","name":"allowInactive","type":"bool"}],"name":"getAssetAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_asset","type":"bytes32"}],"name":"getPoolAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSmartLoansFactoryAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSupportedTokensAddresses","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"groupToExposure","outputs":[{"internalType":"uint256","name":"current","type":"uint256"},{"internalType":"uint256","name":"max","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"identifierToExposureGroup","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"assetIdentifier","type":"bytes32"},{"internalType":"uint256","name":"exposureIncrease","type":"uint256"}],"name":"increaseProtocolExposure","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"asset","type":"bytes32"},{"internalType":"address","name":"assetAddress","type":"address"},{"internalType":"uint256","name":"debtCoverage","type":"uint256"}],"internalType":"struct TokenManager.Asset[]","name":"tokenAssets","type":"tuple[]"},{"components":[{"internalType":"bytes32","name":"asset","type":"bytes32"},{"internalType":"address","name":"poolAddress","type":"address"}],"internalType":"struct TokenManager.poolAsset[]","name":"poolAssets","type":"tuple[]"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"isTokenAssetActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"_poolAssets","type":"bytes32[]"}],"name":"removePoolAssets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"_tokenAssets","type":"bytes32[]"}],"name":"removeTokenAssets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"groupIdentifiers","type":"bytes32[]"},{"internalType":"uint256[]","name":"currentExposures","type":"uint256[]"}],"name":"setCurrentProtocolExposure","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"coverage","type":"uint256"}],"name":"setDebtCoverage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"stakedAsset","type":"bytes32"},{"internalType":"uint256","name":"coverage","type":"uint256"}],"name":"setDebtCoverageStaked","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"identifiers","type":"bytes32[]"},{"internalType":"bytes32[]","name":"exposureGroups","type":"bytes32[]"}],"name":"setIdentifiersToExposureGroups","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"groupIdentifiers","type":"bytes32[]"},{"internalType":"uint256[]","name":"maxExposures","type":"uint256[]"}],"name":"setMaxProtocolsExposure","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"supportedTokensList","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tokenAddressToSymbol","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tokenToStatus","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
608060405234801561001057600080fd5b506123f3806100206000396000f3fe608060405234801561001057600080fd5b50600436106101e55760003560e01c8063762b887a1161010f578063d1bc0831116100a2578063f38555aa11610071578063f38555aa14610460578063f823f1e014610473578063fda4963b14610493578063fff3d39a146104a657600080fd5b8063d1bc083114610407578063e0117bdd1461041a578063ecfc19a01461043a578063f2fde38b1461044d57600080fd5b8063a2d27933116100de578063a2d27933146103bb578063adfe6a0f146103ce578063c3cc6c7a146103e1578063d195f047146103f457600080fd5b8063762b887a1461037c578063869c490d1461038f5780638ce76c05146103975780638da5cb5b146103aa57600080fd5b8063326c2e971161018757806366273c191161015657806366273c191461033457806368173bcf146103495780636953c06c1461035c578063715018a6146101fd57600080fd5b8063326c2e971461029757806335923e03146102c55780633f8ef5c81461030157806363c918771461032157600080fd5b806321f88097116101c357806321f880971461024257806325eb876f146102575780632caeffe21461026a57806331e7866c1461028457600080fd5b806303223bb4146101ea5780630d1ce2d2146101ff5780630edc25b614610212575b600080fd5b6101fd6101f8366004611ce6565b6104e2565b005b6101fd61020d366004611d66565b61061a565b610225610220366004611d81565b6106fa565b6040516001600160a01b0390911681526020015b60405180910390f35b61024a610767565b6040516102399190611d9a565b610225610265366004611df5565b6107c9565b73ff5e3ddaeff411a1dc6cce00014e4bca39265c20610225565b6101fd610292366004611e25565b61088c565b6102b76102a5366004611d81565b60716020526000908152604090205481565b604051908152602001610239565b6102f16102d3366004611d66565b6001600160a01b03166000908152606f602052604090205460021490565b6040519015158152602001610239565b6102b761030f366004611d81565b60706020526000908152604090205481565b61022561032f366004611d81565b6108fa565b61033c610924565b6040516102399190611e4f565b6101fd610357366004611d66565b61097a565b6102b761036a366004611d66565b606d6020526000908152604090205481565b6101fd61038a366004611fa8565b610a53565b61033c610b27565b6101fd6103a5366004612002565b610b7c565b6033546001600160a01b0316610225565b6101fd6103c93660046120bd565b610c21565b6101fd6103dc3660046120f2565b610ccf565b6101fd6103ef3660046120f2565b610e15565b6101fd610402366004612002565b610f9c565b6101fd610415366004612114565b611041565b6102b7610428366004611d66565b606f6020526000908152604090205481565b6101fd6104483660046120f2565b6110ab565b6101fd61045b366004611d66565b61110f565b6101fd61046e366004612149565b6111aa565b6102b7610481366004611d66565b606b6020526000908152604090205481565b6101fd6104a1366004612114565b611236565b6104cd6104b4366004611d81565b6072602052600090815260409020805460019091015482565b60408051928352602083019190915201610239565b6033546001600160a01b031633146105155760405162461bcd60e51b815260040161050c9061217e565b60405180910390fd5b80518251146105365760405162461bcd60e51b815260040161050c906121b3565b60005b825181101561061557818181518110610554576105546121ea565b602002602001015160716000858481518110610572576105726121ea565b602002602001015181526020019081526020016000208190555081818151811061059e5761059e6121ea565b60200260200101518382815181106105b8576105b86121ea565b6020026020010151336001600160a01b03167f6185e65460908e4de770553685b03f20921bc24a081923fc2ca1f0ba7d18cd5f426040516105fb91815260200190565b60405180910390a48061060d81612216565b915050610539565b505050565b6033546001600160a01b031633146106445760405162461bcd60e51b815260040161050c9061217e565b6001600160a01b0381166000908152606f602052604090205460011461069f5760405162461bcd60e51b815260206004820152601060248201526f4d75737420626520696e61637469766560801b604482015260640161050c565b6001600160a01b0381166000818152606f6020908152604091829020600290558151928352429083015233917febd9f0d5b5df9f4d5180bbeec65fda8d99982e273d2a7365431b2a869aa826d491015b60405180910390a250565b6000806107086065846112a0565b9150506001600160a01b0381166107615760405162461bcd60e51b815260206004820152601960248201527f506f6f6c206173736574206e6f7420737570706f727465642e00000000000000604482015260640161050c565b92915050565b6060606e8054806020026020016040519081016040528092919081815260200182805480156107bf57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116107a1575b5050505050905090565b6000806107d76068856112a0565b9150506001600160a01b0381166108275760405162461bcd60e51b815260206004820152601460248201527320b9b9b2ba103737ba1039bab83837b93a32b21760611b604482015260640161050c565b82610885576001600160a01b0381166000908152606f60205260409020546002146108855760405162461bcd60e51b815260206004820152600e60248201526d417373657420696e61637469766560901b604482015260640161050c565b9392505050565b6033546001600160a01b031633146108b65760405162461bcd60e51b815260040161050c9061217e565b670b90984060d355558111156108de5760405162461bcd60e51b815260040161050c9061222f565b6001600160a01b039091166000908152606d6020526040902055565b606e818154811061090a57600080fd5b6000918252602090912001546001600160a01b0316905081565b6065805460408051602080840282018101909252828152606093909290918301828280156107bf57602002820191906000526020600020905b81548152602001906001019080831161095d575050505050905090565b6033546001600160a01b031633146109a45760405162461bcd60e51b815260040161050c9061217e565b6001600160a01b0381166000908152606f60205260409020546002146109fd5760405162461bcd60e51b815260206004820152600e60248201526d4d7573742062652061637469766560901b604482015260640161050c565b6001600160a01b0381166000818152606f6020908152604091829020600190558151928352429083015233917fbf0b0e2d837fddaee4742e91f53ca36bac9fdebdd571738027abb2b5f7c9a2f091016106ef565b565b600054610100900460ff16610a6e5760005460ff1615610a72565b303b155b610ad55760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161050c565b600054610100900460ff16158015610af7576000805461ffff19166101011790555b610aff6112be565b610b0883610c21565b610b11826111aa565b8015610615576000805461ff0019169055505050565b6068805460408051602080840282018101909252828152606093909290918301828280156107bf576020028201919060005260206000209081548152602001906001019080831161095d575050505050905090565b6033546001600160a01b03163314610ba65760405162461bcd60e51b815260040161050c9061217e565b8051825114610bc75760405162461bcd60e51b815260040161050c906121b3565b60005b825181101561061557610c0f838281518110610be857610be86121ea565b6020026020010151838381518110610c0257610c026121ea565b60200260200101516112ed565b80610c1981612216565b915050610bca565b6033546001600160a01b03163314610c4b5760405162461bcd60e51b815260040161050c9061217e565b60005b8151811015610ccb57610cb9828281518110610c6c57610c6c6121ea565b602002602001015160000151838381518110610c8a57610c8a6121ea565b602002602001015160200151848481518110610ca857610ca86121ea565b60200260200101516040015161136f565b80610cc381612216565b915050610c4e565b5050565b600073ff5e3ddaeff411a1dc6cce00014e4bca39265c2060405163039ff21960e21b81523360048201529091506001600160a01b03821690630e7fc86490602401602060405180830381865afa158015610d2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d51919061227b565b80610d6657506033546001600160a01b031633145b610d825760405162461bcd60e51b815260040161050c90612298565b6000838152607160205260409020548015610e0f576000818152607260205260409020600181015415610e0d578054841015610dca578054610dc59085906122f5565b610dcd565b60005b815560408051858152426020820152839133917f45262a952f63661e3b881eb82a0d0bd391ab35692bd26023356b06e452230d4391015b60405180910390a35b505b50505050565b600073ff5e3ddaeff411a1dc6cce00014e4bca39265c2060405163039ff21960e21b81523360048201529091506001600160a01b03821690630e7fc86490602401602060405180830381865afa158015610e73573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e97919061227b565b80610eac57506033546001600160a01b031633145b610ec85760405162461bcd60e51b815260040161050c90612298565b6000838152607160205260409020548015610e0f576000818152607260205260409020600181015415610e0d5783816000016000828254610f099190612308565b9091555050600181015481541115610f635760405162461bcd60e51b815260206004820152601b60248201527f4d6178206173736574206578706f737572652062726561636865640000000000604482015260640161050c565b60408051858152426020820152839133917f45262a952f63661e3b881eb82a0d0bd391ab35692bd26023356b06e452230d439101610e04565b6033546001600160a01b03163314610fc65760405162461bcd60e51b815260040161050c9061217e565b8051825114610fe75760405162461bcd60e51b815260040161050c906121b3565b60005b82518110156106155761102f838281518110611008576110086121ea565b6020026020010151838381518110611022576110226121ea565b602002602001015161158b565b8061103981612216565b915050610fea565b6033546001600160a01b0316331461106b5760405162461bcd60e51b815260040161050c9061217e565b60005b8151811015610ccb5761109982828151811061108c5761108c6121ea565b602002602001015161160f565b806110a381612216565b91505061106e565b6033546001600160a01b031633146110d55760405162461bcd60e51b815260040161050c9061217e565b670b90984060d355558111156110fd5760405162461bcd60e51b815260040161050c9061222f565b60009182526070602052604090912055565b6033546001600160a01b031633146111395760405162461bcd60e51b815260040161050c9061217e565b6001600160a01b03811661119e5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161050c565b6111a78161169f565b50565b6033546001600160a01b031633146111d45760405162461bcd60e51b815260040161050c9061217e565b60005b8151811015610ccb576112248282815181106111f5576111f56121ea565b602002602001015160000151838381518110611213576112136121ea565b6020026020010151602001516116f1565b8061122e81612216565b9150506111d7565b6033546001600160a01b031633146112605760405162461bcd60e51b815260040161050c9061217e565b60005b8151811015610ccb5761128e828281518110611281576112816121ea565b60200260200101516117fd565b8061129881612216565b915050611263565b60008080806112af8686611858565b909450925050505b9250929050565b600054610100900460ff166112e55760405162461bcd60e51b815260040161050c9061231b565b610a51611892565b8160000361130d5760405162461bcd60e51b815260040161050c90612366565b60008281526072602090815260409182902080549084905582518181529182018490524292820192909252839033907f073dc16e9ad72465ac9c9d5249ac0b1ba512ca440e461ff67a34c38e29c3413e906060015b60405180910390a3505050565b8260000361138f5760405162461bcd60e51b815260040161050c90612366565b6001600160a01b0382166113e55760405162461bcd60e51b815260206004820152601c60248201527f43616e6e6f742073657420616e20656d70747920616464726573732e00000000604482015260640161050c565b6113f06068846118c2565b1561143d5760405162461bcd60e51b815260206004820152601c60248201527f4173736574277320746f6b656e20616c72656164792065786973747300000000604482015260640161050c565b6001600160a01b0382166000908152606b6020526040902054156114a35760405162461bcd60e51b815260206004820152601f60248201527f4173736574206164647265737320697320616c726561647920696e2075736500604482015260640161050c565b6114ad828261088c565b6114b9606884846118ce565b506001600160a01b0382166000818152606b60209081526040808320879055606f909152812060029055606e805460018181018355928290527f9930d9ff0dee0ef5ca2f7710ea66b8f84dd0f5f5351ecffe72b952cd9db7142a0180546001600160a01b031916909317909255905461153291906122f5565b6001600160a01b0383166000818152606c60209081526040918290209390935580519182524292820192909252849133917ff73be6b27198eab18ec5fe07c2d7b2fbf4f05ffa1a05c94ca202531d7aa8c5b69101611362565b816000036115ab5760405162461bcd60e51b815260040161050c90612366565b600082815260726020908152604091829020600181018054908590559054835182815292830185905292820192909252426060820152839033907f4e3db1a563ebfee7c496974d792038536dc8311892551dc36d19116131e3dd3c90608001611362565b600061161c8260016107c9565b90506116296068836118ec565b506001600160a01b0381166000908152606b60209081526040808320839055606f8252808320839055606d909152812055611663816118f8565b604051428152829033907f228e158b51be6445b7bd2f4121209717a371d44c7c53d4085ae7f5e496153a93906020015b60405180910390a35050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b0381163b6117565760405162461bcd60e51b815260206004820152602560248201527f546f6b656e4d616e616765723a20506f6f6c206d757374206265206120636f6e6044820152641d1c9858dd60da1b606482015260840161050c565b6117616065836118c2565b156117ae5760405162461bcd60e51b815260206004820152601b60248201527f4173736574277320706f6f6c20616c7265616479206578697374730000000000604482015260640161050c565b6117ba606583836118ce565b50604080516001600160a01b0383168152426020820152839133917fcfbf9a4f33420379df003923a1d986358bb97d4b3455baae186db1d5d35cda3e9101611693565b6000611808826106fa565b90506118156065836118ec565b50604080516001600160a01b0383168152426020820152839133917ff658b7b16fbc2f0f51a3320cc57763ccd8d13f554c4eb34ff0f5b49624b32e839101611693565b60008181526002830160205260408120548190806118875761187a8585611a0c565b9250600091506112b79050565b6001925090506112b7565b600054610100900460ff166118b95760405162461bcd60e51b815260040161050c9061231b565b610a513361169f565b60006108858383611a0c565b60006118e484846001600160a01b038516611a18565b949350505050565b60006108858383611a35565b6001600160a01b0381166000908152606c6020526040902054606e54611920906001906122f5565b81146119ba57606e80546000919061193a906001906122f5565b8154811061194a5761194a6121ea565b60009182526020808320909101546001600160a01b0316808352606c9091526040909120839055606e805491925082918490811061198a5761198a6121ea565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505b606e8054806119cb576119cb6123a7565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b03939093168152606c909252506040812055565b60006108858383611a52565b600082815260028401602052604081208290556118e48484611a6a565b600081815260028301602052604081208190556108858383611a76565b60008181526001830160205260408120541515610885565b60006108858383611a82565b60006108858383611ad1565b6000818152600183016020526040812054611ac957508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610761565b506000610761565b60008181526001830160205260408120548015611bba576000611af56001836122f5565b8554909150600090611b09906001906122f5565b9050818114611b6e576000866000018281548110611b2957611b296121ea565b9060005260206000200154905080876000018481548110611b4c57611b4c6121ea565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611b7f57611b7f6123a7565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610761565b6000915050610761565b634e487b7160e01b600052604160045260246000fd5b6040516060810167ffffffffffffffff81118282101715611bfd57611bfd611bc4565b60405290565b6040805190810167ffffffffffffffff81118282101715611bfd57611bfd611bc4565b604051601f8201601f1916810167ffffffffffffffff81118282101715611c4f57611c4f611bc4565b604052919050565b600067ffffffffffffffff821115611c7157611c71611bc4565b5060051b60200190565b600082601f830112611c8c57600080fd5b81356020611ca1611c9c83611c57565b611c26565b82815260059290921b84018101918181019086841115611cc057600080fd5b8286015b84811015611cdb5780358352918301918301611cc4565b509695505050505050565b60008060408385031215611cf957600080fd5b823567ffffffffffffffff80821115611d1157600080fd5b611d1d86838701611c7b565b93506020850135915080821115611d3357600080fd5b50611d4085828601611c7b565b9150509250929050565b80356001600160a01b0381168114611d6157600080fd5b919050565b600060208284031215611d7857600080fd5b61088582611d4a565b600060208284031215611d9357600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b81811015611ddb5783516001600160a01b031683529284019291840191600101611db6565b50909695505050505050565b80151581146111a757600080fd5b60008060408385031215611e0857600080fd5b823591506020830135611e1a81611de7565b809150509250929050565b60008060408385031215611e3857600080fd5b611e4183611d4a565b946020939093013593505050565b6020808252825182820181905260009190848201906040850190845b81811015611ddb57835183529284019291840191600101611e6b565b600082601f830112611e9857600080fd5b81356020611ea8611c9c83611c57565b82815260609283028501820192828201919087851115611ec757600080fd5b8387015b85811015611f155781818a031215611ee35760008081fd5b611eeb611bda565b81358152611efa868301611d4a565b81870152604082810135908201528452928401928101611ecb565b5090979650505050505050565b600082601f830112611f3357600080fd5b81356020611f43611c9c83611c57565b82815260069290921b84018101918181019086841115611f6257600080fd5b8286015b84811015611cdb5760408189031215611f7f5760008081fd5b611f87611c03565b81358152611f96858301611d4a565b81860152835291830191604001611f66565b60008060408385031215611fbb57600080fd5b823567ffffffffffffffff80821115611fd357600080fd5b611fdf86838701611e87565b93506020850135915080821115611ff557600080fd5b50611d4085828601611f22565b6000806040838503121561201557600080fd5b823567ffffffffffffffff8082111561202d57600080fd5b61203986838701611c7b565b935060209150818501358181111561205057600080fd5b85019050601f8101861361206357600080fd5b8035612071611c9c82611c57565b81815260059190911b8201830190838101908883111561209057600080fd5b928401925b828410156120ae57833582529284019290840190612095565b80955050505050509250929050565b6000602082840312156120cf57600080fd5b813567ffffffffffffffff8111156120e657600080fd5b6118e484828501611e87565b6000806040838503121561210557600080fd5b50508035926020909101359150565b60006020828403121561212657600080fd5b813567ffffffffffffffff81111561213d57600080fd5b6118e484828501611c7b565b60006020828403121561215b57600080fd5b813567ffffffffffffffff81111561217257600080fd5b6118e484828501611f22565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526017908201527f417272617973206c656e67746873206d69736d61746368000000000000000000604082015260600190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006001820161222857612228612200565b5060010190565b6020808252602c908201527f4465627420636f76657261676520686967686572207468616e206d6178696d7560408201526b6d2061636365707461626c6560a01b606082015260800190565b60006020828403121561228d57600080fd5b815161088581611de7565b60208082526037908201527f4f6e6c79205072696d654163636f756e74206f72206f776e65722063616e206360408201527f68616e67652070726f746f636f6c206578706f73757265000000000000000000606082015260800190565b8181038181111561076157610761612200565b8082018082111561076157610761612200565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60208082526021908201527f43616e6e6f742073657420616e20656d70747920737472696e672061737365746040820152601760f91b606082015260800190565b634e487b7160e01b600052603160045260246000fdfea26469706673582212208fc8a4610d384744f54f494787bf119ec504541c8fceefa0eacd2f03fb91352064736f6c63430008110033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101e55760003560e01c8063762b887a1161010f578063d1bc0831116100a2578063f38555aa11610071578063f38555aa14610460578063f823f1e014610473578063fda4963b14610493578063fff3d39a146104a657600080fd5b8063d1bc083114610407578063e0117bdd1461041a578063ecfc19a01461043a578063f2fde38b1461044d57600080fd5b8063a2d27933116100de578063a2d27933146103bb578063adfe6a0f146103ce578063c3cc6c7a146103e1578063d195f047146103f457600080fd5b8063762b887a1461037c578063869c490d1461038f5780638ce76c05146103975780638da5cb5b146103aa57600080fd5b8063326c2e971161018757806366273c191161015657806366273c191461033457806368173bcf146103495780636953c06c1461035c578063715018a6146101fd57600080fd5b8063326c2e971461029757806335923e03146102c55780633f8ef5c81461030157806363c918771461032157600080fd5b806321f88097116101c357806321f880971461024257806325eb876f146102575780632caeffe21461026a57806331e7866c1461028457600080fd5b806303223bb4146101ea5780630d1ce2d2146101ff5780630edc25b614610212575b600080fd5b6101fd6101f8366004611ce6565b6104e2565b005b6101fd61020d366004611d66565b61061a565b610225610220366004611d81565b6106fa565b6040516001600160a01b0390911681526020015b60405180910390f35b61024a610767565b6040516102399190611d9a565b610225610265366004611df5565b6107c9565b73ff5e3ddaeff411a1dc6cce00014e4bca39265c20610225565b6101fd610292366004611e25565b61088c565b6102b76102a5366004611d81565b60716020526000908152604090205481565b604051908152602001610239565b6102f16102d3366004611d66565b6001600160a01b03166000908152606f602052604090205460021490565b6040519015158152602001610239565b6102b761030f366004611d81565b60706020526000908152604090205481565b61022561032f366004611d81565b6108fa565b61033c610924565b6040516102399190611e4f565b6101fd610357366004611d66565b61097a565b6102b761036a366004611d66565b606d6020526000908152604090205481565b6101fd61038a366004611fa8565b610a53565b61033c610b27565b6101fd6103a5366004612002565b610b7c565b6033546001600160a01b0316610225565b6101fd6103c93660046120bd565b610c21565b6101fd6103dc3660046120f2565b610ccf565b6101fd6103ef3660046120f2565b610e15565b6101fd610402366004612002565b610f9c565b6101fd610415366004612114565b611041565b6102b7610428366004611d66565b606f6020526000908152604090205481565b6101fd6104483660046120f2565b6110ab565b6101fd61045b366004611d66565b61110f565b6101fd61046e366004612149565b6111aa565b6102b7610481366004611d66565b606b6020526000908152604090205481565b6101fd6104a1366004612114565b611236565b6104cd6104b4366004611d81565b6072602052600090815260409020805460019091015482565b60408051928352602083019190915201610239565b6033546001600160a01b031633146105155760405162461bcd60e51b815260040161050c9061217e565b60405180910390fd5b80518251146105365760405162461bcd60e51b815260040161050c906121b3565b60005b825181101561061557818181518110610554576105546121ea565b602002602001015160716000858481518110610572576105726121ea565b602002602001015181526020019081526020016000208190555081818151811061059e5761059e6121ea565b60200260200101518382815181106105b8576105b86121ea565b6020026020010151336001600160a01b03167f6185e65460908e4de770553685b03f20921bc24a081923fc2ca1f0ba7d18cd5f426040516105fb91815260200190565b60405180910390a48061060d81612216565b915050610539565b505050565b6033546001600160a01b031633146106445760405162461bcd60e51b815260040161050c9061217e565b6001600160a01b0381166000908152606f602052604090205460011461069f5760405162461bcd60e51b815260206004820152601060248201526f4d75737420626520696e61637469766560801b604482015260640161050c565b6001600160a01b0381166000818152606f6020908152604091829020600290558151928352429083015233917febd9f0d5b5df9f4d5180bbeec65fda8d99982e273d2a7365431b2a869aa826d491015b60405180910390a250565b6000806107086065846112a0565b9150506001600160a01b0381166107615760405162461bcd60e51b815260206004820152601960248201527f506f6f6c206173736574206e6f7420737570706f727465642e00000000000000604482015260640161050c565b92915050565b6060606e8054806020026020016040519081016040528092919081815260200182805480156107bf57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116107a1575b5050505050905090565b6000806107d76068856112a0565b9150506001600160a01b0381166108275760405162461bcd60e51b815260206004820152601460248201527320b9b9b2ba103737ba1039bab83837b93a32b21760611b604482015260640161050c565b82610885576001600160a01b0381166000908152606f60205260409020546002146108855760405162461bcd60e51b815260206004820152600e60248201526d417373657420696e61637469766560901b604482015260640161050c565b9392505050565b6033546001600160a01b031633146108b65760405162461bcd60e51b815260040161050c9061217e565b670b90984060d355558111156108de5760405162461bcd60e51b815260040161050c9061222f565b6001600160a01b039091166000908152606d6020526040902055565b606e818154811061090a57600080fd5b6000918252602090912001546001600160a01b0316905081565b6065805460408051602080840282018101909252828152606093909290918301828280156107bf57602002820191906000526020600020905b81548152602001906001019080831161095d575050505050905090565b6033546001600160a01b031633146109a45760405162461bcd60e51b815260040161050c9061217e565b6001600160a01b0381166000908152606f60205260409020546002146109fd5760405162461bcd60e51b815260206004820152600e60248201526d4d7573742062652061637469766560901b604482015260640161050c565b6001600160a01b0381166000818152606f6020908152604091829020600190558151928352429083015233917fbf0b0e2d837fddaee4742e91f53ca36bac9fdebdd571738027abb2b5f7c9a2f091016106ef565b565b600054610100900460ff16610a6e5760005460ff1615610a72565b303b155b610ad55760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161050c565b600054610100900460ff16158015610af7576000805461ffff19166101011790555b610aff6112be565b610b0883610c21565b610b11826111aa565b8015610615576000805461ff0019169055505050565b6068805460408051602080840282018101909252828152606093909290918301828280156107bf576020028201919060005260206000209081548152602001906001019080831161095d575050505050905090565b6033546001600160a01b03163314610ba65760405162461bcd60e51b815260040161050c9061217e565b8051825114610bc75760405162461bcd60e51b815260040161050c906121b3565b60005b825181101561061557610c0f838281518110610be857610be86121ea565b6020026020010151838381518110610c0257610c026121ea565b60200260200101516112ed565b80610c1981612216565b915050610bca565b6033546001600160a01b03163314610c4b5760405162461bcd60e51b815260040161050c9061217e565b60005b8151811015610ccb57610cb9828281518110610c6c57610c6c6121ea565b602002602001015160000151838381518110610c8a57610c8a6121ea565b602002602001015160200151848481518110610ca857610ca86121ea565b60200260200101516040015161136f565b80610cc381612216565b915050610c4e565b5050565b600073ff5e3ddaeff411a1dc6cce00014e4bca39265c2060405163039ff21960e21b81523360048201529091506001600160a01b03821690630e7fc86490602401602060405180830381865afa158015610d2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d51919061227b565b80610d6657506033546001600160a01b031633145b610d825760405162461bcd60e51b815260040161050c90612298565b6000838152607160205260409020548015610e0f576000818152607260205260409020600181015415610e0d578054841015610dca578054610dc59085906122f5565b610dcd565b60005b815560408051858152426020820152839133917f45262a952f63661e3b881eb82a0d0bd391ab35692bd26023356b06e452230d4391015b60405180910390a35b505b50505050565b600073ff5e3ddaeff411a1dc6cce00014e4bca39265c2060405163039ff21960e21b81523360048201529091506001600160a01b03821690630e7fc86490602401602060405180830381865afa158015610e73573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e97919061227b565b80610eac57506033546001600160a01b031633145b610ec85760405162461bcd60e51b815260040161050c90612298565b6000838152607160205260409020548015610e0f576000818152607260205260409020600181015415610e0d5783816000016000828254610f099190612308565b9091555050600181015481541115610f635760405162461bcd60e51b815260206004820152601b60248201527f4d6178206173736574206578706f737572652062726561636865640000000000604482015260640161050c565b60408051858152426020820152839133917f45262a952f63661e3b881eb82a0d0bd391ab35692bd26023356b06e452230d439101610e04565b6033546001600160a01b03163314610fc65760405162461bcd60e51b815260040161050c9061217e565b8051825114610fe75760405162461bcd60e51b815260040161050c906121b3565b60005b82518110156106155761102f838281518110611008576110086121ea565b6020026020010151838381518110611022576110226121ea565b602002602001015161158b565b8061103981612216565b915050610fea565b6033546001600160a01b0316331461106b5760405162461bcd60e51b815260040161050c9061217e565b60005b8151811015610ccb5761109982828151811061108c5761108c6121ea565b602002602001015161160f565b806110a381612216565b91505061106e565b6033546001600160a01b031633146110d55760405162461bcd60e51b815260040161050c9061217e565b670b90984060d355558111156110fd5760405162461bcd60e51b815260040161050c9061222f565b60009182526070602052604090912055565b6033546001600160a01b031633146111395760405162461bcd60e51b815260040161050c9061217e565b6001600160a01b03811661119e5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161050c565b6111a78161169f565b50565b6033546001600160a01b031633146111d45760405162461bcd60e51b815260040161050c9061217e565b60005b8151811015610ccb576112248282815181106111f5576111f56121ea565b602002602001015160000151838381518110611213576112136121ea565b6020026020010151602001516116f1565b8061122e81612216565b9150506111d7565b6033546001600160a01b031633146112605760405162461bcd60e51b815260040161050c9061217e565b60005b8151811015610ccb5761128e828281518110611281576112816121ea565b60200260200101516117fd565b8061129881612216565b915050611263565b60008080806112af8686611858565b909450925050505b9250929050565b600054610100900460ff166112e55760405162461bcd60e51b815260040161050c9061231b565b610a51611892565b8160000361130d5760405162461bcd60e51b815260040161050c90612366565b60008281526072602090815260409182902080549084905582518181529182018490524292820192909252839033907f073dc16e9ad72465ac9c9d5249ac0b1ba512ca440e461ff67a34c38e29c3413e906060015b60405180910390a3505050565b8260000361138f5760405162461bcd60e51b815260040161050c90612366565b6001600160a01b0382166113e55760405162461bcd60e51b815260206004820152601c60248201527f43616e6e6f742073657420616e20656d70747920616464726573732e00000000604482015260640161050c565b6113f06068846118c2565b1561143d5760405162461bcd60e51b815260206004820152601c60248201527f4173736574277320746f6b656e20616c72656164792065786973747300000000604482015260640161050c565b6001600160a01b0382166000908152606b6020526040902054156114a35760405162461bcd60e51b815260206004820152601f60248201527f4173736574206164647265737320697320616c726561647920696e2075736500604482015260640161050c565b6114ad828261088c565b6114b9606884846118ce565b506001600160a01b0382166000818152606b60209081526040808320879055606f909152812060029055606e805460018181018355928290527f9930d9ff0dee0ef5ca2f7710ea66b8f84dd0f5f5351ecffe72b952cd9db7142a0180546001600160a01b031916909317909255905461153291906122f5565b6001600160a01b0383166000818152606c60209081526040918290209390935580519182524292820192909252849133917ff73be6b27198eab18ec5fe07c2d7b2fbf4f05ffa1a05c94ca202531d7aa8c5b69101611362565b816000036115ab5760405162461bcd60e51b815260040161050c90612366565b600082815260726020908152604091829020600181018054908590559054835182815292830185905292820192909252426060820152839033907f4e3db1a563ebfee7c496974d792038536dc8311892551dc36d19116131e3dd3c90608001611362565b600061161c8260016107c9565b90506116296068836118ec565b506001600160a01b0381166000908152606b60209081526040808320839055606f8252808320839055606d909152812055611663816118f8565b604051428152829033907f228e158b51be6445b7bd2f4121209717a371d44c7c53d4085ae7f5e496153a93906020015b60405180910390a35050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b0381163b6117565760405162461bcd60e51b815260206004820152602560248201527f546f6b656e4d616e616765723a20506f6f6c206d757374206265206120636f6e6044820152641d1c9858dd60da1b606482015260840161050c565b6117616065836118c2565b156117ae5760405162461bcd60e51b815260206004820152601b60248201527f4173736574277320706f6f6c20616c7265616479206578697374730000000000604482015260640161050c565b6117ba606583836118ce565b50604080516001600160a01b0383168152426020820152839133917fcfbf9a4f33420379df003923a1d986358bb97d4b3455baae186db1d5d35cda3e9101611693565b6000611808826106fa565b90506118156065836118ec565b50604080516001600160a01b0383168152426020820152839133917ff658b7b16fbc2f0f51a3320cc57763ccd8d13f554c4eb34ff0f5b49624b32e839101611693565b60008181526002830160205260408120548190806118875761187a8585611a0c565b9250600091506112b79050565b6001925090506112b7565b600054610100900460ff166118b95760405162461bcd60e51b815260040161050c9061231b565b610a513361169f565b60006108858383611a0c565b60006118e484846001600160a01b038516611a18565b949350505050565b60006108858383611a35565b6001600160a01b0381166000908152606c6020526040902054606e54611920906001906122f5565b81146119ba57606e80546000919061193a906001906122f5565b8154811061194a5761194a6121ea565b60009182526020808320909101546001600160a01b0316808352606c9091526040909120839055606e805491925082918490811061198a5761198a6121ea565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505b606e8054806119cb576119cb6123a7565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b03939093168152606c909252506040812055565b60006108858383611a52565b600082815260028401602052604081208290556118e48484611a6a565b600081815260028301602052604081208190556108858383611a76565b60008181526001830160205260408120541515610885565b60006108858383611a82565b60006108858383611ad1565b6000818152600183016020526040812054611ac957508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610761565b506000610761565b60008181526001830160205260408120548015611bba576000611af56001836122f5565b8554909150600090611b09906001906122f5565b9050818114611b6e576000866000018281548110611b2957611b296121ea565b9060005260206000200154905080876000018481548110611b4c57611b4c6121ea565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611b7f57611b7f6123a7565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610761565b6000915050610761565b634e487b7160e01b600052604160045260246000fd5b6040516060810167ffffffffffffffff81118282101715611bfd57611bfd611bc4565b60405290565b6040805190810167ffffffffffffffff81118282101715611bfd57611bfd611bc4565b604051601f8201601f1916810167ffffffffffffffff81118282101715611c4f57611c4f611bc4565b604052919050565b600067ffffffffffffffff821115611c7157611c71611bc4565b5060051b60200190565b600082601f830112611c8c57600080fd5b81356020611ca1611c9c83611c57565b611c26565b82815260059290921b84018101918181019086841115611cc057600080fd5b8286015b84811015611cdb5780358352918301918301611cc4565b509695505050505050565b60008060408385031215611cf957600080fd5b823567ffffffffffffffff80821115611d1157600080fd5b611d1d86838701611c7b565b93506020850135915080821115611d3357600080fd5b50611d4085828601611c7b565b9150509250929050565b80356001600160a01b0381168114611d6157600080fd5b919050565b600060208284031215611d7857600080fd5b61088582611d4a565b600060208284031215611d9357600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b81811015611ddb5783516001600160a01b031683529284019291840191600101611db6565b50909695505050505050565b80151581146111a757600080fd5b60008060408385031215611e0857600080fd5b823591506020830135611e1a81611de7565b809150509250929050565b60008060408385031215611e3857600080fd5b611e4183611d4a565b946020939093013593505050565b6020808252825182820181905260009190848201906040850190845b81811015611ddb57835183529284019291840191600101611e6b565b600082601f830112611e9857600080fd5b81356020611ea8611c9c83611c57565b82815260609283028501820192828201919087851115611ec757600080fd5b8387015b85811015611f155781818a031215611ee35760008081fd5b611eeb611bda565b81358152611efa868301611d4a565b81870152604082810135908201528452928401928101611ecb565b5090979650505050505050565b600082601f830112611f3357600080fd5b81356020611f43611c9c83611c57565b82815260069290921b84018101918181019086841115611f6257600080fd5b8286015b84811015611cdb5760408189031215611f7f5760008081fd5b611f87611c03565b81358152611f96858301611d4a565b81860152835291830191604001611f66565b60008060408385031215611fbb57600080fd5b823567ffffffffffffffff80821115611fd357600080fd5b611fdf86838701611e87565b93506020850135915080821115611ff557600080fd5b50611d4085828601611f22565b6000806040838503121561201557600080fd5b823567ffffffffffffffff8082111561202d57600080fd5b61203986838701611c7b565b935060209150818501358181111561205057600080fd5b85019050601f8101861361206357600080fd5b8035612071611c9c82611c57565b81815260059190911b8201830190838101908883111561209057600080fd5b928401925b828410156120ae57833582529284019290840190612095565b80955050505050509250929050565b6000602082840312156120cf57600080fd5b813567ffffffffffffffff8111156120e657600080fd5b6118e484828501611e87565b6000806040838503121561210557600080fd5b50508035926020909101359150565b60006020828403121561212657600080fd5b813567ffffffffffffffff81111561213d57600080fd5b6118e484828501611c7b565b60006020828403121561215b57600080fd5b813567ffffffffffffffff81111561217257600080fd5b6118e484828501611f22565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526017908201527f417272617973206c656e67746873206d69736d61746368000000000000000000604082015260600190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006001820161222857612228612200565b5060010190565b6020808252602c908201527f4465627420636f76657261676520686967686572207468616e206d6178696d7560408201526b6d2061636365707461626c6560a01b606082015260800190565b60006020828403121561228d57600080fd5b815161088581611de7565b60208082526037908201527f4f6e6c79205072696d654163636f756e74206f72206f776e65722063616e206360408201527f68616e67652070726f746f636f6c206578706f73757265000000000000000000606082015260800190565b8181038181111561076157610761612200565b8082018082111561076157610761612200565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60208082526021908201527f43616e6e6f742073657420616e20656d70747920737472696e672061737365746040820152601760f91b606082015260800190565b634e487b7160e01b600052603160045260246000fdfea26469706673582212208fc8a4610d384744f54f494787bf119ec504541c8fceefa0eacd2f03fb91352064736f6c63430008110033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.