// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)pragmasolidity ^0.8.1;/**
* @dev Collection of functions related to the address type
*/libraryAddress{
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/functionisContract(address account) internalviewreturns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0// for contracts in construction, since the code is only stored at the end// of the constructor execution.return account.code.length>0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/functionsendValue(addresspayable 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._
*/functionfunctionCall(address target, bytesmemory data) internalreturns (bytesmemory) {
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._
*/functionfunctionCall(address target,
bytesmemory data,
stringmemory errorMessage
) internalreturns (bytesmemory) {
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._
*/functionfunctionCallWithValue(address target,
bytesmemory data,
uint256 value
) internalreturns (bytesmemory) {
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._
*/functionfunctionCallWithValue(address target,
bytesmemory data,
uint256 value,
stringmemory errorMessage
) internalreturns (bytesmemory) {
require(address(this).balance>= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytesmemory 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._
*/functionfunctionStaticCall(address target, bytesmemory data) internalviewreturns (bytesmemory) {
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._
*/functionfunctionStaticCall(address target,
bytesmemory data,
stringmemory errorMessage
) internalviewreturns (bytesmemory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytesmemory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/functionfunctionDelegateCall(address target, bytesmemory data) internalreturns (bytesmemory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/functionfunctionDelegateCall(address target,
bytesmemory data,
stringmemory errorMessage
) internalreturns (bytesmemory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytesmemory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/functionverifyCallResult(bool success,
bytesmemory returndata,
stringmemory errorMessage
) internalpurereturns (bytesmemory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if presentif (returndata.length>0) {
// The easiest way to bubble the revert reason is using memory via assembly/// @solidity memory-safe-assemblyassembly {
let returndata_size :=mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
Contract Source Code
File 2 of 17: Context.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)pragmasolidity ^0.8.0;/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/abstractcontractContext{
function_msgSender() internalviewvirtualreturns (address) {
returnmsg.sender;
}
function_msgData() internalviewvirtualreturns (bytescalldata) {
returnmsg.data;
}
}
Contract Source Code
File 3 of 17: Diamond.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.15;import"../access/ownable/OwnableStorage.sol";
import"../access/ownable/IERC173.sol";
import"../introspection/ERC165.sol";
import"../metatx/ERC2771Context.sol";
import"../diamond/IDiamondCut.sol";
import"../diamond/IDiamondLoupe.sol";
import"@openzeppelin/contracts/utils/Multicall.sol";
import"./DiamondStorage.sol";
contractDiamondisMulticall{
usingERC165StorageforERC165Storage.Layout;
usingOwnableStorageforOwnableStorage.Layout;
structInitialization {
address initContract;
bytes initData;
}
structCoreFacets {
address diamondCutFacet;
address diamondLoupeFacet;
address erc165Facet;
address erc173Facet;
}
constructor(address owner,
CoreFacets memory _coreFacets,
IDiamondCut.FacetCut[] memory _facets,
Initialization[] memory _initializations
) {
ERC165Storage.Layout storage erc165 = ERC165Storage.layout();
// register DiamondCutbytes4[] memory selectorsDiamondCut =newbytes4[](1);
selectorsDiamondCut[0] = IDiamondCut.diamondCut.selector;
erc165.setSupportedInterface(type(IDiamondCut).interfaceId, true);
// register DiamondLoupebytes4[] memory selectorsDiamondLoupe =newbytes4[](4);
selectorsDiamondLoupe[0] = IDiamondLoupe.facets.selector;
selectorsDiamondLoupe[1] = IDiamondLoupe.facetFunctionSelectors.selector;
selectorsDiamondLoupe[2] = IDiamondLoupe.facetAddresses.selector;
selectorsDiamondLoupe[3] = IDiamondLoupe.facetAddress.selector;
erc165.setSupportedInterface(type(IDiamondLoupe).interfaceId, true);
// register ERC165 (supportsInterface)bytes4[] memory selectorsERC165 =newbytes4[](1);
selectorsERC165[0] = IERC165.supportsInterface.selector;
erc165.setSupportedInterface(type(IERC165).interfaceId, true);
// register ERC173 (Ownable)bytes4[] memory selectorsERC173 =newbytes4[](2);
selectorsERC173[0] = IERC173.owner.selector;
selectorsERC173[1] = IERC173.transferOwnership.selector;
erc165.setSupportedInterface(type(IERC173).interfaceId, true);
// execute the first ever diamond cut,// we are calling the addFunctions directly to save ~ %50 gas
DiamondStorage.addFunctions(_coreFacets.diamondCutFacet, selectorsDiamondCut);
DiamondStorage.addFunctions(_coreFacets.diamondLoupeFacet, selectorsDiamondLoupe);
DiamondStorage.addFunctions(_coreFacets.erc165Facet, selectorsERC165);
DiamondStorage.addFunctions(_coreFacets.erc173Facet, selectorsERC173);
// set owner
OwnableStorage.layout().setOwner(owner);
// initializationfor (uint256 i =0; i < _facets.length; i++) {
DiamondStorage.addFunctions(_facets[i].facetAddress, _facets[i].functionSelectors);
}
for (uint256 i =0; i < _initializations.length; i++) {
DiamondStorage.initializeDiamondCut(_initializations[i].initContract, _initializations[i].initData);
}
}
// Find facet for function that is called and execute the// function if a facet is found and return any value.fallback() externalpayable{
DiamondStorage.Layout storage l;
bytes32 position = DiamondStorage.DIAMOND_STORAGE_POSITION;
// get diamond storageassembly {
l.slot:= position
}
// get facet from function selectoraddress facet = l.selectorToFacetAndPosition[msg.sig].facetAddress;
require(facet !=address(0), "BAD_FUNC");
// Execute external function from facet using delegatecall and return any value.assembly {
// copy function selector and any argumentscalldatacopy(0, 0, calldatasize())
// execute function call using the facetlet result :=delegatecall(gas(), facet, 0, calldatasize(), 0, 0)
// get any return valuereturndatacopy(0, 0, returndatasize())
// return any return value or error back to the callerswitch result
case0 {
revert(0, returndatasize())
}
default {
return(0, returndatasize())
}
}
}
receive() externalpayable{}
}
Contract Source Code
File 4 of 17: DiamondStorage.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.15;/******************************************************************************\
* Author: Nick Mudge <nick@perfectabstractions.com> (https://twitter.com/mudgen)
* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535
/******************************************************************************/import"../diamond/IDiamondCut.sol";
// Remember to add the loupe functions from DiamondLoupeFacet to the diamond.// The loupe functions are required by the EIP2535 Diamonds standarderrorErrDiamondFacetAlreadyExists(address facet, bytes4 selector);
errorErrDiamondFacetSameFunction(address facet, bytes4 selector);
libraryDiamondStorage{
bytes32constant DIAMOND_STORAGE_POSITION =keccak256("diamond.standard.diamond.storage");
structFacetAddressAndPosition {
address facetAddress;
uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array
}
structFacetFunctionSelectors {
bytes4[] functionSelectors;
uint256 facetAddressPosition; // position of facetAddress in facetAddresses array
}
structLayout {
// maps function selector to the facet address and// the position of the selector in the facetFunctionSelectors.selectors arraymapping(bytes4=> FacetAddressAndPosition) selectorToFacetAndPosition;
// maps facet addresses to function selectorsmapping(address=> FacetFunctionSelectors) facetFunctionSelectors;
// facet addressesaddress[] facetAddresses;
}
functionlayout() internalpurereturns (Layout storage l) {
bytes32 position = DIAMOND_STORAGE_POSITION;
assembly {
l.slot:= position
}
}
eventDiamondCut(IDiamondCut.FacetCut[] _diamondCut, address _init, bytes _calldata);
// Internal function version of diamondCutfunctiondiamondCut(
IDiamondCut.FacetCut[] memory _diamondCut,
address _init,
bytesmemory _calldata
) internal{
for (uint256 facetIndex; facetIndex < _diamondCut.length; facetIndex++) {
IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;
if (action == IDiamondCut.FacetCutAction.Add) {
addFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);
} elseif (action == IDiamondCut.FacetCutAction.Replace) {
replaceFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);
} elseif (action == IDiamondCut.FacetCutAction.Remove) {
removeFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);
} else {
revert("LibDiamondCut: Incorrect FacetCutAction");
}
}
emit DiamondCut(_diamondCut, _init, _calldata);
initializeDiamondCut(_init, _calldata);
}
functionaddFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal{
// require(// _functionSelectors.length > 0,// "LibDiamondCut: No selectors in facet to cut"// );
Layout storage l = layout();
// require(// _facetAddress != address(0),// "LibDiamondCut: Add facet can't be address(0)"// );uint96 selectorPosition =uint96(l.facetFunctionSelectors[_facetAddress].functionSelectors.length);
// add new facet address if it does not existif (selectorPosition ==0) {
addFacet(l, _facetAddress);
}
for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {
bytes4 selector = _functionSelectors[selectorIndex];
address oldFacetAddress = l.selectorToFacetAndPosition[selector].facetAddress;
if (oldFacetAddress !=address(0)) {
revert ErrDiamondFacetAlreadyExists(oldFacetAddress, selector);
}
addFunction(l, selector, selectorPosition, _facetAddress);
selectorPosition++;
}
}
functionreplaceFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal{
// require(// _functionSelectors.length > 0,// "LibDiamondCut: No selectors in facet to cut"// );
Layout storage l = layout();
// require(// _facetAddress != address(0),// "LibDiamondCut: Add facet can't be address(0)"// );uint96 selectorPosition =uint96(l.facetFunctionSelectors[_facetAddress].functionSelectors.length);
// add new facet address if it does not existif (selectorPosition ==0) {
addFacet(l, _facetAddress);
}
for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {
bytes4 selector = _functionSelectors[selectorIndex];
address oldFacetAddress = l.selectorToFacetAndPosition[selector].facetAddress;
if (oldFacetAddress == _facetAddress) {
revert ErrDiamondFacetSameFunction(oldFacetAddress, selector);
}
removeFunction(l, oldFacetAddress, selector);
addFunction(l, selector, selectorPosition, _facetAddress);
selectorPosition++;
}
}
functionremoveFunctions(address, bytes4[] memory _functionSelectors) internal{
// require(// _functionSelectors.length > 0,// "LibDiamondCut: No selectors in facet to cut"// );
Layout storage l = layout();
// if function does not exist then do nothing and return// require(// _facetAddress == address(0),// "LibDiamondCut: Remove facet address must be address(0)"// );for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {
bytes4 selector = _functionSelectors[selectorIndex];
address oldFacetAddress = l.selectorToFacetAndPosition[selector].facetAddress;
removeFunction(l, oldFacetAddress, selector);
}
}
functionaddFacet(Layout storage l, address _facetAddress) internal{
enforceHasContractCode(_facetAddress, "LibDiamondCut: New facet has no code");
l.facetFunctionSelectors[_facetAddress].facetAddressPosition = l.facetAddresses.length;
l.facetAddresses.push(_facetAddress);
}
functionaddFunction(
Layout storage l,
bytes4 _selector,
uint96 _selectorPosition,
address _facetAddress
) internal{
l.selectorToFacetAndPosition[_selector].functionSelectorPosition = _selectorPosition;
l.facetFunctionSelectors[_facetAddress].functionSelectors.push(_selector);
l.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;
}
functionremoveFunction(
Layout storage l,
address _facetAddress,
bytes4 _selector
) internal{
// require(// _facetAddress != address(0),// "LibDiamondCut: Can't remove function that doesn't exist"// );// an immutable function is a function defined directly in a diamond// require(// _facetAddress != address(this),// "LibDiamondCut: Can't remove immutable function"// );// replace selector with last selector, then delete last selectoruint256 selectorPosition = l.selectorToFacetAndPosition[_selector].functionSelectorPosition;
uint256 lastSelectorPosition = l.facetFunctionSelectors[_facetAddress].functionSelectors.length-1;
// if not the same then replace _selector with lastSelectorif (selectorPosition != lastSelectorPosition) {
bytes4 lastSelector = l.facetFunctionSelectors[_facetAddress].functionSelectors[lastSelectorPosition];
l.facetFunctionSelectors[_facetAddress].functionSelectors[selectorPosition] = lastSelector;
l.selectorToFacetAndPosition[lastSelector].functionSelectorPosition =uint96(selectorPosition);
}
// delete the last selector
l.facetFunctionSelectors[_facetAddress].functionSelectors.pop();
delete l.selectorToFacetAndPosition[_selector];
// if no more selectors for facet address then delete the facet addressif (lastSelectorPosition ==0) {
// replace facet address with last facet address and delete last facet addressuint256 lastFacetAddressPosition = l.facetAddresses.length-1;
uint256 facetAddressPosition = l.facetFunctionSelectors[_facetAddress].facetAddressPosition;
if (facetAddressPosition != lastFacetAddressPosition) {
address lastFacetAddress = l.facetAddresses[lastFacetAddressPosition];
l.facetAddresses[facetAddressPosition] = lastFacetAddress;
l.facetFunctionSelectors[lastFacetAddress].facetAddressPosition = facetAddressPosition;
}
l.facetAddresses.pop();
delete l.facetFunctionSelectors[_facetAddress].facetAddressPosition;
}
}
functioninitializeDiamondCut(address _init, bytesmemory _calldata) internal{
if (_init ==address(0)) {
require(_calldata.length==0, "LibDiamondCut: _init is address(0) but_calldata is not empty");
} else {
require(_calldata.length>0, "LibDiamondCut: _calldata is empty but _init is not address(0)");
if (_init !=address(this)) {
enforceHasContractCode(_init, "LibDiamondCut: _init address has no code");
}
(bool success, bytesmemoryerror) = _init.delegatecall(_calldata);
if (!success) {
if (error.length>0) {
// bubble up the errorrevert(string(error));
} else {
revert("LibDiamondCut: _init function reverted");
}
}
}
}
functionenforceHasContractCode(address _contract, stringmemory _errorMessage) internalview{
uint256 contractSize;
assembly {
contractSize :=extcodesize(_contract)
}
require(contractSize >0, _errorMessage);
}
}
Contract Source Code
File 5 of 17: ERC165.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.15;import"@openzeppelin/contracts/utils/introspection/IERC165.sol";
import"./ERC165Storage.sol";
/**
* @title ERC165
* @notice Standard EIP-165 facet which would be already included as a core facet in Flair's Diamond contract.
*
* @custom:type eip-2535-facet
* @custom:category Introspection
* @custom:provides-interfaces IERC165
*/contractERC165isIERC165{
usingERC165StorageforERC165Storage.Layout;
/**
* @inheritdoc IERC165
*/functionsupportsInterface(bytes4 interfaceId) publicviewreturns (bool) {
return ERC165Storage.layout().isSupportedInterface(interfaceId);
}
}
// SPDX-License-Identifier: MITpragmasolidity ^0.8.15;/******************************************************************************\
* Author: Nick Mudge <nick@perfectabstractions.com> (https://twitter.com/mudgen)
* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535
/******************************************************************************/interfaceIDiamondCut{
enumFacetCutAction {
Add,
Replace,
Remove
}
// Add=0, Replace=1, Remove=2structFacetCut {
address facetAddress;
FacetCutAction action;
bytes4[] functionSelectors;
}
/// @notice Add/replace/remove any number of functions and optionally execute/// a function with delegatecall/// @param _diamondCut Contains the facet addresses and function selectors/// @param _init The address of the contract or facet to execute _calldata/// @param _calldata A function call, including function selector and arguments/// _calldata is executed with delegatecall on _initfunctiondiamondCut(
FacetCut[] calldata _diamondCut,
address _init,
bytescalldata _calldata
) external;
eventDiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);
}
Contract Source Code
File 11 of 17: IDiamondLoupe.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.15;/******************************************************************************\
* Author: Nick Mudge <nick@perfectabstractions.com> (https://twitter.com/mudgen)
* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535
/******************************************************************************/// A loupe is a small magnifying glass used to look at diamonds.// These functions look at diamondsinterfaceIDiamondLoupe{
/// These functions are expected to be called frequently/// by tools.structFacet {
address facetAddress;
bytes4[] functionSelectors;
}
/// @notice Gets all facet addresses and their four byte function selectors./// @return facets_ Facetfunctionfacets() externalviewreturns (Facet[] memory facets_);
/// @notice Gets all the function selectors supported by a specific facet./// @param _facet The facet address./// @return facetFunctionSelectors_functionfacetFunctionSelectors(address _facet) externalviewreturns (bytes4[] memory facetFunctionSelectors_);
/// @notice Get all the facet addresses used by a diamond./// @return facetAddresses_functionfacetAddresses() externalviewreturns (address[] memory facetAddresses_);
/// @notice Gets the facet that supports the given selector./// @dev If facet is not found return address(0)./// @param _functionSelector The function selector./// @return facetAddress_ The facet address.functionfacetAddress(bytes4 _functionSelector) externalviewreturns (address facetAddress_);
}
Contract Source Code
File 12 of 17: IERC165.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)pragmasolidity ^0.8.0;/**
* @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}.
*/interfaceIERC165{
/**
* @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.
*/functionsupportsInterface(bytes4 interfaceId) externalviewreturns (bool);
}
Contract Source Code
File 13 of 17: IERC173.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.15;import"./IERC173Events.sol";
/**
* @title Contract ownership standard interface
* @dev see https://eips.ethereum.org/EIPS/eip-173
*/interfaceIERC173isIERC173Events{
/**
* @notice get the ERC173 contract owner
* @return conrtact owner
*/functionowner() externalviewreturns (address);
/**
* @notice transfer contract ownership to new account
* @param account address of new owner
*/functiontransferOwnership(address account) external;
}
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.5.0) (utils/Multicall.sol)pragmasolidity ^0.8.0;import"./Address.sol";
/**
* @dev Provides a function to batch together multiple calls in a single external call.
*
* _Available since v4.1._
*/abstractcontractMulticall{
/**
* @dev Receives and executes a batch of function calls on this contract.
*/functionmulticall(bytes[] calldata data) externalvirtualreturns (bytes[] memory results) {
results =newbytes[](data.length);
for (uint256 i =0; i < data.length; i++) {
results[i] = Address.functionDelegateCall(address(this), data[i]);
}
return results;
}
}