// SPDX-License-Identifier: MITpragmasolidity ^0.8.8;import { UintUtils } from'./UintUtils.sol';
libraryAddressUtils{
usingUintUtilsforuint256;
errorAddressUtils__InsufficientBalance();
errorAddressUtils__NotContract();
errorAddressUtils__SendValueFailed();
functiontoString(address account) internalpurereturns (stringmemory) {
returnuint256(uint160(account)).toHexString(20);
}
functionisContract(address account) internalviewreturns (bool) {
uint256 size;
assembly {
size :=extcodesize(account)
}
return size >0;
}
functionsendValue(addresspayable account, uint256 amount) internal{
(bool success, ) = account.call{ value: amount }('');
if (!success) revert AddressUtils__SendValueFailed();
}
functionfunctionCall(address target,
bytesmemory data
) internalreturns (bytesmemory) {
return
functionCall(target, data, 'AddressUtils: failed low-level call');
}
functionfunctionCall(address target,
bytesmemory data,
stringmemoryerror) internalreturns (bytesmemory) {
return _functionCallWithValue(target, data, 0, error);
}
functionfunctionCallWithValue(address target,
bytesmemory data,
uint256 value
) internalreturns (bytesmemory) {
return
functionCallWithValue(
target,
data,
value,
'AddressUtils: failed low-level call with value'
);
}
functionfunctionCallWithValue(address target,
bytesmemory data,
uint256 value,
stringmemoryerror) internalreturns (bytesmemory) {
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
*/functionexcessivelySafeCall(address target,
uint256 gasAmount,
uint256 value,
uint16 maxCopy,
bytesmemory data
) internalreturns (bool success, bytesmemory returnData) {
returnData =newbytes(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 copylet toCopy :=returndatasize()
ifgt(toCopy, maxCopy) {
toCopy := maxCopy
}
// store the length of the copied bytesmstore(returnData, toCopy)
// copy the bytes from returndata[0:toCopy]returndatacopy(add(returnData, 0x20), 0, toCopy)
}
}
function_functionCallWithValue(address target,
bytesmemory data,
uint256 value,
stringmemoryerror) privatereturns (bytesmemory) {
if (!isContract(target)) revert AddressUtils__NotContract();
(bool success, bytesmemory returnData) = target.call{ value: value }(
data
);
if (success) {
return returnData;
} elseif (returnData.length>0) {
assembly {
let returnData_size :=mload(returnData)
revert(add(32, returnData), returnData_size)
}
} else {
revert(error);
}
}
}
Contract Source Code
File 2 of 49: Constants.sol
// SPDX-License-Identifier: AGPL-3.0-onlypragmasolidity 0.8.19;/**
* @dev The default token decimals value
*/uint256constant DECIMALS_DEFAULT =18;
/**
* @dev The maximum uint256 value for swap amount limit settings
*/uint256constant INFINITY =type(uint256).max;
/**
* @dev The default limit of account list size
*/uint256constant LIST_SIZE_LIMIT_DEFAULT =100;
/**
* @dev The limit of swap router list size
*/uint256constant LIST_SIZE_LIMIT_ROUTERS =200;
/**
* @dev The factor for percentage settings. Example: 100 is 0.1%
*/uint256constant MILLIPERCENT_FACTOR =100_000;
/**
* @dev The de facto standard address to denote the native token
*/addressconstant NATIVE_TOKEN_ADDRESS =0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
// SPDX-License-Identifier: MITpragmasolidity ^0.8.8;import { IERC165BaseInternal } from'./IERC165BaseInternal.sol';
import { ERC165BaseStorage } from'./ERC165BaseStorage.sol';
/**
* @title ERC165 implementation
*/abstractcontractERC165BaseInternalisIERC165BaseInternal{
/**
* @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
) internalviewvirtualreturns (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
) internalvirtual{
if (interfaceId ==0xffffffff) revert ERC165Base__InvalidInterfaceId();
ERC165BaseStorage.layout().supportedInterfaces[interfaceId] = status;
}
}
// SPDX-License-Identifier: MITpragmasolidity ^0.8.8;import { IDiamondBase } from'../base/IDiamondBase.sol';
interfaceIDiamondFallbackisIDiamondBase{
/**
* @notice query the address of the fallback implementation
* @return fallbackAddress address of fallback implementation
*/functiongetFallbackAddress()
externalviewreturns (address fallbackAddress);
/**
* @notice set the address of the fallback implementation
* @param fallbackAddress address of fallback implementation
*/functionsetFallbackAddress(address fallbackAddress) external;
}
Contract Source Code
File 14 of 49: IDiamondReadable.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.8;/**
* @title Diamond proxy introspection interface
* @dev see https://eips.ethereum.org/EIPS/eip-2535
*/interfaceIDiamondReadable{
structFacet {
address target;
bytes4[] selectors;
}
/**
* @notice get all facets and their selectors
* @return diamondFacets array of structured facet data
*/functionfacets() externalviewreturns (Facet[] memory diamondFacets);
/**
* @notice get all selectors for given facet address
* @param facet address of facet to query
* @return selectors array of function selectors
*/functionfacetFunctionSelectors(address facet
) externalviewreturns (bytes4[] memory selectors);
/**
* @notice get addresses of all facets used by diamond
* @return addresses array of facet addresses
*/functionfacetAddresses()
externalviewreturns (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)
*/functionfacetAddress(bytes4 selector
) externalviewreturns (address facet);
}
Contract Source Code
File 15 of 49: IDiamondWritable.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.8;import { IDiamondWritableInternal } from'./IDiamondWritableInternal.sol';
/**
* @title Diamond proxy upgrade interface
* @dev see https://eips.ethereum.org/EIPS/eip-2535
*/interfaceIDiamondWritableisIDiamondWritableInternal{
/**
* @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
*/functiondiamondCut(
FacetCut[] calldata facetCuts,
address target,
bytescalldata data
) external;
}
// SPDX-License-Identifier: AGPL-3.0-onlypragmasolidity 0.8.19;/**
* @title ITokenBalance
* @notice Token balance interface
*/interfaceITokenBalance{
/**
* @notice Getter of the token balance by the account
* @param _account The account address
* @return Token balance
*/functionbalanceOf(address _account) externalviewreturns (uint256);
}
Contract Source Code
File 33 of 49: OFTWrapperDiamond.sol
// SPDX-License-Identifier: AGPL-3.0-onlypragmasolidity 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'asTransferHelper;
import'../../Constants.sol'asConstants;
/**
* @title OFTWrapperDiamond
* @notice The OFT wrapper diamond contract
*/contractOFTWrapperDiamondisSolidStateDiamond, Pausable, ReentrancyGuard{
/**
* @notice Emitted when the address of the collector is set
* @param collector The address of the collector
*/eventSetCollector(addressindexed collector);
uint256privateconstant 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
*/functionsetCollector(address _collector) externalonlyOwner{
_setCollector(_collector);
}
/**
* @notice Enter pause state
*/functionpause() externalonlyOwnerwhenNotPaused{
_pause();
}
/**
* @notice Exit pause state
*/functionunpause() externalonlyOwnerwhenPaused{
_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
*/functionforceTransferOwnership(address _newOwner) externalonlyOwner{
_setOwner(_newOwner);
}
/**
* @notice Performs the token cleanup
* @dev Use the "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE" address for the native token
* @param _tokenAddress The address of the token
*/functioncleanup(address _tokenAddress) externalonlyOwner{
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
*/functioncleanupWithAmount(address _tokenAddress, uint256 _tokenAmount) externalonlyOwner{
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
*/functiontokenBalance(address _tokenAddress) externalviewreturns (uint256) {
if (_tokenAddress == Constants.NATIVE_TOKEN_ADDRESS) {
returnaddress(this).balance;
} else {
return ITokenBalance(_tokenAddress).balanceOf(address(this));
}
}
/**
* @notice Getter of the address of the collector
* @return The address of the collector
*/functioncollector() externalviewreturns (address) {
return OFTWrapperStorage.layout().collector;
}
/**
* @notice Getter of the system version identifier
* @return The system version identifier
*/functionSYSTEM_VERSION_ID() externalpurereturns (uint256) {
return SYSTEM_VERSION_ID_INTERNAL;
}
function_setCollector(address _collector) private{
OFTWrapperStorage.layout().collector = _collector;
emit SetCollector(_collector);
}
function_initOFTWrapperDiamond() private{
bytes4[] memory selectors =newbytes4[](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), '');
}
}