Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00| Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 3055765 | 179 days ago | Contract Creation | 0 ETH |
Cross-Chain Transactions
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
DexManagerFacet
Compiler Version
v0.8.29+commit.ab55807c
Optimization Enabled:
Yes with 1000000 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import { LibDiamond } from "../Libraries/LibDiamond.sol";
import { LibAccess } from "../Libraries/LibAccess.sol";
import { LibAllowList } from "../Libraries/LibAllowList.sol";
import { CannotAuthoriseSelf } from "../Errors/GenericErrors.sol";
/// @title Dex Manager Facet
/// @author LI.FI (https://li.fi)
/// @notice Facet contract for managing approved DEXs to be used in swaps.
/// @custom:version 1.0.2
contract DexManagerFacet {
/// Events ///
event DexAdded(address indexed dexAddress);
event DexRemoved(address indexed dexAddress);
event FunctionSignatureApprovalChanged(
bytes4 indexed functionSignature,
bool indexed approved
);
/// External Methods ///
/// @notice Register the address of a DEX contract to be approved for swapping.
/// @param _dex The address of the DEX contract to be approved.
function addDex(address _dex) external {
if (msg.sender != LibDiamond.contractOwner()) {
LibAccess.enforceAccessControl();
}
LibAllowList.addAllowedContract(_dex);
emit DexAdded(_dex);
}
/// @notice Batch register the address of DEX contracts to be approved for swapping.
/// @param _dexs The addresses of the DEX contracts to be approved.
function batchAddDex(address[] calldata _dexs) external {
if (msg.sender != LibDiamond.contractOwner()) {
LibAccess.enforceAccessControl();
}
uint256 length = _dexs.length;
for (uint256 i = 0; i < length; ) {
address dex = _dexs[i];
if (dex == address(this)) {
revert CannotAuthoriseSelf();
}
if (LibAllowList.contractIsAllowed(dex)) {
unchecked {
++i;
}
continue;
}
LibAllowList.addAllowedContract(dex);
emit DexAdded(dex);
unchecked {
++i;
}
}
}
/// @notice Unregister the address of a DEX contract approved for swapping.
/// @param _dex The address of the DEX contract to be unregistered.
function removeDex(address _dex) external {
if (msg.sender != LibDiamond.contractOwner()) {
LibAccess.enforceAccessControl();
}
LibAllowList.removeAllowedContract(_dex);
emit DexRemoved(_dex);
}
/// @notice Batch unregister the addresses of DEX contracts approved for swapping.
/// @param _dexs The addresses of the DEX contracts to be unregistered.
function batchRemoveDex(address[] calldata _dexs) external {
if (msg.sender != LibDiamond.contractOwner()) {
LibAccess.enforceAccessControl();
}
uint256 length = _dexs.length;
for (uint256 i = 0; i < length; ) {
LibAllowList.removeAllowedContract(_dexs[i]);
emit DexRemoved(_dexs[i]);
unchecked {
++i;
}
}
}
/// @notice Adds/removes a specific function signature to/from the allowlist
/// @param _signature the function signature to allow/disallow
/// @param _approval whether the function signature should be allowed
function setFunctionApprovalBySignature(
bytes4 _signature,
bool _approval
) external {
if (msg.sender != LibDiamond.contractOwner()) {
LibAccess.enforceAccessControl();
}
if (_approval) {
LibAllowList.addAllowedSelector(_signature);
} else {
LibAllowList.removeAllowedSelector(_signature);
}
emit FunctionSignatureApprovalChanged(_signature, _approval);
}
/// @notice Batch Adds/removes a specific function signature to/from the allowlist
/// @param _signatures the function signatures to allow/disallow
/// @param _approval whether the function signatures should be allowed
function batchSetFunctionApprovalBySignature(
bytes4[] calldata _signatures,
bool _approval
) external {
if (msg.sender != LibDiamond.contractOwner()) {
LibAccess.enforceAccessControl();
}
uint256 length = _signatures.length;
for (uint256 i = 0; i < length; ) {
bytes4 _signature = _signatures[i];
if (_approval) {
LibAllowList.addAllowedSelector(_signature);
} else {
LibAllowList.removeAllowedSelector(_signature);
}
emit FunctionSignatureApprovalChanged(_signature, _approval);
unchecked {
++i;
}
}
}
/// @notice Returns whether a function signature is approved
/// @param _signature the function signature to query
/// @return approved Approved or not
function isFunctionApproved(
bytes4 _signature
) public view returns (bool approved) {
return LibAllowList.selectorIsAllowed(_signature);
}
/// @notice Returns a list of all approved DEX addresses.
/// @return addresses List of approved DEX addresses
function approvedDexs()
external
view
returns (address[] memory addresses)
{
return LibAllowList.getAllowedContracts();
}
}// SPDX-License-Identifier: MIT /// @custom:version 1.0.1 pragma solidity ^0.8.17; error AlreadyInitialized(); error CannotAuthoriseSelf(); error CannotBridgeToSameNetwork(); error ContractCallNotAllowed(); error CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount); error DiamondIsPaused(); error ETHTransferFailed(); error ExternalCallFailed(); error FunctionDoesNotExist(); error InformationMismatch(); error InsufficientBalance(uint256 required, uint256 balance); error InvalidAmount(); error InvalidCallData(); error InvalidConfig(); error InvalidContract(); error InvalidDestinationChain(); error InvalidFallbackAddress(); error InvalidReceiver(); error InvalidSendingToken(); error NativeAssetNotSupported(); error NativeAssetTransferFailed(); error NoSwapDataProvided(); error NoSwapFromZeroBalance(); error NotAContract(); error NotInitialized(); error NoTransferToNullAddress(); error NullAddrIsNotAnERC20Token(); error NullAddrIsNotAValidSpender(); error OnlyContractOwner(); error RecoveryAddressCannotBeZero(); error ReentrancyError(); error TokenNotSupported(); error TransferFromFailed(); error UnAuthorized(); error UnsupportedChainId(uint256 chainId); error WithdrawFailed(); error ZeroAmount();
// SPDX-License-Identifier: MIT
/// @custom:version 1.0.0
pragma solidity ^0.8.17;
import { CannotAuthoriseSelf, UnAuthorized } from "../Errors/GenericErrors.sol";
/// @title Access Library
/// @author LI.FI (https://li.fi)
/// @notice Provides functionality for managing method level access control
library LibAccess {
/// Types ///
bytes32 internal constant NAMESPACE =
keccak256("com.lifi.library.access.management");
/// Storage ///
struct AccessStorage {
mapping(bytes4 => mapping(address => bool)) execAccess;
}
/// Events ///
event AccessGranted(address indexed account, bytes4 indexed method);
event AccessRevoked(address indexed account, bytes4 indexed method);
/// @dev Fetch local storage
function accessStorage()
internal
pure
returns (AccessStorage storage accStor)
{
bytes32 position = NAMESPACE;
// solhint-disable-next-line no-inline-assembly
assembly {
accStor.slot := position
}
}
/// @notice Gives an address permission to execute a method
/// @param selector The method selector to execute
/// @param executor The address to grant permission to
function addAccess(bytes4 selector, address executor) internal {
if (executor == address(this)) {
revert CannotAuthoriseSelf();
}
AccessStorage storage accStor = accessStorage();
accStor.execAccess[selector][executor] = true;
emit AccessGranted(executor, selector);
}
/// @notice Revokes permission to execute a method
/// @param selector The method selector to execute
/// @param executor The address to revoke permission from
function removeAccess(bytes4 selector, address executor) internal {
AccessStorage storage accStor = accessStorage();
accStor.execAccess[selector][executor] = false;
emit AccessRevoked(executor, selector);
}
/// @notice Enforces access control by reverting if `msg.sender`
/// has not been given permission to execute `msg.sig`
function enforceAccessControl() internal view {
AccessStorage storage accStor = accessStorage();
if (accStor.execAccess[msg.sig][msg.sender] != true)
revert UnAuthorized();
}
}// SPDX-License-Identifier: MIT
/// @custom:version 1.0.0
pragma solidity ^0.8.17;
import { InvalidContract } from "../Errors/GenericErrors.sol";
/// @title Lib Allow List
/// @author LI.FI (https://li.fi)
/// @notice Library for managing and accessing the conract address allow list
library LibAllowList {
/// Storage ///
bytes32 internal constant NAMESPACE =
keccak256("com.lifi.library.allow.list");
struct AllowListStorage {
mapping(address => bool) allowlist;
mapping(bytes4 => bool) selectorAllowList;
address[] contracts;
}
/// @dev Adds a contract address to the allow list
/// @param _contract the contract address to add
function addAllowedContract(address _contract) internal {
_checkAddress(_contract);
AllowListStorage storage als = _getStorage();
if (als.allowlist[_contract]) return;
als.allowlist[_contract] = true;
als.contracts.push(_contract);
}
/// @dev Checks whether a contract address has been added to the allow list
/// @param _contract the contract address to check
function contractIsAllowed(
address _contract
) internal view returns (bool) {
return _getStorage().allowlist[_contract];
}
/// @dev Remove a contract address from the allow list
/// @param _contract the contract address to remove
function removeAllowedContract(address _contract) internal {
AllowListStorage storage als = _getStorage();
if (!als.allowlist[_contract]) {
return;
}
als.allowlist[_contract] = false;
uint256 length = als.contracts.length;
// Find the contract in the list
for (uint256 i = 0; i < length; i++) {
if (als.contracts[i] == _contract) {
// Move the last element into the place to delete
als.contracts[i] = als.contracts[length - 1];
// Remove the last element
als.contracts.pop();
break;
}
}
}
/// @dev Fetch contract addresses from the allow list
function getAllowedContracts() internal view returns (address[] memory) {
return _getStorage().contracts;
}
/// @dev Add a selector to the allow list
/// @param _selector the selector to add
function addAllowedSelector(bytes4 _selector) internal {
_getStorage().selectorAllowList[_selector] = true;
}
/// @dev Removes a selector from the allow list
/// @param _selector the selector to remove
function removeAllowedSelector(bytes4 _selector) internal {
_getStorage().selectorAllowList[_selector] = false;
}
/// @dev Returns if selector has been added to the allow list
/// @param _selector the selector to check
function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {
return _getStorage().selectorAllowList[_selector];
}
/// @dev Fetch local storage struct
function _getStorage()
internal
pure
returns (AllowListStorage storage als)
{
bytes32 position = NAMESPACE;
// solhint-disable-next-line no-inline-assembly
assembly {
als.slot := position
}
}
/// @dev Contains business logic for validating a contract address.
/// @param _contract address of the dex to check
function _checkAddress(address _contract) private view {
if (_contract == address(0)) revert InvalidContract();
if (_contract.code.length == 0) revert InvalidContract();
}
}// SPDX-License-Identifier: MIT
/// @custom:version 1.0.0
pragma solidity ^0.8.17;
library LibBytes {
// solhint-disable no-inline-assembly
// LibBytes specific errors
error SliceOverflow();
error SliceOutOfBounds();
error AddressOutOfBounds();
bytes16 private constant _SYMBOLS = "0123456789abcdef";
// -------------------------
function slice(
bytes memory _bytes,
uint256 _start,
uint256 _length
) internal pure returns (bytes memory) {
if (_length + 31 < _length) revert SliceOverflow();
if (_bytes.length < _start + _length) revert SliceOutOfBounds();
bytes memory tempBytes;
assembly {
switch iszero(_length)
case 0 {
// Get a location of some free memory and store it in tempBytes as
// Solidity does for memory variables.
tempBytes := mload(0x40)
// The first word of the slice result is potentially a partial
// word read from the original array. To read it, we calculate
// the length of that partial word and start copying that many
// bytes into the array. The first word we copy will start with
// data we don't care about, but the last `lengthmod` bytes will
// land at the beginning of the contents of the new array. When
// we're done copying, we overwrite the full first word with
// the actual length of the slice.
let lengthmod := and(_length, 31)
// The multiplication in the next line is necessary
// because when slicing multiples of 32 bytes (lengthmod == 0)
// the following copy loop was copying the origin's length
// and then ending prematurely not copying everything it should.
let mc := add(
add(tempBytes, lengthmod),
mul(0x20, iszero(lengthmod))
)
let end := add(mc, _length)
for {
// The multiplication in the next line has the same exact purpose
// as the one above.
let cc := add(
add(
add(_bytes, lengthmod),
mul(0x20, iszero(lengthmod))
),
_start
)
} lt(mc, end) {
mc := add(mc, 0x20)
cc := add(cc, 0x20)
} {
mstore(mc, mload(cc))
}
mstore(tempBytes, _length)
//update free-memory pointer
//allocating the array padded to 32 bytes like the compiler does now
mstore(0x40, and(add(mc, 31), not(31)))
}
//if we want a zero-length slice let's just return a zero-length array
default {
tempBytes := mload(0x40)
//zero out the 32 bytes slice we are about to return
//we need to do it because Solidity does not garbage collect
mstore(tempBytes, 0)
mstore(0x40, add(tempBytes, 0x20))
}
}
return tempBytes;
}
function toAddress(
bytes memory _bytes,
uint256 _start
) internal pure returns (address) {
if (_bytes.length < _start + 20) {
revert AddressOutOfBounds();
}
address tempAddress;
assembly {
tempAddress := div(
mload(add(add(_bytes, 0x20), _start)),
0x1000000000000000000000000
)
}
return tempAddress;
}
/// Copied from OpenZeppelin's `Strings.sol` utility library.
/// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol
function toHexString(
uint256 value,
uint256 length
) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
// import { IDiamondCut } from "../Interfaces/LibDiamond.sol";
import { LibDiamond } from "../Libraries/LibDiamond.sol";
import { LibUtil } from "../Libraries/LibUtil.sol";
import { OnlyContractOwner } from "../Errors/GenericErrors.sol";
/// Implementation of EIP-2535 Diamond Standard
/// https://eips.ethereum.org/EIPS/eip-2535
library LibDiamond {
bytes32 internal constant DIAMOND_STORAGE_POSITION =
keccak256("diamond.standard.diamond.storage");
// Diamond specific errors
error IncorrectFacetCutAction();
error NoSelectorsInFace();
error FunctionAlreadyExists();
error FacetAddressIsZero();
error FacetAddressIsNotZero();
error FacetContainsNoCode();
error FunctionDoesNotExist();
error FunctionIsImmutable();
error InitZeroButCalldataNotEmpty();
error CalldataEmptyButInitNotZero();
error InitReverted();
// ----------------
struct FacetAddressAndPosition {
address facetAddress;
uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array
}
struct FacetFunctionSelectors {
bytes4[] functionSelectors;
uint256 facetAddressPosition; // position of facetAddress in facetAddresses array
}
struct DiamondStorage {
// maps function selector to the facet address and
// the position of the selector in the facetFunctionSelectors.selectors array
mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;
// maps facet addresses to function selectors
mapping(address => FacetFunctionSelectors) facetFunctionSelectors;
// facet addresses
address[] facetAddresses;
// Used to query if a contract implements an interface.
// Used to implement ERC-165.
mapping(bytes4 => bool) supportedInterfaces;
// owner of the contract
address contractOwner;
}
enum FacetCutAction {
Add,
Replace,
Remove
}
// Add=0, Replace=1, Remove=2
struct FacetCut {
address facetAddress;
FacetCutAction action;
bytes4[] functionSelectors;
}
function diamondStorage()
internal
pure
returns (DiamondStorage storage ds)
{
bytes32 position = DIAMOND_STORAGE_POSITION;
// solhint-disable-next-line no-inline-assembly
assembly {
ds.slot := position
}
}
event OwnershipTransferred(
address indexed previousOwner,
address indexed newOwner
);
event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);
function setContractOwner(address _newOwner) internal {
DiamondStorage storage ds = diamondStorage();
address previousOwner = ds.contractOwner;
ds.contractOwner = _newOwner;
emit OwnershipTransferred(previousOwner, _newOwner);
}
function contractOwner() internal view returns (address contractOwner_) {
contractOwner_ = diamondStorage().contractOwner;
}
function enforceIsContractOwner() internal view {
if (msg.sender != diamondStorage().contractOwner)
revert OnlyContractOwner();
}
// Internal function version of diamondCut
function diamondCut(
FacetCut[] memory _diamondCut,
address _init,
bytes memory _calldata
) internal {
for (uint256 facetIndex; facetIndex < _diamondCut.length; ) {
LibDiamond.FacetCutAction action = _diamondCut[facetIndex].action;
if (action == LibDiamond.FacetCutAction.Add) {
addFunctions(
_diamondCut[facetIndex].facetAddress,
_diamondCut[facetIndex].functionSelectors
);
} else if (action == LibDiamond.FacetCutAction.Replace) {
replaceFunctions(
_diamondCut[facetIndex].facetAddress,
_diamondCut[facetIndex].functionSelectors
);
} else if (action == LibDiamond.FacetCutAction.Remove) {
removeFunctions(
_diamondCut[facetIndex].facetAddress,
_diamondCut[facetIndex].functionSelectors
);
} else {
revert IncorrectFacetCutAction();
}
unchecked {
++facetIndex;
}
}
emit DiamondCut(_diamondCut, _init, _calldata);
initializeDiamondCut(_init, _calldata);
}
function addFunctions(
address _facetAddress,
bytes4[] memory _functionSelectors
) internal {
if (_functionSelectors.length == 0) {
revert NoSelectorsInFace();
}
DiamondStorage storage ds = diamondStorage();
if (LibUtil.isZeroAddress(_facetAddress)) {
revert FacetAddressIsZero();
}
uint96 selectorPosition = uint96(
ds.facetFunctionSelectors[_facetAddress].functionSelectors.length
);
// add new facet address if it does not exist
if (selectorPosition == 0) {
addFacet(ds, _facetAddress);
}
for (
uint256 selectorIndex;
selectorIndex < _functionSelectors.length;
) {
bytes4 selector = _functionSelectors[selectorIndex];
address oldFacetAddress = ds
.selectorToFacetAndPosition[selector]
.facetAddress;
if (!LibUtil.isZeroAddress(oldFacetAddress)) {
revert FunctionAlreadyExists();
}
addFunction(ds, selector, selectorPosition, _facetAddress);
unchecked {
++selectorPosition;
++selectorIndex;
}
}
}
function replaceFunctions(
address _facetAddress,
bytes4[] memory _functionSelectors
) internal {
if (_functionSelectors.length == 0) {
revert NoSelectorsInFace();
}
DiamondStorage storage ds = diamondStorage();
if (LibUtil.isZeroAddress(_facetAddress)) {
revert FacetAddressIsZero();
}
uint96 selectorPosition = uint96(
ds.facetFunctionSelectors[_facetAddress].functionSelectors.length
);
// add new facet address if it does not exist
if (selectorPosition == 0) {
addFacet(ds, _facetAddress);
}
for (
uint256 selectorIndex;
selectorIndex < _functionSelectors.length;
) {
bytes4 selector = _functionSelectors[selectorIndex];
address oldFacetAddress = ds
.selectorToFacetAndPosition[selector]
.facetAddress;
if (oldFacetAddress == _facetAddress) {
revert FunctionAlreadyExists();
}
removeFunction(ds, oldFacetAddress, selector);
addFunction(ds, selector, selectorPosition, _facetAddress);
unchecked {
++selectorPosition;
++selectorIndex;
}
}
}
function removeFunctions(
address _facetAddress,
bytes4[] memory _functionSelectors
) internal {
if (_functionSelectors.length == 0) {
revert NoSelectorsInFace();
}
DiamondStorage storage ds = diamondStorage();
// if function does not exist then do nothing and return
if (!LibUtil.isZeroAddress(_facetAddress)) {
revert FacetAddressIsNotZero();
}
for (
uint256 selectorIndex;
selectorIndex < _functionSelectors.length;
) {
bytes4 selector = _functionSelectors[selectorIndex];
address oldFacetAddress = ds
.selectorToFacetAndPosition[selector]
.facetAddress;
removeFunction(ds, oldFacetAddress, selector);
unchecked {
++selectorIndex;
}
}
}
function addFacet(
DiamondStorage storage ds,
address _facetAddress
) internal {
enforceHasContractCode(_facetAddress);
ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds
.facetAddresses
.length;
ds.facetAddresses.push(_facetAddress);
}
function addFunction(
DiamondStorage storage ds,
bytes4 _selector,
uint96 _selectorPosition,
address _facetAddress
) internal {
ds
.selectorToFacetAndPosition[_selector]
.functionSelectorPosition = _selectorPosition;
ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(
_selector
);
ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;
}
function removeFunction(
DiamondStorage storage ds,
address _facetAddress,
bytes4 _selector
) internal {
if (LibUtil.isZeroAddress(_facetAddress)) {
revert FunctionDoesNotExist();
}
// an immutable function is a function defined directly in a diamond
if (_facetAddress == address(this)) {
revert FunctionIsImmutable();
}
// replace selector with last selector, then delete last selector
uint256 selectorPosition = ds
.selectorToFacetAndPosition[_selector]
.functionSelectorPosition;
uint256 lastSelectorPosition = ds
.facetFunctionSelectors[_facetAddress]
.functionSelectors
.length - 1;
// if not the same then replace _selector with lastSelector
if (selectorPosition != lastSelectorPosition) {
bytes4 lastSelector = ds
.facetFunctionSelectors[_facetAddress]
.functionSelectors[lastSelectorPosition];
ds.facetFunctionSelectors[_facetAddress].functionSelectors[
selectorPosition
] = lastSelector;
ds
.selectorToFacetAndPosition[lastSelector]
.functionSelectorPosition = uint96(selectorPosition);
}
// delete the last selector
ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();
delete ds.selectorToFacetAndPosition[_selector];
// if no more selectors for facet address then delete the facet address
if (lastSelectorPosition == 0) {
// replace facet address with last facet address and delete last facet address
uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;
uint256 facetAddressPosition = ds
.facetFunctionSelectors[_facetAddress]
.facetAddressPosition;
if (facetAddressPosition != lastFacetAddressPosition) {
address lastFacetAddress = ds.facetAddresses[
lastFacetAddressPosition
];
ds.facetAddresses[facetAddressPosition] = lastFacetAddress;
ds
.facetFunctionSelectors[lastFacetAddress]
.facetAddressPosition = facetAddressPosition;
}
ds.facetAddresses.pop();
delete ds
.facetFunctionSelectors[_facetAddress]
.facetAddressPosition;
}
}
function initializeDiamondCut(
address _init,
bytes memory _calldata
) internal {
if (LibUtil.isZeroAddress(_init)) {
if (_calldata.length != 0) {
revert InitZeroButCalldataNotEmpty();
}
} else {
if (_calldata.length == 0) {
revert CalldataEmptyButInitNotZero();
}
if (_init != address(this)) {
enforceHasContractCode(_init);
}
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory error) = _init.delegatecall(_calldata);
if (!success) {
if (error.length > 0) {
// bubble up the error
revert(string(error));
} else {
revert InitReverted();
}
}
}
}
function enforceHasContractCode(address _contract) internal view {
uint256 contractSize;
// solhint-disable-next-line no-inline-assembly
assembly {
contractSize := extcodesize(_contract)
}
if (contractSize == 0) {
revert FacetContainsNoCode();
}
}
}// SPDX-License-Identifier: MIT
/// @custom:version 1.0.0
pragma solidity ^0.8.17;
import "./LibBytes.sol";
library LibUtil {
using LibBytes for bytes;
function getRevertMsg(
bytes memory _res
) internal pure returns (string memory) {
// If the _res length is less than 68, then the transaction failed silently (without a revert message)
if (_res.length < 68) return "Transaction reverted silently";
bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes
return abi.decode(revertData, (string)); // All that remains is the revert string
}
/// @notice Determines whether the given address is the zero address
/// @param addr The address to verify
/// @return Boolean indicating if the address is the zero address
function isZeroAddress(address addr) internal pure returns (bool) {
return addr == address(0);
}
function revertWith(bytes memory data) internal pure {
assembly {
let dataSize := mload(data) // Load the size of the data
let dataPtr := add(data, 0x20) // Advance data pointer to the next word
revert(dataPtr, dataSize) // Revert with the given data
}
}
}{
"evmVersion": "cancun",
"libraries": {},
"metadata": {
"appendCBOR": true,
"bytecodeHash": "ipfs",
"useLiteralContent": false
},
"optimizer": {
"enabled": true,
"runs": 1000000
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"remappings": [
"@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/",
"@uniswap/=node_modules/@uniswap/",
"eth-gas-reporter/=node_modules/eth-gas-reporter/",
"@openzeppelin/=lib/openzeppelin-contracts/",
"celer-network/=lib/sgn-v2-contracts/",
"create3-factory/=lib/create3-factory/src/",
"solmate/=lib/solmate/src/",
"solady/=lib/solady/src/",
"permit2/=lib/Permit2/src/",
"ds-test/=lib/ds-test/src/",
"forge-std/=lib/forge-std/src/",
"lifi/=src/",
"test/=test/",
"Permit2/=lib/Permit2/",
"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
"forge-gas-snapshot/=lib/Permit2/lib/forge-gas-snapshot/src/",
"hardhat/=node_modules/hardhat/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/",
"openzeppelin/=lib/openzeppelin-contracts/contracts/",
"sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/"
],
"viaIR": false
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"name":"CannotAuthoriseSelf","type":"error"},{"inputs":[],"name":"InvalidContract","type":"error"},{"inputs":[],"name":"UnAuthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"dexAddress","type":"address"}],"name":"DexAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"dexAddress","type":"address"}],"name":"DexRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes4","name":"functionSignature","type":"bytes4"},{"indexed":true,"internalType":"bool","name":"approved","type":"bool"}],"name":"FunctionSignatureApprovalChanged","type":"event"},{"inputs":[{"internalType":"address","name":"_dex","type":"address"}],"name":"addDex","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"approvedDexs","outputs":[{"internalType":"address[]","name":"addresses","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_dexs","type":"address[]"}],"name":"batchAddDex","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_dexs","type":"address[]"}],"name":"batchRemoveDex","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4[]","name":"_signatures","type":"bytes4[]"},{"internalType":"bool","name":"_approval","type":"bool"}],"name":"batchSetFunctionApprovalBySignature","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"_signature","type":"bytes4"}],"name":"isFunctionApproved","outputs":[{"internalType":"bool","name":"approved","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_dex","type":"address"}],"name":"removeDex","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"_signature","type":"bytes4"},{"internalType":"bool","name":"_approval","type":"bool"}],"name":"setFunctionApprovalBySignature","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
6080604052348015600e575f5ffd5b50610f148061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610085575f3560e01c80639afc19c7116100585780639afc19c7146100ec578063c3a6a96b146100ff578063fbb2d38114610112578063fcd8e49e14610127575f5ffd5b8063124f1ead146100895780632d2506a91461009e57806344e2b18c146100c6578063536db266146100d9575b5f5ffd5b61009c610097366004610c56565b61013a565b005b6100b16100ac366004610cc4565b6101cc565b60405190151581526020015b60405180910390f35b61009c6100d4366004610d34565b610226565b61009c6100e7366004610c56565b61031e565b61009c6100fa366004610d84565b6103b0565b61009c61010d366004610dc3565b6104a7565b61011a61055e565b6040516100bd9190610df4565b61009c610135366004610d84565b61056d565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c13205473ffffffffffffffffffffffffffffffffffffffff163314610180576101806106de565b6101898161077d565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f78e0a2ffcdfbbb49ba5c8050d8630fab2176d825e8360809db049cd98f462a78905f90a250565b7fffffffff0000000000000000000000000000000000000000000000000000000081165f9081527f7a8ac5d3b7183f220a0602439da45ea337311d699902d1ed11a3725a714e7f1f602052604081205460ff165b92915050565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c13205473ffffffffffffffffffffffffffffffffffffffff16331461026c5761026c6106de565b815f5b81811015610317575f85858381811061028a5761028a610e4c565b905060200201602081019061029f9190610cc4565b905083156102b5576102b08161098f565b6102be565b6102be81610a18565b604051841515907fffffffff000000000000000000000000000000000000000000000000000000008316907f9167f6a23d52a4522e9211205d62ce63f02d928227ae0fe00326f51e152a3c45905f90a35060010161026f565b5050505050565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c13205473ffffffffffffffffffffffffffffffffffffffff163314610364576103646106de565b61036d81610a3f565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f7e0058dd0cbc0a8b7beaa013a4825655d8e9e81a5e2cc6582818deded0a41b99905f90a250565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c13205473ffffffffffffffffffffffffffffffffffffffff1633146103f6576103f66106de565b805f5b818110156104a15761043084848381811061041657610416610e4c565b905060200201602081019061042b9190610c56565b61077d565b83838281811061044257610442610e4c565b90506020020160208101906104579190610c56565b73ffffffffffffffffffffffffffffffffffffffff167f78e0a2ffcdfbbb49ba5c8050d8630fab2176d825e8360809db049cd98f462a7860405160405180910390a26001016103f9565b50505050565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c13205473ffffffffffffffffffffffffffffffffffffffff1633146104ed576104ed6106de565b8015610501576104fc8261098f565b61050a565b61050a82610a18565b604051811515907fffffffff000000000000000000000000000000000000000000000000000000008416907f9167f6a23d52a4522e9211205d62ce63f02d928227ae0fe00326f51e152a3c45905f90a35050565b6060610568610b2a565b905090565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c13205473ffffffffffffffffffffffffffffffffffffffff1633146105b3576105b36106de565b805f5b818110156104a1575f8484838181106105d1576105d1610e4c565b90506020020160208101906105e69190610c56565b90503073ffffffffffffffffffffffffffffffffffffffff821603610637576040517fa9cefcae00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81165f9081527f7a8ac5d3b7183f220a0602439da45ea337311d699902d1ed11a3725a714e7f1e602052604090205460ff161561068c57506001016105b6565b61069581610a3f565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f7e0058dd0cbc0a8b7beaa013a4825655d8e9e81a5e2cc6582818deded0a41b99905f90a2506001016105b6565b5f80357fffffffff000000000000000000000000000000000000000000000000000000001681527fdf05114fe8fad5d7cd2d71c5651effc2a4c21f13ee8b4a462e2a3bd4e140c73e6020818152604080842033855290915290912054600160ff90911615151461077a576040517fbe24598300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b73ffffffffffffffffffffffffffffffffffffffff81165f9081527f7a8ac5d3b7183f220a0602439da45ea337311d699902d1ed11a3725a714e7f1e602081905260409091205460ff166107cf575050565b73ffffffffffffffffffffffffffffffffffffffff82165f90815260208290526040812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556002820154905b818110156104a1578373ffffffffffffffffffffffffffffffffffffffff1683600201828154811061085457610854610e4c565b5f9182526020909120015473ffffffffffffffffffffffffffffffffffffffff16036109875760028301610889600184610e79565b8154811061089957610899610e4c565b5f9182526020909120015460028401805473ffffffffffffffffffffffffffffffffffffffff90921691839081106108d3576108d3610e4c565b905f5260205f20015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508260020180548061092b5761092b610eb1565b5f8281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690550190556104a1565b600101610820565b60017f7a8ac5d3b7183f220a0602439da45ea337311d699902d1ed11a3725a714e7f1e5b7fffffffff00000000000000000000000000000000000000000000000000000000929092165f9081526001909201602052604090912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b5f7f7a8ac5d3b7183f220a0602439da45ea337311d699902d1ed11a3725a714e7f1e6109b3565b610a4881610bb9565b73ffffffffffffffffffffffffffffffffffffffff81165f9081527f7a8ac5d3b7183f220a0602439da45ea337311d699902d1ed11a3725a714e7f1e602081905260409091205460ff1615610a9b575050565b73ffffffffffffffffffffffffffffffffffffffff9091165f81815260208381526040822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091556002909401805494850181558252902090910180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169091179055565b60607f7a8ac5d3b7183f220a0602439da45ea337311d699902d1ed11a3725a714e7f1e600201805480602002602001604051908101604052809291908181526020018280548015610baf57602002820191905f5260205f20905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610b84575b5050505050905090565b73ffffffffffffffffffffffffffffffffffffffff8116610c06576040517f6eefed2000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff163b5f0361077a576040517f6eefed2000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60208284031215610c66575f5ffd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610c89575f5ffd5b9392505050565b80357fffffffff0000000000000000000000000000000000000000000000000000000081168114610cbf575f5ffd5b919050565b5f60208284031215610cd4575f5ffd5b610c8982610c90565b5f5f83601f840112610ced575f5ffd5b50813567ffffffffffffffff811115610d04575f5ffd5b6020830191508360208260051b8501011115610d1e575f5ffd5b9250929050565b80358015158114610cbf575f5ffd5b5f5f5f60408486031215610d46575f5ffd5b833567ffffffffffffffff811115610d5c575f5ffd5b610d6886828701610cdd565b9094509250610d7b905060208501610d25565b90509250925092565b5f5f60208385031215610d95575f5ffd5b823567ffffffffffffffff811115610dab575f5ffd5b610db785828601610cdd565b90969095509350505050565b5f5f60408385031215610dd4575f5ffd5b610ddd83610c90565b9150610deb60208401610d25565b90509250929050565b602080825282518282018190525f918401906040840190835b81811015610e4157835173ffffffffffffffffffffffffffffffffffffffff16835260209384019390920191600101610e0d565b509095945050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b81810381811115610220577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffdfea264697066735822122000166c47d632ab10469d487077326207cbfe598543f2956b0e93010acc48798464736f6c634300081d0033
Deployed Bytecode
0x608060405234801561000f575f5ffd5b5060043610610085575f3560e01c80639afc19c7116100585780639afc19c7146100ec578063c3a6a96b146100ff578063fbb2d38114610112578063fcd8e49e14610127575f5ffd5b8063124f1ead146100895780632d2506a91461009e57806344e2b18c146100c6578063536db266146100d9575b5f5ffd5b61009c610097366004610c56565b61013a565b005b6100b16100ac366004610cc4565b6101cc565b60405190151581526020015b60405180910390f35b61009c6100d4366004610d34565b610226565b61009c6100e7366004610c56565b61031e565b61009c6100fa366004610d84565b6103b0565b61009c61010d366004610dc3565b6104a7565b61011a61055e565b6040516100bd9190610df4565b61009c610135366004610d84565b61056d565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c13205473ffffffffffffffffffffffffffffffffffffffff163314610180576101806106de565b6101898161077d565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f78e0a2ffcdfbbb49ba5c8050d8630fab2176d825e8360809db049cd98f462a78905f90a250565b7fffffffff0000000000000000000000000000000000000000000000000000000081165f9081527f7a8ac5d3b7183f220a0602439da45ea337311d699902d1ed11a3725a714e7f1f602052604081205460ff165b92915050565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c13205473ffffffffffffffffffffffffffffffffffffffff16331461026c5761026c6106de565b815f5b81811015610317575f85858381811061028a5761028a610e4c565b905060200201602081019061029f9190610cc4565b905083156102b5576102b08161098f565b6102be565b6102be81610a18565b604051841515907fffffffff000000000000000000000000000000000000000000000000000000008316907f9167f6a23d52a4522e9211205d62ce63f02d928227ae0fe00326f51e152a3c45905f90a35060010161026f565b5050505050565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c13205473ffffffffffffffffffffffffffffffffffffffff163314610364576103646106de565b61036d81610a3f565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f7e0058dd0cbc0a8b7beaa013a4825655d8e9e81a5e2cc6582818deded0a41b99905f90a250565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c13205473ffffffffffffffffffffffffffffffffffffffff1633146103f6576103f66106de565b805f5b818110156104a15761043084848381811061041657610416610e4c565b905060200201602081019061042b9190610c56565b61077d565b83838281811061044257610442610e4c565b90506020020160208101906104579190610c56565b73ffffffffffffffffffffffffffffffffffffffff167f78e0a2ffcdfbbb49ba5c8050d8630fab2176d825e8360809db049cd98f462a7860405160405180910390a26001016103f9565b50505050565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c13205473ffffffffffffffffffffffffffffffffffffffff1633146104ed576104ed6106de565b8015610501576104fc8261098f565b61050a565b61050a82610a18565b604051811515907fffffffff000000000000000000000000000000000000000000000000000000008416907f9167f6a23d52a4522e9211205d62ce63f02d928227ae0fe00326f51e152a3c45905f90a35050565b6060610568610b2a565b905090565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c13205473ffffffffffffffffffffffffffffffffffffffff1633146105b3576105b36106de565b805f5b818110156104a1575f8484838181106105d1576105d1610e4c565b90506020020160208101906105e69190610c56565b90503073ffffffffffffffffffffffffffffffffffffffff821603610637576040517fa9cefcae00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81165f9081527f7a8ac5d3b7183f220a0602439da45ea337311d699902d1ed11a3725a714e7f1e602052604090205460ff161561068c57506001016105b6565b61069581610a3f565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f7e0058dd0cbc0a8b7beaa013a4825655d8e9e81a5e2cc6582818deded0a41b99905f90a2506001016105b6565b5f80357fffffffff000000000000000000000000000000000000000000000000000000001681527fdf05114fe8fad5d7cd2d71c5651effc2a4c21f13ee8b4a462e2a3bd4e140c73e6020818152604080842033855290915290912054600160ff90911615151461077a576040517fbe24598300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b73ffffffffffffffffffffffffffffffffffffffff81165f9081527f7a8ac5d3b7183f220a0602439da45ea337311d699902d1ed11a3725a714e7f1e602081905260409091205460ff166107cf575050565b73ffffffffffffffffffffffffffffffffffffffff82165f90815260208290526040812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556002820154905b818110156104a1578373ffffffffffffffffffffffffffffffffffffffff1683600201828154811061085457610854610e4c565b5f9182526020909120015473ffffffffffffffffffffffffffffffffffffffff16036109875760028301610889600184610e79565b8154811061089957610899610e4c565b5f9182526020909120015460028401805473ffffffffffffffffffffffffffffffffffffffff90921691839081106108d3576108d3610e4c565b905f5260205f20015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508260020180548061092b5761092b610eb1565b5f8281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690550190556104a1565b600101610820565b60017f7a8ac5d3b7183f220a0602439da45ea337311d699902d1ed11a3725a714e7f1e5b7fffffffff00000000000000000000000000000000000000000000000000000000929092165f9081526001909201602052604090912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b5f7f7a8ac5d3b7183f220a0602439da45ea337311d699902d1ed11a3725a714e7f1e6109b3565b610a4881610bb9565b73ffffffffffffffffffffffffffffffffffffffff81165f9081527f7a8ac5d3b7183f220a0602439da45ea337311d699902d1ed11a3725a714e7f1e602081905260409091205460ff1615610a9b575050565b73ffffffffffffffffffffffffffffffffffffffff9091165f81815260208381526040822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091556002909401805494850181558252902090910180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169091179055565b60607f7a8ac5d3b7183f220a0602439da45ea337311d699902d1ed11a3725a714e7f1e600201805480602002602001604051908101604052809291908181526020018280548015610baf57602002820191905f5260205f20905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610b84575b5050505050905090565b73ffffffffffffffffffffffffffffffffffffffff8116610c06576040517f6eefed2000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff163b5f0361077a576040517f6eefed2000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60208284031215610c66575f5ffd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610c89575f5ffd5b9392505050565b80357fffffffff0000000000000000000000000000000000000000000000000000000081168114610cbf575f5ffd5b919050565b5f60208284031215610cd4575f5ffd5b610c8982610c90565b5f5f83601f840112610ced575f5ffd5b50813567ffffffffffffffff811115610d04575f5ffd5b6020830191508360208260051b8501011115610d1e575f5ffd5b9250929050565b80358015158114610cbf575f5ffd5b5f5f5f60408486031215610d46575f5ffd5b833567ffffffffffffffff811115610d5c575f5ffd5b610d6886828701610cdd565b9094509250610d7b905060208501610d25565b90509250925092565b5f5f60208385031215610d95575f5ffd5b823567ffffffffffffffff811115610dab575f5ffd5b610db785828601610cdd565b90969095509350505050565b5f5f60408385031215610dd4575f5ffd5b610ddd83610c90565b9150610deb60208401610d25565b90509250929050565b602080825282518282018190525f918401906040840190835b81811015610e4157835173ffffffffffffffffffffffffffffffffffffffff16835260209384019390920191600101610e0d565b509095945050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b81810381811115610220577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffdfea264697066735822122000166c47d632ab10469d487077326207cbfe598543f2956b0e93010acc48798464736f6c634300081d0033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ 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.