Feature Tip: Add private address tag to any address under My Name Tag !
Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
CoreBorrow
Compiler Version
v0.8.12+commit.f00d7308
Contract Source Code (Solidity)
/**
*Submitted for verification at Etherscan.io on 2022-06-15
*/
// SPDX-License-Identifier: MIT AND GPL-3.0
// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)
pragma solidity 0.8.12;
/**
* @dev External interface of AccessControl declared to support ERC165 detection.
*/
interface IAccessControlUpgradeable {
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted signaling this.
*
* _Available since v3.1._
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call, an admin role
* bearer except when using {AccessControl-_setupRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) external view returns (bool);
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) external view returns (bytes32);
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*/
function renounceRole(bytes32 role, address account) external;
}
// File @openzeppelin/contracts-upgradeable/access/[email protected]
// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol)
/**
* @dev External interface of AccessControlEnumerable declared to support ERC165 detection.
*/
interface IAccessControlEnumerableUpgradeable is IAccessControlUpgradeable {
/**
* @dev Returns one of the accounts that have `role`. `index` must be a
* value between 0 and {getRoleMemberCount}, non-inclusive.
*
* Role bearers are not sorted in any particular way, and their ordering may
* change at any point.
*
* WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure
* you perform all queries on the same block. See the following
* https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]
* for more information.
*/
function getRoleMember(bytes32 role, uint256 index) external view returns (address);
/**
* @dev Returns the number of accounts that have `role`. Can be used
* together with {getRoleMember} to enumerate all bearers of a role.
*/
function getRoleMemberCount(bytes32 role) external view returns (uint256);
}
// File @openzeppelin/contracts-upgradeable/utils/[email protected]
// OpenZeppelin Contracts v4.4.1 (utils/Address.sol)
/**
* @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
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
assembly {
size := extcodesize(account)
}
return size > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
// File @openzeppelin/contracts-upgradeable/proxy/utils/[email protected]
// OpenZeppelin Contracts v4.4.1 (proxy/utils/Initializable.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 a proxied contract can't have 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));
}
}
// File @openzeppelin/contracts-upgradeable/utils/[email protected]
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract ContextUpgradeable is Initializable {
function __Context_init() internal onlyInitializing {
__Context_init_unchained();
}
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;
}
uint256[50] private __gap;
}
// File @openzeppelin/contracts-upgradeable/utils/[email protected]
// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)
/**
* @dev String operations.
*/
library StringsUpgradeable {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
// Inspired by OraclizeAPI's implementation - MIT licence
// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
}
// File @openzeppelin/contracts-upgradeable/utils/introspection/[email protected]
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165Upgradeable {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
// File @openzeppelin/contracts-upgradeable/utils/introspection/[email protected]
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/
abstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable {
function __ERC165_init() internal onlyInitializing {
__ERC165_init_unchained();
}
function __ERC165_init_unchained() internal onlyInitializing {
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165Upgradeable).interfaceId;
}
uint256[50] private __gap;
}
// File @openzeppelin/contracts-upgradeable/access/[email protected]
// OpenZeppelin Contracts v4.4.1 (access/AccessControl.sol)
/**
* @dev Contract module that allows children to implement role-based access
* control mechanisms. This is a lightweight version that doesn't allow enumerating role
* members except through off-chain means by accessing the contract event logs. Some
* applications may benefit from on-chain enumerability, for those cases see
* {AccessControlEnumerable}.
*
* Roles are referred to by their `bytes32` identifier. These should be exposed
* in the external API and be unique. The best way to achieve this is by
* using `public constant` hash digests:
*
* ```
* bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
* ```
*
* Roles can be used to represent a set of permissions. To restrict access to a
* function call, use {hasRole}:
*
* ```
* function foo() public {
* require(hasRole(MY_ROLE, msg.sender));
* ...
* }
* ```
*
* Roles can be granted and revoked dynamically via the {grantRole} and
* {revokeRole} functions. Each role has an associated admin role, and only
* accounts that have a role's admin role can call {grantRole} and {revokeRole}.
*
* By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
* that only accounts with this role will be able to grant or revoke other
* roles. More complex role relationships can be created by using
* {_setRoleAdmin}.
*
* WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
* grant and revoke this role. Extra precautions should be taken to secure
* accounts that have been granted it.
*/
abstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable, IAccessControlUpgradeable, ERC165Upgradeable {
function __AccessControl_init() internal onlyInitializing {
__Context_init_unchained();
__ERC165_init_unchained();
__AccessControl_init_unchained();
}
function __AccessControl_init_unchained() internal onlyInitializing {
}
struct RoleData {
mapping(address => bool) members;
bytes32 adminRole;
}
mapping(bytes32 => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
/**
* @dev Modifier that checks that an account has a specific role. Reverts
* with a standardized message including the required role.
*
* The format of the revert reason is given by the following regular expression:
*
* /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
*
* _Available since v4.1._
*/
modifier onlyRole(bytes32 role) {
_checkRole(role, _msgSender());
_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControlUpgradeable).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) public view override returns (bool) {
return _roles[role].members[account];
}
/**
* @dev Revert with a standard message if `account` is missing `role`.
*
* The format of the revert reason is given by the following regular expression:
*
* /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
*/
function _checkRole(bytes32 role, address account) internal view {
if (!hasRole(role, account)) {
revert(
string(
abi.encodePacked(
"AccessControl: account ",
StringsUpgradeable.toHexString(uint160(account), 20),
" is missing role ",
StringsUpgradeable.toHexString(uint256(role), 32)
)
)
);
}
}
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) public view override returns (bytes32) {
return _roles[role].adminRole;
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been revoked `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*/
function renounceRole(bytes32 role, address account) public virtual override {
require(account == _msgSender(), "AccessControl: can only renounce roles for self");
_revokeRole(role, account);
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event. Note that unlike {grantRole}, this function doesn't perform any
* checks on the calling account.
*
* [WARNING]
* ====
* This function should only be called from the constructor when setting
* up the initial roles for the system.
*
* Using this function in any other way is effectively circumventing the admin
* system imposed by {AccessControl}.
* ====
*
* NOTE: This function is deprecated in favor of {_grantRole}.
*/
function _setupRole(bytes32 role, address account) internal virtual {
_grantRole(role, account);
}
/**
* @dev Sets `adminRole` as ``role``'s admin role.
*
* Emits a {RoleAdminChanged} event.
*/
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
bytes32 previousAdminRole = getRoleAdmin(role);
_roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
/**
* @dev Grants `role` to `account`.
*
* Internal function without access restriction.
*/
function _grantRole(bytes32 role, address account) internal virtual {
if (!hasRole(role, account)) {
_roles[role].members[account] = true;
emit RoleGranted(role, account, _msgSender());
}
}
/**
* @dev Revokes `role` from `account`.
*
* Internal function without access restriction.
*/
function _revokeRole(bytes32 role, address account) internal virtual {
if (hasRole(role, account)) {
_roles[role].members[account] = false;
emit RoleRevoked(role, account, _msgSender());
}
}
uint256[49] private __gap;
}
// File @openzeppelin/contracts-upgradeable/utils/structs/[email protected]
// OpenZeppelin Contracts v4.4.1 (utils/structs/EnumerableSet.sol)
/**
* @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 EnumerableSetUpgradeable {
// 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;
}
}
// File @openzeppelin/contracts-upgradeable/access/[email protected]
// OpenZeppelin Contracts v4.4.1 (access/AccessControlEnumerable.sol)
/**
* @dev Extension of {AccessControl} that allows enumerating the members of each role.
*/
abstract contract AccessControlEnumerableUpgradeable is Initializable, IAccessControlEnumerableUpgradeable, AccessControlUpgradeable {
function __AccessControlEnumerable_init() internal onlyInitializing {
__Context_init_unchained();
__ERC165_init_unchained();
__AccessControl_init_unchained();
__AccessControlEnumerable_init_unchained();
}
function __AccessControlEnumerable_init_unchained() internal onlyInitializing {
}
using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;
mapping(bytes32 => EnumerableSetUpgradeable.AddressSet) private _roleMembers;
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControlEnumerableUpgradeable).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev Returns one of the accounts that have `role`. `index` must be a
* value between 0 and {getRoleMemberCount}, non-inclusive.
*
* Role bearers are not sorted in any particular way, and their ordering may
* change at any point.
*
* WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure
* you perform all queries on the same block. See the following
* https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]
* for more information.
*/
function getRoleMember(bytes32 role, uint256 index) public view override returns (address) {
return _roleMembers[role].at(index);
}
/**
* @dev Returns the number of accounts that have `role`. Can be used
* together with {getRoleMember} to enumerate all bearers of a role.
*/
function getRoleMemberCount(bytes32 role) public view override returns (uint256) {
return _roleMembers[role].length();
}
/**
* @dev Overload {_grantRole} to track enumerable memberships
*/
function _grantRole(bytes32 role, address account) internal virtual override {
super._grantRole(role, account);
_roleMembers[role].add(account);
}
/**
* @dev Overload {_revokeRole} to track enumerable memberships
*/
function _revokeRole(bytes32 role, address account) internal virtual override {
super._revokeRole(role, account);
_roleMembers[role].remove(account);
}
uint256[49] private __gap;
}
// File contracts/interfaces/ICoreBorrow.sol
/// @title ICoreBorrow
/// @author Angle Core Team
/// @notice Interface for the `CoreBorrow` contract
/// @dev This interface only contains functions of the `CoreBorrow` contract which are called by other contracts
/// of this module
interface ICoreBorrow {
/// @notice Checks if an address corresponds to a treasury of a stablecoin with a flash loan
/// module initialized on it
/// @param treasury Address to check
/// @return Whether the address has the `FLASHLOANER_TREASURY_ROLE` or not
function isFlashLoanerTreasury(address treasury) external view returns (bool);
/// @notice Checks whether an address is governor of the Angle Protocol or not
/// @param admin Address to check
/// @return Whether the address has the `GOVERNOR_ROLE` or not
function isGovernor(address admin) external view returns (bool);
/// @notice Checks whether an address is governor or a guardian of the Angle Protocol or not
/// @param admin Address to check
/// @return Whether the address has the `GUARDIAN_ROLE` or not
/// @dev Governance should make sure when adding a governor to also give this governor the guardian
/// role by calling the `addGovernor` function
function isGovernorOrGuardian(address admin) external view returns (bool);
}
// File @openzeppelin/contracts-upgradeable/token/ERC20/[email protected]
// OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol)
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20Upgradeable {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}
// File contracts/interfaces/IAgToken.sol
/// @title IAgToken
/// @author Angle Core Team
/// @notice Interface for the stablecoins `AgToken` contracts
/// @dev This interface only contains functions of the `AgToken` contract which are called by other contracts
/// of this module or of the first module of the Angle Protocol
interface IAgToken is IERC20Upgradeable {
// ======================= Minter Role Only Functions ===========================
/// @notice Lets the `StableMaster` contract or another whitelisted contract mint agTokens
/// @param account Address to mint to
/// @param amount Amount to mint
/// @dev The contracts allowed to issue agTokens are the `StableMaster` contract, `VaultManager` contracts
/// associated to this stablecoin as well as the flash loan module (if activated) and potentially contracts
/// whitelisted by governance
function mint(address account, uint256 amount) external;
/// @notice Burns `amount` tokens from a `burner` address after being asked to by `sender`
/// @param amount Amount of tokens to burn
/// @param burner Address to burn from
/// @param sender Address which requested the burn from `burner`
/// @dev This method is to be called by a contract with the minter right after being requested
/// to do so by a `sender` address willing to burn tokens from another `burner` address
/// @dev The method checks the allowance between the `sender` and the `burner`
function burnFrom(
uint256 amount,
address burner,
address sender
) external;
/// @notice Burns `amount` tokens from a `burner` address
/// @param amount Amount of tokens to burn
/// @param burner Address to burn from
/// @dev This method is to be called by a contract with a minter right on the AgToken after being
/// requested to do so by an address willing to burn tokens from its address
function burnSelf(uint256 amount, address burner) external;
// ========================= Treasury Only Functions ===========================
/// @notice Adds a minter in the contract
/// @param minter Minter address to add
/// @dev Zero address checks are performed directly in the `Treasury` contract
function addMinter(address minter) external;
/// @notice Removes a minter from the contract
/// @param minter Minter address to remove
/// @dev This function can also be called by a minter wishing to revoke itself
function removeMinter(address minter) external;
/// @notice Sets a new treasury contract
/// @param _treasury New treasury address
function setTreasury(address _treasury) external;
// ========================= External functions ================================
/// @notice Checks whether an address has the right to mint agTokens
/// @param minter Address for which the minting right should be checked
/// @return Whether the address has the right to mint agTokens or not
function isMinter(address minter) external view returns (bool);
}
// File contracts/interfaces/IFlashAngle.sol
/// @title IFlashAngle
/// @author Angle Core Team
/// @notice Interface for the `FlashAngle` contract
/// @dev This interface only contains functions of the contract which are called by other contracts
/// of this module
interface IFlashAngle {
/// @notice Reference to the `CoreBorrow` contract managing the FlashLoan module
function core() external view returns (ICoreBorrow);
/// @notice Sends the fees taken from flash loans to the treasury contract associated to the stablecoin
/// @param stablecoin Stablecoin from which profits should be sent
/// @return balance Amount of profits sent
/// @dev This function can only be called by the treasury contract
function accrueInterestToTreasury(IAgToken stablecoin) external returns (uint256 balance);
/// @notice Adds support for a stablecoin
/// @param _treasury Treasury associated to the stablecoin to add support for
/// @dev This function can only be called by the `CoreBorrow` contract
function addStablecoinSupport(address _treasury) external;
/// @notice Removes support for a stablecoin
/// @param _treasury Treasury associated to the stablecoin to remove support for
/// @dev This function can only be called by the `CoreBorrow` contract
function removeStablecoinSupport(address _treasury) external;
/// @notice Sets a new core contract
/// @param _core Core contract address to set
/// @dev This function can only be called by the `CoreBorrow` contract
function setCore(address _core) external;
}
// File contracts/interfaces/ITreasury.sol
/// @title ITreasury
/// @author Angle Core Team
/// @notice Interface for the `Treasury` contract
/// @dev This interface only contains functions of the `Treasury` which are called by other contracts
/// of this module
interface ITreasury {
/// @notice Stablecoin handled by this `treasury` contract
function stablecoin() external view returns (IAgToken);
/// @notice Checks whether a given address has the governor role
/// @param admin Address to check
/// @return Whether the address has the governor role
/// @dev Access control is only kept in the `CoreBorrow` contract
function isGovernor(address admin) external view returns (bool);
/// @notice Checks whether a given address has the guardian or the governor role
/// @param admin Address to check
/// @return Whether the address has the guardian or the governor role
/// @dev Access control is only kept in the `CoreBorrow` contract which means that this function
/// queries the `CoreBorrow` contract
function isGovernorOrGuardian(address admin) external view returns (bool);
/// @notice Checks whether a given address has well been initialized in this contract
/// as a `VaultManager``
/// @param _vaultManager Address to check
/// @return Whether the address has been initialized or not
function isVaultManager(address _vaultManager) external view returns (bool);
/// @notice Sets a new flash loan module for this stablecoin
/// @param _flashLoanModule Reference to the new flash loan module
/// @dev This function removes the minting right to the old flash loan module and grants
/// it to the new module
function setFlashLoanModule(address _flashLoanModule) external;
}
// File contracts/coreBorrow/CoreBorrow.sol
/// @title CoreBorrow
/// @author Angle Core Team
/// @notice Core contract of the borrowing module. This contract handles the access control across all contracts
/// (it is read by all treasury contracts), and manages the `flashLoanModule`. It has no minting rights over the
/// stablecoin contracts
contract CoreBorrow is ICoreBorrow, Initializable, AccessControlEnumerableUpgradeable {
/// @notice Role for guardians
bytes32 public constant GUARDIAN_ROLE = keccak256("GUARDIAN_ROLE");
/// @notice Role for governors
bytes32 public constant GOVERNOR_ROLE = keccak256("GOVERNOR_ROLE");
/// @notice Role for treasury contract
bytes32 public constant FLASHLOANER_TREASURY_ROLE = keccak256("FLASHLOANER_TREASURY_ROLE");
// ============================= Reference =====================================
/// @notice Reference to the `flashLoanModule` with minting rights over the different stablecoins of the protocol
address public flashLoanModule;
// =============================== Events ======================================
event FlashLoanModuleUpdated(address indexed _flashloanModule);
event CoreUpdated(address indexed _core);
// =============================== Errors ======================================
error InvalidCore();
error IncompatibleGovernorAndGuardian();
error NotEnoughGovernorsLeft();
error ZeroAddress();
/// @notice Initializes the `CoreBorrow` contract and the access control of the borrowing module
/// @param governor Address of the governor of the Angle Protocol
/// @param guardian Guardian address of the protocol
function initialize(address governor, address guardian) public initializer {
if (governor == address(0) || guardian == address(0)) revert ZeroAddress();
if (governor == guardian) revert IncompatibleGovernorAndGuardian();
_setupRole(GOVERNOR_ROLE, governor);
_setupRole(GUARDIAN_ROLE, guardian);
_setupRole(GUARDIAN_ROLE, governor);
_setRoleAdmin(GUARDIAN_ROLE, GOVERNOR_ROLE);
_setRoleAdmin(GOVERNOR_ROLE, GOVERNOR_ROLE);
_setRoleAdmin(FLASHLOANER_TREASURY_ROLE, GOVERNOR_ROLE);
}
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() initializer {}
// =========================== View Functions ==================================
/// @inheritdoc ICoreBorrow
function isFlashLoanerTreasury(address treasury) external view returns (bool) {
return hasRole(FLASHLOANER_TREASURY_ROLE, treasury);
}
/// @inheritdoc ICoreBorrow
function isGovernor(address admin) external view returns (bool) {
return hasRole(GOVERNOR_ROLE, admin);
}
/// @inheritdoc ICoreBorrow
function isGovernorOrGuardian(address admin) external view returns (bool) {
return hasRole(GUARDIAN_ROLE, admin);
}
// =========================== Governor Functions ==============================
/// @notice Grants the `FLASHLOANER_TREASURY_ROLE` to a `treasury` contract
/// @param treasury Contract to grant the role to
/// @dev This function can be used to allow flash loans on a stablecoin of the protocol
function addFlashLoanerTreasuryRole(address treasury) external {
grantRole(FLASHLOANER_TREASURY_ROLE, treasury);
address _flashLoanModule = flashLoanModule;
if (_flashLoanModule != address(0)) {
// This call will revert if `treasury` is the zero address or if it is not linked
// to this `CoreBorrow` contract
ITreasury(treasury).setFlashLoanModule(_flashLoanModule);
IFlashAngle(_flashLoanModule).addStablecoinSupport(treasury);
}
}
/// @notice Adds a governor in the protocol
/// @param governor Address to grant the role to
/// @dev It is necessary to call this function to grant a governor role to make sure
/// all governors also have the guardian role
function addGovernor(address governor) external {
grantRole(GOVERNOR_ROLE, governor);
grantRole(GUARDIAN_ROLE, governor);
}
/// @notice Revokes the flash loan ability for a stablecoin
/// @param treasury Treasury address associated with the stablecoin for which flash loans
/// should no longer be available
function removeFlashLoanerTreasuryRole(address treasury) external {
revokeRole(FLASHLOANER_TREASURY_ROLE, treasury);
ITreasury(treasury).setFlashLoanModule(address(0));
address _flashLoanModule = flashLoanModule;
if (_flashLoanModule != address(0)) {
IFlashAngle(flashLoanModule).removeStablecoinSupport(treasury);
}
}
/// @notice Revokes a governor from the protocol
/// @param governor Address to remove the role to
/// @dev It is necessary to call this function to remove a governor role to make sure
/// the address also loses its guardian role
function removeGovernor(address governor) external {
if (getRoleMemberCount(GOVERNOR_ROLE) <= 1) revert NotEnoughGovernorsLeft();
revokeRole(GUARDIAN_ROLE, governor);
revokeRole(GOVERNOR_ROLE, governor);
}
/// @notice Changes the `flashLoanModule` of the protocol
/// @param _flashLoanModule Address of the new flash loan module
function setFlashLoanModule(address _flashLoanModule) external onlyRole(GOVERNOR_ROLE) {
if (_flashLoanModule != address(0)) {
if (address(IFlashAngle(_flashLoanModule).core()) != address(this)) revert InvalidCore();
}
uint256 count = getRoleMemberCount(FLASHLOANER_TREASURY_ROLE);
for (uint256 i = 0; i < count; i++) {
ITreasury(getRoleMember(FLASHLOANER_TREASURY_ROLE, i)).setFlashLoanModule(_flashLoanModule);
}
flashLoanModule = _flashLoanModule;
emit FlashLoanModuleUpdated(_flashLoanModule);
}
/// @notice Changes the core contract of the protocol
/// @param _core New core contract
/// @dev This function verifies that all governors of the current core contract are also governors
/// of the new core contract. It also notifies the `flashLoanModule` of the change.
/// @dev Governance wishing to change the core contract should also make sure to call `setCore`
/// in the different treasury contracts
function setCore(ICoreBorrow _core) external onlyRole(GOVERNOR_ROLE) {
uint256 count = getRoleMemberCount(GOVERNOR_ROLE);
bool success;
for (uint256 i = 0; i < count; i++) {
success = _core.isGovernor(getRoleMember(GOVERNOR_ROLE, i));
if (!success) break;
}
if (!success) revert InvalidCore();
address _flashLoanModule = flashLoanModule;
if (_flashLoanModule != address(0)) IFlashAngle(_flashLoanModule).setCore(address(_core));
emit CoreUpdated(address(_core));
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"IncompatibleGovernorAndGuardian","type":"error"},{"inputs":[],"name":"InvalidCore","type":"error"},{"inputs":[],"name":"NotEnoughGovernorsLeft","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_core","type":"address"}],"name":"CoreUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_flashloanModule","type":"address"}],"name":"FlashLoanModuleUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FLASHLOANER_TREASURY_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GOVERNOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GUARDIAN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"treasury","type":"address"}],"name":"addFlashLoanerTreasuryRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"governor","type":"address"}],"name":"addGovernor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"flashLoanModule","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"governor","type":"address"},{"internalType":"address","name":"guardian","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"treasury","type":"address"}],"name":"isFlashLoanerTreasury","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"isGovernor","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"isGovernorOrGuardian","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"treasury","type":"address"}],"name":"removeFlashLoanerTreasuryRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"governor","type":"address"}],"name":"removeGovernor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ICoreBorrow","name":"_core","type":"address"}],"name":"setCore","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_flashLoanModule","type":"address"}],"name":"setFlashLoanModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]Contract Creation Code
60806040523480156200001157600080fd5b50600054610100900460ff166200002f5760005460ff161562000039565b62000039620000de565b620000a15760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b600054610100900460ff16158015620000c4576000805461ffff19166101011790555b8015620000d7576000805461ff00191690555b5062000102565b6000620000f630620000fc60201b6200123a1760201c565b15905090565b3b151590565b611e2180620001126000396000f3fe608060405234801561001057600080fd5b506004361061018d5760003560e01c806380009630116100e3578063ccc574901161008c578063eecdac8811610066578063eecdac88146103c5578063ef5f12c5146103d8578063f02dd8a2146103ff57600080fd5b8063ccc5749014610378578063d547741f1461039f578063e43581b8146103b257600080fd5b8063959d5a01116100bd578063959d5a011461033d578063a217fddf1461035d578063ca15c8731461036557600080fd5b806380009630146102ac5780639010d07c146102bf57806391d14854146102f757600080fd5b806336568abe11610145578063485cc9551161011f578063485cc95514610273578063521d4de9146102865780635704cc461461029957600080fd5b806336568abe1461023a5780633c4a25d01461024d578063449ba8811461026057600080fd5b8063248a9ca311610176578063248a9ca3146101cf57806324ea54f4146102005780632f2ff15d1461022757600080fd5b806301ffc9a71461019257806321c29f92146101ba575b600080fd5b6101a56101a03660046119fa565b610412565b60405190151581526020015b60405180910390f35b6101cd6101c8366004611a5e565b61046e565b005b6101f26101dd366004611a7b565b60009081526065602052604090206001015490565b6040519081526020016101b1565b6101f27f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a504181565b6101cd610235366004611a94565b6106f2565b6101cd610248366004611a94565b61071d565b6101cd61025b366004611a5e565b6107d5565b6101cd61026e366004611a5e565b61082c565b6101cd610281366004611ac4565b610980565b6101a5610294366004611a5e565b610cad565b6101cd6102a7366004611a5e565b610cfa565b6101cd6102ba366004611a5e565b610e18565b6102d26102cd366004611af2565b61108e565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101b1565b6101a5610305366004611a94565b600091825260656020908152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b60c9546102d29073ffffffffffffffffffffffffffffffffffffffff1681565b6101f2600081565b6101f2610373366004611a7b565b6110ad565b6101f27f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5581565b6101cd6103ad366004611a94565b6110c4565b6101a56103c0366004611a5e565b6110ea565b6101cd6103d3366004611a5e565b611137565b6101f27f0ae0130c6b34f32239dfe5e419a3fbd7546b44e99783257f2d93526d5a936d4681565b6101a561040d366004611a5e565b6111ed565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f5a05180f000000000000000000000000000000000000000000000000000000001480610468575061046882611240565b92915050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5561049981336112d7565b73ffffffffffffffffffffffffffffffffffffffff821615610588573073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1663f2f4eb266040518163ffffffff1660e01b8152600401602060405180830381865afa158015610517573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061053b9190611b14565b73ffffffffffffffffffffffffffffffffffffffff1614610588576040517fc5c23c8d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006105b37f0ae0130c6b34f32239dfe5e419a3fbd7546b44e99783257f2d93526d5a936d466110ad565b905060005b81811015610680576105ea7f0ae0130c6b34f32239dfe5e419a3fbd7546b44e99783257f2d93526d5a936d468261108e565b6040517f21c29f9200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015291909116906321c29f9290602401600060405180830381600087803b15801561065557600080fd5b505af1158015610669573d6000803e3d6000fd5b50505050808061067890611b60565b9150506105b8565b5060c980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff85169081179091556040517ffcbb758b478e66ede9f90baed6bef1a7563f6da23642cf16a274e18b66cd8baa90600090a2505050565b60008281526065602052604090206001015461070e81336112d7565b61071883836113a9565b505050565b73ffffffffffffffffffffffffffffffffffffffff811633146107c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c66000000000000000000000000000000000060648201526084015b60405180910390fd5b6107d182826113cb565b5050565b6107ff7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f55826106f2565b6108297f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a5041826106f2565b50565b6108567f0ae0130c6b34f32239dfe5e419a3fbd7546b44e99783257f2d93526d5a936d46826110c4565b6040517f21c29f920000000000000000000000000000000000000000000000000000000081526000600482015273ffffffffffffffffffffffffffffffffffffffff8216906321c29f9290602401600060405180830381600087803b1580156108be57600080fd5b505af11580156108d2573d6000803e3d6000fd5b505060c95473ffffffffffffffffffffffffffffffffffffffff1691505080156107d15760c9546040517f543bd64700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301529091169063543bd647906024015b600060405180830381600087803b15801561096457600080fd5b505af1158015610978573d6000803e3d6000fd5b505050505050565b600054610100900460ff1661099b5760005460ff161561099f565b303b155b610a2b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016107be565b600054610100900460ff16158015610a6a57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000166101011790555b73ffffffffffffffffffffffffffffffffffffffff83161580610aa1575073ffffffffffffffffffffffffffffffffffffffff8216155b15610ad8576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610b3e576040517f5468228700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b687f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f55846113ed565b610b927f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a5041836113ed565b610bbc7f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a5041846113ed565b610c067f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a50417f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f556113f7565b610c307f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f55806113f7565b610c7a7f0ae0130c6b34f32239dfe5e419a3fbd7546b44e99783257f2d93526d5a936d467f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f556113f7565b801561071857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081527f069cdf9dfc2229276970916c1858214fdc1e7fbd582c817d68d15a269f9e469c602052604081205460ff16610468565b610d247f0ae0130c6b34f32239dfe5e419a3fbd7546b44e99783257f2d93526d5a936d46826106f2565b60c95473ffffffffffffffffffffffffffffffffffffffff1680156107d1576040517f21c29f9200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301528316906321c29f9290602401600060405180830381600087803b158015610dac57600080fd5b505af1158015610dc0573d6000803e3d6000fd5b50506040517f442320c100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528416925063442320c1915060240161094a565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f55610e4381336112d7565b6000610e6e7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f556110ad565b90506000805b82811015610f6d578473ffffffffffffffffffffffffffffffffffffffff1663e43581b8610ec27f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f558461108e565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401602060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190611b99565b915081610f5b57610f6d565b80610f6581611b60565b915050610e74565b5080610fa5576040517fc5c23c8d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60c95473ffffffffffffffffffffffffffffffffffffffff168015611046576040517f8000963000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8681166004830152821690638000963090602401600060405180830381600087803b15801561102d57600080fd5b505af1158015611041573d6000803e3d6000fd5b505050505b60405173ffffffffffffffffffffffffffffffffffffffff8616907f0c9c0f914e121785e2cd2269d6698bc11f59a50b85ef9aa1197fb4ddb96c4e5690600090a25050505050565b60008281526097602052604081206110a69083611442565b9392505050565b60008181526097602052604081206104689061144e565b6000828152606560205260409020600101546110e081336112d7565b61071883836113cb565b73ffffffffffffffffffffffffffffffffffffffff811660009081527f5b3690852b26f7232357f142d58d00e1cca98c361fba25f077120aefa687fb54602052604081205460ff16610468565b60016111627f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f556110ad565b11611199576040517fb76a773a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111c37f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a5041826110c4565b6108297f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f55826110c4565b73ffffffffffffffffffffffffffffffffffffffff811660009081527f8c1a1c2e4dcafefdcb61fcbadefc1a4e194ef54665c481e5a1f8b483cf279726602052604081205460ff16610468565b3b151590565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061046857507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831614610468565b600082815260656020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166107d15761132f8173ffffffffffffffffffffffffffffffffffffffff166014611458565b61133a836020611458565b60405160200161134b929190611beb565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f08c379a00000000000000000000000000000000000000000000000000000000082526107be91600401611c6c565b6113b3828261169b565b6000828152609760205260409020610718908261178f565b6113d582826117b1565b6000828152609760205260409020610718908261186c565b6107d182826113a9565b600082815260656020526040808220600101805490849055905190918391839186917fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff9190a4505050565b60006110a6838361188e565b6000610468825490565b60606000611467836002611cbd565b611472906002611cfa565b67ffffffffffffffff81111561148a5761148a611d12565b6040519080825280601f01601f1916602001820160405280156114b4576020820181803683370190505b5090507f3000000000000000000000000000000000000000000000000000000000000000816000815181106114eb576114eb611d41565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f78000000000000000000000000000000000000000000000000000000000000008160018151811061154e5761154e611d41565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600061158a846002611cbd565b611595906001611cfa565b90505b6001811115611632577f303132333435363738396162636465660000000000000000000000000000000085600f16601081106115d6576115d6611d41565b1a60f81b8282815181106115ec576115ec611d41565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c9361162b81611d70565b9050611598565b5083156110a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016107be565b600082815260656020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166107d157600082815260656020908152604080832073ffffffffffffffffffffffffffffffffffffffff85168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556117313390565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b60006110a68373ffffffffffffffffffffffffffffffffffffffff84166118b8565b600082815260656020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16156107d157600082815260656020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60006110a68373ffffffffffffffffffffffffffffffffffffffff8416611907565b60008260000182815481106118a5576118a5611d41565b9060005260206000200154905092915050565b60008181526001830160205260408120546118ff57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610468565b506000610468565b600081815260018301602052604081205480156119f057600061192b600183611da5565b855490915060009061193f90600190611da5565b90508181146119a457600086600001828154811061195f5761195f611d41565b906000526020600020015490508087600001848154811061198257611982611d41565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806119b5576119b5611dbc565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610468565b6000915050610468565b600060208284031215611a0c57600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146110a657600080fd5b73ffffffffffffffffffffffffffffffffffffffff8116811461082957600080fd5b600060208284031215611a7057600080fd5b81356110a681611a3c565b600060208284031215611a8d57600080fd5b5035919050565b60008060408385031215611aa757600080fd5b823591506020830135611ab981611a3c565b809150509250929050565b60008060408385031215611ad757600080fd5b8235611ae281611a3c565b91506020830135611ab981611a3c565b60008060408385031215611b0557600080fd5b50508035926020909101359150565b600060208284031215611b2657600080fd5b81516110a681611a3c565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415611b9257611b92611b31565b5060010190565b600060208284031215611bab57600080fd5b815180151581146110a657600080fd5b60005b83811015611bd6578181015183820152602001611bbe565b83811115611be5576000848401525b50505050565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351611c23816017850160208801611bbb565b7f206973206d697373696e6720726f6c65200000000000000000000000000000006017918401918201528351611c60816028840160208801611bbb565b01602801949350505050565b6020815260008251806020840152611c8b816040850160208701611bbb565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615611cf557611cf5611b31565b500290565b60008219821115611d0d57611d0d611b31565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600081611d7f57611d7f611b31565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b600082821015611db757611db7611b31565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea2646970667358221220faf50b4e1cfe5514a26d332a59bba2961ddbd993de4a7ef16cefbe90fcfe29fe64736f6c634300080c0033
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061018d5760003560e01c806380009630116100e3578063ccc574901161008c578063eecdac8811610066578063eecdac88146103c5578063ef5f12c5146103d8578063f02dd8a2146103ff57600080fd5b8063ccc5749014610378578063d547741f1461039f578063e43581b8146103b257600080fd5b8063959d5a01116100bd578063959d5a011461033d578063a217fddf1461035d578063ca15c8731461036557600080fd5b806380009630146102ac5780639010d07c146102bf57806391d14854146102f757600080fd5b806336568abe11610145578063485cc9551161011f578063485cc95514610273578063521d4de9146102865780635704cc461461029957600080fd5b806336568abe1461023a5780633c4a25d01461024d578063449ba8811461026057600080fd5b8063248a9ca311610176578063248a9ca3146101cf57806324ea54f4146102005780632f2ff15d1461022757600080fd5b806301ffc9a71461019257806321c29f92146101ba575b600080fd5b6101a56101a03660046119fa565b610412565b60405190151581526020015b60405180910390f35b6101cd6101c8366004611a5e565b61046e565b005b6101f26101dd366004611a7b565b60009081526065602052604090206001015490565b6040519081526020016101b1565b6101f27f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a504181565b6101cd610235366004611a94565b6106f2565b6101cd610248366004611a94565b61071d565b6101cd61025b366004611a5e565b6107d5565b6101cd61026e366004611a5e565b61082c565b6101cd610281366004611ac4565b610980565b6101a5610294366004611a5e565b610cad565b6101cd6102a7366004611a5e565b610cfa565b6101cd6102ba366004611a5e565b610e18565b6102d26102cd366004611af2565b61108e565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101b1565b6101a5610305366004611a94565b600091825260656020908152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b60c9546102d29073ffffffffffffffffffffffffffffffffffffffff1681565b6101f2600081565b6101f2610373366004611a7b565b6110ad565b6101f27f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5581565b6101cd6103ad366004611a94565b6110c4565b6101a56103c0366004611a5e565b6110ea565b6101cd6103d3366004611a5e565b611137565b6101f27f0ae0130c6b34f32239dfe5e419a3fbd7546b44e99783257f2d93526d5a936d4681565b6101a561040d366004611a5e565b6111ed565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f5a05180f000000000000000000000000000000000000000000000000000000001480610468575061046882611240565b92915050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5561049981336112d7565b73ffffffffffffffffffffffffffffffffffffffff821615610588573073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1663f2f4eb266040518163ffffffff1660e01b8152600401602060405180830381865afa158015610517573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061053b9190611b14565b73ffffffffffffffffffffffffffffffffffffffff1614610588576040517fc5c23c8d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006105b37f0ae0130c6b34f32239dfe5e419a3fbd7546b44e99783257f2d93526d5a936d466110ad565b905060005b81811015610680576105ea7f0ae0130c6b34f32239dfe5e419a3fbd7546b44e99783257f2d93526d5a936d468261108e565b6040517f21c29f9200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015291909116906321c29f9290602401600060405180830381600087803b15801561065557600080fd5b505af1158015610669573d6000803e3d6000fd5b50505050808061067890611b60565b9150506105b8565b5060c980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff85169081179091556040517ffcbb758b478e66ede9f90baed6bef1a7563f6da23642cf16a274e18b66cd8baa90600090a2505050565b60008281526065602052604090206001015461070e81336112d7565b61071883836113a9565b505050565b73ffffffffffffffffffffffffffffffffffffffff811633146107c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c66000000000000000000000000000000000060648201526084015b60405180910390fd5b6107d182826113cb565b5050565b6107ff7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f55826106f2565b6108297f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a5041826106f2565b50565b6108567f0ae0130c6b34f32239dfe5e419a3fbd7546b44e99783257f2d93526d5a936d46826110c4565b6040517f21c29f920000000000000000000000000000000000000000000000000000000081526000600482015273ffffffffffffffffffffffffffffffffffffffff8216906321c29f9290602401600060405180830381600087803b1580156108be57600080fd5b505af11580156108d2573d6000803e3d6000fd5b505060c95473ffffffffffffffffffffffffffffffffffffffff1691505080156107d15760c9546040517f543bd64700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301529091169063543bd647906024015b600060405180830381600087803b15801561096457600080fd5b505af1158015610978573d6000803e3d6000fd5b505050505050565b600054610100900460ff1661099b5760005460ff161561099f565b303b155b610a2b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016107be565b600054610100900460ff16158015610a6a57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000166101011790555b73ffffffffffffffffffffffffffffffffffffffff83161580610aa1575073ffffffffffffffffffffffffffffffffffffffff8216155b15610ad8576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610b3e576040517f5468228700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b687f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f55846113ed565b610b927f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a5041836113ed565b610bbc7f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a5041846113ed565b610c067f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a50417f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f556113f7565b610c307f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f55806113f7565b610c7a7f0ae0130c6b34f32239dfe5e419a3fbd7546b44e99783257f2d93526d5a936d467f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f556113f7565b801561071857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081527f069cdf9dfc2229276970916c1858214fdc1e7fbd582c817d68d15a269f9e469c602052604081205460ff16610468565b610d247f0ae0130c6b34f32239dfe5e419a3fbd7546b44e99783257f2d93526d5a936d46826106f2565b60c95473ffffffffffffffffffffffffffffffffffffffff1680156107d1576040517f21c29f9200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301528316906321c29f9290602401600060405180830381600087803b158015610dac57600080fd5b505af1158015610dc0573d6000803e3d6000fd5b50506040517f442320c100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528416925063442320c1915060240161094a565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f55610e4381336112d7565b6000610e6e7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f556110ad565b90506000805b82811015610f6d578473ffffffffffffffffffffffffffffffffffffffff1663e43581b8610ec27f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f558461108e565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401602060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190611b99565b915081610f5b57610f6d565b80610f6581611b60565b915050610e74565b5080610fa5576040517fc5c23c8d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60c95473ffffffffffffffffffffffffffffffffffffffff168015611046576040517f8000963000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8681166004830152821690638000963090602401600060405180830381600087803b15801561102d57600080fd5b505af1158015611041573d6000803e3d6000fd5b505050505b60405173ffffffffffffffffffffffffffffffffffffffff8616907f0c9c0f914e121785e2cd2269d6698bc11f59a50b85ef9aa1197fb4ddb96c4e5690600090a25050505050565b60008281526097602052604081206110a69083611442565b9392505050565b60008181526097602052604081206104689061144e565b6000828152606560205260409020600101546110e081336112d7565b61071883836113cb565b73ffffffffffffffffffffffffffffffffffffffff811660009081527f5b3690852b26f7232357f142d58d00e1cca98c361fba25f077120aefa687fb54602052604081205460ff16610468565b60016111627f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f556110ad565b11611199576040517fb76a773a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111c37f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a5041826110c4565b6108297f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f55826110c4565b73ffffffffffffffffffffffffffffffffffffffff811660009081527f8c1a1c2e4dcafefdcb61fcbadefc1a4e194ef54665c481e5a1f8b483cf279726602052604081205460ff16610468565b3b151590565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061046857507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831614610468565b600082815260656020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166107d15761132f8173ffffffffffffffffffffffffffffffffffffffff166014611458565b61133a836020611458565b60405160200161134b929190611beb565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f08c379a00000000000000000000000000000000000000000000000000000000082526107be91600401611c6c565b6113b3828261169b565b6000828152609760205260409020610718908261178f565b6113d582826117b1565b6000828152609760205260409020610718908261186c565b6107d182826113a9565b600082815260656020526040808220600101805490849055905190918391839186917fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff9190a4505050565b60006110a6838361188e565b6000610468825490565b60606000611467836002611cbd565b611472906002611cfa565b67ffffffffffffffff81111561148a5761148a611d12565b6040519080825280601f01601f1916602001820160405280156114b4576020820181803683370190505b5090507f3000000000000000000000000000000000000000000000000000000000000000816000815181106114eb576114eb611d41565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f78000000000000000000000000000000000000000000000000000000000000008160018151811061154e5761154e611d41565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600061158a846002611cbd565b611595906001611cfa565b90505b6001811115611632577f303132333435363738396162636465660000000000000000000000000000000085600f16601081106115d6576115d6611d41565b1a60f81b8282815181106115ec576115ec611d41565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c9361162b81611d70565b9050611598565b5083156110a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016107be565b600082815260656020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166107d157600082815260656020908152604080832073ffffffffffffffffffffffffffffffffffffffff85168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556117313390565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b60006110a68373ffffffffffffffffffffffffffffffffffffffff84166118b8565b600082815260656020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16156107d157600082815260656020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60006110a68373ffffffffffffffffffffffffffffffffffffffff8416611907565b60008260000182815481106118a5576118a5611d41565b9060005260206000200154905092915050565b60008181526001830160205260408120546118ff57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610468565b506000610468565b600081815260018301602052604081205480156119f057600061192b600183611da5565b855490915060009061193f90600190611da5565b90508181146119a457600086600001828154811061195f5761195f611d41565b906000526020600020015490508087600001848154811061198257611982611d41565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806119b5576119b5611dbc565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610468565b6000915050610468565b600060208284031215611a0c57600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146110a657600080fd5b73ffffffffffffffffffffffffffffffffffffffff8116811461082957600080fd5b600060208284031215611a7057600080fd5b81356110a681611a3c565b600060208284031215611a8d57600080fd5b5035919050565b60008060408385031215611aa757600080fd5b823591506020830135611ab981611a3c565b809150509250929050565b60008060408385031215611ad757600080fd5b8235611ae281611a3c565b91506020830135611ab981611a3c565b60008060408385031215611b0557600080fd5b50508035926020909101359150565b600060208284031215611b2657600080fd5b81516110a681611a3c565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415611b9257611b92611b31565b5060010190565b600060208284031215611bab57600080fd5b815180151581146110a657600080fd5b60005b83811015611bd6578181015183820152602001611bbe565b83811115611be5576000848401525b50505050565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351611c23816017850160208801611bbb565b7f206973206d697373696e6720726f6c65200000000000000000000000000000006017918401918201528351611c60816028840160208801611bbb565b01602801949350505050565b6020815260008251806020840152611c8b816040850160208701611bbb565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615611cf557611cf5611b31565b500290565b60008219821115611d0d57611d0d611b31565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600081611d7f57611d7f611b31565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b600082821015611db757611db7611b31565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea2646970667358221220faf50b4e1cfe5514a26d332a59bba2961ddbd993de4a7ef16cefbe90fcfe29fe64736f6c634300080c0033
Deployed Bytecode Sourcemap
54748:6698:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;41712:225;;;;;;:::i;:::-;;:::i;:::-;;;516:14:1;;509:22;491:41;;479:2;464:18;41712:225:0;;;;;;;;59837:593;;;;;;:::i;:::-;;:::i;:::-;;24554:123;;;;;;:::i;:::-;24620:7;24647:12;;;:6;:12;;;;;:22;;;;24554:123;;;;1285:25:1;;;1273:2;1258:18;24554:123:0;1139:177:1;54877:66:0;;54917:26;54877:66;;24939:147;;;;;;:::i;:::-;;:::i;25987:218::-;;;;;;:::i;:::-;;:::i;58467:146::-;;;;;;:::i;:::-;;:::i;58820:381::-;;;;;;:::i;:::-;;:::i;56110:557::-;;;;;;:::i;:::-;;:::i;57235:129::-;;;;;;:::i;:::-;;:::i;57689:526::-;;;;;;:::i;:::-;;:::i;60876:567::-;;;;;;:::i;:::-;;:::i;42536:145::-;;;;;;:::i;:::-;;:::i;:::-;;;2735:42:1;2723:55;;;2705:74;;2693:2;2678:18;42536:145:0;2559:226:1;23417:139:0;;;;;;:::i;:::-;23495:4;23519:12;;;:6;:12;;;;;;;;:29;;;;;;;;;;;;;;;;23417:139;55409:30;;;;;;;;;22497:49;;22542:4;22497:49;;42855:134;;;;;;:::i;:::-;;:::i;54986:66::-;;55026:26;54986:66;;25331:149;;;;;;:::i;:::-;;:::i;57075:119::-;;;;;;:::i;:::-;;:::i;59459:237::-;;;;;;:::i;:::-;;:::i;55103:90::-;;55155:38;55103:90;;56886:148;;;;;;:::i;:::-;;:::i;41712:225::-;41797:4;41821:68;;;41836:53;41821:68;;:108;;;41893:36;41917:11;41893:23;:36::i;:::-;41814:115;41712:225;-1:-1:-1;;41712:225:0:o;59837:593::-;55026:26;22988:30;55026:26;15687:10;22988;:30::i;:::-;59939::::1;::::0;::::1;::::0;59935:151:::1;;60047:4;59990:62;;60010:16;59998:34;;;:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;59990:62;;;59986:88;;60061:13;;;;;;;;;;;;;;59986:88;60096:13;60112:45;55155:38;60112:18;:45::i;:::-;60096:61;;60173:9;60168:154;60192:5;60188:1;:9;60168:154;;;60229:43;55155:38;60270:1;60229:13;:43::i;:::-;60219:91;::::0;;;;:73:::1;2723:55:1::0;;;60219:91:0::1;::::0;::::1;2705:74:1::0;60219:73:0;;;::::1;::::0;::::1;::::0;2678:18:1;;60219:91:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;60199:3;;;;;:::i;:::-;;;;60168:154;;;-1:-1:-1::0;60332:15:0::1;:34:::0;;;::::1;;::::0;::::1;::::0;;::::1;::::0;;;60382:40:::1;::::0;::::1;::::0;-1:-1:-1;;60382:40:0::1;59924:506;59837:593:::0;;:::o;24939:147::-;24620:7;24647:12;;;:6;:12;;;;;:22;;;22988:30;22999:4;15687:10;22988;:30::i;:::-;25053:25:::1;25064:4;25070:7;25053:10;:25::i;:::-;24939:147:::0;;;:::o;25987:218::-;26083:23;;;15687:10;26083:23;26075:83;;;;;;;3839:2:1;26075:83:0;;;3821:21:1;3878:2;3858:18;;;3851:30;3917:34;3897:18;;;3890:62;3988:17;3968:18;;;3961:45;4023:19;;26075:83:0;;;;;;;;;26171:26;26183:4;26189:7;26171:11;:26::i;:::-;25987:218;;:::o;58467:146::-;58526:34;55026:26;58551:8;58526:9;:34::i;:::-;58571;54917:26;58596:8;58571:9;:34::i;:::-;58467:146;:::o;58820:381::-;58897:47;55155:38;58935:8;58897:10;:47::i;:::-;58955:50;;;;;59002:1;58955:50;;;2705:74:1;58955:38:0;;;;;;2678:18:1;;58955:50:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;59043:15:0;;;;;-1:-1:-1;;59073:30:0;;59069:125;;59132:15;;59120:62;;;;;59132:15;2723:55:1;;;59120:62:0;;;2705:74:1;59132:15:0;;;;59120:52;;2678:18:1;;59120:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;58886:315;58820:381;:::o;56110:557::-;13893:13;;;;;;;:48;;13929:12;;;;13928:13;13893:48;;;14696:4;5485:20;5533:8;13909:16;13885:107;;;;;;;4255:2:1;13885:107:0;;;4237:21:1;4294:2;4274:18;;;4267:30;4333:34;4313:18;;;4306:62;4404:16;4384:18;;;4377:44;4438:19;;13885:107:0;4053:410:1;13885:107:0;14005:19;14028:13;;;;;;14027:14;14052:101;;;;14087:13;:20;;14122:19;;;;;;14052:101;56200:22:::1;::::0;::::1;::::0;;:48:::1;;-1:-1:-1::0;56226:22:0::1;::::0;::::1;::::0;56200:48:::1;56196:74;;;56257:13;;;;;;;;;;;;;;56196:74;56297:8;56285:20;;:8;:20;;;56281:66;;;56314:33;;;;;;;;;;;;;;56281:66;56358:35;55026:26;56384:8;56358:10;:35::i;:::-;56404;54917:26;56430:8;56404:10;:35::i;:::-;56450;54917:26;56476:8;56450:10;:35::i;:::-;56496:43;54917:26;55026;56496:13;:43::i;:::-;56550;55026:26;::::0;56550:13:::1;:43::i;:::-;56604:55;55155:38;55026:26;56604:13;:55::i;:::-;14183:14:::0;14179:68;;;14230:5;14214:21;;;;;;13600:654;56110:557;;:::o;57235:129::-;23519:29;;;57303:4;23519:29;;;:12;;:29;:12;:29;;;;;57327;23417:139;57689:526;57763:46;55155:38;57800:8;57763:9;:46::i;:::-;57847:15;;;;57877:30;;57873:335;;58065:56;;;;;:38;2723:55:1;;;58065:56:0;;;2705:74:1;58065:38:0;;;;;2678:18:1;;58065:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;58136:60:0;;;;;:50;2723:55:1;;;58136:60:0;;;2705:74:1;58136:50:0;;;-1:-1:-1;58136:50:0;;-1:-1:-1;2678:18:1;;58136:60:0;2559:226:1;60876:567:0;55026:26;22988:30;55026:26;15687:10;22988;:30::i;:::-;60956:13:::1;60972:33;55026:26;60972:18;:33::i;:::-;60956:49:::0;-1:-1:-1;61016:12:0::1;::::0;61039:156:::1;61063:5;61059:1;:9;61039:156;;;61100:5;:16;;;61117:31;55026:26;61146:1;61117:13;:31::i;:::-;61100:49;::::0;;::::1;::::0;;;;;;2735:42:1;2723:55;;;61100:49:0::1;::::0;::::1;2705:74:1::0;2678:18;;61100:49:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;61090:59;;61169:7;61164:19;;61178:5;;61164:19;61070:3:::0;::::1;::::0;::::1;:::i;:::-;;;;61039:156;;;;61210:7;61205:34;;61226:13;;;;;;;;;;;;;;61205:34;61277:15;::::0;::::1;;61307:30:::0;;61303:89:::1;;61339:53;::::0;;;;:37:::1;2723:55:1::0;;;61339:53:0::1;::::0;::::1;2705:74:1::0;61339:37:0;::::1;::::0;::::1;::::0;2678:18:1;;61339:53:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;61303:89;61408:27;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;;::::1;60945:498;;;60876:567:::0;;:::o;42536:145::-;42618:7;42645:18;;;:12;:18;;;;;:28;;42667:5;42645:21;:28::i;:::-;42638:35;42536:145;-1:-1:-1;;;42536:145:0:o;42855:134::-;42927:7;42954:18;;;:12;:18;;;;;:27;;:25;:27::i;25331:149::-;24620:7;24647:12;;;:6;:12;;;;;:22;;;22988:30;22999:4;15687:10;22988;:30::i;:::-;25446:26:::1;25458:4;25464:7;25446:11;:26::i;57075:119::-:0;23519:29;;;57133:4;23519:29;;;:12;;:29;:12;:29;;;;;57157;23417:139;59459:237;59562:1;59525:33;55026:26;59525:18;:33::i;:::-;:38;59521:75;;59572:24;;;;;;;;;;;;;;59521:75;59607:35;54917:26;59633:8;59607:10;:35::i;:::-;59653;55026:26;59679:8;59653:10;:35::i;56886:148::-;23519:29;;;56958:4;23519:29;;;:12;;:29;:12;:29;;;;;56982:44;23417:139;5162:387;5485:20;5533:8;;;5162:387::o;23110:215::-;23195:4;23219:58;;;23234:43;23219:58;;:98;;-1:-1:-1;20124:36:0;20109:51;;;;23281:36;20000:168;23846:519;23495:4;23519:12;;;:6;:12;;;;;;;;:29;;;;;;;;;;;;;23922:436;;24115:52;24154:7;24115:52;;24164:2;24115:30;:52::i;:::-;24240:49;24279:4;24286:2;24240:30;:49::i;:::-;24020:292;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;23966:380;;;;;;;;:::i;43082:169::-;43170:31;43187:4;43193:7;43170:16;:31::i;:::-;43212:18;;;;:12;:18;;;;;:31;;43235:7;43212:22;:31::i;43345:174::-;43434:32;43452:4;43458:7;43434:17;:32::i;:::-;43477:18;;;;:12;:18;;;;;:34;;43503:7;43477:25;:34::i;26864:112::-;26943:25;26954:4;26960:7;26943:10;:25::i;27108:251::-;27192:25;24647:12;;;:6;:12;;;;;;:22;;;;27249:34;;;;27299:52;;24647:22;;27249:34;;24647:22;;:12;;27299:52;;27192:25;27299:52;27181:178;27108:251;;:::o;37317:158::-;37391:7;37442:22;37446:3;37458:5;37442:3;:22::i;36846:117::-;36909:7;36936:19;36944:3;32330:18;;32247:109;17532:451;17607:13;17633:19;17665:10;17669:6;17665:1;:10;:::i;:::-;:14;;17678:1;17665:14;:::i;:::-;17655:25;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;17655:25:0;;17633:47;;17691:15;:6;17698:1;17691:9;;;;;;;;:::i;:::-;;;;:15;;;;;;;;;;;17717;:6;17724:1;17717:9;;;;;;;;:::i;:::-;;;;:15;;;;;;;;;;-1:-1:-1;17748:9:0;17760:10;17764:6;17760:1;:10;:::i;:::-;:14;;17773:1;17760:14;:::i;:::-;17748:26;;17743:135;17780:1;17776;:5;17743:135;;;17815:12;17828:5;17836:3;17828:11;17815:25;;;;;;;:::i;:::-;;;;17803:6;17810:1;17803:9;;;;;;;;:::i;:::-;;;;:37;;;;;;;;;;-1:-1:-1;17865:1:0;17855:11;;;;;17783:3;;;:::i;:::-;;;17743:135;;;-1:-1:-1;17896:10:0;;17888:55;;;;;;;7398:2:1;17888:55:0;;;7380:21:1;;;7417:18;;;7410:30;7476:34;7456:18;;;7449:62;7528:18;;17888:55:0;7196:356:1;27488:238:0;23495:4;23519:12;;;:6;:12;;;;;;;;:29;;;;;;;;;;;;;27567:152;;27611:12;;;;:6;:12;;;;;;;;:29;;;;;;;;;;:36;;;;27643:4;27611:36;;;27694:12;15687:10;;15607:98;27694:12;27667:40;;27685:7;27667:40;;27679:4;27667:40;;;;;;;;;;27488:238;;:::o;36021:152::-;36091:4;36115:50;36120:3;36140:23;;;36115:4;:50::i;27858:239::-;23495:4;23519:12;;;:6;:12;;;;;;;;:29;;;;;;;;;;;;;27938:152;;;28013:5;27981:12;;;:6;:12;;;;;;;;:29;;;;;;;;;;;:37;;;;;;28038:40;15687:10;;27981:12;;28038:40;;28013:5;28038:40;27858:239;;:::o;36349:158::-;36422:4;36446:53;36454:3;36474:23;;;36446:7;:53::i;32710:120::-;32777:7;32804:3;:11;;32816:5;32804:18;;;;;;;;:::i;:::-;;;;;;;;;32797:25;;32710:120;;;;:::o;29936:414::-;29999:4;32129:19;;;:12;;;:19;;;;;;30016:327;;-1:-1:-1;30059:23:0;;;;;;;;:11;:23;;;;;;;;;;;;;30242:18;;30220:19;;;:12;;;:19;;;;;;:40;;;;30275:11;;30016:327;-1:-1:-1;30326:5:0;30319:12;;30526:1420;30592:4;30731:19;;;:12;;;:19;;;;;;30767:15;;30763:1176;;31142:21;31166:14;31179:1;31166:10;:14;:::i;:::-;31215:18;;31142:38;;-1:-1:-1;31195:17:0;;31215:22;;31236:1;;31215:22;:::i;:::-;31195:42;;31271:13;31258:9;:26;31254:405;;31305:17;31325:3;:11;;31337:9;31325:22;;;;;;;;:::i;:::-;;;;;;;;;31305:42;;31479:9;31450:3;:11;;31462:13;31450:26;;;;;;;;:::i;:::-;;;;;;;;;;;;:38;;;;31564:23;;;:12;;;:23;;;;;:36;;;31254:405;31740:17;;:3;;:17;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;31835:3;:12;;:19;31848:5;31835:19;;;;;;;;;;;31828:26;;;31878:4;31871:11;;;;;;;30763:1176;31922:5;31915:12;;;;;14:332:1;72:6;125:2;113:9;104:7;100:23;96:32;93:52;;;141:1;138;131:12;93:52;180:9;167:23;230:66;223:5;219:78;212:5;209:89;199:117;;312:1;309;302:12;543:154;629:42;622:5;618:54;611:5;608:65;598:93;;687:1;684;677:12;702:247;761:6;814:2;802:9;793:7;789:23;785:32;782:52;;;830:1;827;820:12;782:52;869:9;856:23;888:31;913:5;888:31;:::i;954:180::-;1013:6;1066:2;1054:9;1045:7;1041:23;1037:32;1034:52;;;1082:1;1079;1072:12;1034:52;-1:-1:-1;1105:23:1;;954:180;-1:-1:-1;954:180:1:o;1321:315::-;1389:6;1397;1450:2;1438:9;1429:7;1425:23;1421:32;1418:52;;;1466:1;1463;1456:12;1418:52;1502:9;1489:23;1479:33;;1562:2;1551:9;1547:18;1534:32;1575:31;1600:5;1575:31;:::i;:::-;1625:5;1615:15;;;1321:315;;;;;:::o;1641:388::-;1709:6;1717;1770:2;1758:9;1749:7;1745:23;1741:32;1738:52;;;1786:1;1783;1776:12;1738:52;1825:9;1812:23;1844:31;1869:5;1844:31;:::i;:::-;1894:5;-1:-1:-1;1951:2:1;1936:18;;1923:32;1964:33;1923:32;1964:33;:::i;2306:248::-;2374:6;2382;2435:2;2423:9;2414:7;2410:23;2406:32;2403:52;;;2451:1;2448;2441:12;2403:52;-1:-1:-1;;2474:23:1;;;2544:2;2529:18;;;2516:32;;-1:-1:-1;2306:248:1:o;2972:271::-;3062:6;3115:2;3103:9;3094:7;3090:23;3086:32;3083:52;;;3131:1;3128;3121:12;3083:52;3163:9;3157:16;3182:31;3207:5;3182:31;:::i;3248:184::-;3300:77;3297:1;3290:88;3397:4;3394:1;3387:15;3421:4;3418:1;3411:15;3437:195;3476:3;3507:66;3500:5;3497:77;3494:103;;;3577:18;;:::i;:::-;-1:-1:-1;3624:1:1;3613:13;;3437:195::o;4468:277::-;4535:6;4588:2;4576:9;4567:7;4563:23;4559:32;4556:52;;;4604:1;4601;4594:12;4556:52;4636:9;4630:16;4689:5;4682:13;4675:21;4668:5;4665:32;4655:60;;4711:1;4708;4701:12;4750:258;4822:1;4832:113;4846:6;4843:1;4840:13;4832:113;;;4922:11;;;4916:18;4903:11;;;4896:39;4868:2;4861:10;4832:113;;;4963:6;4960:1;4957:13;4954:48;;;4998:1;4989:6;4984:3;4980:16;4973:27;4954:48;;4750:258;;;:::o;5013:786::-;5424:25;5419:3;5412:38;5394:3;5479:6;5473:13;5495:62;5550:6;5545:2;5540:3;5536:12;5529:4;5521:6;5517:17;5495:62;:::i;:::-;5621:19;5616:2;5576:16;;;5608:11;;;5601:40;5666:13;;5688:63;5666:13;5737:2;5729:11;;5722:4;5710:17;;5688:63;:::i;:::-;5771:17;5790:2;5767:26;;5013:786;-1:-1:-1;;;;5013:786:1:o;5804:442::-;5953:2;5942:9;5935:21;5916:4;5985:6;5979:13;6028:6;6023:2;6012:9;6008:18;6001:34;6044:66;6103:6;6098:2;6087:9;6083:18;6078:2;6070:6;6066:15;6044:66;:::i;:::-;6162:2;6150:15;6167:66;6146:88;6131:104;;;;6237:2;6127:113;;5804:442;-1:-1:-1;;5804:442:1:o;6251:228::-;6291:7;6417:1;6349:66;6345:74;6342:1;6339:81;6334:1;6327:9;6320:17;6316:105;6313:131;;;6424:18;;:::i;:::-;-1:-1:-1;6464:9:1;;6251:228::o;6484:128::-;6524:3;6555:1;6551:6;6548:1;6545:13;6542:39;;;6561:18;;:::i;:::-;-1:-1:-1;6597:9:1;;6484:128::o;6617:184::-;6669:77;6666:1;6659:88;6766:4;6763:1;6756:15;6790:4;6787:1;6780:15;6806:184;6858:77;6855:1;6848:88;6955:4;6952:1;6945:15;6979:4;6976:1;6969:15;6995:196;7034:3;7062:5;7052:39;;7071:18;;:::i;:::-;-1:-1:-1;7118:66:1;7107:78;;6995:196::o;7557:125::-;7597:4;7625:1;7622;7619:8;7616:34;;;7630:18;;:::i;:::-;-1:-1:-1;7667:9:1;;7557:125::o;7687:184::-;7739:77;7736:1;7729:88;7836:4;7833:1;7826:15;7860:4;7857:1;7850:15
Swarm Source
ipfs://faf50b4e1cfe5514a26d332a59bba2961ddbd993de4a7ef16cefbe90fcfe29fe
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.