POL Price: $0.578891 (-15.04%)
Gas: 45.7 GWei
 

Overview

POL Balance

Polygon PoS Chain LogoPolygon PoS Chain LogoPolygon PoS Chain Logo0.140000000000000102 POL

POL Value

$0.08 (@ $0.58/POL)

Token Holdings

Multichain Info

Transaction Hash
Method
Block
From
To
Start Bridge Tok...289891582022-05-31 10:42:50923 days ago1653993770IN
0x5A9Fd7c3...3d5596eD1
0 POL0.0114820239.8
Start Bridge Tok...289888252022-05-31 10:31:19923 days ago1653993079IN
0x5A9Fd7c3...3d5596eD1
0 POL0.0080271330.00000001
Swap And Start B...289887932022-05-31 10:30:07923 days ago1653993007IN
0x5A9Fd7c3...3d5596eD1
119 POL0.0173991640
Swap And Start B...289886752022-05-31 10:26:07923 days ago1653992767IN
0x5A9Fd7c3...3d5596eD1
40 POL0.0368491550
Swap And Start B...289886042022-05-31 10:23:32923 days ago1653992612IN
0x5A9Fd7c3...3d5596eD1
10 POL0.0307629240
Start Bridge Tok...289885172022-05-31 10:20:34923 days ago1653992434IN
0x5A9Fd7c3...3d5596eD1
0 POL0.015425450
Swap And Start B...289883002022-05-31 10:13:08923 days ago1653991988IN
0x5A9Fd7c3...3d5596eD1
25 POL0.031493550
Swap And Start B...289882862022-05-31 10:12:32923 days ago1653991952IN
0x5A9Fd7c3...3d5596eD1
0 POL0.017109440
Start Bridge Tok...289882622022-05-31 10:11:44923 days ago1653991904IN
0x5A9Fd7c3...3d5596eD1
0 POL0.0151886550
Swap And Start B...289882482022-05-31 10:11:16923 days ago1653991876IN
0x5A9Fd7c3...3d5596eD1
100 POL0.0193376440
Swap And Start B...289881882022-05-31 10:09:12923 days ago1653991752IN
0x5A9Fd7c3...3d5596eD1
0 POL0.01891750
Start Bridge Tok...289881462022-05-31 10:07:44923 days ago1653991664IN
0x5A9Fd7c3...3d5596eD1
0 POL0.0141846550
Start Bridge Tok...289881142022-05-31 10:06:40923 days ago1653991600IN
0x5A9Fd7c3...3d5596eD1
0 POL0.013405650
Start Bridge Tok...289879262022-05-31 10:00:12923 days ago1653991212IN
0x5A9Fd7c3...3d5596eD1
0 POL0.0060026550
Start Bridge Tok...289879042022-05-31 9:59:28923 days ago1653991168IN
0x5A9Fd7c3...3d5596eD1
0 POL0.0141846550
Start Bridge Tok...289878692022-05-31 9:57:06923 days ago1653991026IN
0x5A9Fd7c3...3d5596eD1
0 POL0.006610550
Swap And Start B...289878242022-05-31 9:54:32923 days ago1653990872IN
0x5A9Fd7c3...3d5596eD1
0 POL0.0318687550
Swap And Start B...289877712022-05-31 9:52:42923 days ago1653990762IN
0x5A9Fd7c3...3d5596eD1
0 POL0.0240469550
Start Bridge Tok...289877692022-05-31 9:52:38923 days ago1653990758IN
0x5A9Fd7c3...3d5596eD1
0 POL0.0103589240
Start Bridge Tok...289877522022-05-31 9:52:04923 days ago1653990724IN
0x5A9Fd7c3...3d5596eD1
0 POL0.006610550
Start Bridge Tok...289876812022-05-31 9:49:38923 days ago1653990578IN
0x5A9Fd7c3...3d5596eD1
0 POL0.0043083234.3257644
Start Bridge Tok...289876742022-05-31 9:49:24923 days ago1653990564IN
0x5A9Fd7c3...3d5596eD1
0 POL0.02536212140
Start Bridge Tok...289876102022-05-31 9:47:12923 days ago1653990432IN
0x5A9Fd7c3...3d5596eD1
0 POL0.005516950
Start Bridge Tok...289875922022-05-31 9:46:36923 days ago1653990396IN
0x5A9Fd7c3...3d5596eD1
0 POL0.0118282141
Start Bridge Tok...289875402022-05-31 9:44:48923 days ago1653990288IN
0x5A9Fd7c3...3d5596eD1
0 POL0.0100086835.27999999
View all transactions

Latest 25 internal transactions (View All)

Parent Transaction Hash Block From To
289887932022-05-31 10:30:07923 days ago1653993007
0x5A9Fd7c3...3d5596eD1
119 POL
289886752022-05-31 10:26:07923 days ago1653992767
0x5A9Fd7c3...3d5596eD1
40 POL
289886042022-05-31 10:23:32923 days ago1653992612
0x5A9Fd7c3...3d5596eD1
10 POL
289884532022-05-31 10:18:22923 days ago1653992302
0x5A9Fd7c3...3d5596eD1
119.27275213 POL
289884532022-05-31 10:18:22923 days ago1653992302
0x5A9Fd7c3...3d5596eD1
119.27275213 POL
289883572022-05-31 10:15:06923 days ago1653992106
0x5A9Fd7c3...3d5596eD1
119.66784217 POL
289883572022-05-31 10:15:06923 days ago1653992106
0x5A9Fd7c3...3d5596eD1
119.66784217 POL
289883002022-05-31 10:13:08923 days ago1653991988
0x5A9Fd7c3...3d5596eD1
25 POL
289882482022-05-31 10:11:16923 days ago1653991876
0x5A9Fd7c3...3d5596eD1
100 POL
289873892022-05-31 9:39:34923 days ago1653989974
0x5A9Fd7c3...3d5596eD1
64 POL
289870082022-05-31 9:26:32923 days ago1653989192
0x5A9Fd7c3...3d5596eD1
2 wei
289870082022-05-31 9:26:32923 days ago1653989192
0x5A9Fd7c3...3d5596eD1
0.069 POL
289867402022-05-31 9:17:16923 days ago1653988636
0x5A9Fd7c3...3d5596eD1
0.066 POL
289866832022-05-31 9:15:18923 days ago1653988518
0x5A9Fd7c3...3d5596eD1
137.7211151 POL
289866832022-05-31 9:15:18923 days ago1653988518
0x5A9Fd7c3...3d5596eD1
137.7211151 POL
289866562022-05-31 9:14:24923 days ago1653988464
0x5A9Fd7c3...3d5596eD1
3.01448149 POL
289866562022-05-31 9:14:24923 days ago1653988464
0x5A9Fd7c3...3d5596eD1
3.01448149 POL
289865292022-05-31 9:10:02923 days ago1653988202
0x5A9Fd7c3...3d5596eD1
20 POL
289864972022-05-31 9:08:58923 days ago1653988138
0x5A9Fd7c3...3d5596eD1
0.052 POL
289856832022-05-31 8:40:50923 days ago1653986450
0x5A9Fd7c3...3d5596eD1
15 POL
289855382022-05-31 8:35:52923 days ago1653986152
0x5A9Fd7c3...3d5596eD1
0.08 POL
289855362022-05-31 8:35:48923 days ago1653986148
0x5A9Fd7c3...3d5596eD1
4 POL
289853152022-05-31 8:26:02923 days ago1653985562
0x5A9Fd7c3...3d5596eD1
2 wei
289853152022-05-31 8:26:02923 days ago1653985562
0x5A9Fd7c3...3d5596eD1
0.07 POL
289843782022-05-31 7:53:48923 days ago1653983628
0x5A9Fd7c3...3d5596eD1
0.043 POL
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
LiFiDiamond

Compiler Version
v0.8.7+commit.e28d00a7

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license
File 1 of 32 : LiFiDiamond.sol
// 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 {}
}

File 2 of 32 : AnyswapFacet.sol
// 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
        }
    }
}

File 3 of 32 : ERC20.sol
// 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 {}
}

File 4 of 32 : ILiFi.sol
// 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
    );
}

File 5 of 32 : IAnyswapRouter.sol
// 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;
}

File 6 of 32 : LibDiamond.sol
// 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);
    }
}

File 7 of 32 : LibAsset.sol
// 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);
    }
}

File 8 of 32 : LibSwap.sol
// 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
        );
    }
}

File 9 of 32 : IAnyswapToken.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

interface IAnyswapToken {
    function underlying() external returns (address);
}

File 10 of 32 : IERC20.sol
// 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);
}

File 11 of 32 : IERC20Metadata.sol
// 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);
}

File 12 of 32 : Context.sol
// 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;
    }
}

File 13 of 32 : IDiamondCut.sol
// 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);
}

File 14 of 32 : SafeERC20.sol
// 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");
        }
    }
}

File 15 of 32 : Address.sol
// 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);
            }
        }
    }
}

File 16 of 32 : LibUtil.sol
// 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
    }
}

File 17 of 32 : LibBytes.sol
// 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;
    }
}

File 18 of 32 : NXTPFacet.sol
// 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);
    }
}

File 19 of 32 : ITransactionManager.sol
// 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);
}

File 20 of 32 : DiamondCutFacet.sol
// 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);
    }
}

File 21 of 32 : WithdrawFacet.sol
// 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);
    }
}

File 22 of 32 : HopFacet.sol
// 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
        }
    }
}

File 23 of 32 : IHopBridge.sol
// 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;
}

File 24 of 32 : GenericBridgeFacet.sol
// 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);
        }
    }
}

File 25 of 32 : USDT.sol
// 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));
    }
}

File 26 of 32 : CBridgeFacet.sol
// 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
        }
    }
}

File 27 of 32 : ICBridge.sol
// 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;
}

File 28 of 32 : OwnershipFacet.sol
// 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();
    }
}

File 29 of 32 : IERC173.sol
// 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;
}

File 30 of 32 : DiamondLoupeFacet.sol
// 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];
    }
}

File 31 of 32 : IDiamondLoupe.sol
// 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_);
}

File 32 of 32 : IERC165.sol
// 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);
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  },
  "metadata": {
    "useLiteralContent": true
  }
}

Contract Security Audit

Contract ABI

[{"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"}]

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

Block Transaction Gas Used Reward
view all blocks produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
[ 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.