Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
OFTWrapperDiamond
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.19;
import { SolidStateDiamond } from '@solidstate/contracts/proxy/diamond/SolidStateDiamond.sol';
import { IPausable } from '@solidstate/contracts/security/pausable/IPausable.sol';
import { Pausable } from '@solidstate/contracts/security/pausable/Pausable.sol';
import { ReentrancyGuard } from '@solidstate/contracts/security/reentrancy_guard/ReentrancyGuard.sol';
import { ITokenBalance } from '../../interfaces/ITokenBalance.sol';
import { OFTWrapperStorage } from './OFTWrapperStorage.sol';
import '../../helpers/TransferHelper.sol' as TransferHelper;
import '../../Constants.sol' as Constants;
/**
* @title OFTWrapperDiamond
* @notice The OFT wrapper diamond contract
*/
contract OFTWrapperDiamond is SolidStateDiamond, Pausable, ReentrancyGuard {
/**
* @notice Emitted when the address of the collector is set
* @param collector The address of the collector
*/
event SetCollector(address indexed collector);
uint256 private constant SYSTEM_VERSION_ID_INTERNAL = uint256(keccak256('Initial'));
/**
* @notice Initializes the contract
* @param _collector The initial address of the collector
* @param _owner The address of the initial owner of the contract
*/
constructor(address _collector, address _owner) {
_initOFTWrapperDiamond();
_setCollector(_collector);
if (_owner != msg.sender && _owner != address(0)) {
_setOwner(_owner);
}
}
/**
* @notice Sets the address of the collector
* @param _collector The address of the collector
*/
function setCollector(address _collector) external onlyOwner {
_setCollector(_collector);
}
/**
* @notice Enter pause state
*/
function pause() external onlyOwner whenNotPaused {
_pause();
}
/**
* @notice Exit pause state
*/
function unpause() external onlyOwner whenPaused {
_unpause();
}
/**
* @notice Transfers ownership of the contract to a new account
* @dev Can only be called by the current owner
* @param _newOwner The address of the contract owner
*/
function forceTransferOwnership(address _newOwner) external onlyOwner {
_setOwner(_newOwner);
}
/**
* @notice Performs the token cleanup
* @dev Use the "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE" address for the native token
* @param _tokenAddress The address of the token
*/
function cleanup(address _tokenAddress) external onlyOwner {
if (_tokenAddress == Constants.NATIVE_TOKEN_ADDRESS) {
TransferHelper.safeTransferNative(msg.sender, address(this).balance);
} else {
TransferHelper.safeTransfer(
_tokenAddress,
msg.sender,
ITokenBalance(_tokenAddress).balanceOf(address(this))
);
}
}
/**
* @notice Performs the token cleanup using the provided amount
* @dev Use the "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE" address for the native token
* @param _tokenAddress The address of the token
* @param _tokenAmount The amount of the token
*/
function cleanupWithAmount(address _tokenAddress, uint256 _tokenAmount) external onlyOwner {
if (_tokenAddress == Constants.NATIVE_TOKEN_ADDRESS) {
TransferHelper.safeTransferNative(msg.sender, _tokenAmount);
} else {
TransferHelper.safeTransfer(_tokenAddress, msg.sender, _tokenAmount);
}
}
/**
* @notice Getter of the token balance of the current contract
* @dev Use the "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE" address for the native token
* @param _tokenAddress The address of the token
* @return The token balance of the current contract
*/
function tokenBalance(address _tokenAddress) external view returns (uint256) {
if (_tokenAddress == Constants.NATIVE_TOKEN_ADDRESS) {
return address(this).balance;
} else {
return ITokenBalance(_tokenAddress).balanceOf(address(this));
}
}
/**
* @notice Getter of the address of the collector
* @return The address of the collector
*/
function collector() external view returns (address) {
return OFTWrapperStorage.layout().collector;
}
/**
* @notice Getter of the system version identifier
* @return The system version identifier
*/
function SYSTEM_VERSION_ID() external pure returns (uint256) {
return SYSTEM_VERSION_ID_INTERNAL;
}
function _setCollector(address _collector) private {
OFTWrapperStorage.layout().collector = _collector;
emit SetCollector(_collector);
}
function _initOFTWrapperDiamond() private {
bytes4[] memory selectors = new bytes4[](10);
uint256 selectorIndex;
// register Pausable
selectors[selectorIndex++] = IPausable.paused.selector;
_setSupportsInterface(type(IPausable).interfaceId, true);
// register collector functions
selectors[selectorIndex++] = OFTWrapperDiamond.setCollector.selector;
selectors[selectorIndex++] = OFTWrapperDiamond.collector.selector;
// register service functions
selectors[selectorIndex++] = OFTWrapperDiamond.pause.selector;
selectors[selectorIndex++] = OFTWrapperDiamond.unpause.selector;
selectors[selectorIndex++] = OFTWrapperDiamond.forceTransferOwnership.selector;
selectors[selectorIndex++] = OFTWrapperDiamond.cleanup.selector;
selectors[selectorIndex++] = OFTWrapperDiamond.cleanupWithAmount.selector;
selectors[selectorIndex++] = OFTWrapperDiamond.tokenBalance.selector;
selectors[selectorIndex++] = OFTWrapperDiamond.SYSTEM_VERSION_ID.selector;
// diamond cut
FacetCut[] memory facetCuts = new FacetCut[](1);
facetCuts[0] = FacetCut({
target: address(this),
action: FacetCutAction.ADD,
selectors: selectors
});
_diamondCut(facetCuts, address(0), '');
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
import { IERC173 } from '../../interfaces/IERC173.sol';
import { IOwnableInternal } from './IOwnableInternal.sol';
interface IOwnable is IOwnableInternal, IERC173 {}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
import { IERC173Internal } from '../../interfaces/IERC173Internal.sol';
interface IOwnableInternal is IERC173Internal {
error Ownable__NotOwner();
error Ownable__NotTransitiveOwner();
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
import { IOwnable } from './IOwnable.sol';
import { ISafeOwnableInternal } from './ISafeOwnableInternal.sol';
interface ISafeOwnable is ISafeOwnableInternal, IOwnable {
/**
* @notice get the nominated owner who has permission to call acceptOwnership
*/
function nomineeOwner() external view returns (address);
/**
* @notice accept transfer of contract ownership
*/
function acceptOwnership() external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
import { IOwnableInternal } from './IOwnableInternal.sol';
interface ISafeOwnableInternal is IOwnableInternal {
error SafeOwnable__NotNomineeOwner();
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
import { IERC173 } from '../../interfaces/IERC173.sol';
import { IOwnable } from './IOwnable.sol';
import { OwnableInternal } from './OwnableInternal.sol';
/**
* @title Ownership access control based on ERC173
*/
abstract contract Ownable is IOwnable, OwnableInternal {
/**
* @inheritdoc IERC173
*/
function owner() public view virtual returns (address) {
return _owner();
}
/**
* @inheritdoc IERC173
*/
function transferOwnership(address account) public virtual onlyOwner {
_transferOwnership(account);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
import { IERC173 } from '../../interfaces/IERC173.sol';
import { AddressUtils } from '../../utils/AddressUtils.sol';
import { IOwnableInternal } from './IOwnableInternal.sol';
import { OwnableStorage } from './OwnableStorage.sol';
abstract contract OwnableInternal is IOwnableInternal {
using AddressUtils for address;
modifier onlyOwner() {
if (msg.sender != _owner()) revert Ownable__NotOwner();
_;
}
modifier onlyTransitiveOwner() {
if (msg.sender != _transitiveOwner())
revert Ownable__NotTransitiveOwner();
_;
}
function _owner() internal view virtual returns (address) {
return OwnableStorage.layout().owner;
}
function _transitiveOwner() internal view virtual returns (address owner) {
owner = _owner();
while (owner.isContract()) {
try IERC173(owner).owner() returns (address transitiveOwner) {
owner = transitiveOwner;
} catch {
break;
}
}
}
function _transferOwnership(address account) internal virtual {
_setOwner(account);
}
function _setOwner(address account) internal virtual {
OwnableStorage.Layout storage l = OwnableStorage.layout();
emit OwnershipTransferred(l.owner, account);
l.owner = account;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
library OwnableStorage {
struct Layout {
address owner;
}
bytes32 internal constant STORAGE_SLOT =
keccak256('solidstate.contracts.storage.Ownable');
function layout() internal pure returns (Layout storage l) {
bytes32 slot = STORAGE_SLOT;
assembly {
l.slot := slot
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
import { Ownable } from './Ownable.sol';
import { ISafeOwnable } from './ISafeOwnable.sol';
import { OwnableInternal } from './OwnableInternal.sol';
import { SafeOwnableInternal } from './SafeOwnableInternal.sol';
/**
* @title Ownership access control based on ERC173 with ownership transfer safety check
*/
abstract contract SafeOwnable is ISafeOwnable, Ownable, SafeOwnableInternal {
/**
* @inheritdoc ISafeOwnable
*/
function nomineeOwner() public view virtual returns (address) {
return _nomineeOwner();
}
/**
* @inheritdoc ISafeOwnable
*/
function acceptOwnership() public virtual onlyNomineeOwner {
_acceptOwnership();
}
function _transferOwnership(
address account
) internal virtual override(OwnableInternal, SafeOwnableInternal) {
super._transferOwnership(account);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
import { ISafeOwnableInternal } from './ISafeOwnableInternal.sol';
import { OwnableInternal } from './OwnableInternal.sol';
import { SafeOwnableStorage } from './SafeOwnableStorage.sol';
abstract contract SafeOwnableInternal is ISafeOwnableInternal, OwnableInternal {
modifier onlyNomineeOwner() {
if (msg.sender != _nomineeOwner())
revert SafeOwnable__NotNomineeOwner();
_;
}
/**
* @notice get the nominated owner who has permission to call acceptOwnership
*/
function _nomineeOwner() internal view virtual returns (address) {
return SafeOwnableStorage.layout().nomineeOwner;
}
/**
* @notice accept transfer of contract ownership
*/
function _acceptOwnership() internal virtual {
_setOwner(msg.sender);
delete SafeOwnableStorage.layout().nomineeOwner;
}
/**
* @notice grant permission to given address to claim contract ownership
*/
function _transferOwnership(address account) internal virtual override {
_setNomineeOwner(account);
}
/**
* @notice set nominee owner
*/
function _setNomineeOwner(address account) internal virtual {
SafeOwnableStorage.layout().nomineeOwner = account;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
library SafeOwnableStorage {
struct Layout {
address nomineeOwner;
}
bytes32 internal constant STORAGE_SLOT =
keccak256('solidstate.contracts.storage.SafeOwnable');
function layout() internal pure returns (Layout storage l) {
bytes32 slot = STORAGE_SLOT;
assembly {
l.slot := slot
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
import { IERC165Internal } from './IERC165Internal.sol';
/**
* @title ERC165 interface registration interface
* @dev see https://eips.ethereum.org/EIPS/eip-165
*/
interface IERC165 is IERC165Internal {
/**
* @notice query whether contract has registered support for given interface
* @param interfaceId interface id
* @return bool whether interface is supported
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
/**
* @title ERC165 interface registration interface
*/
interface IERC165Internal {
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
import { IERC173Internal } from './IERC173Internal.sol';
/**
* @title Contract ownership standard interface
* @dev see https://eips.ethereum.org/EIPS/eip-173
*/
interface IERC173 is IERC173Internal {
/**
* @notice get the ERC173 contract owner
* @return contract owner
*/
function owner() external view returns (address);
/**
* @notice transfer contract ownership to new account
* @param account address of new owner
*/
function transferOwnership(address account) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
/**
* @title Partial ERC173 interface needed by internal functions
*/
interface IERC173Internal {
event OwnershipTransferred(
address indexed previousOwner,
address indexed newOwner
);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
import { IERC165 } from '../../../interfaces/IERC165.sol';
import { IERC165Base } from './IERC165Base.sol';
import { ERC165BaseInternal } from './ERC165BaseInternal.sol';
import { ERC165BaseStorage } from './ERC165BaseStorage.sol';
/**
* @title ERC165 implementation
*/
abstract contract ERC165Base is IERC165Base, ERC165BaseInternal {
/**
* @inheritdoc IERC165
*/
function supportsInterface(bytes4 interfaceId) public view returns (bool) {
return _supportsInterface(interfaceId);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
import { IERC165BaseInternal } from './IERC165BaseInternal.sol';
import { ERC165BaseStorage } from './ERC165BaseStorage.sol';
/**
* @title ERC165 implementation
*/
abstract contract ERC165BaseInternal is IERC165BaseInternal {
/**
* @notice indicates whether an interface is already supported based on the interfaceId
* @param interfaceId id of interface to check
* @return bool indicating whether interface is supported
*/
function _supportsInterface(
bytes4 interfaceId
) internal view virtual returns (bool) {
return ERC165BaseStorage.layout().supportedInterfaces[interfaceId];
}
/**
* @notice sets status of interface support
* @param interfaceId id of interface to set status for
* @param status boolean indicating whether interface will be set as supported
*/
function _setSupportsInterface(
bytes4 interfaceId,
bool status
) internal virtual {
if (interfaceId == 0xffffffff) revert ERC165Base__InvalidInterfaceId();
ERC165BaseStorage.layout().supportedInterfaces[interfaceId] = status;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
library ERC165BaseStorage {
struct Layout {
mapping(bytes4 => bool) supportedInterfaces;
}
bytes32 internal constant STORAGE_SLOT =
keccak256('solidstate.contracts.storage.ERC165Base');
function layout() internal pure returns (Layout storage l) {
bytes32 slot = STORAGE_SLOT;
assembly {
l.slot := slot
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { IERC165 } from '../../../interfaces/IERC165.sol';
import { IERC165BaseInternal } from './IERC165BaseInternal.sol';
interface IERC165Base is IERC165, IERC165BaseInternal {}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { IERC165Internal } from '../../../interfaces/IERC165Internal.sol';
interface IERC165BaseInternal is IERC165Internal {
error ERC165Base__InvalidInterfaceId();
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
import { Proxy } from '../../Proxy.sol';
import { IDiamondBase } from './IDiamondBase.sol';
import { DiamondBaseStorage } from './DiamondBaseStorage.sol';
/**
* @title EIP-2535 "Diamond" proxy base contract
* @dev see https://eips.ethereum.org/EIPS/eip-2535
*/
abstract contract DiamondBase is IDiamondBase, Proxy {
/**
* @inheritdoc Proxy
*/
function _getImplementation()
internal
view
virtual
override
returns (address implementation)
{
// inline storage layout retrieval uses less gas
DiamondBaseStorage.Layout storage l;
bytes32 slot = DiamondBaseStorage.STORAGE_SLOT;
assembly {
l.slot := slot
}
implementation = address(bytes20(l.facets[msg.sig]));
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
/**
* @dev derived from https://github.com/mudgen/diamond-2 (MIT license)
*/
library DiamondBaseStorage {
struct Layout {
// function selector => (facet address, selector slot position)
mapping(bytes4 => bytes32) facets;
// total number of selectors registered
uint16 selectorCount;
// array of selector slots with 8 selectors per slot
mapping(uint256 => bytes32) selectorSlots;
address fallbackAddress;
}
bytes32 internal constant STORAGE_SLOT =
keccak256('solidstate.contracts.storage.DiamondBase');
function layout() internal pure returns (Layout storage l) {
bytes32 slot = STORAGE_SLOT;
assembly {
l.slot := slot
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
import { IProxy } from '../../IProxy.sol';
interface IDiamondBase is IProxy {}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
import { OwnableInternal } from '../../../access/ownable/OwnableInternal.sol';
import { DiamondBase } from '../base/DiamondBase.sol';
import { DiamondBaseStorage } from '../base/DiamondBaseStorage.sol';
import { IDiamondFallback } from './IDiamondFallback.sol';
/**
* @title Fallback feature for EIP-2535 "Diamond" proxy
*/
abstract contract DiamondFallback is
IDiamondFallback,
OwnableInternal,
DiamondBase
{
/**
* @inheritdoc IDiamondFallback
*/
function getFallbackAddress()
external
view
returns (address fallbackAddress)
{
fallbackAddress = _getFallbackAddress();
}
/**
* @inheritdoc IDiamondFallback
*/
function setFallbackAddress(address fallbackAddress) external onlyOwner {
_setFallbackAddress(fallbackAddress);
}
/**
* @inheritdoc DiamondBase
* @notice query custom fallback address is no implementation is found
*/
function _getImplementation()
internal
view
virtual
override
returns (address implementation)
{
implementation = super._getImplementation();
if (implementation == address(0)) {
implementation = _getFallbackAddress();
}
}
/**
* @notice query the address of the fallback implementation
* @return fallbackAddress address of fallback implementation
*/
function _getFallbackAddress()
internal
view
virtual
returns (address fallbackAddress)
{
fallbackAddress = DiamondBaseStorage.layout().fallbackAddress;
}
/**
* @notice set the address of the fallback implementation
* @param fallbackAddress address of fallback implementation
*/
function _setFallbackAddress(address fallbackAddress) internal virtual {
DiamondBaseStorage.layout().fallbackAddress = fallbackAddress;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
import { IDiamondBase } from '../base/IDiamondBase.sol';
interface IDiamondFallback is IDiamondBase {
/**
* @notice query the address of the fallback implementation
* @return fallbackAddress address of fallback implementation
*/
function getFallbackAddress()
external
view
returns (address fallbackAddress);
/**
* @notice set the address of the fallback implementation
* @param fallbackAddress address of fallback implementation
*/
function setFallbackAddress(address fallbackAddress) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
import { ISafeOwnable } from '../../access/ownable/ISafeOwnable.sol';
import { IERC165 } from '../../interfaces/IERC165.sol';
import { IDiamondBase } from './base/IDiamondBase.sol';
import { IDiamondFallback } from './fallback/IDiamondFallback.sol';
import { IDiamondReadable } from './readable/IDiamondReadable.sol';
import { IDiamondWritable } from './writable/IDiamondWritable.sol';
interface ISolidStateDiamond is
IDiamondBase,
IDiamondFallback,
IDiamondReadable,
IDiamondWritable,
ISafeOwnable,
IERC165
{
receive() external payable;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
import { DiamondBaseStorage } from '../base/DiamondBaseStorage.sol';
import { IDiamondReadable } from './IDiamondReadable.sol';
/**
* @title EIP-2535 "Diamond" proxy introspection contract
* @dev derived from https://github.com/mudgen/diamond-2 (MIT license)
*/
abstract contract DiamondReadable is IDiamondReadable {
/**
* @inheritdoc IDiamondReadable
*/
function facets() external view returns (Facet[] memory diamondFacets) {
DiamondBaseStorage.Layout storage l = DiamondBaseStorage.layout();
diamondFacets = new Facet[](l.selectorCount);
uint8[] memory numFacetSelectors = new uint8[](l.selectorCount);
uint256 numFacets;
uint256 selectorIndex;
// loop through function selectors
for (uint256 slotIndex; selectorIndex < l.selectorCount; slotIndex++) {
bytes32 slot = l.selectorSlots[slotIndex];
for (
uint256 selectorSlotIndex;
selectorSlotIndex < 8;
selectorSlotIndex++
) {
selectorIndex++;
if (selectorIndex > l.selectorCount) {
break;
}
bytes4 selector = bytes4(slot << (selectorSlotIndex << 5));
address facet = address(bytes20(l.facets[selector]));
bool continueLoop;
for (uint256 facetIndex; facetIndex < numFacets; facetIndex++) {
if (diamondFacets[facetIndex].target == facet) {
diamondFacets[facetIndex].selectors[
numFacetSelectors[facetIndex]
] = selector;
// probably will never have more than 256 functions from one facet contract
require(numFacetSelectors[facetIndex] < 255);
numFacetSelectors[facetIndex]++;
continueLoop = true;
break;
}
}
if (continueLoop) {
continue;
}
diamondFacets[numFacets].target = facet;
diamondFacets[numFacets].selectors = new bytes4[](
l.selectorCount
);
diamondFacets[numFacets].selectors[0] = selector;
numFacetSelectors[numFacets] = 1;
numFacets++;
}
}
for (uint256 facetIndex; facetIndex < numFacets; facetIndex++) {
uint256 numSelectors = numFacetSelectors[facetIndex];
bytes4[] memory selectors = diamondFacets[facetIndex].selectors;
// setting the number of selectors
assembly {
mstore(selectors, numSelectors)
}
}
// setting the number of facets
assembly {
mstore(diamondFacets, numFacets)
}
}
/**
* @inheritdoc IDiamondReadable
*/
function facetFunctionSelectors(
address facet
) external view returns (bytes4[] memory selectors) {
DiamondBaseStorage.Layout storage l = DiamondBaseStorage.layout();
selectors = new bytes4[](l.selectorCount);
uint256 numSelectors;
uint256 selectorIndex;
// loop through function selectors
for (uint256 slotIndex; selectorIndex < l.selectorCount; slotIndex++) {
bytes32 slot = l.selectorSlots[slotIndex];
for (
uint256 selectorSlotIndex;
selectorSlotIndex < 8;
selectorSlotIndex++
) {
selectorIndex++;
if (selectorIndex > l.selectorCount) {
break;
}
bytes4 selector = bytes4(slot << (selectorSlotIndex << 5));
if (facet == address(bytes20(l.facets[selector]))) {
selectors[numSelectors] = selector;
numSelectors++;
}
}
}
// set the number of selectors in the array
assembly {
mstore(selectors, numSelectors)
}
}
/**
* @inheritdoc IDiamondReadable
*/
function facetAddresses()
external
view
returns (address[] memory addresses)
{
DiamondBaseStorage.Layout storage l = DiamondBaseStorage.layout();
addresses = new address[](l.selectorCount);
uint256 numFacets;
uint256 selectorIndex;
for (uint256 slotIndex; selectorIndex < l.selectorCount; slotIndex++) {
bytes32 slot = l.selectorSlots[slotIndex];
for (
uint256 selectorSlotIndex;
selectorSlotIndex < 8;
selectorSlotIndex++
) {
selectorIndex++;
if (selectorIndex > l.selectorCount) {
break;
}
bytes4 selector = bytes4(slot << (selectorSlotIndex << 5));
address facet = address(bytes20(l.facets[selector]));
bool continueLoop;
for (uint256 facetIndex; facetIndex < numFacets; facetIndex++) {
if (facet == addresses[facetIndex]) {
continueLoop = true;
break;
}
}
if (continueLoop) {
continue;
}
addresses[numFacets] = facet;
numFacets++;
}
}
// set the number of facet addresses in the array
assembly {
mstore(addresses, numFacets)
}
}
/**
* @inheritdoc IDiamondReadable
*/
function facetAddress(
bytes4 selector
) external view returns (address facet) {
facet = address(bytes20(DiamondBaseStorage.layout().facets[selector]));
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
/**
* @title Diamond proxy introspection interface
* @dev see https://eips.ethereum.org/EIPS/eip-2535
*/
interface IDiamondReadable {
struct Facet {
address target;
bytes4[] selectors;
}
/**
* @notice get all facets and their selectors
* @return diamondFacets array of structured facet data
*/
function facets() external view returns (Facet[] memory diamondFacets);
/**
* @notice get all selectors for given facet address
* @param facet address of facet to query
* @return selectors array of function selectors
*/
function facetFunctionSelectors(
address facet
) external view returns (bytes4[] memory selectors);
/**
* @notice get addresses of all facets used by diamond
* @return addresses array of facet addresses
*/
function facetAddresses()
external
view
returns (address[] memory addresses);
/**
* @notice get the address of the facet associated with given selector
* @param selector function selector to query
* @return facet facet address (zero address if not found)
*/
function facetAddress(
bytes4 selector
) external view returns (address facet);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
import { IOwnable, Ownable, OwnableInternal } from '../../access/ownable/Ownable.sol';
import { ISafeOwnable, SafeOwnable } from '../../access/ownable/SafeOwnable.sol';
import { IERC165 } from '../../interfaces/IERC165.sol';
import { IERC173 } from '../../interfaces/IERC173.sol';
import { ERC165Base, ERC165BaseStorage } from '../../introspection/ERC165/base/ERC165Base.sol';
import { DiamondBase } from './base/DiamondBase.sol';
import { DiamondFallback, IDiamondFallback } from './fallback/DiamondFallback.sol';
import { DiamondReadable, IDiamondReadable } from './readable/DiamondReadable.sol';
import { DiamondWritable, IDiamondWritable } from './writable/DiamondWritable.sol';
import { ISolidStateDiamond } from './ISolidStateDiamond.sol';
/**
* @title SolidState "Diamond" proxy reference implementation
*/
abstract contract SolidStateDiamond is
ISolidStateDiamond,
DiamondBase,
DiamondFallback,
DiamondReadable,
DiamondWritable,
SafeOwnable,
ERC165Base
{
constructor() {
bytes4[] memory selectors = new bytes4[](12);
uint256 selectorIndex;
// register DiamondFallback
selectors[selectorIndex++] = IDiamondFallback
.getFallbackAddress
.selector;
selectors[selectorIndex++] = IDiamondFallback
.setFallbackAddress
.selector;
_setSupportsInterface(type(IDiamondFallback).interfaceId, true);
// register DiamondWritable
selectors[selectorIndex++] = IDiamondWritable.diamondCut.selector;
_setSupportsInterface(type(IDiamondWritable).interfaceId, true);
// register DiamondReadable
selectors[selectorIndex++] = IDiamondReadable.facets.selector;
selectors[selectorIndex++] = IDiamondReadable
.facetFunctionSelectors
.selector;
selectors[selectorIndex++] = IDiamondReadable.facetAddresses.selector;
selectors[selectorIndex++] = IDiamondReadable.facetAddress.selector;
_setSupportsInterface(type(IDiamondReadable).interfaceId, true);
// register ERC165
selectors[selectorIndex++] = IERC165.supportsInterface.selector;
_setSupportsInterface(type(IERC165).interfaceId, true);
// register SafeOwnable
selectors[selectorIndex++] = Ownable.owner.selector;
selectors[selectorIndex++] = SafeOwnable.nomineeOwner.selector;
selectors[selectorIndex++] = Ownable.transferOwnership.selector;
selectors[selectorIndex++] = SafeOwnable.acceptOwnership.selector;
_setSupportsInterface(type(IERC173).interfaceId, true);
// diamond cut
FacetCut[] memory facetCuts = new FacetCut[](1);
facetCuts[0] = FacetCut({
target: address(this),
action: FacetCutAction.ADD,
selectors: selectors
});
_diamondCut(facetCuts, address(0), '');
// set owner
_setOwner(msg.sender);
}
receive() external payable {}
function _transferOwnership(
address account
) internal virtual override(OwnableInternal, SafeOwnable) {
super._transferOwnership(account);
}
/**
* @inheritdoc DiamondFallback
*/
function _getImplementation()
internal
view
override(DiamondBase, DiamondFallback)
returns (address implementation)
{
implementation = super._getImplementation();
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
import { OwnableInternal } from '../../../access/ownable/OwnableInternal.sol';
import { IDiamondWritable } from './IDiamondWritable.sol';
import { DiamondWritableInternal } from './DiamondWritableInternal.sol';
/**
* @title EIP-2535 "Diamond" proxy update contract
*/
abstract contract DiamondWritable is
IDiamondWritable,
DiamondWritableInternal,
OwnableInternal
{
/**
* @inheritdoc IDiamondWritable
*/
function diamondCut(
FacetCut[] calldata facetCuts,
address target,
bytes calldata data
) external onlyOwner {
_diamondCut(facetCuts, target, data);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { AddressUtils } from '../../../utils/AddressUtils.sol';
import { DiamondBaseStorage } from '../base/DiamondBaseStorage.sol';
import { IDiamondWritableInternal } from './IDiamondWritableInternal.sol';
abstract contract DiamondWritableInternal is IDiamondWritableInternal {
using AddressUtils for address;
bytes32 private constant CLEAR_ADDRESS_MASK =
bytes32(uint256(0xffffffffffffffffffffffff));
bytes32 private constant CLEAR_SELECTOR_MASK =
bytes32(uint256(0xffffffff << 224));
/**
* @notice update functions callable on Diamond proxy
* @param facetCuts array of structured Diamond facet update data
* @param target optional recipient of initialization delegatecall
* @param data optional initialization call data
*/
function _diamondCut(
FacetCut[] memory facetCuts,
address target,
bytes memory data
) internal virtual {
DiamondBaseStorage.Layout storage l = DiamondBaseStorage.layout();
unchecked {
uint256 originalSelectorCount = l.selectorCount;
uint256 selectorCount = originalSelectorCount;
bytes32 selectorSlot;
// Check if last selector slot is not full
if (selectorCount & 7 > 0) {
// get last selectorSlot
selectorSlot = l.selectorSlots[selectorCount >> 3];
}
for (uint256 i; i < facetCuts.length; i++) {
FacetCut memory facetCut = facetCuts[i];
FacetCutAction action = facetCut.action;
if (facetCut.selectors.length == 0)
revert DiamondWritable__SelectorNotSpecified();
if (action == FacetCutAction.ADD) {
(selectorCount, selectorSlot) = _addFacetSelectors(
l,
selectorCount,
selectorSlot,
facetCut
);
} else if (action == FacetCutAction.REPLACE) {
_replaceFacetSelectors(l, facetCut);
} else if (action == FacetCutAction.REMOVE) {
(selectorCount, selectorSlot) = _removeFacetSelectors(
l,
selectorCount,
selectorSlot,
facetCut
);
}
}
if (selectorCount != originalSelectorCount) {
l.selectorCount = uint16(selectorCount);
}
// If last selector slot is not full
if (selectorCount & 7 > 0) {
l.selectorSlots[selectorCount >> 3] = selectorSlot;
}
emit DiamondCut(facetCuts, target, data);
_initialize(target, data);
}
}
function _addFacetSelectors(
DiamondBaseStorage.Layout storage l,
uint256 selectorCount,
bytes32 selectorSlot,
FacetCut memory facetCut
) internal returns (uint256, bytes32) {
unchecked {
if (
facetCut.target != address(this) &&
!facetCut.target.isContract()
) revert DiamondWritable__TargetHasNoCode();
for (uint256 i; i < facetCut.selectors.length; i++) {
bytes4 selector = facetCut.selectors[i];
bytes32 oldFacet = l.facets[selector];
if (address(bytes20(oldFacet)) != address(0))
revert DiamondWritable__SelectorAlreadyAdded();
// add facet for selector
l.facets[selector] =
bytes20(facetCut.target) |
bytes32(selectorCount);
uint256 selectorInSlotPosition = (selectorCount & 7) << 5;
// clear selector position in slot and add selector
selectorSlot =
(selectorSlot &
~(CLEAR_SELECTOR_MASK >> selectorInSlotPosition)) |
(bytes32(selector) >> selectorInSlotPosition);
// if slot is full then write it to storage
if (selectorInSlotPosition == 224) {
l.selectorSlots[selectorCount >> 3] = selectorSlot;
selectorSlot = 0;
}
selectorCount++;
}
return (selectorCount, selectorSlot);
}
}
function _removeFacetSelectors(
DiamondBaseStorage.Layout storage l,
uint256 selectorCount,
bytes32 selectorSlot,
FacetCut memory facetCut
) internal returns (uint256, bytes32) {
unchecked {
if (facetCut.target != address(0))
revert DiamondWritable__RemoveTargetNotZeroAddress();
uint256 selectorSlotCount = selectorCount >> 3;
uint256 selectorInSlotIndex = selectorCount & 7;
for (uint256 i; i < facetCut.selectors.length; i++) {
bytes4 selector = facetCut.selectors[i];
bytes32 oldFacet = l.facets[selector];
if (address(bytes20(oldFacet)) == address(0))
revert DiamondWritable__SelectorNotFound();
if (address(bytes20(oldFacet)) == address(this))
revert DiamondWritable__SelectorIsImmutable();
if (selectorSlot == 0) {
selectorSlotCount--;
selectorSlot = l.selectorSlots[selectorSlotCount];
selectorInSlotIndex = 7;
} else {
selectorInSlotIndex--;
}
bytes4 lastSelector;
uint256 oldSelectorsSlotCount;
uint256 oldSelectorInSlotPosition;
// adding a block here prevents stack too deep error
{
// replace selector with last selector in l.facets
lastSelector = bytes4(
selectorSlot << (selectorInSlotIndex << 5)
);
if (lastSelector != selector) {
// update last selector slot position info
l.facets[lastSelector] =
(oldFacet & CLEAR_ADDRESS_MASK) |
bytes20(l.facets[lastSelector]);
}
delete l.facets[selector];
uint256 oldSelectorCount = uint16(uint256(oldFacet));
oldSelectorsSlotCount = oldSelectorCount >> 3;
oldSelectorInSlotPosition = (oldSelectorCount & 7) << 5;
}
if (oldSelectorsSlotCount != selectorSlotCount) {
bytes32 oldSelectorSlot = l.selectorSlots[
oldSelectorsSlotCount
];
// clears the selector we are deleting and puts the last selector in its place.
oldSelectorSlot =
(oldSelectorSlot &
~(CLEAR_SELECTOR_MASK >>
oldSelectorInSlotPosition)) |
(bytes32(lastSelector) >> oldSelectorInSlotPosition);
// update storage with the modified slot
l.selectorSlots[oldSelectorsSlotCount] = oldSelectorSlot;
} else {
// clears the selector we are deleting and puts the last selector in its place.
selectorSlot =
(selectorSlot &
~(CLEAR_SELECTOR_MASK >>
oldSelectorInSlotPosition)) |
(bytes32(lastSelector) >> oldSelectorInSlotPosition);
}
if (selectorInSlotIndex == 0) {
delete l.selectorSlots[selectorSlotCount];
selectorSlot = 0;
}
}
selectorCount = (selectorSlotCount << 3) | selectorInSlotIndex;
return (selectorCount, selectorSlot);
}
}
function _replaceFacetSelectors(
DiamondBaseStorage.Layout storage l,
FacetCut memory facetCut
) internal {
unchecked {
if (!facetCut.target.isContract())
revert DiamondWritable__TargetHasNoCode();
for (uint256 i; i < facetCut.selectors.length; i++) {
bytes4 selector = facetCut.selectors[i];
bytes32 oldFacet = l.facets[selector];
address oldFacetAddress = address(bytes20(oldFacet));
if (oldFacetAddress == address(0))
revert DiamondWritable__SelectorNotFound();
if (oldFacetAddress == address(this))
revert DiamondWritable__SelectorIsImmutable();
if (oldFacetAddress == facetCut.target)
revert DiamondWritable__ReplaceTargetIsIdentical();
// replace old facet address
l.facets[selector] =
(oldFacet & CLEAR_ADDRESS_MASK) |
bytes20(facetCut.target);
}
}
}
function _initialize(address target, bytes memory data) private {
if ((target == address(0)) != (data.length == 0))
revert DiamondWritable__InvalidInitializationParameters();
if (target != address(0)) {
if (target != address(this)) {
if (!target.isContract())
revert DiamondWritable__TargetHasNoCode();
}
(bool success, ) = target.delegatecall(data);
if (!success) {
assembly {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
import { IDiamondWritableInternal } from './IDiamondWritableInternal.sol';
/**
* @title Diamond proxy upgrade interface
* @dev see https://eips.ethereum.org/EIPS/eip-2535
*/
interface IDiamondWritable is IDiamondWritableInternal {
/**
* @notice update diamond facets and optionally execute arbitrary initialization function
* @param facetCuts array of structured Diamond facet update data
* @param target optional target of initialization delegatecall
* @param data optional initialization function call data
*/
function diamondCut(
FacetCut[] calldata facetCuts,
address target,
bytes calldata data
) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
interface IDiamondWritableInternal {
enum FacetCutAction {
ADD,
REPLACE,
REMOVE
}
event DiamondCut(FacetCut[] facetCuts, address target, bytes data);
error DiamondWritable__InvalidInitializationParameters();
error DiamondWritable__RemoveTargetNotZeroAddress();
error DiamondWritable__ReplaceTargetIsIdentical();
error DiamondWritable__SelectorAlreadyAdded();
error DiamondWritable__SelectorIsImmutable();
error DiamondWritable__SelectorNotFound();
error DiamondWritable__SelectorNotSpecified();
error DiamondWritable__TargetHasNoCode();
struct FacetCut {
address target;
FacetCutAction action;
bytes4[] selectors;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
interface IProxy {
error Proxy__ImplementationIsNotContract();
fallback() external payable;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
import { AddressUtils } from '../utils/AddressUtils.sol';
import { IProxy } from './IProxy.sol';
/**
* @title Base proxy contract
*/
abstract contract Proxy is IProxy {
using AddressUtils for address;
/**
* @notice delegate all calls to implementation contract
* @dev reverts if implementation address contains no code, for compatibility with metamorphic contracts
* @dev memory location in use by assembly may be unsafe in other contexts
*/
fallback() external payable virtual {
address implementation = _getImplementation();
if (!implementation.isContract())
revert Proxy__ImplementationIsNotContract();
assembly {
calldatacopy(0, 0, calldatasize())
let result := delegatecall(
gas(),
implementation,
0,
calldatasize(),
0,
0
)
returndatacopy(0, 0, returndatasize())
switch result
case 0 {
revert(0, returndatasize())
}
default {
return(0, returndatasize())
}
}
}
/**
* @notice get logic implementation address
* @return implementation address
*/
function _getImplementation() internal virtual returns (address);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
import { IPausableInternal } from './IPausableInternal.sol';
interface IPausable is IPausableInternal {
/**
* @notice query whether contract is paused
* @return status whether contract is paused
*/
function paused() external view returns (bool status);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
interface IPausableInternal {
error Pausable__Paused();
error Pausable__NotPaused();
event Paused(address account);
event Unpaused(address account);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
import { IPausable } from './IPausable.sol';
import { PausableInternal } from './PausableInternal.sol';
/**
* @title Pausable security control module.
*/
abstract contract Pausable is IPausable, PausableInternal {
/**
* @inheritdoc IPausable
*/
function paused() external view virtual returns (bool status) {
status = _paused();
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
import { IPausableInternal } from './IPausableInternal.sol';
import { PausableStorage } from './PausableStorage.sol';
/**
* @title Internal functions for Pausable security control module.
*/
abstract contract PausableInternal is IPausableInternal {
modifier whenNotPaused() {
if (_paused()) revert Pausable__Paused();
_;
}
modifier whenPaused() {
if (!_paused()) revert Pausable__NotPaused();
_;
}
/**
* @notice query whether contract is paused
* @return status whether contract is paused
*/
function _paused() internal view virtual returns (bool status) {
status = PausableStorage.layout().paused;
}
/**
* @notice Triggers paused state, when contract is unpaused.
*/
function _pause() internal virtual whenNotPaused {
PausableStorage.layout().paused = true;
emit Paused(msg.sender);
}
/**
* @notice Triggers unpaused state, when contract is paused.
*/
function _unpause() internal virtual whenPaused {
delete PausableStorage.layout().paused;
emit Unpaused(msg.sender);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
library PausableStorage {
struct Layout {
bool paused;
}
bytes32 internal constant STORAGE_SLOT =
keccak256('solidstate.contracts.storage.Pausable');
function layout() internal pure returns (Layout storage l) {
bytes32 slot = STORAGE_SLOT;
assembly {
l.slot := slot
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IReentrancyGuard {
error ReentrancyGuard__ReentrantCall();
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
import { IReentrancyGuard } from './IReentrancyGuard.sol';
import { ReentrancyGuardStorage } from './ReentrancyGuardStorage.sol';
/**
* @title Utility contract for preventing reentrancy attacks
*/
abstract contract ReentrancyGuard is IReentrancyGuard {
uint256 internal constant REENTRANCY_STATUS_LOCKED = 2;
uint256 internal constant REENTRANCY_STATUS_UNLOCKED = 1;
modifier nonReentrant() virtual {
if (_isReentrancyGuardLocked()) revert ReentrancyGuard__ReentrantCall();
_lockReentrancyGuard();
_;
_unlockReentrancyGuard();
}
/**
* @notice returns true if the reentrancy guard is locked, false otherwise
*/
function _isReentrancyGuardLocked() internal view virtual returns (bool) {
return
ReentrancyGuardStorage.layout().status == REENTRANCY_STATUS_LOCKED;
}
/**
* @notice lock functions that use the nonReentrant modifier
*/
function _lockReentrancyGuard() internal virtual {
ReentrancyGuardStorage.layout().status = REENTRANCY_STATUS_LOCKED;
}
/**
* @notice unlock functions that use the nonReentrant modifier
*/
function _unlockReentrancyGuard() internal virtual {
ReentrancyGuardStorage.layout().status = REENTRANCY_STATUS_UNLOCKED;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
library ReentrancyGuardStorage {
struct Layout {
uint256 status;
}
bytes32 internal constant STORAGE_SLOT =
keccak256('solidstate.contracts.storage.ReentrancyGuard');
function layout() internal pure returns (Layout storage l) {
bytes32 slot = STORAGE_SLOT;
assembly {
l.slot := slot
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
import { UintUtils } from './UintUtils.sol';
library AddressUtils {
using UintUtils for uint256;
error AddressUtils__InsufficientBalance();
error AddressUtils__NotContract();
error AddressUtils__SendValueFailed();
function toString(address account) internal pure returns (string memory) {
return uint256(uint160(account)).toHexString(20);
}
function isContract(address account) internal view returns (bool) {
uint256 size;
assembly {
size := extcodesize(account)
}
return size > 0;
}
function sendValue(address payable account, uint256 amount) internal {
(bool success, ) = account.call{ value: amount }('');
if (!success) revert AddressUtils__SendValueFailed();
}
function functionCall(
address target,
bytes memory data
) internal returns (bytes memory) {
return
functionCall(target, data, 'AddressUtils: failed low-level call');
}
function functionCall(
address target,
bytes memory data,
string memory error
) internal returns (bytes memory) {
return _functionCallWithValue(target, data, 0, error);
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return
functionCallWithValue(
target,
data,
value,
'AddressUtils: failed low-level call with value'
);
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory error
) internal returns (bytes memory) {
if (value > address(this).balance)
revert AddressUtils__InsufficientBalance();
return _functionCallWithValue(target, data, value, error);
}
/**
* @notice execute arbitrary external call with limited gas usage and amount of copied return data
* @dev derived from https://github.com/nomad-xyz/ExcessivelySafeCall (MIT License)
* @param target recipient of call
* @param gasAmount gas allowance for call
* @param value native token value to include in call
* @param maxCopy maximum number of bytes to copy from return data
* @param data encoded call data
* @return success whether call is successful
* @return returnData copied return data
*/
function excessivelySafeCall(
address target,
uint256 gasAmount,
uint256 value,
uint16 maxCopy,
bytes memory data
) internal returns (bool success, bytes memory returnData) {
returnData = new bytes(maxCopy);
assembly {
// execute external call via assembly to avoid automatic copying of return data
success := call(
gasAmount,
target,
value,
add(data, 0x20),
mload(data),
0,
0
)
// determine whether to limit amount of data to copy
let toCopy := returndatasize()
if gt(toCopy, maxCopy) {
toCopy := maxCopy
}
// store the length of the copied bytes
mstore(returnData, toCopy)
// copy the bytes from returndata[0:toCopy]
returndatacopy(add(returnData, 0x20), 0, toCopy)
}
}
function _functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory error
) private returns (bytes memory) {
if (!isContract(target)) revert AddressUtils__NotContract();
(bool success, bytes memory returnData) = target.call{ value: value }(
data
);
if (success) {
return returnData;
} else if (returnData.length > 0) {
assembly {
let returnData_size := mload(returnData)
revert(add(32, returnData), returnData_size)
}
} else {
revert(error);
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
/**
* @title utility functions for uint256 operations
* @dev derived from https://github.com/OpenZeppelin/openzeppelin-contracts/ (MIT license)
*/
library UintUtils {
error UintUtils__InsufficientHexLength();
bytes16 private constant HEX_SYMBOLS = '0123456789abcdef';
function add(uint256 a, int256 b) internal pure returns (uint256) {
return b < 0 ? sub(a, -b) : a + uint256(b);
}
function sub(uint256 a, int256 b) internal pure returns (uint256) {
return b < 0 ? add(a, -b) : a - uint256(b);
}
function toString(uint256 value) internal pure returns (string memory) {
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);
}
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return '0x00';
}
uint256 length = 0;
for (uint256 temp = value; temp != 0; temp >>= 8) {
unchecked {
length++;
}
}
return toHexString(value, 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';
unchecked {
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
}
if (value != 0) revert UintUtils__InsufficientHexLength();
return string(buffer);
}
}// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; /** * @dev The default token decimals value */ uint256 constant DECIMALS_DEFAULT = 18; /** * @dev The maximum uint256 value for swap amount limit settings */ uint256 constant INFINITY = type(uint256).max; /** * @dev The default limit of account list size */ uint256 constant LIST_SIZE_LIMIT_DEFAULT = 100; /** * @dev The limit of swap router list size */ uint256 constant LIST_SIZE_LIMIT_ROUTERS = 200; /** * @dev The factor for percentage settings. Example: 100 is 0.1% */ uint256 constant MILLIPERCENT_FACTOR = 100_000; /** * @dev The de facto standard address to denote the native token */ address constant NATIVE_TOKEN_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.19;
/**
* @notice Emitted when an approval action fails
*/
error SafeApproveError();
/**
* @notice Emitted when a transfer action fails
*/
error SafeTransferError();
/**
* @notice Emitted when a transferFrom action fails
*/
error SafeTransferFromError();
/**
* @notice Emitted when a transfer of the native token fails
*/
error SafeTransferNativeError();
/**
* @notice Safely approve the token to the account
* @param _token The token address
* @param _to The token approval recipient address
* @param _value The token approval amount
*/
function safeApprove(address _token, address _to, uint256 _value) {
// 0x095ea7b3 is the selector for "approve(address,uint256)"
(bool success, bytes memory data) = _token.call(
abi.encodeWithSelector(0x095ea7b3, _to, _value)
);
bool condition = success && (data.length == 0 || abi.decode(data, (bool)));
if (!condition) {
revert SafeApproveError();
}
}
/**
* @notice Safely transfer the token to the account
* @param _token The token address
* @param _to The token transfer recipient address
* @param _value The token transfer amount
*/
function safeTransfer(address _token, address _to, uint256 _value) {
// 0xa9059cbb is the selector for "transfer(address,uint256)"
(bool success, bytes memory data) = _token.call(
abi.encodeWithSelector(0xa9059cbb, _to, _value)
);
bool condition = success && (data.length == 0 || abi.decode(data, (bool)));
if (!condition) {
revert SafeTransferError();
}
}
/**
* @notice Safely transfer the token between the accounts
* @param _token The token address
* @param _from The token transfer source address
* @param _to The token transfer recipient address
* @param _value The token transfer amount
*/
function safeTransferFrom(address _token, address _from, address _to, uint256 _value) {
// 0x23b872dd is the selector for "transferFrom(address,address,uint256)"
(bool success, bytes memory data) = _token.call(
abi.encodeWithSelector(0x23b872dd, _from, _to, _value)
);
bool condition = success && (data.length == 0 || abi.decode(data, (bool)));
if (!condition) {
revert SafeTransferFromError();
}
}
/**
* @notice Safely transfer the native token to the account
* @param _to The native token transfer recipient address
* @param _value The native token transfer amount
*/
function safeTransferNative(address _to, uint256 _value) {
(bool success, ) = _to.call{ value: _value }(new bytes(0));
if (!success) {
revert SafeTransferNativeError();
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.19;
/**
* @title ITokenBalance
* @notice Token balance interface
*/
interface ITokenBalance {
/**
* @notice Getter of the token balance by the account
* @param _account The account address
* @return Token balance
*/
function balanceOf(address _account) external view returns (uint256);
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.19;
/**
* @title OFTWrapperStorage
* @notice OFTWrapperDiamond storage
*/
library OFTWrapperStorage {
/**
* @notice OFTWrapperDiamond storage layout
* @param collector The address of the collector
*/
struct Layout {
address collector;
}
bytes32 internal constant STORAGE_SLOT = keccak256('interport.oft.wrapper.OFTWrapperDiamond');
function layout() internal pure returns (Layout storage l) {
bytes32 slot = STORAGE_SLOT;
assembly {
l.slot := slot
}
}
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_collector","type":"address"},{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"DiamondWritable__InvalidInitializationParameters","type":"error"},{"inputs":[],"name":"DiamondWritable__RemoveTargetNotZeroAddress","type":"error"},{"inputs":[],"name":"DiamondWritable__ReplaceTargetIsIdentical","type":"error"},{"inputs":[],"name":"DiamondWritable__SelectorAlreadyAdded","type":"error"},{"inputs":[],"name":"DiamondWritable__SelectorIsImmutable","type":"error"},{"inputs":[],"name":"DiamondWritable__SelectorNotFound","type":"error"},{"inputs":[],"name":"DiamondWritable__SelectorNotSpecified","type":"error"},{"inputs":[],"name":"DiamondWritable__TargetHasNoCode","type":"error"},{"inputs":[],"name":"ERC165Base__InvalidInterfaceId","type":"error"},{"inputs":[],"name":"Ownable__NotOwner","type":"error"},{"inputs":[],"name":"Ownable__NotTransitiveOwner","type":"error"},{"inputs":[],"name":"Pausable__NotPaused","type":"error"},{"inputs":[],"name":"Pausable__Paused","type":"error"},{"inputs":[],"name":"Proxy__ImplementationIsNotContract","type":"error"},{"inputs":[],"name":"ReentrancyGuard__ReentrantCall","type":"error"},{"inputs":[],"name":"SafeOwnable__NotNomineeOwner","type":"error"},{"inputs":[],"name":"SafeTransferError","type":"error"},{"inputs":[],"name":"SafeTransferNativeError","type":"error"},{"anonymous":false,"inputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"enum IDiamondWritableInternal.FacetCutAction","name":"action","type":"uint8"},{"internalType":"bytes4[]","name":"selectors","type":"bytes4[]"}],"indexed":false,"internalType":"struct IDiamondWritableInternal.FacetCut[]","name":"facetCuts","type":"tuple[]"},{"indexed":false,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"DiamondCut","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"collector","type":"address"}],"name":"SetCollector","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"SYSTEM_VERSION_ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"}],"name":"cleanup","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"uint256","name":"_tokenAmount","type":"uint256"}],"name":"cleanupWithAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"collector","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"enum IDiamondWritableInternal.FacetCutAction","name":"action","type":"uint8"},{"internalType":"bytes4[]","name":"selectors","type":"bytes4[]"}],"internalType":"struct IDiamondWritableInternal.FacetCut[]","name":"facetCuts","type":"tuple[]"},{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"diamondCut","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"selector","type":"bytes4"}],"name":"facetAddress","outputs":[{"internalType":"address","name":"facet","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"facetAddresses","outputs":[{"internalType":"address[]","name":"addresses","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"facet","type":"address"}],"name":"facetFunctionSelectors","outputs":[{"internalType":"bytes4[]","name":"selectors","type":"bytes4[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"facets","outputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes4[]","name":"selectors","type":"bytes4[]"}],"internalType":"struct IDiamondReadable.Facet[]","name":"diamondFacets","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"forceTransferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getFallbackAddress","outputs":[{"internalType":"address","name":"fallbackAddress","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nomineeOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"status","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_collector","type":"address"}],"name":"setCollector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"fallbackAddress","type":"address"}],"name":"setFallbackAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"}],"name":"tokenBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60806040523480156200001157600080fd5b50604051620038383803806200383883398101604081905262000034916200119a565b60408051600c8082526101a0820190925260009160208201610180803683370190505090506000632c40805960e01b82826200007081620011d2565b935081518110620000855762000085620011fa565b6001600160e01b031990921660209283029190910190910152639142376560e01b8282620000b381620011d2565b935081518110620000c857620000c8620011fa565b6001600160e01b031990921660209283029190910190910152620000f5632f40adcf60e21b6001620004ed565b6307e4c70760e21b82826200010a81620011d2565b9350815181106200011f576200011f620011fa565b6001600160e01b0319909216602092830291909101909101526200014c6307e4c70760e21b6001620004ed565b637a0ed62760e01b82826200016181620011d2565b935081518110620001765762000176620011fa565b6001600160e01b0319909216602092830291909101909101526356fe50af60e11b8282620001a481620011d2565b935081518110620001b957620001b9620011fa565b6001600160e01b0319909216602092830291909101909101526314bbdacb60e21b8282620001e781620011d2565b935081518110620001fc57620001fc620011fa565b6001600160e01b0319909216602092830291909101909101526366ffd66360e11b82826200022a81620011d2565b9350815181106200023f576200023f620011fa565b6001600160e01b0319909216602092830291909101909101526200026c6348e2b09360e01b6001620004ed565b6301ffc9a760e01b82826200028181620011d2565b935081518110620002965762000296620011fa565b6001600160e01b031990921660209283029190910190910152620002c36301ffc9a760e01b6001620004ed565b638da5cb5b60e01b8282620002d881620011d2565b935081518110620002ed57620002ed620011fa565b6001600160e01b03199092166020928302919091019091015263455a8a8560e11b82826200031b81620011d2565b935081518110620003305762000330620011fa565b6001600160e01b03199092166020928302919091019091015263f2fde38b60e01b82826200035e81620011d2565b935081518110620003735762000373620011fa565b6001600160e01b0319909216602092830291909101909101526379ba509760e01b8282620003a181620011d2565b935081518110620003b657620003b6620011fa565b6001600160e01b031990921660209283029190910190910152620003e36307f5828d60e41b6001620004ed565b604080516001808252818301909252600091816020015b60408051606080820183526000808352602083015291810191909152815260200190600190039081620003fa57905050604080516060810190915230815290915060208101600081526020018481525081600081518110620004605762000460620011fa565b60200260200101819052506200048e816000604051806020016040528060008152506200056460201b60201c565b620004993362000765565b50620004a7915050620007df565b620004b28262000b69565b6001600160a01b0381163314801590620004d457506001600160a01b03811615155b15620004e557620004e58162000765565b50506200139f565b6001600160e01b03198083169003620005195760405163b0a19dd560e01b815260040160405180910390fd5b6001600160e01b03199190911660009081527ffc606c433378e3a7e0a6a531deac289b66caa1b4aa8554fd4ab2c6f1570f92d860205260409020805460ff1916911515919091179055565b7f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc94547f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc939061ffff811690819060009060071615620005d45750600381901c60009081526002840160205260409020545b60005b8751811015620006d3576000888281518110620005f857620005f8620011fa565b60200260200101519050600081602001519050816040015151600003620006325760405163eb6c3aeb60e01b815260040160405180910390fd5b600081600281111562000649576200064962001210565b0362000668576200065d8786868562000bd2565b9095509350620006c8565b60018160028111156200067f576200067f62001210565b03620006975762000691878362000d1a565b620006c8565b6002816002811115620006ae57620006ae62001210565b03620006c857620006c28786868562000e64565b90955093505b5050600101620005d7565b50828214620006f05760018401805461ffff191661ffff84161790555b60078216156200071357600382901c600090815260028501602052604090208190555b7f8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb67387878760405162000748939291906200127a565b60405180910390a16200075c868662001090565b50505050505050565b7f8a22373512790c48b83a1fe2efdd2888d4a917bcdc24d0adf63e60f67168046080546040516001600160a01b038481169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a380546001600160a01b0319166001600160a01b0392909216919091179055565b60408051600a808252610160820190925260009160208201610140803683370190505090506000635c975abb60e01b82826200081b81620011d2565b935081518110620008305762000830620011fa565b6001600160e01b0319909216602092830291909101909101526200085d635c975abb60e01b6001620004ed565b630fb5b82d60e41b82826200087281620011d2565b935081518110620008875762000887620011fa565b6001600160e01b03199092166020928302919091019091015263913e77ad60e01b8282620008b581620011d2565b935081518110620008ca57620008ca620011fa565b6001600160e01b031990921660209283029190910190910152638456cb5960e01b8282620008f881620011d2565b9350815181106200090d576200090d620011fa565b6001600160e01b031990921660209283029190910190910152631fa5d41d60e11b82826200093b81620011d2565b935081518110620009505762000950620011fa565b6001600160e01b031990921660209283029190910190910152631513622560e31b82826200097e81620011d2565b935081518110620009935762000993620011fa565b6001600160e01b031990921660209283029190910190910152637dd677e760e11b8282620009c181620011d2565b935081518110620009d657620009d6620011fa565b6001600160e01b03199092166020928302919091019091015263160b7c9360e11b828262000a0481620011d2565b93508151811062000a195762000a19620011fa565b6001600160e01b03199092166020928302919091019091015263776e4b3560e11b828262000a4781620011d2565b93508151811062000a5c5762000a5c620011fa565b6001600160e01b03199092166020928302919091019091015263093f0e2760e01b828262000a8a81620011d2565b93508151811062000a9f5762000a9f620011fa565b6001600160e01b03199290921660209283029190910190910152604080516001808252818301909252600091816020015b6040805160608082018352600080835260208301529181019190915281526020019060019003908162000ad05790505060408051606081019091523081529091506020810160008152602001848152508160008151811062000b365762000b36620011fa565b602002602001018190525062000b64816000604051806020016040528060008152506200056460201b60201c565b505050565b7f8135b9b8d3411dab68efe82c12999875113f270399aa3b0126860dde293ca8f380546001600160a01b0319166001600160a01b0383169081179091556040517f0cc5437d7c9c1d9eab549acbb533eea3e9868e9443dd75309ed5820b33a3774e90600090a250565b805160009081906001600160a01b0316301480159062000bfb575082516001600160a01b03163b155b1562000c1a57604051633ddc5cab60e21b815260040160405180910390fd5b60005b83604001515181101562000d0d5760008460400151828151811062000c465762000c46620011fa565b6020908102919091018101516001600160e01b031981166000908152918a9052604090912054909150606081901c1562000c9357604051634923a77160e11b815260040160405180910390fd5b85516001600160e01b0319838116600081815260208d90526040902060609390931b6001600160601b0319168b1790925560058a901b60e090811692831c91831c1999909916179781900362000cfd57600389901c600090815260028b0160205260408120989098555b5050506001958601950162000c1d565b5093959294509192505050565b80516001600160a01b03163b62000d4457604051633ddc5cab60e21b815260040160405180910390fd5b60005b81604001515181101562000b645760008260400151828151811062000d705762000d70620011fa565b6020908102919091018101516001600160e01b03198116600090815291869052604090912054909150606081901c8062000dbd576040516337e25a9760e11b815260040160405180910390fd5b306001600160a01b0382160362000de75760405163e983573160e01b815260040160405180910390fd5b84600001516001600160a01b0316816001600160a01b03160362000e1e576040516330baabf360e11b815260040160405180910390fd5b5083516001600160e01b031992909216600090815260208690526040902060609290921b6001600160601b0319166001600160601b039190911617905560010162000d47565b805160009081906001600160a01b03161562000e9357604051633ab3490960e21b815260040160405180910390fd5b600385901c6007861660005b8560400151518110156200107c5760008660400151828151811062000ec85762000ec8620011fa565b6020908102919091018101516001600160e01b031981166000908152918c9052604090912054909150606081901c62000f14576040516337e25a9760e11b815260040160405180910390fd5b30606082901c0362000f395760405163e983573160e01b815260040160405180910390fd5b600089900362000f6757600019909401600081815260028c0160205260409020549850936007935062000f6f565b600019909301925b600584901b89901b6000806001600160e01b03198084169086161462000fc2576001600160e01b03198316600090815260208f90526040902080546001600160601b0319166001600160601b0386161790555b50506001600160e01b03198316600090815260208d90526040812055611fff600383901c1660e0600584901b168782146200102757600082815260028f016020526040902080546001600160e01b031980841c19909116908516831c1790556200104b565b80836001600160e01b031916901c816001600160e01b031960001b901c198d16179b505b866000036200106a57600088815260028f01602052604081208190559b505b50506001909301925062000e9f915050565b5060039190911b1796939550929350505050565b8051156001600160a01b0383161514620010bd576040516326df4ccd60e01b815260040160405180910390fd5b6001600160a01b0382161562001179576001600160a01b038216301462001107576001600160a01b0382163b6200110757604051633ddc5cab60e21b815260040160405180910390fd5b6000826001600160a01b03168260405162001123919062001381565b600060405180830381855af49150503d806000811462001160576040519150601f19603f3d011682016040523d82523d6000602084013e62001165565b606091505b505090508062000b64573d6000803e3d6000fd5b5050565b80516001600160a01b03811681146200119557600080fd5b919050565b60008060408385031215620011ae57600080fd5b620011b9836200117d565b9150620011c9602084016200117d565b90509250929050565b600060018201620011f357634e487b7160e01b600052601160045260246000fd5b5060010190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b60005b838110156200124357818101518382015260200162001229565b50506000910152565b600081518084526200126681602086016020860162001226565b601f01601f19169290920160200192915050565b60006060808301818452808751808352608092508286019150828160051b8701016020808b0160005b848110156200134f57898403607f19018652815180516001600160a01b03168552838101518986019060038110620012eb57634e487b7160e01b600052602160045260246000fd5b868601526040918201519186018a905281519081905290840190600090898701905b80831015620013395783516001600160e01b03191682529286019260019290920191908601906200130d565b50978501979550505090820190600101620012a3565b50506001600160a01b038a169088015286810360408801526200137381896200124c565b9a9950505050505050505050565b600082516200139581846020870162001226565b9190910192915050565b61248980620013af6000396000f3fe6080604052600436106101395760003560e01c80638ab5150a116100ab578063adfca15e1161006f578063adfca15e14610390578063cdffacc6146103bd578063eedc966a14610404578063f2fde38b14610424578063fb5b82d014610444578063fbacefce1461046457610140565b80638ab5150a146103115780638da5cb5b14610326578063913e77ad1461033b5780639142376514610350578063a89b11281461037057610140565b80633f4ba83a116100fd5780633f4ba83a1461027957806352ef6b2c1461028e5780635c975abb146102b057806379ba5097146102c55780637a0ed627146102da5780638456cb59146102fc57610140565b806301ffc9a71461019a578063093f0e27146101cf5780631f931c1c1461020c5780632c16f9261461022c5780632c4080591461024c57610140565b3661014057005b600061014a610484565b90506001600160a01b0381163b610174576040516321f27f0d60e21b815260040160405180910390fd5b3660008037600080366000845af43d6000803e808015610193573d6000f35b3d6000fd5b005b3480156101a657600080fd5b506101ba6101b5366004611d77565b610493565b60405190151581526020015b60405180910390f35b3480156101db57600080fd5b507f22ad9585a395edc8067b50da4778cafbb7fa2c4bbd7619fad6aeba403857fd745b6040519081526020016101c6565b34801561021857600080fd5b50610198610227366004611df9565b6104d6565b34801561023857600080fd5b50610198610247366004611eab565b610560565b34801561025857600080fd5b506102616105d7565b6040516001600160a01b0390911681526020016101c6565b34801561028557600080fd5b5061019861060a565b34801561029a57600080fd5b506102a361067d565b6040516101c69190611ed5565b3480156102bc57600080fd5b506101ba61082f565b3480156102d157600080fd5b5061019861084a565b3480156102e657600080fd5b506102ef61088b565b6040516101c69190611f67565b34801561030857600080fd5b50610198610cc2565b34801561031d57600080fd5b50610261610d34565b34801561033257600080fd5b50610261610d3e565b34801561034757600080fd5b50610261610d48565b34801561035c57600080fd5b5061019861036b366004611fe4565b610d7b565b34801561037c57600080fd5b5061019861038b366004611fe4565b610df4565b34801561039c57600080fd5b506103b06103ab366004611fe4565b610e36565b6040516101c69190611fff565b3480156103c957600080fd5b506102616103d8366004611d77565b6001600160e01b0319166000908152600080516020612434833981519152602052604090205460601c90565b34801561041057600080fd5b506101fe61041f366004611fe4565b610f91565b34801561043057600080fd5b5061019861043f366004611fe4565b61102c565b34801561045057600080fd5b5061019861045f366004611fe4565b61106e565b34801561047057600080fd5b5061019861047f366004611fe4565b6110b0565b600061048e61118d565b905090565b6001600160e01b0319811660009081527ffc606c433378e3a7e0a6a531deac289b66caa1b4aa8554fd4ab2c6f1570f92d8602052604081205460ff165b92915050565b6104de6111ee565b6001600160a01b0316336001600160a01b03161461050f57604051632f7a8ee160e01b815260040160405180910390fd5b61055961051c85876120d5565b8484848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061121692505050565b5050505050565b6105686111ee565b6001600160a01b0316336001600160a01b03161461059957604051632f7a8ee160e01b815260040160405180910390fd5b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b038316016105cc576105c833826113d2565b5050565b6105c8823383611465565b600061048e7f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc96546001600160a01b031690565b6106126111ee565b6001600160a01b0316336001600160a01b03161461064357604051632f7a8ee160e01b815260040160405180910390fd5b6000805160206123f48339815191525460ff1661067357604051632ca4452d60e11b815260040160405180910390fd5b61067b611557565b565b600080516020612414833981519152546060906000805160206124348339815191529061ffff1667ffffffffffffffff8111156106bc576106bc612041565b6040519080825280602002602001820160405280156106e5578160200160208202803683370190505b50915060008060005b600184015461ffff16821015610827576000818152600285016020526040812054905b600881101561081257836107248161221f565b600188015490955061ffff168511905061081257600581901b82901b6001600160e01b0319811660009081526020889052604081205460601c90805b888110156107b5578a818151811061077a5761077a612238565b60200260200101516001600160a01b0316836001600160a01b0316036107a357600191506107b5565b806107ad8161221f565b915050610760565b5080156107c457505050610800565b818a89815181106107d7576107d7612238565b6001600160a01b0390921660209283029190910190910152876107f98161221f565b9850505050505b8061080a8161221f565b915050610711565b5050808061081f9061221f565b9150506106ee565b505082525090565b600061048e6000805160206123f48339815191525460ff1690565b6108526115d4565b6001600160a01b0316336001600160a01b0316146108835760405163efd1052d60e01b815260040160405180910390fd5b61067b6115fc565b600080516020612414833981519152546060906000805160206124348339815191529061ffff1667ffffffffffffffff8111156108ca576108ca612041565b60405190808252806020026020018201604052801561091057816020015b6040805180820190915260008152606060208201528152602001906001900390816108e85790505b50600182015490925060009061ffff1667ffffffffffffffff81111561093857610938612041565b604051908082528060200260200182016040528015610961578160200160208202803683370190505b50905060008060005b600185015461ffff16821015610c50576000818152600286016020526040812054905b6008811015610c3b57836109a08161221f565b600189015490955061ffff1685119050610c3b57600581901b82901b6001600160e01b0319811660009081526020899052604081205460601c90805b88811015610af957826001600160a01b03168c8281518110610a0057610a00612238565b6020026020010151600001516001600160a01b031603610ae757838c8281518110610a2d57610a2d612238565b6020026020010151602001518b8381518110610a4b57610a4b612238565b602002602001015160ff1681518110610a6657610a66612238565b60200260200101906001600160e01b03191690816001600160e01b0319168152505060ff8a8281518110610a9c57610a9c612238565b602002602001015160ff1610610ab157600080fd5b898181518110610ac357610ac3612238565b602002602001018051809190610ad89061224e565b60ff1690525060019150610af9565b80610af18161221f565b9150506109dc565b508015610b0857505050610c29565b818b8981518110610b1b57610b1b612238565b60209081029190910101516001600160a01b03909116905260018a015461ffff1667ffffffffffffffff811115610b5457610b54612041565b604051908082528060200260200182016040528015610b7d578160200160208202803683370190505b508b8981518110610b9057610b90612238565b602002602001015160200181905250828b8981518110610bb257610bb2612238565b602002602001015160200151600081518110610bd057610bd0612238565b60200260200101906001600160e01b03191690816001600160e01b031916815250506001898981518110610c0657610c06612238565b60ff9092166020928302919091019091015287610c228161221f565b9850505050505b80610c338161221f565b91505061098d565b50508080610c489061221f565b91505061096a565b5060005b82811015610cb7576000848281518110610c7057610c70612238565b602002602001015160ff1690506000878381518110610c9157610c91612238565b602002602001015160200151905081815250508080610caf9061221f565b915050610c54565b508185525050505090565b610cca6111ee565b6001600160a01b0316336001600160a01b031614610cfb57604051632f7a8ee160e01b815260040160405180910390fd5b6000805160206123f48339815191525460ff1615610d2c576040516302ca8ced60e11b815260040160405180910390fd5b61067b611636565b600061048e6115d4565b600061048e6111ee565b60007f8135b9b8d3411dab68efe82c12999875113f270399aa3b0126860dde293ca8f35b546001600160a01b0316919050565b610d836111ee565b6001600160a01b0316336001600160a01b031614610db457604051632f7a8ee160e01b815260040160405180910390fd5b7f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc9680546001600160a01b0319166001600160a01b03831617905550565b50565b610dfc6111ee565b6001600160a01b0316336001600160a01b031614610e2d57604051632f7a8ee160e01b815260040160405180910390fd5b610df1816116b1565b600080516020612414833981519152546060906000805160206124348339815191529061ffff1667ffffffffffffffff811115610e7557610e75612041565b604051908082528060200260200182016040528015610e9e578160200160208202803683370190505b50915060008060005b600184015461ffff16821015610f87576000818152600285016020526040812054905b6008811015610f725783610edd8161221f565b600188015490955061ffff1685119050610f7257600581901b82901b6001600160e01b0319811660009081526020889052604090205460601c6001600160a01b038a1603610f5f5780888781518110610f3857610f38612238565b6001600160e01b03199092166020928302919091019091015285610f5b8161221f565b9650505b5080610f6a8161221f565b915050610eca565b50508080610f7f9061221f565b915050610ea7565b5050825250919050565b600073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03831601610fbf575047919050565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015611003573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104d0919061226d565b919050565b6110346111ee565b6001600160a01b0316336001600160a01b03161461106557604051632f7a8ee160e01b815260040160405180910390fd5b610df18161172b565b6110766111ee565b6001600160a01b0316336001600160a01b0316146110a757604051632f7a8ee160e01b815260040160405180910390fd5b610df18161176e565b6110b86111ee565b6001600160a01b0316336001600160a01b0316146110e957604051632f7a8ee160e01b815260040160405180910390fd5b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b0382160161111857610df133476113d2565b6040516370a0823160e01b8152306004820152610df190829033906001600160a01b038316906370a0823190602401602060405180830381865afa158015611164573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611188919061226d565b611465565b600080356001600160e01b0319168152600080516020612434833981519152602052604090205460601c806111eb57507f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc96546001600160a01b031690565b90565b60007f8a22373512790c48b83a1fe2efdd2888d4a917bcdc24d0adf63e60f671680460610d6c565b600080516020612414833981519152546000805160206124348339815191529061ffff8116908190600090600716156112615750600381901c60009081526002840160205260409020545b60005b875181101561134657600088828151811061128157611281612238565b602002602001015190506000816020015190508160400151516000036112ba5760405163eb6c3aeb60e01b815260040160405180910390fd5b60008160028111156112ce576112ce612286565b036112e9576112df878686856117d7565b909550935061133c565b60018160028111156112fd576112fd612286565b036113115761130c8783611916565b61133c565b600281600281111561132557611325612286565b0361133c5761133687868685611a5c565b90955093505b5050600101611264565b508282146113625760018401805461ffff191661ffff84161790555b600782161561138457600382901c600090815260028501602052604090208190555b7f8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb6738787876040516113b7939291906122ec565b60405180910390a16113c98686611c7f565b50505050505050565b604080516000808252602082019092526001600160a01b0384169083906040516113fc91906123b5565b60006040518083038185875af1925050503d8060008114611439576040519150601f19603f3d011682016040523d82523d6000602084013e61143e565b606091505b505090508061146057604051632e05b05360e21b815260040160405180910390fd5b505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916114c191906123b5565b6000604051808303816000865af19150503d80600081146114fe576040519150601f19603f3d011682016040523d82523d6000602084013e611503565b606091505b5091509150600082801561152f57508151158061152f57508180602001905181019061152f91906123d1565b90508061154f57604051632fdb1b7f60e11b815260040160405180910390fd5b505050505050565b6000805160206123f48339815191525460ff1661158757604051632ca4452d60e11b815260040160405180910390fd5b6000805160206123f4833981519152805460ff191690556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b60007f24aa1f7b31fd188a8d3ecfb06bc55c806040e59b03bd4396283442fce6617890610d6c565b611605336116b1565b7f24aa1f7b31fd188a8d3ecfb06bc55c806040e59b03bd4396283442fce661789080546001600160a01b0319169055565b6000805160206123f48339815191525460ff1615611667576040516302ca8ced60e11b815260040160405180910390fd5b6000805160206123f4833981519152805460ff191660011790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258906020016115ca565b7f8a22373512790c48b83a1fe2efdd2888d4a917bcdc24d0adf63e60f67168046080546040516001600160a01b038481169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a380546001600160a01b0319166001600160a01b0392909216919091179055565b7f24aa1f7b31fd188a8d3ecfb06bc55c806040e59b03bd4396283442fce661789080546001600160a01b0319166001600160a01b038316179055610df181818181565b7f8135b9b8d3411dab68efe82c12999875113f270399aa3b0126860dde293ca8f380546001600160a01b0319166001600160a01b0383169081179091556040517f0cc5437d7c9c1d9eab549acbb533eea3e9868e9443dd75309ed5820b33a3774e90600090a250565b805160009081906001600160a01b031630148015906117ff575082516001600160a01b03163b155b1561181d57604051633ddc5cab60e21b815260040160405180910390fd5b60005b8360400151518110156119095760008460400151828151811061184557611845612238565b6020908102919091018101516001600160e01b031981166000908152918a9052604090912054909150606081901c1561189157604051634923a77160e11b815260040160405180910390fd5b85516001600160e01b0319838116600081815260208d90526040902060609390931b6001600160601b0319168b1790925560058a901b60e090811692831c91831c199990991617978190036118fa57600389901c600090815260028b0160205260408120989098555b50505060019586019501611820565b5093959294509192505050565b80516001600160a01b03163b61193f57604051633ddc5cab60e21b815260040160405180910390fd5b60005b8160400151518110156114605760008260400151828151811061196757611967612238565b6020908102919091018101516001600160e01b03198116600090815291869052604090912054909150606081901c806119b3576040516337e25a9760e11b815260040160405180910390fd5b306001600160a01b038216036119dc5760405163e983573160e01b815260040160405180910390fd5b84600001516001600160a01b0316816001600160a01b031603611a12576040516330baabf360e11b815260040160405180910390fd5b5083516001600160e01b031992909216600090815260208690526040902060609290921b6001600160601b0319166bffffffffffffffffffffffff91909116179055600101611942565b805160009081906001600160a01b031615611a8a57604051633ab3490960e21b815260040160405180910390fd5b600385901c6007861660005b856040015151811015611c6b57600086604001518281518110611abb57611abb612238565b6020908102919091018101516001600160e01b031981166000908152918c9052604090912054909150606081901c611b06576040516337e25a9760e11b815260040160405180910390fd5b30606082901c03611b2a5760405163e983573160e01b815260040160405180910390fd5b6000899003611b5657600019909401600081815260028c01602052604090205498509360079350611b5e565b600019909301925b600584901b89901b6000806001600160e01b031980841690861614611bb5576001600160e01b03198316600090815260208f90526040902080546001600160601b0319166bffffffffffffffffffffffff86161790555b50506001600160e01b03198316600090815260208d90526040812055611fff600383901c1660e0600584901b16878214611c1857600082815260028f016020526040902080546001600160e01b031980841c19909116908516831c179055611c3c565b80836001600160e01b031916901c816001600160e01b031960001b901c198d16179b505b86600003611c5a57600088815260028f01602052604081208190559b505b505060019093019250611a96915050565b5060039190911b1796939550929350505050565b8051156001600160a01b0383161514611cab576040516326df4ccd60e01b815260040160405180910390fd5b6001600160a01b038216156105c8576001600160a01b0382163014611cf2576001600160a01b0382163b611cf257604051633ddc5cab60e21b815260040160405180910390fd5b6000826001600160a01b031682604051611d0c91906123b5565b600060405180830381855af49150503d8060008114611d47576040519150601f19603f3d011682016040523d82523d6000602084013e611d4c565b606091505b5050905080611460573d6000803e3d6000fd5b80356001600160e01b03198116811461102757600080fd5b600060208284031215611d8957600080fd5b611d9282611d5f565b9392505050565b80356001600160a01b038116811461102757600080fd5b60008083601f840112611dc257600080fd5b50813567ffffffffffffffff811115611dda57600080fd5b602083019150836020828501011115611df257600080fd5b9250929050565b600080600080600060608688031215611e1157600080fd5b853567ffffffffffffffff80821115611e2957600080fd5b818801915088601f830112611e3d57600080fd5b813581811115611e4c57600080fd5b8960208260051b8501011115611e6157600080fd5b60208301975080965050611e7760208901611d99565b94506040880135915080821115611e8d57600080fd5b50611e9a88828901611db0565b969995985093965092949392505050565b60008060408385031215611ebe57600080fd5b611ec783611d99565b946020939093013593505050565b6020808252825182820181905260009190848201906040850190845b81811015611f165783516001600160a01b031683529284019291840191600101611ef1565b50909695505050505050565b600081518084526020808501945080840160005b83811015611f5c5781516001600160e01b03191687529582019590820190600101611f36565b509495945050505050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b83811015611fd657888303603f19018552815180516001600160a01b03168452870151878401879052611fc387850182611f22565b9588019593505090860190600101611f8e565b509098975050505050505050565b600060208284031215611ff657600080fd5b611d9282611d99565b6020808252825182820181905260009190848201906040850190845b81811015611f165783516001600160e01b0319168352928401929184019160010161201b565b634e487b7160e01b600052604160045260246000fd5b6040516060810167ffffffffffffffff8111828210171561207a5761207a612041565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156120a9576120a9612041565b604052919050565b600067ffffffffffffffff8211156120cb576120cb612041565b5060051b60200190565b60006120e86120e3846120b1565b612080565b83815260208082019190600586811b86013681111561210657600080fd5b865b818110156121fc57803567ffffffffffffffff808211156121295760008081fd5b818a0191506060823603121561213f5760008081fd5b612147612057565b61215083611d99565b815286830135600381106121645760008081fd5b818801526040838101358381111561217c5760008081fd5b939093019236601f85011261219357600092508283fd5b833592506121a36120e3846120b1565b83815292871b840188019288810190368511156121c05760008081fd5b948901945b848610156121e5576121d686611d5f565b825294890194908901906121c5565b918301919091525088525050948301948301612108565b5092979650505050505050565b634e487b7160e01b600052601160045260246000fd5b60006001820161223157612231612209565b5060010190565b634e487b7160e01b600052603260045260246000fd5b600060ff821660ff810361226457612264612209565b60010192915050565b60006020828403121561227f57600080fd5b5051919050565b634e487b7160e01b600052602160045260246000fd5b60005b838110156122b757818101518382015260200161229f565b50506000910152565b600081518084526122d881602086016020860161229c565b601f01601f19169290920160200192915050565b6000606080830181845280875180835260808601915060808160051b87010192506020808a016000805b8481101561238557898703607f19018652825180516001600160a01b03168852848101516003811061235657634e487b7160e01b84526021600452602484fd5b8886015260409081015190880189905261237289890182611f22565b9750509483019491830191600101612316565b5050506001600160a01b03891690870152505083810360408501526123aa81866122c0565b979650505050505050565b600082516123c781846020870161229c565b9190910192915050565b6000602082840312156123e357600080fd5b81518015158114611d9257600080fdfe68721c0bbf2c02a4d65000340d1370666be06a630022208d4baa9bd7a4b6fea8177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc94177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc93a2646970667358221220751905fa7cd544137dff4ce7e9fc230c133b64991687e4362da02260e7634aaf64736f6c6343000813003300000000000000000000000070287bd7a8e1b6deb354b0df11130b3be03d1ece0000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x6080604052600436106101395760003560e01c80638ab5150a116100ab578063adfca15e1161006f578063adfca15e14610390578063cdffacc6146103bd578063eedc966a14610404578063f2fde38b14610424578063fb5b82d014610444578063fbacefce1461046457610140565b80638ab5150a146103115780638da5cb5b14610326578063913e77ad1461033b5780639142376514610350578063a89b11281461037057610140565b80633f4ba83a116100fd5780633f4ba83a1461027957806352ef6b2c1461028e5780635c975abb146102b057806379ba5097146102c55780637a0ed627146102da5780638456cb59146102fc57610140565b806301ffc9a71461019a578063093f0e27146101cf5780631f931c1c1461020c5780632c16f9261461022c5780632c4080591461024c57610140565b3661014057005b600061014a610484565b90506001600160a01b0381163b610174576040516321f27f0d60e21b815260040160405180910390fd5b3660008037600080366000845af43d6000803e808015610193573d6000f35b3d6000fd5b005b3480156101a657600080fd5b506101ba6101b5366004611d77565b610493565b60405190151581526020015b60405180910390f35b3480156101db57600080fd5b507f22ad9585a395edc8067b50da4778cafbb7fa2c4bbd7619fad6aeba403857fd745b6040519081526020016101c6565b34801561021857600080fd5b50610198610227366004611df9565b6104d6565b34801561023857600080fd5b50610198610247366004611eab565b610560565b34801561025857600080fd5b506102616105d7565b6040516001600160a01b0390911681526020016101c6565b34801561028557600080fd5b5061019861060a565b34801561029a57600080fd5b506102a361067d565b6040516101c69190611ed5565b3480156102bc57600080fd5b506101ba61082f565b3480156102d157600080fd5b5061019861084a565b3480156102e657600080fd5b506102ef61088b565b6040516101c69190611f67565b34801561030857600080fd5b50610198610cc2565b34801561031d57600080fd5b50610261610d34565b34801561033257600080fd5b50610261610d3e565b34801561034757600080fd5b50610261610d48565b34801561035c57600080fd5b5061019861036b366004611fe4565b610d7b565b34801561037c57600080fd5b5061019861038b366004611fe4565b610df4565b34801561039c57600080fd5b506103b06103ab366004611fe4565b610e36565b6040516101c69190611fff565b3480156103c957600080fd5b506102616103d8366004611d77565b6001600160e01b0319166000908152600080516020612434833981519152602052604090205460601c90565b34801561041057600080fd5b506101fe61041f366004611fe4565b610f91565b34801561043057600080fd5b5061019861043f366004611fe4565b61102c565b34801561045057600080fd5b5061019861045f366004611fe4565b61106e565b34801561047057600080fd5b5061019861047f366004611fe4565b6110b0565b600061048e61118d565b905090565b6001600160e01b0319811660009081527ffc606c433378e3a7e0a6a531deac289b66caa1b4aa8554fd4ab2c6f1570f92d8602052604081205460ff165b92915050565b6104de6111ee565b6001600160a01b0316336001600160a01b03161461050f57604051632f7a8ee160e01b815260040160405180910390fd5b61055961051c85876120d5565b8484848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061121692505050565b5050505050565b6105686111ee565b6001600160a01b0316336001600160a01b03161461059957604051632f7a8ee160e01b815260040160405180910390fd5b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b038316016105cc576105c833826113d2565b5050565b6105c8823383611465565b600061048e7f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc96546001600160a01b031690565b6106126111ee565b6001600160a01b0316336001600160a01b03161461064357604051632f7a8ee160e01b815260040160405180910390fd5b6000805160206123f48339815191525460ff1661067357604051632ca4452d60e11b815260040160405180910390fd5b61067b611557565b565b600080516020612414833981519152546060906000805160206124348339815191529061ffff1667ffffffffffffffff8111156106bc576106bc612041565b6040519080825280602002602001820160405280156106e5578160200160208202803683370190505b50915060008060005b600184015461ffff16821015610827576000818152600285016020526040812054905b600881101561081257836107248161221f565b600188015490955061ffff168511905061081257600581901b82901b6001600160e01b0319811660009081526020889052604081205460601c90805b888110156107b5578a818151811061077a5761077a612238565b60200260200101516001600160a01b0316836001600160a01b0316036107a357600191506107b5565b806107ad8161221f565b915050610760565b5080156107c457505050610800565b818a89815181106107d7576107d7612238565b6001600160a01b0390921660209283029190910190910152876107f98161221f565b9850505050505b8061080a8161221f565b915050610711565b5050808061081f9061221f565b9150506106ee565b505082525090565b600061048e6000805160206123f48339815191525460ff1690565b6108526115d4565b6001600160a01b0316336001600160a01b0316146108835760405163efd1052d60e01b815260040160405180910390fd5b61067b6115fc565b600080516020612414833981519152546060906000805160206124348339815191529061ffff1667ffffffffffffffff8111156108ca576108ca612041565b60405190808252806020026020018201604052801561091057816020015b6040805180820190915260008152606060208201528152602001906001900390816108e85790505b50600182015490925060009061ffff1667ffffffffffffffff81111561093857610938612041565b604051908082528060200260200182016040528015610961578160200160208202803683370190505b50905060008060005b600185015461ffff16821015610c50576000818152600286016020526040812054905b6008811015610c3b57836109a08161221f565b600189015490955061ffff1685119050610c3b57600581901b82901b6001600160e01b0319811660009081526020899052604081205460601c90805b88811015610af957826001600160a01b03168c8281518110610a0057610a00612238565b6020026020010151600001516001600160a01b031603610ae757838c8281518110610a2d57610a2d612238565b6020026020010151602001518b8381518110610a4b57610a4b612238565b602002602001015160ff1681518110610a6657610a66612238565b60200260200101906001600160e01b03191690816001600160e01b0319168152505060ff8a8281518110610a9c57610a9c612238565b602002602001015160ff1610610ab157600080fd5b898181518110610ac357610ac3612238565b602002602001018051809190610ad89061224e565b60ff1690525060019150610af9565b80610af18161221f565b9150506109dc565b508015610b0857505050610c29565b818b8981518110610b1b57610b1b612238565b60209081029190910101516001600160a01b03909116905260018a015461ffff1667ffffffffffffffff811115610b5457610b54612041565b604051908082528060200260200182016040528015610b7d578160200160208202803683370190505b508b8981518110610b9057610b90612238565b602002602001015160200181905250828b8981518110610bb257610bb2612238565b602002602001015160200151600081518110610bd057610bd0612238565b60200260200101906001600160e01b03191690816001600160e01b031916815250506001898981518110610c0657610c06612238565b60ff9092166020928302919091019091015287610c228161221f565b9850505050505b80610c338161221f565b91505061098d565b50508080610c489061221f565b91505061096a565b5060005b82811015610cb7576000848281518110610c7057610c70612238565b602002602001015160ff1690506000878381518110610c9157610c91612238565b602002602001015160200151905081815250508080610caf9061221f565b915050610c54565b508185525050505090565b610cca6111ee565b6001600160a01b0316336001600160a01b031614610cfb57604051632f7a8ee160e01b815260040160405180910390fd5b6000805160206123f48339815191525460ff1615610d2c576040516302ca8ced60e11b815260040160405180910390fd5b61067b611636565b600061048e6115d4565b600061048e6111ee565b60007f8135b9b8d3411dab68efe82c12999875113f270399aa3b0126860dde293ca8f35b546001600160a01b0316919050565b610d836111ee565b6001600160a01b0316336001600160a01b031614610db457604051632f7a8ee160e01b815260040160405180910390fd5b7f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc9680546001600160a01b0319166001600160a01b03831617905550565b50565b610dfc6111ee565b6001600160a01b0316336001600160a01b031614610e2d57604051632f7a8ee160e01b815260040160405180910390fd5b610df1816116b1565b600080516020612414833981519152546060906000805160206124348339815191529061ffff1667ffffffffffffffff811115610e7557610e75612041565b604051908082528060200260200182016040528015610e9e578160200160208202803683370190505b50915060008060005b600184015461ffff16821015610f87576000818152600285016020526040812054905b6008811015610f725783610edd8161221f565b600188015490955061ffff1685119050610f7257600581901b82901b6001600160e01b0319811660009081526020889052604090205460601c6001600160a01b038a1603610f5f5780888781518110610f3857610f38612238565b6001600160e01b03199092166020928302919091019091015285610f5b8161221f565b9650505b5080610f6a8161221f565b915050610eca565b50508080610f7f9061221f565b915050610ea7565b5050825250919050565b600073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03831601610fbf575047919050565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015611003573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104d0919061226d565b919050565b6110346111ee565b6001600160a01b0316336001600160a01b03161461106557604051632f7a8ee160e01b815260040160405180910390fd5b610df18161172b565b6110766111ee565b6001600160a01b0316336001600160a01b0316146110a757604051632f7a8ee160e01b815260040160405180910390fd5b610df18161176e565b6110b86111ee565b6001600160a01b0316336001600160a01b0316146110e957604051632f7a8ee160e01b815260040160405180910390fd5b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b0382160161111857610df133476113d2565b6040516370a0823160e01b8152306004820152610df190829033906001600160a01b038316906370a0823190602401602060405180830381865afa158015611164573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611188919061226d565b611465565b600080356001600160e01b0319168152600080516020612434833981519152602052604090205460601c806111eb57507f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc96546001600160a01b031690565b90565b60007f8a22373512790c48b83a1fe2efdd2888d4a917bcdc24d0adf63e60f671680460610d6c565b600080516020612414833981519152546000805160206124348339815191529061ffff8116908190600090600716156112615750600381901c60009081526002840160205260409020545b60005b875181101561134657600088828151811061128157611281612238565b602002602001015190506000816020015190508160400151516000036112ba5760405163eb6c3aeb60e01b815260040160405180910390fd5b60008160028111156112ce576112ce612286565b036112e9576112df878686856117d7565b909550935061133c565b60018160028111156112fd576112fd612286565b036113115761130c8783611916565b61133c565b600281600281111561132557611325612286565b0361133c5761133687868685611a5c565b90955093505b5050600101611264565b508282146113625760018401805461ffff191661ffff84161790555b600782161561138457600382901c600090815260028501602052604090208190555b7f8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb6738787876040516113b7939291906122ec565b60405180910390a16113c98686611c7f565b50505050505050565b604080516000808252602082019092526001600160a01b0384169083906040516113fc91906123b5565b60006040518083038185875af1925050503d8060008114611439576040519150601f19603f3d011682016040523d82523d6000602084013e61143e565b606091505b505090508061146057604051632e05b05360e21b815260040160405180910390fd5b505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916114c191906123b5565b6000604051808303816000865af19150503d80600081146114fe576040519150601f19603f3d011682016040523d82523d6000602084013e611503565b606091505b5091509150600082801561152f57508151158061152f57508180602001905181019061152f91906123d1565b90508061154f57604051632fdb1b7f60e11b815260040160405180910390fd5b505050505050565b6000805160206123f48339815191525460ff1661158757604051632ca4452d60e11b815260040160405180910390fd5b6000805160206123f4833981519152805460ff191690556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b60007f24aa1f7b31fd188a8d3ecfb06bc55c806040e59b03bd4396283442fce6617890610d6c565b611605336116b1565b7f24aa1f7b31fd188a8d3ecfb06bc55c806040e59b03bd4396283442fce661789080546001600160a01b0319169055565b6000805160206123f48339815191525460ff1615611667576040516302ca8ced60e11b815260040160405180910390fd5b6000805160206123f4833981519152805460ff191660011790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258906020016115ca565b7f8a22373512790c48b83a1fe2efdd2888d4a917bcdc24d0adf63e60f67168046080546040516001600160a01b038481169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a380546001600160a01b0319166001600160a01b0392909216919091179055565b7f24aa1f7b31fd188a8d3ecfb06bc55c806040e59b03bd4396283442fce661789080546001600160a01b0319166001600160a01b038316179055610df181818181565b7f8135b9b8d3411dab68efe82c12999875113f270399aa3b0126860dde293ca8f380546001600160a01b0319166001600160a01b0383169081179091556040517f0cc5437d7c9c1d9eab549acbb533eea3e9868e9443dd75309ed5820b33a3774e90600090a250565b805160009081906001600160a01b031630148015906117ff575082516001600160a01b03163b155b1561181d57604051633ddc5cab60e21b815260040160405180910390fd5b60005b8360400151518110156119095760008460400151828151811061184557611845612238565b6020908102919091018101516001600160e01b031981166000908152918a9052604090912054909150606081901c1561189157604051634923a77160e11b815260040160405180910390fd5b85516001600160e01b0319838116600081815260208d90526040902060609390931b6001600160601b0319168b1790925560058a901b60e090811692831c91831c199990991617978190036118fa57600389901c600090815260028b0160205260408120989098555b50505060019586019501611820565b5093959294509192505050565b80516001600160a01b03163b61193f57604051633ddc5cab60e21b815260040160405180910390fd5b60005b8160400151518110156114605760008260400151828151811061196757611967612238565b6020908102919091018101516001600160e01b03198116600090815291869052604090912054909150606081901c806119b3576040516337e25a9760e11b815260040160405180910390fd5b306001600160a01b038216036119dc5760405163e983573160e01b815260040160405180910390fd5b84600001516001600160a01b0316816001600160a01b031603611a12576040516330baabf360e11b815260040160405180910390fd5b5083516001600160e01b031992909216600090815260208690526040902060609290921b6001600160601b0319166bffffffffffffffffffffffff91909116179055600101611942565b805160009081906001600160a01b031615611a8a57604051633ab3490960e21b815260040160405180910390fd5b600385901c6007861660005b856040015151811015611c6b57600086604001518281518110611abb57611abb612238565b6020908102919091018101516001600160e01b031981166000908152918c9052604090912054909150606081901c611b06576040516337e25a9760e11b815260040160405180910390fd5b30606082901c03611b2a5760405163e983573160e01b815260040160405180910390fd5b6000899003611b5657600019909401600081815260028c01602052604090205498509360079350611b5e565b600019909301925b600584901b89901b6000806001600160e01b031980841690861614611bb5576001600160e01b03198316600090815260208f90526040902080546001600160601b0319166bffffffffffffffffffffffff86161790555b50506001600160e01b03198316600090815260208d90526040812055611fff600383901c1660e0600584901b16878214611c1857600082815260028f016020526040902080546001600160e01b031980841c19909116908516831c179055611c3c565b80836001600160e01b031916901c816001600160e01b031960001b901c198d16179b505b86600003611c5a57600088815260028f01602052604081208190559b505b505060019093019250611a96915050565b5060039190911b1796939550929350505050565b8051156001600160a01b0383161514611cab576040516326df4ccd60e01b815260040160405180910390fd5b6001600160a01b038216156105c8576001600160a01b0382163014611cf2576001600160a01b0382163b611cf257604051633ddc5cab60e21b815260040160405180910390fd5b6000826001600160a01b031682604051611d0c91906123b5565b600060405180830381855af49150503d8060008114611d47576040519150601f19603f3d011682016040523d82523d6000602084013e611d4c565b606091505b5050905080611460573d6000803e3d6000fd5b80356001600160e01b03198116811461102757600080fd5b600060208284031215611d8957600080fd5b611d9282611d5f565b9392505050565b80356001600160a01b038116811461102757600080fd5b60008083601f840112611dc257600080fd5b50813567ffffffffffffffff811115611dda57600080fd5b602083019150836020828501011115611df257600080fd5b9250929050565b600080600080600060608688031215611e1157600080fd5b853567ffffffffffffffff80821115611e2957600080fd5b818801915088601f830112611e3d57600080fd5b813581811115611e4c57600080fd5b8960208260051b8501011115611e6157600080fd5b60208301975080965050611e7760208901611d99565b94506040880135915080821115611e8d57600080fd5b50611e9a88828901611db0565b969995985093965092949392505050565b60008060408385031215611ebe57600080fd5b611ec783611d99565b946020939093013593505050565b6020808252825182820181905260009190848201906040850190845b81811015611f165783516001600160a01b031683529284019291840191600101611ef1565b50909695505050505050565b600081518084526020808501945080840160005b83811015611f5c5781516001600160e01b03191687529582019590820190600101611f36565b509495945050505050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b83811015611fd657888303603f19018552815180516001600160a01b03168452870151878401879052611fc387850182611f22565b9588019593505090860190600101611f8e565b509098975050505050505050565b600060208284031215611ff657600080fd5b611d9282611d99565b6020808252825182820181905260009190848201906040850190845b81811015611f165783516001600160e01b0319168352928401929184019160010161201b565b634e487b7160e01b600052604160045260246000fd5b6040516060810167ffffffffffffffff8111828210171561207a5761207a612041565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156120a9576120a9612041565b604052919050565b600067ffffffffffffffff8211156120cb576120cb612041565b5060051b60200190565b60006120e86120e3846120b1565b612080565b83815260208082019190600586811b86013681111561210657600080fd5b865b818110156121fc57803567ffffffffffffffff808211156121295760008081fd5b818a0191506060823603121561213f5760008081fd5b612147612057565b61215083611d99565b815286830135600381106121645760008081fd5b818801526040838101358381111561217c5760008081fd5b939093019236601f85011261219357600092508283fd5b833592506121a36120e3846120b1565b83815292871b840188019288810190368511156121c05760008081fd5b948901945b848610156121e5576121d686611d5f565b825294890194908901906121c5565b918301919091525088525050948301948301612108565b5092979650505050505050565b634e487b7160e01b600052601160045260246000fd5b60006001820161223157612231612209565b5060010190565b634e487b7160e01b600052603260045260246000fd5b600060ff821660ff810361226457612264612209565b60010192915050565b60006020828403121561227f57600080fd5b5051919050565b634e487b7160e01b600052602160045260246000fd5b60005b838110156122b757818101518382015260200161229f565b50506000910152565b600081518084526122d881602086016020860161229c565b601f01601f19169290920160200192915050565b6000606080830181845280875180835260808601915060808160051b87010192506020808a016000805b8481101561238557898703607f19018652825180516001600160a01b03168852848101516003811061235657634e487b7160e01b84526021600452602484fd5b8886015260409081015190880189905261237289890182611f22565b9750509483019491830191600101612316565b5050506001600160a01b03891690870152505083810360408501526123aa81866122c0565b979650505050505050565b600082516123c781846020870161229c565b9190910192915050565b6000602082840312156123e357600080fd5b81518015158114611d9257600080fdfe68721c0bbf2c02a4d65000340d1370666be06a630022208d4baa9bd7a4b6fea8177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc94177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc93a2646970667358221220751905fa7cd544137dff4ce7e9fc230c133b64991687e4362da02260e7634aaf64736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000070287bd7a8e1b6deb354b0df11130b3be03d1ece0000000000000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _collector (address): 0x70287bd7A8e1b6deb354b0dF11130b3be03D1Ece
Arg [1] : _owner (address): 0x0000000000000000000000000000000000000000
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 00000000000000000000000070287bd7a8e1b6deb354b0df11130b3be03d1ece
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.