Source Code
Latest 25 from a total of 30,220 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Start Bridge Tok... | 28989158 | 1334 days ago | IN | 0 POL | 0.01148202 | ||||
| Start Bridge Tok... | 28988825 | 1334 days ago | IN | 0 POL | 0.00802713 | ||||
| Swap And Start B... | 28988793 | 1334 days ago | IN | 119 POL | 0.01739916 | ||||
| Swap And Start B... | 28988675 | 1334 days ago | IN | 40 POL | 0.03684915 | ||||
| Swap And Start B... | 28988604 | 1334 days ago | IN | 10 POL | 0.03076292 | ||||
| Start Bridge Tok... | 28988517 | 1334 days ago | IN | 0 POL | 0.0154254 | ||||
| Swap And Start B... | 28988300 | 1334 days ago | IN | 25 POL | 0.0314935 | ||||
| Swap And Start B... | 28988286 | 1334 days ago | IN | 0 POL | 0.0171094 | ||||
| Start Bridge Tok... | 28988262 | 1334 days ago | IN | 0 POL | 0.01518865 | ||||
| Swap And Start B... | 28988248 | 1334 days ago | IN | 100 POL | 0.01933764 | ||||
| Swap And Start B... | 28988188 | 1334 days ago | IN | 0 POL | 0.018917 | ||||
| Start Bridge Tok... | 28988146 | 1334 days ago | IN | 0 POL | 0.01418465 | ||||
| Start Bridge Tok... | 28988114 | 1334 days ago | IN | 0 POL | 0.0134056 | ||||
| Start Bridge Tok... | 28987926 | 1334 days ago | IN | 0 POL | 0.00600265 | ||||
| Start Bridge Tok... | 28987904 | 1334 days ago | IN | 0 POL | 0.01418465 | ||||
| Start Bridge Tok... | 28987869 | 1334 days ago | IN | 0 POL | 0.0066105 | ||||
| Swap And Start B... | 28987824 | 1334 days ago | IN | 0 POL | 0.03186875 | ||||
| Swap And Start B... | 28987771 | 1334 days ago | IN | 0 POL | 0.02404695 | ||||
| Start Bridge Tok... | 28987769 | 1334 days ago | IN | 0 POL | 0.01035892 | ||||
| Start Bridge Tok... | 28987752 | 1334 days ago | IN | 0 POL | 0.0066105 | ||||
| Start Bridge Tok... | 28987681 | 1334 days ago | IN | 0 POL | 0.00430832 | ||||
| Start Bridge Tok... | 28987674 | 1334 days ago | IN | 0 POL | 0.02536212 | ||||
| Start Bridge Tok... | 28987610 | 1334 days ago | IN | 0 POL | 0.0055169 | ||||
| Start Bridge Tok... | 28987592 | 1334 days ago | IN | 0 POL | 0.01182821 | ||||
| Start Bridge Tok... | 28987540 | 1334 days ago | IN | 0 POL | 0.01000868 |
Latest 25 internal transactions (View All)
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 28988793 | 1334 days ago | 119 POL | ||||
| 28988675 | 1334 days ago | 40 POL | ||||
| 28988604 | 1334 days ago | 10 POL | ||||
| 28988453 | 1334 days ago | 119.27275213 POL | ||||
| 28988453 | 1334 days ago | 119.27275213 POL | ||||
| 28988357 | 1334 days ago | 119.66784217 POL | ||||
| 28988357 | 1334 days ago | 119.66784217 POL | ||||
| 28988300 | 1334 days ago | 25 POL | ||||
| 28988248 | 1334 days ago | 100 POL | ||||
| 28987389 | 1334 days ago | 64 POL | ||||
| 28987008 | 1334 days ago | 2 wei | ||||
| 28987008 | 1334 days ago | 0.069 POL | ||||
| 28986740 | 1334 days ago | 0.066 POL | ||||
| 28986683 | 1334 days ago | 137.7211151 POL | ||||
| 28986683 | 1334 days ago | 137.7211151 POL | ||||
| 28986656 | 1334 days ago | 3.01448149 POL | ||||
| 28986656 | 1334 days ago | 3.01448149 POL | ||||
| 28986529 | 1334 days ago | 20 POL | ||||
| 28986497 | 1334 days ago | 0.052 POL | ||||
| 28985683 | 1334 days ago | 15 POL | ||||
| 28985538 | 1334 days ago | 0.08 POL | ||||
| 28985536 | 1334 days ago | 4 POL | ||||
| 28985315 | 1334 days ago | 2 wei | ||||
| 28985315 | 1334 days ago | 0.07 POL | ||||
| 28984378 | 1334 days ago | 0.043 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:
LiFiDiamond
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 { 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 "@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 { 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 { 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[{"inputs":[{"internalType":"address","name":"_contractOwner","type":"address"},{"internalType":"address","name":"_diamondCutFacet","type":"address"}],"stateMutability":"payable","type":"constructor"},{"stateMutability":"payable","type":"fallback"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60806040526040516200269938038062002699833981016040819052620000269162001168565b6200003c826200015660201b620000b61760201c565b604080516001808252818301909252600091816020015b60408051606080820183526000808352602083015291810191909152815260200190600190039081620000535750506040805160018082528183019092529192506000919060208083019080368337019050509050631f931c1c60e01b81600081518110620000c657620000c6620013e2565b6001600160e01b031990921660209283029190910182015260408051606081019091526001600160a01b0385168152908101600081526020018281525082600081518110620001195762000119620013e2565b60200260200101819052506200014c82600060405180602001604052806000815250620001da60201b620001391760201c565b50505050620013f8565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c132080546001600160a01b031981166001600160a01b03848116918217909355604051600080516020620025ed833981519152939092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b60005b8351811015620003e9576000848281518110620001fe57620001fe620013e2565b602002602001015160200151905060006002811115620002225762000222620013b6565b816002811115620002375762000237620013b6565b1415620002965762000290858381518110620002575762000257620013e2565b602002602001015160000151868481518110620002785762000278620013e2565b6020026020010151604001516200043860201b60201c565b620003d3565b6001816002811115620002ad57620002ad620013b6565b1415620003065762000290858381518110620002cd57620002cd620013e2565b602002602001015160000151868481518110620002ee57620002ee620013e2565b602002602001015160400151620006c260201b60201c565b60028160028111156200031d576200031d620013b6565b14156200037657620002908583815181106200033d576200033d620013e2565b6020026020010151600001518684815181106200035e576200035e620013e2565b6020026020010151604001516200095860201b60201c565b60405162461bcd60e51b815260206004820152602760248201527f4c69624469616d6f6e644375743a20496e636f727265637420466163657443756044820152663a20b1ba34b7b760c91b60648201526084015b60405180910390fd5b5080620003e08162001358565b915050620001dd565b507f8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb6738383836040516200041f93929190620011ec565b60405180910390a162000433828262000abe565b505050565b60008151116200048e5760405162461bcd60e51b815260206004820152602b60248201526000805160206200267983398151915260448201526a1858d95d081d1bc818dd5d60aa1b6064820152608401620003ca565b600080516020620025ed8339815191526001600160a01b038316620004fa5760405162461bcd60e51b815260206004820152602c60248201526000805160206200263583398151915260448201526b65206164647265737328302960a01b6064820152608401620003ca565b6001600160a01b03831660009081526001820160205260409020546001600160601b038116620005305762000530828562000cdd565b60005b8351811015620006bb576000848281518110620005545762000554620013e2565b6020908102919091018101516001600160e01b031981166000908152918690526040909120549091506001600160a01b03168015620005fc5760405162461bcd60e51b815260206004820152603560248201527f4c69624469616d6f6e644375743a2043616e2774206164642066756e6374696f60448201527f6e207468617420616c72656164792065786973747300000000000000000000006064820152608401620003ca565b6001600160e01b0319821660008181526020878152604080832080546001600160a01b03908116600160a01b6001600160601b038c16021782558c168085526001808c0185529285208054938401815585528385206008840401805463ffffffff60079095166004026101000a948502191660e08a901c94909402939093179092559390925287905281546001600160a01b03191617905583620006a08162001376565b94505050508080620006b29062001358565b91505062000533565b5050505050565b6000815111620007185760405162461bcd60e51b815260206004820152602b60248201526000805160206200267983398151915260448201526a1858d95d081d1bc818dd5d60aa1b6064820152608401620003ca565b600080516020620025ed8339815191526001600160a01b038316620007845760405162461bcd60e51b815260206004820152602c60248201526000805160206200263583398151915260448201526b65206164647265737328302960a01b6064820152608401620003ca565b6001600160a01b03831660009081526001820160205260409020546001600160601b038116620007ba57620007ba828562000cdd565b60005b8351811015620006bb576000848281518110620007de57620007de620013e2565b6020908102919091018101516001600160e01b031981166000908152918690526040909120549091506001600160a01b039081169087168114156200088c5760405162461bcd60e51b815260206004820152603860248201527f4c69624469616d6f6e644375743a2043616e2774207265706c6163652066756e60448201527f6374696f6e20776974682073616d652066756e6374696f6e00000000000000006064820152608401620003ca565b6200089985828462000d4a565b6001600160e01b0319821660008181526020878152604080832080546001600160a01b03908116600160a01b6001600160601b038c16021782558c168085526001808c0185529285208054938401815585528385206008840401805463ffffffff60079095166004026101000a948502191660e08a901c94909402939093179092559390925287905281546001600160a01b031916179055836200093d8162001376565b945050505080806200094f9062001358565b915050620007bd565b6000815111620009ae5760405162461bcd60e51b815260206004820152602b60248201526000805160206200267983398151915260448201526a1858d95d081d1bc818dd5d60aa1b6064820152608401620003ca565b600080516020620025ed8339815191526001600160a01b0383161562000a3d5760405162461bcd60e51b815260206004820152603660248201527f4c69624469616d6f6e644375743a2052656d6f7665206661636574206164647260448201527f657373206d7573742062652061646472657373283029000000000000000000006064820152608401620003ca565b60005b825181101562000ab857600083828151811062000a615762000a61620013e2565b6020908102919091018101516001600160e01b031981166000908152918590526040909120549091506001600160a01b031662000aa084828462000d4a565b5050808062000aaf9062001358565b91505062000a40565b50505050565b6001600160a01b03821662000b485780511562000b445760405162461bcd60e51b815260206004820152603c60248201527f4c69624469616d6f6e644375743a205f696e697420697320616464726573732860448201527f3029206275745f63616c6c64617461206973206e6f7420656d707479000000006064820152608401620003ca565b5050565b600081511162000bc15760405162461bcd60e51b815260206004820152603d60248201527f4c69624469616d6f6e644375743a205f63616c6c6461746120697320656d707460448201527f7920627574205f696e6974206973206e6f7420616464726573732830290000006064820152608401620003ca565b6001600160a01b038216301462000bf75762000bf7826040518060600160405280602881526020016200260d6028913962001127565b600080836001600160a01b03168360405162000c149190620011ce565b600060405180830381855af49150503d806000811462000c51576040519150601f19603f3d011682016040523d82523d6000602084013e62000c56565b606091505b50915091508162000ab85780511562000c85578060405162461bcd60e51b8152600401620003ca9190620012f3565b60405162461bcd60e51b815260206004820152602660248201527f4c69624469616d6f6e644375743a205f696e69742066756e6374696f6e2072656044820152651d995c9d195960d21b6064820152608401620003ca565b62000d0281604051806060016040528060248152602001620026556024913962001127565b6002820180546001600160a01b0390921660008181526001948501602090815260408220860185905594840183559182529290200180546001600160a01b0319169091179055565b6001600160a01b03821662000dc85760405162461bcd60e51b815260206004820152603760248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f76652066756e6360448201527f74696f6e207468617420646f65736e27742065786973740000000000000000006064820152608401620003ca565b6001600160a01b03821630141562000e3a5760405162461bcd60e51b815260206004820152602e60248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f766520696d6d7560448201526d3a30b1363290333ab731ba34b7b760911b6064820152608401620003ca565b6001600160e01b03198116600090815260208481526040808320546001600160a01b0386168452600180880190935290832054600160a01b9091046001600160601b0316929162000e8b916200130f565b905080821462000f84576001600160a01b0384166000908152600186016020526040812080548390811062000ec45762000ec4620013e2565b600091825260208083206008830401546001600160a01b038916845260018a019091526040909220805460079092166004026101000a90920460e01b92508291908590811062000f185762000f18620013e2565b600091825260208083206008830401805463ffffffff60079094166004026101000a938402191660e09590951c929092029390931790556001600160e01b03199290921682528690526040902080546001600160a01b0316600160a01b6001600160601b038516021790555b6001600160a01b0384166000908152600186016020526040902080548062000fb05762000fb0620013cc565b60008281526020808220600860001990940193840401805463ffffffff600460078716026101000a0219169055919092556001600160e01b031985168252869052604081205580620006bb57600285015460009062001012906001906200130f565b6001600160a01b0386166000908152600180890160205260409091200154909150808214620010c8576000876002018381548110620010555762001055620013e2565b6000918252602090912001546002890180546001600160a01b039092169250829184908110620010895762001089620013e2565b600091825260208083209190910180546001600160a01b0319166001600160a01b03948516179055929091168152600189810190925260409020018190555b86600201805480620010de57620010de620013cc565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b0388168252600189810190915260408220015550505050505050565b813b818162000ab85760405162461bcd60e51b8152600401620003ca9190620012f3565b80516001600160a01b03811681146200116357600080fd5b919050565b600080604083850312156200117c57600080fd5b62001187836200114b565b915062001197602084016200114b565b90509250929050565b60008151808452620011ba81602086016020860162001329565b601f01601f19169290920160200192915050565b60008251620011e281846020870162001329565b9190910192915050565b60006060808301818452808751808352608092508286019150828160051b8701016020808b0160005b84811015620012c157898403607f19018652815180516001600160a01b031685528381015189860190600381106200125d57634e487b7160e01b600052602160045260246000fd5b868601526040918201519186018a905281519081905290840190600090898701905b80831015620012ab5783516001600160e01b03191682529286019260019290920191908601906200127f565b5097850197955050509082019060010162001215565b50506001600160a01b038a16908801528681036040880152620012e58189620011a0565b9a9950505050505050505050565b602081526000620013086020830184620011a0565b9392505050565b600082821015620013245762001324620013a0565b500390565b60005b83811015620013465781810151838201526020016200132c565b8381111562000ab85750506000910152565b60006000198214156200136f576200136f620013a0565b5060010190565b60006001600160601b0382811680821415620013965762001396620013a0565b6001019392505050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6111e580620014086000396000f3fe60806040523661000b57005b600080356001600160e01b0319168152600080516020611144833981519152602081905260409091205481906001600160a01b0316806100925760405162461bcd60e51b815260206004820181905260248201527f4469616d6f6e643a2046756e6374696f6e20646f6573206e6f7420657869737460448201526064015b60405180910390fd5b3660008037600080366000845af43d6000803e8080156100b1573d6000f35b3d6000fd5b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c132080546001600160a01b031981166001600160a01b03848116918217909355604051600080516020611144833981519152939092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b60005b83518110156103025760008482815181106101595761015961112d565b60200260200101516020015190506000600281111561017a5761017a611101565b81600281111561018c5761018c611101565b14156101db576101d68583815181106101a7576101a761112d565b6020026020010151600001518684815181106101c5576101c561112d565b60200260200101516040015161034d565b6102ef565b60018160028111156101ef576101ef611101565b1415610239576101d685838151811061020a5761020a61112d565b6020026020010151600001518684815181106102285761022861112d565b6020026020010151604001516104c9565b600281600281111561024d5761024d611101565b1415610297576101d68583815181106102685761026861112d565b6020026020010151600001518684815181106102865761028661112d565b602002602001015160400151610657565b60405162461bcd60e51b815260206004820152602760248201527f4c69624469616d6f6e644375743a20496e636f727265637420466163657443756044820152663a20b1ba34b7b760c91b6064820152608401610089565b50806102fa816110a9565b91505061013c565b507f8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb67383838360405161033693929190610eb5565b60405180910390a16103488282610775565b505050565b600081511161036e5760405162461bcd60e51b815260040161008990610fcf565b6000805160206111448339815191526001600160a01b0383166103a35760405162461bcd60e51b81526004016100899061101a565b6001600160a01b03831660009081526001820160205260409020546001600160601b0381166103d6576103d68285610982565b60005b83518110156104c25760008482815181106103f6576103f661112d565b6020908102919091018101516001600160e01b031981166000908152918690526040909120549091506001600160a01b031680156104945760405162461bcd60e51b815260206004820152603560248201527f4c69624469616d6f6e644375743a2043616e2774206164642066756e6374696f6044820152746e207468617420616c72656164792065786973747360581b6064820152608401610089565b6104a08583868a6109ec565b836104aa816110c4565b945050505080806104ba906110a9565b9150506103d9565b5050505050565b60008151116104ea5760405162461bcd60e51b815260040161008990610fcf565b6000805160206111448339815191526001600160a01b03831661051f5760405162461bcd60e51b81526004016100899061101a565b6001600160a01b03831660009081526001820160205260409020546001600160601b038116610552576105528285610982565b60005b83518110156104c25760008482815181106105725761057261112d565b6020908102919091018101516001600160e01b031981166000908152918690526040909120549091506001600160a01b0390811690871681141561061e5760405162461bcd60e51b815260206004820152603860248201527f4c69624469616d6f6e644375743a2043616e2774207265706c6163652066756e60448201527f6374696f6e20776974682073616d652066756e6374696f6e00000000000000006064820152608401610089565b610629858284610a8c565b6106358583868a6109ec565b8361063f816110c4565b9450505050808061064f906110a9565b915050610555565b60008151116106785760405162461bcd60e51b815260040161008990610fcf565b6000805160206111448339815191526001600160a01b038316156106fd5760405162461bcd60e51b815260206004820152603660248201527f4c69624469616d6f6e644375743a2052656d6f76652066616365742061646472604482015275657373206d757374206265206164647265737328302960501b6064820152608401610089565b60005b825181101561076f57600083828151811061071d5761071d61112d565b6020908102919091018101516001600160e01b031981166000908152918590526040909120549091506001600160a01b031661075a848284610a8c565b50508080610767906110a9565b915050610700565b50505050565b6001600160a01b0382166107fc578051156107f85760405162461bcd60e51b815260206004820152603c60248201527f4c69624469616d6f6e644375743a205f696e697420697320616464726573732860448201527f3029206275745f63616c6c64617461206973206e6f7420656d707479000000006064820152608401610089565b5050565b60008151116108735760405162461bcd60e51b815260206004820152603d60248201527f4c69624469616d6f6e644375743a205f63616c6c6461746120697320656d707460448201527f7920627574205f696e6974206973206e6f7420616464726573732830290000006064820152608401610089565b6001600160a01b03821630146108a5576108a58260405180606001604052806028815260200161116460289139610e4c565b600080836001600160a01b0316836040516108c09190610e99565b600060405180830381855af49150503d80600081146108fb576040519150601f19603f3d011682016040523d82523d6000602084013e610900565b606091505b50915091508161076f5780511561092b578060405162461bcd60e51b81526004016100899190610fb5565b60405162461bcd60e51b815260206004820152602660248201527f4c69624469616d6f6e644375743a205f696e69742066756e6374696f6e2072656044820152651d995c9d195960d21b6064820152608401610089565b6109a48160405180606001604052806024815260200161118c60249139610e4c565b6002820180546001600160a01b0390921660008181526001948501602090815260408220860185905594840183559182529290200180546001600160a01b0319169091179055565b6001600160e01b0319831660008181526020868152604080832080546001600160601b03909716600160a01b026001600160a01b0397881617815594909516808352600180890183529583208054968701815583528183206008870401805460e09890981c60046007909816979097026101000a96870263ffffffff9097021990971695909517909555529290915281546001600160a01b031916179055565b6001600160a01b038216610b085760405162461bcd60e51b815260206004820152603760248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f76652066756e6360448201527f74696f6e207468617420646f65736e27742065786973740000000000000000006064820152608401610089565b6001600160a01b038216301415610b785760405162461bcd60e51b815260206004820152602e60248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f766520696d6d7560448201526d3a30b1363290333ab731ba34b7b760911b6064820152608401610089565b6001600160e01b03198116600090815260208481526040808320546001600160a01b0386168452600180880190935290832054600160a01b9091046001600160601b03169291610bc791611066565b9050808214610cb9576001600160a01b03841660009081526001860160205260408120805483908110610bfc57610bfc61112d565b600091825260208083206008830401546001600160a01b038916845260018a019091526040909220805460079092166004026101000a90920460e01b925082919085908110610c4d57610c4d61112d565b600091825260208083206008830401805463ffffffff60079094166004026101000a938402191660e09590951c929092029390931790556001600160e01b03199290921682528690526040902080546001600160a01b0316600160a01b6001600160601b038516021790555b6001600160a01b03841660009081526001860160205260409020805480610ce257610ce2611117565b60008281526020808220600860001990940193840401805463ffffffff600460078716026101000a0219169055919092556001600160e01b0319851682528690526040812055806104c2576002850154600090610d4190600190611066565b6001600160a01b0386166000908152600180890160205260409091200154909150808214610df0576000876002018381548110610d8057610d8061112d565b6000918252602090912001546002890180546001600160a01b039092169250829184908110610db157610db161112d565b600091825260208083209190910180546001600160a01b0319166001600160a01b03948516179055929091168152600189810190925260409020018190555b86600201805480610e0357610e03611117565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b0388168252600189810190915260408220015550505050505050565b813b818161076f5760405162461bcd60e51b81526004016100899190610fb5565b60008151808452610e8581602086016020860161107d565b601f01601f19169290920160200192915050565b60008251610eab81846020870161107d565b9190910192915050565b60006060808301818452808751808352608092508286019150828160051b8701016020808b0160005b84811015610f8557898403607f19018652815180516001600160a01b03168552838101518986019060038110610f2457634e487b7160e01b600052602160045260246000fd5b868601526040918201519186018a905281519081905290840190600090898701905b80831015610f705783516001600160e01b0319168252928601926001929092019190860190610f46565b50978501979550505090820190600101610ede565b50506001600160a01b038a16908801528681036040880152610fa78189610e6d565b9a9950505050505050505050565b602081526000610fc86020830184610e6d565b9392505050565b6020808252602b908201527f4c69624469616d6f6e644375743a204e6f2073656c6563746f727320696e206660408201526a1858d95d081d1bc818dd5d60aa1b606082015260800190565b6020808252602c908201527f4c69624469616d6f6e644375743a204164642066616365742063616e2774206260408201526b65206164647265737328302960a01b606082015260800190565b600082821015611078576110786110eb565b500390565b60005b83811015611098578181015183820152602001611080565b8381111561076f5750506000910152565b60006000198214156110bd576110bd6110eb565b5060010190565b60006001600160601b03808316818114156110e1576110e16110eb565b6001019392505050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fdfec8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c4c69624469616d6f6e644375743a205f696e6974206164647265737320686173206e6f20636f64654c69624469616d6f6e644375743a204e657720666163657420686173206e6f20636f6465a2646970667358221220795ef6cc7673851b890285a5dba416996941361b46ed69aa34655dcb7d15532464736f6c63430008070033c8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c4c69624469616d6f6e644375743a205f696e6974206164647265737320686173206e6f20636f64654c69624469616d6f6e644375743a204164642066616365742063616e277420624c69624469616d6f6e644375743a204e657720666163657420686173206e6f20636f64654c69624469616d6f6e644375743a204e6f2073656c6563746f727320696e2066000000000000000000000000cb1e9fa11edd27098a6b2ff23cb6b79183ccf8ee000000000000000000000000c46304a0b2accc4462d9bdcaa0f6bf632510d617
Deployed Bytecode
0x60806040523661000b57005b600080356001600160e01b0319168152600080516020611144833981519152602081905260409091205481906001600160a01b0316806100925760405162461bcd60e51b815260206004820181905260248201527f4469616d6f6e643a2046756e6374696f6e20646f6573206e6f7420657869737460448201526064015b60405180910390fd5b3660008037600080366000845af43d6000803e8080156100b1573d6000f35b3d6000fd5b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c132080546001600160a01b031981166001600160a01b03848116918217909355604051600080516020611144833981519152939092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b60005b83518110156103025760008482815181106101595761015961112d565b60200260200101516020015190506000600281111561017a5761017a611101565b81600281111561018c5761018c611101565b14156101db576101d68583815181106101a7576101a761112d565b6020026020010151600001518684815181106101c5576101c561112d565b60200260200101516040015161034d565b6102ef565b60018160028111156101ef576101ef611101565b1415610239576101d685838151811061020a5761020a61112d565b6020026020010151600001518684815181106102285761022861112d565b6020026020010151604001516104c9565b600281600281111561024d5761024d611101565b1415610297576101d68583815181106102685761026861112d565b6020026020010151600001518684815181106102865761028661112d565b602002602001015160400151610657565b60405162461bcd60e51b815260206004820152602760248201527f4c69624469616d6f6e644375743a20496e636f727265637420466163657443756044820152663a20b1ba34b7b760c91b6064820152608401610089565b50806102fa816110a9565b91505061013c565b507f8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb67383838360405161033693929190610eb5565b60405180910390a16103488282610775565b505050565b600081511161036e5760405162461bcd60e51b815260040161008990610fcf565b6000805160206111448339815191526001600160a01b0383166103a35760405162461bcd60e51b81526004016100899061101a565b6001600160a01b03831660009081526001820160205260409020546001600160601b0381166103d6576103d68285610982565b60005b83518110156104c25760008482815181106103f6576103f661112d565b6020908102919091018101516001600160e01b031981166000908152918690526040909120549091506001600160a01b031680156104945760405162461bcd60e51b815260206004820152603560248201527f4c69624469616d6f6e644375743a2043616e2774206164642066756e6374696f6044820152746e207468617420616c72656164792065786973747360581b6064820152608401610089565b6104a08583868a6109ec565b836104aa816110c4565b945050505080806104ba906110a9565b9150506103d9565b5050505050565b60008151116104ea5760405162461bcd60e51b815260040161008990610fcf565b6000805160206111448339815191526001600160a01b03831661051f5760405162461bcd60e51b81526004016100899061101a565b6001600160a01b03831660009081526001820160205260409020546001600160601b038116610552576105528285610982565b60005b83518110156104c25760008482815181106105725761057261112d565b6020908102919091018101516001600160e01b031981166000908152918690526040909120549091506001600160a01b0390811690871681141561061e5760405162461bcd60e51b815260206004820152603860248201527f4c69624469616d6f6e644375743a2043616e2774207265706c6163652066756e60448201527f6374696f6e20776974682073616d652066756e6374696f6e00000000000000006064820152608401610089565b610629858284610a8c565b6106358583868a6109ec565b8361063f816110c4565b9450505050808061064f906110a9565b915050610555565b60008151116106785760405162461bcd60e51b815260040161008990610fcf565b6000805160206111448339815191526001600160a01b038316156106fd5760405162461bcd60e51b815260206004820152603660248201527f4c69624469616d6f6e644375743a2052656d6f76652066616365742061646472604482015275657373206d757374206265206164647265737328302960501b6064820152608401610089565b60005b825181101561076f57600083828151811061071d5761071d61112d565b6020908102919091018101516001600160e01b031981166000908152918590526040909120549091506001600160a01b031661075a848284610a8c565b50508080610767906110a9565b915050610700565b50505050565b6001600160a01b0382166107fc578051156107f85760405162461bcd60e51b815260206004820152603c60248201527f4c69624469616d6f6e644375743a205f696e697420697320616464726573732860448201527f3029206275745f63616c6c64617461206973206e6f7420656d707479000000006064820152608401610089565b5050565b60008151116108735760405162461bcd60e51b815260206004820152603d60248201527f4c69624469616d6f6e644375743a205f63616c6c6461746120697320656d707460448201527f7920627574205f696e6974206973206e6f7420616464726573732830290000006064820152608401610089565b6001600160a01b03821630146108a5576108a58260405180606001604052806028815260200161116460289139610e4c565b600080836001600160a01b0316836040516108c09190610e99565b600060405180830381855af49150503d80600081146108fb576040519150601f19603f3d011682016040523d82523d6000602084013e610900565b606091505b50915091508161076f5780511561092b578060405162461bcd60e51b81526004016100899190610fb5565b60405162461bcd60e51b815260206004820152602660248201527f4c69624469616d6f6e644375743a205f696e69742066756e6374696f6e2072656044820152651d995c9d195960d21b6064820152608401610089565b6109a48160405180606001604052806024815260200161118c60249139610e4c565b6002820180546001600160a01b0390921660008181526001948501602090815260408220860185905594840183559182529290200180546001600160a01b0319169091179055565b6001600160e01b0319831660008181526020868152604080832080546001600160601b03909716600160a01b026001600160a01b0397881617815594909516808352600180890183529583208054968701815583528183206008870401805460e09890981c60046007909816979097026101000a96870263ffffffff9097021990971695909517909555529290915281546001600160a01b031916179055565b6001600160a01b038216610b085760405162461bcd60e51b815260206004820152603760248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f76652066756e6360448201527f74696f6e207468617420646f65736e27742065786973740000000000000000006064820152608401610089565b6001600160a01b038216301415610b785760405162461bcd60e51b815260206004820152602e60248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f766520696d6d7560448201526d3a30b1363290333ab731ba34b7b760911b6064820152608401610089565b6001600160e01b03198116600090815260208481526040808320546001600160a01b0386168452600180880190935290832054600160a01b9091046001600160601b03169291610bc791611066565b9050808214610cb9576001600160a01b03841660009081526001860160205260408120805483908110610bfc57610bfc61112d565b600091825260208083206008830401546001600160a01b038916845260018a019091526040909220805460079092166004026101000a90920460e01b925082919085908110610c4d57610c4d61112d565b600091825260208083206008830401805463ffffffff60079094166004026101000a938402191660e09590951c929092029390931790556001600160e01b03199290921682528690526040902080546001600160a01b0316600160a01b6001600160601b038516021790555b6001600160a01b03841660009081526001860160205260409020805480610ce257610ce2611117565b60008281526020808220600860001990940193840401805463ffffffff600460078716026101000a0219169055919092556001600160e01b0319851682528690526040812055806104c2576002850154600090610d4190600190611066565b6001600160a01b0386166000908152600180890160205260409091200154909150808214610df0576000876002018381548110610d8057610d8061112d565b6000918252602090912001546002890180546001600160a01b039092169250829184908110610db157610db161112d565b600091825260208083209190910180546001600160a01b0319166001600160a01b03948516179055929091168152600189810190925260409020018190555b86600201805480610e0357610e03611117565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b0388168252600189810190915260408220015550505050505050565b813b818161076f5760405162461bcd60e51b81526004016100899190610fb5565b60008151808452610e8581602086016020860161107d565b601f01601f19169290920160200192915050565b60008251610eab81846020870161107d565b9190910192915050565b60006060808301818452808751808352608092508286019150828160051b8701016020808b0160005b84811015610f8557898403607f19018652815180516001600160a01b03168552838101518986019060038110610f2457634e487b7160e01b600052602160045260246000fd5b868601526040918201519186018a905281519081905290840190600090898701905b80831015610f705783516001600160e01b0319168252928601926001929092019190860190610f46565b50978501979550505090820190600101610ede565b50506001600160a01b038a16908801528681036040880152610fa78189610e6d565b9a9950505050505050505050565b602081526000610fc86020830184610e6d565b9392505050565b6020808252602b908201527f4c69624469616d6f6e644375743a204e6f2073656c6563746f727320696e206660408201526a1858d95d081d1bc818dd5d60aa1b606082015260800190565b6020808252602c908201527f4c69624469616d6f6e644375743a204164642066616365742063616e2774206260408201526b65206164647265737328302960a01b606082015260800190565b600082821015611078576110786110eb565b500390565b60005b83811015611098578181015183820152602001611080565b8381111561076f5750506000910152565b60006000198214156110bd576110bd6110eb565b5060010190565b60006001600160601b03808316818114156110e1576110e16110eb565b6001019392505050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fdfec8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c4c69624469616d6f6e644375743a205f696e6974206164647265737320686173206e6f20636f64654c69624469616d6f6e644375743a204e657720666163657420686173206e6f20636f6465a2646970667358221220795ef6cc7673851b890285a5dba416996941361b46ed69aa34655dcb7d15532464736f6c63430008070033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000cb1e9fa11edd27098a6b2ff23cb6b79183ccf8ee000000000000000000000000c46304a0b2accc4462d9bdcaa0f6bf632510d617
-----Decoded View---------------
Arg [0] : _contractOwner (address): 0xCB1e9fA11Edd27098A6B2Ff23cB6b79183ccf8Ee
Arg [1] : _diamondCutFacet (address): 0xC46304a0B2ACcC4462d9BDCAa0f6bf632510d617
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000cb1e9fa11edd27098a6b2ff23cb6b79183ccf8ee
Arg [1] : 000000000000000000000000c46304a0b2accc4462d9bdcaa0f6bf632510d617
Deployed Bytecode Sourcemap
175:2212:25:-:0;;;;;;;;1072:36;1422:7;;-1:-1:-1;;;;;;1422:7:25;1392:38;;-1:-1:-1;;;;;;;;;;;1392:38:25;;;;;;;;:51;197:45:28;;-1:-1:-1;;;;;1392:51:25;;1453:64;;;;-1:-1:-1;;;1453:64:25;;5678:2:32;1453:64:25;;;5660:21:32;;;5697:18;;;5690:30;5756:34;5736:18;;;5729:62;5808:18;;1453:64:25;;;;;;;;;1771:14;1768:1;1765;1752:34;1915:1;1912;1896:14;1893:1;1886:5;1879;1866:51;1987:16;1984:1;1981;1966:38;2091:6;2110:66;;;;2225:16;2222:1;2215:27;2110:66;2145:16;2142:1;2135:27;1612:264:28;1754:16;;;-1:-1:-1;;;;;;1780:28:28;;-1:-1:-1;;;;;1780:28:28;;;;;;;;;1823:46;;-1:-1:-1;;;;;;;;;;;197:45:28;1754:16;;;;;;1823:46;;1676:25;;1823:46;1666:210;;1612:264;:::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;;4857:2:32;3207:49:28;;;4839:21:32;4896:2;4876:18;;;4869:30;4935:34;4915:18;;;4908:62;-1:-1:-1;;;4986:18:32;;;4979:37;5033:19;;3207:49:28;4655: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;;6884:2:32;4250:95:28;;;6866:21:32;6923:2;6903:18;;;6896:30;6962:34;6942:18;;;6935:62;-1:-1:-1;;;7013:18:32;;;7006:51;7074:19;;4250:95:28;6682: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;;;;3487:979;;3397:1069;;:::o;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;;7306:2:32;5329:101:28;;;7288:21:32;7345:2;7325:18;;;7318:30;7384:34;7364:18;;;7357:62;7455:26;7435:18;;;7428:54;7499:19;;5329:101:28;7104: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;;7731:2:32;5933:94:28;;;7713:21:32;7770:2;7750:18;;;7743:30;7809:34;7789:18;;;7782:62;-1:-1:-1;;;7860:18:32;;;7853:52;7922:19;;5933:94:28;7529: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;;3185:2:32;9464:94:28;;;3167:21:32;3224:2;3204:18;;;3197:30;3263:34;3243:18;;;3236:62;3334:30;3314:18;;;3307:58;3382:19;;9464:94:28;2983:424:32;9464:94:28;9337:934;;:::o;9425:840::-;9616:1;9597:9;:16;:20;9589:94;;;;-1:-1:-1;;;9589:94:28;;6039:2:32;9589:94:28;;;6021:21:32;6078:2;6058:18;;;6051:30;6117:34;6097:18;;;6090:62;6188:31;6168:18;;;6161:59;6237:19;;9589:94:28;5837: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;;3614:2:32;10174:48:28;;;3596:21:32;3653:2;3633:18;;;3626:30;3692:34;3672:18;;;3665:62;-1:-1:-1;;;3743:18:32;;;3736:36;3789:19;;10174:48:28;3412: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;;4433:2:32;7260:95:28;;;4415:21:32;4472:2;4452:18;;;4445:30;4511:34;4491:18;;;4484:62;4582:25;4562:18;;;4555:53;4625:19;;7260:95:28;4231:419:32;7260:95:28;-1:-1:-1;;;;;7450:30:28;;7475:4;7450:30;;7442:89;;;;-1:-1:-1;;;7442:89:28;;6469:2:32;7442:89:28;;;6451:21:32;6508:2;6488:18;;;6481:30;6547:34;6527:18;;;6520:62;-1:-1:-1;;;6598:18:32;;;6591:44;6652:19;;7442:89:28;6267: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;123:257:32:-;164:3;202:5;196:12;229:6;224:3;217:19;245:63;301:6;294:4;289:3;285:14;278:4;271:5;267:16;245:63;:::i;:::-;362:2;341:15;-1:-1:-1;;337:29:32;328:39;;;;369:4;324:50;;123:257;-1:-1:-1;;123:257:32:o;385:274::-;514:3;552:6;546:13;568:53;614:6;609:3;602:4;594:6;590:17;568:53;:::i;:::-;637:16;;;;;385:274;-1:-1:-1;;385:274:32:o;664:2090::-;932:4;961:2;1001;990:9;986:18;1031:2;1020:9;1013:21;1054:6;1089;1083:13;1120:6;1112;1105:22;1146:3;1136:13;;1180:2;1169:9;1165:18;1158:25;;1242:2;1232:6;1229:1;1225:14;1214:9;1210:30;1206:39;1264:4;1303:2;1295:6;1291:15;1324:1;1334:1249;1348:6;1345:1;1342:13;1334:1249;;;1413:22;;;-1:-1:-1;;1409:37:32;1397:50;;1470:13;;1557:9;;-1:-1:-1;;;;;1553:35:32;1538:51;;1628:11;;;1622:18;1510:15;;;;1680:1;1663:19;;1653:170;;1733:10;1728:3;1724:20;1721:1;1714:31;1772:4;1769:1;1762:15;1804:4;1801:1;1794:15;1653:170;1843:15;;;1836:37;1896:4;1941:11;;;1935:18;1973:15;;;1966:27;;;2054:21;;2088:24;;;;2178:23;;;;-1:-1:-1;;2134:15:32;;;;2239:236;2255:8;2250:3;2247:17;2239:236;;;2336:15;;-1:-1:-1;;;;;;2332:42:32;2318:57;;2444:17;;;;2283:1;2274:11;;;;;2401:14;;;;2239:236;;;-1:-1:-1;2561:12:32;;;;2498:5;-1:-1:-1;;;2526:15:32;;;;1370:1;1363:9;1334:1249;;;-1:-1:-1;;;;;;;80:31:32;;2619:18;;;68:44;2676:22;;;2669:4;2654:20;;2647:52;2716:32;2680:6;2733;2716:32;:::i;:::-;2708:40;664:2090;-1:-1:-1;;;;;;;;;;664:2090:32:o;2759:219::-;2908:2;2897:9;2890:21;2871:4;2928:44;2968:2;2957:9;2953:18;2945:6;2928:44;:::i;:::-;2920:52;2759:219;-1:-1:-1;;;2759:219:32:o;3819:407::-;4021:2;4003:21;;;4060:2;4040:18;;;4033:30;4099:34;4094:2;4079:18;;4072:62;-1:-1:-1;;;4165:2:32;4150:18;;4143:41;4216:3;4201:19;;3819:407::o;5063:408::-;5265:2;5247:21;;;5304:2;5284:18;;;5277:30;5343:34;5338:2;5323:18;;5316:62;-1:-1:-1;;;5409:2:32;5394:18;;5387:42;5461:3;5446:19;;5063:408::o;7952:125::-;7992:4;8020:1;8017;8014:8;8011:34;;;8025:18;;:::i;:::-;-1:-1:-1;8062:9:32;;7952:125::o;8082:258::-;8154:1;8164:113;8178:6;8175:1;8172:13;8164:113;;;8254:11;;;8248:18;8235:11;;;8228:39;8200:2;8193:10;8164:113;;;8295:6;8292:1;8289:13;8286:48;;;-1:-1:-1;;8330:1:32;8312:16;;8305:27;8082:258::o;8345:135::-;8384:3;-1:-1:-1;;8405:17:32;;8402:43;;;8425:18;;:::i;:::-;-1:-1:-1;8472:1:32;8461:13;;8345:135::o;8485:217::-;8523:3;-1:-1:-1;;;;;8612:2:32;8605:5;8601:14;8639:2;8630:7;8627:15;8624:41;;;8645:18;;:::i;:::-;8694:1;8681:15;;8485:217;-1:-1:-1;;;8485:217:32:o;8707:127::-;8768:10;8763:3;8759:20;8756:1;8749:31;8799:4;8796:1;8789:15;8823:4;8820:1;8813:15;8839:127;8900:10;8895:3;8891:20;8888:1;8881:31;8931:4;8928:1;8921:15;8955:4;8952:1;8945:15;8971:127;9032:10;9027:3;9023:20;9020:1;9013:31;9063:4;9060:1;9053:15;9087:4;9084:1;9077:15;9103:127;9164:10;9159:3;9155:20;9152:1;9145:31;9195:4;9192:1;9185:15;9219:4;9216:1;9209:15
Swarm Source
ipfs://795ef6cc7673851b890285a5dba416996941361b46ed69aa34655dcb7d155324
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$4.22
Net Worth in POL
Token Allocations
IMX.A
54.56%
USDT
17.65%
WOO
12.19%
Others
15.60%
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| AVAX | 54.56% | $0.004143 | 556.3432 | $2.3 | |
| AVAX | 5.51% | $2,935.83 | 0.00007929 | $0.2327 | |
| OP | 17.65% | $0.998573 | 0.7468 | $0.7457 | |
| OP | <0.01% | $2,936.24 | 0.00000000000000003 | <$0.000001 | |
| BSC | 12.19% | $0.024766 | 20.7952 | $0.515 | |
| BSC | 4.78% | $89,036.19 | 0.00000227 | $0.2019 | |
| POL | 2.53% | $0.000664 | 161.05 | $0.1069 | |
| POL | 0.41% | $0.124986 | 0.14 | $0.017498 | |
| GNO | 2.37% | $0.999488 | 0.1 | $0.099949 |
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.