Source Code
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 6503430 | 577 days ago | Contract Creation | 0 FRAX |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
DexManagerFacet
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 1000000 runs
Other Settings:
london 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.1
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)) 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
pragma solidity 0.8.17;
import { IDiamondCut } from "../Interfaces/IDiamondCut.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;
}
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
);
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();
}
event DiamondCut(
IDiamondCut.FacetCut[] _diamondCut,
address _init,
bytes _calldata
);
// Internal function version of diamondCut
function diamondCut(
IDiamondCut.FacetCut[] memory _diamondCut,
address _init,
bytes memory _calldata
) internal {
for (uint256 facetIndex; facetIndex < _diamondCut.length; ) {
IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;
if (action == IDiamondCut.FacetCutAction.Add) {
addFunctions(
_diamondCut[facetIndex].facetAddress,
_diamondCut[facetIndex].functionSelectors
);
} else if (action == IDiamondCut.FacetCutAction.Replace) {
replaceFunctions(
_diamondCut[facetIndex].facetAddress,
_diamondCut[facetIndex].functionSelectors
);
} else if (action == IDiamondCut.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
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
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 pragma solidity 0.8.17; error AlreadyInitialized(); error CannotAuthoriseSelf(); error CannotBridgeToSameNetwork(); error ContractCallNotAllowed(); error CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount); error ExternalCallFailed(); 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 UnAuthorized(); error UnsupportedChainId(uint256 chainId); error WithdrawFailed(); error ZeroAmount();
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
interface IDiamondCut {
enum FacetCutAction {
Add,
Replace,
Remove
}
// Add=0, Replace=1, Remove=2
struct FacetCut {
address facetAddress;
FacetCutAction action;
bytes4[] functionSelectors;
}
/// @notice Add/replace/remove any number of functions and optionally execute
/// a function with delegatecall
/// @param _diamondCut Contains the facet addresses and function selectors
/// @param _init The address of the contract or facet to execute _calldata
/// @param _calldata A function call, including function selector and arguments
/// _calldata is executed with delegatecall on _init
function diamondCut(
FacetCut[] calldata _diamondCut,
address _init,
bytes calldata _calldata
) external;
event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);
}// SPDX-License-Identifier: MIT
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
}
}
}// SPDX-License-Identifier: MIT
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);
}
}{
"remappings": [
"@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/",
"@uniswap/=node_modules/@uniswap/",
"eth-gas-reporter/=node_modules/eth-gas-reporter/",
"hardhat/=node_modules/hardhat/",
"hardhat-deploy/=node_modules/hardhat-deploy/",
"@openzeppelin/=lib/openzeppelin-contracts/",
"celer-network/=lib/sgn-v2-contracts/",
"create3-factory/=lib/create3-factory/src/",
"solmate/=lib/solmate/src/",
"ds-test/=lib/ds-test/src/",
"forge-std/=lib/forge-std/src/",
"lifi/=src/",
"test/=test/",
"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/",
"openzeppelin/=lib/openzeppelin-contracts/contracts/",
"sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/"
],
"optimizer": {
"enabled": true,
"runs": 1000000
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs"
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "london",
"viaIR": false,
"libraries": {}
}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
608060405234801561001057600080fd5b50610f97806100206000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c80639afc19c71161005b5780639afc19c7146100f0578063c3a6a96b14610103578063fbb2d38114610116578063fcd8e49e1461012b57600080fd5b8063124f1ead1461008d5780632d2506a9146100a257806344e2b18c146100ca578063536db266146100dd575b600080fd5b6100a061009b366004610c7d565b61013e565b005b6100b56100b0366004610cef565b6101d1565b60405190151581526020015b60405180910390f35b6100a06100d8366004610d66565b61022c565b6100a06100eb366004610c7d565b610327565b6100a06100fe366004610dba565b6103ba565b6100a0610111366004610dfc565b6104b2565b61011e61056a565b6040516100c19190610e2f565b6100a0610139366004610dba565b610579565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c13205473ffffffffffffffffffffffffffffffffffffffff163314610184576101846106eb565b61018d8161078b565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f78e0a2ffcdfbbb49ba5c8050d8630fab2176d825e8360809db049cd98f462a7890600090a250565b7fffffffff00000000000000000000000000000000000000000000000000000000811660009081527f7a8ac5d3b7183f220a0602439da45ea337311d699902d1ed11a3725a714e7f1f602052604081205460ff165b92915050565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c13205473ffffffffffffffffffffffffffffffffffffffff163314610272576102726106eb565b8160005b8181101561032057600085858381811061029257610292610e89565b90506020020160208101906102a79190610cef565b905083156102bd576102b8816109af565b6102c6565b6102c681610a39565b604051841515907fffffffff000000000000000000000000000000000000000000000000000000008316907f9167f6a23d52a4522e9211205d62ce63f02d928227ae0fe00326f51e152a3c4590600090a350600101610276565b5050505050565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c13205473ffffffffffffffffffffffffffffffffffffffff16331461036d5761036d6106eb565b61037681610a61565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f7e0058dd0cbc0a8b7beaa013a4825655d8e9e81a5e2cc6582818deded0a41b9990600090a250565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c13205473ffffffffffffffffffffffffffffffffffffffff163314610400576104006106eb565b8060005b818110156104ac5761043b84848381811061042157610421610e89565b90506020020160208101906104369190610c7d565b61078b565b83838281811061044d5761044d610e89565b90506020020160208101906104629190610c7d565b73ffffffffffffffffffffffffffffffffffffffff167f78e0a2ffcdfbbb49ba5c8050d8630fab2176d825e8360809db049cd98f462a7860405160405180910390a2600101610404565b50505050565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c13205473ffffffffffffffffffffffffffffffffffffffff1633146104f8576104f86106eb565b801561050c57610507826109af565b610515565b61051582610a39565b604051811515907fffffffff000000000000000000000000000000000000000000000000000000008416907f9167f6a23d52a4522e9211205d62ce63f02d928227ae0fe00326f51e152a3c4590600090a35050565b6060610574610b4e565b905090565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c13205473ffffffffffffffffffffffffffffffffffffffff1633146105bf576105bf6106eb565b8060005b818110156104ac5760008484838181106105df576105df610e89565b90506020020160208101906105f49190610c7d565b90503073ffffffffffffffffffffffffffffffffffffffff821603610645576040517fa9cefcae00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff811660009081527f7a8ac5d3b7183f220a0602439da45ea337311d699902d1ed11a3725a714e7f1e602052604090205460ff161561069857506105c3565b6106a181610a61565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f7e0058dd0cbc0a8b7beaa013a4825655d8e9e81a5e2cc6582818deded0a41b9990600090a2506001016105c3565b600080357fffffffff000000000000000000000000000000000000000000000000000000001681527fdf05114fe8fad5d7cd2d71c5651effc2a4c21f13ee8b4a462e2a3bd4e140c73e6020818152604080842033855290915290912054600160ff909116151514610788576040517fbe24598300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b73ffffffffffffffffffffffffffffffffffffffff811660009081527f7a8ac5d3b7183f220a0602439da45ea337311d699902d1ed11a3725a714e7f1e602081905260409091205460ff166107de575050565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260208290526040812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556002820154905b818110156104ac578373ffffffffffffffffffffffffffffffffffffffff1683600201828154811061086457610864610e89565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff160361099d576002830161089a600184610ee7565b815481106108aa576108aa610e89565b60009182526020909120015460028401805473ffffffffffffffffffffffffffffffffffffffff90921691839081106108e5576108e5610e89565b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508260020180548061094057610940610efa565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690550190556104ac565b806109a781610f29565b915050610830565b60017f7a8ac5d3b7183f220a0602439da45ea337311d699902d1ed11a3725a714e7f1e5b7fffffffff000000000000000000000000000000000000000000000000000000009290921660009081526001909201602052604090912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b60007f7a8ac5d3b7183f220a0602439da45ea337311d699902d1ed11a3725a714e7f1e6109d3565b610a6a81610bdf565b73ffffffffffffffffffffffffffffffffffffffff811660009081527f7a8ac5d3b7183f220a0602439da45ea337311d699902d1ed11a3725a714e7f1e602081905260409091205460ff1615610abe575050565b73ffffffffffffffffffffffffffffffffffffffff909116600081815260208381526040822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091556002909401805494850181558252902090910180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169091179055565b60607f7a8ac5d3b7183f220a0602439da45ea337311d699902d1ed11a3725a714e7f1e600201805480602002602001604051908101604052809291908181526020018280548015610bd557602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610baa575b5050505050905090565b73ffffffffffffffffffffffffffffffffffffffff8116610c2c576040517f6eefed2000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff163b600003610788576040517f6eefed2000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060208284031215610c8f57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610cb357600080fd5b9392505050565b80357fffffffff0000000000000000000000000000000000000000000000000000000081168114610cea57600080fd5b919050565b600060208284031215610d0157600080fd5b610cb382610cba565b60008083601f840112610d1c57600080fd5b50813567ffffffffffffffff811115610d3457600080fd5b6020830191508360208260051b8501011115610d4f57600080fd5b9250929050565b80358015158114610cea57600080fd5b600080600060408486031215610d7b57600080fd5b833567ffffffffffffffff811115610d9257600080fd5b610d9e86828701610d0a565b9094509250610db1905060208501610d56565b90509250925092565b60008060208385031215610dcd57600080fd5b823567ffffffffffffffff811115610de457600080fd5b610df085828601610d0a565b90969095509350505050565b60008060408385031215610e0f57600080fd5b610e1883610cba565b9150610e2660208401610d56565b90509250929050565b6020808252825182820181905260009190848201906040850190845b81811015610e7d57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101610e4b565b50909695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561022657610226610eb8565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610f5a57610f5a610eb8565b506001019056fea264697066735822122027ba529033ed69667f59b7ca1f4cc5524bd5942cfc7f4aa5cd6c57d3201cdd6164736f6c63430008110033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100885760003560e01c80639afc19c71161005b5780639afc19c7146100f0578063c3a6a96b14610103578063fbb2d38114610116578063fcd8e49e1461012b57600080fd5b8063124f1ead1461008d5780632d2506a9146100a257806344e2b18c146100ca578063536db266146100dd575b600080fd5b6100a061009b366004610c7d565b61013e565b005b6100b56100b0366004610cef565b6101d1565b60405190151581526020015b60405180910390f35b6100a06100d8366004610d66565b61022c565b6100a06100eb366004610c7d565b610327565b6100a06100fe366004610dba565b6103ba565b6100a0610111366004610dfc565b6104b2565b61011e61056a565b6040516100c19190610e2f565b6100a0610139366004610dba565b610579565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c13205473ffffffffffffffffffffffffffffffffffffffff163314610184576101846106eb565b61018d8161078b565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f78e0a2ffcdfbbb49ba5c8050d8630fab2176d825e8360809db049cd98f462a7890600090a250565b7fffffffff00000000000000000000000000000000000000000000000000000000811660009081527f7a8ac5d3b7183f220a0602439da45ea337311d699902d1ed11a3725a714e7f1f602052604081205460ff165b92915050565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c13205473ffffffffffffffffffffffffffffffffffffffff163314610272576102726106eb565b8160005b8181101561032057600085858381811061029257610292610e89565b90506020020160208101906102a79190610cef565b905083156102bd576102b8816109af565b6102c6565b6102c681610a39565b604051841515907fffffffff000000000000000000000000000000000000000000000000000000008316907f9167f6a23d52a4522e9211205d62ce63f02d928227ae0fe00326f51e152a3c4590600090a350600101610276565b5050505050565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c13205473ffffffffffffffffffffffffffffffffffffffff16331461036d5761036d6106eb565b61037681610a61565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f7e0058dd0cbc0a8b7beaa013a4825655d8e9e81a5e2cc6582818deded0a41b9990600090a250565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c13205473ffffffffffffffffffffffffffffffffffffffff163314610400576104006106eb565b8060005b818110156104ac5761043b84848381811061042157610421610e89565b90506020020160208101906104369190610c7d565b61078b565b83838281811061044d5761044d610e89565b90506020020160208101906104629190610c7d565b73ffffffffffffffffffffffffffffffffffffffff167f78e0a2ffcdfbbb49ba5c8050d8630fab2176d825e8360809db049cd98f462a7860405160405180910390a2600101610404565b50505050565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c13205473ffffffffffffffffffffffffffffffffffffffff1633146104f8576104f86106eb565b801561050c57610507826109af565b610515565b61051582610a39565b604051811515907fffffffff000000000000000000000000000000000000000000000000000000008416907f9167f6a23d52a4522e9211205d62ce63f02d928227ae0fe00326f51e152a3c4590600090a35050565b6060610574610b4e565b905090565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c13205473ffffffffffffffffffffffffffffffffffffffff1633146105bf576105bf6106eb565b8060005b818110156104ac5760008484838181106105df576105df610e89565b90506020020160208101906105f49190610c7d565b90503073ffffffffffffffffffffffffffffffffffffffff821603610645576040517fa9cefcae00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff811660009081527f7a8ac5d3b7183f220a0602439da45ea337311d699902d1ed11a3725a714e7f1e602052604090205460ff161561069857506105c3565b6106a181610a61565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f7e0058dd0cbc0a8b7beaa013a4825655d8e9e81a5e2cc6582818deded0a41b9990600090a2506001016105c3565b600080357fffffffff000000000000000000000000000000000000000000000000000000001681527fdf05114fe8fad5d7cd2d71c5651effc2a4c21f13ee8b4a462e2a3bd4e140c73e6020818152604080842033855290915290912054600160ff909116151514610788576040517fbe24598300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b73ffffffffffffffffffffffffffffffffffffffff811660009081527f7a8ac5d3b7183f220a0602439da45ea337311d699902d1ed11a3725a714e7f1e602081905260409091205460ff166107de575050565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260208290526040812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556002820154905b818110156104ac578373ffffffffffffffffffffffffffffffffffffffff1683600201828154811061086457610864610e89565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff160361099d576002830161089a600184610ee7565b815481106108aa576108aa610e89565b60009182526020909120015460028401805473ffffffffffffffffffffffffffffffffffffffff90921691839081106108e5576108e5610e89565b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508260020180548061094057610940610efa565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690550190556104ac565b806109a781610f29565b915050610830565b60017f7a8ac5d3b7183f220a0602439da45ea337311d699902d1ed11a3725a714e7f1e5b7fffffffff000000000000000000000000000000000000000000000000000000009290921660009081526001909201602052604090912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b60007f7a8ac5d3b7183f220a0602439da45ea337311d699902d1ed11a3725a714e7f1e6109d3565b610a6a81610bdf565b73ffffffffffffffffffffffffffffffffffffffff811660009081527f7a8ac5d3b7183f220a0602439da45ea337311d699902d1ed11a3725a714e7f1e602081905260409091205460ff1615610abe575050565b73ffffffffffffffffffffffffffffffffffffffff909116600081815260208381526040822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091556002909401805494850181558252902090910180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169091179055565b60607f7a8ac5d3b7183f220a0602439da45ea337311d699902d1ed11a3725a714e7f1e600201805480602002602001604051908101604052809291908181526020018280548015610bd557602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610baa575b5050505050905090565b73ffffffffffffffffffffffffffffffffffffffff8116610c2c576040517f6eefed2000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff163b600003610788576040517f6eefed2000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060208284031215610c8f57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610cb357600080fd5b9392505050565b80357fffffffff0000000000000000000000000000000000000000000000000000000081168114610cea57600080fd5b919050565b600060208284031215610d0157600080fd5b610cb382610cba565b60008083601f840112610d1c57600080fd5b50813567ffffffffffffffff811115610d3457600080fd5b6020830191508360208260051b8501011115610d4f57600080fd5b9250929050565b80358015158114610cea57600080fd5b600080600060408486031215610d7b57600080fd5b833567ffffffffffffffff811115610d9257600080fd5b610d9e86828701610d0a565b9094509250610db1905060208501610d56565b90509250925092565b60008060208385031215610dcd57600080fd5b823567ffffffffffffffff811115610de457600080fd5b610df085828601610d0a565b90969095509350505050565b60008060408385031215610e0f57600080fd5b610e1883610cba565b9150610e2660208401610d56565b90509250929050565b6020808252825182820181905260009190848201906040850190845b81811015610e7d57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101610e4b565b50909695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561022657610226610eb8565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610f5a57610f5a610eb8565b506001019056fea264697066735822122027ba529033ed69667f59b7ca1f4cc5524bd5942cfc7f4aa5cd6c57d3201cdd6164736f6c63430008110033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in FRAX
0
Multichain Portfolio | 35 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.