ETH Price: $1,793.04 (+10.15%)

Contract

0x00000029e6005863Bb2E1686a17C4ae0D1723669
 

Overview

ETH Balance

0 ETH

ETH Value

$0.00

Token Holdings

Transaction Hash
Method
Block
From
To
Execute79518682024-08-26 23:05:51239 days ago1724713551IN
0x00000029...0D1723669
0 ETH0.000000250.00110146
Execute77406382024-08-22 1:44:51244 days ago1724291091IN
0x00000029...0D1723669
0.00998913 ETH0.000006610.01967615
Execute77133702024-08-21 10:35:55244 days ago1724236555IN
0x00000029...0D1723669
0 ETH0.000002240.00991989
Execute77131032024-08-21 10:27:01244 days ago1724236021IN
0x00000029...0D1723669
0.00501125 ETH0.000003050.00908649
Execute77119882024-08-21 9:49:51244 days ago1724233791IN
0x00000029...0D1723669
0 ETH0.000002120.00930698
Execute77115852024-08-21 9:36:25244 days ago1724232985IN
0x00000029...0D1723669
0.0208938 ETH0.00000340.0101382
Execute77114832024-08-21 9:33:01244 days ago1724232781IN
0x00000029...0D1723669
0 ETH0.000002290.01028073
Execute77088262024-08-21 8:04:27245 days ago1724227467IN
0x00000029...0D1723669
0 ETH0.000002270.01050846
Execute77087772024-08-21 8:02:49245 days ago1724227369IN
0x00000029...0D1723669
0.00003853 ETH0.000003770.0107033
Execute77073382024-08-21 7:14:51245 days ago1724224491IN
0x00000029...0D1723669
0.03558515 ETH0.000003490.01039948
Execute77072532024-08-21 7:12:01245 days ago1724224321IN
0x00000029...0D1723669
0 ETH0.00000230.01031241
Execute77059062024-08-21 6:27:07245 days ago1724221627IN
0x00000029...0D1723669
0.005241 ETH0.00000230.0097
Execute77046622024-08-21 5:45:39245 days ago1724219139IN
0x00000029...0D1723669
2.00001056 ETH0.000003160.00942016
Execute77046062024-08-21 5:43:47245 days ago1724219027IN
0x00000029...0D1723669
2.00001074 ETH0.000003220.00958724
Execute77045792024-08-21 5:42:53245 days ago1724218973IN
0x00000029...0D1723669
1.00001073 ETH0.000003250.00967816
Execute77044322024-08-21 5:37:59245 days ago1724218679IN
0x00000029...0D1723669
1.00001099 ETH0.000003320.00988943
Execute77043822024-08-21 5:36:19245 days ago1724218579IN
0x00000029...0D1723669
1.00001124 ETH0.000003570.01012714
Execute76920682024-08-20 22:45:51245 days ago1724193951IN
0x00000029...0D1723669
0.000088 ETH0.000001750.0078
Execute76891762024-08-20 21:09:27245 days ago1724188167IN
0x00000029...0D1723669
0 ETH0.000002410.0107
Execute76883632024-08-20 20:42:21245 days ago1724186541IN
0x00000029...0D1723669
0 ETH0.000002410.0108
Execute76880552024-08-20 20:32:05245 days ago1724185925IN
0x00000029...0D1723669
0.00501103 ETH0.000003770.01124388
Execute76783372024-08-20 15:08:09245 days ago1724166489IN
0x00000029...0D1723669
0 ETH0.000002840.01259626
Execute76774012024-08-20 14:36:57245 days ago1724164617IN
0x00000029...0D1723669
0.0168493 ETH0.000004390.01243858
Execute76755792024-08-20 13:36:13245 days ago1724160973IN
0x00000029...0D1723669
0.00501572 ETH0.00000410.01163145
Execute76726432024-08-20 11:58:21245 days ago1724155101IN
0x00000029...0D1723669
0.00421037 ETH0.000003710.01052632
View all transactions

Latest 25 internal transactions (View All)

Parent Transaction Hash Block From To
79518682024-08-26 23:05:51239 days ago1724713551
0x00000029...0D1723669
0.05052066 ETH
79518682024-08-26 23:05:51239 days ago1724713551
0x00000029...0D1723669
0.05052066 ETH
77406382024-08-22 1:44:51244 days ago1724291091
0x00000029...0D1723669
0.00001987 ETH
77406382024-08-22 1:44:51244 days ago1724291091
0x00000029...0D1723669
0.00996925 ETH
77406162024-08-22 1:44:07244 days ago1724291047
0x00000029...0D1723669
0.0099911 ETH
77406162024-08-22 1:44:07244 days ago1724291047
0x00000029...0D1723669
0.0099911 ETH
77139692024-08-21 10:55:53244 days ago1724237753
0x00000029...0D1723669
0.01401874 ETH
77139692024-08-21 10:55:53244 days ago1724237753
0x00000029...0D1723669
0.01401874 ETH
77137932024-08-21 10:50:01244 days ago1724237401
0x00000029...0D1723669
0.02514874 ETH
77137932024-08-21 10:50:01244 days ago1724237401
0x00000029...0D1723669
0.02514874 ETH
77134612024-08-21 10:38:57244 days ago1724236737
0x00000029...0D1723669
0.04005667 ETH
77134612024-08-21 10:38:57244 days ago1724236737
0x00000029...0D1723669
0.04005667 ETH
77133702024-08-21 10:35:55244 days ago1724236555
0x00000029...0D1723669
0.03216331 ETH
77133702024-08-21 10:35:55244 days ago1724236555
0x00000029...0D1723669
0.03216331 ETH
77131622024-08-21 10:28:59244 days ago1724236139
0x00000029...0D1723669
0.0030181 ETH
77131622024-08-21 10:28:59244 days ago1724236139
0x00000029...0D1723669
0.0030181 ETH
77131032024-08-21 10:27:01244 days ago1724236021
0x00000029...0D1723669
0.00001125 ETH
77131032024-08-21 10:27:01244 days ago1724236021
0x00000029...0D1723669
0.005 ETH
77130742024-08-21 10:26:03244 days ago1724235963
0x00000029...0D1723669
0.00503026 ETH
77130742024-08-21 10:26:03244 days ago1724235963
0x00000029...0D1723669
0.00503026 ETH
77119882024-08-21 9:49:51244 days ago1724233791
0x00000029...0D1723669
0.0103614 ETH
77119882024-08-21 9:49:51244 days ago1724233791
0x00000029...0D1723669
0.0103614 ETH
77115852024-08-21 9:36:25244 days ago1724232985
0x00000029...0D1723669
0.00001023 ETH
77115852024-08-21 9:36:25244 days ago1724232985
0x00000029...0D1723669
0.02088356 ETH
77114832024-08-21 9:33:01244 days ago1724232781
0x00000029...0D1723669
0.02040903 ETH
View All Internal Transactions

Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
CatalystRouter

Compiler Version
v0.8.22+commit.4fc1097e

Optimization Enabled:
Yes with 10000 runs

Other Settings:
paris EvmVersion, MIT license
File 1 of 29 : CatalystRouter.sol
//SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.19;

// Command implementations
import {Dispatcher} from './base/Dispatcher.sol';
import {RouterParameters, RouterImmutables} from './base/RouterImmutables.sol';
import {Commands} from './libraries/Commands.sol';
import {BytesLib} from './libraries/BytesLib.sol';
import {ICatalystRouter} from './interfaces/ICatalystRouter.sol';
import {ICatalystReceiver} from '../interfaces/IOnCatalyst.sol';

/**
 * @title Catalyst: Swap Router
 * @author Catalyst Labs
 * @notice Based on the Universal Router by Uniswap
 * https://github.com/Uniswap/universal-router
 */
contract CatalystRouter is RouterImmutables, ICatalystRouter, Dispatcher, ICatalystReceiver {
    using BytesLib for bytes;

    modifier checkDeadline(uint256 deadline) {
        if (block.timestamp > deadline) revert TransactionDeadlinePassed();
        _;
    }

    constructor(RouterParameters memory params) payable RouterImmutables(params) {}

    /// @inheritdoc ICatalystRouter
    function execute(
        bytes calldata commands,
        bytes[] calldata inputs,
        uint256 deadline
    ) external payable checkDeadline(deadline) {
        execute(commands, inputs);
    }

    /// @inheritdoc Dispatcher
    function execute(bytes calldata commands, bytes[] calldata inputs)
        public
        payable
        override
        isNotLocked
    {
        bool success;
        bytes memory output;
        uint256 numCommands = commands.length;
        if (inputs.length != numCommands) revert LengthMismatch();

        // loop through all given commands, execute them and pass along outputs as defined
        for (uint256 commandIndex = 0; commandIndex < numCommands; ) {
            bytes1 command = commands[commandIndex];

            bytes calldata input = inputs[commandIndex];

            (success, output) = dispatch(command, input);

            if (!success && successRequired(command)) {
                revert ExecutionFailed({
                    commandIndex: commandIndex,
                    message: output
                });
            }

            unchecked {
                commandIndex++;
            }
        }
    }

    function successRequired(bytes1 command) internal pure returns (bool) {
        return command & Commands.FLAG_ALLOW_REVERT == 0;
    }

    function onCatalystCall(uint256 /* purchasedTokens */, bytes calldata data, bool /* underwritten */) external {
        bytes calldata commands = data.toBytes(0);
        bytes[] calldata inputs = data.toBytesArray(1);

        execute(commands, inputs);
    }

    /// @notice To receive ETH from WETH and NFT protocols
    receive() external payable {}
}

File 2 of 29 : Dispatcher.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.17;

import {IAllowanceTransfer} from '../libraries/permit2/IAllowanceTransfer.sol';
import {ERC20} from 'solady/tokens/ERC20.sol';
import {RouterImmutables} from '../base/RouterImmutables.sol';
import {Payments} from '../libraries/Payments.sol';
import {Permit2Payments} from '../libraries/Permit2Payments.sol';
import {CatalystExchange} from '../libraries/CatalystExchange.sol';
import {Commands} from '../libraries/Commands.sol';
import {BytesLib} from '../libraries/BytesLib.sol';
import {CancelSwap} from '../libraries/CancelSwap.sol';
import {LockAndMsgSender} from './LockAndMsgSender.sol';
import {ICatalystV1Structs} from '../../interfaces/ICatalystV1VaultState.sol';

/// @title Decodes and Executes Commands
/// @notice Called by the UniversalRouter contract to efficiently decode and execute a singular command
abstract contract Dispatcher is Permit2Payments, CatalystExchange, CancelSwap, LockAndMsgSender {
    using BytesLib for bytes;

    error debugError(bytes tt);  // 300df159
    error InvalidCommandType(uint256 commandType);  // d76a1e9e
    error BalanceTooLow();  // a3281672

    /// @notice Decodes and executes the given command with the given inputs
    /// @param commandType The command type to execute
    /// @param inputs The inputs to execute the command with
    /// @dev 2 masks are used to enable use of a nested-if statement in execution for efficiency reasons
    /// @return success True on success of the command, false on failure
    /// @return output The outputs or error messages, if any, from the command
    function dispatch(bytes1 commandType, bytes calldata inputs) internal returns (bool success, bytes memory output) {
        uint256 command = uint8(commandType & Commands.COMMAND_TYPE_MASK);

        success = true;

        if (command < 0x10) {
            // 0x00 <= command < 0x07
            if (command < 0x07) {
                if (command == Commands.LOCALSWAP) {
                    // equivalent:  abi.decode(inputs, (address, address, address, uint256, uint256))
                    address vault;
                    address fromAsset;
                    address toAsset;
                    uint256 amount;
                    uint256 minOut;
                    assembly {
                        vault := calldataload(inputs.offset)
                        fromAsset := calldataload(add(inputs.offset, 0x20))
                        toAsset := calldataload(add(inputs.offset, 0x40))
                        amount := calldataload(add(inputs.offset, 0x60))
                        minOut := calldataload(add(inputs.offset, 0x80))
                    }
                    CatalystExchange.localSwap(vault, fromAsset, toAsset, amount, minOut);
                }  else if (command == Commands.SENDASSET) {
                    (address vault, RouteDescription memory routeDescription, address fromAsset, uint8 toAssetIndex8, uint256 amount, uint256 minOut, address fallbackUser, uint256 gas, uint16 underwritingIncentive) = abi.decode(inputs, (address, RouteDescription, address, uint8, uint256, uint256, address, uint256, uint16));

                    // To save gas, the calldata is decoded as a slice at the end. This is possible because we know the exact sizes of
                    // other variables.
                    bytes calldata calldata_ = inputs[864:];
                    
                    CatalystExchange.sendAsset(vault, routeDescription, fromAsset, toAssetIndex8, amount, minOut, map(fallbackUser), gas, underwritingIncentive, calldata_);
                } else if (command == Commands.PERMIT2_TRANSFER_FROM) {
                    // equivalent: abi.decode(inputs, (address, address, uint160))
                    address token;
                    address recipient;
                    uint160 amount;
                    assembly {
                        token := calldataload(inputs.offset)
                        recipient := calldataload(add(inputs.offset, 0x20))
                        amount := calldataload(add(inputs.offset, 0x40))
                    }
                    permit2TransferFrom(token, lockedBy, map(recipient), amount);
                } else if (command == Commands.PERMIT2_PERMIT_BATCH) {
                    (IAllowanceTransfer.PermitBatch memory permitBatch,) =
                        abi.decode(inputs, (IAllowanceTransfer.PermitBatch, bytes));
                    bytes calldata data = inputs.toBytes(1);
                    PERMIT2.permit(lockedBy, permitBatch, data);
                } else if (command == Commands.SWEEP) {
                    // equivalent:  abi.decode(inputs, (address, address, uint256))
                    address token;
                    address recipient;
                    uint160 amountMin;
                    assembly {
                        token := calldataload(inputs.offset)
                        recipient := calldataload(add(inputs.offset, 0x20))
                        amountMin := calldataload(add(inputs.offset, 0x40))
                    }
                    Payments.sweep(token, map(recipient), amountMin);
                } else if (command == Commands.TRANSFER) {
                    // equivalent:  abi.decode(inputs, (address, address, uint256))
                    address token;
                    address recipient;
                    uint256 value;
                    assembly {
                        token := calldataload(inputs.offset)
                        recipient := calldataload(add(inputs.offset, 0x20))
                        value := calldataload(add(inputs.offset, 0x40))
                    }
                    Payments.pay(token, map(recipient), value);
                } else if (command == Commands.PAY_PORTION) {
                    // equivalent:  abi.decode(inputs, (address, address, uint256))
                    address token;
                    address recipient;
                    uint256 bips;
                    assembly {
                        token := calldataload(inputs.offset)
                        recipient := calldataload(add(inputs.offset, 0x20))
                        bips := calldataload(add(inputs.offset, 0x40))
                    }
                    Payments.payPortion(token, map(recipient), bips);
                }
            // 0x08 <= command < 0x0d
            } else if (command < 0x0d) { // 0x08 <= command < 0x0d
                if (command == Commands.PERMIT2_PERMIT) {
                    // equivalent: abi.decode(inputs, (IAllowanceTransfer.PermitSingle, bytes))
                    IAllowanceTransfer.PermitSingle calldata permitSingle;
                    assembly {
                        permitSingle := inputs.offset
                    }
                    bytes calldata data = inputs.toBytes(6); // PermitSingle takes first 6 slots (0..5)
                    PERMIT2.permit(lockedBy, permitSingle, data);
                } else if (command == Commands.WRAP_GAS) {
                    // equivalent: abi.decode(inputs, (address, uint256))
                    address recipient;
                    uint256 amountMin;
                    assembly {
                        recipient := calldataload(inputs.offset)
                        amountMin := calldataload(add(inputs.offset, 0x20))
                    }
                    Payments.wrapETH(map(recipient), amountMin);
                } else if (command == Commands.UNWRAP_GAS) {
                    // equivalent: abi.decode(inputs, (address, uint256))
                    address recipient;
                    uint256 amountMin;
                    assembly {
                        recipient := calldataload(inputs.offset)
                        amountMin := calldataload(add(inputs.offset, 0x20))
                    }
                    Payments.unwrapWETH9(map(recipient), amountMin);
                } else if (command == Commands.WITHDRAW_EQUAL) {
                    // equivalent:  abi.decode(inputs, (address, uint256, uint256[]))
                    address vault;
                    uint256 amount;
                    assembly {
                        vault := calldataload(inputs.offset)
                        amount := calldataload(add(inputs.offset, 0x20))
                    }

                    uint256[] calldata minOut = inputs.toUintArray(2);
                    
                    CatalystExchange.withdrawAll(vault, amount, minOut);
                } else if (command == Commands.WITHDRAW_MIXED) {
                    // equivalent:  abi.decode(inputs, (address, uint256, uint256[], uint256[]))
                    address vault;
                    uint256 amount;
                    assembly {
                        vault := calldataload(inputs.offset)
                        amount := calldataload(add(inputs.offset, 0x20))
                    }

                    uint256[] calldata withdrawRatio = inputs.toUintArray(2);
                    uint256[] calldata minOut = inputs.toUintArray(3);

                    CatalystExchange.withdrawMixed(vault, amount, withdrawRatio, minOut);
                } else if (command == Commands.DEPOSIT_MIXED) {
                    // equivalent:  abi.decode(inputs, (address, address[], uint256[], uint256))
                    address vault;
                    uint256 minOut;
                    assembly {
                        vault := calldataload(inputs.offset)
                        minOut := calldataload(add(inputs.offset, 0x60))
                    }

                    address[] calldata tokens = inputs.toAddressArray(1);
                    uint256[] calldata tokenAmounts = inputs.toUintArray(2);

                    CatalystExchange.depositMixed(vault, tokens, tokenAmounts, minOut);
                }
                // 0x0e <= command < 0x10
            } else if (command < 0x10) {
                if (command == Commands.SENDLIQUIDITY) {
                    (address vault, RouteDescription memory routeDescription, uint256 amount, uint256[2] memory minOut, address fallbackUser, uint256 gas) = abi.decode(inputs, (address, RouteDescription, uint256, uint256[2], address, uint256));

                    // To save gas, the calldata is decoded as a slice at the end. This is possible because we know the exact sizes of
                    // other variables.
                    bytes calldata calldata_ = inputs[800:];
                    
                    CatalystExchange.sendLiquidity(vault, routeDescription, amount, minOut, fallbackUser, gas, calldata_);
                } else if (command == Commands.ALLOW_CANCEL) {
                    // equivalent: abi.decode(inputs, (address, bytes32))
                    address swappie;
                    bytes32 cancelIdentifier;
                    assembly {
                        swappie := calldataload(inputs.offset)
                        cancelIdentifier := calldataload(add(inputs.offset, 0x20))
                    }
                    CancelSwap.requireNotCanceled(swappie, cancelIdentifier);
                } else if (command == Commands.BALANCE_CHECK_ERC20) {
                    // equivalent: abi.decode(inputs, (address, address, uint256))
                    address owner;
                    address token;
                    uint256 minBalance;
                    assembly {
                        owner := calldataload(inputs.offset)
                        token := calldataload(add(inputs.offset, 0x20))
                        minBalance := calldataload(add(inputs.offset, 0x40))
                    }
                    success = (ERC20(token).balanceOf(owner) >= minBalance);
                    if (!success) output = abi.encodePacked(BalanceTooLow.selector);
                }
            }
        } else {
             if (command == Commands.PERMIT2_TRANSFER_FROM_BATCH) {
                (IAllowanceTransfer.AllowanceTransferDetails[] memory batchDetails) = abi.decode(inputs, (IAllowanceTransfer.AllowanceTransferDetails[]));
                permit2TransferFrom(batchDetails, lockedBy);
             } else if (command == Commands.TRANSFER_FROM) {
                    // equivalent: abi.decode(inputs, (address, address, uint160))
                    address token;
                    address recipient;
                    uint160 amount;
                    assembly {
                        token := calldataload(inputs.offset)
                        recipient := calldataload(add(inputs.offset, 0x20))
                        amount := calldataload(add(inputs.offset, 0x40))
                    }
                    Payments.transferFrom(token, lockedBy, map(recipient), amount);
            } else if (command == Commands.EXECUTE_SUB_PLAN) {
                (bytes memory _commands, bytes[] memory _inputs) = abi.decode(inputs, (bytes, bytes[]));
                (success, output) =
                    (address(this)).call(abi.encodeWithSelector(Dispatcher.execute.selector, _commands, _inputs));
            } else {
                // placeholder area for all other commands
                revert InvalidCommandType(command);
            }
        }
    }

    /// @notice Executes encoded commands along with provided inputs.
    /// @param commands A set of concatenated commands, each 1 byte in length
    /// @param inputs An array of byte strings containing abi encoded inputs for each command
    function execute(bytes calldata commands, bytes[] calldata inputs) external payable virtual;
}

File 3 of 29 : RouterImmutables.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.17;

import {IAllowanceTransfer} from '../libraries/permit2/IAllowanceTransfer.sol';
import {ERC20} from 'solady/tokens/ERC20.sol';
import {IWETH9} from '../interfaces/external/IWETH9.sol';

struct RouterParameters {
    address permit2;
    address weth9;
}

/// @title Router Immutable Storage contract
/// @notice Used along with the `RouterParameters` struct for ease of cross-chain deployment
contract RouterImmutables {
    /// @dev Permit2 address
    IAllowanceTransfer internal immutable PERMIT2;

    /// @dev WETH9 address
    IWETH9 public immutable WETH9;

    constructor(RouterParameters memory params) payable {
        PERMIT2 = IAllowanceTransfer(params.permit2);
        WETH9 = IWETH9(params.weth9);
    }
}

File 4 of 29 : Commands.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.17;

/// @title Commands
/// @notice Command Flags used to decode commands
library Commands {
    // Masks to extract certain bits of commands
    bytes1 internal constant FLAG_ALLOW_REVERT = 0x80;
    bytes1 internal constant COMMAND_TYPE_MASK = 0x3f;

    // Block 1
    uint256 constant LOCALSWAP              = 0x00;
    uint256 constant SENDASSET              = 0x01;
    uint256 constant PERMIT2_TRANSFER_FROM  = 0x02;
    uint256 constant PERMIT2_PERMIT_BATCH   = 0x03;
    uint256 constant SWEEP                  = 0x04;
    uint256 constant TRANSFER               = 0x05;
    uint256 constant PAY_PORTION            = 0x06;

    // Block 2
    uint256 constant PERMIT2_PERMIT         = 0x07;
    uint256 constant WRAP_GAS               = 0x08;
    uint256 constant UNWRAP_GAS             = 0x09;
    uint256 constant WITHDRAW_EQUAL         = 0x0a;
    uint256 constant WITHDRAW_MIXED         = 0x0b;
    uint256 constant DEPOSIT_MIXED          = 0x0c;
    uint256 constant SENDLIQUIDITY          = 0x0d;
    uint256 constant ALLOW_CANCEL           = 0x0e;
    uint256 constant BALANCE_CHECK_ERC20    = 0x0f;

    // Command Types where 0x10<=value
    uint256 constant EXECUTE_SUB_PLAN       = 0x10;
    uint256 constant PERMIT2_TRANSFER_FROM_BATCH = 0x1e;
    uint256 constant TRANSFER_FROM          = 0x1f;
}

File 5 of 29 : BytesLib.sol
// SPDX-License-Identifier: GPL-3.0-or-later

/// @title Library for Bytes Manipulation
/// Based on Gonçalo Sá's BytesLib - but updated and heavily editted
pragma solidity ^0.8.0;

library BytesLib {
    /// @notice Returns the address starting at byte 0
    /// @dev length and overflow checks must be carried out before calling
    /// @param _bytes The input bytes string to slice
    /// @return tempAddress The address starting at byte 0
    function toAddress(bytes calldata _bytes) internal pure returns (address tempAddress) {
        assembly {
            tempAddress := shr(96, calldataload(_bytes.offset))
        }
    }

    function toBytes(bytes calldata _bytes, uint256 arg) internal pure returns (bytes calldata res) {
        assembly {
            let lengthPtr := add(_bytes.offset, calldataload(add(_bytes.offset, mul(0x20, arg))))
            res.offset := add(lengthPtr, 0x20)
            res.length := calldataload(lengthPtr)
        }
    }

    function toBytesArray(bytes calldata _bytes, uint256 arg) internal pure returns (bytes[] calldata res) {
        assembly {
            let lengthPtr := add(_bytes.offset, calldataload(add(_bytes.offset, mul(0x20, arg))))
            res.offset := add(lengthPtr, 0x20)
            res.length := calldataload(lengthPtr)
        }
    }

    function toAddressArray(bytes calldata _bytes, uint256 arg) internal pure returns (address[] calldata res) {
        assembly {
            let lengthPtr := add(_bytes.offset, calldataload(add(_bytes.offset, mul(0x20, arg))))
            res.offset := add(lengthPtr, 0x20)
            res.length := calldataload(lengthPtr)
        }
    }

    function toUintArray(bytes calldata _bytes, uint256 arg) internal pure returns (uint256[] calldata res) {
        assembly {
            let lengthPtr := add(_bytes.offset, calldataload(add(_bytes.offset, mul(0x20, arg))))
            res.offset := add(lengthPtr, 0x20)
            res.length := calldataload(lengthPtr)
        }
    }
}

File 6 of 29 : ICatalystRouter.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.17;

interface ICatalystRouter {
    /// @notice Thrown when a required command has failed
    error ExecutionFailed(uint256 commandIndex, bytes message);  // 2c4029e9

    /// @notice Thrown when attempting to send ETH directly to the contract
    error ETHNotAccepted();  // 1231ae4

    /// @notice Thrown when executing commands with an expired deadline
    error TransactionDeadlinePassed();  // 5bf6f916

    /// @notice Thrown when attempting to execute commands and an incorrect number of inputs are provided
    error LengthMismatch();  // ff633a38

    /// @notice Executes encoded commands along with provided inputs. Reverts if deadline has expired.
    /// @param commands A set of concatenated commands, each 1 byte in length
    /// @param inputs An array of byte strings containing abi encoded inputs for each command
    /// @param deadline The deadline by which the transaction must be executed
    function execute(bytes calldata commands, bytes[] calldata inputs, uint256 deadline) external payable;
}

File 7 of 29 : IOnCatalyst.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

interface ICatalystReceiver {
    /** 
     * @notice The callback from a catalyst call. To determine if the swap was an asset or liquidity swap, either the current balance should be checked or it should be encoded into data.
     * @dev If you want full finality (not just economical finality)
     * revert on underwritten == true.
     */
    function onCatalystCall(uint256 purchasedTokens, bytes calldata data, bool underwritten) external;
}

File 8 of 29 : IAllowanceTransfer.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

/// @title AllowanceTransfer
/// @notice Handles ERC20 token permissions through signature based allowance setting and ERC20 token transfers by checking allowed amounts
/// @dev Requires user's token approval on the Permit2 contract
interface IAllowanceTransfer {
    /// @notice Thrown when an allowance on a token has expired.
    /// @param deadline The timestamp at which the allowed amount is no longer valid
    error AllowanceExpired(uint256 deadline);

    /// @notice Thrown when an allowance on a token has been depleted.
    /// @param amount The maximum amount allowed
    error InsufficientAllowance(uint256 amount);

    /// @notice Thrown when too many nonces are invalidated.
    error ExcessiveInvalidation();

    /// @notice Emits an event when the owner successfully invalidates an ordered nonce.
    event NonceInvalidation(
        address indexed owner, address indexed token, address indexed spender, uint48 newNonce, uint48 oldNonce
    );

    /// @notice Emits an event when the owner successfully sets permissions on a token for the spender.
    event Approval(
        address indexed owner, address indexed token, address indexed spender, uint160 amount, uint48 expiration
    );

    /// @notice Emits an event when the owner successfully sets permissions using a permit signature on a token for the spender.
    event Permit(
        address indexed owner,
        address indexed token,
        address indexed spender,
        uint160 amount,
        uint48 expiration,
        uint48 nonce
    );

    /// @notice Emits an event when the owner sets the allowance back to 0 with the lockdown function.
    event Lockdown(address indexed owner, address token, address spender);

    /// @notice The permit data for a token
    struct PermitDetails {
        // ERC20 token address
        address token;
        // the maximum amount allowed to spend
        uint160 amount;
        // timestamp at which a spender's token allowances become invalid
        uint48 expiration;
        // an incrementing value indexed per owner,token,and spender for each signature
        uint48 nonce;
    }

    /// @notice The permit message signed for a single token allownce
    struct PermitSingle {
        // the permit data for a single token alownce
        PermitDetails details;
        // address permissioned on the allowed tokens
        address spender;
        // deadline on the permit signature
        uint256 sigDeadline;
    }

    /// @notice The permit message signed for multiple token allowances
    struct PermitBatch {
        // the permit data for multiple token allowances
        PermitDetails[] details;
        // address permissioned on the allowed tokens
        address spender;
        // deadline on the permit signature
        uint256 sigDeadline;
    }

    /// @notice The saved permissions
    /// @dev This info is saved per owner, per token, per spender and all signed over in the permit message
    /// @dev Setting amount to type(uint160).max sets an unlimited approval
    struct PackedAllowance {
        // amount allowed
        uint160 amount;
        // permission expiry
        uint48 expiration;
        // an incrementing value indexed per owner,token,and spender for each signature
        uint48 nonce;
    }

    /// @notice A token spender pair.
    struct TokenSpenderPair {
        // the token the spender is approved
        address token;
        // the spender address
        address spender;
    }

    /// @notice Details for a token transfer.
    struct AllowanceTransferDetails {
        // the owner of the token
        address from;
        // the recipient of the token
        address to;
        // the amount of the token
        uint160 amount;
        // the token to be transferred
        address token;
    }

    /// @notice A mapping from owner address to token address to spender address to PackedAllowance struct, which contains details and conditions of the approval.
    /// @notice The mapping is indexed in the above order see: allowance[ownerAddress][tokenAddress][spenderAddress]
    /// @dev The packed slot holds the allowed amount, expiration at which the allowed amount is no longer valid, and current nonce thats updated on any signature based approvals.
    function allowance(address user, address token, address spender)
        external
        view
        returns (uint160 amount, uint48 expiration, uint48 nonce);

    /// @notice Approves the spender to use up to amount of the specified token up until the expiration
    /// @param token The token to approve
    /// @param spender The spender address to approve
    /// @param amount The approved amount of the token
    /// @param expiration The timestamp at which the approval is no longer valid
    /// @dev The packed allowance also holds a nonce, which will stay unchanged in approve
    /// @dev Setting amount to type(uint160).max sets an unlimited approval
    function approve(address token, address spender, uint160 amount, uint48 expiration) external;

    /// @notice Permit a spender to a given amount of the owners token via the owner's EIP-712 signature
    /// @dev May fail if the owner's nonce was invalidated in-flight by invalidateNonce
    /// @param owner The owner of the tokens being approved
    /// @param permitSingle Data signed over by the owner specifying the terms of approval
    /// @param signature The owner's signature over the permit data
    function permit(address owner, PermitSingle memory permitSingle, bytes calldata signature) external;

    /// @notice Permit a spender to the signed amounts of the owners tokens via the owner's EIP-712 signature
    /// @dev May fail if the owner's nonce was invalidated in-flight by invalidateNonce
    /// @param owner The owner of the tokens being approved
    /// @param permitBatch Data signed over by the owner specifying the terms of approval
    /// @param signature The owner's signature over the permit data
    function permit(address owner, PermitBatch memory permitBatch, bytes calldata signature) external;

    /// @notice Transfer approved tokens from one address to another
    /// @param from The address to transfer from
    /// @param to The address of the recipient
    /// @param amount The amount of the token to transfer
    /// @param token The token address to transfer
    /// @dev Requires the from address to have approved at least the desired amount
    /// of tokens to msg.sender.
    function transferFrom(address from, address to, uint160 amount, address token) external;

    /// @notice Transfer approved tokens in a batch
    /// @param transferDetails Array of owners, recipients, amounts, and tokens for the transfers
    /// @dev Requires the from addresses to have approved at least the desired amount
    /// of tokens to msg.sender.
    function transferFrom(AllowanceTransferDetails[] calldata transferDetails) external;

    /// @notice Enables performing a "lockdown" of the sender's Permit2 identity
    /// by batch revoking approvals
    /// @param approvals Array of approvals to revoke.
    function lockdown(TokenSpenderPair[] calldata approvals) external;

    /// @notice Invalidate nonces for a given (token, spender) pair
    /// @param token The token to invalidate nonces for
    /// @param spender The spender to invalidate nonces for
    /// @param newNonce The new nonce to set. Invalidates all nonces less than it.
    /// @dev Can't invalidate more than 2**16 nonces per transaction.
    function invalidateNonces(address token, address spender, uint48 newNonce) external;
}

File 9 of 29 : ERC20.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Simple ERC20 + EIP-2612 implementation.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/tokens/ERC20.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol)
///
/// @dev Note:
/// - The ERC20 standard allows minting and transferring to and from the zero address,
///   minting and transferring zero tokens, as well as self-approvals.
///   For performance, this implementation WILL NOT revert for such actions.
///   Please add any checks with overrides if desired.
/// - The `permit` function uses the ecrecover precompile (0x1).
///
/// If you are overriding:
/// - NEVER violate the ERC20 invariant:
///   the total sum of all balances must be equal to `totalSupply()`.
/// - Check that the overridden function is actually used in the function you want to
///   change the behavior of. Much of the code has been manually inlined for performance.
abstract contract ERC20 {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The total supply has overflowed.
    error TotalSupplyOverflow();

    /// @dev The allowance has overflowed.
    error AllowanceOverflow();

    /// @dev The allowance has underflowed.
    error AllowanceUnderflow();

    /// @dev Insufficient balance.
    error InsufficientBalance();

    /// @dev Insufficient allowance.
    error InsufficientAllowance();

    /// @dev The permit is invalid.
    error InvalidPermit();

    /// @dev The permit has expired.
    error PermitExpired();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                           EVENTS                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Emitted when `amount` tokens is transferred from `from` to `to`.
    event Transfer(address indexed from, address indexed to, uint256 amount);

    /// @dev Emitted when `amount` tokens is approved by `owner` to be used by `spender`.
    event Approval(address indexed owner, address indexed spender, uint256 amount);

    /// @dev `keccak256(bytes("Transfer(address,address,uint256)"))`.
    uint256 private constant _TRANSFER_EVENT_SIGNATURE =
        0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef;

    /// @dev `keccak256(bytes("Approval(address,address,uint256)"))`.
    uint256 private constant _APPROVAL_EVENT_SIGNATURE =
        0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                          STORAGE                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The storage slot for the total supply.
    uint256 private constant _TOTAL_SUPPLY_SLOT = 0x05345cdf77eb68f44c;

    /// @dev The balance slot of `owner` is given by:
    /// ```
    ///     mstore(0x0c, _BALANCE_SLOT_SEED)
    ///     mstore(0x00, owner)
    ///     let balanceSlot := keccak256(0x0c, 0x20)
    /// ```
    uint256 private constant _BALANCE_SLOT_SEED = 0x87a211a2;

    /// @dev The allowance slot of (`owner`, `spender`) is given by:
    /// ```
    ///     mstore(0x20, spender)
    ///     mstore(0x0c, _ALLOWANCE_SLOT_SEED)
    ///     mstore(0x00, owner)
    ///     let allowanceSlot := keccak256(0x0c, 0x34)
    /// ```
    uint256 private constant _ALLOWANCE_SLOT_SEED = 0x7f5e9f20;

    /// @dev The nonce slot of `owner` is given by:
    /// ```
    ///     mstore(0x0c, _NONCES_SLOT_SEED)
    ///     mstore(0x00, owner)
    ///     let nonceSlot := keccak256(0x0c, 0x20)
    /// ```
    uint256 private constant _NONCES_SLOT_SEED = 0x38377508;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         CONSTANTS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev `(_NONCES_SLOT_SEED << 16) | 0x1901`.
    uint256 private constant _NONCES_SLOT_SEED_WITH_SIGNATURE_PREFIX = 0x383775081901;

    /// @dev `keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")`.
    bytes32 private constant _DOMAIN_TYPEHASH =
        0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f;

    /// @dev `keccak256("1")`.
    bytes32 private constant _VERSION_HASH =
        0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6;

    /// @dev `keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)")`.
    bytes32 private constant _PERMIT_TYPEHASH =
        0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       ERC20 METADATA                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the name of the token.
    function name() public view virtual returns (string memory);

    /// @dev Returns the symbol of the token.
    function symbol() public view virtual returns (string memory);

    /// @dev Returns the decimals places of the token.
    function decimals() public view virtual returns (uint8) {
        return 18;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                           ERC20                            */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the amount of tokens in existence.
    function totalSupply() public view virtual returns (uint256 result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := sload(_TOTAL_SUPPLY_SLOT)
        }
    }

    /// @dev Returns the amount of tokens owned by `owner`.
    function balanceOf(address owner) public view virtual returns (uint256 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x0c, _BALANCE_SLOT_SEED)
            mstore(0x00, owner)
            result := sload(keccak256(0x0c, 0x20))
        }
    }

    /// @dev Returns the amount of tokens that `spender` can spend on behalf of `owner`.
    function allowance(address owner, address spender)
        public
        view
        virtual
        returns (uint256 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x20, spender)
            mstore(0x0c, _ALLOWANCE_SLOT_SEED)
            mstore(0x00, owner)
            result := sload(keccak256(0x0c, 0x34))
        }
    }

    /// @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
    ///
    /// Emits a {Approval} event.
    function approve(address spender, uint256 amount) public virtual returns (bool) {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute the allowance slot and store the amount.
            mstore(0x20, spender)
            mstore(0x0c, _ALLOWANCE_SLOT_SEED)
            mstore(0x00, caller())
            sstore(keccak256(0x0c, 0x34), amount)
            // Emit the {Approval} event.
            mstore(0x00, amount)
            log3(0x00, 0x20, _APPROVAL_EVENT_SIGNATURE, caller(), shr(96, mload(0x2c)))
        }
        return true;
    }

    /// @dev Transfer `amount` tokens from the caller to `to`.
    ///
    /// Requirements:
    /// - `from` must at least have `amount`.
    ///
    /// Emits a {Transfer} event.
    function transfer(address to, uint256 amount) public virtual returns (bool) {
        _beforeTokenTransfer(msg.sender, to, amount);
        /// @solidity memory-safe-assembly
        assembly {
            // Compute the balance slot and load its value.
            mstore(0x0c, _BALANCE_SLOT_SEED)
            mstore(0x00, caller())
            let fromBalanceSlot := keccak256(0x0c, 0x20)
            let fromBalance := sload(fromBalanceSlot)
            // Revert if insufficient balance.
            if gt(amount, fromBalance) {
                mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`.
                revert(0x1c, 0x04)
            }
            // Subtract and store the updated balance.
            sstore(fromBalanceSlot, sub(fromBalance, amount))
            // Compute the balance slot of `to`.
            mstore(0x00, to)
            let toBalanceSlot := keccak256(0x0c, 0x20)
            // Add and store the updated balance of `to`.
            // Will not overflow because the sum of all user balances
            // cannot exceed the maximum uint256 value.
            sstore(toBalanceSlot, add(sload(toBalanceSlot), amount))
            // Emit the {Transfer} event.
            mstore(0x20, amount)
            log3(0x20, 0x20, _TRANSFER_EVENT_SIGNATURE, caller(), shr(96, mload(0x0c)))
        }
        _afterTokenTransfer(msg.sender, to, amount);
        return true;
    }

    /// @dev Transfers `amount` tokens from `from` to `to`.
    ///
    /// Note: Does not update the allowance if it is the maximum uint256 value.
    ///
    /// Requirements:
    /// - `from` must at least have `amount`.
    /// - The caller must have at least `amount` of allowance to transfer the tokens of `from`.
    ///
    /// Emits a {Transfer} event.
    function transferFrom(address from, address to, uint256 amount) public virtual returns (bool) {
        _beforeTokenTransfer(from, to, amount);
        /// @solidity memory-safe-assembly
        assembly {
            let from_ := shl(96, from)
            // Compute the allowance slot and load its value.
            mstore(0x20, caller())
            mstore(0x0c, or(from_, _ALLOWANCE_SLOT_SEED))
            let allowanceSlot := keccak256(0x0c, 0x34)
            let allowance_ := sload(allowanceSlot)
            // If the allowance is not the maximum uint256 value.
            if add(allowance_, 1) {
                // Revert if the amount to be transferred exceeds the allowance.
                if gt(amount, allowance_) {
                    mstore(0x00, 0x13be252b) // `InsufficientAllowance()`.
                    revert(0x1c, 0x04)
                }
                // Subtract and store the updated allowance.
                sstore(allowanceSlot, sub(allowance_, amount))
            }
            // Compute the balance slot and load its value.
            mstore(0x0c, or(from_, _BALANCE_SLOT_SEED))
            let fromBalanceSlot := keccak256(0x0c, 0x20)
            let fromBalance := sload(fromBalanceSlot)
            // Revert if insufficient balance.
            if gt(amount, fromBalance) {
                mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`.
                revert(0x1c, 0x04)
            }
            // Subtract and store the updated balance.
            sstore(fromBalanceSlot, sub(fromBalance, amount))
            // Compute the balance slot of `to`.
            mstore(0x00, to)
            let toBalanceSlot := keccak256(0x0c, 0x20)
            // Add and store the updated balance of `to`.
            // Will not overflow because the sum of all user balances
            // cannot exceed the maximum uint256 value.
            sstore(toBalanceSlot, add(sload(toBalanceSlot), amount))
            // Emit the {Transfer} event.
            mstore(0x20, amount)
            log3(0x20, 0x20, _TRANSFER_EVENT_SIGNATURE, shr(96, from_), shr(96, mload(0x0c)))
        }
        _afterTokenTransfer(from, to, amount);
        return true;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                          EIP-2612                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev For more performance, override to return the constant value
    /// of `keccak256(bytes(name()))` if `name()` will never change.
    function _constantNameHash() internal view virtual returns (bytes32 result) {}

    /// @dev Returns the current nonce for `owner`.
    /// This value is used to compute the signature for EIP-2612 permit.
    function nonces(address owner) public view virtual returns (uint256 result) {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute the nonce slot and load its value.
            mstore(0x0c, _NONCES_SLOT_SEED)
            mstore(0x00, owner)
            result := sload(keccak256(0x0c, 0x20))
        }
    }

    /// @dev Sets `value` as the allowance of `spender` over the tokens of `owner`,
    /// authorized by a signed approval by `owner`.
    ///
    /// Emits a {Approval} event.
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual {
        bytes32 nameHash = _constantNameHash();
        //  We simply calculate it on-the-fly to allow for cases where the `name` may change.
        if (nameHash == bytes32(0)) nameHash = keccak256(bytes(name()));
        /// @solidity memory-safe-assembly
        assembly {
            // Revert if the block timestamp is greater than `deadline`.
            if gt(timestamp(), deadline) {
                mstore(0x00, 0x1a15a3cc) // `PermitExpired()`.
                revert(0x1c, 0x04)
            }
            let m := mload(0x40) // Grab the free memory pointer.
            // Clean the upper 96 bits.
            owner := shr(96, shl(96, owner))
            spender := shr(96, shl(96, spender))
            // Compute the nonce slot and load its value.
            mstore(0x0e, _NONCES_SLOT_SEED_WITH_SIGNATURE_PREFIX)
            mstore(0x00, owner)
            let nonceSlot := keccak256(0x0c, 0x20)
            let nonceValue := sload(nonceSlot)
            // Prepare the domain separator.
            mstore(m, _DOMAIN_TYPEHASH)
            mstore(add(m, 0x20), nameHash)
            mstore(add(m, 0x40), _VERSION_HASH)
            mstore(add(m, 0x60), chainid())
            mstore(add(m, 0x80), address())
            mstore(0x2e, keccak256(m, 0xa0))
            // Prepare the struct hash.
            mstore(m, _PERMIT_TYPEHASH)
            mstore(add(m, 0x20), owner)
            mstore(add(m, 0x40), spender)
            mstore(add(m, 0x60), value)
            mstore(add(m, 0x80), nonceValue)
            mstore(add(m, 0xa0), deadline)
            mstore(0x4e, keccak256(m, 0xc0))
            // Prepare the ecrecover calldata.
            mstore(0x00, keccak256(0x2c, 0x42))
            mstore(0x20, and(0xff, v))
            mstore(0x40, r)
            mstore(0x60, s)
            let t := staticcall(gas(), 1, 0, 0x80, 0x20, 0x20)
            // If the ecrecover fails, the returndatasize will be 0x00,
            // `owner` will be checked if it equals the hash at 0x00,
            // which evaluates to false (i.e. 0), and we will revert.
            // If the ecrecover succeeds, the returndatasize will be 0x20,
            // `owner` will be compared against the returned address at 0x20.
            if iszero(eq(mload(returndatasize()), owner)) {
                mstore(0x00, 0xddafbaef) // `InvalidPermit()`.
                revert(0x1c, 0x04)
            }
            // Increment and store the updated nonce.
            sstore(nonceSlot, add(nonceValue, t)) // `t` is 1 if ecrecover succeeds.
            // Compute the allowance slot and store the value.
            // The `owner` is already at slot 0x20.
            mstore(0x40, or(shl(160, _ALLOWANCE_SLOT_SEED), spender))
            sstore(keccak256(0x2c, 0x34), value)
            // Emit the {Approval} event.
            log3(add(m, 0x60), 0x20, _APPROVAL_EVENT_SIGNATURE, owner, spender)
            mstore(0x40, m) // Restore the free memory pointer.
            mstore(0x60, 0) // Restore the zero pointer.
        }
    }

    /// @dev Returns the EIP-712 domain separator for the EIP-2612 permit.
    function DOMAIN_SEPARATOR() public view virtual returns (bytes32 result) {
        bytes32 nameHash = _constantNameHash();
        //  We simply calculate it on-the-fly to allow for cases where the `name` may change.
        if (nameHash == bytes32(0)) nameHash = keccak256(bytes(name()));
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Grab the free memory pointer.
            mstore(m, _DOMAIN_TYPEHASH)
            mstore(add(m, 0x20), nameHash)
            mstore(add(m, 0x40), _VERSION_HASH)
            mstore(add(m, 0x60), chainid())
            mstore(add(m, 0x80), address())
            result := keccak256(m, 0xa0)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  INTERNAL MINT FUNCTIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Mints `amount` tokens to `to`, increasing the total supply.
    ///
    /// Emits a {Transfer} event.
    function _mint(address to, uint256 amount) internal virtual {
        _beforeTokenTransfer(address(0), to, amount);
        /// @solidity memory-safe-assembly
        assembly {
            let totalSupplyBefore := sload(_TOTAL_SUPPLY_SLOT)
            let totalSupplyAfter := add(totalSupplyBefore, amount)
            // Revert if the total supply overflows.
            if lt(totalSupplyAfter, totalSupplyBefore) {
                mstore(0x00, 0xe5cfe957) // `TotalSupplyOverflow()`.
                revert(0x1c, 0x04)
            }
            // Store the updated total supply.
            sstore(_TOTAL_SUPPLY_SLOT, totalSupplyAfter)
            // Compute the balance slot and load its value.
            mstore(0x0c, _BALANCE_SLOT_SEED)
            mstore(0x00, to)
            let toBalanceSlot := keccak256(0x0c, 0x20)
            // Add and store the updated balance.
            sstore(toBalanceSlot, add(sload(toBalanceSlot), amount))
            // Emit the {Transfer} event.
            mstore(0x20, amount)
            log3(0x20, 0x20, _TRANSFER_EVENT_SIGNATURE, 0, shr(96, mload(0x0c)))
        }
        _afterTokenTransfer(address(0), to, amount);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  INTERNAL BURN FUNCTIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Burns `amount` tokens from `from`, reducing the total supply.
    ///
    /// Emits a {Transfer} event.
    function _burn(address from, uint256 amount) internal virtual {
        _beforeTokenTransfer(from, address(0), amount);
        /// @solidity memory-safe-assembly
        assembly {
            // Compute the balance slot and load its value.
            mstore(0x0c, _BALANCE_SLOT_SEED)
            mstore(0x00, from)
            let fromBalanceSlot := keccak256(0x0c, 0x20)
            let fromBalance := sload(fromBalanceSlot)
            // Revert if insufficient balance.
            if gt(amount, fromBalance) {
                mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`.
                revert(0x1c, 0x04)
            }
            // Subtract and store the updated balance.
            sstore(fromBalanceSlot, sub(fromBalance, amount))
            // Subtract and store the updated total supply.
            sstore(_TOTAL_SUPPLY_SLOT, sub(sload(_TOTAL_SUPPLY_SLOT), amount))
            // Emit the {Transfer} event.
            mstore(0x00, amount)
            log3(0x00, 0x20, _TRANSFER_EVENT_SIGNATURE, shr(96, shl(96, from)), 0)
        }
        _afterTokenTransfer(from, address(0), amount);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                INTERNAL TRANSFER FUNCTIONS                 */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Moves `amount` of tokens from `from` to `to`.
    function _transfer(address from, address to, uint256 amount) internal virtual {
        _beforeTokenTransfer(from, to, amount);
        /// @solidity memory-safe-assembly
        assembly {
            let from_ := shl(96, from)
            // Compute the balance slot and load its value.
            mstore(0x0c, or(from_, _BALANCE_SLOT_SEED))
            let fromBalanceSlot := keccak256(0x0c, 0x20)
            let fromBalance := sload(fromBalanceSlot)
            // Revert if insufficient balance.
            if gt(amount, fromBalance) {
                mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`.
                revert(0x1c, 0x04)
            }
            // Subtract and store the updated balance.
            sstore(fromBalanceSlot, sub(fromBalance, amount))
            // Compute the balance slot of `to`.
            mstore(0x00, to)
            let toBalanceSlot := keccak256(0x0c, 0x20)
            // Add and store the updated balance of `to`.
            // Will not overflow because the sum of all user balances
            // cannot exceed the maximum uint256 value.
            sstore(toBalanceSlot, add(sload(toBalanceSlot), amount))
            // Emit the {Transfer} event.
            mstore(0x20, amount)
            log3(0x20, 0x20, _TRANSFER_EVENT_SIGNATURE, shr(96, from_), shr(96, mload(0x0c)))
        }
        _afterTokenTransfer(from, to, amount);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                INTERNAL ALLOWANCE FUNCTIONS                */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Updates the allowance of `owner` for `spender` based on spent `amount`.
    function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute the allowance slot and load its value.
            mstore(0x20, spender)
            mstore(0x0c, _ALLOWANCE_SLOT_SEED)
            mstore(0x00, owner)
            let allowanceSlot := keccak256(0x0c, 0x34)
            let allowance_ := sload(allowanceSlot)
            // If the allowance is not the maximum uint256 value.
            if add(allowance_, 1) {
                // Revert if the amount to be transferred exceeds the allowance.
                if gt(amount, allowance_) {
                    mstore(0x00, 0x13be252b) // `InsufficientAllowance()`.
                    revert(0x1c, 0x04)
                }
                // Subtract and store the updated allowance.
                sstore(allowanceSlot, sub(allowance_, amount))
            }
        }
    }

    /// @dev Sets `amount` as the allowance of `spender` over the tokens of `owner`.
    ///
    /// Emits a {Approval} event.
    function _approve(address owner, address spender, uint256 amount) internal virtual {
        /// @solidity memory-safe-assembly
        assembly {
            let owner_ := shl(96, owner)
            // Compute the allowance slot and store the amount.
            mstore(0x20, spender)
            mstore(0x0c, or(owner_, _ALLOWANCE_SLOT_SEED))
            sstore(keccak256(0x0c, 0x34), amount)
            // Emit the {Approval} event.
            mstore(0x00, amount)
            log3(0x00, 0x20, _APPROVAL_EVENT_SIGNATURE, shr(96, owner_), shr(96, mload(0x2c)))
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     HOOKS TO OVERRIDE                      */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Hook that is called before any transfer of tokens.
    /// This includes minting and burning.
    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.
    function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}
}

File 10 of 29 : Payments.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.17;

import {Constants} from '../libraries/Constants.sol';
import {RouterImmutables} from '../base/RouterImmutables.sol';
import {SafeTransferLib} from 'solady/utils/SafeTransferLib.sol';
import {ERC20} from 'solady/tokens/ERC20.sol';

/// @title Payments contract
/// @notice Performs various operations around the payment of ETH and tokens
abstract contract Payments is RouterImmutables {
    using SafeTransferLib for address;

    error InsufficientToken();  // 675cae38
    error InsufficientETH();  // 6a12f104
    error InvalidBips();  // deaa01e6

    uint256 internal constant FEE_BIPS_BASE = 10_000;

    /// @notice Pays an amount of ETH or ERC20 to a recipient
    /// @param token The token to pay (can be ETH using Constants.ETH)
    /// @param recipient The address that will receive the payment
    /// @param value The amount to pay
    function pay(address token, address recipient, uint256 value) internal {
        if (token == Constants.ETH) {
            recipient.safeTransferETH(value);
        } else {
            if (value == Constants.CONTRACT_BALANCE) {
                value = ERC20(token).balanceOf(address(this));
            }

            SafeTransferLib.safeTransfer(token, recipient, value);
        }
    }


    /// @notice Pays a proportion of the contract's ETH or ERC20 to a recipient
    /// @param token The token to pay (can be ETH using Constants.ETH)
    /// @param recipient The address that will receive payment
    /// @param bips Portion in bips of whole balance of the contract
    function payPortion(address token, address recipient, uint256 bips) internal {
        if (bips == 0 || bips > 10_000) revert InvalidBips();
        if (token == Constants.ETH) {
            uint256 balance = address(this).balance;
            uint256 amount = (balance * bips) / FEE_BIPS_BASE;
            recipient.safeTransferETH(amount);
        } else {
            uint256 balance = ERC20(token).balanceOf(address(this));
            uint256 amount = (balance * bips) / FEE_BIPS_BASE;
            // pay with tokens already in the contract (for the exact input multihop case)
            SafeTransferLib.safeTransfer(token, recipient, amount);
        }
    }

    /// @notice Sweeps all of the contract's ERC20 or ETH to an address
    /// @param token The token to sweep (can be ETH using Constants.ETH)
    /// @param recipient The address that will receive payment
    /// @param amountMinimum The minimum desired amount
    function sweep(address token, address recipient, uint256 amountMinimum) internal {
        uint256 balance;
        if (token == Constants.ETH) {
            balance = address(this).balance;
            if (balance < amountMinimum) revert InsufficientETH();
            if (balance > 0) recipient.safeTransferETH(balance);
        } else {
            balance = ERC20(token).balanceOf(address(this));
            if (balance < amountMinimum) revert InsufficientToken();
            if (balance > 0) SafeTransferLib.safeTransfer(token, recipient, balance);
        }
    }

    /// @notice Wraps an amount of ETH into WETH
    /// @param recipient The recipient of the WETH
    /// @param amount The amount to wrap (can be CONTRACT_BALANCE)
    function wrapETH(address recipient, uint256 amount) internal {
        if (amount == Constants.CONTRACT_BALANCE) {
            amount = address(this).balance;
        } else if (amount > address(this).balance) {
            revert InsufficientETH();
        }
        if (amount > 0) {
            WETH9.deposit{value: amount}();
            if (recipient != address(this)) {
                WETH9.transfer(recipient, amount);
            }
        }
    }

    /// @notice Unwraps all of the contract's WETH into ETH
    /// @param recipient The recipient of the ETH
    /// @param amountMinimum The minimum amount of ETH desired
    function unwrapWETH9(address recipient, uint256 amountMinimum) internal {
        uint256 value = WETH9.balanceOf(address(this));
        if (value < amountMinimum) {
            revert InsufficientETH();
        }
        if (value > 0) {
            WETH9.withdraw(value);
            if (recipient != address(this)) {
                recipient.safeTransferETH(value);
            }
        }
    }

    function transferFrom(address token, address from, address to, uint160 amount) internal {
        SafeTransferLib.safeTransferFrom(token, from, to, amount);
    }
}

File 11 of 29 : Permit2Payments.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.17;

import {IAllowanceTransfer} from './permit2/IAllowanceTransfer.sol';
import {Payments} from './Payments.sol';
import {Constants} from '../libraries/Constants.sol';
import {RouterImmutables} from '../base/RouterImmutables.sol';

/// @title Payments through Permit2
/// @notice Performs interactions with Permit2 to transfer tokens
abstract contract Permit2Payments is Payments {
    error FromAddressIsNotOwner();  // e7002877
    
    /// @notice Thrown when a valude greater than type(uint160).max is cast to uint160
    error UnsafeCast();  // c4bd89a9

    /// @notice Safely casts uint256 to uint160
    /// @dev https://github.com/Uniswap/permit2/blob/main/src/libraries/SafeCast160.sol
    /// @param value The uint256 to be cast
    function toUint160(uint256 value) internal pure returns (uint160) {
        if (value > type(uint160).max) revert UnsafeCast();
        return uint160(value);
    }

    /// @notice Performs a transferFrom on Permit2
    /// @param token The token to transfer
    /// @param from The address to transfer from
    /// @param to The recipient of the transfer
    /// @param amount The amount to transfer
    function permit2TransferFrom(address token, address from, address to, uint160 amount) internal {
        PERMIT2.transferFrom(from, to, amount, token);
    }

    /// @notice Performs a batch transferFrom on Permit2
    /// @param batchDetails An array detailing each of the transfers that should occur
    function permit2TransferFrom(IAllowanceTransfer.AllowanceTransferDetails[] memory batchDetails, address owner)
        internal
    {
        uint256 batchLength = batchDetails.length;
        for (uint256 i = 0; i < batchLength; ++i) {
            if (batchDetails[i].from != owner) revert FromAddressIsNotOwner();
        }
        PERMIT2.transferFrom(batchDetails);
    }

    /// @notice Either performs a regular payment or transferFrom on Permit2, depending on the payer address
    /// @param token The token to transfer
    /// @param payer The address to pay for the transfer
    /// @param recipient The recipient of the transfer
    /// @param amount The amount to transfer
    function payOrPermit2Transfer(address token, address payer, address recipient, uint256 amount) internal {
        if (payer == address(this)) pay(token, recipient, amount);
        else permit2TransferFrom(token, payer, recipient, toUint160(amount));
    }
}

File 12 of 29 : CatalystExchange.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.17;

import {Constants} from '../libraries/Constants.sol';
import {RouterImmutables} from '../base/RouterImmutables.sol';
import {ERC20} from 'solady/tokens/ERC20.sol';
import {Payments} from './Payments.sol';
import {ICatalystV1Vault} from '../../ICatalystV1Vault.sol';
import {BytesLib} from './BytesLib.sol';
import {ICatalystV1Structs} from '../../interfaces/ICatalystV1VaultState.sol';

/// @title Catalyst Exchange Wrapper
/// @notice Wraps the Catalyst exchange calls
abstract contract CatalystExchange is RouterImmutables, ICatalystV1Structs {
    using BytesLib for bytes;

    /**
     * @notice A swap between 2 assets which both are inside the vault. Is atomic.
     * @param fromAsset The asset the user wants to sell.
     * @param toAsset The asset the user wants to buy
     * @param amount The amount of fromAsset the user wants to sell
     * @param minOut The minimum output of _toAsset the user wants.
     */
    function localSwap(
        address vault,
        address fromAsset,
        address toAsset,
        uint256 amount,
        uint256 minOut
    ) internal {
        amount = amount == Constants.CONTRACT_BALANCE ? ERC20(fromAsset).balanceOf(address(this)) : amount;

        ERC20(fromAsset).approve(vault, amount);

        ICatalystV1Vault(vault).localSwap(
            fromAsset,
            toAsset,
            amount,
            minOut
        );
    }

    function sendAsset(
        address vault,
        RouteDescription memory routeDescription,
        address fromAsset,
        uint8 toAssetIndex,
        uint256 amount,
        uint256 minOut,
        address fallbackUser,
        uint256 gas,
        uint16 underwritingIncentive,
        bytes calldata calldata_
    ) internal {
        amount = amount == Constants.CONTRACT_BALANCE ? ERC20(fromAsset).balanceOf(address(this)) : amount;
        gas = gas == Constants.CONTRACT_BALANCE ? address(this).balance : gas;

        ERC20(fromAsset).approve(vault, amount);

        ICatalystV1Vault(vault).sendAsset{value: gas}(
            routeDescription,
            fromAsset,
            toAssetIndex,
            amount,
            minOut,
            fallbackUser,
            underwritingIncentive,
            calldata_
        );
    }

    function sendLiquidity(
        address vault,
        RouteDescription memory routeDescription,
        uint256 vaultTokens,
        uint256[2] memory minOut,
        address fallbackUser,
        uint256 gas,
        bytes calldata calldata_
    ) internal {
        vaultTokens = vaultTokens == Constants.CONTRACT_BALANCE ? ERC20(vault).balanceOf(address(this)) : vaultTokens;
        gas = gas == Constants.CONTRACT_BALANCE ? address(this).balance : gas;

        ICatalystV1Vault(vault).sendLiquidity{value: gas}(
            routeDescription,
            vaultTokens,
            minOut,
            fallbackUser,
            calldata_
        );
    }

    /**
     * @notice Deposits a user configurable amount of tokens.
     * @dev Requires approvals for all tokens within the vault.
     * Volatile: It is advised that the deposit matches the vault's %token distribution.
     * Amplified: It is advised that the deposit is as close to 1,1,... as possible.
     *            Otherwise between 1,1,... and the vault's %token distribution.
     * @param tokenAmounts An array of the tokens amounts to be deposited.
     * @param minOut The minimum number of vault tokens to be minted.
     */
    function depositMixed(address vault, address[] calldata tokens, uint256[] memory tokenAmounts, uint256 minOut) internal {
        uint256 numberOfTokens = tokenAmounts.length;
        for (uint256 it = 0; it < numberOfTokens; ++it) {
            uint256 tknAmount = tokenAmounts[it];
            if (tknAmount == Constants.CONTRACT_BALANCE) tknAmount = ERC20(tokens[it]).balanceOf(address(this));
            tokenAmounts[it] = tknAmount;

            ERC20(tokens[it]).approve(vault, tknAmount);
        }

        ICatalystV1Vault(vault).depositMixed(tokenAmounts, minOut);
    }

    /**
     * @notice Burns baseAmount and releases the symmetrical share
     * of tokens to the burner. This doesn't change the vault price.
     * @param amount The number of vault tokens to burn.
     */
    function withdrawAll(address vault, uint256 amount, uint256[] calldata minOut) internal {
        amount = amount == Constants.CONTRACT_BALANCE ? ERC20(vault).balanceOf(address(this)) : amount;

        ICatalystV1Vault(vault).withdrawAll(amount, minOut);
    }

    /**
     * @notice Burns vaultTokens and release a token distribution which can be set by the user.
     * @dev Requires approvals for all tokens within the vault.
     * Volatile: It is advised that the deposit matches the vault's %token distribution.
     * Amplified: It is advised that the deposit matches the vault's %token distribution.
     *            Otherwise it should be weighted towards the tokens the vault has more of.
     * @param amount The number of vault tokens to withdraw
     * @param withdrawRatio The percentage of units used to withdraw. In the following special scheme: U_a = U · withdrawRatio[0], U_b = (U - U_a) · withdrawRatio[1], U_c = (U - U_a - U_b) · withdrawRatio[2], .... Is X64
     * @param minOut The minimum number of tokens minted.
     */
    function withdrawMixed(
        address vault,
        uint256 amount,
        uint256[] calldata withdrawRatio,
        uint256[] calldata minOut
    ) internal {
        amount = amount == Constants.CONTRACT_BALANCE ? ERC20(vault).balanceOf(address(this)) : amount;
        
        ICatalystV1Vault(vault).withdrawMixed(amount, withdrawRatio, minOut);
    }
}

File 13 of 29 : CancelSwap.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.17;

/// @title Cancel on-going swaps
/// @notice Allows swappers to cancel their swaps. Given that they already have gas and access to the target chain.
abstract contract CancelSwap {
    error SwapCanceled();  // 599be0bf

    mapping(address => mapping(bytes32 => bool)) public swapIdentifier;

    /// @notice Check if a swap has been cancled
    /// @dev Because swappie is not given to be the swapper, it can be an external contract
    /// which allows people to cancel swaps even from the sending chain. (given high routing incentives)
    /// This contract could then encode cancelIdentifier as a hash of the swapper and another iterator:
    ///     keccak256(abi.encodePacked(swapper, block.timestamp))
    /// @param swappie The address to check for cancelment
    /// @param cancelIdentifier The token to pay (can be ETH using Constants.ETH)
    function requireNotCanceled(address swappie, bytes32 cancelIdentifier) internal view {
        if (swapIdentifier[swappie][cancelIdentifier]) revert SwapCanceled();
    }

    /// @notice If an ognoing swap has cancelIdentifier, calling this function will cancel the swap
    /// @param cancelIdentifier The swap identifier to set.
    function cancelSwap(bytes32 cancelIdentifier) external {
        swapIdentifier[msg.sender][cancelIdentifier] = true;
    }

    /// @notice If an ognoing swap has cancelIdentifier, calling this function will cancel the swap
    /// @param cancelIdentifier The swap identifier to set.
    /// @param state Sets a new state for a specific identifier. Allows one to uncancel a swap.
    function cancelSwap(bytes32 cancelIdentifier, bool state) external {
        swapIdentifier[msg.sender][cancelIdentifier] = state;
    }
}

File 14 of 29 : LockAndMsgSender.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.17;

import {Constants} from '../libraries/Constants.sol';

contract LockAndMsgSender {
    error ContractLocked();  // 6f5ffb7e

    address private constant ADDRESS_ONE = address(1);
    address internal lockedBy = ADDRESS_ONE;

    modifier isNotLocked() {
        if (msg.sender != address(this)) {
            if (lockedBy != ADDRESS_ONE) revert ContractLocked();
            lockedBy = msg.sender;
            _;
            lockedBy = ADDRESS_ONE;
        } else {
            _;
        }
    }

    /// @notice Calculates the recipient address for a command
    /// @param recipient The recipient or recipient-flag for the command
    /// @return output The resultant recipient for the command
    function map(address recipient) internal view returns (address) {
        if (recipient == Constants.MSG_SENDER) {
            return lockedBy;
        } else if (recipient == Constants.ADDRESS_THIS) {
            return address(this);
        } else {
            return recipient;
        }
    }
}

File 15 of 29 : ICatalystV1VaultState.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

import { IMessageEscrowStructs } from "GeneralisedIncentives/src/interfaces/IMessageEscrowStructs.sol";

interface ICatalystV1Structs is IMessageEscrowStructs {
    /**
     * @param chainIdentifier target chain identifier.
     * @param toVault Target vault on the target chain. Encoded in 64 + 1 bytes.
     * @param toAccount Recipient of the transaction on the target chain. Encoded in 64 + 1 bytes.
     * @param incentive Cross-chain relaying incentive description.
     */
    struct RouteDescription {
        bytes32 chainIdentifier;
        bytes toVault;
        bytes toAccount;
        IncentiveDescription incentive;
        uint64 deadline;
    }
}

/**
 * @title Vault state
 * @notice Contains all vault storage which depends on the vault state.
 */
interface ICatalystV1VaultState {
    /** @notice Token weights. Used for maintaining a non symmetric vault asset balance. */
    function _weight(address token) external view returns (uint256);

    function _adjustmentTarget() external view returns (uint48);

    function _lastModificationTime() external view returns (uint48);

    /** @notice The vault fee in WAD. Implementation of fee: mulWadDown(_amount, _vaultFee) */
    function _vaultFee() external view returns (uint64);

    function _governanceFeeShare() external view returns (uint64);

    /** @notice The address of the responsible for adjusting the fees. */
    function _feeAdministrator() external view returns (address);

    /** @notice The setupMaster is the short-term owner of the vault. They can connect the vault to vaults on other chains. */
    function _setupMaster() external view returns (address);

    // Security limit
    /** @notice The max incoming liquidity flow from the router. */
    function _maxUnitCapacity() external view returns (uint256);

    // Escrow reference
    /** @notice Total current escrowed tokens */
    function _escrowedTokens(address token) external view returns (uint256);

    /** @notice Find escrow information. Used for both normal swaps and liquidity swaps. */
    function _escrowLookup(bytes32 sendAssetHash) external view returns (address);

    /** @notice Total current escrowed vault tokens */
    function _escrowedVaultTokens() external view returns (uint256);

    /** @notice Checks if there is a connection to the described vault */
    function _vaultConnection(bytes32 sourceIdentifier, bytes calldata fromVault) external view returns (bool);

    function factoryOwner() external view returns (address);

    function governanceFeeDestination() external view returns (address);

    /**
     * @notice External view function purely used to signal if a vault is safe to use.
     * @dev Just checks if the setup master has been set to ZERO_ADDRESS. In other words, has finishSetup been called?
     */
    function ready() external view returns (bool);
}

File 16 of 29 : IWETH9.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.4;

import {IERC20} from 'openzeppelin-contracts/contracts/token/ERC20/IERC20.sol';

/// @title Interface for WETH9
interface IWETH9 is IERC20 {
    /// @notice Deposit ether to get wrapped ether
    function deposit() external payable;

    /// @notice Withdraw wrapped ether to get ether
    function withdraw(uint256) external;
}

File 17 of 29 : Constants.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.17;

import {IWETH9} from '../interfaces/external/IWETH9.sol';

/// @title Constant state
/// @notice Constant state used by the Universal Router
library Constants {
    /// @dev Used for identifying cases when this contract's balance of a token is to be used as an input
    /// This value is equivalent to 1<<255, i.e. a singular 1 in the most significant bit.
    uint256 internal constant CONTRACT_BALANCE = 0x8000000000000000000000000000000000000000000000000000000000000000;

    /// @dev Used as a flag for identifying the transfer of ETH instead of a token
    address internal constant ETH = address(0);

    /// @dev Used as a flag for identifying that msg.sender should be used, saves gas by sending more 0 bytes
    address internal constant MSG_SENDER = address(1);

    /// @dev Used as a flag for identifying address(this) should be used, saves gas by sending more 0 bytes
    address internal constant ADDRESS_THIS = address(2);
}

File 18 of 29 : SafeTransferLib.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SafeTransferLib.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)
///
/// @dev Note:
/// - For ETH transfers, please use `forceSafeTransferETH` for DoS protection.
/// - For ERC20s, this implementation won't check that a token has code,
///   responsibility is delegated to the caller.
library SafeTransferLib {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The ETH transfer has failed.
    error ETHTransferFailed();

    /// @dev The ERC20 `transferFrom` has failed.
    error TransferFromFailed();

    /// @dev The ERC20 `transfer` has failed.
    error TransferFailed();

    /// @dev The ERC20 `approve` has failed.
    error ApproveFailed();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         CONSTANTS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Suggested gas stipend for contract receiving ETH that disallows any storage writes.
    uint256 internal constant GAS_STIPEND_NO_STORAGE_WRITES = 2300;

    /// @dev Suggested gas stipend for contract receiving ETH to perform a few
    /// storage reads and writes, but low enough to prevent griefing.
    uint256 internal constant GAS_STIPEND_NO_GRIEF = 100000;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       ETH OPERATIONS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    // If the ETH transfer MUST succeed with a reasonable gas budget, use the force variants.
    //
    // The regular variants:
    // - Forwards all remaining gas to the target.
    // - Reverts if the target reverts.
    // - Reverts if the current contract has insufficient balance.
    //
    // The force variants:
    // - Forwards with an optional gas stipend
    //   (defaults to `GAS_STIPEND_NO_GRIEF`, which is sufficient for most cases).
    // - If the target reverts, or if the gas stipend is exhausted,
    //   creates a temporary contract to force send the ETH via `SELFDESTRUCT`.
    //   Future compatible with `SENDALL`: https://eips.ethereum.org/EIPS/eip-4758.
    // - Reverts if the current contract has insufficient balance.
    //
    // The try variants:
    // - Forwards with a mandatory gas stipend.
    // - Instead of reverting, returns whether the transfer succeeded.

    /// @dev Sends `amount` (in wei) ETH to `to`.
    function safeTransferETH(address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(call(gas(), to, amount, codesize(), 0x00, codesize(), 0x00)) {
                mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Sends all the ETH in the current contract to `to`.
    function safeTransferAllETH(address to) internal {
        /// @solidity memory-safe-assembly
        assembly {
            // Transfer all the ETH and check if it succeeded or not.
            if iszero(call(gas(), to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) {
                mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Force sends `amount` (in wei) ETH to `to`, with a `gasStipend`.
    function forceSafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal {
        /// @solidity memory-safe-assembly
        assembly {
            if lt(selfbalance(), amount) {
                mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                revert(0x1c, 0x04)
            }
            if iszero(call(gasStipend, to, amount, codesize(), 0x00, codesize(), 0x00)) {
                mstore(0x00, to) // Store the address in scratch space.
                mstore8(0x0b, 0x73) // Opcode `PUSH20`.
                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
                if iszero(create(amount, 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.
            }
        }
    }

    /// @dev Force sends all the ETH in the current contract to `to`, with a `gasStipend`.
    function forceSafeTransferAllETH(address to, uint256 gasStipend) internal {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(call(gasStipend, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) {
                mstore(0x00, to) // Store the address in scratch space.
                mstore8(0x0b, 0x73) // Opcode `PUSH20`.
                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
                if iszero(create(selfbalance(), 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.
            }
        }
    }

    /// @dev Force sends `amount` (in wei) ETH to `to`, with `GAS_STIPEND_NO_GRIEF`.
    function forceSafeTransferETH(address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            if lt(selfbalance(), amount) {
                mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                revert(0x1c, 0x04)
            }
            if iszero(call(GAS_STIPEND_NO_GRIEF, to, amount, codesize(), 0x00, codesize(), 0x00)) {
                mstore(0x00, to) // Store the address in scratch space.
                mstore8(0x0b, 0x73) // Opcode `PUSH20`.
                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
                if iszero(create(amount, 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.
            }
        }
    }

    /// @dev Force sends all the ETH in the current contract to `to`, with `GAS_STIPEND_NO_GRIEF`.
    function forceSafeTransferAllETH(address to) internal {
        /// @solidity memory-safe-assembly
        assembly {
            // forgefmt: disable-next-item
            if iszero(call(GAS_STIPEND_NO_GRIEF, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) {
                mstore(0x00, to) // Store the address in scratch space.
                mstore8(0x0b, 0x73) // Opcode `PUSH20`.
                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
                if iszero(create(selfbalance(), 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.
            }
        }
    }

    /// @dev Sends `amount` (in wei) ETH to `to`, with a `gasStipend`.
    function trySafeTransferETH(address to, uint256 amount, uint256 gasStipend)
        internal
        returns (bool success)
    {
        /// @solidity memory-safe-assembly
        assembly {
            success := call(gasStipend, to, amount, codesize(), 0x00, codesize(), 0x00)
        }
    }

    /// @dev Sends all the ETH in the current contract to `to`, with a `gasStipend`.
    function trySafeTransferAllETH(address to, uint256 gasStipend)
        internal
        returns (bool success)
    {
        /// @solidity memory-safe-assembly
        assembly {
            success := call(gasStipend, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      ERC20 OPERATIONS                      */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Sends `amount` of ERC20 `token` from `from` to `to`.
    /// Reverts upon failure.
    ///
    /// The `from` account must have at least `amount` approved for
    /// the current contract to manage.
    function safeTransferFrom(address token, address from, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x60, amount) // Store the `amount` argument.
            mstore(0x40, to) // Store the `to` argument.
            mstore(0x2c, shl(96, from)) // Store the `from` argument.
            mstore(0x0c, 0x23b872dd000000000000000000000000) // `transferFrom(address,address,uint256)`.
            // Perform the transfer, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
                    call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)
                )
            ) {
                mstore(0x00, 0x7939f424) // `TransferFromFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x60, 0) // Restore the zero slot to zero.
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Sends all of ERC20 `token` from `from` to `to`.
    /// Reverts upon failure.
    ///
    /// The `from` account must have their entire balance approved for
    /// the current contract to manage.
    function safeTransferAllFrom(address token, address from, address to)
        internal
        returns (uint256 amount)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x40, to) // Store the `to` argument.
            mstore(0x2c, shl(96, from)) // Store the `from` argument.
            mstore(0x0c, 0x70a08231000000000000000000000000) // `balanceOf(address)`.
            // Read the balance, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    gt(returndatasize(), 0x1f), // At least 32 bytes returned.
                    staticcall(gas(), token, 0x1c, 0x24, 0x60, 0x20)
                )
            ) {
                mstore(0x00, 0x7939f424) // `TransferFromFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x00, 0x23b872dd) // `transferFrom(address,address,uint256)`.
            amount := mload(0x60) // The `amount` is already at 0x60. We'll need to return it.
            // Perform the transfer, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
                    call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)
                )
            ) {
                mstore(0x00, 0x7939f424) // `TransferFromFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x60, 0) // Restore the zero slot to zero.
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Sends `amount` of ERC20 `token` from the current contract to `to`.
    /// Reverts upon failure.
    function safeTransfer(address token, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x14, to) // Store the `to` argument.
            mstore(0x34, amount) // Store the `amount` argument.
            mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`.
            // Perform the transfer, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
                    call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
                )
            ) {
                mstore(0x00, 0x90b8ec18) // `TransferFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
        }
    }

    /// @dev Sends all of ERC20 `token` from the current contract to `to`.
    /// Reverts upon failure.
    function safeTransferAll(address token, address to) internal returns (uint256 amount) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, 0x70a08231) // Store the function selector of `balanceOf(address)`.
            mstore(0x20, address()) // Store the address of the current contract.
            // Read the balance, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    gt(returndatasize(), 0x1f), // At least 32 bytes returned.
                    staticcall(gas(), token, 0x1c, 0x24, 0x34, 0x20)
                )
            ) {
                mstore(0x00, 0x90b8ec18) // `TransferFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x14, to) // Store the `to` argument.
            amount := mload(0x34) // The `amount` is already at 0x34. We'll need to return it.
            mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`.
            // Perform the transfer, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
                    call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
                )
            ) {
                mstore(0x00, 0x90b8ec18) // `TransferFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
        }
    }

    /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract.
    /// Reverts upon failure.
    function safeApprove(address token, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x14, to) // Store the `to` argument.
            mstore(0x34, amount) // Store the `amount` argument.
            mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.
            // Perform the approval, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
                    call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
                )
            ) {
                mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
        }
    }

    /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract.
    /// If the initial attempt to approve fails, attempts to reset the approved amount to zero,
    /// then retries the approval again (some tokens, e.g. USDT, requires this).
    /// Reverts upon failure.
    function safeApproveWithRetry(address token, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x14, to) // Store the `to` argument.
            mstore(0x34, amount) // Store the `amount` argument.
            mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.
            // Perform the approval, retrying upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
                    call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
                )
            ) {
                mstore(0x34, 0) // Store 0 for the `amount`.
                mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.
                pop(call(gas(), token, 0, 0x10, 0x44, codesize(), 0x00)) // Reset the approval.
                mstore(0x34, amount) // Store back the original `amount`.
                // Retry the approval, reverting upon failure.
                if iszero(
                    and(
                        or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
                        call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
                    )
                ) {
                    mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`.
                    revert(0x1c, 0x04)
                }
            }
            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
        }
    }

    /// @dev Returns the amount of ERC20 `token` owned by `account`.
    /// Returns zero if the `token` does not exist.
    function balanceOf(address token, address account) internal view returns (uint256 amount) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x14, account) // Store the `account` argument.
            mstore(0x00, 0x70a08231000000000000000000000000) // `balanceOf(address)`.
            amount :=
                mul(
                    mload(0x20),
                    and( // The arguments of `and` are evaluated from right to left.
                        gt(returndatasize(), 0x1f), // At least 32 bytes returned.
                        staticcall(gas(), token, 0x10, 0x24, 0x20, 0x20)
                    )
                )
        }
    }
}

File 19 of 29 : ICatalystV1Vault.sol
//SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.19;

import "./interfaces/ICatalystV1VaultSuccessFailure.sol";
import "./interfaces/ICatalystV1VaultAdministration.sol";
import "./interfaces/ICatalystV1VaultDerived.sol";
import "./interfaces/ICatalystV1VaultErrors.sol";
import "./interfaces/ICatalystV1VaultEvents.sol";
import "./interfaces/ICatalystV1VaultImmutables.sol";
import "./interfaces/ICatalystV1VaultPermissionless.sol";
import "./interfaces/ICatalystV1VaultState.sol";
import "./interfaces/ICatalystV1Underwriting.sol";

interface ICatalystV1Vault is
    ICatalystV1VaultSuccessFailure,
    ICatalystV1VaultAdministration,
    ICatalystV1VaultDerived,
    ICatalystV1VaultEvents,
    ICatalystV1VaultImmutables,
    ICatalystV1VaultPermissionless,
    ICatalystV1VaultState,
    ICatalystV1Structs,
    ICatalystV1Underwriting
{}

File 20 of 29 : IMessageEscrowStructs.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

interface IMessageEscrowStructs {
    struct IncentiveDescription {
        uint48 maxGasDelivery;      // 0: 6/32 bytes
        uint48 maxGasAck;           // 0: 12/32 bytes
        address refundGasTo;        // 0: 32/32 bytes
        uint96 priceOfDeliveryGas;  // 1: 12/32 bytes
        uint96 priceOfAckGas;       // 1: 24/32 bytes
        uint64 targetDelta;         // 1: 32/32 bytes
    }
}

File 21 of 29 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-20 standard as defined in the ERC.
 */
interface IERC20 {
    /**
     * @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);

    /**
     * @dev Returns the value of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the value of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 value) 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 a `value` amount of tokens 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 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the
     * allowance mechanism. `value` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 value) external returns (bool);
}

File 22 of 29 : ICatalystV1VaultSuccessFailure.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

/**
 * @title Escrow related functions defined by Catalyst v1 Vaults
 * @notice Contains the functions used to manage escrows by the cross-chain interface.
 */
interface ICatalystV1VaultSuccessFailure {
    /** @notice Release the escrowed tokens into the vault.  */
    function onSendAssetSuccess(
        bytes32 channelId,
        bytes calldata toAccount,
        uint256 U,
        uint256 escrowAmount,
        address escrowToken,
        uint32 blockNumberMod
    ) external;

    /** @notice Returned the escrowed tokens to the user */
    function onSendAssetFailure(
        bytes32 channelId,
        bytes calldata toAccount,
        uint256 U,
        uint256 escrowAmount,
        address escrowToken,
        uint32 blockNumberMod
    ) external;

    /** @notice Release the escrowed tokens into the vault.  */
    function onSendLiquiditySuccess(
        bytes32 channelId,
        bytes calldata toAccount,
        uint256 U,
        uint256 escrowAmount,
        uint32 blockNumberMod
    ) external;

    /** @notice Returned the escrowed tokens to the user */
    function onSendLiquidityFailure(
        bytes32 channelId,
        bytes calldata toAccount,
        uint256 U,
        uint256 escrowAmount,
        uint32 blockNumberMod
    ) external;
}

File 23 of 29 : ICatalystV1VaultAdministration.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
/**
 * @title Administrative actions defined by Catalyst v1 Vaults
 * @notice Contains all functions which can only be called by privileged users.
 */
interface ICatalystV1VaultAdministration {
    function setFeeAdministrator(address administrator) external;

    function setVaultFee(uint64 fee) external;

    function setGovernanceFee(uint64 fee) external;

    /**
     * @notice Initializes the vault pricing parameters.
     * @param assets The list of assets the vault will support.
     * @param weights The weights of the tokens.
     * @param amp Vault amplification.
     * @param depositor The account to which the initial vault tokens are minted to.
     */
    function initializeSwapCurves(
        address[] calldata assets,
        uint256[] calldata weights,
        uint64 amp,
        address depositor
    ) external;

    /**
     * @notice Creates a connection to the vault toVault on the channel _channelId.
     * @dev if _vaultReceiving is an EVM vault, it can be computes as:
     *     Vyper: convert(_vaultAddress, bytes32)
     *     Solidity: abi.encode(_vaultAddress)
     *     Brownie: brownie.convert.to_bytes(_vaultAddress, type_str="bytes32")
     * setupMaster == ZERO_ADDRESS
     * @param channelId The _channelId of the target vault.
     * @param toVault The bytes32 representation of the target vault
     * @param state Boolean indicating if the connection should be open or closed.
     */
    function setConnection(
        bytes32 channelId,
        bytes calldata toVault,
        bool state
    ) external;

    /**
     * @notice Gives up short term ownership of the vault. This makes the vault unstoppable.
     */
    function finishSetup() external;
}

File 24 of 29 : ICatalystV1VaultDerived.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

/**
 * @title Derived Vault state
 * @notice Contains all vault state which is derived from vault storage
 */
interface ICatalystV1VaultDerived {
    /** @notice  Returns the current cross-chain unit capacity. */
    function getUnitCapacity() external view returns (uint256);

    function calcSendAsset(address from, uint256 amount) external view returns (uint256);

    /**
     * @notice Computes the output of ReceiveAsset, without executing one.
     * @param to The address of the token to buy.
     * @param U The number of units used to buy to.
     * @return uint256 Number of purchased tokens.
     */
    function calcReceiveAsset(address to, uint256 U) external view returns (uint256);

    /**
     * @notice Computes the output of localSwap, without executing one.
     * @param from The address of the token to sell.
     * @param to The address of the token to buy.
     * @param amount The amount of from token to sell for to token.
     * @return Output denominated in to token.
     */
    function calcLocalSwap(address from, address to, uint256 amount) external view returns (uint256);
}

File 25 of 29 : ICatalystV1VaultErrors.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

error EscrowAlreadyExists(); // 0xed778779
error ExceedsSecurityLimit(); // 0x7c1e66d0
error NotEnoughGas(); // 0xdd629f86
error ReturnInsufficient(uint256,uint256); // 0x24557f05
error UnusedUnitsAfterWithdrawal(uint256); // 0x0289311f
error VaultNotConnected(); // 0x2c64c1b2
error WithdrawRatioNotZero(); // 0xb8003bfa

File 26 of 29 : ICatalystV1VaultEvents.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

/**
 * @title Events emitted by Catalyst v1 Vaults
 * @notice Contains all events emitted by the vault
 * @dev When using events to match transations, the combination of: channelId, fromVault, toAccount, toAsset, units, and block number is semi-guranteed to be unique.
 *      If more than 2**32 blocks exist, then all instances are guaranteed to be non-overlapping
 */
interface ICatalystV1VaultEvents {
    /**
     * @notice  Describes an atomic swap between the 2 tokens: _fromAsset and _toAsset.
     * @param account The user / exchange who facilitated the trade (msg.sender)
     * @param fromAsset The asset which was sold in exchange for _toAsset
     * @param toAsset The asset which was purchased with _fromAsset
     * @param fromAmount The number of _fromAsset sold
     * @param toAmount The number of tokens provided to toAccount
     */
    event LocalSwap(
        address indexed account,
        address fromAsset,
        address toAsset,
        uint256 fromAmount,
        uint256 toAmount
    );

    /**
     * @notice Describes the creation of an external swap: Cross-chain swap.
     * @param channelId The target chain identifier
     * @param toVault The target vault.
     * @param toAccount The recipient of the trade. The person who bought the trade is not present.
     * @param fromAsset The asset which was sold in exchange for _toAsset.
     * @param toAssetIndex The token index of the asset to purchase on _toChain.
     * @param fromAmount The number of _fromAsset sold.
     * @param minOut The minimum output to be accepted of fromAsset.
     * @param units The calculated number of units bought. Will be sold to buy _toAsset
     * @param underwriteIncentiveX16 The incentive out of 2**16 - 1 provided to the underwriter.
     * @param fee The number of tokens paid to the vault in fees.
     */
    event SendAsset(
        bytes32 channelId,
        bytes toVault,
        bytes toAccount,
        address fromAsset,
        uint8 toAssetIndex,
        uint256 fromAmount,
        uint256 minOut,
        uint256 units,
        uint256 fee,
        uint16 underwriteIncentiveX16
    );

    /**
     * @notice Describes the arrival of an external swap: Cross-chain swap.
     * If toAccount is used to match trades, remember to convert it into 64 + 1 bytes.
     * @param channelId The target chain identifier
     * @param fromVault The source vault.
     * @param toAccount The recipient of the trade.
     * @param toAsset The asset which was purchased with _fromAsset
     * @param units The number of units sent from the other chain.
     * @param toAmount The number of tokens provided to toAccount
     * @param fromAmount The amount spent to get units on the source side.
     * @param fromAsset The provided asset on the source side.
     * @param sourceBlockNumberMod The block number of the sending transaction mod 2**32 - 1
     */
    event ReceiveAsset(
        bytes32 channelId,
        bytes fromVault,
        address toAccount,
        address toAsset,
        uint256 units,
        uint256 toAmount,
        uint256 fromAmount,
        bytes fromAsset,
        uint32 sourceBlockNumberMod

    );

    /**
     * @notice Describes the creation of a liquidity swap
     * @param channelId The target chain identifier
     * @param toVault The target vault.
     * @param toAccount The recipient of the liquidity. The person who bought the trade is not present.
     * @param fromAmount The number of _fromAsset sold
     * @param minOut An array containing a list of minimum outputs [minVaultTokens, minReferenceAssets]
     * @param units The calculated number of liquidity units bought.
     */
    event SendLiquidity(
        bytes32 channelId,
        bytes toVault,
        bytes toAccount,
        uint256 fromAmount,
        uint256[2] minOut,
        uint256 units
    );

    /**
     * @notice Describes the arrival of a liquidity swap
     * @param channelId The target chain identifier
     * @param fromVault The source vault.
     * @param toAccount The recipient of the liquidity.
     * @param units The number of liquidity units sent from the other chain.
     * @param toAmount The number of vault tokens provided to toAccount
     * @param fromAmount The amount spent to get units on the source side.
     * @param sourceBlockNumberMod The block number of the sending transaction mod 2**32 - 1
     */
    event ReceiveLiquidity(
        bytes32 channelId,
        bytes fromVault,
        address toAccount,
        uint256 units,
        uint256 toAmount,
        uint256 fromAmount,
        uint256 sourceBlockNumberMod
    );

    /**
     * @notice Emitted on liquidity deposits.
     * @param toAccount The depositor. Is credited with _mints vault tokens.
     * @param mint The number of minted vault tokens credited to toAccount
     * @param assets An array of the number of deposited assets.
     */
    event VaultDeposit(address indexed toAccount, uint256 mint, uint256[] assets);

    /**
     * @notice Emitted on liquidity withdrawal.
     * @param toAccount The withdrawer. Is debited _burns vault tokens.
     * @param burn The number of burned vault tokens.
     * @param assets An array of the token amounts returned
     */
    event VaultWithdraw(address indexed toAccount, uint256 burn, uint256[] assets);

    /** @notice Called upon successful asset swap. */
    event SendAssetSuccess(
        bytes32 channelId,
        bytes toAccount,
        uint256 units,
        uint256 escrowAmount,
        address escrowToken,
        uint32 blockNumberMod
    );

    /** @notice Called upon failed asset swap. */
    event SendAssetFailure(
        bytes32 channelId,
        bytes toAccount,
        uint256 units,
        uint256 escrowAmount,
        address escrowToken,
        uint32 blockNumberMod
    );

    /** @notice Called upon successful liquidity swap. */
    event SendLiquiditySuccess(
        bytes32 channelId,
        bytes toAccount,
        uint256 units,
        uint256 escrowAmount,
        uint32 blockNumberMod
    );

    /** @notice Called upon failed liquidity swap. */
    event SendLiquidityFailure(
        bytes32 channelId,
        bytes toAccount,
        uint256 units,
        uint256 escrowAmount,
        uint32 blockNumberMod
    );

    /** @notice Vault setup has been finalised. */
    event FinishSetup();

    /**
     * @notice Emitted on fee administrator adjustment
     * @param administrator The new vault fee administrator
     */
    event SetFeeAdministrator(
        address administrator
    );

    /**
     * @notice Emitted on vault fee adjustment
     * @param fee The new vault fee
     */
    event SetVaultFee(
        uint64 fee
    );

    /**
     * @notice Emitted on governance fee adjustment
     * @param fee The new governance fee
     */
    event SetGovernanceFee(
        uint64 fee
    );

    /**
     * @notice Emitted on weights modification
     * @param targetTime Time at which the weights adjustment must complete.
     * @param targetWeights The desired new weights.
     */
    event SetWeights(
        uint248 targetTime,
        uint256[] targetWeights
    );

    /**
     * @notice Amplification has been modification
     * @param targetTime Time at which the amplification adjustment must complete.
     * @param targetAmplification The desired new amplification.
     */
    event SetAmplification(
        uint48 targetTime,
        uint256 targetAmplification
    );

    /**
     * @notice A connection has been modified
     * @param channelId Target chain identifier.
     * @param toVault Bytes32 representation of the target vault.
     * @param newState Boolean indicating if the connection should be open or closed.
     */
    event SetConnection(
        bytes32 channelId,
        bytes toVault,
        bool newState
    );

    //-- Underwriting Events --//

    /**
     * @notice A swap has been underwritten.
     */
    event SwapUnderwritten(
        bytes32 indexed identifier,
        address toAsset,
        uint256 U,
        uint256 purchasedTokens
    );

}

File 27 of 29 : ICatalystV1VaultImmutables.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

/**
 * @title Immutable vault state
 * @notice Contains all vault state which doesn't change once set.
 */
interface ICatalystV1VaultImmutables {
    function _chainInterface() external view returns (address);

    function FACTORY() external view returns (address);

    function MATHLIB() external view returns (address);

    /** 
     * @notice To indicate which token is desired on the target vault,the _toAsset is an integer
     * from 0 to MAX_ASSETS indicating which asset the vault should purchase with units.
     */
    function _tokenIndexing(uint256 tokenIndex) external view returns (address);
}

File 28 of 29 : ICatalystV1VaultPermissionless.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

import { ICatalystV1Structs } from "./ICatalystV1VaultState.sol";

interface ICatalystV1VaultPermissionless {
    /** 
     * @notice Setup a vault.
     * @param name_ Name of the Vault token.
     * @param symbol_ Symbol for the Vault token.
     * @param chainInterface Cross chain interface used for cross-chain swaps. (Can be address(0) to disable cross-chain swaps.)
     * @param vaultFee Vault fee.
     * @param governanceFee Governance fee share.
     * @param feeAdministrator Account that can modify the fees.
     * @param setupMaster Short-term owner of the vault (until finishSetup is called).
     */
    function setup(
        string calldata name_,
        string calldata symbol_,
        address chainInterface,
        uint64 vaultFee,
        uint64 governanceFee,
        address feeAdministrator,
        address setupMaster
    ) external;

    //--- Balance Changes ---//

    /**
     * @notice Deposits a user configurable amount of tokens.
     * @dev Requires approvals for all deposited tokens within the vault.
     * Volatile: It is advised that the deposit matches the vault's %token distribution.
     * Amplified: It is advised that the deposit is as close to 1,1,... as possible.
     *            Otherwise between 1,1,... and the vault's %token distribution.
     * @param tokenAmounts Array of the tokens amounts to be deposited.
     * @param minOut Minimum number of vault tokens to be minted.
     */
    function depositMixed(uint256[] calldata tokenAmounts, uint256 minOut)
        external returns(uint256);

    /**
     * @notice Burns baseAmount and releases the symmetrical share
     * of tokens to the burner. This doesn't change the vault price.
     * @param baseAmount Number of vault tokens to burn.
     */
    function withdrawAll(uint256 baseAmount, uint256[] calldata minOut)
        external returns(uint256[] memory);

    /**
     * @notice Burns vaultTokens and release a token distribution which can be set by the user.
     * @dev Requires approvals for all tokens within the vault.
     * Volatile: It is advised that the deposit matches the vault's %token distribution.
     * Amplified: It is advised that the deposit matches the vault's %token distribution.
     *            Otherwise it should be weighted towards the tokens the vault has more of.
     * @param vaultTokens Number of vault tokens to withdraw.
     * @param withdrawRatio Percentage of units used to withdraw. In the following special scheme: U_0 = U · withdrawRatio[0], U_1 = (U - U_0) · withdrawRatio[1], U_2 = (U - U_0 - U_1) · withdrawRatio[2], .... Is WAD.
     * @param minOut Minimum number of tokens minted.
     */
    function withdrawMixed(
        uint256 vaultTokens,
        uint256[] calldata withdrawRatio,
        uint256[] calldata minOut
    ) external returns(uint256[] memory);

    //--- Swaps ---//

    /**
     * @notice A swap between 2 assets which both are inside the vault. Is atomic.
     * @param fromAsset Asset the user wants to sell.
     * @param toAsset Asset the user wants to buy.
     * @param amount Amount of fromAsset the user wants to sell.
     * @param minOut Minimum output of _toAsset the user wants.
     */
    function localSwap(
        address fromAsset,
        address toAsset,
        uint256 amount,
        uint256 minOut
    ) external returns (uint256);

    /**
     * @notice Initiate a cross-chain swap by purchasing units and transfer them to another vault.
     * @dev Addresses are encoded in 64 + 1 bytes. To encode for EVM, encode as:
     * Solidity: abi.encodePacket(uint8(20), bytes32(0), abi.encode(<vaultAddress>))
     * @param routeDescription A cross-chain route description which contains the chainIdentifier, toAccount, toVault and relaying incentive.
     * @param fromAsset Asset the user wants to sell.
     * @param toAssetIndex Index of the asset the user wants to buy in the target vault.
     * @param amount Number of fromAsset to sell to the vault.
     * @param minOut Minimum number of returned tokens to the toAccount on the target chain.
     * @param fallbackUser If the transaction fails, send the escrowed funds to this address.
     * @param underwriteIncentiveX16 Payment for underwriting the swap (out of type(uint16.max))
     * @param calldata_ Data field if a call should be made on the target chain.
     * Encoding depends on the target chain, with EVM: abi.encodePacket(bytes20(<address>), <data>). At maximum 65535 bytes can be passed.
     * @return uint256 The number of units minted.
     */
    function sendAsset(
        ICatalystV1Structs.RouteDescription calldata routeDescription,
        address fromAsset,
        uint8 toAssetIndex,
        uint256 amount,
        uint256 minOut,
        address fallbackUser,
        uint16 underwriteIncentiveX16,
        bytes calldata calldata_
    ) external payable returns (uint256);

    /**
     * @notice Initiate a cross-chain swap by purchasing units and transfer them to another vault using a fixed number of units.
     * @dev Addresses are encoded in 64 + 1 bytes. To encode for EVM, encode as:
     * Solidity: abi.encodePacket(uint8(20), bytes32(0), abi.encode(<vaultAddress>))
     * @param routeDescription A cross-chain route description which contains the chainIdentifier, toAccount, toVault and relaying incentive.
     * @param fromAsset Asset the user wants to sell.
     * @param toAssetIndex Index of the asset the user wants to buy in the target vault.
     * @param amount Number of fromAsset to sell to the vault.
     * @param minOut Minimum number of returned tokens to the toAccount on the target chain.
     * @param minU Minimum and exact number of units sent.
     * @param fallbackUser If the transaction fails, send the escrowed funds to this address.
     * @param calldata_ Data field if a call should be made on the target chain.
     * Encoding depends on the target chain, with evm being: abi.encodePacket(bytes20(<address>), <data>)
     * @param underwriteIncentiveX16 Payment for underwriting the swap (out of type(uint16.max))
     * @return uint256 Number of units minted.
     */
    function sendAssetFixedUnit(
        ICatalystV1Structs.RouteDescription calldata routeDescription,
        address fromAsset,
        uint8 toAssetIndex,
        uint256 amount,
        uint256 minOut,
        uint256 minU,
        address fallbackUser,
        uint16 underwriteIncentiveX16,
        bytes calldata calldata_
    ) external payable returns (uint256);

    /**
     * @notice Completes a cross-chain swap by converting units to the desired token (toAsset)
     * @dev Can only be called by the chainInterface.
     * @param channelId The incoming connection identifier.
     * @param fromVault The source vault.
     * @param toAssetIndex Index of the asset to be purchased with Units.
     * @param toAccount The recipient.
     * @param U Number of units to convert into toAsset.
     * @param minOut Minimum number of tokens bought. Reverts if less.
     * @param fromAmount Used to match cross-chain swap events. The input amount on the sending chain.
     * @param fromAsset Used to match cross-chain swap events. The input asset on the sending chain.
     * @param blockNumberMod Used to match cross-chain swap events. The block number from the host side.
     */
    function receiveAsset(
        bytes32 channelId,
        bytes calldata fromVault,
        uint256 toAssetIndex,
        address toAccount,
        uint256 U,
        uint256 minOut,
        uint256 fromAmount,
        bytes calldata fromAsset,
        uint32 blockNumberMod
    ) external returns(uint256 purchasedTokens);

    /**
     * @notice Initiate a cross-chain liquidity swap by withdrawing tokens and converting them to units.
     * @dev While the description says tokens are withdrawn and then converted to units, vault tokens are converted
     * directly into units through the following equation:
     *      U = ln(PT/(PT-pt)) * \sum W_i
     * @param routeDescription A cross-chain route description which contains the chainIdentifier, toAccount, toVault and relaying incentive.
     * @param vaultTokens Number of vault tokens to exchange.
     * @param minOut Array of minout describing: [the minimum number of vault tokens, the minimum number of reference assets].
     * @param fallbackUser If the transaction fails, send the escrowed funds to this address.
     * @param calldata_ Data field if a call should be made on the target chain.
     * Encoding depends on the target chain, with EVM: abi.encodePacket(bytes20(<address>), <data>). At maximum 65535 bytes can be passed.
     * @return uint256 Number of units minted.
     */
    function sendLiquidity(
        ICatalystV1Structs.RouteDescription calldata routeDescription,
        uint256 vaultTokens,
        uint256[2] calldata minOut,
        address fallbackUser,
        bytes calldata calldata_
    ) external payable returns (uint256);

    /**
     * @notice Completes a cross-chain liquidity swap by converting units to tokens and depositing.
     * @dev Called exclusively by the chainInterface.
     * @param fromVault Source vault
     * @param toAccount Recipient of the vault tokens
     * @param U Number of units to convert into vault tokens.
     * @param minVaultTokens Minimum number of vault tokens to mint on target vault. Otherwise: Reject
     * @param minReferenceAsset Minimum number of reference asset the vaults tokens are worth. Otherwise: Reject
     * @param fromAmount Used to match cross-chain swap events. The input amount on the sending chain.
     * @param blockNumberMod Used to match cross-chain swap events. The block number from the host side.
     */
    function receiveLiquidity(
        bytes32 channelId,
        bytes calldata fromVault,
        address toAccount,
        uint256 U,
        uint256 minVaultTokens,
        uint256 minReferenceAsset,
        uint256 fromAmount,
        uint32 blockNumberMod
    ) external returns(uint256 purchasedVaultTokens);
}

File 29 of 29 : ICatalystV1Underwriting.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

/** @title Extensions to vaults which supports underwriting. */
interface ICatalystV1Underwriting {
    function underwriteAsset(
        bytes32 identifier,
        address toAsset,
        uint256 U,
        uint256 minOut
    ) external returns (uint256);

    function releaseUnderwriteAsset(
        address refundTo,
        bytes32 identifier,
        uint256 escrowAmount,
        address escrowToken,
        bytes32 sourceIdentifier,
        bytes calldata fromVault
    ) external;

    function deleteUnderwriteAsset(
        bytes32 identifier,
        uint256 U,
        uint256 escrowAmount,
        address escrowToken
    ) external;
}

Settings
{
  "remappings": [
    "forge-std/=lib/forge-std/src/",
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/",
    "solmate/=lib/solmate/src/",
    "GeneralisedIncentives/=lib/GeneralisedIncentives/",
    "@lazyledger/protobuf3-solidity-lib/=lib/GeneralisedIncentives/lib/vibc-core-smart-contracts/lib/protobuf3-solidity-lib/",
    "@openzeppelin-upgradeable/=lib/GeneralisedIncentives/lib/vibc-core-smart-contracts/lib/openzeppelin-contracts-upgradeable/",
    "@openzeppelin/=lib/GeneralisedIncentives/lib/vibc-core-smart-contracts/lib/openzeppelin-contracts/",
    "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
    "base64/=lib/GeneralisedIncentives/lib/vibc-core-smart-contracts/lib/base64/",
    "clones-with-immutable-args/=lib/GeneralisedIncentives/lib/vibc-core-smart-contracts/lib/optimism/packages/contracts-bedrock/lib/clones-with-immutable-args/src/",
    "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
    "openzeppelin-contracts-upgradeable/=lib/GeneralisedIncentives/lib/vibc-core-smart-contracts/lib/openzeppelin-contracts-upgradeable/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/",
    "openzeppelin/=lib/GeneralisedIncentives/lib/openzeppelin-contracts/contracts/",
    "optimism/=lib/GeneralisedIncentives/lib/vibc-core-smart-contracts/lib/",
    "proto/=lib/GeneralisedIncentives/lib/vibc-core-smart-contracts/lib/proto/",
    "protobuf3-solidity-lib/=lib/GeneralisedIncentives/lib/vibc-core-smart-contracts/lib/protobuf3-solidity-lib/contracts/",
    "safe-contracts/=lib/GeneralisedIncentives/lib/vibc-core-smart-contracts/lib/optimism/packages/contracts-bedrock/lib/safe-contracts/contracts/",
    "solady/=lib/solady/src/",
    "solmate/=lib/GeneralisedIncentives/lib/vibc-core-smart-contracts/lib/optimism/packages/contracts-bedrock/lib/solmate/src/",
    "vibc-core-smart-contracts/=lib/GeneralisedIncentives/lib/vibc-core-smart-contracts/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 10000
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  },
  "evmVersion": "paris",
  "viaIR": true,
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"components":[{"internalType":"address","name":"permit2","type":"address"},{"internalType":"address","name":"weth9","type":"address"}],"internalType":"struct RouterParameters","name":"params","type":"tuple"}],"stateMutability":"payable","type":"constructor"},{"inputs":[],"name":"BalanceTooLow","type":"error"},{"inputs":[],"name":"ContractLocked","type":"error"},{"inputs":[],"name":"ETHNotAccepted","type":"error"},{"inputs":[{"internalType":"uint256","name":"commandIndex","type":"uint256"},{"internalType":"bytes","name":"message","type":"bytes"}],"name":"ExecutionFailed","type":"error"},{"inputs":[],"name":"FromAddressIsNotOwner","type":"error"},{"inputs":[],"name":"InsufficientETH","type":"error"},{"inputs":[],"name":"InsufficientToken","type":"error"},{"inputs":[],"name":"InvalidBips","type":"error"},{"inputs":[{"internalType":"uint256","name":"commandType","type":"uint256"}],"name":"InvalidCommandType","type":"error"},{"inputs":[],"name":"LengthMismatch","type":"error"},{"inputs":[],"name":"SwapCanceled","type":"error"},{"inputs":[],"name":"TransactionDeadlinePassed","type":"error"},{"inputs":[],"name":"UnsafeCast","type":"error"},{"inputs":[{"internalType":"bytes","name":"tt","type":"bytes"}],"name":"debugError","type":"error"},{"inputs":[],"name":"WETH9","outputs":[{"internalType":"contract IWETH9","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"cancelIdentifier","type":"bytes32"}],"name":"cancelSwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"cancelIdentifier","type":"bytes32"},{"internalType":"bool","name":"state","type":"bool"}],"name":"cancelSwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"commands","type":"bytes"},{"internalType":"bytes[]","name":"inputs","type":"bytes[]"}],"name":"execute","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"commands","type":"bytes"},{"internalType":"bytes[]","name":"inputs","type":"bytes[]"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"execute","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bool","name":"","type":"bool"}],"name":"onCatalystCall","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"swapIdentifier","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]

6200302f60c06001600160401b03601f38849003908101601f191683019082821184831017620000e35780849160409687948552833981010312620000f95782519081840190811182821017620000e357835260206200006f816200006485620000fe565b9485855201620000fe565b91019081526001600160a01b03918216608052511660a052600180546001600160a01b0319168117905551612f1b9081620001148239608051818181610c7901528181610e6401528181610f4b015281816114a901526124f0015260a0518181816102ad0152818161163901526117c10152f35b634e487b7160e01b600052604160045260246000fd5b600080fd5b51906001600160a01b0382168203620000f95756fe60406101408152600480361015610020575b5050361561001e57600080fd5b005b600091823560e01c806324856bc3146103b85780633593564c146102d55780634aa4a4fc146102805780635ea79f2614610187578063d47b7d9b14610134578063d541beb3146100e25763e58577521461007a5750610011565b346100de57806003193601126100de57602435918215158093036100da57338452836020528184209035845260205282209060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00835416911617905580f35b8380fd5b8280fd5b5090346100de5760206003193601126100de573383528260205281832090358352602052812060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082541617905580f35b5090346100de57816003193601126100de573573ffffffffffffffffffffffffffffffffffffffff81168091036100de57818360ff92602095528085528181206024358252855220541690519015158152f35b50346100de5760606003193601126100de5760243567ffffffffffffffff81116100da576101b89036908401610461565b50604435801515036100da5760208082013582018035929082019181359091018035910133301461026e576001958654958773ffffffffffffffffffffffffffffffffffffffff881603610248575050918594939161023f937fffffffffffffffffffffffff00000000000000000000000000000000000000009586339116178755610526565b81541617905580f35b517f6f5ffb7e000000000000000000000000000000000000000000000000000000008152fd5b909192935061027d9450610526565b80f35b8382346102d157816003193601126102d1576020905173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b5080fd5b5060606003193601126100de5767ffffffffffffffff82358181116103b4576103019036908501610461565b916024359081116103b0576103199036908601610494565b92909160443542116103885733301461026e576001958654958773ffffffffffffffffffffffffffffffffffffffff881603610248575050918594939161023f937fffffffffffffffffffffffff00000000000000000000000000000000000000009586339116178755610526565b8585517f5bf6f916000000000000000000000000000000000000000000000000000000008152fd5b8580fd5b8480fd5b50806003193601126100de5767ffffffffffffffff82358181116103b4576103e39036908501610461565b916024359081116103b0576103fb9036908601610494565b92909133301461026e576001958654958773ffffffffffffffffffffffffffffffffffffffff881603610248575050918594939161023f937fffffffffffffffffffffffff00000000000000000000000000000000000000009586339116178755610526565b9181601f8401121561048f5782359167ffffffffffffffff831161048f576020838186019501011161048f57565b600080fd5b9181601f8401121561048f5782359167ffffffffffffffff831161048f576020808501948460051b01011161048f57565b359073ffffffffffffffffffffffffffffffffffffffff8216820361048f57565b919082519283825260005b848110610512575050601f19601f8460006020809697860101520116010190565b6020818301810151848301820152016104f1565b60e052610100526101205260c0526101005160c051036129ae57600060a0525b6101005160a0511061055457565b60c05160a051101561297f5760a05160051b6101205101357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe16101205136030181121561048f5767ffffffffffffffff816101205101351161048f57610120518101602081019190353603821361048f57606060805260a05160e05160019391013560f81c603f1660108110801561243657600782101561146b5750806108ce57506101205182016040818101359390923591608001357f800000000000000000000000000000000000000000000000000000000000000081036108c8575082517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260208160248173ffffffffffffffffffffffffffffffffffffffff89165afa9081156108bd57600091610888575b50935b73ffffffffffffffffffffffffffffffffffffffff809116928451927f095ea7b3000000000000000000000000000000000000000000000000000000008452600493602081806107058b878a84016020909392919373ffffffffffffffffffffffffffffffffffffffff60408201951681520152565b038160008a5af1801561087d579260a0600093608496936020999896610850575b5089519a8b9889977f505b0c1200000000000000000000000000000000000000000000000000000000895288015284606083610120510101351660248801526044870152610120510101356064850152165af1908115610846575061081b575b505b15806107ea575b6107a157600160a0510160a052610546565b60408051907f2c4029e900000000000000000000000000000000000000000000000000000000825260a05160048301526024820152806107e6604482016080516104e6565b0390fd5b507f800000000000000000000000000000000000000000000000000000000000000060a05160e0510135161561078f565b602090813d831161083f575b6108318183612a08565b8101031261048f5738610786565b503d610827565b513d6000823e3d90fd5b61086f908a3d8c11610876575b6108678183612a08565b810190612d6d565b5038610726565b503d61085d565b87513d6000823e3d90fd5b906020823d6020116108b5575b816108a260209383612a08565b810103126108b25750513861068c565b80fd5b3d9150610895565b84513d6000823e3d90fd5b9361068f565b60018103610c3c5750610120805190929081018035810192908303841361048f576108f8906104c5565b9060409283826101205101013567ffffffffffffffff811161048f5760208061092a9301918461012051010101612ae7565b9061093c6060826101205101016104c5565b92608082610120510101359560ff871680970361048f5761012051830160a0810135939061096c9060e0016104c5565b91610100938483610120510101359183610120510101359061ffff821680920361048f5773ffffffffffffffffffffffffffffffffffffffff80809216991692846101205101356103601161048f576109c7828b9716612c30565b907f800000000000000000000000000000000000000000000000000000000000000098898114600014610c365750909192939495508a517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152602081602481895afa908115610c2b57908b97969594939291600091610bea575b50985b8103610be4575047975b8b517f095ea7b300000000000000000000000000000000000000000000000000000000815260208180610ab08560049c8d84016020909392919373ffffffffffffffffffffffffffffffffffffffff60408201951681520152565b038160008a5af18015610bd957610bba575b508b519c8d9a8b998a997fde6bbd9d000000000000000000000000000000000000000000000000000000008b528a01526101048901610b0091612c80565b9560248901526044880152606487015284610120510160c0013560848701521660a485015260c48401528281036003190160e4840152816101205101357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffca0019161012051016103800191610b7392612c0f565b03915a94602095f19081156108465750610b8f575b505b610788565b602090813d8311610bb3575b610ba58183612a08565b8101031261048f5738610b88565b503d610b9b565b610bd29060203d602011610876576108678183612a08565b5038610ac2565b8d513d6000823e3d90fd5b97610a55565b91929394959697506020823d602011610c23575b81610c0b60209383612a08565b810103126108b25750908a9695949392915138610a48565b3d9150610bfe565b8c513d6000823e3d90fd5b98610a4b565b60028103610d19575060409073ffffffffffffffffffffffffffffffffffffffff92836001541690610c75848261012051010135612c30565b91857f00000000000000000000000000000000000000000000000000000000000000001693843b1561048f576000948786928160606084978b519c8d9a8b997f36c78516000000000000000000000000000000000000000000000000000000008b5260048b015216602489015261012051010135166044860152351660648401525af19081156108465750610d0a5750610788565b610d13906129f4565b38610b88565b6003810361109757506101205182018035810191602083019160409084031261048f573567ffffffffffffffff811161048f57836101205101019060608284031261048f57604051926060840184811067ffffffffffffffff82111761106857604052602083013567ffffffffffffffff811161048f57830182603f8201121561048f57602081013590610dac82612a8e565b92610dba6040519485612a08565b8284526040602085019360071b8301019185831161048f57604001925b82841061100357505050508352610df0604083016104c5565b93602084019485526060604085019301358352604081610120510101359067ffffffffffffffff821161048f5761012051010191610e32602084019283612a47565b5073ffffffffffffffffffffffffffffffffffffffff600154169473ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163b1561048f5794929391906040519586947f2a2d80d100000000000000000000000000000000000000000000000000000000865260048601526060602486015260c48501935193606060648701528451809152602060e487019501906000905b808210610f8957505050946040610f319386959373ffffffffffffffffffffffffffffffffffffffff600099511660848801525160a4870152600319868503016044870152359101612c0f565b03818373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165af18015610f7d57610d0a5750610788565b6040513d6000823e3d90fd5b9197965091929394602060806001928a5173ffffffffffffffffffffffffffffffffffffffff815116825273ffffffffffffffffffffffffffffffffffffffff848201511684830152606060408201519165ffffffffffff8093166040850152015116606082015201980192018896979594939291610ee4565b60806020858403011261048f576020608091604051611021816129d8565b61102a876104c5565b81526110378388016104c5565b8382015261104760408801612aa6565b604082015261105860608801612aa6565b6060820152815201930192610dd7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6004919082810361120e575090606091356040906110bc828661012051010135612c30565b9473ffffffffffffffffffffffffffffffffffffffff948591610120510101351693811680156000146111385750504792831061111257505080611102575b5050610788565b61110b91612e7e565b38806110fb565b517f6a12f104000000000000000000000000000000000000000000000000000000008152fd5b936020602495849397959451968780927f70a0823100000000000000000000000000000000000000000000000000000000825230888301525afa948515611203576000956111cf575b5084106111a957505081611198575b505050610788565b6111a192612e9c565b388080611190565b517f675cae38000000000000000000000000000000000000000000000000000000008152fd5b90946020823d6020116111fb575b816111ea60209383612a08565b810103126108b25750519338611181565b3d91506111dd565b82513d6000823e3d90fd5b929493926005810361132857506101205160409501606081013591359061123790870135612c30565b919273ffffffffffffffffffffffffffffffffffffffff82169084826112675750505050610b8a92939450612e7e565b7f80000000000000000000000000000000000000000000000000000000000000001461129c575b5050610b8a93949550612e9c565b60209192945060248851809481937f70a0823100000000000000000000000000000000000000000000000000000000835230908301525afa95861561084657506000956112f4575b50929384939091610b8a3861128e565b6020813d602011611320575b8161130d60209383612a08565b810103126103b057519450610b8a6112e4565b3d9150611300565b9394929360061461133b57505050610788565b3591604061135a81606084610120510101359361012051010135612c30565b9282158015611460575b6114395773ffffffffffffffffffffffffffffffffffffffff851690816113a1575050506111a1925061139a6127109147612e3c565b0490612e7e565b60209060248451809481937f70a0823100000000000000000000000000000000000000000000000000000000835230908301525afa9182156108465750600091611405575b506113f961140094939261271092612e3c565b0491612e9c565b6111a1565b906020823d602011611431575b8161141f60209383612a08565b810103126108b25750516113f96113e6565b3d9150611412565b90517fdeaa01e6000000000000000000000000000000000000000000000000000000008152fd5b506127108311611364565b600d9081831015611f5a575050600781036115c757506101205160015473ffffffffffffffffffffffffffffffffffffffff936040939185169290917f0000000000000000000000000000000000000000000000000000000000000000861691830160e081013501823b1561048f576000946115b1869260c061151f978b8b519c8d9a8b998a987f2b67b570000000000000000000000000000000000000000000000000000000008a5260048a01526104c5565b166024870152806115368d846101205101016104c5565b16604487015261154d606083610120510101612aa6565b65ffffffffffff809116606488015261156d608084610120510101612aa6565b16608487015261158460a0836101205101016104c5565b1660a48601526101205101013560c484015261010060e48401526101048301908960208201359101612c0f565b03925af19081156108465750610d0a5750610788565b600881036117915750906115e660408092610120510101359235612c30565b91807f80000000000000000000000000000000000000000000000000000000000000008103611761575050475b8061162057505050610788565b73ffffffffffffffffffffffffffffffffffffffff90817f000000000000000000000000000000000000000000000000000000000000000016803b1561048f578351927fd0e30db0000000000000000000000000000000000000000000000000000000008452600493600081868187875af1801561175657611747575b5030908616036116af575b5050611190565b61170e9460006020948651978895869485937fa9059cbb00000000000000000000000000000000000000000000000000000000855284016020909392919373ffffffffffffffffffffffffffffffffffffffff60408201951681520152565b03925af19081156108465750611728575b808080806116a8565b6117409060203d602011610876576108678183612a08565b503861171f565b611750906129f4565b3861169d565b86513d6000823e3d90fd5b47101561161357600482517f6a12f104000000000000000000000000000000000000000000000000000000008152fd5b600981036119225750906117a760409235612c30565b9173ffffffffffffffffffffffffffffffffffffffff90817f000000000000000000000000000000000000000000000000000000000000000016908051937f70a08231000000000000000000000000000000000000000000000000000000008552600430818701526024916020878481885afa9687156108bd576000976118ee575b50610120510183013586106118c7578561184a575b50505050505050610788565b833b1561048f57600091869183855196879485937f2e1a7d4d0000000000000000000000000000000000000000000000000000000085528401525af190811561084657506118b8575b5030908316036118a8575b808080808061183e565b6118b191612e7e565b388061189e565b6118c1906129f4565b38611893565b82517f6a12f104000000000000000000000000000000000000000000000000000000008152fd5b90966020823d60201161191a575b8161190960209383612a08565b810103126108b25750519583611829565b3d91506118fc565b600a8103611aa557506101205160409201606081013581019135908301357f80000000000000000000000000000000000000000000000000000000000000008101611a97575082517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260208160248173ffffffffffffffffffffffffffffffffffffffff86165afa9081156108bd57600091611a64575b5091600091611a2a94935b8373ffffffffffffffffffffffffffffffffffffffff86518098819682957f5c459a5b000000000000000000000000000000000000000000000000000000008452600484015289602484015260448301908a60208201359101612dff565b0393165af19081156108465750611a415750610788565b611a5d903d806000833e611a558183612a08565b810190612d85565b5038610b88565b906020823d602011611a8f575b81611a7e60209383612a08565b810103126108b257505160006119c1565b3d9150611a71565b91600091611a2a94936119cc565b600b8103611c2c5750610120516080920191820135820191604091359060608101358101908301357f80000000000000000000000000000000000000000000000000000000000000008103611c09575082517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260208160248173ffffffffffffffffffffffffffffffffffffffff87165afa9081156108bd57600091611bd5575b5091611bbb91600073ffffffffffffffffffffffffffffffffffffffff81955b611a2a8851998a97889687947f3b49580d00000000000000000000000000000000000000000000000000000000865260048601526060602486015260648501908c60208201359101612dff565b906003198483030160448501528a60208201359101612dff565b906020823d602011611c01575b81611bef60209383612a08565b810103126108b2575051611bbb611b4e565b3d9150611be2565b91611bbb91600073ffffffffffffffffffffffffffffffffffffffff8195611b6e565b600c14611c3a575050610788565b6101205182016060810135810192604092359160208086013592918581013501808601910135611c6984612a8e565b96611c7687519889612a08565b8488526020880187819660051b8301019136831161048f57949895948801905b828210611f4a5750505083519160005b838110611d87575050505083519485927fe75552fb0000000000000000000000000000000000000000000000000000000084526044840190866004860152518091526064840192906000905b808210611d6b57505050600073ffffffffffffffffffffffffffffffffffffffff8460209694608082956101205101013560248301520393165af19081156108465750611d40575b806110fb565b602090813d8311611d64575b611d568183612a08565b8101031261048f5738611d3a565b503d611d4c565b8251855288955060209485019490920191600190910190611cf2565b8086611d9682829c9899612c6c565b517f80000000000000000000000000000000000000000000000000000000000000008114611e9c575b80611dcf611e5394602094612c6c565b5273ffffffffffffffffffffffffffffffffffffffff611df8611df3868989612d3c565b612d4c565b168a60008d518096819582947f095ea7b3000000000000000000000000000000000000000000000000000000008452600484016020909392919373ffffffffffffffffffffffffffffffffffffffff60408201951681520152565b03925af18015611e91579060019291611e72575b500197949397611ca6565b611e8a9060203d602011610876576108678183612a08565b5038611e67565b89513d6000823e3d90fd5b5050602073ffffffffffffffffffffffffffffffffffffffff611ec5611df36024948888612d3c565b168a51928380927f70a082310000000000000000000000000000000000000000000000000000000082523060048301525afa908115611e915782918b91600091611f10575b50611dbf565b925090506020823d602011611f42575b81611f2d60209383612a08565b810103126108b257505181908a906020611f0a565b3d9150611f20565b8135815260209182019101611c96565b611f68575b50505050610788565b8103612265575061012051820180358101919060e09083031261048f57611f8e906104c5565b906040836101205101013567ffffffffffffffff811161048f57611fbf906020808401918661012051010101612ae7565b9260208201609f82610120510101121561048f57604051916040830183811067ffffffffffffffff8211176110685760405282602060c0846101205101019201821161048f57608083610120510101905b828210612255575050612022906104c5565b90806101205101356103201161048f577f800000000000000000000000000000000000000000000000000000000000000091826060836101205101013514600014612245576040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260208160248173ffffffffffffffffffffffffffffffffffffffff8a165afa908115610f7d57600091612213575b50925b61012051830160e00135036121fc574792919061211796945b6040519788967f36ae087e00000000000000000000000000000000000000000000000000000000885260c0600489015260c4880190612c80565b93602487015260448601906000915b600283106121e3575050508461219d8194602098969473ffffffffffffffffffffffffffffffffffffffff80951660848501526003198483030160a48501526103407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffce0826101205101350191610120510101612c0f565b0393165af18015610f7d576121b8575b505b38808080611f5f565b602090813d83116121dc575b6121ce8183612a08565b8101031261048f57386121ad565b503d6121c4565b8151815289975060019092019160209182019101612126565b60e0826101205101013592919061211796946120dd565b906020823d60201161223d575b8161222d60209383612a08565b810103126108b2575051386120c1565b3d9150612220565b60608261012051010135926120c4565b8135815260209182019101612010565b600e81036122df57509073ffffffffffffffffffffffffffffffffffffffff604092351660005260006020528180600020916101205101013560005260205260ff8160002054166122b657506121af565b600490517f599be0bf000000000000000000000000000000000000000000000000000000008152fd5b600f146122ee575b50506121af565b602091925060409273ffffffffffffffffffffffffffffffffffffffff908451938480937f70a08231000000000000000000000000000000000000000000000000000000008252806004963516868301526024968791898661012051010135165afa91821561242b576000926123f6575b506101205101606001351180159390612379575b506122e7565b8051927fa32816720000000000000000000000000000000000000000000000000000000060208501528284528184019284841067ffffffffffffffff8511176123ca57505052608052388080612373565b6041907f4e487b7100000000000000000000000000000000000000000000000000000000600052526000fd5b90916020823d602011612423575b8161241160209383612a08565b810103126108b257505190606061235f565b3d9150612404565b85513d6000823e3d90fd5b50601e810361266d57506101205182018035810192602080850193919285031261048f57359067ffffffffffffffff821161048f5761012051010181603f8201121561048f5760208101359060409261248e83612a8e565b9461249b85519687612a08565b838652602086019285849560071b82010192831161048f578501925b82841061260b575050505073ffffffffffffffffffffffffffffffffffffffff90816001541684519060005b8281106125c657505050817f00000000000000000000000000000000000000000000000000000000000000001691823b1561048f5783517f0d58b1db000000000000000000000000000000000000000000000000000000008152602060048201529451602486018190528592604484019290916000915b81831061258257505050509181600081819503925af19081156108465750610d0a5750610788565b91938395506080602091846060600195975182815116845282868201511686850152828d820151168d8501520151166060820152019501930190918794939261255a565b81856125d2838a612c6c565b515116036125e2576001016124e3565b600486517fe7002877000000000000000000000000000000000000000000000000000000008152fd5b60806020858403011261048f5760206080918751612628816129d8565b612631876104c5565b815261263e8388016104c5565b8382015261264d8988016104c5565b8982015261265d606088016104c5565b60608201528152019301926124b7565b601f81036127275750600060208160646040947fffffffffffffffffffffffffffffffffffffffff0000000000000000000000006001546126b5888a61012051010135612c30565b73ffffffffffffffffffffffffffffffffffffffff60608a519b6101205101013516606052885260601b16602c526f23b872dd000000000000000000000000600c52601c948591355af13d1560016000511417161561271a5750600060605252610788565b600490637939f424600052fd5b6010810361294e575061012051820180358101602081019291604091031261048f573567ffffffffffffffff811161048f5781602061276d928561012051010101612a47565b92604083610120510101359267ffffffffffffffff841161048f5782603f858361012051010101121561048f576020848261012051010101356127af81612a8e565b936127bd6040519586612a08565b8185526020850180968260408560051b838861012051010101011161048f576040818661012051010101915b60408560051b83886101205101010101831061291857505050505050612843604051947f24856bc30000000000000000000000000000000000000000000000000000000060208701526040602487015260648601906104e6565b917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc8584030160448601525190818352602083019160208160051b850101949360005b8281106128ed57505050505050816128aa600093849303601f198101835282612a08565b60208151910182305af13d156128e5573d6128c481612a2b565b906128d26040519283612a08565b81523d6000602083013e5b608052610788565b6080516128dd565b90919260208061290a89601f1987869a9b9c03018a528a516104e6565b980196019493929101612886565b823567ffffffffffffffff811161048f576020916129438660408594878c6101205101010101612a47565b8152019201916127e9565b602490604051907fd76a1e9e0000000000000000000000000000000000000000000000000000000082526004820152fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60046040517fff633a38000000000000000000000000000000000000000000000000000000008152fd5b6080810190811067ffffffffffffffff82111761106857604052565b67ffffffffffffffff811161106857604052565b90601f601f19910116810190811067ffffffffffffffff82111761106857604052565b67ffffffffffffffff811161106857601f01601f191660200190565b81601f8201121561048f57803590612a5e82612a2b565b92612a6c6040519485612a08565b8284526020838301011161048f57816000926020809301838601378301015290565b67ffffffffffffffff81116110685760051b60200190565b359065ffffffffffff8216820361048f57565b35906bffffffffffffffffffffffff8216820361048f57565b359067ffffffffffffffff8216820361048f57565b91909180830390610140821261048f57604080519267ffffffffffffffff9060a0850182811186821017611068578352849684358652602085013583811161048f5781612b35918701612a47565b6020870152838501359183831161048f57612b757fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa09260c0948801612a47565b85880152011261048f5781519260c0840191821184831017611068576080938361012093612c0a9552612baa60608401612aa6565b8252612bb7868401612aa6565b6020830152612bc860a084016104c5565b90820152612bd860c08301612ab9565b6060820152612be960e08301612ab9565b85820152612bfa6101008301612ad2565b60a0820152606086015201612ad2565b910152565b601f8260209493601f19938186528686013760008582860101520116010190565b73ffffffffffffffffffffffffffffffffffffffff9080821660018103612c5a5750506001541690565b909150600203612c6957503090565b90565b805182101561297f5760209160051b010190565b90610120612cb7612ca5610140855185526020860151908060208701528501906104e6565b604085015184820360408601526104e6565b92608060a0606083015165ffffffffffff8082511660608801526020820151168387015273ffffffffffffffffffffffffffffffffffffffff6040820151168287015260608101516bffffffffffffffffffffffff80911660c0880152838201511660e087015201519167ffffffffffffffff80931661010086015201511691015290565b919081101561297f5760051b0190565b3573ffffffffffffffffffffffffffffffffffffffff8116810361048f5790565b9081602091031261048f5751801515810361048f5790565b602090818184031261048f5780519067ffffffffffffffff821161048f57019180601f8401121561048f578251612dbb81612a8e565b93612dc96040519586612a08565b818552838086019260051b82010192831161048f578301905b828210612df0575050505090565b81518152908301908301612de2565b90918281527f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831161048f5760209260051b809284830137010190565b81810292918115918404141715612e4f57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600080809338935af115612e8e57565b63b12d13eb6000526004601cfd5b60109260209260145260345260446000938480936fa9059cbb00000000000000000000000082525af13d156001835114171615612ed857603452565b6390b8ec1890526004601cfdfea2646970667358221220131bf048f3ec4b09c2413c5008eb92f93b7d457c2ca59f56ccdd2bb2ee4ddeac64736f6c63430008160033000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba30000000000000000000000004300000000000000000000000000000000000004

Deployed Bytecode

0x60406101408152600480361015610020575b5050361561001e57600080fd5b005b600091823560e01c806324856bc3146103b85780633593564c146102d55780634aa4a4fc146102805780635ea79f2614610187578063d47b7d9b14610134578063d541beb3146100e25763e58577521461007a5750610011565b346100de57806003193601126100de57602435918215158093036100da57338452836020528184209035845260205282209060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00835416911617905580f35b8380fd5b8280fd5b5090346100de5760206003193601126100de573383528260205281832090358352602052812060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082541617905580f35b5090346100de57816003193601126100de573573ffffffffffffffffffffffffffffffffffffffff81168091036100de57818360ff92602095528085528181206024358252855220541690519015158152f35b50346100de5760606003193601126100de5760243567ffffffffffffffff81116100da576101b89036908401610461565b50604435801515036100da5760208082013582018035929082019181359091018035910133301461026e576001958654958773ffffffffffffffffffffffffffffffffffffffff881603610248575050918594939161023f937fffffffffffffffffffffffff00000000000000000000000000000000000000009586339116178755610526565b81541617905580f35b517f6f5ffb7e000000000000000000000000000000000000000000000000000000008152fd5b909192935061027d9450610526565b80f35b8382346102d157816003193601126102d1576020905173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000004300000000000000000000000000000000000004168152f35b5080fd5b5060606003193601126100de5767ffffffffffffffff82358181116103b4576103019036908501610461565b916024359081116103b0576103199036908601610494565b92909160443542116103885733301461026e576001958654958773ffffffffffffffffffffffffffffffffffffffff881603610248575050918594939161023f937fffffffffffffffffffffffff00000000000000000000000000000000000000009586339116178755610526565b8585517f5bf6f916000000000000000000000000000000000000000000000000000000008152fd5b8580fd5b8480fd5b50806003193601126100de5767ffffffffffffffff82358181116103b4576103e39036908501610461565b916024359081116103b0576103fb9036908601610494565b92909133301461026e576001958654958773ffffffffffffffffffffffffffffffffffffffff881603610248575050918594939161023f937fffffffffffffffffffffffff00000000000000000000000000000000000000009586339116178755610526565b9181601f8401121561048f5782359167ffffffffffffffff831161048f576020838186019501011161048f57565b600080fd5b9181601f8401121561048f5782359167ffffffffffffffff831161048f576020808501948460051b01011161048f57565b359073ffffffffffffffffffffffffffffffffffffffff8216820361048f57565b919082519283825260005b848110610512575050601f19601f8460006020809697860101520116010190565b6020818301810151848301820152016104f1565b60e052610100526101205260c0526101005160c051036129ae57600060a0525b6101005160a0511061055457565b60c05160a051101561297f5760a05160051b6101205101357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe16101205136030181121561048f5767ffffffffffffffff816101205101351161048f57610120518101602081019190353603821361048f57606060805260a05160e05160019391013560f81c603f1660108110801561243657600782101561146b5750806108ce57506101205182016040818101359390923591608001357f800000000000000000000000000000000000000000000000000000000000000081036108c8575082517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260208160248173ffffffffffffffffffffffffffffffffffffffff89165afa9081156108bd57600091610888575b50935b73ffffffffffffffffffffffffffffffffffffffff809116928451927f095ea7b3000000000000000000000000000000000000000000000000000000008452600493602081806107058b878a84016020909392919373ffffffffffffffffffffffffffffffffffffffff60408201951681520152565b038160008a5af1801561087d579260a0600093608496936020999896610850575b5089519a8b9889977f505b0c1200000000000000000000000000000000000000000000000000000000895288015284606083610120510101351660248801526044870152610120510101356064850152165af1908115610846575061081b575b505b15806107ea575b6107a157600160a0510160a052610546565b60408051907f2c4029e900000000000000000000000000000000000000000000000000000000825260a05160048301526024820152806107e6604482016080516104e6565b0390fd5b507f800000000000000000000000000000000000000000000000000000000000000060a05160e0510135161561078f565b602090813d831161083f575b6108318183612a08565b8101031261048f5738610786565b503d610827565b513d6000823e3d90fd5b61086f908a3d8c11610876575b6108678183612a08565b810190612d6d565b5038610726565b503d61085d565b87513d6000823e3d90fd5b906020823d6020116108b5575b816108a260209383612a08565b810103126108b25750513861068c565b80fd5b3d9150610895565b84513d6000823e3d90fd5b9361068f565b60018103610c3c5750610120805190929081018035810192908303841361048f576108f8906104c5565b9060409283826101205101013567ffffffffffffffff811161048f5760208061092a9301918461012051010101612ae7565b9061093c6060826101205101016104c5565b92608082610120510101359560ff871680970361048f5761012051830160a0810135939061096c9060e0016104c5565b91610100938483610120510101359183610120510101359061ffff821680920361048f5773ffffffffffffffffffffffffffffffffffffffff80809216991692846101205101356103601161048f576109c7828b9716612c30565b907f800000000000000000000000000000000000000000000000000000000000000098898114600014610c365750909192939495508a517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152602081602481895afa908115610c2b57908b97969594939291600091610bea575b50985b8103610be4575047975b8b517f095ea7b300000000000000000000000000000000000000000000000000000000815260208180610ab08560049c8d84016020909392919373ffffffffffffffffffffffffffffffffffffffff60408201951681520152565b038160008a5af18015610bd957610bba575b508b519c8d9a8b998a997fde6bbd9d000000000000000000000000000000000000000000000000000000008b528a01526101048901610b0091612c80565b9560248901526044880152606487015284610120510160c0013560848701521660a485015260c48401528281036003190160e4840152816101205101357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffca0019161012051016103800191610b7392612c0f565b03915a94602095f19081156108465750610b8f575b505b610788565b602090813d8311610bb3575b610ba58183612a08565b8101031261048f5738610b88565b503d610b9b565b610bd29060203d602011610876576108678183612a08565b5038610ac2565b8d513d6000823e3d90fd5b97610a55565b91929394959697506020823d602011610c23575b81610c0b60209383612a08565b810103126108b25750908a9695949392915138610a48565b3d9150610bfe565b8c513d6000823e3d90fd5b98610a4b565b60028103610d19575060409073ffffffffffffffffffffffffffffffffffffffff92836001541690610c75848261012051010135612c30565b91857f000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba31693843b1561048f576000948786928160606084978b519c8d9a8b997f36c78516000000000000000000000000000000000000000000000000000000008b5260048b015216602489015261012051010135166044860152351660648401525af19081156108465750610d0a5750610788565b610d13906129f4565b38610b88565b6003810361109757506101205182018035810191602083019160409084031261048f573567ffffffffffffffff811161048f57836101205101019060608284031261048f57604051926060840184811067ffffffffffffffff82111761106857604052602083013567ffffffffffffffff811161048f57830182603f8201121561048f57602081013590610dac82612a8e565b92610dba6040519485612a08565b8284526040602085019360071b8301019185831161048f57604001925b82841061100357505050508352610df0604083016104c5565b93602084019485526060604085019301358352604081610120510101359067ffffffffffffffff821161048f5761012051010191610e32602084019283612a47565b5073ffffffffffffffffffffffffffffffffffffffff600154169473ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba3163b1561048f5794929391906040519586947f2a2d80d100000000000000000000000000000000000000000000000000000000865260048601526060602486015260c48501935193606060648701528451809152602060e487019501906000905b808210610f8957505050946040610f319386959373ffffffffffffffffffffffffffffffffffffffff600099511660848801525160a4870152600319868503016044870152359101612c0f565b03818373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba3165af18015610f7d57610d0a5750610788565b6040513d6000823e3d90fd5b9197965091929394602060806001928a5173ffffffffffffffffffffffffffffffffffffffff815116825273ffffffffffffffffffffffffffffffffffffffff848201511684830152606060408201519165ffffffffffff8093166040850152015116606082015201980192018896979594939291610ee4565b60806020858403011261048f576020608091604051611021816129d8565b61102a876104c5565b81526110378388016104c5565b8382015261104760408801612aa6565b604082015261105860608801612aa6565b6060820152815201930192610dd7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6004919082810361120e575090606091356040906110bc828661012051010135612c30565b9473ffffffffffffffffffffffffffffffffffffffff948591610120510101351693811680156000146111385750504792831061111257505080611102575b5050610788565b61110b91612e7e565b38806110fb565b517f6a12f104000000000000000000000000000000000000000000000000000000008152fd5b936020602495849397959451968780927f70a0823100000000000000000000000000000000000000000000000000000000825230888301525afa948515611203576000956111cf575b5084106111a957505081611198575b505050610788565b6111a192612e9c565b388080611190565b517f675cae38000000000000000000000000000000000000000000000000000000008152fd5b90946020823d6020116111fb575b816111ea60209383612a08565b810103126108b25750519338611181565b3d91506111dd565b82513d6000823e3d90fd5b929493926005810361132857506101205160409501606081013591359061123790870135612c30565b919273ffffffffffffffffffffffffffffffffffffffff82169084826112675750505050610b8a92939450612e7e565b7f80000000000000000000000000000000000000000000000000000000000000001461129c575b5050610b8a93949550612e9c565b60209192945060248851809481937f70a0823100000000000000000000000000000000000000000000000000000000835230908301525afa95861561084657506000956112f4575b50929384939091610b8a3861128e565b6020813d602011611320575b8161130d60209383612a08565b810103126103b057519450610b8a6112e4565b3d9150611300565b9394929360061461133b57505050610788565b3591604061135a81606084610120510101359361012051010135612c30565b9282158015611460575b6114395773ffffffffffffffffffffffffffffffffffffffff851690816113a1575050506111a1925061139a6127109147612e3c565b0490612e7e565b60209060248451809481937f70a0823100000000000000000000000000000000000000000000000000000000835230908301525afa9182156108465750600091611405575b506113f961140094939261271092612e3c565b0491612e9c565b6111a1565b906020823d602011611431575b8161141f60209383612a08565b810103126108b25750516113f96113e6565b3d9150611412565b90517fdeaa01e6000000000000000000000000000000000000000000000000000000008152fd5b506127108311611364565b600d9081831015611f5a575050600781036115c757506101205160015473ffffffffffffffffffffffffffffffffffffffff936040939185169290917f000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba3861691830160e081013501823b1561048f576000946115b1869260c061151f978b8b519c8d9a8b998a987f2b67b570000000000000000000000000000000000000000000000000000000008a5260048a01526104c5565b166024870152806115368d846101205101016104c5565b16604487015261154d606083610120510101612aa6565b65ffffffffffff809116606488015261156d608084610120510101612aa6565b16608487015261158460a0836101205101016104c5565b1660a48601526101205101013560c484015261010060e48401526101048301908960208201359101612c0f565b03925af19081156108465750610d0a5750610788565b600881036117915750906115e660408092610120510101359235612c30565b91807f80000000000000000000000000000000000000000000000000000000000000008103611761575050475b8061162057505050610788565b73ffffffffffffffffffffffffffffffffffffffff90817f000000000000000000000000430000000000000000000000000000000000000416803b1561048f578351927fd0e30db0000000000000000000000000000000000000000000000000000000008452600493600081868187875af1801561175657611747575b5030908616036116af575b5050611190565b61170e9460006020948651978895869485937fa9059cbb00000000000000000000000000000000000000000000000000000000855284016020909392919373ffffffffffffffffffffffffffffffffffffffff60408201951681520152565b03925af19081156108465750611728575b808080806116a8565b6117409060203d602011610876576108678183612a08565b503861171f565b611750906129f4565b3861169d565b86513d6000823e3d90fd5b47101561161357600482517f6a12f104000000000000000000000000000000000000000000000000000000008152fd5b600981036119225750906117a760409235612c30565b9173ffffffffffffffffffffffffffffffffffffffff90817f000000000000000000000000430000000000000000000000000000000000000416908051937f70a08231000000000000000000000000000000000000000000000000000000008552600430818701526024916020878481885afa9687156108bd576000976118ee575b50610120510183013586106118c7578561184a575b50505050505050610788565b833b1561048f57600091869183855196879485937f2e1a7d4d0000000000000000000000000000000000000000000000000000000085528401525af190811561084657506118b8575b5030908316036118a8575b808080808061183e565b6118b191612e7e565b388061189e565b6118c1906129f4565b38611893565b82517f6a12f104000000000000000000000000000000000000000000000000000000008152fd5b90966020823d60201161191a575b8161190960209383612a08565b810103126108b25750519583611829565b3d91506118fc565b600a8103611aa557506101205160409201606081013581019135908301357f80000000000000000000000000000000000000000000000000000000000000008101611a97575082517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260208160248173ffffffffffffffffffffffffffffffffffffffff86165afa9081156108bd57600091611a64575b5091600091611a2a94935b8373ffffffffffffffffffffffffffffffffffffffff86518098819682957f5c459a5b000000000000000000000000000000000000000000000000000000008452600484015289602484015260448301908a60208201359101612dff565b0393165af19081156108465750611a415750610788565b611a5d903d806000833e611a558183612a08565b810190612d85565b5038610b88565b906020823d602011611a8f575b81611a7e60209383612a08565b810103126108b257505160006119c1565b3d9150611a71565b91600091611a2a94936119cc565b600b8103611c2c5750610120516080920191820135820191604091359060608101358101908301357f80000000000000000000000000000000000000000000000000000000000000008103611c09575082517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260208160248173ffffffffffffffffffffffffffffffffffffffff87165afa9081156108bd57600091611bd5575b5091611bbb91600073ffffffffffffffffffffffffffffffffffffffff81955b611a2a8851998a97889687947f3b49580d00000000000000000000000000000000000000000000000000000000865260048601526060602486015260648501908c60208201359101612dff565b906003198483030160448501528a60208201359101612dff565b906020823d602011611c01575b81611bef60209383612a08565b810103126108b2575051611bbb611b4e565b3d9150611be2565b91611bbb91600073ffffffffffffffffffffffffffffffffffffffff8195611b6e565b600c14611c3a575050610788565b6101205182016060810135810192604092359160208086013592918581013501808601910135611c6984612a8e565b96611c7687519889612a08565b8488526020880187819660051b8301019136831161048f57949895948801905b828210611f4a5750505083519160005b838110611d87575050505083519485927fe75552fb0000000000000000000000000000000000000000000000000000000084526044840190866004860152518091526064840192906000905b808210611d6b57505050600073ffffffffffffffffffffffffffffffffffffffff8460209694608082956101205101013560248301520393165af19081156108465750611d40575b806110fb565b602090813d8311611d64575b611d568183612a08565b8101031261048f5738611d3a565b503d611d4c565b8251855288955060209485019490920191600190910190611cf2565b8086611d9682829c9899612c6c565b517f80000000000000000000000000000000000000000000000000000000000000008114611e9c575b80611dcf611e5394602094612c6c565b5273ffffffffffffffffffffffffffffffffffffffff611df8611df3868989612d3c565b612d4c565b168a60008d518096819582947f095ea7b3000000000000000000000000000000000000000000000000000000008452600484016020909392919373ffffffffffffffffffffffffffffffffffffffff60408201951681520152565b03925af18015611e91579060019291611e72575b500197949397611ca6565b611e8a9060203d602011610876576108678183612a08565b5038611e67565b89513d6000823e3d90fd5b5050602073ffffffffffffffffffffffffffffffffffffffff611ec5611df36024948888612d3c565b168a51928380927f70a082310000000000000000000000000000000000000000000000000000000082523060048301525afa908115611e915782918b91600091611f10575b50611dbf565b925090506020823d602011611f42575b81611f2d60209383612a08565b810103126108b257505181908a906020611f0a565b3d9150611f20565b8135815260209182019101611c96565b611f68575b50505050610788565b8103612265575061012051820180358101919060e09083031261048f57611f8e906104c5565b906040836101205101013567ffffffffffffffff811161048f57611fbf906020808401918661012051010101612ae7565b9260208201609f82610120510101121561048f57604051916040830183811067ffffffffffffffff8211176110685760405282602060c0846101205101019201821161048f57608083610120510101905b828210612255575050612022906104c5565b90806101205101356103201161048f577f800000000000000000000000000000000000000000000000000000000000000091826060836101205101013514600014612245576040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260208160248173ffffffffffffffffffffffffffffffffffffffff8a165afa908115610f7d57600091612213575b50925b61012051830160e00135036121fc574792919061211796945b6040519788967f36ae087e00000000000000000000000000000000000000000000000000000000885260c0600489015260c4880190612c80565b93602487015260448601906000915b600283106121e3575050508461219d8194602098969473ffffffffffffffffffffffffffffffffffffffff80951660848501526003198483030160a48501526103407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffce0826101205101350191610120510101612c0f565b0393165af18015610f7d576121b8575b505b38808080611f5f565b602090813d83116121dc575b6121ce8183612a08565b8101031261048f57386121ad565b503d6121c4565b8151815289975060019092019160209182019101612126565b60e0826101205101013592919061211796946120dd565b906020823d60201161223d575b8161222d60209383612a08565b810103126108b2575051386120c1565b3d9150612220565b60608261012051010135926120c4565b8135815260209182019101612010565b600e81036122df57509073ffffffffffffffffffffffffffffffffffffffff604092351660005260006020528180600020916101205101013560005260205260ff8160002054166122b657506121af565b600490517f599be0bf000000000000000000000000000000000000000000000000000000008152fd5b600f146122ee575b50506121af565b602091925060409273ffffffffffffffffffffffffffffffffffffffff908451938480937f70a08231000000000000000000000000000000000000000000000000000000008252806004963516868301526024968791898661012051010135165afa91821561242b576000926123f6575b506101205101606001351180159390612379575b506122e7565b8051927fa32816720000000000000000000000000000000000000000000000000000000060208501528284528184019284841067ffffffffffffffff8511176123ca57505052608052388080612373565b6041907f4e487b7100000000000000000000000000000000000000000000000000000000600052526000fd5b90916020823d602011612423575b8161241160209383612a08565b810103126108b257505190606061235f565b3d9150612404565b85513d6000823e3d90fd5b50601e810361266d57506101205182018035810192602080850193919285031261048f57359067ffffffffffffffff821161048f5761012051010181603f8201121561048f5760208101359060409261248e83612a8e565b9461249b85519687612a08565b838652602086019285849560071b82010192831161048f578501925b82841061260b575050505073ffffffffffffffffffffffffffffffffffffffff90816001541684519060005b8281106125c657505050817f000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba31691823b1561048f5783517f0d58b1db000000000000000000000000000000000000000000000000000000008152602060048201529451602486018190528592604484019290916000915b81831061258257505050509181600081819503925af19081156108465750610d0a5750610788565b91938395506080602091846060600195975182815116845282868201511686850152828d820151168d8501520151166060820152019501930190918794939261255a565b81856125d2838a612c6c565b515116036125e2576001016124e3565b600486517fe7002877000000000000000000000000000000000000000000000000000000008152fd5b60806020858403011261048f5760206080918751612628816129d8565b612631876104c5565b815261263e8388016104c5565b8382015261264d8988016104c5565b8982015261265d606088016104c5565b60608201528152019301926124b7565b601f81036127275750600060208160646040947fffffffffffffffffffffffffffffffffffffffff0000000000000000000000006001546126b5888a61012051010135612c30565b73ffffffffffffffffffffffffffffffffffffffff60608a519b6101205101013516606052885260601b16602c526f23b872dd000000000000000000000000600c52601c948591355af13d1560016000511417161561271a5750600060605252610788565b600490637939f424600052fd5b6010810361294e575061012051820180358101602081019291604091031261048f573567ffffffffffffffff811161048f5781602061276d928561012051010101612a47565b92604083610120510101359267ffffffffffffffff841161048f5782603f858361012051010101121561048f576020848261012051010101356127af81612a8e565b936127bd6040519586612a08565b8185526020850180968260408560051b838861012051010101011161048f576040818661012051010101915b60408560051b83886101205101010101831061291857505050505050612843604051947f24856bc30000000000000000000000000000000000000000000000000000000060208701526040602487015260648601906104e6565b917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc8584030160448601525190818352602083019160208160051b850101949360005b8281106128ed57505050505050816128aa600093849303601f198101835282612a08565b60208151910182305af13d156128e5573d6128c481612a2b565b906128d26040519283612a08565b81523d6000602083013e5b608052610788565b6080516128dd565b90919260208061290a89601f1987869a9b9c03018a528a516104e6565b980196019493929101612886565b823567ffffffffffffffff811161048f576020916129438660408594878c6101205101010101612a47565b8152019201916127e9565b602490604051907fd76a1e9e0000000000000000000000000000000000000000000000000000000082526004820152fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60046040517fff633a38000000000000000000000000000000000000000000000000000000008152fd5b6080810190811067ffffffffffffffff82111761106857604052565b67ffffffffffffffff811161106857604052565b90601f601f19910116810190811067ffffffffffffffff82111761106857604052565b67ffffffffffffffff811161106857601f01601f191660200190565b81601f8201121561048f57803590612a5e82612a2b565b92612a6c6040519485612a08565b8284526020838301011161048f57816000926020809301838601378301015290565b67ffffffffffffffff81116110685760051b60200190565b359065ffffffffffff8216820361048f57565b35906bffffffffffffffffffffffff8216820361048f57565b359067ffffffffffffffff8216820361048f57565b91909180830390610140821261048f57604080519267ffffffffffffffff9060a0850182811186821017611068578352849684358652602085013583811161048f5781612b35918701612a47565b6020870152838501359183831161048f57612b757fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa09260c0948801612a47565b85880152011261048f5781519260c0840191821184831017611068576080938361012093612c0a9552612baa60608401612aa6565b8252612bb7868401612aa6565b6020830152612bc860a084016104c5565b90820152612bd860c08301612ab9565b6060820152612be960e08301612ab9565b85820152612bfa6101008301612ad2565b60a0820152606086015201612ad2565b910152565b601f8260209493601f19938186528686013760008582860101520116010190565b73ffffffffffffffffffffffffffffffffffffffff9080821660018103612c5a5750506001541690565b909150600203612c6957503090565b90565b805182101561297f5760209160051b010190565b90610120612cb7612ca5610140855185526020860151908060208701528501906104e6565b604085015184820360408601526104e6565b92608060a0606083015165ffffffffffff8082511660608801526020820151168387015273ffffffffffffffffffffffffffffffffffffffff6040820151168287015260608101516bffffffffffffffffffffffff80911660c0880152838201511660e087015201519167ffffffffffffffff80931661010086015201511691015290565b919081101561297f5760051b0190565b3573ffffffffffffffffffffffffffffffffffffffff8116810361048f5790565b9081602091031261048f5751801515810361048f5790565b602090818184031261048f5780519067ffffffffffffffff821161048f57019180601f8401121561048f578251612dbb81612a8e565b93612dc96040519586612a08565b818552838086019260051b82010192831161048f578301905b828210612df0575050505090565b81518152908301908301612de2565b90918281527f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831161048f5760209260051b809284830137010190565b81810292918115918404141715612e4f57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600080809338935af115612e8e57565b63b12d13eb6000526004601cfd5b60109260209260145260345260446000938480936fa9059cbb00000000000000000000000082525af13d156001835114171615612ed857603452565b6390b8ec1890526004601cfdfea2646970667358221220131bf048f3ec4b09c2413c5008eb92f93b7d457c2ca59f56ccdd2bb2ee4ddeac64736f6c63430008160033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba30000000000000000000000004300000000000000000000000000000000000004

-----Decoded View---------------
Arg [0] : params (tuple): System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput]

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba3
Arg [1] : 0000000000000000000000004300000000000000000000000000000000000004


Deployed Bytecode Sourcemap

625:2070:15:-:0;;;;;;;;;;;-1:-1:-1;625:2070:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;625:2070:15;;;;;;;;;;;;;;;;1738:10:22;625:2070:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;625:2070:15;;;;;1341:10:22;625:2070:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;625:2070:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;625:2070:15;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;748:215:21;;;;;;;;;;;;;;;;;;;;;;;338:10:17;360:4;338:27;360:4;;625:2070:15;;;;;;;;;385:23:17;381:52;;239:10;;;;;;;482:1;239:10;;338;;;239;;;;;482:1;:::i;:::-;239:10;;;;;;625:2070:15;;381:52:17;625:2070:15;417:16:17;;;;334:228;550:1;;;;;;;;;:::i;:::-;625:2070:15;;;;;;;;;-1:-1:-1;;625:2070:15;;;;;;;;;604:29:18;625:2070:15;;;;;;;;;;;-1:-1:-1;;625:2070:15;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;809:15;:26;805:66;;338:10:17;360:4;338:27;360:4;;625:2070:15;;;;;;;;;385:23:17;381:52;;239:10;;;;;;;482:1;239:10;;338;;;239;;;;;482:1;:::i;805:66:15:-;625:2070;;;844:27;;;;625:2070;;;;;;;;;;;-1:-1:-1;;625:2070:15;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::i;:::-;360:4:17;;;338:10;360:4;338:27;360:4;;385:8;625:2070:15;;;;;;;;385:23:17;381:52;;239:10;;;;;;;482:1;239:10;;338;;;239;;;;;482:1;:::i;625:2070:15:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;-1:-1:-1;;625:2070:15;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;1251:941;;;;;;;;;1502:28;;;;;1498:57;;-1:-1:-1;1662:24:15;;1688:26;;;;;;;;1251:941::o;1662:24::-;625:2070;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1864:24;1715:19:16;625:2070:15;;;;1832:4:16;;1822:14;625:2070:15;1749:22;625:2070;313:4:24;;;1861::16;1851:14;;1847:11318;;;;1933:4;1923:14;;1933:4;;;-1:-1:-1;1961:29:16;;;-1:-1:-1;625:2070:15;;;;2299:389:16;;;;;;;;;;;;;478:66:25;1176:36:23;;478:66:25;;625:2070:15;;;1177:4:24;1215:41:23;;1250:4;1215:41;;;1177:4:24;625:2070:15;;1177:4:24;625:2070:15;;;;1215:41:23;;;;;;;-1:-1:-1;1215:41:23;;;1176:89;;;;625:2070:15;;;;;;;1276:39:23;1177:4:24;1276:39:23;;;;625:2070:15;1276:39:23;;;;;;;;625:2070:15;;;;;;;;;;;;1177:4:24;;625:2070:15;;;1276:39:23;;;-1:-1:-1;1276:39:23;;;;;;;;2299:389:16;-1:-1:-1;1276:39:23;625:2070:15;1276:39:23;;625:2070:15;1276:39:23;;;;;1176:89;625:2070:15;;;1326:127:23;;;;;1177:4:24;1326:127:23;;;;1177:4:24;625:2070:15;;;;;;2299:389:16;;625:2070:15;;;;1177:4:24;625:2070:15;;;;;;;2299:389:16;;625:2070:15;;;;;1326:127:23;;;;;;;;;;1176:89;1957:4377:16;;1907:8:15;:36;;;1847:11318:16;1903:202:15;;1832:4:16;2147:14:15;;625:2070;2147:14;;1662:24;;1903:202;625:2070;;;1970:120;;;;625:2070;;1970:120;;;625:2070;;;;;;;;;;;;;:::i;:::-;1970:120;;;1907:36;625:2070;;;;;;;1749:22;2285:36;:41;1907:36;;1326:127:23;625:2070:15;1326:127:23;;;;;;;;;;;;:::i;:::-;;;1177:4:24;;;;1326:127:23;;;;;;;;;625:2070:15;1177:4:24;-1:-1:-1;1177:4:24;;;;;1276:39:23;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;;;;625:2070:15;;1177:4:24;-1:-1:-1;1177:4:24;;;;;1215:41:23;;625:2070:15;1215:41:23;;625:2070:15;1215:41:23;;;;;;625:2070:15;1215:41:23;;;:::i;:::-;;;1177:4:24;;;;;;1215:41:23;;;1177:4:24;625:2070:15;;1215:41:23;;;-1:-1:-1;1215:41:23;;;625:2070:15;;1177:4:24;-1:-1:-1;1177:4:24;;;;;1176:89:23;;;;1957:4377:16;1832:4;2808:29;;1832:4;;-1:-1:-1;625:2070:15;;;;;;;;;;3058:107:16;;;625:2070:15;693:4:24;;;-1:-1:-1;693:4:24;;1177;;;:::i;:::-;693;;625:2070:15;;;;;;693:4:24;;625:2070:15;693:4:24;;;;625:2070:15;3058:107:16;693:4:24;3058:107:16;;625:2070:15;;;;;693:4:24;;;:::i;:::-;625:2070:15;1177:4:24;625:2070:15;;;;;693:4:24;1177;:::i;:::-;625:2070:15;693:4:24;625:2070:15;;;;693:4:24;;625:2070:15;;;;693:4:24;;;;;625:2070:15;;;;693:4:24;;;625:2070:15;;;1177:4:24;;693;;1177;:::i;:::-;693;;625:2070:15;;;;;;693:4:24;625:2070:15;;;;;;693:4:24;;;;;;;;;;;625:2070:15;;;;;;;;;;;;;3397:3:16;1177:4:24;;;3539:17:16;625:2070:15;;;;3539:17:16;:::i;:::-;478:66:25;;1818:89:23;:36;;;:89;478:66:25;;;625:2070:15;;;;;;;;;;1177:4:24;1857:41:23;;1892:4;1857:41;;;1177:4:24;625:2070:15;1857:41:23;1177:4:24;1857:41:23;;;;;;;;;;;;;;;;;;-1:-1:-1;1857:41:23;;;1818:89;;;;1923:33;;478:66:25;;1959:21:23;;1923:63;;625:2070:15;;1177:4:24;1997:39:23;;625:2070:15;1997:39:23;;;;;;;;;625:2070:15;;;;;;;;;;;;1177:4:24;;625:2070:15;;;1997:39:23;;;-1:-1:-1;1997:39:23;;;;;;;;;1923:63;625:2070:15;;;2047:258:23;;;;;;;1177:4:24;2047:258:23;;;;625:2070:15;;;;;;;:::i;:::-;;;;;1177:4:24;625:2070:15;;;;;;;;;;;;693:4:24;;625:2070:15;;;;;;;;;1177:4:24;625:2070:15;;;;;;;-1:-1:-1;;625:2070:15;;;;;;;;;;1177:4:24;;625:2070:15;;;;1177:4:24;;625:2070:15;;;;:::i;:::-;2047:258:23;;;;625:2070:15;2047:258:23;;;;;;;;;;1923:63;2804:3530:16;;1957:4377;;2047:258:23;625:2070:15;2047:258:23;;;;;;;;;;;;:::i;:::-;;;1177:4:24;;;;2047:258:23;;;;;;;;1997:39;;;625:2070:15;1997:39:23;625:2070:15;1997:39:23;;;;;;;:::i;:::-;;;;;;625:2070:15;;1177:4:24;-1:-1:-1;1177:4:24;;;;;1923:63:23;;;;1857:41;;;;;;;;;625:2070:15;1857:41:23;;625:2070:15;1857:41:23;;;;;;625:2070:15;1857:41:23;;;:::i;:::-;;;1177:4:24;;;;;;;;;;;;;;1857:41:23;;;;;;-1:-1:-1;1857:41:23;;;625:2070:15;;1177:4:24;-1:-1:-1;1177:4:24;;;;;1818:89:23;;;;2804:3530:16;485:4:24;3625:41:16;;485:4:24;;3883:242:16;;625:2070:15;;;;1832:4:16;625:2070:15;;;4183:14:16;625:2070:15;;;;;3883:242:16;;4183:14;:::i;:::-;1322:7:27;;;625:2070:15;1322:45:27;;;;;;-1:-1:-1;625:2070:15;;;;;;;;;;1322:45:27;;;;;1177:4:24;1322:45:27;;;;;1177:4:24;625:2070:15;;;;1177:4:24;625:2070:15;;;3883:242:16;;625:2070:15;;;;1177:4:24;3883:242:16;625:2070:15;;;;1177:4:24;1322:45:27;;;;;;;;;;3621:2713:16;1957:4377;;1322:45:27;;;;:::i;:::-;;;;3621:2713:16;537:4:24;4235:40:16;;537:4:24;;-1:-1:-1;625:2070:15;;;;;;4378:59:16;;;625:2070:15;4378:59:16;;;693:4:24;;;;;;;;625:2070:15;693:4:24;;;;625:2070:15;;;;693:4:24;;625:2070:15;693:4:24;;;;;;;625:2070:15;1269:4:24;625:2070:15;1269:4:24;;;;;625:2070:15;1269:4:24;;;;;693;1269;625:2070:15;693:4:24;;;625:2070:15;693:4:24;;;;;;;313;693;;;;;;625:2070:15;693:4:24;;;;;;;:::i;:::-;625:2070:15;1269:4:24;693;625:2070:15;1269:4:24;;;:::i;:::-;693;;;;625:2070:15;693:4:24;;;1933::16;693::24;;;;;;;;;;;;;;;;;;;;;;;;;625:2070:15;693:4:24;;;625:2070:15;:::i;:::-;693:4:24;625:2070:15;693:4:24;;;;;625:2070:15;693:4:24;;;;;625:2070:15;693:4:24;;;625:2070:15;;;;693:4:24;;;625:2070:15;693:4:24;;;;625:2070:15;;;693:4:24;;;625:2070:15;693:4:24;;;;;:::i;:::-;;625:2070:15;1832:4:16;625:2070:15;;4520:7:16;625:2070:15;4520:7:16;625:2070:15;4520:43:16;;;;625:2070:15;;;;;693:4:24;625:2070:15;4520:43:16;;;1177:4:24;4520:43:16;;;;;1177:4:24;625:2070:15;693:4:24;;;;;;;;;;625:2070:15;693:4:24;;;;625:2070:15;;;;;;;;;1269:4:24;;693;-1:-1:-1;693:4:24;;;;;;;;;;;;;;;;;625:2070:15;-1:-1:-1;693:4:24;;625:2070:15;693:4:24;;;1177;693;;;;625:2070:15;-1:-1:-1;;693:4:24;;;;;;;;748:215:21;;;693:4:24;:::i;:::-;4520:43:16;:7;;625:2070:15;4520:7:16;625:2070:15;4520:43:16;;;;;;;;4231:2103;1957:4377;;4520:43;693:4:24;625:2070:15;1177:4:24;-1:-1:-1;1177:4:24;;;;;693;;;;;;;;;625:2070:15;693:4:24;1832::16;693::24;;;625:2070:15;693:4:24;;625:2070:15;1177:4:24;;625:2070:15;693:4:24;;;;625:2070:15;693:4:24;;;1177;625:2070:15;693:4:24;;;;1177;;;;;693;;;1021;693;;1177;625:2070:15;693:4:24;;1021;693;1269;;693;;;;;;;;;;;;;;625:2070:15;693:4:24;;;;;;;625:2070:15;693:4:24;625:2070:15;693:4:24;625:2070:15;1269:4:24;;;:::i;:::-;625:2070:15;;;:::i;:::-;693:4:24;;1269;693;;;1269;:::i;:::-;693;;;;1177;693;;;1177;:::i;:::-;693;;;;1177;625:2070:15;693:4:24;;1177;:::i;:::-;625:2070:15;693:4:24;;;;;;;;;;;1269;;-1:-1:-1;1269:4:24;;;;;-1:-1:-1;1269:4:24;4231:2103:16;589:4:24;;;4592:25:16;;;589:4:24;;4838:245:16;;625:2070:15;4838:245:16;;;625:2070:15;5126:14:16;625:2070:15;;;;;4838:245:16;;5126:14;:::i;:::-;625:2070:15;;;;;;;;4838:245:16;;625:2070:15;;;;2654:22:26;;2650:449;625:2070:15;;;2702:21:26;;;2741:23;;;2737:53;;2808:11;;;2804:51;;2650:449;;;1957:4377:16;;2804:51:26;2847:7;;;:::i;:::-;2804:51;;;;2737:53;625:2070:15;2773:17:26;;;;2650:449;625:2070:15;;1177:4:24;625:2070:15;;;;;;;2896:37:26;;;;1177:4:24;2896:37:26;;2927:4;2896:37;;;1177:4:24;2896:37:26;;;;;;;-1:-1:-1;2896:37:26;;;2650:449;2951:23;;;2947:55;;3020:11;;;3016:72;;2650:449;;;;1957:4377:16;;3016:72:26;3080:7;;;:::i;:::-;3016:72;;;;;2947:55;625:2070:15;2983:19:26;;;;2896:37;;;625:2070:15;2896:37:26;;625:2070:15;2896:37:26;;;;;;625:2070:15;2896:37:26;;;:::i;:::-;;;1177:4:24;;;;;;2896:37:26;;;;;;;-1:-1:-1;2896:37:26;;;625:2070:15;;1177:4:24;-1:-1:-1;1177:4:24;;;;;4588:1746:16;5181:28;;;;625:2070:15;5181:28:16;;625:2070:15;;-1:-1:-1;625:2070:15;;5426:241:16;;625:2070:15;;5426:241:16;;;;;;5708:14;;5426:241;;;5708:14;:::i;:::-;5724:5;;625:2070:15;;;;5724:5:16;1005:22:26;625:2070:15;;1069:5:26;;;;;;;;;;:::i;1001:302::-;478:66:25;1110:35:26;1106:119;;1001:302;1286:5;;;;;;;;:::i;1106:119::-;625:2070:15;;;;;1177:4:24;625:2070:15;;1173:37:26;;;;1177:4:24;1173:37:26;;1204:4;1173:37;;;1177:4:24;1173:37:26;;;;;;;;-1:-1:-1;1173:37:26;;;1106:119;-1:-1:-1;1165:45:26;;;;;;1286:5;1106:119;;;1173:37;625:2070:15;1173:37:26;;625:2070:15;1173:37:26;;;;;;625:2070:15;1173:37:26;;;:::i;:::-;;;1177:4:24;;;;;;-1:-1:-1;1286:5:26;1173:37;;;;;-1:-1:-1;1173:37:26;;5177:1157:16;5759:31;;;;693:4:24;5759:31:16;5755:579;;5177:1157;;;1957:4377;;5755:579;6006:240;;;6294:14;625:2070:15;;;;;;6006:240:16;;625:2070:15;;;;6006:240:16;;6294:14;:::i;:::-;1690:9:26;;;:26;;;;5755:579:16;1686:52:26;;625:2070:15;;;;1752:22:26;625:2070:15;;1808:21:26;;;1932:6;1808:21;;1861:14;668:6;1808:21;;1861:14;:::i;:::-;668:6;1932;;:::i;1748:510::-;625:2070:15;;1177:4:24;625:2070:15;;1988:37:26;;;;1177:4:24;1988:37:26;;2019:4;1988:37;;;1177:4:24;1988:37:26;;;;;;;;-1:-1:-1;1988:37:26;;;1748:510;2057:14;;2240:6;2057:14;;;668:6;2057:14;;:::i;:::-;668:6;2240;;:::i;:::-;1748:510;;1988:37;;625:2070:15;1988:37:26;;625:2070:15;1988:37:26;;;;;;625:2070:15;1988:37:26;;;:::i;:::-;;;1177:4:24;;;;-1:-1:-1;1177:4:24;2057:14:26;1988:37;;;;;-1:-1:-1;1988:37:26;;1686:52;625:2070:15;;1725:13:26;;;;1690:26;1703:13;1710:6;1703:13;;1690:26;;1919:9869:16;6406:4;;6396:14;;;6406:4;;;-1:-1:-1;;1933:4:16;6460:34;;1933:4;;-1:-1:-1;625:2070:15;;1832:4:16;625:2070:15;;;748:215:21;;625:2070:15;;;;;;6900:7:16;625:2070:15;;;;;748:215:21;;;;;6900:44:16;;;;;-1:-1:-1;625:2070:15;1021:4:24;625:2070:15;;748:215:21;625:2070:15;;;;;6900:44:16;;;;;;;1177:4:24;6900:44:16;;;;;1177:4:24;625:2070:15;:::i;:::-;;1021:4:24;;;1177;625:2070:15;1269:4:24;625:2070:15;;;;;1021:4:24;1269;:::i;:::-;625:2070:15;1021:4:24;;;1177;;625:2070:15;;;;;1021:4:24;1177;:::i;:::-;;;;;1021;;;;1177;1021;625:2070:15;;;;1021:4:24;1177;:::i;:::-;;1021;;;;625:2070:15;1021:4:24;625:2070:15;;;;1021:4:24;625:2070:15;:::i;:::-;;1021:4:24;;;1177;625:2070:15;;;1021:4:24;625:2070:15;1021:4:24;;;625:2070:15;1021:4:24;;;;;;;;748:215:21;;625:2070:15;748:215:21;;;;;1021:4:24;:::i;:::-;6900:44:16;;;;;;;;;;;;6456:3349;1919:9869;;6456:3349;813:4:24;6973:28:16;;813:4:24;;7177:173:16;;7388:14;7177:173;625:2070:15;;;;;7177:173:16;;;;7388:14;:::i;:::-;7404:9;;478:66:25;3353:36:26;;478:66:25;;3414:21:26;;;3349:188;3550:10;3546:182;;6969:2836:16;;;1957:4377;;3546:182:26;625:2070:15;3576:5:26;;;625:2070:15;3576:30:26;;;;;625:2070:15;;3576:30:26;1177:4:24;3576:30:26;;;;-1:-1:-1;3576:30:26;;;;;;;;;;;;;3546:182;3645:4;;625:2070:15;;;3624:26:26;3620:98;;3546:182;;;;;3620:98;3670:33;625:2070:15;-1:-1:-1;625:2070:15;;;;3670:33:26;;;;;;;1177:4:24;3670:33:26;;;;625:2070:15;;;;;;;;;;;;1177:4:24;;625:2070:15;;;3670:33:26;;;;;;;;;;;;;3620:98;;;;;;;3670:33;;;625:2070:15;3670:33:26;625:2070:15;3670:33:26;;;;;;;:::i;:::-;;;;;3576:30;;;;:::i;:::-;;;;;625:2070:15;;1177:4:24;-1:-1:-1;1177:4:24;;;;;3349:188:26;3465:21;-1:-1:-1;3452:85:26;3349:188;3452:85;3509:17;625:2070:15;;3509:17:26;;;;6969:2836:16;865:4:24;7443:30:16;;865:4:24;;7649:173:16;;7864:14;7649:173;;;7864:14;:::i;:::-;625:2070:15;;4011:5:26;;;625:2070:15;;;;4011:30:26;1177:4:24;4011:30:26;;;4035:4;4011:30;;;1177:4:24;;4011:30:26;625:2070:15;4011:30:26;;;;;;;;;;;-1:-1:-1;4011:30:26;;;7439:2366:16;-1:-1:-1;625:2070:15;;;7649:173:16;;;4055:21:26;;4051:76;;4140:9;4136:171;;7439:2366:16;;;;;;;;1957:4377;;4136:171:26;4165:21;;;;;-1:-1:-1;625:2070:15;;;;;;4165:21:26;;;;;1177:4:24;4165:21:26;;;;625:2070:15;4165:21:26;;;;;;;;;;4136:171;4035:4;;625:2070:15;;;4204:26:26;4200:97;;4136:171;;;;;;;;4200:97;4276:5;;;:::i;:::-;4200:97;;;;4165:21;;;;:::i;:::-;;;;4051:76;625:2070:15;;4099:17:26;;;;4011:30;;;625:2070:15;4011:30:26;;625:2070:15;4011:30:26;;;;;;625:2070:15;4011:30:26;;;:::i;:::-;;;1177:4:24;;;;-1:-1:-1;1177:4:24;;;4011:30:26;;;;;-1:-1:-1;4011:30:26;;7439:2366:16;917:4:24;7919:34:16;;917:4:24;;-1:-1:-1;625:2070:15;;8134:166:16;;625:2070:15;;748:215:21;;;;;;8134:166:16;;;;;478:66:25;4427:36:23;;478:66:25;;625:2070:15;;;1177:4:24;4466:37:23;;4497:4;4466:37;;;1177:4:24;625:2070:15;;1177:4:24;625:2070:15;;;;4466:37:23;;;;;;;-1:-1:-1;4466:37:23;;;4427:85;;;-1:-1:-1;4427:85:23;625:2070:15;4427:85:23;;;625:2070:15;;;;4523:51:23;;;;;;1177:4:24;4523:51:23;;;;;625:2070:15;;;;;;;;;748:215:21;;625:2070:15;748:215:21;;;;;625:2070:15;:::i;:::-;4523:51:23;625:2070:15;;4523:51:23;;;;;;;;;;7915:1890:16;1957:4377;;4523:51:23;;;;;-1:-1:-1;4523:51:23;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;4466:37;;625:2070:15;4466:37:23;;625:2070:15;4466:37:23;;;;;;625:2070:15;4466:37:23;;;:::i;:::-;;;1177:4:24;;;;-1:-1:-1;1177:4:24;-1:-1:-1;4466:37:23;;;;;-1:-1:-1;4466:37:23;;4427:85;;-1:-1:-1;4427:85:23;625:2070:15;4427:85:23;;;;7915:1890:16;969:4:24;8494:34:16;;969:4:24;;-1:-1:-1;625:2070:15;;748:215:21;625:2070:15;;748:215:21;;;;;;;8720:166:16;;;;625:2070:15;748:215:21;;;;;;8720:166:16;;;478:66:25;5557:36:23;;478:66:25;;625:2070:15;;;1177:4:24;5596:37:23;;5627:4;5596:37;;;1177:4:24;625:2070:15;;1177:4:24;625:2070:15;;;;5596:37:23;;;;;;;-1:-1:-1;5596:37:23;;;5557:85;;;625:2070:15;5557:85:23;-1:-1:-1;625:2070:15;5557:85:23;;;625:2070:15;;;5661:68:23;;;;;;;1177:4:24;5661:68:23;;;;;625:2070:15;;;;;;;;;748:215:21;;625:2070:15;748:215:21;;;;;625:2070:15;:::i;:::-;;-1:-1:-1;;625:2070:15;;;;;;;;748:215:21;625:2070:15;748:215:21;;;;;625:2070:15;:::i;5596:37:23:-;;625:2070:15;5596:37:23;;625:2070:15;5596:37:23;;;;;;625:2070:15;5596:37:23;;;:::i;:::-;;;1177:4:24;;;;-1:-1:-1;1177:4:24;625:2070:15;5596:37:23;;;;;-1:-1:-1;5596:37:23;;5557:85;;625:2070:15;5557:85:23;-1:-1:-1;625:2070:15;5557:85:23;;;;8490:1315:16;1021:4:24;9155:33:16;9151:654;;8490:1315;;1957:4377;;9151:654;625:2070:15;;;;;748:215:21;;;;;;;;9380:166:16;;625:2070:15;748:215:21;;;;;625:2070:15;748:215:21;;;;;;;;;;;1021:4:24;748:215:21;1021:4:24;:::i;:::-;625:2070:15;1269:4:24;625:2070:15;;1269:4:24;;;:::i;:::-;1021;;;625:2070:15;1021:4:24;;;;;625:2070:15;1021:4:24;;;;625:2070:15;;1021:4:24;;;;748:215:21;;;;;;;1021:4:24;;;;;;625:2070:15;;;;;3713:14:23;-1:-1:-1;3729:19:23;;;;;;625:2070:15;;;;;;4040:58:23;;;1177:4:24;4040:58:23;;625:2070:15;;;4040:58:23;;3976:43;4040:58;;625:2070:15;;;;;;;;;;-1:-1:-1;625:2070:15;;;;;;;;;;-1:-1:-1;625:2070:15;;;;;9380:166:16;625:2070:15;;;;;9380:166:16;;625:2070:15;;;;4040:58:23;625:2070:15;;4040:58:23;;;;;;;;;;625:2070:15;9151:654:16;;;4040:58:23;625:2070:15;4040:58:23;;;;;;;;;;;;:::i;:::-;;;1177:4:24;;;;4040:58:23;;;;;;;;625:2070:15;;;;;;;-1:-1:-1;625:2070:15;478:66:25;;;;1269:4:24;;;;1832::16;625:2070:15;;;;;;3750:4:23;3790:16;;;;;;;;;:::i;:::-;625:2070:15;478:66:25;3824:39:23;;3820:99;;3750:4;3933:28;;3976:43;3933:28;625:2070:15;3933:28:23;;:::i;:::-;625:2070:15;;3982:10:23;;;;;;:::i;:::-;;:::i;:::-;625:2070:15;;-1:-1:-1;625:2070:15;;3976:43:23;;;;;;1177:4:24;3976:43:23;;;;;625:2070:15;;;;;;;;;;;;1177:4:24;;625:2070:15;;;3976:43:23;;;;;;;;;;1832:4:16;3976:43:23;;;;3750:4;;625:2070:15;3713:14:23;;;;;;3976:43;;;625:2070:15;3976:43:23;625:2070:15;3976:43:23;;;;;;;:::i;:::-;;;;;;625:2070:15;;1177:4:24;-1:-1:-1;1177:4:24;;;;;3820:99:23;3883:10;;625:2070:15;;3883:10:23;;1177:4:24;3883:10:23;;;;:::i;:::-;625:2070:15;;;3877:42:23;;;;1177:4:24;3877:42:23;;3913:4;3976:43;3877:42;;1177:4:24;3877:42:23;;;;;;;;;;;-1:-1:-1;3877:42:23;;;3820:99;-1:-1:-1;3820:99:23;;3877:42;;;;;625:2070:15;3877:42:23;;625:2070:15;3877:42:23;;;;;;625:2070:15;3877:42:23;;;:::i;:::-;;;1177:4:24;;;;-1:-1:-1;1177:4:24;;;;;625:2070:15;3877:42:23;;;;;-1:-1:-1;3877:42:23;;1021:4:24;625:2070:15;;1021:4:24;;625:2070:15;1021:4:24;;;;;;;6392:5396:16;9867:1921;;6392:5396;;;;;1919:9869;;9867:1921;9909:33;;6406:4;;-1:-1:-1;625:2070:15;;;;;;10103:86:16;;;625:2070:15;1177:4:24;;;;;;;;;;:::i;:::-;625:2070:15;1177:4:24;625:2070:15;;;;1177:4:24;;625:2070:15;1177:4:24;;;;;10103:86:16;625:2070:15;10103:86:16;;;625:2070:15;;;;;1177:4:24;;;:::i;:::-;10103:86:16;625:2070:15;10103:86:16;;1177:4:24;625:2070:15;;;;1177:4:24;;;;;;625:2070:15;1269:4:24;1177;1269;;;;;625:2070:15;1269:4:24;;;;;1177;1269;1177;625:2070:15;1177:4:24;625:2070:15;;;;1177:4:24;10103:86:16;;1177:4:24;;;;;625:2070:15;;;;1177:4:24;;;;;;;;;;;;;:::i;:::-;625:2070:15;;;;;;10421:3:16;1177:4:24;;;478:66:25;2601:95:23;625:2070:15;;;;;;1177:4:24;625:2070:15;2601:41:23;:95;478:66:25;;;1177:4:24;625:2070:15;1177:4:24;2645:37:23;;2676:4;2645:37;;;1177:4:24;625:2070:15;;1177:4:24;625:2070:15;;;;2645:37:23;;;;;;;-1:-1:-1;2645:37:23;;;2601:95;;;;625:2070:15;;;;1177:4:24;;625:2070:15;2712:33:23;478:66:25;;2748:21:23;2712:63;;;478:66:25;2712:63:23;;;1177:4:24;625:2070:15;2786:183:23;;;1177:4:24;2786:183:23;;1177:4:24;2786:183:23;;;478:66:25;;;;;;:::i;:::-;;;;;625:2070:15;478:66:25;;;;-1:-1:-1;478:66:25;;1177:4:24;478:66:25;;;;625:2070:15;;;;478:66:25;625:2070:15;;;;;;;;;;478:66:25;;;1177:4:24;-1:-1:-1;;478:66:25;;;;;;;;1177:4:24;;625:2070:15;;;;;1177:4:24;625:2070:15;;;;1177:4:24;478:66:25;:::i;:::-;2786:183:23;625:2070:15;;2786:183:23;;;;;;;;478:66:25;9905:1869:16;;9867:1921;;;;;;2786:183:23;625:2070:15;2786:183:23;;;;;;;;;;;;:::i;:::-;;;1177:4:24;;;;2786:183:23;;;;;;;;478:66:25;;;625:2070:15;;478:66:25;;-1:-1:-1;1832:4:16;478:66:25;;;;625:2070:15;1269:4:24;;;;478:66:25;;;2712:63:23;1177:4:24;625:2070:15;;;;1177:4:24;625:2070:15;2712:63:23;;;478:66:25;2712:63:23;;;;2645:37;;625:2070:15;2645:37:23;;625:2070:15;2645:37:23;;;;;;625:2070:15;2645:37:23;;;:::i;:::-;;;1177:4:24;;;;;;2645:37:23;;;;;;-1:-1:-1;2645:37:23;;2601:95;625:2070:15;;;;;1177:4:24;625:2070:15;2601:95:23;;;1177:4:24;625:2070:15;;1177:4:24;;625:2070:15;1177:4:24;;;;;;;9905:1869:16;1125:4:24;10599:32:16;;1125:4:24;;10812:178:16;;625:2070:15;10812:178:16;;;625:2070:15;-1:-1:-1;625:2070:15;-1:-1:-1;625:2070:15;;;;-1:-1:-1;625:2070:15;;;;;10812:178:16;;-1:-1:-1;625:2070:15;;;;;-1:-1:-1;625:2070:15;;;1020:68:22;;10595:1179:16;9905:1869;;1020:68:22;1074:14;625:2070:15;;1074:14:22;;;;10595:1179:16;1177:4:24;11096:39:16;11092:682;;10595:1179;;;9905:1869;;11092:682;625:2070:15;11352:242:16;;;;625:2070:15;;;;;11626:29:16;;;;1177:4:24;11626:29:16;;;;11352:242;;625:2070:15;11626:29:16;;;1177:4:24;;625:2070:15;;;;;;;;11352:242:16;;625:2070:15;11626:29:16;;;;;;;-1:-1:-1;11626:29:16;;;11092:682;-1:-1:-1;625:2070:15;;;;11352:242:16;;-1:-1:-1;11626:43:16;;;;11692:63;;11092:682;;;;11692:63;625:2070:15;;11715:40:16;11732:22;625:2070:15;11715:40:16;;1177:4:24;11715:40:16;;;1269:4:24;;;;;;;625:2070:15;1269:4:24;;;;;;;;11706:49:16;;11692:63;;;;;1269:4:24;;;;-1:-1:-1;1269:4:24;;-1:-1:-1;1269:4:24;11626:29:16;;;625:2070:15;11626:29:16;;625:2070:15;11626:29:16;;;;;;625:2070:15;11626:29:16;;;:::i;:::-;;;1177:4:24;;;;-1:-1:-1;1177:4:24;;625:2070:15;11626:29:16;;;;;-1:-1:-1;11626:29:16;;;625:2070:15;;1177:4:24;-1:-1:-1;1177:4:24;;;;;1847:11318:16;-1:-1:-1;1326:4:24;11823:47:16;;1326:4:24;;-1:-1:-1;625:2070:15;;;;;;11960:67:16;;;625:2070:15;11960:67:16;;;;625:2070:15;;1269:4:24;;;;;;;625:2070:15;1269:4:24;;;;625:2070:15;;;1269:4:24;;313;1269;;;;;;625:2070:15;1269:4:24;;;;;;;;;:::i;:::-;625:2070:15;1269:4:24;625:2070:15;;1269:4:24;;;:::i;:::-;;;;625:2070:15;1269:4:24;;;;;;;;;;;;;;;;;;;;;;;;;625:2070:15;;;;;;;1832:4:16;625:2070:15;;;;1722:13:27;-1:-1:-1;1737:15:27;;;;;;1858:7;;;;;625:2070:15;1858:34:27;;;;;;625:2070:15;;1177:4:24;1858:34:27;;625:2070:15;1858:34:27;;;625:2070:15;;;;;;;;;;;;;;;;;-1:-1:-1;;625:2070:15;;;;;;1858:34:27;;;;;;-1:-1:-1;1858:34:27;;;;;;;;;;;;;;;11819:1336:16;1847:11318;;625:2070:15;;;;;;1269:4:24;625:2070:15;;;;1832:4:16;625:2070:15;;;;;;;1177:4:24;;625:2070:15;;;;;;;;;1177:4:24;625:2070:15;;;;;;;;;1177:4:24;625:2070:15;;;;;;1177:4:24;625:2070:15;1269:4:24;;625:2070:15;;;;;;;;;;1754:3:27;1777:15;;;;;;:::i;:::-;;625:2070:15;;1777:29:27;1773:65;;1832:4:16;625:2070:15;1722:13:27;;1773:65;1815:23;625:2070:15;;1815:23:27;;;;1269:4:24;;625:2070:15;1269:4:24;;;;;;;625:2070:15;1269:4:24;625:2070:15;;;1269:4:24;;;:::i;:::-;625:2070:15;;;:::i;:::-;1269:4:24;;625:2070:15;1269:4:24;;;625:2070:15;:::i;:::-;1269:4:24;;;;;;;;;:::i;:::-;;;;;625:2070:15;;1269:4:24;;625:2070:15;:::i;:::-;;1269:4:24;;;;;;;;;;;11819:1336:16;1378:4:24;12114:33:16;;1378:4:24;;12364:242:16;-1:-1:-1;625:2070:15;12364:242:16;8326:988:3;12364:242:16;625:2070:15;8326:988:3;1832:4:16;625:2070:15;12666:14:16;625:2070:15;;;;;12364:242:16;;12666:14;:::i;:::-;625:2070:15;;8326:988:3;;625:2070:15;;;;12364:242:16;;625:2070:15;;8326:988:3;;;625:2070:15;8326:988:3;;;;;;;;12364:242:16;;;;8326:988:3;;;;1832:4:16;-1:-1:-1;8326:988:3;;;;;;;;-1:-1:-1;625:2070:15;8326:988:3;;1847:11318:16;;8326:988:3;;;;-1:-1:-1;8326:988:3;;12110:1045:16;1861:4;12714:36;;1861:4;;-1:-1:-1;625:2070:15;;;;;;12821:36:16;;625:2070:15;12821:36:16;;;;1269:4:24;;;;;;;625:2070:15;1269:4:24;;;;625:2070:15;;1269:4:24;625:2070:15;;;;;1269:4:24;;;:::i;:::-;625:2070:15;1269:4:24;625:2070:15;;;;1269:4:24;;;625:2070:15;1269:4:24;;;;625:2070:15;313:4:24;625:2070:15;;;;;1269:4:24;;;;;;625:2070:15;;;;;;1269:4:24;;;;;;:::i;:::-;625:2070:15;1269:4:24;;625:2070:15;1269:4:24;;;:::i;:::-;;;;625:2070:15;1269:4:24;;;;;;;625:2070:15;1269:4:24;625:2070:15;;;;;1269:4:24;;;;;;;625:2070:15;;;;;1269:4:24;;;;;;625:2070:15;1269:4:24;625:2070:15;;;;;1269:4:24;;;;;;;625:2070:15;;;;;;1269:4:24;;625:2070:15;12936:71:16;12959:27;625:2070:15;12936:71:16;;;1269:4:24;12936:71:16;;;1269:4:24;;;;;;:::i;:::-;;;;;;;;;;;625:2070:15;;;;;;;;1269:4:24;625:2070:15;1269:4:24;625:2070:15;1269:4:24;;;;;;-1:-1:-1;1269:4:24;;;;;;12936:71:16;;;;;;;;-1:-1:-1;12936:71:16;;;;-1:-1:-1;;12936:71:16;;;;;;:::i;:::-;625:2070:15;12915:93:16;;12936:71;;12924:4;;12915:93;;1269:4:24;;;;;;;;:::i;:::-;625:2070:15;1269:4:24;;625:2070:15;1269:4:24;;;:::i;:::-;;;;-1:-1:-1;625:2070:15;1269:4:24;;;;12875:133:16;;1957:4377;;1269:4:24;625:2070:15;;1269:4:24;;;;;;625:2070:15;1269:4:24;;;-1:-1:-1;;1269:4:24;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;625:2070:15;1269:4:24;;;;625:2070:15;;1269:4:24;625:2070:15;1269:4:24;625:2070:15;;;;;;;1269:4:24;;;;:::i;:::-;;;;;;;;;12710:445:16;1269:4:24;625:2070:15;;;13113:27:16;;;;;;;625:2070:15;13113:27:16;625:2070:15;;-1:-1:-1;625:2070:15;;;;;-1:-1:-1;625:2070:15;1498:57;1539:16;625:2070;;1539:16;;;;1269:4:24;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;:::o;:::-;;625:2070:15;-1:-1:-1;;1269:4:24;625:2070:15;;1269:4:24;;;;;;;;;;;;;:::o;:::-;;;;;;625:2070:15;;-1:-1:-1;;625:2070:15;1269:4:24;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;625:2070:15;1269:4:24;625:2070:15;;1269:4:24;;;:::i;:::-;;;;;;;;;;;;;-1:-1:-1;1269:4:24;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;:::o;1177:::-;;;;;;;;;;:::o;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;625:2070:15;;;;1269:4:24;;1177;1269;;;;;;;;;;;;;1177;625:2070:15;;;1177:4:24;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;625:2070:15;;;1177:4:24;1269;;;;;;;;;;;1177;1269;;1177;1269;1177;1269;;1177;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;625:2070:15;1177:4:24;;;625:2070:15;:::i;:::-;1177:4:24;;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;:::o;1021:::-;625:2070:15;1021:4:24;625:2070:15;1021:4:24;;-1:-1:-1;;1021:4:24;625:2070:15;;;;;;1269:4:24;-1:-1:-1;1269:4:24;;;;;;625:2070:15;;1021:4:24;;;:::o;773:298:17:-;625:2070:15;;;;;247:1:17;851:33;;247:1;;625:2070:15;;247:1:17;625:2070:15;;900:15:17;:::o;847:218::-;936:35;;-1:-1:-1;1006:1:25;936:35:17;1006:1:25;;1002:4:17;;987:20;:::o;932:133::-;1038:16;:::o;625:2070:15:-;;;;;;;;;;;;;;;:::o;478:66:25:-;;;;;;;;625:2070:15;;478:66:25;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;1177:4:24;478:66:25;;;1177:4:24;478:66:25;;;1021:4:24;478:66:25;;;;1177:4:24;478:66:25;;;1021:4:24;625:2070:15;478:66:25;;;;625:2070:15;478:66:25;;;1177:4:24;478:66:25;;;;1177:4:24;;;;478:66:25;;;;;;;;1177:4:24;478:66:25;;;;;;1177:4:24;;;;;478:66:25;;;;;;1177:4:24;478:66:25;;;;:::o;625:2070:15:-;;;;;;;;;;;;:::o;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;1269:4:24;625:2070:15;;1269:4:24;;;:::i;:::-;625:2070:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;1177:4:24;;625:2070:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;666:10:25:-;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;3103:342:3;3218:221;3103:342;;;3218:221;;;;;;;3103:342::o;3218:221::-;;;;;;;11375:939;11502:806;11375:939;11502:806;11375:939;11502:806;;;;;;;;;;;;;;;;;;;;;;;;;;;;11375:939::o;11502:806::-;;;;;;

Swarm Source

ipfs://131bf048f3ec4b09c2413c5008eb92f93b7d457c2ca59f56ccdd2bb2ee4ddeac

Block Transaction Difficulty 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.