Source Code
Overview
POL Balance
POL Value
$0.00| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 22551775 | 1501 days ago | Contract Creation | 0 POL |
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
DiamondCutFacet
Compiler Version
v0.8.7+commit.e28d00a7
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import { IDiamondCut } from "../Interfaces/IDiamondCut.sol";
import { LibDiamond } from "../Libraries/LibDiamond.sol";
contract DiamondCutFacet is IDiamondCut {
/// @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 override {
LibDiamond.enforceIsContractOwner();
LibDiamond.diamondCut(_diamondCut, _init, _calldata);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import { ILiFi } from "../Interfaces/ILiFi.sol";
import { IAnyswapRouter } from "../Interfaces/IAnyswapRouter.sol";
import { LibDiamond } from "../Libraries/LibDiamond.sol";
import { LibAsset } from "../Libraries/LibAsset.sol";
import { LibSwap } from "../Libraries/LibSwap.sol";
import { IAnyswapToken } from "../Interfaces/IAnyswapToken.sol";
import { LibDiamond } from "../Libraries/LibDiamond.sol";
contract AnyswapFacet is ILiFi {
/* ========== Storage ========== */
bytes32 internal constant NAMESPACE = keccak256("com.lifi.facets.anyswap");
struct Storage {
address anyswapRouter;
}
/* ========== Types ========== */
struct AnyswapData {
address token;
uint256 amount;
address recipient;
uint256 toChainId;
}
/* ========== Init ========== */
function initAnyswap(address _anyswapRouter) external {
Storage storage s = getStorage();
LibDiamond.enforceIsContractOwner();
s.anyswapRouter = _anyswapRouter;
}
/* ========== Public Bridge Functions ========== */
/**
* @notice Bridges tokens via Anyswap
* @param _lifiData data used purely for tracking and analytics
* @param _anyswapData data specific to Anyswap
*/
function startBridgeTokensViaAnyswap(LiFiData memory _lifiData, AnyswapData calldata _anyswapData) public payable {
if (_anyswapData.token != address(0)) {
uint256 _fromTokenBalance = LibAsset.getOwnBalance(_anyswapData.token);
address underlyingToken = IAnyswapToken(_anyswapData.token).underlying();
LibAsset.transferFromERC20(underlyingToken, msg.sender, address(this), _anyswapData.amount);
require(
LibAsset.getOwnBalance(underlyingToken) - _fromTokenBalance == _anyswapData.amount,
"ERR_INVALID_AMOUNT"
);
} else {
require(msg.value == _anyswapData.amount, "ERR_INVALID_AMOUNT");
}
_startBridge(_anyswapData);
emit LiFiTransferStarted(
_lifiData.transactionId,
_lifiData.integrator,
_lifiData.referrer,
_lifiData.sendingAssetId,
_lifiData.receivingAssetId,
_lifiData.receiver,
_lifiData.amount,
_lifiData.destinationChainId,
block.timestamp
);
}
/**
* @notice Performs a swap before bridging via Anyswap
* @param _lifiData data used purely for tracking and analytics
* @param _swapData an array of swap related data for performing swaps before bridging
* @param _anyswapData data specific to Anyswap
*/
function swapAndStartBridgeTokensViaAnyswap(
LiFiData memory _lifiData,
LibSwap.SwapData[] calldata _swapData,
AnyswapData calldata _anyswapData
) public payable {
if (_anyswapData.token != address(0)) {
address underlyingToken = IAnyswapToken(_anyswapData.token).underlying();
uint256 _fromTokenBalance = LibAsset.getOwnBalance(underlyingToken);
// Swap
for (uint8 i; i < _swapData.length; i++) {
LibSwap.swap(_lifiData.transactionId, _swapData[i]);
}
require(
LibAsset.getOwnBalance(underlyingToken) - _fromTokenBalance >= _anyswapData.amount,
"ERR_INVALID_AMOUNT"
);
} else {
uint256 _fromBalance = address(this).balance;
// Swap
for (uint8 i; i < _swapData.length; i++) {
LibSwap.swap(_lifiData.transactionId, _swapData[i]);
}
require(address(this).balance - _fromBalance >= _anyswapData.amount, "ERR_INVALID_AMOUNT");
}
_startBridge(_anyswapData);
emit LiFiTransferStarted(
_lifiData.transactionId,
_lifiData.integrator,
_lifiData.referrer,
_lifiData.sendingAssetId,
_lifiData.receivingAssetId,
_lifiData.receiver,
_lifiData.amount,
_lifiData.destinationChainId,
block.timestamp
);
}
/* ========== External Config Functions ========== */
/**
* @dev Changes address of Anyswap router
* @param _newRouter address of the new router
*/
function changeAnyswapRouter(address _newRouter) external {
Storage storage s = getStorage();
LibDiamond.enforceIsContractOwner();
s.anyswapRouter = _newRouter;
}
/* ========== Internal Functions ========== */
/**
* @dev Conatains the business logic for the bridge via Anyswap
* @param _anyswapData data specific to Anyswap
*/
function _startBridge(AnyswapData calldata _anyswapData) internal {
Storage storage s = getStorage();
// Check chain id
require(block.chainid != _anyswapData.toChainId, "Cannot bridge to the same network.");
if (_anyswapData.token != address(0)) {
// Give Anyswap approval to bridge tokens
LibAsset.approveERC20(
IERC20(IAnyswapToken(_anyswapData.token).underlying()),
s.anyswapRouter,
_anyswapData.amount
);
IAnyswapRouter(s.anyswapRouter).anySwapOutUnderlying(
_anyswapData.token,
_anyswapData.recipient,
_anyswapData.amount,
_anyswapData.toChainId
);
} else {
IAnyswapRouter(s.anyswapRouter).anySwapOutNative{ value: _anyswapData.amount }(
_anyswapData.token,
_anyswapData.recipient,
_anyswapData.toChainId
);
}
}
function getStorage() internal pure returns (Storage storage s) {
bytes32 namespace = NAMESPACE;
// solhint-disable-next-line no-inline-assembly
assembly {
s.slot := namespace
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./extensions/IERC20Metadata.sol";
import "../../utils/Context.sol";
/**
* @dev Implementation of the {IERC20} interface.
*
* This implementation is agnostic to the way tokens are created. This means
* that a supply mechanism has to be added in a derived contract using {_mint}.
* For a generic mechanism see {ERC20PresetMinterPauser}.
*
* TIP: For a detailed writeup see our guide
* https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* We have followed general OpenZeppelin Contracts guidelines: functions revert
* instead returning `false` on failure. This behavior is nonetheless
* conventional and does not conflict with the expectations of ERC20
* applications.
*
* Additionally, an {Approval} event is emitted on calls to {transferFrom}.
* This allows applications to reconstruct the allowance for all accounts just
* by listening to said events. Other implementations of the EIP may not emit
* these events, as it isn't required by the specification.
*
* Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
* functions have been added to mitigate the well-known issues around setting
* allowances. See {IERC20-approve}.
*/
contract ERC20 is Context, IERC20, IERC20Metadata {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
/**
* @dev Sets the values for {name} and {symbol}.
*
* The default value of {decimals} is 18. To select a different value for
* {decimals} you should overload it.
*
* All two of these values are immutable: they can only be set once during
* construction.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev Returns the name of the token.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5.05` (`505 / 10 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei. This is the value {ERC20} uses, unless this function is
* overridden;
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/
function decimals() public view virtual override returns (uint8) {
return 18;
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
/**
* @dev See {IERC20-transfer}.
*
* Requirements:
*
* - `recipient` cannot be the zero address.
* - the caller must have a balance of at least `amount`.
*/
function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
/**
* @dev See {IERC20-allowance}.
*/
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
/**
* @dev See {IERC20-approve}.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function approve(address spender, uint256 amount) public virtual override returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
/**
* @dev See {IERC20-transferFrom}.
*
* Emits an {Approval} event indicating the updated allowance. This is not
* required by the EIP. See the note at the beginning of {ERC20}.
*
* Requirements:
*
* - `sender` and `recipient` cannot be the zero address.
* - `sender` must have a balance of at least `amount`.
* - the caller must have allowance for ``sender``'s tokens of at least
* `amount`.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) public virtual override returns (bool) {
_transfer(sender, recipient, amount);
uint256 currentAllowance = _allowances[sender][_msgSender()];
require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
unchecked {
_approve(sender, _msgSender(), currentAllowance - amount);
}
return true;
}
/**
* @dev Atomically increases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);
return true;
}
/**
* @dev Atomically decreases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `spender` must have allowance for the caller of at least
* `subtractedValue`.
*/
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
uint256 currentAllowance = _allowances[_msgSender()][spender];
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(_msgSender(), spender, currentAllowance - subtractedValue);
}
return true;
}
/**
* @dev Moves `amount` of tokens from `sender` to `recipient`.
*
* This internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Emits a {Transfer} event.
*
* Requirements:
*
* - `sender` cannot be the zero address.
* - `recipient` cannot be the zero address.
* - `sender` must have a balance of at least `amount`.
*/
function _transfer(
address sender,
address recipient,
uint256 amount
) internal virtual {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(sender, recipient, amount);
uint256 senderBalance = _balances[sender];
require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[sender] = senderBalance - amount;
}
_balances[recipient] += amount;
emit Transfer(sender, recipient, amount);
_afterTokenTransfer(sender, recipient, amount);
}
/** @dev Creates `amount` tokens and assigns them to `account`, increasing
* the total supply.
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
_balances[account] += amount;
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
/**
* @dev Destroys `amount` tokens from `account`, reducing the
* total supply.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens.
*/
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
}
_totalSupply -= amount;
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
/**
* @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
*
* This internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*/
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
/**
* @dev Hook that is called before any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* will be transferred to `to`.
* - when `from` is zero, `amount` tokens will be minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens will be burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
/**
* @dev Hook that is called after any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* has been transferred to `to`.
* - when `from` is zero, `amount` tokens have been minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens have been burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _afterTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
interface ILiFi {
/* ========== Structs ========== */
struct LiFiData {
bytes32 transactionId;
string integrator;
address referrer;
address sendingAssetId;
address receivingAssetId;
address receiver;
uint256 destinationChainId;
uint256 amount;
}
/* ========== Events ========== */
event LiFiTransferStarted(
bytes32 indexed transactionId,
string integrator,
address referrer,
address sendingAssetId,
address receivingAssetId,
address receiver,
uint256 amount,
uint256 destinationChainId,
uint256 timestamp
);
event LiFiTransferCompleted(
bytes32 indexed transactionId,
address receivingAssetId,
address receiver,
uint256 amount,
uint256 timestamp
);
event LiFiTransferConfirmed(
bytes32 indexed transactionId,
string integrator,
address referrer,
address sendingAssetId,
address receivingAssetId,
address receiver,
uint256 amount,
uint256 destinationChainId,
uint256 timestamp
);
event LiFiTransferRefunded(
bytes32 indexed transactionId,
string integrator,
address referrer,
address sendingAssetId,
address receivingAssetId,
address receiver,
uint256 amount,
uint256 destinationChainId,
uint256 timestamp
);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
interface IAnyswapRouter {
function anySwapOutUnderlying(
address token,
address to,
uint256 amount,
uint256 toChainID
) external;
function anySwapOutNative(
address token,
address to,
uint256 toChainID
) external payable;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import { IDiamondCut } from "../Interfaces/IDiamondCut.sol";
library LibDiamond {
bytes32 internal constant DIAMOND_STORAGE_POSITION = keccak256("diamond.standard.diamond.storage");
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 {
require(msg.sender == diamondStorage().contractOwner, "LibDiamond: Must be contract owner");
}
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; facetIndex++) {
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("LibDiamondCut: Incorrect FacetCutAction");
}
}
emit DiamondCut(_diamondCut, _init, _calldata);
initializeDiamondCut(_init, _calldata);
}
function addFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {
require(_functionSelectors.length > 0, "LibDiamondCut: No selectors in facet to cut");
DiamondStorage storage ds = diamondStorage();
require(_facetAddress != address(0), "LibDiamondCut: Add facet can't be address(0)");
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; selectorIndex++) {
bytes4 selector = _functionSelectors[selectorIndex];
address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;
require(oldFacetAddress == address(0), "LibDiamondCut: Can't add function that already exists");
addFunction(ds, selector, selectorPosition, _facetAddress);
selectorPosition++;
}
}
function replaceFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {
require(_functionSelectors.length > 0, "LibDiamondCut: No selectors in facet to cut");
DiamondStorage storage ds = diamondStorage();
require(_facetAddress != address(0), "LibDiamondCut: Add facet can't be address(0)");
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; selectorIndex++) {
bytes4 selector = _functionSelectors[selectorIndex];
address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;
require(oldFacetAddress != _facetAddress, "LibDiamondCut: Can't replace function with same function");
removeFunction(ds, oldFacetAddress, selector);
addFunction(ds, selector, selectorPosition, _facetAddress);
selectorPosition++;
}
}
function removeFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {
require(_functionSelectors.length > 0, "LibDiamondCut: No selectors in facet to cut");
DiamondStorage storage ds = diamondStorage();
// if function does not exist then do nothing and return
require(_facetAddress == address(0), "LibDiamondCut: Remove facet address must be address(0)");
for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {
bytes4 selector = _functionSelectors[selectorIndex];
address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;
removeFunction(ds, oldFacetAddress, selector);
}
}
function addFacet(DiamondStorage storage ds, address _facetAddress) internal {
enforceHasContractCode(_facetAddress, "LibDiamondCut: New facet has no code");
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 {
require(_facetAddress != address(0), "LibDiamondCut: Can't remove function that doesn't exist");
// an immutable function is a function defined directly in a diamond
require(_facetAddress != address(this), "LibDiamondCut: Can't remove immutable function");
// replace selector with last selector, then delete last 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 (_init == address(0)) {
require(_calldata.length == 0, "LibDiamondCut: _init is address(0) but_calldata is not empty");
} else {
require(_calldata.length > 0, "LibDiamondCut: _calldata is empty but _init is not address(0)");
if (_init != address(this)) {
enforceHasContractCode(_init, "LibDiamondCut: _init address has no code");
}
// 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("LibDiamondCut: _init function reverted");
}
}
}
}
function enforceHasContractCode(address _contract, string memory _errorMessage) internal view {
uint256 contractSize;
// solhint-disable-next-line no-inline-assembly
assembly {
contractSize := extcodesize(_contract)
}
require(contractSize > 0, _errorMessage);
}
}// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.7; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; /** * @title LibAsset * @author Connext <[email protected]> * @notice This library contains helpers for dealing with onchain transfers * of assets, including accounting for the native asset `assetId` * conventions and any noncompliant ERC20 transfers */ library LibAsset { /** * @dev All native assets use the empty address for their asset id * by convention */ address internal constant NATIVE_ASSETID = address(0); /** * @notice Determines whether the given assetId is the native asset * @param assetId The asset identifier to evaluate * @return Boolean indicating if the asset is the native asset */ function isNativeAsset(address assetId) internal pure returns (bool) { return assetId == NATIVE_ASSETID; } /** * @notice Gets the balance of the inheriting contract for the given asset * @param assetId The asset identifier to get the balance of * @return Balance held by contracts using this library */ function getOwnBalance(address assetId) internal view returns (uint256) { return isNativeAsset(assetId) ? address(this).balance : IERC20(assetId).balanceOf(address(this)); } /** * @notice Transfers ether from the inheriting contract to a given * recipient * @param recipient Address to send ether to * @param amount Amount to send to given recipient */ function transferNativeAsset(address payable recipient, uint256 amount) internal { // solhint-disable-next-line avoid-low-level-calls (bool success, ) = recipient.call{ value: amount }(""); require(success, "#TNA:028"); } /** * @notice Gives approval for another address to spend tokens * @param assetId Token address to transfer * @param spender Address to give spend approval to * @param amount Amount to approve for spending */ function approveERC20( IERC20 assetId, address spender, uint256 amount ) internal { if (isNativeAsset(address(assetId))) return; uint256 allowance = assetId.allowance(address(this), spender); if (allowance > 0) SafeERC20.safeApprove(IERC20(assetId), spender, 0); SafeERC20.safeIncreaseAllowance(IERC20(assetId), spender, amount); } /** * @notice Transfers tokens from the inheriting contract to a given * recipient * @param assetId Token address to transfer * @param recipient Address to send ether to * @param amount Amount to send to given recipient */ function transferERC20( address assetId, address recipient, uint256 amount ) internal { SafeERC20.safeTransfer(IERC20(assetId), recipient, amount); } /** * @notice Transfers tokens from a sender to a given recipient * @param assetId Token address to transfer * @param from Address of sender/owner * @param to Address of recipient/spender * @param amount Amount to transfer from owner to spender */ function transferFromERC20( address assetId, address from, address to, uint256 amount ) internal { SafeERC20.safeTransferFrom(IERC20(assetId), from, to, amount); } /** * @notice Increases the allowance of a token to a spender * @param assetId Token address of asset to increase allowance of * @param spender Account whos allowance is increased * @param amount Amount to increase allowance by */ function increaseERC20Allowance( address assetId, address spender, uint256 amount ) internal { require(!isNativeAsset(assetId), "#IA:034"); SafeERC20.safeIncreaseAllowance(IERC20(assetId), spender, amount); } /** * @notice Decreases the allowance of a token to a spender * @param assetId Token address of asset to decrease allowance of * @param spender Account whos allowance is decreased * @param amount Amount to decrease allowance by */ function decreaseERC20Allowance( address assetId, address spender, uint256 amount ) internal { require(!isNativeAsset(assetId), "#DA:034"); SafeERC20.safeDecreaseAllowance(IERC20(assetId), spender, amount); } /** * @notice Wrapper function to transfer a given asset (native or erc20) to * some recipient. Should handle all non-compliant return value * tokens as well by using the SafeERC20 contract by open zeppelin. * @param assetId Asset id for transfer (address(0) for native asset, * token address for erc20s) * @param recipient Address to send asset to * @param amount Amount to send to given recipient */ function transferAsset( address assetId, address payable recipient, uint256 amount ) internal { isNativeAsset(assetId) ? transferNativeAsset(recipient, amount) : transferERC20(assetId, recipient, amount); } }
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import { LibAsset } from "./LibAsset.sol";
import { LibUtil } from "./LibUtil.sol";
library LibSwap {
struct SwapData {
address callTo;
address approveTo;
address sendingAssetId;
address receivingAssetId;
uint256 fromAmount;
bytes callData;
}
event AssetSwapped(
bytes32 transactionId,
address dex,
address fromAssetId,
address toAssetId,
uint256 fromAmount,
uint256 toAmount,
uint256 timestamp
);
function swap(bytes32 transactionId, SwapData calldata _swapData) internal {
uint256 fromAmount = _swapData.fromAmount;
uint256 toAmount = LibAsset.getOwnBalance(_swapData.receivingAssetId);
address fromAssetId = _swapData.sendingAssetId;
if (!LibAsset.isNativeAsset(fromAssetId) && LibAsset.getOwnBalance(fromAssetId) < fromAmount) {
LibAsset.transferFromERC20(_swapData.sendingAssetId, msg.sender, address(this), fromAmount);
}
if (!LibAsset.isNativeAsset(fromAssetId)) {
LibAsset.approveERC20(IERC20(fromAssetId), _swapData.approveTo, fromAmount);
}
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory res) = _swapData.callTo.call{ value: msg.value }(_swapData.callData);
if (!success) {
string memory reason = LibUtil.getRevertMsg(res);
revert(reason);
}
toAmount = LibAsset.getOwnBalance(_swapData.receivingAssetId) - toAmount;
emit AssetSwapped(
transactionId,
_swapData.callTo,
_swapData.sendingAssetId,
_swapData.receivingAssetId,
fromAmount,
toAmount,
block.timestamp
);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
interface IAnyswapToken {
function underlying() external returns (address);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
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.0;
import "../IERC20.sol";
import "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
// Return data is optional
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
assembly {
size := extcodesize(account)
}
return size > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
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
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
library LibBytes {
// solhint-disable no-inline-assembly
function concat(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bytes memory) {
bytes memory tempBytes;
assembly {
// Get a location of some free memory and store it in tempBytes as
// Solidity does for memory variables.
tempBytes := mload(0x40)
// Store the length of the first bytes array at the beginning of
// the memory for tempBytes.
let length := mload(_preBytes)
mstore(tempBytes, length)
// Maintain a memory counter for the current write location in the
// temp bytes array by adding the 32 bytes for the array length to
// the starting location.
let mc := add(tempBytes, 0x20)
// Stop copying when the memory counter reaches the length of the
// first bytes array.
let end := add(mc, length)
for {
// Initialize a copy counter to the start of the _preBytes data,
// 32 bytes into its memory.
let cc := add(_preBytes, 0x20)
} lt(mc, end) {
// Increase both counters by 32 bytes each iteration.
mc := add(mc, 0x20)
cc := add(cc, 0x20)
} {
// Write the _preBytes data into the tempBytes memory 32 bytes
// at a time.
mstore(mc, mload(cc))
}
// Add the length of _postBytes to the current length of tempBytes
// and store it as the new length in the first 32 bytes of the
// tempBytes memory.
length := mload(_postBytes)
mstore(tempBytes, add(length, mload(tempBytes)))
// Move the memory counter back from a multiple of 0x20 to the
// actual end of the _preBytes data.
mc := end
// Stop copying when the memory counter reaches the new combined
// length of the arrays.
end := add(mc, length)
for {
let cc := add(_postBytes, 0x20)
} lt(mc, end) {
mc := add(mc, 0x20)
cc := add(cc, 0x20)
} {
mstore(mc, mload(cc))
}
// Update the free-memory pointer by padding our last write location
// to 32 bytes: add 31 bytes to the end of tempBytes to move to the
// next 32 byte block, then round down to the nearest multiple of
// 32. If the sum of the length of the two arrays is zero then add
// one before rounding down to leave a blank 32 bytes (the length block with 0).
mstore(
0x40,
and(
add(add(end, iszero(add(length, mload(_preBytes)))), 31),
not(31) // Round down to the nearest 32 bytes.
)
)
}
return tempBytes;
}
function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal {
assembly {
// Read the first 32 bytes of _preBytes storage, which is the length
// of the array. (We don't need to use the offset into the slot
// because arrays use the entire slot.)
let fslot := sload(_preBytes.slot)
// Arrays of 31 bytes or less have an even value in their slot,
// while longer arrays have an odd value. The actual length is
// the slot divided by two for odd values, and the lowest order
// byte divided by two for even values.
// If the slot is even, bitwise and the slot with 255 and divide by
// two to get the length. If the slot is odd, bitwise and the slot
// with -1 and divide by two.
let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)
let mlength := mload(_postBytes)
let newlength := add(slength, mlength)
// slength can contain both the length and contents of the array
// if length < 32 bytes so let's prepare for that
// v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage
switch add(lt(slength, 32), lt(newlength, 32))
case 2 {
// Since the new array still fits in the slot, we just need to
// update the contents of the slot.
// uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length
sstore(
_preBytes.slot,
// all the modifications to the slot are inside this
// next block
add(
// we can just add to the slot contents because the
// bytes we want to change are the LSBs
fslot,
add(
mul(
div(
// load the bytes from memory
mload(add(_postBytes, 0x20)),
// zero all bytes to the right
exp(0x100, sub(32, mlength))
),
// and now shift left the number of bytes to
// leave space for the length in the slot
exp(0x100, sub(32, newlength))
),
// increase length by the double of the memory
// bytes length
mul(mlength, 2)
)
)
)
}
case 1 {
// The stored value fits in the slot, but the combined value
// will exceed it.
// get the keccak hash to get the contents of the array
mstore(0x0, _preBytes.slot)
let sc := add(keccak256(0x0, 0x20), div(slength, 32))
// save new length
sstore(_preBytes.slot, add(mul(newlength, 2), 1))
// The contents of the _postBytes array start 32 bytes into
// the structure. Our first read should obtain the `submod`
// bytes that can fit into the unused space in the last word
// of the stored array. To get this, we read 32 bytes starting
// from `submod`, so the data we read overlaps with the array
// contents by `submod` bytes. Masking the lowest-order
// `submod` bytes allows us to add that value directly to the
// stored value.
let submod := sub(32, slength)
let mc := add(_postBytes, submod)
let end := add(_postBytes, mlength)
let mask := sub(exp(0x100, submod), 1)
sstore(
sc,
add(
and(fslot, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00),
and(mload(mc), mask)
)
)
for {
mc := add(mc, 0x20)
sc := add(sc, 1)
} lt(mc, end) {
sc := add(sc, 1)
mc := add(mc, 0x20)
} {
sstore(sc, mload(mc))
}
mask := exp(0x100, sub(mc, end))
sstore(sc, mul(div(mload(mc), mask), mask))
}
default {
// get the keccak hash to get the contents of the array
mstore(0x0, _preBytes.slot)
// Start copying to the last used word of the stored array.
let sc := add(keccak256(0x0, 0x20), div(slength, 32))
// save new length
sstore(_preBytes.slot, add(mul(newlength, 2), 1))
// Copy over the first `submod` bytes of the new data as in
// case 1 above.
let slengthmod := mod(slength, 32)
let submod := sub(32, slengthmod)
let mc := add(_postBytes, submod)
let end := add(_postBytes, mlength)
let mask := sub(exp(0x100, submod), 1)
sstore(sc, add(sload(sc), and(mload(mc), mask)))
for {
sc := add(sc, 1)
mc := add(mc, 0x20)
} lt(mc, end) {
sc := add(sc, 1)
mc := add(mc, 0x20)
} {
sstore(sc, mload(mc))
}
mask := exp(0x100, sub(mc, end))
sstore(sc, mul(div(mload(mc), mask), mask))
}
}
}
function slice(
bytes memory _bytes,
uint256 _start,
uint256 _length
) internal pure returns (bytes memory) {
require(_length + 31 >= _length, "slice_overflow");
require(_bytes.length >= _start + _length, "slice_outOfBounds");
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) {
require(_bytes.length >= _start + 20, "toAddress_outOfBounds");
address tempAddress;
assembly {
tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)
}
return tempAddress;
}
function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) {
require(_bytes.length >= _start + 1, "toUint8_outOfBounds");
uint8 tempUint;
assembly {
tempUint := mload(add(add(_bytes, 0x1), _start))
}
return tempUint;
}
function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) {
require(_bytes.length >= _start + 2, "toUint16_outOfBounds");
uint16 tempUint;
assembly {
tempUint := mload(add(add(_bytes, 0x2), _start))
}
return tempUint;
}
function toUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) {
require(_bytes.length >= _start + 4, "toUint32_outOfBounds");
uint32 tempUint;
assembly {
tempUint := mload(add(add(_bytes, 0x4), _start))
}
return tempUint;
}
function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) {
require(_bytes.length >= _start + 8, "toUint64_outOfBounds");
uint64 tempUint;
assembly {
tempUint := mload(add(add(_bytes, 0x8), _start))
}
return tempUint;
}
function toUint96(bytes memory _bytes, uint256 _start) internal pure returns (uint96) {
require(_bytes.length >= _start + 12, "toUint96_outOfBounds");
uint96 tempUint;
assembly {
tempUint := mload(add(add(_bytes, 0xc), _start))
}
return tempUint;
}
function toUint128(bytes memory _bytes, uint256 _start) internal pure returns (uint128) {
require(_bytes.length >= _start + 16, "toUint128_outOfBounds");
uint128 tempUint;
assembly {
tempUint := mload(add(add(_bytes, 0x10), _start))
}
return tempUint;
}
function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) {
require(_bytes.length >= _start + 32, "toUint256_outOfBounds");
uint256 tempUint;
assembly {
tempUint := mload(add(add(_bytes, 0x20), _start))
}
return tempUint;
}
function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) {
require(_bytes.length >= _start + 32, "toBytes32_outOfBounds");
bytes32 tempBytes32;
assembly {
tempBytes32 := mload(add(add(_bytes, 0x20), _start))
}
return tempBytes32;
}
function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) {
bool success = true;
assembly {
let length := mload(_preBytes)
// if lengths don't match the arrays are not equal
switch eq(length, mload(_postBytes))
case 1 {
// cb is a circuit breaker in the for loop since there's
// no said feature for inline assembly loops
// cb = 1 - don't breaker
// cb = 0 - break
let cb := 1
let mc := add(_preBytes, 0x20)
let end := add(mc, length)
for {
let cc := add(_postBytes, 0x20)
// the next line is the loop condition:
// while(uint256(mc < end) + cb == 2)
} eq(add(lt(mc, end), cb), 2) {
mc := add(mc, 0x20)
cc := add(cc, 0x20)
} {
// if any of these checks fails then arrays are not equal
if iszero(eq(mload(mc), mload(cc))) {
// unsuccess:
success := 0
cb := 0
}
}
}
default {
// unsuccess:
success := 0
}
}
return success;
}
function equalStorage(bytes storage _preBytes, bytes memory _postBytes) internal view returns (bool) {
bool success = true;
assembly {
// we know _preBytes_offset is 0
let fslot := sload(_preBytes.slot)
// Decode the length of the stored array like in concatStorage().
let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)
let mlength := mload(_postBytes)
// if lengths don't match the arrays are not equal
switch eq(slength, mlength)
case 1 {
// slength can contain both the length and contents of the array
// if length < 32 bytes so let's prepare for that
// v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage
if iszero(iszero(slength)) {
switch lt(slength, 32)
case 1 {
// blank the last byte which is the length
fslot := mul(div(fslot, 0x100), 0x100)
if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) {
// unsuccess:
success := 0
}
}
default {
// cb is a circuit breaker in the for loop since there's
// no said feature for inline assembly loops
// cb = 1 - don't breaker
// cb = 0 - break
let cb := 1
// get the keccak hash to get the contents of the array
mstore(0x0, _preBytes.slot)
let sc := keccak256(0x0, 0x20)
let mc := add(_postBytes, 0x20)
let end := add(mc, mlength)
// the next line is the loop condition:
// while(uint256(mc < end) + cb == 2)
// solhint-disable-next-line no-empty-blocks
for {
} eq(add(lt(mc, end), cb), 2) {
sc := add(sc, 1)
mc := add(mc, 0x20)
} {
if iszero(eq(sload(sc), mload(mc))) {
// unsuccess:
success := 0
cb := 0
}
}
}
}
}
default {
// unsuccess:
success := 0
}
}
return success;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import { ITransactionManager } from "../Interfaces/ITransactionManager.sol";
import { ILiFi } from "../Interfaces/ILiFi.sol";
import { LibAsset } from "../Libraries/LibAsset.sol";
import { LibSwap } from "../Libraries/LibSwap.sol";
import { LibDiamond } from "../Libraries/LibDiamond.sol";
contract NXTPFacet is ILiFi {
/* ========== Storage ========== */
bytes32 internal constant NAMESPACE = keccak256("com.lifi.facets.nxtp");
struct Storage {
ITransactionManager nxtpTxManager;
}
/* ========== Events ========== */
event NXTPBridgeStarted(
bytes32 indexed lifiTransactionId,
bytes32 nxtpTransactionId,
ITransactionManager.TransactionData txData
);
/* ========== Init ========== */
function initNXTP(ITransactionManager _txMgrAddr) external {
Storage storage s = getStorage();
LibDiamond.enforceIsContractOwner();
s.nxtpTxManager = _txMgrAddr;
}
/* ========== Public Bridge Functions ========== */
/**
* @notice This function starts a cross-chain transaction using the NXTP protocol
* @param _lifiData data used purely for tracking and analytics
* @param _nxtpData data needed to complete an NXTP cross-chain transaction
*/
function startBridgeTokensViaNXTP(LiFiData memory _lifiData, ITransactionManager.PrepareArgs memory _nxtpData)
public
payable
{
// Ensure sender has enough to complete the bridge transaction
address sendingAssetId = _nxtpData.invariantData.sendingAssetId;
if (sendingAssetId == address(0)) require(msg.value == _nxtpData.amount, "ERR_INVALID_AMOUNT");
else {
uint256 _sendingAssetIdBalance = LibAsset.getOwnBalance(sendingAssetId);
LibAsset.transferFromERC20(sendingAssetId, msg.sender, address(this), _nxtpData.amount);
require(
LibAsset.getOwnBalance(sendingAssetId) - _sendingAssetIdBalance == _nxtpData.amount,
"ERR_INVALID_AMOUNT"
);
}
// Start the bridge process
_startBridge(_lifiData.transactionId, _nxtpData);
emit LiFiTransferStarted(
_lifiData.transactionId,
_lifiData.integrator,
_lifiData.referrer,
_lifiData.sendingAssetId,
_lifiData.receivingAssetId,
_lifiData.receiver,
_lifiData.amount,
_lifiData.destinationChainId,
block.timestamp
);
}
/**
* @notice This function performs a swap or multiple swaps and then starts a cross-chain transaction
* using the NXTP protocol.
* @param _lifiData data used purely for tracking and analytics
* @param _swapData array of data needed for swaps
* @param _nxtpData data needed to complete an NXTP cross-chain transaction
*/
function swapAndStartBridgeTokensViaNXTP(
LiFiData memory _lifiData,
LibSwap.SwapData[] calldata _swapData,
ITransactionManager.PrepareArgs memory _nxtpData
) public payable {
address sendingAssetId = _nxtpData.invariantData.sendingAssetId;
uint256 _sendingAssetIdBalance = LibAsset.getOwnBalance(sendingAssetId);
// Swap
for (uint8 i; i < _swapData.length; i++) {
LibSwap.swap(_lifiData.transactionId, _swapData[i]);
}
uint256 _postSwapBalance = LibAsset.getOwnBalance(sendingAssetId) - _sendingAssetIdBalance;
require(_postSwapBalance > 0, "ERR_INVALID_AMOUNT");
_nxtpData.amount = _postSwapBalance;
_startBridge(_lifiData.transactionId, _nxtpData);
emit LiFiTransferStarted(
_lifiData.transactionId,
_lifiData.integrator,
_lifiData.referrer,
_lifiData.sendingAssetId,
_lifiData.receivingAssetId,
_lifiData.receiver,
_lifiData.amount,
_lifiData.destinationChainId,
block.timestamp
);
}
/**
* @notice Completes a cross-chain transaction on the receiving chain using the NXTP protocol.
* @param _lifiData data used purely for tracking and analytics
* @param assetId token received on the receiving chain
* @param receiver address that will receive the tokens
* @param amount number of tokens received
*/
function completeBridgeTokensViaNXTP(
LiFiData memory _lifiData,
address assetId,
address receiver,
uint256 amount
) public payable {
if (LibAsset.isNativeAsset(assetId)) {
require(msg.value == amount, "INVALID_ETH_AMOUNT");
} else {
require(msg.value == 0, "ETH_WITH_ERC");
LibAsset.transferFromERC20(assetId, msg.sender, address(this), amount);
}
LibAsset.transferAsset(assetId, payable(receiver), amount);
emit LiFiTransferCompleted(_lifiData.transactionId, assetId, receiver, amount, block.timestamp);
}
/**
* @notice Performs a swap before completing a cross-chain transaction
* on the receiving chain using the NXTP protocol.
* @param _lifiData data used purely for tracking and analytics
* @param _swapData array of data needed for swaps
* @param finalAssetId token received on the receiving chain
* @param receiver address that will receive the tokens
*/
function swapAndCompleteBridgeTokensViaNXTP(
LiFiData memory _lifiData,
LibSwap.SwapData[] calldata _swapData,
address finalAssetId,
address receiver
) public payable {
uint256 startingBalance = LibAsset.getOwnBalance(finalAssetId);
// Swap
for (uint8 i; i < _swapData.length; i++) {
LibSwap.swap(_lifiData.transactionId, _swapData[i]);
}
uint256 postSwapBalance = LibAsset.getOwnBalance(finalAssetId);
uint256 finalBalance;
if (postSwapBalance > startingBalance) {
finalBalance = postSwapBalance - startingBalance;
LibAsset.transferAsset(finalAssetId, payable(receiver), finalBalance);
}
emit LiFiTransferCompleted(_lifiData.transactionId, finalAssetId, receiver, finalBalance, block.timestamp);
}
/* ========== Internal Functions ========== */
function _startBridge(bytes32 _transactionId, ITransactionManager.PrepareArgs memory _nxtpData) internal {
Storage storage s = getStorage();
IERC20 sendingAssetId = IERC20(_nxtpData.invariantData.sendingAssetId);
// Give Connext approval to bridge tokens
LibAsset.approveERC20(IERC20(sendingAssetId), address(s.nxtpTxManager), _nxtpData.amount);
uint256 value = LibAsset.isNativeAsset(address(sendingAssetId)) ? msg.value : 0;
// Initiate bridge transaction on sending chain
ITransactionManager.TransactionData memory result = s.nxtpTxManager.prepare{ value: value }(_nxtpData);
emit NXTPBridgeStarted(_transactionId, result.transactionId, result);
}
function getStorage() internal pure returns (Storage storage s) {
bytes32 namespace = NAMESPACE;
// solhint-disable-next-line no-inline-assembly
assembly {
s.slot := namespace
}
}
/* ========== Getter Functions ========== */
/**
* @notice show the NXTP transaction manager contract address
*/
function getNXTPTransactionManager() external view returns (address) {
Storage storage s = getStorage();
return address(s.nxtpTxManager);
}
}// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.7;
interface ITransactionManager {
// Structs
// Holds all data that is constant between sending and
// receiving chains. The hash of this is what gets signed
// to ensure the signature can be used on both chains.
struct InvariantTransactionData {
address receivingChainTxManagerAddress;
address user;
address router;
address initiator; // msg.sender of sending side
address sendingAssetId;
address receivingAssetId;
address sendingChainFallback; // funds sent here on cancel
address receivingAddress;
address callTo;
uint256 sendingChainId;
uint256 receivingChainId;
bytes32 callDataHash; // hashed to prevent free option
bytes32 transactionId;
}
// Holds all data that varies between sending and receiving
// chains. The hash of this is stored onchain to ensure the
// information passed in is valid.
struct VariantTransactionData {
uint256 amount;
uint256 expiry;
uint256 preparedBlockNumber;
}
// All Transaction data, constant and variable
struct TransactionData {
address receivingChainTxManagerAddress;
address user;
address router;
address initiator; // msg.sender of sending side
address sendingAssetId;
address receivingAssetId;
address sendingChainFallback;
address receivingAddress;
address callTo;
bytes32 callDataHash;
bytes32 transactionId;
uint256 sendingChainId;
uint256 receivingChainId;
uint256 amount;
uint256 expiry;
uint256 preparedBlockNumber; // Needed for removal of active blocks on fulfill/cancel
}
// The structure of the signed data for fulfill
struct SignedFulfillData {
bytes32 transactionId;
uint256 relayerFee;
string functionIdentifier; // "fulfill" or "cancel"
uint256 receivingChainId; // For domain separation
address receivingChainTxManagerAddress; // For domain separation
}
// The structure of the signed data for cancellation
struct SignedCancelData {
bytes32 transactionId;
string functionIdentifier;
uint256 receivingChainId;
address receivingChainTxManagerAddress; // For domain separation
}
/**
* Arguments for calling prepare()
* @param invariantData The data for a crosschain transaction that will
* not change between sending and receiving chains.
* The hash of this data is used as the key to store
* the inforamtion that does change between chains
* (amount,expiry,preparedBlock) for verification
* @param amount The amount of the transaction on this chain
* @param expiry The block.timestamp when the transaction will no longer be
* fulfillable and is freely cancellable on this chain
* @param encryptedCallData The calldata to be executed when the tx is
* fulfilled. Used in the function to allow the user
* to reconstruct the tx from events. Hash is stored
* onchain to prevent shenanigans.
* @param encodedBid The encoded bid that was accepted by the user for this
* crosschain transfer. It is supplied as a param to the
* function but is only used in event emission
* @param bidSignature The signature of the bidder on the encoded bid for
* this transaction. Only used within the function for
* event emission. The validity of the bid and
* bidSignature are enforced offchain
* @param encodedMeta The meta for the function
*/
struct PrepareArgs {
InvariantTransactionData invariantData;
uint256 amount;
uint256 expiry;
bytes encryptedCallData;
bytes encodedBid;
bytes bidSignature;
bytes encodedMeta;
}
/**
* @param txData All of the data (invariant and variant) for a crosschain
* transaction. The variant data provided is checked against
* what was stored when the `prepare` function was called.
* @param relayerFee The fee that should go to the relayer when they are
* calling the function on the receiving chain for the user
* @param signature The users signature on the transaction id + fee that
* can be used by the router to unlock the transaction on
* the sending chain
* @param callData The calldata to be sent to and executed by the
* `FulfillHelper`
* @param encodedMeta The meta for the function
*/
struct FulfillArgs {
TransactionData txData;
uint256 relayerFee;
bytes signature;
bytes callData;
bytes encodedMeta;
}
/**
* Arguments for calling cancel()
* @param txData All of the data (invariant and variant) for a crosschain
* transaction. The variant data provided is checked against
* what was stored when the `prepare` function was called.
* @param signature The user's signature that allows a transaction to be
* cancelled by a relayer
* @param encodedMeta The meta for the function
*/
struct CancelArgs {
TransactionData txData;
bytes signature;
bytes encodedMeta;
}
// Adding/removing asset events
event RouterAdded(address indexed addedRouter, address indexed caller);
event RouterRemoved(address indexed removedRouter, address indexed caller);
// Adding/removing router events
event AssetAdded(address indexed addedAssetId, address indexed caller);
event AssetRemoved(address indexed removedAssetId, address indexed caller);
// Liquidity events
event LiquidityAdded(address indexed router, address indexed assetId, uint256 amount, address caller);
event LiquidityRemoved(address indexed router, address indexed assetId, uint256 amount, address recipient);
// Transaction events
event TransactionPrepared(
address indexed user,
address indexed router,
bytes32 indexed transactionId,
TransactionData txData,
address caller,
PrepareArgs args
);
event TransactionFulfilled(
address indexed user,
address indexed router,
bytes32 indexed transactionId,
FulfillArgs args,
bool success,
bool isContract,
bytes returnData,
address caller
);
event TransactionCancelled(
address indexed user,
address indexed router,
bytes32 indexed transactionId,
CancelArgs args,
address caller
);
// Getters
function getChainId() external view returns (uint256);
function getStoredChainId() external view returns (uint256);
// Owner only methods
function addRouter(address router) external;
function removeRouter(address router) external;
function addAssetId(address assetId) external;
function removeAssetId(address assetId) external;
// Router only methods
function addLiquidityFor(
uint256 amount,
address assetId,
address router
) external payable;
function addLiquidity(uint256 amount, address assetId) external payable;
function removeLiquidity(
uint256 amount,
address assetId,
address payable recipient
) external;
// Methods for crosschain transfers
// called in the following order (in happy case)
// 1. prepare by user on sending chain
// 2. prepare by router on receiving chain
// 3. fulfill by user on receiving chain
// 4. fulfill by router on sending chain
function prepare(PrepareArgs calldata args) external payable returns (TransactionData memory);
function fulfill(FulfillArgs calldata args) external returns (TransactionData memory);
function cancel(CancelArgs calldata args) external returns (TransactionData memory);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import { LibDiamond } from "./Libraries/LibDiamond.sol";
import { IDiamondCut } from "./Interfaces/IDiamondCut.sol";
contract LiFiDiamond {
constructor(address _contractOwner, address _diamondCutFacet) payable {
LibDiamond.setContractOwner(_contractOwner);
// Add the diamondCut external function from the diamondCutFacet
IDiamondCut.FacetCut[] memory cut = new IDiamondCut.FacetCut[](1);
bytes4[] memory functionSelectors = new bytes4[](1);
functionSelectors[0] = IDiamondCut.diamondCut.selector;
cut[0] = IDiamondCut.FacetCut({
facetAddress: _diamondCutFacet,
action: IDiamondCut.FacetCutAction.Add,
functionSelectors: functionSelectors
});
LibDiamond.diamondCut(cut, address(0), "");
}
// Find facet for function that is called and execute the
// function if a facet is found and return any value.
// solhint-disable-next-line no-complex-fallback
fallback() external payable {
LibDiamond.DiamondStorage storage ds;
bytes32 position = LibDiamond.DIAMOND_STORAGE_POSITION;
// get diamond storage
// solhint-disable-next-line no-inline-assembly
assembly {
ds.slot := position
}
// get facet from function selector
address facet = ds.selectorToFacetAndPosition[msg.sig].facetAddress;
require(facet != address(0), "Diamond: Function does not exist");
// Execute external function from facet using delegatecall and return any value.
// solhint-disable-next-line no-inline-assembly
assembly {
// copy function selector and any arguments
calldatacopy(0, 0, calldatasize())
// execute function call using the facet
let result := delegatecall(gas(), facet, 0, calldatasize(), 0, 0)
// get any return value
returndatacopy(0, 0, returndatasize())
// return any return value or error back to the caller
switch result
case 0 {
revert(0, returndatasize())
}
default {
return(0, returndatasize())
}
}
}
// Able to receive ether
// solhint-disable-next-line no-empty-blocks
receive() external payable {}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { LibDiamond } from "../Libraries/LibDiamond.sol";
contract WithdrawFacet {
using SafeERC20 for IERC20;
address private constant NATIVE_ASSET = address(0);
event LogWithdraw(address indexed _assetAddress, address _from, uint256 amount);
/**
* @dev Withdraw asset.
* @param _assetAddress Asset to be withdrawn.
* @param _to address to withdraw to.
* @param _amount amount of asset to withdraw.
*/
function withdraw(
address _assetAddress,
address _to,
uint256 _amount
) public {
LibDiamond.enforceIsContractOwner();
address sendTo = (_to == address(0)) ? msg.sender : _to;
uint256 assetBalance;
if (_assetAddress == NATIVE_ASSET) {
address self = address(this); // workaround for a possible solidity bug
assert(_amount <= self.balance);
payable(sendTo).transfer(_amount);
} else {
assetBalance = IERC20(_assetAddress).balanceOf(address(this));
assert(_amount <= assetBalance);
IERC20(_assetAddress).safeTransfer(sendTo, _amount);
}
emit LogWithdraw(sendTo, _assetAddress, _amount);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import { ILiFi } from "../Interfaces/ILiFi.sol";
import { IHopBridge } from "../Interfaces/IHopBridge.sol";
import { LibAsset } from "../Libraries/LibAsset.sol";
import { LibSwap } from "../Libraries/LibSwap.sol";
import { LibDiamond } from "../Libraries/LibDiamond.sol";
contract HopFacet is ILiFi {
/* ========== Storage ========== */
bytes32 internal constant NAMESPACE = keccak256("com.lifi.facets.hop");
struct Storage {
mapping(string => IHopBridge.BridgeConfig) hopBridges;
uint256 hopChainId;
}
/* ========== Types ========== */
struct HopData {
string asset;
address recipient;
uint256 chainId;
uint256 amount;
uint256 bonderFee;
uint256 amountOutMin;
uint256 deadline;
uint256 destinationAmountOutMin;
uint256 destinationDeadline;
}
/* ========== Init ========== */
function initHop(
string[] memory _tokens,
IHopBridge.BridgeConfig[] memory _bridgeConfigs,
uint256 _chainId
) external {
Storage storage s = getStorage();
LibDiamond.enforceIsContractOwner();
for (uint8 i; i < _tokens.length; i++) {
s.hopBridges[_tokens[i]] = _bridgeConfigs[i];
}
s.hopChainId = _chainId;
}
/* ========== Public Bridge Functions ========== */
/**
* @notice Bridges tokens via Hop Protocol
* @param _lifiData data used purely for tracking and analytics
* @param _hopData data specific to Hop Protocol
*/
function startBridgeTokensViaHop(LiFiData memory _lifiData, HopData calldata _hopData) public payable {
address fromToken = _bridge(_hopData.asset).token;
uint256 _fromTokenBalance = LibAsset.getOwnBalance(fromToken);
LibAsset.transferFromERC20(fromToken, msg.sender, address(this), _hopData.amount);
require(LibAsset.getOwnBalance(fromToken) - _fromTokenBalance == _hopData.amount, "ERR_INVALID_AMOUNT");
_startBridge(_hopData);
emit LiFiTransferStarted(
_lifiData.transactionId,
_lifiData.integrator,
_lifiData.referrer,
_lifiData.sendingAssetId,
_lifiData.receivingAssetId,
_lifiData.receiver,
_lifiData.amount,
_lifiData.destinationChainId,
block.timestamp
);
}
/**
* @notice Performs a swap before bridging via Hop Protocol
* @param _lifiData data used purely for tracking and analytics
* @param _swapData an array of swap related data for performing swaps before bridging
* @param _hopData data specific to Hop Protocol
*/
function swapAndStartBridgeTokensViaHop(
LiFiData memory _lifiData,
LibSwap.SwapData[] calldata _swapData,
HopData calldata _hopData
) public payable {
address fromToken = _bridge(_hopData.asset).token;
uint256 _fromTokenBalance = LibAsset.getOwnBalance(fromToken);
// Swap
for (uint8 i; i < _swapData.length; i++) {
LibSwap.swap(_lifiData.transactionId, _swapData[i]);
}
require(LibAsset.getOwnBalance(fromToken) - _fromTokenBalance >= _hopData.amount, "ERR_INVALID_AMOUNT");
_startBridge(_hopData);
emit LiFiTransferStarted(
_lifiData.transactionId,
_lifiData.integrator,
_lifiData.referrer,
_lifiData.sendingAssetId,
_lifiData.receivingAssetId,
_lifiData.receiver,
_lifiData.amount,
_lifiData.destinationChainId,
block.timestamp
);
}
/* ========== Internal Functions ========== */
/**
* @dev Conatains the business logic for the bridge via Hop Protocol
* @param _hopData data specific to Hop Protocol
*/
function _startBridge(HopData calldata _hopData) internal {
Storage storage s = getStorage();
address fromToken = _bridge(_hopData.asset).token;
address bridge;
if (s.hopChainId == 1) {
bridge = _bridge(_hopData.asset).bridge;
} else {
bridge = _bridge(_hopData.asset).ammWrapper;
}
// Do HOP stuff
require(s.hopChainId != _hopData.chainId, "Cannot bridge to the same network.");
// Give Hop approval to bridge tokens
LibAsset.approveERC20(IERC20(fromToken), bridge, _hopData.amount);
if (s.hopChainId == 1) {
// Ethereum L1
IHopBridge(bridge).sendToL2(
_hopData.chainId,
_hopData.recipient,
_hopData.amount,
_hopData.destinationAmountOutMin,
_hopData.destinationDeadline,
address(0),
0
);
} else {
// L2
// solhint-disable-next-line check-send-result
IHopBridge(bridge).swapAndSend(
_hopData.chainId,
_hopData.recipient,
_hopData.amount,
_hopData.bonderFee,
_hopData.amountOutMin,
_hopData.deadline,
_hopData.destinationAmountOutMin,
_hopData.destinationDeadline
);
}
}
function _bridge(string memory _asset) internal view returns (IHopBridge.BridgeConfig memory) {
Storage storage s = getStorage();
return s.hopBridges[_asset];
}
function getStorage() internal pure returns (Storage storage s) {
bytes32 namespace = NAMESPACE;
// solhint-disable-next-line no-inline-assembly
assembly {
s.slot := namespace
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
interface IHopBridge {
struct BridgeConfig {
address token;
address bridge;
address ammWrapper;
}
function sendToL2(
uint256 chainId,
address recipient,
uint256 amount,
uint256 amountOutMin,
uint256 deadline,
address relayer,
uint256 relayerFee
) external payable;
function swapAndSend(
uint256 chainId,
address recipient,
uint256 amount,
uint256 bonderFee,
uint256 amountOutMin,
uint256 deadline,
uint256 destinationAmountOutMin,
uint256 destinationDeadline
) external payable;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import { ILiFi } from "../Interfaces/ILiFi.sol";
import { LibAsset } from "../Libraries/LibAsset.sol";
import { LibSwap } from "../Libraries/LibSwap.sol";
import { LibUtil } from "../Libraries/LibUtil.sol";
contract GenericBridgeFacet is ILiFi {
/* ========== Types ========== */
struct BridgeData {
uint256 amount;
address assetId;
address callTo;
bytes callData;
}
/* ========== Public Bridge Functions ========== */
/**
* @notice Bridges tokens via Generic Bridge
* @param _lifiData data used purely for tracking and analytics
* @param _bridgeData data used for bridging via various contracts
*/
function startBridgeTokensGeneric(LiFiData memory _lifiData, BridgeData memory _bridgeData) public payable {
LibAsset.transferFromERC20(_bridgeData.assetId, msg.sender, address(this), _bridgeData.amount);
_startBridge(_bridgeData);
emit LiFiTransferStarted(
_lifiData.transactionId,
_lifiData.integrator,
_lifiData.referrer,
_lifiData.sendingAssetId,
_lifiData.receivingAssetId,
_lifiData.receiver,
_lifiData.amount,
_lifiData.destinationChainId,
block.timestamp
);
}
/**
* @notice Performs a swap before bridging via Hop Protocol
* @param _lifiData data used purely for tracking and analytics
* @param _swapData an array of swap related data for performing swaps before bridging
* @param _bridgeData data used for bridging via various contracts
*/
function swapAndStartBridgeTokensGeneric(
LiFiData memory _lifiData,
LibSwap.SwapData[] calldata _swapData,
BridgeData memory _bridgeData
) public payable {
uint256 _fromTokenBalance = LibAsset.getOwnBalance(_bridgeData.assetId);
// Swap
for (uint8 i; i < _swapData.length; i++) {
LibSwap.swap(_lifiData.transactionId, _swapData[i]);
}
require(
LibAsset.getOwnBalance(_bridgeData.assetId) - _fromTokenBalance >= _bridgeData.amount,
"ERR_INVALID_AMOUNT"
);
_startBridge(_bridgeData);
emit LiFiTransferStarted(
_lifiData.transactionId,
_lifiData.integrator,
_lifiData.referrer,
_lifiData.sendingAssetId,
_lifiData.receivingAssetId,
_lifiData.receiver,
_lifiData.amount,
_lifiData.destinationChainId,
block.timestamp
);
}
/* ========== Internal Functions ========== */
/**
* @dev Conatains the business logic for the bridge via Hop Protocol
*/
function _startBridge(BridgeData memory _bridgeData) internal {
LibAsset.approveERC20(IERC20(_bridgeData.assetId), _bridgeData.callTo, _bridgeData.amount);
(bool success, bytes memory res) = _bridgeData.callTo.call{ value: msg.value }(_bridgeData.callData);
if (!success) {
string memory reason = LibUtil.getRevertMsg(res);
revert(reason);
}
}
}// SPDX-License-Identifier: MIT
// for testing only not for production
// solhint-disable
pragma solidity ^0.8.3;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract USDT is ERC20 {
constructor(
address receiver,
string memory name,
string memory symbol
) ERC20(name, symbol) {
// Mint 100 tokens to msg.sender
// Similar to how
// 1 dollar = 100 cents
// 1 token = 1 * (10 ** decimals)
_mint(receiver, 10000 * 10**uint256(6));
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import { LibAsset } from "../Libraries/LibAsset.sol";
import { ILiFi } from "../Interfaces/ILiFi.sol";
import { LibSwap } from "../Libraries/LibSwap.sol";
import { ICBridge } from "../Interfaces/ICBridge.sol";
import { LibDiamond } from "../Libraries/LibDiamond.sol";
contract CBridgeFacet is ILiFi {
/* ========== Storage ========== */
bytes32 internal constant NAMESPACE = keccak256("com.lifi.facets.cbridge");
struct Storage {
address cBridge;
uint256 cBridgeChainId;
}
/* ========== Types ========== */
struct CBridgeData {
address bridge;
address token;
uint256 amount;
bytes32 hashlock;
uint64 timelock;
uint64 dstChainId;
address dstAddress;
}
/* ========== Init ========== */
function initCbridge(address _cBridge, uint256 _chainId) external {
Storage storage s = getStorage();
LibDiamond.enforceIsContractOwner();
s.cBridge = _cBridge;
s.cBridgeChainId = _chainId;
}
/* ========== Public Bridge Functions ========== */
function startBridgeTokensViaCBridge(LiFiData memory _lifiData, CBridgeData calldata _cBridgeData) public payable {
uint256 _fromTokenBalance = LibAsset.getOwnBalance(_cBridgeData.token);
LibAsset.transferFromERC20(_cBridgeData.token, msg.sender, address(this), _cBridgeData.amount);
require(
LibAsset.getOwnBalance(_cBridgeData.token) - _fromTokenBalance == _cBridgeData.amount,
"ERR_INVALID_AMOUNT"
);
_startBridge(_cBridgeData);
emit LiFiTransferStarted(
_lifiData.transactionId,
_lifiData.integrator,
_lifiData.referrer,
_lifiData.sendingAssetId,
_lifiData.receivingAssetId,
_lifiData.receiver,
_lifiData.amount,
_lifiData.destinationChainId,
block.timestamp
);
}
function swapAndStartBridgeTokensViaCBridge(
LiFiData memory _lifiData,
LibSwap.SwapData[] calldata _swapData,
CBridgeData calldata _cBridgeData
) public payable {
uint256 _fromTokenBalance = LibAsset.getOwnBalance(_cBridgeData.token);
LibAsset.transferFromERC20(_cBridgeData.token, msg.sender, address(this), _cBridgeData.amount);
// Swap
for (uint8 i; i < _swapData.length; i++) {
LibSwap.swap(_lifiData.transactionId, _swapData[i]);
}
require(
LibAsset.getOwnBalance(_cBridgeData.token) - _fromTokenBalance == _cBridgeData.amount,
"ERR_INVALID_AMOUNT"
);
_startBridge(_cBridgeData);
emit LiFiTransferStarted(
_lifiData.transactionId,
_lifiData.integrator,
_lifiData.referrer,
_lifiData.sendingAssetId,
_lifiData.receivingAssetId,
_lifiData.receiver,
_lifiData.amount,
_lifiData.destinationChainId,
block.timestamp
);
}
/* ========== Internal Functions ========== */
/*
* @dev Conatains the business logic for the bridge via CBridge
* @param _cBridgeData data specific to CBridge
*/
function _startBridge(CBridgeData calldata _cBridgeData) internal {
Storage storage s = getStorage();
address bridge = _bridge();
// Do CBridge stuff
require(s.cBridgeChainId != _cBridgeData.dstChainId, "Cannot bridge to the same network.");
// Give CBridge approval to bridge tokens
LibAsset.approveERC20(IERC20(_cBridgeData.token), bridge, _cBridgeData.amount);
ICBridge(bridge).transferOut(
_cBridgeData.bridge,
_cBridgeData.token,
_cBridgeData.amount,
_cBridgeData.hashlock,
_cBridgeData.timelock,
_cBridgeData.dstChainId,
_cBridgeData.dstAddress
);
}
function confirmTransaction(
LiFiData memory _lifiData,
bytes32 _transferId,
bytes32 _preimage
) public {
address bridge = _bridge();
ICBridge(bridge).confirm(_transferId, _preimage);
emit LiFiTransferConfirmed(
_lifiData.transactionId,
_lifiData.integrator,
_lifiData.referrer,
_lifiData.sendingAssetId,
_lifiData.receivingAssetId,
_lifiData.receiver,
_lifiData.amount,
_lifiData.destinationChainId,
block.timestamp
);
}
function refund(LiFiData memory _lifiData, bytes32 _transferId) public {
address bridge = _bridge();
ICBridge(bridge).refund(_transferId);
emit LiFiTransferRefunded(
_lifiData.transactionId,
_lifiData.integrator,
_lifiData.referrer,
_lifiData.sendingAssetId,
_lifiData.receivingAssetId,
_lifiData.receiver,
_lifiData.amount,
_lifiData.destinationChainId,
block.timestamp
);
}
function _bridge() internal view returns (address) {
Storage storage s = getStorage();
return s.cBridge;
}
function getStorage() internal pure returns (Storage storage s) {
bytes32 namespace = NAMESPACE;
// solhint-disable-next-line no-inline-assembly
assembly {
s.slot := namespace
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
interface ICBridge {
struct BridgeConfig {
address bridge;
}
function transferOut(
address _bridge,
address _token,
uint256 _amount,
bytes32 _hashlock,
uint64 _timelock,
uint64 _dstChinId,
address _dstAddress
) external;
function transferIn(
address _dstAddress,
address _token,
uint256 _amount,
bytes32 _hashlock,
uint64 _timelock,
uint64 _srcChainId,
bytes32 _srcTransferId
) external;
function confirm(bytes32 _transferId, bytes32 _preimage) external;
function refund(bytes32 _transferId) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import { LibDiamond } from "../Libraries/LibDiamond.sol";
import { IERC173 } from "../Interfaces/IERC173.sol";
contract OwnershipFacet is IERC173 {
function transferOwnership(address _newOwner) external override {
LibDiamond.enforceIsContractOwner();
LibDiamond.setContractOwner(_newOwner);
}
function owner() external view override returns (address owner_) {
owner_ = LibDiamond.contractOwner();
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
/// @title ERC-173 Contract Ownership Standard
/// Note: the ERC-165 identifier for this interface is 0x7f5828d0
/* is ERC165 */
interface IERC173 {
/// @dev This emits when ownership of a contract changes.
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/// @notice Get the address of the owner
/// @return owner_ The address of the owner.
function owner() external view returns (address owner_);
/// @notice Set the address of the new owner of the contract
/// @dev Set _newOwner to address(0) to renounce any ownership.
/// @param _newOwner The address of the new owner of the contract
function transferOwnership(address _newOwner) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import { LibDiamond } from "../Libraries/LibDiamond.sol";
import { IDiamondLoupe } from "../Interfaces/IDiamondLoupe.sol";
import { IERC165 } from "../Interfaces/IERC165.sol";
contract DiamondLoupeFacet is IDiamondLoupe, IERC165 {
// Diamond Loupe Functions
////////////////////////////////////////////////////////////////////
/// These functions are expected to be called frequently by tools.
//
// struct Facet {
// address facetAddress;
// bytes4[] functionSelectors;
// }
/// @notice Gets all facets and their selectors.
/// @return facets_ Facet
function facets() external view override returns (Facet[] memory facets_) {
LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();
uint256 numFacets = ds.facetAddresses.length;
facets_ = new Facet[](numFacets);
for (uint256 i; i < numFacets; i++) {
address facetAddress_ = ds.facetAddresses[i];
facets_[i].facetAddress = facetAddress_;
facets_[i].functionSelectors = ds.facetFunctionSelectors[facetAddress_].functionSelectors;
}
}
/// @notice Gets all the function selectors provided by a facet.
/// @param _facet The facet address.
/// @return facetFunctionSelectors_
function facetFunctionSelectors(address _facet)
external
view
override
returns (bytes4[] memory facetFunctionSelectors_)
{
LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();
facetFunctionSelectors_ = ds.facetFunctionSelectors[_facet].functionSelectors;
}
/// @notice Get all the facet addresses used by a diamond.
/// @return facetAddresses_
function facetAddresses() external view override returns (address[] memory facetAddresses_) {
LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();
facetAddresses_ = ds.facetAddresses;
}
/// @notice Gets the facet that supports the given selector.
/// @dev If facet is not found return address(0).
/// @param _functionSelector The function selector.
/// @return facetAddress_ The facet address.
function facetAddress(bytes4 _functionSelector) external view override returns (address facetAddress_) {
LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();
facetAddress_ = ds.selectorToFacetAndPosition[_functionSelector].facetAddress;
}
// This implements ERC-165.
function supportsInterface(bytes4 _interfaceId) external view override returns (bool) {
LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();
return ds.supportedInterfaces[_interfaceId];
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
// A loupe is a small magnifying glass used to look at diamonds.
// These functions look at diamonds
interface IDiamondLoupe {
/// These functions are expected to be called frequently
/// by tools.
struct Facet {
address facetAddress;
bytes4[] functionSelectors;
}
/// @notice Gets all facet addresses and their four byte function selectors.
/// @return facets_ Facet
function facets() external view returns (Facet[] memory facets_);
/// @notice Gets all the function selectors supported by a specific facet.
/// @param _facet The facet address.
/// @return facetFunctionSelectors_
function facetFunctionSelectors(address _facet) external view returns (bytes4[] memory facetFunctionSelectors_);
/// @notice Get all the facet addresses used by a diamond.
/// @return facetAddresses_
function facetAddresses() external view returns (address[] memory facetAddresses_);
/// @notice Gets the facet that supports the given selector.
/// @dev If facet is not found return address(0).
/// @param _functionSelector The function selector.
/// @return facetAddress_ The facet address.
function facetAddress(bytes4 _functionSelector) external view returns (address facetAddress_);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
interface IERC165 {
/// @notice Query if a contract implements an interface
/// @param interfaceId The interface identifier, as specified in ERC-165
/// @dev Interface identification is specified in ERC-165. This function
/// uses less than 30,000 gas.
/// @return `true` if the contract implements `interfaceID` and
/// `interfaceID` is not 0xffffffff, `false` otherwise
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"abi"
]
}
},
"metadata": {
"useLiteralContent": true
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"anonymous":false,"inputs":[{"components":[{"internalType":"address","name":"facetAddress","type":"address"},{"internalType":"enum IDiamondCut.FacetCutAction","name":"action","type":"uint8"},{"internalType":"bytes4[]","name":"functionSelectors","type":"bytes4[]"}],"indexed":false,"internalType":"struct IDiamondCut.FacetCut[]","name":"_diamondCut","type":"tuple[]"},{"indexed":false,"internalType":"address","name":"_init","type":"address"},{"indexed":false,"internalType":"bytes","name":"_calldata","type":"bytes"}],"name":"DiamondCut","type":"event"},{"inputs":[{"components":[{"internalType":"address","name":"facetAddress","type":"address"},{"internalType":"enum IDiamondCut.FacetCutAction","name":"action","type":"uint8"},{"internalType":"bytes4[]","name":"functionSelectors","type":"bytes4[]"}],"internalType":"struct IDiamondCut.FacetCut[]","name":"_diamondCut","type":"tuple[]"},{"internalType":"address","name":"_init","type":"address"},{"internalType":"bytes","name":"_calldata","type":"bytes"}],"name":"diamondCut","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
608060405234801561001057600080fd5b506114b2806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c80631f931c1c14610030575b600080fd5b61004361003e366004610eac565b610045565b005b61004d61009e565b61009761005a85876111ec565b8484848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061011a92505050565b5050505050565b600080516020611411833981519152600401546001600160a01b031633146101185760405162461bcd60e51b815260206004820152602260248201527f4c69624469616d6f6e643a204d75737420626520636f6e7472616374206f776e60448201526132b960f11b60648201526084015b60405180910390fd5b565b60005b83518110156102e357600084828151811061013a5761013a6113e4565b60200260200101516020015190506000600281111561015b5761015b6113b8565b81600281111561016d5761016d6113b8565b14156101bc576101b7858381518110610188576101886113e4565b6020026020010151600001518684815181106101a6576101a66113e4565b60200260200101516040015161032e565b6102d0565b60018160028111156101d0576101d06113b8565b141561021a576101b78583815181106101eb576101eb6113e4565b602002602001015160000151868481518110610209576102096113e4565b6020026020010151604001516104a3565b600281600281111561022e5761022e6113b8565b1415610278576101b7858381518110610249576102496113e4565b602002602001015160000151868481518110610267576102676113e4565b602002602001015160400151610631565b60405162461bcd60e51b815260206004820152602760248201527f4c69624469616d6f6e644375743a20496e636f727265637420466163657443756044820152663a20b1ba34b7b760c91b606482015260840161010f565b50806102db81611360565b91505061011d565b507f8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb67383838360405161031793929190610fa6565b60405180910390a1610329828261074f565b505050565b600081511161034f5760405162461bcd60e51b815260040161010f906110c0565b6000805160206114118339815191526001600160a01b0383166103845760405162461bcd60e51b815260040161010f9061110b565b6001600160a01b03831660009081526001820160205260409020546001600160601b0381166103b7576103b7828561095c565b60005b83518110156100975760008482815181106103d7576103d76113e4565b6020908102919091018101516001600160e01b031981166000908152918690526040909120549091506001600160a01b031680156104755760405162461bcd60e51b815260206004820152603560248201527f4c69624469616d6f6e644375743a2043616e2774206164642066756e6374696f6044820152746e207468617420616c72656164792065786973747360581b606482015260840161010f565b6104818583868a6109c6565b8361048b8161137b565b9450505050808061049b90611360565b9150506103ba565b60008151116104c45760405162461bcd60e51b815260040161010f906110c0565b6000805160206114118339815191526001600160a01b0383166104f95760405162461bcd60e51b815260040161010f9061110b565b6001600160a01b03831660009081526001820160205260409020546001600160601b03811661052c5761052c828561095c565b60005b835181101561009757600084828151811061054c5761054c6113e4565b6020908102919091018101516001600160e01b031981166000908152918690526040909120549091506001600160a01b039081169087168114156105f85760405162461bcd60e51b815260206004820152603860248201527f4c69624469616d6f6e644375743a2043616e2774207265706c6163652066756e60448201527f6374696f6e20776974682073616d652066756e6374696f6e0000000000000000606482015260840161010f565b610603858284610a66565b61060f8583868a6109c6565b836106198161137b565b9450505050808061062990611360565b91505061052f565b60008151116106525760405162461bcd60e51b815260040161010f906110c0565b6000805160206114118339815191526001600160a01b038316156106d75760405162461bcd60e51b815260206004820152603660248201527f4c69624469616d6f6e644375743a2052656d6f76652066616365742061646472604482015275657373206d757374206265206164647265737328302960501b606482015260840161010f565b60005b82518110156107495760008382815181106106f7576106f76113e4565b6020908102919091018101516001600160e01b031981166000908152918590526040909120549091506001600160a01b0316610734848284610a66565b5050808061074190611360565b9150506106da565b50505050565b6001600160a01b0382166107d6578051156107d25760405162461bcd60e51b815260206004820152603c60248201527f4c69624469616d6f6e644375743a205f696e697420697320616464726573732860448201527f3029206275745f63616c6c64617461206973206e6f7420656d70747900000000606482015260840161010f565b5050565b600081511161084d5760405162461bcd60e51b815260206004820152603d60248201527f4c69624469616d6f6e644375743a205f63616c6c6461746120697320656d707460448201527f7920627574205f696e6974206973206e6f742061646472657373283029000000606482015260840161010f565b6001600160a01b038216301461087f5761087f8260405180606001604052806028815260200161143160289139610e26565b600080836001600160a01b03168360405161089a9190610f8a565b600060405180830381855af49150503d80600081146108d5576040519150601f19603f3d011682016040523d82523d6000602084013e6108da565b606091505b50915091508161074957805115610905578060405162461bcd60e51b815260040161010f91906110a6565b60405162461bcd60e51b815260206004820152602660248201527f4c69624469616d6f6e644375743a205f696e69742066756e6374696f6e2072656044820152651d995c9d195960d21b606482015260840161010f565b61097e8160405180606001604052806024815260200161145960249139610e26565b6002820180546001600160a01b0390921660008181526001948501602090815260408220860185905594840183559182529290200180546001600160a01b0319169091179055565b6001600160e01b0319831660008181526020868152604080832080546001600160601b03909716600160a01b026001600160a01b0397881617815594909516808352600180890183529583208054968701815583528183206008870401805460e09890981c60046007909816979097026101000a96870263ffffffff9097021990971695909517909555529290915281546001600160a01b031916179055565b6001600160a01b038216610ae25760405162461bcd60e51b815260206004820152603760248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f76652066756e6360448201527f74696f6e207468617420646f65736e2774206578697374000000000000000000606482015260840161010f565b6001600160a01b038216301415610b525760405162461bcd60e51b815260206004820152602e60248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f766520696d6d7560448201526d3a30b1363290333ab731ba34b7b760911b606482015260840161010f565b6001600160e01b03198116600090815260208481526040808320546001600160a01b0386168452600180880190935290832054600160a01b9091046001600160601b03169291610ba1916111d5565b9050808214610c93576001600160a01b03841660009081526001860160205260408120805483908110610bd657610bd66113e4565b600091825260208083206008830401546001600160a01b038916845260018a019091526040909220805460079092166004026101000a90920460e01b925082919085908110610c2757610c276113e4565b600091825260208083206008830401805463ffffffff60079094166004026101000a938402191660e09590951c929092029390931790556001600160e01b03199290921682528690526040902080546001600160a01b0316600160a01b6001600160601b038516021790555b6001600160a01b03841660009081526001860160205260409020805480610cbc57610cbc6113ce565b60008281526020808220600860001990940193840401805463ffffffff600460078716026101000a0219169055919092556001600160e01b031985168252869052604081205580610097576002850154600090610d1b906001906111d5565b6001600160a01b0386166000908152600180890160205260409091200154909150808214610dca576000876002018381548110610d5a57610d5a6113e4565b6000918252602090912001546002890180546001600160a01b039092169250829184908110610d8b57610d8b6113e4565b600091825260208083209190910180546001600160a01b0319166001600160a01b03948516179055929091168152600189810190925260409020018190555b86600201805480610ddd57610ddd6113ce565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b0388168252600189810190915260408220015550505050505050565b813b81816107495760405162461bcd60e51b815260040161010f91906110a6565b80356001600160a01b0381168114610e5e57600080fd5b919050565b60008083601f840112610e7557600080fd5b50813567ffffffffffffffff811115610e8d57600080fd5b602083019150836020828501011115610ea557600080fd5b9250929050565b600080600080600060608688031215610ec457600080fd5b853567ffffffffffffffff80821115610edc57600080fd5b818801915088601f830112610ef057600080fd5b813581811115610eff57600080fd5b8960208260051b8501011115610f1457600080fd5b60208301975080965050610f2a60208901610e47565b94506040880135915080821115610f4057600080fd5b50610f4d88828901610e63565b969995985093965092949392505050565b60008151808452610f76816020860160208601611334565b601f01601f19169290920160200192915050565b60008251610f9c818460208701611334565b9190910192915050565b60006060808301818452808751808352608092508286019150828160051b8701016020808b0160005b8481101561107657898403607f19018652815180516001600160a01b0316855283810151898601906003811061101557634e487b7160e01b600052602160045260246000fd5b868601526040918201519186018a905281519081905290840190600090898701905b808310156110615783516001600160e01b0319168252928601926001929092019190860190611037565b50978501979550505090820190600101610fcf565b50506001600160a01b038a169088015286810360408801526110988189610f5e565b9a9950505050505050505050565b6020815260006110b96020830184610f5e565b9392505050565b6020808252602b908201527f4c69624469616d6f6e644375743a204e6f2073656c6563746f727320696e206660408201526a1858d95d081d1bc818dd5d60aa1b606082015260800190565b6020808252602c908201527f4c69624469616d6f6e644375743a204164642066616365742063616e2774206260408201526b65206164647265737328302960a01b606082015260800190565b6040516060810167ffffffffffffffff8111828210171561117a5761117a6113fa565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156111a9576111a96113fa565b604052919050565b600067ffffffffffffffff8211156111cb576111cb6113fa565b5060051b60200190565b6000828210156111e7576111e76113a2565b500390565b60006111ff6111fa846111b1565b611180565b838152602080820191908460053688821b8301111561121d57600080fd5b60005b8881101561132757823567ffffffffffffffff8082111561124057600080fd5b818a0191506060823603121561125557600080fd5b61125d611157565b61126683610e47565b8152868301356003811061127957600080fd5b818801526040838101358381111561129057600080fd5b939093019236601f8501126112a457600080fd5b833592506112b46111fa846111b1565b83815288810190858a0136868a1b88018c0111156112d157600080fd5b600096505b8587101561130a5780356001600160e01b0319811681146112f657600080fd5b835260019690960195918a01918a016112d6565b509183019190915250885250509483019491830191600101611220565b5092979650505050505050565b60005b8381101561134f578181015183820152602001611337565b838111156107495750506000910152565b6000600019821415611374576113746113a2565b5060010190565b60006001600160601b0380831681811415611398576113986113a2565b6001019392505050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fdfec8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c4c69624469616d6f6e644375743a205f696e6974206164647265737320686173206e6f20636f64654c69624469616d6f6e644375743a204e657720666163657420686173206e6f20636f6465a2646970667358221220cb3608f985e15fe1c810d3b025db6fcab323b52b076c5ed6b949dd3015c7d6a564736f6c63430008070033
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061002b5760003560e01c80631f931c1c14610030575b600080fd5b61004361003e366004610eac565b610045565b005b61004d61009e565b61009761005a85876111ec565b8484848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061011a92505050565b5050505050565b600080516020611411833981519152600401546001600160a01b031633146101185760405162461bcd60e51b815260206004820152602260248201527f4c69624469616d6f6e643a204d75737420626520636f6e7472616374206f776e60448201526132b960f11b60648201526084015b60405180910390fd5b565b60005b83518110156102e357600084828151811061013a5761013a6113e4565b60200260200101516020015190506000600281111561015b5761015b6113b8565b81600281111561016d5761016d6113b8565b14156101bc576101b7858381518110610188576101886113e4565b6020026020010151600001518684815181106101a6576101a66113e4565b60200260200101516040015161032e565b6102d0565b60018160028111156101d0576101d06113b8565b141561021a576101b78583815181106101eb576101eb6113e4565b602002602001015160000151868481518110610209576102096113e4565b6020026020010151604001516104a3565b600281600281111561022e5761022e6113b8565b1415610278576101b7858381518110610249576102496113e4565b602002602001015160000151868481518110610267576102676113e4565b602002602001015160400151610631565b60405162461bcd60e51b815260206004820152602760248201527f4c69624469616d6f6e644375743a20496e636f727265637420466163657443756044820152663a20b1ba34b7b760c91b606482015260840161010f565b50806102db81611360565b91505061011d565b507f8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb67383838360405161031793929190610fa6565b60405180910390a1610329828261074f565b505050565b600081511161034f5760405162461bcd60e51b815260040161010f906110c0565b6000805160206114118339815191526001600160a01b0383166103845760405162461bcd60e51b815260040161010f9061110b565b6001600160a01b03831660009081526001820160205260409020546001600160601b0381166103b7576103b7828561095c565b60005b83518110156100975760008482815181106103d7576103d76113e4565b6020908102919091018101516001600160e01b031981166000908152918690526040909120549091506001600160a01b031680156104755760405162461bcd60e51b815260206004820152603560248201527f4c69624469616d6f6e644375743a2043616e2774206164642066756e6374696f6044820152746e207468617420616c72656164792065786973747360581b606482015260840161010f565b6104818583868a6109c6565b8361048b8161137b565b9450505050808061049b90611360565b9150506103ba565b60008151116104c45760405162461bcd60e51b815260040161010f906110c0565b6000805160206114118339815191526001600160a01b0383166104f95760405162461bcd60e51b815260040161010f9061110b565b6001600160a01b03831660009081526001820160205260409020546001600160601b03811661052c5761052c828561095c565b60005b835181101561009757600084828151811061054c5761054c6113e4565b6020908102919091018101516001600160e01b031981166000908152918690526040909120549091506001600160a01b039081169087168114156105f85760405162461bcd60e51b815260206004820152603860248201527f4c69624469616d6f6e644375743a2043616e2774207265706c6163652066756e60448201527f6374696f6e20776974682073616d652066756e6374696f6e0000000000000000606482015260840161010f565b610603858284610a66565b61060f8583868a6109c6565b836106198161137b565b9450505050808061062990611360565b91505061052f565b60008151116106525760405162461bcd60e51b815260040161010f906110c0565b6000805160206114118339815191526001600160a01b038316156106d75760405162461bcd60e51b815260206004820152603660248201527f4c69624469616d6f6e644375743a2052656d6f76652066616365742061646472604482015275657373206d757374206265206164647265737328302960501b606482015260840161010f565b60005b82518110156107495760008382815181106106f7576106f76113e4565b6020908102919091018101516001600160e01b031981166000908152918590526040909120549091506001600160a01b0316610734848284610a66565b5050808061074190611360565b9150506106da565b50505050565b6001600160a01b0382166107d6578051156107d25760405162461bcd60e51b815260206004820152603c60248201527f4c69624469616d6f6e644375743a205f696e697420697320616464726573732860448201527f3029206275745f63616c6c64617461206973206e6f7420656d70747900000000606482015260840161010f565b5050565b600081511161084d5760405162461bcd60e51b815260206004820152603d60248201527f4c69624469616d6f6e644375743a205f63616c6c6461746120697320656d707460448201527f7920627574205f696e6974206973206e6f742061646472657373283029000000606482015260840161010f565b6001600160a01b038216301461087f5761087f8260405180606001604052806028815260200161143160289139610e26565b600080836001600160a01b03168360405161089a9190610f8a565b600060405180830381855af49150503d80600081146108d5576040519150601f19603f3d011682016040523d82523d6000602084013e6108da565b606091505b50915091508161074957805115610905578060405162461bcd60e51b815260040161010f91906110a6565b60405162461bcd60e51b815260206004820152602660248201527f4c69624469616d6f6e644375743a205f696e69742066756e6374696f6e2072656044820152651d995c9d195960d21b606482015260840161010f565b61097e8160405180606001604052806024815260200161145960249139610e26565b6002820180546001600160a01b0390921660008181526001948501602090815260408220860185905594840183559182529290200180546001600160a01b0319169091179055565b6001600160e01b0319831660008181526020868152604080832080546001600160601b03909716600160a01b026001600160a01b0397881617815594909516808352600180890183529583208054968701815583528183206008870401805460e09890981c60046007909816979097026101000a96870263ffffffff9097021990971695909517909555529290915281546001600160a01b031916179055565b6001600160a01b038216610ae25760405162461bcd60e51b815260206004820152603760248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f76652066756e6360448201527f74696f6e207468617420646f65736e2774206578697374000000000000000000606482015260840161010f565b6001600160a01b038216301415610b525760405162461bcd60e51b815260206004820152602e60248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f766520696d6d7560448201526d3a30b1363290333ab731ba34b7b760911b606482015260840161010f565b6001600160e01b03198116600090815260208481526040808320546001600160a01b0386168452600180880190935290832054600160a01b9091046001600160601b03169291610ba1916111d5565b9050808214610c93576001600160a01b03841660009081526001860160205260408120805483908110610bd657610bd66113e4565b600091825260208083206008830401546001600160a01b038916845260018a019091526040909220805460079092166004026101000a90920460e01b925082919085908110610c2757610c276113e4565b600091825260208083206008830401805463ffffffff60079094166004026101000a938402191660e09590951c929092029390931790556001600160e01b03199290921682528690526040902080546001600160a01b0316600160a01b6001600160601b038516021790555b6001600160a01b03841660009081526001860160205260409020805480610cbc57610cbc6113ce565b60008281526020808220600860001990940193840401805463ffffffff600460078716026101000a0219169055919092556001600160e01b031985168252869052604081205580610097576002850154600090610d1b906001906111d5565b6001600160a01b0386166000908152600180890160205260409091200154909150808214610dca576000876002018381548110610d5a57610d5a6113e4565b6000918252602090912001546002890180546001600160a01b039092169250829184908110610d8b57610d8b6113e4565b600091825260208083209190910180546001600160a01b0319166001600160a01b03948516179055929091168152600189810190925260409020018190555b86600201805480610ddd57610ddd6113ce565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b0388168252600189810190915260408220015550505050505050565b813b81816107495760405162461bcd60e51b815260040161010f91906110a6565b80356001600160a01b0381168114610e5e57600080fd5b919050565b60008083601f840112610e7557600080fd5b50813567ffffffffffffffff811115610e8d57600080fd5b602083019150836020828501011115610ea557600080fd5b9250929050565b600080600080600060608688031215610ec457600080fd5b853567ffffffffffffffff80821115610edc57600080fd5b818801915088601f830112610ef057600080fd5b813581811115610eff57600080fd5b8960208260051b8501011115610f1457600080fd5b60208301975080965050610f2a60208901610e47565b94506040880135915080821115610f4057600080fd5b50610f4d88828901610e63565b969995985093965092949392505050565b60008151808452610f76816020860160208601611334565b601f01601f19169290920160200192915050565b60008251610f9c818460208701611334565b9190910192915050565b60006060808301818452808751808352608092508286019150828160051b8701016020808b0160005b8481101561107657898403607f19018652815180516001600160a01b0316855283810151898601906003811061101557634e487b7160e01b600052602160045260246000fd5b868601526040918201519186018a905281519081905290840190600090898701905b808310156110615783516001600160e01b0319168252928601926001929092019190860190611037565b50978501979550505090820190600101610fcf565b50506001600160a01b038a169088015286810360408801526110988189610f5e565b9a9950505050505050505050565b6020815260006110b96020830184610f5e565b9392505050565b6020808252602b908201527f4c69624469616d6f6e644375743a204e6f2073656c6563746f727320696e206660408201526a1858d95d081d1bc818dd5d60aa1b606082015260800190565b6020808252602c908201527f4c69624469616d6f6e644375743a204164642066616365742063616e2774206260408201526b65206164647265737328302960a01b606082015260800190565b6040516060810167ffffffffffffffff8111828210171561117a5761117a6113fa565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156111a9576111a96113fa565b604052919050565b600067ffffffffffffffff8211156111cb576111cb6113fa565b5060051b60200190565b6000828210156111e7576111e76113a2565b500390565b60006111ff6111fa846111b1565b611180565b838152602080820191908460053688821b8301111561121d57600080fd5b60005b8881101561132757823567ffffffffffffffff8082111561124057600080fd5b818a0191506060823603121561125557600080fd5b61125d611157565b61126683610e47565b8152868301356003811061127957600080fd5b818801526040838101358381111561129057600080fd5b939093019236601f8501126112a457600080fd5b833592506112b46111fa846111b1565b83815288810190858a0136868a1b88018c0111156112d157600080fd5b600096505b8587101561130a5780356001600160e01b0319811681146112f657600080fd5b835260019690960195918a01918a016112d6565b509183019190915250885250509483019491830191600101611220565b5092979650505050505050565b60005b8381101561134f578181015183820152602001611337565b838111156107495750506000910152565b6000600019821415611374576113746113a2565b5060010190565b60006001600160601b0380831681811415611398576113986113a2565b6001019392505050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fdfec8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c4c69624469616d6f6e644375743a205f696e6974206164647265737320686173206e6f20636f64654c69624469616d6f6e644375743a204e657720666163657420686173206e6f20636f6465a2646970667358221220cb3608f985e15fe1c810d3b025db6fcab323b52b076c5ed6b949dd3015c7d6a564736f6c63430008070033
Deployed Bytecode Sourcemap
177:747:8:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;666:256;;;;;;:::i;:::-;;:::i;:::-;;;818:35;:33;:35::i;:::-;863:52;;885:11;;863:52;:::i;:::-;898:5;905:9;;863:52;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;863:21:8;;-1:-1:-1;;;863:52:8:i;:::-;666:256;;;;;:::o;2024:156:28:-;-1:-1:-1;;;;;;;;;;;2104:30:28;;;-1:-1:-1;;;;;2104:30:28;2090:10;:44;2082:91;;;;-1:-1:-1;;;2082:91:28;;5566:2:32;2082:91:28;;;5548:21:32;5605:2;5585:18;;;5578:30;5644:34;5624:18;;;5617:62;-1:-1:-1;;;5695:18:32;;;5688:32;5737:19;;2082:91:28;;;;;;;;;2024:156::o;2324:1067::-;2480:18;2475:806;2513:11;:18;2500:10;:31;2475:806;;;2561:33;2597:11;2609:10;2597:23;;;;;;;;:::i;:::-;;;;;;;:30;;;2561:66;;2655:30;2645:40;;;;;;;;:::i;:::-;:6;:40;;;;;;;;:::i;:::-;;2641:630;;;2705:93;2718:11;2730:10;2718:23;;;;;;;;:::i;:::-;;;;;;;:36;;;2756:11;2768:10;2756:23;;;;;;;;:::i;:::-;;;;;;;:41;;;2705:12;:93::i;:::-;2641:630;;;2833:34;2823:6;:44;;;;;;;;:::i;:::-;;2819:452;;;2887:97;2904:11;2916:10;2904:23;;;;;;;;:::i;:::-;;;;;;;:36;;;2942:11;2954:10;2942:23;;;;;;;;:::i;:::-;;;;;;;:41;;;2887:16;:97::i;2819:452::-;3019:33;3009:6;:43;;;;;;;;:::i;:::-;;3005:266;;;3072:96;3088:11;3100:10;3088:23;;;;;;;;:::i;:::-;;;;;;;:36;;;3126:11;3138:10;3126:23;;;;;;;;:::i;:::-;;;;;;;:41;;;3072:15;:96::i;3005:266::-;3207:49;;-1:-1:-1;;;3207:49:28;;6805:2:32;3207:49:28;;;6787:21:32;6844:2;6824:18;;;6817:30;6883:34;6863:18;;;6856:62;-1:-1:-1;;;6934:18:32;;;6927:37;6981:19;;3207:49:28;6603:403:32;3005:266:28;-1:-1:-1;2533:12:28;;;;:::i;:::-;;;;2475:806;;;;3295:41;3306:11;3319:5;3326:9;3295:41;;;;;;;;:::i;:::-;;;;;;;;3346:38;3367:5;3374:9;3346:20;:38::i;:::-;2324:1067;;;:::o;3397:1069::-;3533:1;3505:18;:25;:29;3497:85;;;;-1:-1:-1;;;3497:85:28;;;;;;;:::i;:::-;-1:-1:-1;;;;;;;;;;;;;;;;3654:27:28;;3646:84;;;;-1:-1:-1;;;3646:84:28;;;;;;;:::i;:::-;-1:-1:-1;;;;;3773:40:28;;3740:23;3773:40;;;:25;;;:40;;;;;:65;-1:-1:-1;;;;;3907:21:28;;3903:79;;3944:27;3953:2;3957:13;3944:8;:27::i;:::-;3996:21;3991:469;4035:18;:25;4019:13;:41;3991:469;;;4093:15;4111:18;4130:13;4111:33;;;;;;;;:::i;:::-;;;;;;;;;;;;-1:-1:-1;;;;;;4184:39:28;;4158:23;4184:39;;;;;;;;;;;:52;4111:33;;-1:-1:-1;;;;;;4184:52:28;4258:29;;4250:95;;;;-1:-1:-1;;;4250:95:28;;8471:2:32;4250:95:28;;;8453:21:32;8510:2;8490:18;;;8483:30;8549:34;8529:18;;;8522:62;-1:-1:-1;;;8600:18:32;;;8593:51;8661:19;;4250:95:28;8269:417:32;4250:95:28;4359:58;4371:2;4375:8;4385:16;4403:13;4359:11;:58::i;:::-;4431:18;;;;:::i;:::-;;;;4079:381;;4062:15;;;;;:::i;:::-;;;;3991:469;;4472:1138;4612:1;4584:18;:25;:29;4576:85;;;;-1:-1:-1;;;4576:85:28;;;;;;;:::i;:::-;-1:-1:-1;;;;;;;;;;;;;;;;4733:27:28;;4725:84;;;;-1:-1:-1;;;4725:84:28;;;;;;;:::i;:::-;-1:-1:-1;;;;;4852:40:28;;4819:23;4852:40;;;:25;;;:40;;;;;:65;-1:-1:-1;;;;;4986:21:28;;4982:79;;5023:27;5032:2;5036:13;5023:8;:27::i;:::-;5075:21;5070:534;5114:18;:25;5098:13;:41;5070:534;;;5172:15;5190:18;5209:13;5190:33;;;;;;;;:::i;:::-;;;;;;;;;;;;-1:-1:-1;;;;;;5263:39:28;;5237:23;5263:39;;;;;;;;;;;:52;5190:33;;-1:-1:-1;;;;;;5263:52:28;;;;5337:32;;;;;5329:101;;;;-1:-1:-1;;;5329:101:28;;8893:2:32;5329:101:28;;;8875:21:32;8932:2;8912:18;;;8905:30;8971:34;8951:18;;;8944:62;9042:26;9022:18;;;9015:54;9086:19;;5329:101:28;8691:420:32;5329:101:28;5444:45;5459:2;5463:15;5480:8;5444:14;:45::i;:::-;5503:58;5515:2;5519:8;5529:16;5547:13;5503:11;:58::i;:::-;5575:18;;;;:::i;:::-;;;;5158:446;;5141:15;;;;;:::i;:::-;;;;5070:534;;5616:742;5755:1;5727:18;:25;:29;5719:85;;;;-1:-1:-1;;;5719:85:28;;;;;;;:::i;:::-;-1:-1:-1;;;;;;;;;;;;;;;;5941:27:28;;;5933:94;;;;-1:-1:-1;;;5933:94:28;;9318:2:32;5933:94:28;;;9300:21:32;9357:2;9337:18;;;9330:30;9396:34;9376:18;;;9369:62;-1:-1:-1;;;9447:18:32;;;9440:52;9509:19;;5933:94:28;9116:418:32;5933:94:28;6042:21;6037:315;6081:18;:25;6065:13;:41;6037:315;;;6139:15;6157:18;6176:13;6157:33;;;;;;;;:::i;:::-;;;;;;;;;;;;-1:-1:-1;;;;;;6230:39:28;;6204:23;6230:39;;;;;;;;;;;:52;6157:33;;-1:-1:-1;;;;;;6230:52:28;6296:45;6230:2;:52;6157:33;6296:14;:45::i;:::-;6125:227;;6108:15;;;;;:::i;:::-;;;;6037:315;;;;5709:649;5616:742;;:::o;9337:934::-;-1:-1:-1;;;;;9429:19:28;;9425:840;;9472:16;;:21;9464:94;;;;-1:-1:-1;;;9464:94:28;;4730:2:32;9464:94:28;;;4712:21:32;4769:2;4749:18;;;4742:30;4808:34;4788:18;;;4781:62;4879:30;4859:18;;;4852:58;4927:19;;9464:94:28;4528:424:32;9464:94:28;9337:934;;:::o;9425:840::-;9616:1;9597:9;:16;:20;9589:94;;;;-1:-1:-1;;;9589:94:28;;7626:2:32;9589:94:28;;;7608:21:32;7665:2;7645:18;;;7638:30;7704:34;7684:18;;;7677:62;7775:31;7755:18;;;7748:59;7824:19;;9589:94:28;7424:425:32;9589:94:28;-1:-1:-1;;;;;9701:22:28;;9718:4;9701:22;9697:134;;9743:73;9766:5;9743:73;;;;;;;;;;;;;;;;;:22;:73::i;:::-;9908:12;9922:18;9944:5;-1:-1:-1;;;;;9944:18:28;9963:9;9944:29;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9907:66;;;;9992:7;9987:268;;10023:12;;:16;10019:222;;10120:5;10106:21;;-1:-1:-1;;;10106:21:28;;;;;;;;:::i;10019:222::-;10174:48;;-1:-1:-1;;;10174:48:28;;5159:2:32;10174:48:28;;;5141:21:32;5198:2;5178:18;;;5171:30;5237:34;5217:18;;;5210:62;-1:-1:-1;;;5288:18:32;;;5281:36;5334:19;;10174:48:28;4957:402:32;6364:316:28;6451:77;6474:13;6451:77;;;;;;;;;;;;;;;;;:22;:77::i;:::-;6602:17;;;:24;;-1:-1:-1;;;;;6538:40:28;;;;;;;:25;;;;:40;;;;;;;:61;;:88;;;6636:37;;;;;;;;;;;;;;-1:-1:-1;;;;;;6636:37:28;;;;;;6364:316::o;6686:427::-;-1:-1:-1;;;;;;6858:40:28;;:29;:40;;;;;;;;;;;:85;;-1:-1:-1;;;;;6858:85:28;;;-1:-1:-1;;;6858:85:28;-1:-1:-1;;;;;6858:85:28;;;;;;6953:40;;;;;;;-1:-1:-1;6953:25:28;;;:40;;;;;:74;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6858:85;6953:74;;;;;;;;;;;;;;;;;;;7037:40;;;;;:69;;-1:-1:-1;;;;;;7037:69:28;;;;6686:427::o;7119:2212::-;-1:-1:-1;;;;;7268:27:28;;7260:95;;;;-1:-1:-1;;;7260:95:28;;6381:2:32;7260:95:28;;;6363:21:32;6420:2;6400:18;;;6393:30;6459:34;6439:18;;;6432:62;6530:25;6510:18;;;6503:53;6573:19;;7260:95:28;6179:419:32;7260:95:28;-1:-1:-1;;;;;7450:30:28;;7475:4;7450:30;;7442:89;;;;-1:-1:-1;;;7442:89:28;;8056:2:32;7442:89:28;;;8038:21:32;8095:2;8075:18;;;8068:30;8134:34;8114:18;;;8107:62;-1:-1:-1;;;8185:18:32;;;8178:44;8239:19;;7442:89:28;7854:410:32;7442:89:28;-1:-1:-1;;;;;;7642:40:28;;7615:24;7642:40;;;;;;;;;;;:65;-1:-1:-1;;;;;7748:40:28;;;;7816:1;7748:25;;;:40;;;;;;:65;-1:-1:-1;;;7642:65:28;;;-1:-1:-1;;;;;7642:65:28;;7615:24;7748:69;;;:::i;:::-;7717:100;;7919:20;7899:16;:40;7895:387;;-1:-1:-1;;;;;7977:40:28;;7955:19;7977:40;;;:25;;;:40;;;;;:80;;8036:20;;7977:80;;;;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;;;;;8071:40:28;;;;:25;;;:40;;;;;;;:76;;7977:80;;;;;;;;;;;;;;-1:-1:-1;7977:80:28;;8071:40;8130:16;;8071:76;;;;;;:::i;:::-;;;;;;;;;;;;;:91;;;:76;;;;;;:91;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;8176:43:28;;;;;;;;;;;;:95;;-1:-1:-1;;;;;8176:95:28;-1:-1:-1;;;;;;;;8176:95:28;;;;;;7895:387;-1:-1:-1;;;;;8327:40:28;;;;;;:25;;;:40;;;;;:64;;;;;;;:::i;:::-;;;;;;;;;;-1:-1:-1;;8327:64:28;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;8408:40:28;;;;;;;;;;8401:47;8543:25;8539:786;;8710:17;;;:24;8675:32;;8710:28;;8737:1;;8710:28;:::i;:::-;-1:-1:-1;;;;;8783:40:28;;8752:28;8783:40;;;:25;;;;:40;;;;;;:61;;8675:63;;-1:-1:-1;8862:48:28;;;8858:338;;8930:24;8957:2;:17;;8975:24;8957:43;;;;;;;;:::i;:::-;;;;;;;;;;;9018:17;;;:39;;-1:-1:-1;;;;;8957:43:28;;;;-1:-1:-1;8957:43:28;;9036:20;;9018:39;;;;;;:::i;:::-;;;;;;;;;;;;;:58;;-1:-1:-1;;;;;;9018:58:28;-1:-1:-1;;;;;9018:58:28;;;;;;9094:43;;;;;;-1:-1:-1;9094:25:28;;;:43;;;;;;:64;:87;;;8858:338;9209:2;:17;;:23;;;;;;;:::i;:::-;;;;;;;;;;;-1:-1:-1;;9209:23:28;;;;;-1:-1:-1;;;;;;9209:23:28;;;;;;;;;-1:-1:-1;;;;;9253:40:28;;;;9209:23;9253:25;;;:40;;;;;;:61;9246:68;-1:-1:-1;;7250:2081:28;;7119:2212;;;:::o;10277:317::-;10506:22;;10573:13;10555:16;10547:40;;;;-1:-1:-1;;;10547:40:28;;;;;;;;:::i;14:173:32:-;82:20;;-1:-1:-1;;;;;131:31:32;;121:42;;111:70;;177:1;174;167:12;111:70;14:173;;;:::o;192:347::-;243:8;253:6;307:3;300:4;292:6;288:17;284:27;274:55;;325:1;322;315:12;274:55;-1:-1:-1;348:20:32;;391:18;380:30;;377:50;;;423:1;420;413:12;377:50;460:4;452:6;448:17;436:29;;512:3;505:4;496:6;488;484:19;480:30;477:39;474:59;;;529:1;526;519:12;474:59;192:347;;;;;:::o;544:1010::-;687:6;695;703;711;719;772:2;760:9;751:7;747:23;743:32;740:52;;;788:1;785;778:12;740:52;828:9;815:23;857:18;898:2;890:6;887:14;884:34;;;914:1;911;904:12;884:34;952:6;941:9;937:22;927:32;;997:7;990:4;986:2;982:13;978:27;968:55;;1019:1;1016;1009:12;968:55;1059:2;1046:16;1085:2;1077:6;1074:14;1071:34;;;1101:1;1098;1091:12;1071:34;1156:7;1149:4;1139:6;1136:1;1132:14;1128:2;1124:23;1120:34;1117:47;1114:67;;;1177:1;1174;1167:12;1114:67;1208:4;1204:2;1200:13;1190:23;;1232:6;1222:16;;;1257:40;1291:4;1280:9;1276:20;1257:40;:::i;:::-;1247:50;;1350:2;1339:9;1335:18;1322:32;1306:48;;1379:2;1369:8;1366:16;1363:36;;;1395:1;1392;1385:12;1363:36;;1434:60;1486:7;1475:8;1464:9;1460:24;1434:60;:::i;:::-;544:1010;;;;-1:-1:-1;544:1010:32;;-1:-1:-1;1513:8:32;;1408:86;544:1010;-1:-1:-1;;;544:1010:32:o;1668:257::-;1709:3;1747:5;1741:12;1774:6;1769:3;1762:19;1790:63;1846:6;1839:4;1834:3;1830:14;1823:4;1816:5;1812:16;1790:63;:::i;:::-;1907:2;1886:15;-1:-1:-1;;1882:29:32;1873:39;;;;1914:4;1869:50;;1668:257;-1:-1:-1;;1668:257:32:o;1930:274::-;2059:3;2097:6;2091:13;2113:53;2159:6;2154:3;2147:4;2139:6;2135:17;2113:53;:::i;:::-;2182:16;;;;;1930:274;-1:-1:-1;;1930:274:32:o;2209:2090::-;2477:4;2506:2;2546;2535:9;2531:18;2576:2;2565:9;2558:21;2599:6;2634;2628:13;2665:6;2657;2650:22;2691:3;2681:13;;2725:2;2714:9;2710:18;2703:25;;2787:2;2777:6;2774:1;2770:14;2759:9;2755:30;2751:39;2809:4;2848:2;2840:6;2836:15;2869:1;2879:1249;2893:6;2890:1;2887:13;2879:1249;;;2958:22;;;-1:-1:-1;;2954:37:32;2942:50;;3015:13;;3102:9;;-1:-1:-1;;;;;3098:35:32;3083:51;;3173:11;;;3167:18;3055:15;;;;3225:1;3208:19;;3198:170;;3278:10;3273:3;3269:20;3266:1;3259:31;3317:4;3314:1;3307:15;3349:4;3346:1;3339:15;3198:170;3388:15;;;3381:37;3441:4;3486:11;;;3480:18;3518:15;;;3511:27;;;3599:21;;3633:24;;;;3723:23;;;;-1:-1:-1;;3679:15:32;;;;3784:236;3800:8;3795:3;3792:17;3784:236;;;3881:15;;-1:-1:-1;;;;;;3877:42:32;3863:57;;3989:17;;;;3828:1;3819:11;;;;;3946:14;;;;3784:236;;;-1:-1:-1;4106:12:32;;;;4043:5;-1:-1:-1;;;4071:15:32;;;;2915:1;2908:9;2879:1249;;;-1:-1:-1;;;;;;;1625:31:32;;4164:18;;;1613:44;4221:22;;;4214:4;4199:20;;4192:52;4261:32;4225:6;4278;4261:32;:::i;:::-;4253:40;2209:2090;-1:-1:-1;;;;;;;;;;2209:2090:32:o;4304:219::-;4453:2;4442:9;4435:21;4416:4;4473:44;4513:2;4502:9;4498:18;4490:6;4473:44;:::i;:::-;4465:52;4304:219;-1:-1:-1;;;4304:219:32:o;5767:407::-;5969:2;5951:21;;;6008:2;5988:18;;;5981:30;6047:34;6042:2;6027:18;;6020:62;-1:-1:-1;;;6113:2:32;6098:18;;6091:41;6164:3;6149:19;;5767:407::o;7011:408::-;7213:2;7195:21;;;7252:2;7232:18;;;7225:30;7291:34;7286:2;7271:18;;7264:62;-1:-1:-1;;;7357:2:32;7342:18;;7335:42;7409:3;7394:19;;7011:408::o;9539:253::-;9611:2;9605:9;9653:4;9641:17;;9688:18;9673:34;;9709:22;;;9670:62;9667:88;;;9735:18;;:::i;:::-;9771:2;9764:22;9539:253;:::o;9797:275::-;9868:2;9862:9;9933:2;9914:13;;-1:-1:-1;;9910:27:32;9898:40;;9968:18;9953:34;;9989:22;;;9950:62;9947:88;;;10015:18;;:::i;:::-;10051:2;10044:22;9797:275;;-1:-1:-1;9797:275:32:o;10077:182::-;10136:4;10169:18;10161:6;10158:30;10155:56;;;10191:18;;:::i;:::-;-1:-1:-1;10236:1:32;10232:14;10248:4;10228:25;;10077:182::o;10264:125::-;10304:4;10332:1;10329;10326:8;10323:34;;;10337:18;;:::i;:::-;-1:-1:-1;10374:9:32;;10264:125::o;10394:2213::-;10564:9;10599:63;10615:46;10654:6;10615:46;:::i;:::-;10599:63;:::i;:::-;10696:19;;;10734:4;10754:12;;;;10684:3;10786:5;10810:1;10855:14;10837:15;;;10826:27;;10823:47;10820:67;;;10883:1;10880;10873:12;10820:67;10905:1;10915:1659;10929:6;10926:1;10923:13;10915:1659;;;11010:3;10997:17;11037:18;11087:2;11074:11;11071:19;11068:39;;;11103:1;11100;11093:12;11068:39;11141:11;11134:5;11130:23;11120:33;;11198:4;11193:2;11177:14;11173:23;11169:34;11166:54;;;11216:1;11213;11206:12;11166:54;11248:22;;:::i;:::-;11299;11318:2;11299:22;:::i;:::-;11290:7;11283:39;11371:2;11367;11363:11;11350:25;11410:1;11401:7;11398:14;11388:42;;11426:1;11423;11416:12;11388:42;11450:16;;;11443:33;11499:2;11541:11;;;11528:25;11569:14;;;11566:34;;;11596:1;11593;11586:12;11566:34;11623:15;;;;;11680:14;11673:4;11665:13;;11661:34;11651:62;;11709:1;11706;11699:12;11651:62;11749:2;11736:16;11726:26;;11778:59;11794:42;11833:2;11794:42;:::i;11778:59::-;11881:17;;;11920:14;;;;11960:11;;;12021:14;12002:11;;;11994:20;;11990:29;;11987:49;11984:69;;;12049:1;12046;12039:12;11984:69;12077:1;12066:12;;12091:332;12107:2;12102:3;12099:11;12091:332;;;12179:19;;-1:-1:-1;;;;;;12237:34:32;;12225:47;;12215:75;;12286:1;12283;12276:12;12215:75;12307:22;;12129:1;12120:11;;;;;12355:14;;;;12395;;12091:332;;;-1:-1:-1;12443:16:32;;;12436:31;;;;-1:-1:-1;12480:20:32;;-1:-1:-1;;12520:12:32;;;;12552;;;;10951:1;10944:9;10915:1659;;;-1:-1:-1;12596:5:32;;10394:2213;-1:-1:-1;;;;;;;10394:2213:32:o;12612:258::-;12684:1;12694:113;12708:6;12705:1;12702:13;12694:113;;;12784:11;;;12778:18;12765:11;;;12758:39;12730:2;12723:10;12694:113;;;12825:6;12822:1;12819:13;12816:48;;;-1:-1:-1;;12860:1:32;12842:16;;12835:27;12612:258::o;12875:135::-;12914:3;-1:-1:-1;;12935:17:32;;12932:43;;;12955:18;;:::i;:::-;-1:-1:-1;13002:1:32;12991:13;;12875:135::o;13015:217::-;13053:3;-1:-1:-1;;;;;13142:2:32;13135:5;13131:14;13169:2;13160:7;13157:15;13154:41;;;13175:18;;:::i;:::-;13224:1;13211:15;;13015:217;-1:-1:-1;;;13015:217:32:o;13237:127::-;13298:10;13293:3;13289:20;13286:1;13279:31;13329:4;13326:1;13319:15;13353:4;13350:1;13343:15;13369:127;13430:10;13425:3;13421:20;13418:1;13411:31;13461:4;13458:1;13451:15;13485:4;13482:1;13475:15;13501:127;13562:10;13557:3;13553:20;13550:1;13543:31;13593:4;13590:1;13583:15;13617:4;13614:1;13607:15;13633:127;13694:10;13689:3;13685:20;13682:1;13675:31;13725:4;13722:1;13715:15;13749:4;13746:1;13739:15;13765:127;13826:10;13821:3;13817:20;13814:1;13807:31;13857:4;13854:1;13847:15;13881:4;13878:1;13871:15
Swarm Source
ipfs://cb3608f985e15fe1c810d3b025db6fcab323b52b076c5ed6b949dd3015c7d6a5
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in POL
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.