ETH Price: $3,219.44 (+4.18%)

Contract

0xED306e38BB930ec9646FF3D917B2e513a97530b1
 
Transaction Hash
Method
Block
From
To
Sell Order Swap216251182025-01-14 20:28:5930 mins ago1736886539IN
0xED306e38...3a97530b1
0 ETH0.004589166.88284976
Sell Order Swap216095612025-01-12 16:19:232 days ago1736698763IN
0xED306e38...3a97530b1
0.34503737 ETH0.000778473.16444124
Sell Order Swap216094332025-01-12 15:53:472 days ago1736697227IN
0xED306e38...3a97530b1
0 ETH0.001824352.94577776
Sell Order Swap216089162025-01-12 14:09:472 days ago1736690987IN
0xED306e38...3a97530b1
0 ETH0.000643153.4
Sell Order Swap216087882025-01-12 13:43:592 days ago1736689439IN
0xED306e38...3a97530b1
0 ETH0.000791482.54909264
Sell Order Swap215720192025-01-07 10:33:117 days ago1736245991IN
0xED306e38...3a97530b1
0 ETH0.001392416.66601577
Sell Order Swap215619842025-01-06 0:55:358 days ago1736124935IN
0xED306e38...3a97530b1
0 ETH0.003575818.5914273
Sell Order Swap215545142025-01-04 23:51:119 days ago1736034671IN
0xED306e38...3a97530b1
0 ETH0.001396515.68043856
Sell Order Swap215545062025-01-04 23:49:359 days ago1736034575IN
0xED306e38...3a97530b1
0 ETH0.000982836.00028146
Buy Order Swap215495652025-01-04 7:17:1110 days ago1735975031IN
0xED306e38...3a97530b1
0 ETH0.001926055.90644323
Sell Order Swap215440272025-01-03 12:42:2311 days ago1735908143IN
0xED306e38...3a97530b1
0 ETH0.005237689.89745646
Sell Order Swap215254342024-12-31 22:28:1113 days ago1735684091IN
0xED306e38...3a97530b1
0 ETH0.001860294.63291367
Sell Order Swap215240752024-12-31 17:55:2314 days ago1735667723IN
0xED306e38...3a97530b1
0.15 ETH0.0046186810.99825067
Sell Order Swap215166662024-12-30 17:04:3515 days ago1735578275IN
0xED306e38...3a97530b1
0 ETH0.0073392110.38193474
Sell Order Swap215101672024-12-29 19:17:5916 days ago1735499879IN
0xED306e38...3a97530b1
6.16778894 ETH0.003011645.85793455
Sell Order Swap215068242024-12-29 8:06:3516 days ago1735459595IN
0xED306e38...3a97530b1
0 ETH0.000562452.92118294
Sell Order Swap215066472024-12-29 7:31:1116 days ago1735457471IN
0xED306e38...3a97530b1
0 ETH0.000545592.9191882
Sell Order Swap215066142024-12-29 7:24:3516 days ago1735457075IN
0xED306e38...3a97530b1
0 ETH0.000830363.2118528
Sell Order Swap214998022024-12-28 8:34:5917 days ago1735374899IN
0xED306e38...3a97530b1
0 ETH0.001720733.59774822
Sell Order Swap214970192024-12-27 23:16:1117 days ago1735341371IN
0xED306e38...3a97530b1
0 ETH0.001159684.28073506
Sell Order Swap214890582024-12-26 20:34:3519 days ago1735245275IN
0xED306e38...3a97530b1
0.2 ETH0.001102625.52640769
Sell Order Swap214764552024-12-25 2:18:5920 days ago1735093139IN
0xED306e38...3a97530b1
0 ETH0.000772424.25194537
Sell Order Swap214685062024-12-23 23:37:4721 days ago1734997067IN
0xED306e38...3a97530b1
0 ETH0.006481379.83514682
Sell Order Swap214649222024-12-23 11:35:1122 days ago1734953711IN
0xED306e38...3a97530b1
0 ETH0.001371575.22648964
Sell Order Swap214534172024-12-21 20:58:4724 days ago1734814727IN
0xED306e38...3a97530b1
0.00075998 ETH0.001639556.74335479
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block
From
To
216095612025-01-12 16:19:232 days ago1736698763
0xED306e38...3a97530b1
0.34503737 ETH
216094332025-01-12 15:53:472 days ago1736697227
0xED306e38...3a97530b1
0.29903439 ETH
216094332025-01-12 15:53:472 days ago1736697227
0xED306e38...3a97530b1
0.29903439 ETH
215545142025-01-04 23:51:119 days ago1736034671
0xED306e38...3a97530b1
0.04909159 ETH
215545142025-01-04 23:51:119 days ago1736034671
0xED306e38...3a97530b1
0.04909159 ETH
215545062025-01-04 23:49:359 days ago1736034575
0xED306e38...3a97530b1
0.44521985 ETH
215545062025-01-04 23:49:359 days ago1736034575
0xED306e38...3a97530b1
0.44521985 ETH
215495652025-01-04 7:17:1110 days ago1735975031
0xED306e38...3a97530b1
0.03027412 ETH
215495652025-01-04 7:17:1110 days ago1735975031
0xED306e38...3a97530b1
0.03027412 ETH
215240752024-12-31 17:55:2314 days ago1735667723
0xED306e38...3a97530b1
0.15 ETH
215101672024-12-29 19:17:5916 days ago1735499879
0xED306e38...3a97530b1
6.16778894 ETH
215068242024-12-29 8:06:3516 days ago1735459595
0xED306e38...3a97530b1
0.0285071 ETH
215068242024-12-29 8:06:3516 days ago1735459595
0xED306e38...3a97530b1
0.0285071 ETH
215066472024-12-29 7:31:1116 days ago1735457471
0xED306e38...3a97530b1
0.0293861 ETH
215066472024-12-29 7:31:1116 days ago1735457471
0xED306e38...3a97530b1
0.0293861 ETH
214890582024-12-26 20:34:3519 days ago1735245275
0xED306e38...3a97530b1
0.2 ETH
214871492024-12-26 14:11:1119 days ago1735222271
0xED306e38...3a97530b1
0.37882736 ETH
214871492024-12-26 14:11:1119 days ago1735222271
0xED306e38...3a97530b1
0.37882736 ETH
214764552024-12-25 2:18:5920 days ago1735093139
0xED306e38...3a97530b1
0.05129378 ETH
214764552024-12-25 2:18:5920 days ago1735093139
0xED306e38...3a97530b1
0.05129378 ETH
214649222024-12-23 11:35:1122 days ago1734953711
0xED306e38...3a97530b1
0.20035662 ETH
214649222024-12-23 11:35:1122 days ago1734953711
0xED306e38...3a97530b1
0.20035662 ETH
214534172024-12-21 20:58:4724 days ago1734814727
0xED306e38...3a97530b1
0.5290609 ETH
214534172024-12-21 20:58:4724 days ago1734814727
0xED306e38...3a97530b1
0.52830091 ETH
214443842024-12-20 14:39:4725 days ago1734705587
0xED306e38...3a97530b1
20 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
UniversalPermit2Adapter

Compiler Version
v0.8.19+commit.7dd6d404

Optimization Enabled:
Yes with 10000 runs

Other Settings:
paris EvmVersion
File 1 of 18 : UniversalPermit2Adapter.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.8.0;

import { SimulationAdapter } from "@call-simulation/SimulationAdapter.sol";
// solhint-disable no-unused-import
import { BasePermit2Adapter, IPermit2, Token } from "./base/BasePermit2Adapter.sol";
import {
  IArbitraryExecutionPermit2Adapter,
  ArbitraryExecutionPermit2Adapter
} from "./base/ArbitraryExecutionPermit2Adapter.sol";
import { ISwapPermit2Adapter, SwapPermit2Adapter } from "./base/SwapPermit2Adapter.sol";
// solhint-enable no-unused-import

/**
 * @title Universal Permit2 Adapter
 * @author Sam Bugs
 * @notice This contracts adds Permit2 capabilities to existing contracts by acting as a proxy
 * @dev It's important to note that this contract should never hold any funds outside of the scope of a transaction,
 *      nor should it be granted "regular" ERC20 token approvals. This contract is meant to be used as a proxy, so
 *      the only tokens approved/transferred through Permit2 should be entirely spent in the same transaction.
 *      Any unspent allowance or remaining tokens on the contract can be transferred by anyone, so please be careful!
 */
contract UniversalPermit2Adapter is SimulationAdapter, SwapPermit2Adapter, ArbitraryExecutionPermit2Adapter {
  constructor(IPermit2 _permit2) BasePermit2Adapter(_permit2) { }
}

File 2 of 18 : SimulationAdapter.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.8.0;

import { IERC165 } from "./interfaces/external/IERC165.sol";
import { ISimulationAdapter } from "./interfaces/ISimulationAdapter.sol";

/**
 * @title Simulation Adapter
 * @author Sam Bugs
 * @notice This contracts adds off-chain simulation capabilities to existing contracts. It works similarly to a
 *         multicall, but the state is not modified in each subcall.
 */
abstract contract SimulationAdapter is IERC165, ISimulationAdapter {
  /// @notice An error that contains a simulation's result
  error SimulatedCall(SimulationResult result);

  /// @inheritdoc IERC165
  function supportsInterface(bytes4 _interfaceId) public view virtual override returns (bool) {
    return _interfaceId == type(ISimulationAdapter).interfaceId || _interfaceId == type(IERC165).interfaceId;
  }

  /// @inheritdoc ISimulationAdapter
  function simulate(bytes[] calldata _calls) external payable returns (SimulationResult[] memory _results) {
    _results = new SimulationResult[](_calls.length);
    for (uint256 i = 0; i < _calls.length; i++) {
      _results[i] = _simulate(_calls[i]);
    }
    return _results;
  }

  /**
   * @notice Executes a simulation and returns the result
   * @param _call The call to simulate
   * @return _simulationResult The simulation's result
   */
  function _simulate(bytes calldata _call) internal returns (SimulationResult memory _simulationResult) {
    (bool _success, bytes memory _result) =
    // solhint-disable-next-line avoid-low-level-calls
     address(this).delegatecall(abi.encodeWithSelector(this.simulateAndRevert.selector, _call));
    require(!_success, "WTF? Should have failed!");
    // Move pointer to ignore selector
    // solhint-disable-next-line no-inline-assembly
    assembly {
      _result := add(_result, 0x04)
    }
    (_simulationResult) = abi.decode(_result, (SimulationResult));
  }

  /**
   * @notice Executes a call agains this contract and reverts with the result
   * @dev This is meant to be used internally, do not call!
   * @param _call The call to simulate
   */
  function simulateAndRevert(bytes calldata _call) external payable {
    uint256 _gasAtStart = gasleft();
    // solhint-disable-next-line avoid-low-level-calls
    (bool _success, bytes memory _result) = address(this).delegatecall(_call);
    uint256 _gasSpent = _gasAtStart - gasleft();
    revert SimulatedCall(SimulationResult({ success: _success, result: _result, gasSpent: _gasSpent }));
  }
}

File 3 of 18 : ISimulationAdapter.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.8.0;

interface ISimulationAdapter {
  /// @notice A simulation's result
  struct SimulationResult {
    bool success;
    bytes result;
    uint256 gasSpent;
  }

  /**
   * @notice Executes individual simulations against this contract but doesn't modify the state when doing so
   * @dev This function is meant to be used for off-chain simulation and should not be called on-chain
   * @param calls The calls to simulate
   * @return results Each simulation result
   */
  function simulate(bytes[] calldata calls) external payable returns (SimulationResult[] memory results);
}

File 4 of 18 : IERC165.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.8.0;

interface IERC165 {
  /**
   * @dev Returns true if this contract implements the interface defined by
   * `interfaceId`. See the corresponding
   * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
   * to learn more about how these ids are created.
   *
   * This function call must use less than 30 000 gas.
   */
  function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

File 5 of 18 : ArbitraryExecutionPermit2Adapter.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.8.0;

// solhint-disable-next-line no-unused-import
import { Permit2Transfers, IPermit2 } from "../libraries/Permit2Transfers.sol";
import { Token, IERC20 } from "../libraries/Token.sol";
import { IArbitraryExecutionPermit2Adapter } from "../interfaces/IArbitraryExecutionPermit2Adapter.sol";
import { BasePermit2Adapter } from "./BasePermit2Adapter.sol";

/**
 * @title Arbitrary Execution Permit2 Adapter
 * @author Sam Bugs
 * @notice This contracts adds Permit2 capabilities to existing contracts by acting as a proxy
 * @dev It's important to note that this contract should never hold any funds outside of the scope of a transaction,
 *      nor should it be granted "regular" ERC20 token approvals. This contract is meant to be used as a proxy, so
 *      the only tokens approved/transferred through Permit2 should be entirely spent in the same transaction.
 *      Any unspent allowance or remaining tokens on the contract can be transferred by anyone, so please be careful!
 */
abstract contract ArbitraryExecutionPermit2Adapter is BasePermit2Adapter, IArbitraryExecutionPermit2Adapter {
  using Permit2Transfers for IPermit2;
  using Token for address;
  using Token for IERC20;

  /// @inheritdoc IArbitraryExecutionPermit2Adapter
  function executeWithPermit(
    SinglePermit calldata _permit,
    AllowanceTarget[] calldata _allowanceTargets,
    ContractCall[] calldata _contractCalls,
    TransferOut[] calldata _transferOut,
    uint256 _deadline
  )
    external
    payable
    checkDeadline(_deadline)
    returns (bytes[] memory _executionResults, uint256[] memory _tokenBalances)
  {
    PERMIT2.takeFromCaller(_permit.token, _permit.amount, _permit.nonce, _deadline, _permit.signature);
    return _approveExecuteAndTransfer(_allowanceTargets, _contractCalls, _transferOut);
  }

  /// @inheritdoc IArbitraryExecutionPermit2Adapter
  function executeWithBatchPermit(
    BatchPermit calldata _batchPermit,
    AllowanceTarget[] calldata _allowanceTargets,
    ContractCall[] calldata _contractCalls,
    TransferOut[] calldata _transferOut,
    uint256 _deadline
  )
    external
    payable
    checkDeadline(_deadline)
    returns (bytes[] memory _executionResults, uint256[] memory _tokenBalances)
  {
    PERMIT2.batchTakeFromCaller(_batchPermit.tokens, _batchPermit.nonce, _deadline, _batchPermit.signature);
    return _approveExecuteAndTransfer(_allowanceTargets, _contractCalls, _transferOut);
  }

  function _approveExecuteAndTransfer(
    AllowanceTarget[] calldata _allowanceTargets,
    ContractCall[] calldata _contractCalls,
    TransferOut[] calldata _transferOut
  )
    internal
    returns (bytes[] memory _executionResults, uint256[] memory _tokenBalances)
  {
    // Approve targets
    for (uint256 i; i < _allowanceTargets.length;) {
      IERC20(_allowanceTargets[i].token).maxApprove(_allowanceTargets[i].allowanceTarget);
      unchecked {
        ++i;
      }
    }

    // Call contracts
    _executionResults = new bytes[](_contractCalls.length);
    for (uint256 i; i < _contractCalls.length;) {
      _executionResults[i] = _callContract(_contractCalls[i].target, _contractCalls[i].data, _contractCalls[i].value);
      unchecked {
        ++i;
      }
    }

    // Reset allowance to prevent attacks. Also, we are setting it to 1 instead of 0 for gas optimization
    for (uint256 i; i < _allowanceTargets.length;) {
      IERC20(_allowanceTargets[i].token).setAllowance(_allowanceTargets[i].allowanceTarget, 1);
      unchecked {
        ++i;
      }
    }

    // Distribute tokens
    _tokenBalances = new uint256[](_transferOut.length);
    for (uint256 i; i < _transferOut.length;) {
      _tokenBalances[i] = _transferOut[i].token.distributeTo(_transferOut[i].distribution);
      unchecked {
        ++i;
      }
    }
  }
}

File 6 of 18 : BasePermit2Adapter.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.8.0;

import { Address } from "@openzeppelin/contracts/utils/Address.sol";
import { IERC1271 } from "@openzeppelin/contracts/interfaces/IERC1271.sol";
import { IBasePermit2Adapter, IPermit2 } from "../interfaces/IBasePermit2Adapter.sol";
import { Token } from "../libraries/Token.sol";

/**
 * @title Base Permit2 Adapter
 * @author Sam Bugs
 * @notice The base contract for Permit2 adapters
 */
abstract contract BasePermit2Adapter is IBasePermit2Adapter, IERC1271 {
  using Address for address;

  /// @inheritdoc IBasePermit2Adapter
  address public constant NATIVE_TOKEN = Token.NATIVE_TOKEN;
  /// @inheritdoc IBasePermit2Adapter
  // solhint-disable-next-line var-name-mixedcase
  IPermit2 public immutable PERMIT2;

  bytes4 private constant MAGIC_WORD = IERC1271.isValidSignature.selector;

  constructor(IPermit2 _permit2) {
    PERMIT2 = _permit2;
  }

  // solhint-disable-next-line no-empty-blocks
  receive() external payable { }

  function isValidSignature(bytes32, bytes memory) external view returns (bytes4 magicValue) {
    // Note: both swap and arbitrary adapters support approving tokens for other addresses, for integrations to work. The
    //       thing is that sometimes, these third party contracts use Permit2 instead of using ERC20's transfer from.
    //       When that happens, the allowance target will need to be the Permit2 contract, and then Permit2 will call
    //       this function to make sure we authorize the  extraction of tokens. Since this contract is not meant to hold
    //       any funds outside of the scope of a swap or arbitrary execution, we'll allow it
    return msg.sender == address(PERMIT2) ? MAGIC_WORD : bytes4(0);
  }

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

  function _callContract(address _target, bytes calldata _data, uint256 _value) internal returns (bytes memory _result) {
    if (_target == address(PERMIT2)) revert InvalidContractCall();
    return _target.functionCallWithValue(_data, _value);
  }
}

File 7 of 18 : SwapPermit2Adapter.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.8.0;

// solhint-disable-next-line no-unused-import
import { Permit2Transfers, IPermit2 } from "../libraries/Permit2Transfers.sol";
import { Token } from "../libraries/Token.sol";
import { ISwapPermit2Adapter } from "../interfaces/ISwapPermit2Adapter.sol";
import { BasePermit2Adapter } from "./BasePermit2Adapter.sol";

/**
 * @title Swap Permit2 Adapter
 * @author Sam Bugs
 * @notice This contracts adds Permit2 capabilities to existing token swap contracts by acting as a proxy. It performs
 *         some extra checks to guarantee that the minimum amounts are respected
 * @dev It's important to note that this contract should never hold any funds outside of the scope of a transaction,
 *      nor should it be granted "regular" ERC20 token approvals. This contract is meant to be used as a proxy, so
 *      the only tokens approved/transferred through Permit2 should be entirely spent in the same transaction.
 *      Any unspent allowance or remaining tokens on the contract can be transferred by anyone, so please be careful!
 */
abstract contract SwapPermit2Adapter is BasePermit2Adapter, ISwapPermit2Adapter {
  using Permit2Transfers for IPermit2;
  using Token for address;

  /// @inheritdoc ISwapPermit2Adapter
  function sellOrderSwap(SellOrderSwapParams calldata _params)
    public
    payable
    checkDeadline(_params.deadline)
    returns (uint256 _amountIn, uint256 _amountOut)
  {
    // Take from caller
    PERMIT2.takeFromCaller(_params.tokenIn, _params.amountIn, _params.nonce, _params.deadline, _params.signature);

    // Max approve token in
    _params.tokenIn.maxApproveIfNecessary(_params.allowanceTarget);

    // Execute swap
    uint256 _value = _params.tokenIn == Token.NATIVE_TOKEN ? _params.amountIn : 0;
    _callContract(_params.swapper, _params.swapData, _value);

    // Distribute token out
    _amountOut = _params.tokenOut.distributeTo(_params.transferOut);

    // Check min amount
    if (_amountOut < _params.minAmountOut) revert ReceivedTooLittleTokenOut(_amountOut, _params.minAmountOut);

    // Reset allowance
    _params.tokenIn.setAllowanceIfNecessary(_params.allowanceTarget, 1);

    // Set amount in
    _amountIn = _params.amountIn;

    // Emit event
    emit Swapped({
      caller: msg.sender,
      swapType: SwapType.Sell,
      tokenIn: _params.tokenIn,
      tokenOut: _params.tokenOut,
      amountIn: _params.amountIn,
      amountOut: _amountOut,
      swapper: _params.swapper,
      misc: _params.misc
    });
  }

  /// @inheritdoc ISwapPermit2Adapter
  function buyOrderSwap(BuyOrderSwapParams calldata _params)
    public
    payable
    checkDeadline(_params.deadline)
    returns (uint256 _amountIn, uint256 _amountOut)
  {
    // Take from caller
    PERMIT2.takeFromCaller(_params.tokenIn, _params.maxAmountIn, _params.nonce, _params.deadline, _params.signature);

    // Max approve token in
    _params.tokenIn.maxApproveIfNecessary(_params.allowanceTarget);

    // Execute swap
    uint256 _value = _params.tokenIn == Token.NATIVE_TOKEN ? _params.maxAmountIn : 0;
    _callContract(_params.swapper, _params.swapData, _value);

    // Check balance for unspent tokens
    uint256 _unspentTokenIn = _params.tokenIn.balanceOnContract();

    // Distribute token out
    _amountOut = _params.tokenOut.distributeTo(_params.transferOut);

    // Check min amount
    if (_amountOut < _params.amountOut) revert ReceivedTooLittleTokenOut(_amountOut, _params.amountOut);

    // Send unspent to the set recipient
    _params.tokenIn.sendAmountTo(_unspentTokenIn, _params.unspentTokenInRecipient);

    // Reset allowance
    _params.tokenIn.setAllowanceIfNecessary(_params.allowanceTarget, 1);

    // Set amount in
    _amountIn = _params.maxAmountIn - _unspentTokenIn;

    // Emit event
    emit Swapped({
      caller: msg.sender,
      swapType: SwapType.Buy,
      tokenIn: _params.tokenIn,
      tokenOut: _params.tokenOut,
      amountIn: _amountIn,
      amountOut: _amountOut,
      swapper: _params.swapper,
      misc: _params.misc
    });
  }
}

File 8 of 18 : IArbitraryExecutionPermit2Adapter.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.8.0;

import { Token } from "../libraries/Token.sol";
import { IBasePermit2Adapter, IPermit2 } from "./IBasePermit2Adapter.sol";

interface IArbitraryExecutionPermit2Adapter is IBasePermit2Adapter {
  /// @notice Data necessary to execute a single permit transfer
  struct SinglePermit {
    address token;
    uint256 amount;
    uint256 nonce;
    bytes signature;
  }

  /// @notice Data necessary to execute a batch permit transfer
  struct BatchPermit {
    IPermit2.TokenPermissions[] tokens;
    uint256 nonce;
    bytes signature;
  }

  /// @notice Allowance target for a specific token
  struct AllowanceTarget {
    address token;
    address allowanceTarget;
  }

  /// @notice A specific contract call
  struct ContractCall {
    address target;
    bytes data;
    uint256 value;
  }

  /// @notice A token and how to distribute it
  struct TransferOut {
    address token;
    Token.DistributionTarget[] distribution;
  }

  /**
   * @notice Executes arbitrary calls by proxing to another contracts, but using Permit2 to transfer tokens from the
   *         caller
   * @param permit The permit data to use to transfer tokens from the user
   * @param allowanceTargets The contracts to approve before executing calls
   * @param contractCalls The calls to execute
   * @param transferOut The tokens to transfer out of our contract after all calls have been executed. Note that each
   *                    element of the array should handle different tokens
   * @param deadline The max time where this call can be executed
   * @return executionResults The results of each contract call
   * @return tokenBalances The balances held by the contract after contract calls were executed
   */
  function executeWithPermit(
    SinglePermit calldata permit,
    AllowanceTarget[] calldata allowanceTargets,
    ContractCall[] calldata contractCalls,
    TransferOut[] calldata transferOut,
    uint256 deadline
  )
    external
    payable
    returns (bytes[] memory executionResults, uint256[] memory tokenBalances);

  /**
   * @notice Executes arbitrary calls by proxing to another contracts, but using Permit2 to transfer tokens from the
   *         caller
   * @param batchPermit The permit data to use to batch transfer tokens from the user
   * @param allowanceTargets The contracts to approve before executing calls
   * @param contractCalls The calls to execute
   * @param transferOut The tokens to transfer out of our contract after all calls have been executed
   * @param deadline The max time where this call can be executed
   * @return executionResults The results of each contract call
   * @return tokenBalances The balances held by the contract after contract calls were executed
   */
  function executeWithBatchPermit(
    BatchPermit calldata batchPermit,
    AllowanceTarget[] calldata allowanceTargets,
    ContractCall[] calldata contractCalls,
    TransferOut[] calldata transferOut,
    uint256 deadline
  )
    external
    payable
    returns (bytes[] memory executionResults, uint256[] memory tokenBalances);
}

File 9 of 18 : IBasePermit2Adapter.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.8.0;

import { IPermit2 } from "./external/IPermit2.sol";

/// @notice The interface all Permit2 adapters should implement
interface IBasePermit2Adapter {
  /// @notice Thrown when the user tries to execute an invalid contract call
  error InvalidContractCall();

  /**
   * @notice Thrown when a transaction deadline has passed
   * @param current The current time
   * @param deadline The set deadline
   */
  error TransactionDeadlinePassed(uint256 current, uint256 deadline);

  /**
   * @notice Returns the address that represents the native token
   * @dev This value is constant and cannot change
   * @return The address that represents the native token
   */
  function NATIVE_TOKEN() external view returns (address);

  /**
   * @notice Returns the address of the Permit2 contract
   * @dev This value is constant and cannot change
   * @return The address of the Permit2 contract
   */
  function PERMIT2() external view returns (IPermit2);
}

File 10 of 18 : ISwapPermit2Adapter.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.8.0;

import { Token } from "../libraries/Token.sol";
import { IBasePermit2Adapter } from "./IBasePermit2Adapter.sol";

interface ISwapPermit2Adapter is IBasePermit2Adapter {
  /**
   * @notice Thrown when the swap produced less token out than expected
   * @param received The amount of token out received
   * @param expected The amount of token out expected
   */
  error ReceivedTooLittleTokenOut(uint256 received, uint256 expected);

  /**
   * @notice Emitted when a swap ocurrs
   * @param caller The swap caller
   * @param swapType The swap type, 'buy' or 'sell'
   * @param tokenIn The token swapped
   * @param tokenOut The token received
   * @param amountIn The amount of token in swapped
   * @param amountOut The amount of token out received
   * @param swapper The aggregator address
   * @param misc Misc bytes
   */
  event Swapped(
    address caller,
    SwapType swapType,
    address tokenIn,
    address tokenOut,
    uint256 amountIn,
    uint256 amountOut,
    address swapper,
    bytes misc
  );

  /// @notice Swap params for a sell order
  struct SellOrderSwapParams {
    // Deadline
    uint256 deadline;
    // Take from caller
    address tokenIn;
    uint256 amountIn;
    uint256 nonce;
    bytes signature;
    // Swap approval
    address allowanceTarget;
    // Swap execution
    address swapper;
    bytes swapData;
    // Swap validation
    address tokenOut;
    uint256 minAmountOut;
    // Transfer token out
    Token.DistributionTarget[] transferOut;
    bytes misc;
  }

  // @notice Swap params for a buy order
  struct BuyOrderSwapParams {
    // Deadline
    uint256 deadline;
    // Take from caller
    address tokenIn;
    uint256 maxAmountIn;
    uint256 nonce;
    bytes signature;
    // Swap approval
    address allowanceTarget;
    // Swap execution
    address swapper;
    bytes swapData;
    // Swap validation
    address tokenOut;
    uint256 amountOut;
    // Transfer token out
    Token.DistributionTarget[] transferOut;
    // Transfer token in
    address unspentTokenInRecipient;
    bytes misc;
  }

  enum SwapType {
    Buy,
    Sell
  }

  /**
   * @notice Executes a sell order swap by proxing to another contract, but using Permit2 to transfer tokens from the
   * caller
   * @param params The swap's data, such as tokens, amounts, recipient, etc
   * @return amountIn The amount ot `token in` spent on the swap
   * @return amountOut The amount of `token out` produced by the proxied swap
   */
  function sellOrderSwap(SellOrderSwapParams calldata params)
    external
    payable
    returns (uint256 amountIn, uint256 amountOut);

  /**
   * @notice Executes a buy order swap by proxing to another contract, but using Permit2 to transfer tokens from the
   * caller
   * @param params The swap's data, such as tokens, amounts, recipient, etc
   * @return amountIn The amount ot `token in` spent on the swap
   * @return amountOut The amount of `token out` produced by the proxied swap
   */
  function buyOrderSwap(BuyOrderSwapParams calldata params)
    external
    payable
    returns (uint256 amountIn, uint256 amountOut);
}

File 11 of 18 : IPermit2.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.8.0;

// Minimal Permit2 interface, derived from
// https://github.com/Uniswap/permit2/blob/main/src/interfaces/ISignatureTransfer.sol
interface IPermit2 {
  struct TokenPermissions {
    address token;
    uint256 amount;
  }

  struct PermitTransferFrom {
    TokenPermissions permitted;
    uint256 nonce;
    uint256 deadline;
  }

  struct PermitBatchTransferFrom {
    TokenPermissions[] permitted;
    uint256 nonce;
    uint256 deadline;
  }

  struct SignatureTransferDetails {
    address to;
    uint256 requestedAmount;
  }

  function DOMAIN_SEPARATOR() external view returns (bytes32);

  function permitTransferFrom(
    PermitTransferFrom calldata permit,
    SignatureTransferDetails calldata transferDetails,
    address owner,
    bytes calldata signature
  )
    external;

  function permitTransferFrom(
    PermitBatchTransferFrom memory permit,
    SignatureTransferDetails[] calldata transferDetails,
    address owner,
    bytes calldata signature
  )
    external;
}

File 12 of 18 : Permit2Transfers.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.8.0;

import { IPermit2 } from "../interfaces/external/IPermit2.sol";
import { Token } from "./Token.sol";

/**
 * @title Permit2 Transfers Library
 * @author Sam Bugs
 * @notice A small library to call Permit2's transfer from methods
 */
library Permit2Transfers {
  /**
   * @notice Executes a transfer from using Permit2
   * @param _permit2 The Permit2 contract
   * @param _token The token to transfer
   * @param _amount The amount to transfer
   * @param _nonce The owner's nonce
   * @param _deadline The signature's expiration deadline
   * @param _signature The signature that allows the transfer
   */
  function takeFromCaller(
    IPermit2 _permit2,
    address _token,
    uint256 _amount,
    uint256 _nonce,
    uint256 _deadline,
    bytes calldata _signature
  )
    internal
  {
    if (_signature.length > 0) {
      _permit2.permitTransferFrom(
        // The permit message.
        IPermit2.PermitTransferFrom({
          permitted: IPermit2.TokenPermissions({ token: _token, amount: _amount }),
          nonce: _nonce,
          deadline: _deadline
        }),
        // The transfer recipient and amount.
        IPermit2.SignatureTransferDetails({ to: address(this), requestedAmount: _amount }),
        // The owner of the tokens, which must also be
        // the signer of the message, otherwise this call
        // will fail.
        msg.sender,
        // The packed signature that was the result of signing
        // the EIP712 hash of `permit`.
        _signature
      );
    }
  }

  /**
   * @notice Executes a batch transfer from using Permit2
   * @param _permit2 The Permit2 contract
   * @param _tokens The amount of tokens to transfer
   * @param _nonce The owner's nonce
   * @param _deadline The signature's expiration deadline
   * @param _signature The signature that allows the transfer
   */
  function batchTakeFromCaller(
    IPermit2 _permit2,
    IPermit2.TokenPermissions[] calldata _tokens,
    uint256 _nonce,
    uint256 _deadline,
    bytes calldata _signature
  )
    internal
  {
    if (_tokens.length > 0) {
      _permit2.permitTransferFrom(
        // The permit message.
        IPermit2.PermitBatchTransferFrom({ permitted: _tokens, nonce: _nonce, deadline: _deadline }),
        // The transfer recipients and amounts.
        _buildTransferDetails(_tokens),
        // The owner of the tokens, which must also be
        // the signer of the message, otherwise this call
        // will fail.
        msg.sender,
        // The packed signature that was the result of signing
        // the EIP712 hash of `permit`.
        _signature
      );
    }
  }

  function _buildTransferDetails(IPermit2.TokenPermissions[] calldata _tokens)
    private
    view
    returns (IPermit2.SignatureTransferDetails[] memory _details)
  {
    _details = new IPermit2.SignatureTransferDetails[](_tokens.length);
    for (uint256 i; i < _details.length;) {
      _details[i] = IPermit2.SignatureTransferDetails({ to: address(this), requestedAmount: _tokens[i].amount });
      unchecked {
        ++i;
      }
    }
  }
}

File 13 of 18 : Token.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.8.0;

import { SafeERC20, IERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { Address } from "@openzeppelin/contracts/utils/Address.sol";

/**
 * @title Token Library
 * @author Sam Bugs
 * @notice A small library that contains helpers for tokens (both ERC20 and native)
 */
library Token {
  using SafeERC20 for IERC20;
  using Address for address payable;
  using Address for address;

  /// @notice A specific target to distribute tokens to
  struct DistributionTarget {
    address recipient;
    uint256 shareBps;
  }

  address public constant NATIVE_TOKEN = address(0);

  /**
   * @notice Calculates the amount of token balance held by the contract
   * @param _token The token to check
   * @return _balance The current balance held by the contract
   */
  function balanceOnContract(address _token) internal view returns (uint256 _balance) {
    return _token == NATIVE_TOKEN ? address(this).balance : IERC20(_token).balanceOf(address(this));
  }

  /**
   * @notice Performs a max approval to the allowance target, for the given token
   * @param _token The token to approve
   * @param _allowanceTarget The spender that will be approved
   */
  function maxApprove(IERC20 _token, address _allowanceTarget) internal {
    setAllowance(_token, _allowanceTarget, type(uint256).max);
  }

  /**
   * @notice Performs an approval to the allowance target, for the given token and amount
   * @param _token The token to approve
   * @param _allowanceTarget The spender that will be approved
   * @param _amount The allowance to set
   */
  function setAllowance(IERC20 _token, address _allowanceTarget, uint256 _amount) internal {
    // This helper should handle cases like USDT. Thanks OZ!
    _token.forceApprove(_allowanceTarget, _amount);
  }

  /**
   * @notice Performs a max approval to the allowance target for the given token, as long as the token is not
   *         the native token, and the allowance target is not the zero address
   * @param _token The token to approve
   * @param _allowanceTarget The spender that will be approved
   */
  function maxApproveIfNecessary(address _token, address _allowanceTarget) internal {
    setAllowanceIfNecessary(_token, _allowanceTarget, type(uint256).max);
  }

  /**
   * @notice Performs an approval to the allowance target for the given token and amount, as long as the token is not
   *         the native token, and the allowance target is not the zero address
   * @param _token The token to approve
   * @param _allowanceTarget The spender that will be approved
   * @param _amount The allowance to set
   */
  function setAllowanceIfNecessary(address _token, address _allowanceTarget, uint256 _amount) internal {
    if (_token != NATIVE_TOKEN && _allowanceTarget != address(0)) {
      setAllowance(IERC20(_token), _allowanceTarget, _amount);
    }
  }

  /**
   * @notice Distributes the available amount of the given token according to the set distribution. All tokens
   *         will be distributed according to the configured shares. The last target will get sent all unassigned
   *         tokens
   * @param _token The token to distribute
   * @param _distribution How to distribute the available amount of the token. Must have at least one target
   */
  function distributeTo(
    address _token,
    DistributionTarget[] calldata _distribution
  )
    internal
    returns (uint256 _available)
  {
    _available = balanceOnContract(_token);
    uint256 _amountLeft = _available;

    // Distribute amounts
    for (uint256 i; i < _distribution.length - 1;) {
      uint256 _toSend = _available * _distribution[i].shareBps / 10_000;
      sendAmountTo(_token, _toSend, _distribution[i].recipient);
      _amountLeft -= _toSend;
      unchecked {
        ++i;
      }
    }

    // Send amount left to the last recipient
    sendAmountTo(_token, _amountLeft, _distribution[_distribution.length - 1].recipient);
  }

  /**
   * @notice Checks if the contract has any balance of the given token, and if it does,
   *         it sends it to the given recipient
   * @param _token The token to check
   * @param _recipient The recipient of the token balance
   * @return _balance The current balance held by the contract
   */
  function sendBalanceOnContractTo(address _token, address _recipient) internal returns (uint256 _balance) {
    _balance = balanceOnContract(_token);
    sendAmountTo(_token, _balance, _recipient);
  }

  /**
   * @notice Transfers the given amount of tokens from the contract to the recipient
   * @param _token The token to check
   * @param _amount The amount to send
   * @param _recipient The recipient
   */
  function sendAmountTo(address _token, uint256 _amount, address _recipient) internal {
    if (_amount > 0) {
      if (_recipient == address(0)) _recipient = msg.sender;
      if (_token == NATIVE_TOKEN) {
        payable(_recipient).sendValue(_amount);
      } else {
        IERC20(_token).safeTransfer(_recipient, _amount);
      }
    }
  }
}

File 14 of 18 : IERC1271.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1271.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC1271 standard signature validation method for
 * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271].
 *
 * _Available since v4.1._
 */
interface IERC1271 {
    /**
     * @dev Should return whether the signature provided is valid for the provided data
     * @param hash      Hash of the data to be signed
     * @param signature Signature byte array associated with _data
     */
    function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue);
}

File 15 of 18 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
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 amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

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

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

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

File 16 of 18 : IERC20Permit.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 */
interface IERC20Permit {
    /**
     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
     * given ``owner``'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @dev Returns the current nonce for `owner`. This value must be
     * included whenever a signature is generated for {permit}.
     *
     * Every successful call to {permit} increases ``owner``'s nonce by one. This
     * prevents a signature from being used multiple times.
     */
    function nonces(address owner) external view returns (uint256);

    /**
     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}

File 17 of 18 : SafeERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.0;

import "../IERC20.sol";
import "../extensions/IERC20Permit.sol";
import "../../../utils/Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using Address for address;

    /**
     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    /**
     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
     */
    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(IERC20 token, address spender, uint256 value) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        require(
            (value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    /**
     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 oldAllowance = token.allowance(address(this), spender);
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
    }

    /**
     * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        unchecked {
            uint256 oldAllowance = token.allowance(address(this), spender);
            require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
        }
    }

    /**
     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
     * to be set to zero before setting it to a non-zero value, such as USDT.
     */
    function forceApprove(IERC20 token, address spender, uint256 value) internal {
        bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);

        if (!_callOptionalReturnBool(token, approvalCall)) {
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
            _callOptionalReturn(token, approvalCall);
        }
    }

    /**
     * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.
     * Revert on invalid signature.
     */
    function safePermit(
        IERC20Permit token,
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal {
        uint256 nonceBefore = token.nonces(owner);
        token.permit(owner, spender, value, deadline, v, r, s);
        uint256 nonceAfter = token.nonces(owner);
        require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     *
     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
     */
    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
        // and not revert is the subcall reverts.

        (bool success, bytes memory returndata) = address(token).call(data);
        return
            success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
    }
}

File 18 of 18 : Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     *
     * Furthermore, `isContract` will also return true if the target contract within
     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
     * which only has an effect at the end of a transaction.
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
     *
     * _Available since v4.8._
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        if (success) {
            if (returndata.length == 0) {
                // only check isContract if the call was successful and the return data is empty
                // otherwise we already know that it was a contract
                require(isContract(target), "Address: call to non-contract");
            }
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason or using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    function _revert(bytes memory returndata, string memory errorMessage) private pure {
        // Look for revert reason and bubble it up if present
        if (returndata.length > 0) {
            // The easiest way to bubble the revert reason is using memory via assembly
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert(errorMessage);
        }
    }
}

Settings
{
  "viaIR": false,
  "optimizer": {
    "runs": 10000,
    "enabled": true
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "none",
    "appendCBOR": false
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "paris",
  "libraries": {},
  "remappings": [
    "@mean-finance/oracles/=node_modules/@mean-finance/oracles/",
    "@mean-finance/nft-descriptors/=node_modules/@mean-finance/nft-descriptors/",
    "@mean-finance/call-simulation/contracts/=node_modules/@mean-finance/call-simulation/src/",
    "@mean-finance/swappers/=node_modules/@mean-finance/swappers/",
    "@mean-finance/dca-v2-core/=node_modules/@mean-finance/dca-v2-core/",
    "@mean-finance/permit2-adapter/=node_modules/@mean-finance/permit2-adapter/src/",
    "@mean-finance/transformers/=node_modules/@mean-finance/transformers/",
    "@mean-finance/uniswap-v3-oracle/=node_modules/@mean-finance/uniswap-v3-oracle/",
    "@call-simulation/=node_modules/@mean-finance/call-simulation/src/",
    "@chainlink/=node_modules/@chainlink/",
    "@openzeppelin/=node_modules/@openzeppelin/",
    "@api3/=node_modules/@api3/",
    "@uniswap/=node_modules/@uniswap/",
    "keep3r-v2/=node_modules/keep3r-v2/",
    "base64-sol/=node_modules/base64-sol/",
    "@sphinx-labs/contracts/=lib/sphinx/packages/contracts/contracts/foundry/",
    "forge-std/=lib/forge-std/src/",
    "@rari-capital/solmate/=lib/solmate/",
    "ds-test/=lib/solmate/lib/ds-test/src/",
    "solmate/=lib/solmate/src/",
    "sphinx/=lib/sphinx/packages/contracts/contracts/forge-std/src/"
  ]
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"contract IPermit2","name":"_permit2","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InvalidContractCall","type":"error"},{"inputs":[{"internalType":"uint256","name":"received","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"ReceivedTooLittleTokenOut","type":"error"},{"inputs":[{"components":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"bytes","name":"result","type":"bytes"},{"internalType":"uint256","name":"gasSpent","type":"uint256"}],"internalType":"struct ISimulationAdapter.SimulationResult","name":"result","type":"tuple"}],"name":"SimulatedCall","type":"error"},{"inputs":[{"internalType":"uint256","name":"current","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"TransactionDeadlinePassed","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"enum ISwapPermit2Adapter.SwapType","name":"swapType","type":"uint8"},{"indexed":false,"internalType":"address","name":"tokenIn","type":"address"},{"indexed":false,"internalType":"address","name":"tokenOut","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOut","type":"uint256"},{"indexed":false,"internalType":"address","name":"swapper","type":"address"},{"indexed":false,"internalType":"bytes","name":"misc","type":"bytes"}],"name":"Swapped","type":"event"},{"inputs":[],"name":"NATIVE_TOKEN","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERMIT2","outputs":[{"internalType":"contract IPermit2","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"maxAmountIn","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"address","name":"allowanceTarget","type":"address"},{"internalType":"address","name":"swapper","type":"address"},{"internalType":"bytes","name":"swapData","type":"bytes"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"components":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"shareBps","type":"uint256"}],"internalType":"struct Token.DistributionTarget[]","name":"transferOut","type":"tuple[]"},{"internalType":"address","name":"unspentTokenInRecipient","type":"address"},{"internalType":"bytes","name":"misc","type":"bytes"}],"internalType":"struct ISwapPermit2Adapter.BuyOrderSwapParams","name":"_params","type":"tuple"}],"name":"buyOrderSwap","outputs":[{"internalType":"uint256","name":"_amountIn","type":"uint256"},{"internalType":"uint256","name":"_amountOut","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct IPermit2.TokenPermissions[]","name":"tokens","type":"tuple[]"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct IArbitraryExecutionPermit2Adapter.BatchPermit","name":"_batchPermit","type":"tuple"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"allowanceTarget","type":"address"}],"internalType":"struct IArbitraryExecutionPermit2Adapter.AllowanceTarget[]","name":"_allowanceTargets","type":"tuple[]"},{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct IArbitraryExecutionPermit2Adapter.ContractCall[]","name":"_contractCalls","type":"tuple[]"},{"components":[{"internalType":"address","name":"token","type":"address"},{"components":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"shareBps","type":"uint256"}],"internalType":"struct Token.DistributionTarget[]","name":"distribution","type":"tuple[]"}],"internalType":"struct IArbitraryExecutionPermit2Adapter.TransferOut[]","name":"_transferOut","type":"tuple[]"},{"internalType":"uint256","name":"_deadline","type":"uint256"}],"name":"executeWithBatchPermit","outputs":[{"internalType":"bytes[]","name":"_executionResults","type":"bytes[]"},{"internalType":"uint256[]","name":"_tokenBalances","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct IArbitraryExecutionPermit2Adapter.SinglePermit","name":"_permit","type":"tuple"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"allowanceTarget","type":"address"}],"internalType":"struct IArbitraryExecutionPermit2Adapter.AllowanceTarget[]","name":"_allowanceTargets","type":"tuple[]"},{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct IArbitraryExecutionPermit2Adapter.ContractCall[]","name":"_contractCalls","type":"tuple[]"},{"components":[{"internalType":"address","name":"token","type":"address"},{"components":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"shareBps","type":"uint256"}],"internalType":"struct Token.DistributionTarget[]","name":"distribution","type":"tuple[]"}],"internalType":"struct IArbitraryExecutionPermit2Adapter.TransferOut[]","name":"_transferOut","type":"tuple[]"},{"internalType":"uint256","name":"_deadline","type":"uint256"}],"name":"executeWithPermit","outputs":[{"internalType":"bytes[]","name":"_executionResults","type":"bytes[]"},{"internalType":"uint256[]","name":"_tokenBalances","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"isValidSignature","outputs":[{"internalType":"bytes4","name":"magicValue","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"address","name":"allowanceTarget","type":"address"},{"internalType":"address","name":"swapper","type":"address"},{"internalType":"bytes","name":"swapData","type":"bytes"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"minAmountOut","type":"uint256"},{"components":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"shareBps","type":"uint256"}],"internalType":"struct Token.DistributionTarget[]","name":"transferOut","type":"tuple[]"},{"internalType":"bytes","name":"misc","type":"bytes"}],"internalType":"struct ISwapPermit2Adapter.SellOrderSwapParams","name":"_params","type":"tuple"}],"name":"sellOrderSwap","outputs":[{"internalType":"uint256","name":"_amountIn","type":"uint256"},{"internalType":"uint256","name":"_amountOut","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"_calls","type":"bytes[]"}],"name":"simulate","outputs":[{"components":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"bytes","name":"result","type":"bytes"},{"internalType":"uint256","name":"gasSpent","type":"uint256"}],"internalType":"struct ISimulationAdapter.SimulationResult[]","name":"_results","type":"tuple[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_call","type":"bytes"}],"name":"simulateAndRevert","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"_interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]

60a06040523480156200001157600080fd5b50604051620028b5380380620028b5833981016040819052620000349162000046565b6001600160a01b031660805262000078565b6000602082840312156200005957600080fd5b81516001600160a01b03811681146200007157600080fd5b9392505050565b608051612805620000b0600039600081816101ef015281816102f2015281816103c80152818161087a015261105b01526128056000f3fe6080604052600436106100b55760003560e01c80634321431a11610069578063bcbef2061161004e578063bcbef20614610211578063ee4cfaf714610226578063ee8117211461023957600080fd5b80634321431a146101b55780636afdd850146101dd57600080fd5b80632c8aaabe1161009a5780632c8aaabe1461014757806331f7d964146101685780633ed242b41461019557600080fd5b806301ffc9a7146100c15780631626ba7e146100f657600080fd5b366100bc57005b600080fd5b3480156100cd57600080fd5b506100e16100dc366004611b4a565b61024c565b60405190151581526020015b60405180910390f35b34801561010257600080fd5b50610116610111366004611c3d565b6102e5565b6040517fffffffff0000000000000000000000000000000000000000000000000000000090911681526020016100ed565b61015a610155366004611d58565b610347565b6040516100ed929190611e76565b34801561017457600080fd5b5061017d600081565b6040516001600160a01b0390911681526020016100ed565b6101a86101a3366004611f2f565b610413565b6040516100ed9190611fa6565b6101c86101c3366004612026565b6104f6565b604080519283526020830191909152016100ed565b3480156101e957600080fd5b5061017d7f000000000000000000000000000000000000000000000000000000000000000081565b61022461021f366004612062565b610740565b005b61015a6102343660046120d4565b610806565b6101c861024736600461211c565b6108a5565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f3ed242b40000000000000000000000000000000000000000000000000000000014806102df57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b6000336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461031e576000610340565b7f1626ba7e000000000000000000000000000000000000000000000000000000005b9392505050565b6060808280421115610393576040517f25f14a28000000000000000000000000000000000000000000000000000000008152426004820152602481018290526044015b60405180910390fd5b6103f36103a360208d018d612174565b8c602001358d60400135878f80606001906103be919061218f565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016959493929190610ae4565b6104018a8a8a8a8a8a610bad565b92509250509850989650505050505050565b60608167ffffffffffffffff81111561042e5761042e611b8c565b60405190808252806020026020018201604052801561048557816020015b610472604051806060016040528060001515815260200160608152602001600081525090565b81526020019060019003908161044c5790505b50905060005b828110156104ef576104bf8484838181106104a8576104a86121f4565b90506020028101906104ba919061218f565b610e9f565b8282815181106104d1576104d16121f4565b602002602001018190525080806104e790612252565b91505061048b565b5092915050565b60008082354281101561053e576040517f25f14a280000000000000000000000000000000000000000000000000000000081524260048201526024810182905260440161038a565b61056a6105516040860160208701612174565b6040860135606087013587356103be60808a018a61218f565b61059c61057d60c0860160a08701612174565b61058d6040870160208801612174565b6001600160a01b031690611028565b6000806105af6040870160208801612174565b6001600160a01b0316146105c45760006105ca565b84604001355b90506105f26105df60e0870160c08801612174565b6105ec60e088018861218f565b84611057565b5061062661060461014087018761228a565b61061661012089016101008a01612174565b6001600160a01b0316919061111a565b9250846101200135831015610675576040517f763dfca000000000000000000000000000000000000000000000000000000000815260048101849052610120860135602482015260440161038a565b6106aa61068860c0870160a08801612174565b600161069a6040890160208a01612174565b6001600160a01b031691906111e6565b60408501803594507ff186b619e99ec011dd2df76f232917ce8326af9997ad34223335e401e95536f29033906001906106e69060208a01612174565b6106f86101208a016101008b01612174565b60408a01358861070e60e08d0160c08e01612174565b61071c6101608e018e61218f565b6040516107319998979695949392919061231d565b60405180910390a15050915091565b60005a9050600080306001600160a01b031685856040516107629291906123b4565b600060405180830381855af49150503d806000811461079d576040519150601f19603f3d011682016040523d82523d6000602084013e6107a2565b606091505b509150915060005a6107b490856123c4565b905060405180606001604052808415158152602001838152602001828152506040517f493703af00000000000000000000000000000000000000000000000000000000815260040161038a91906123d7565b606080828042111561084d576040517f25f14a280000000000000000000000000000000000000000000000000000000081524260048201526024810182905260440161038a565b6103f361085a8c8061228a565b8d60200135878f8060400190610870919061218f565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001695949392919061121b565b6000808235428110156108ed576040517f25f14a280000000000000000000000000000000000000000000000000000000081524260048201526024810182905260440161038a565b6109006105516040860160208701612174565b61091361057d60c0860160a08701612174565b6000806109266040870160208801612174565b6001600160a01b03161461093b576000610941565b84604001355b90506109566105df60e0870160c08801612174565b50600061097a61096c6040880160208901612174565b6001600160a01b03166112ca565b905061099f61098d61014088018861228a565b6106166101208a016101008b01612174565b93508561012001358410156109ee576040517f763dfca000000000000000000000000000000000000000000000000000000000815260048101859052610120870135602482015260440161038a565b610a2481610a0461018089016101608a01612174565b610a1460408a0160208b01612174565b6001600160a01b03169190611368565b610a49610a3760c0880160a08901612174565b600161069a60408a0160208b01612174565b610a578160408801356123c4565b94507ff186b619e99ec011dd2df76f232917ce8326af9997ad34223335e401e95536f2336000610a8d60408a0160208b01612174565b610a9f6101208b016101008c01612174565b8989610ab160e08e0160c08f01612174565b610abf6101808f018f61218f565b604051610ad49998979695949392919061231d565b60405180910390a1505050915091565b8015610ba4576040805160a0810182526001600160a01b038881166060830190815260808301899052825260208083018890528284018790528351808501855230815290810189905292517f30f28b7a000000000000000000000000000000000000000000000000000000008152908a16926330f28b7a92610b71929091903390889088906004016123ea565b600060405180830381600087803b158015610b8b57600080fd5b505af1158015610b9f573d6000803e3d6000fd5b505050505b50505050505050565b60608060005b87811015610c2757610c1f898983818110610bd057610bd06121f4565b9050604002016020016020810190610be89190612174565b8a8a84818110610bfa57610bfa6121f4565b610c109260206040909202019081019150612174565b6001600160a01b0316906113b4565b600101610bb3565b508467ffffffffffffffff811115610c4157610c41611b8c565b604051908082528060200260200182016040528015610c7457816020015b6060815260200190600190039081610c5f5790505b50915060005b85811015610d3b57610d16878783818110610c9757610c976121f4565b9050602002810190610ca9919061246f565b610cb7906020810190612174565b888884818110610cc957610cc96121f4565b9050602002810190610cdb919061246f565b610ce990602081019061218f565b8a8a86818110610cfb57610cfb6121f4565b9050602002810190610d0d919061246f565b60400135611057565b838281518110610d2857610d286121f4565b6020908102919091010152600101610c7a565b5060005b87811015610db657610dae898983818110610d5c57610d5c6121f4565b9050604002016020016020810190610d749190612174565b60018b8b85818110610d8857610d886121f4565b610d9e9260206040909202019081019150612174565b6001600160a01b031691906113db565b600101610d3f565b508267ffffffffffffffff811115610dd057610dd0611b8c565b604051908082528060200260200182016040528015610df9578160200160208202803683370190505b50905060005b83811015610e9357610e6e858583818110610e1c57610e1c6121f4565b9050602002810190610e2e91906124ad565b610e3c90602081019061228a565b878785818110610e4e57610e4e6121f4565b9050602002810190610e6091906124ad565b610616906020810190612174565b828281518110610e8057610e806121f4565b6020908102919091010152600101610dff565b50965096945050505050565b610ec5604051806060016040528060001515815260200160608152602001600081525090565b600080306001600160a01b031663bcbef20660e01b8686604051602401610eed9291906124e1565b60408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051610f5891906124f5565b600060405180830381855af49150503d8060008114610f93576040519150601f19603f3d011682016040523d82523d6000602084013e610f98565b606091505b50915091508115611005576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f5754463f2053686f756c642068617665206661696c6564210000000000000000604482015260640161038a565b6004810190508080602001905181019061101f9190612517565b95945050505050565b61105382827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6111e6565b5050565b60607f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316856001600160a01b0316036110c4576040517fe0d7940800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61110f84848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050506001600160a01b038816919050846113ef565b90505b949350505050565b6000611125846112ca565b90508060005b6111366001856123c4565b8110156111bc576000612710868684818110611154576111546121f4565b905060400201602001358561116991906125dc565b61117391906125f3565b90506111a7878288888681811061118c5761118c6121f4565b6111a29260206040909202019081019150612174565b611368565b6111b181846123c4565b92505060010161112b565b506111de858286866111cf6001826123c4565b81811061118c5761118c6121f4565b509392505050565b6001600160a01b0383161580159061120657506001600160a01b03821615155b15611216576112168383836113db565b505050565b8415610ba457866001600160a01b031663edd9444b60405180606001604052808989808060200260200160405190810160405280939291908181526020016000905b828210156112895761127a6040830286013681900381019061262e565b8152602001906001019061125d565b50505050508152602001878152602001868152506112a78989611415565b3386866040518663ffffffff1660e01b8152600401610b719594939291906126dd565b60006001600160a01b03821615611361576040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015611338573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061135c9190612794565b6102df565b4792915050565b8115611216576001600160a01b03811661137f5750335b6001600160a01b0383166113a0576112166001600160a01b038216836114e2565b6112166001600160a01b038416828461162f565b61105382827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5b6112166001600160a01b03841683836116d8565b60606111128484846040518060600160405280602981526020016127dc602991396117b4565b60608167ffffffffffffffff81111561143057611430611b8c565b60405190808252806020026020018201604052801561147557816020015b604080518082019091526000808252602082015281526020019060019003908161144e5790505b50905060005b81518110156104ef576040518060400160405280306001600160a01b031681526020018585848181106114b0576114b06121f4565b905060400201602001358152508282815181106114cf576114cf6121f4565b602090810291909101015260010161147b565b8047101561154c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015260640161038a565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114611599576040519150601f19603f3d011682016040523d82523d6000602084013e61159e565b606091505b5050905080611216576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d61792068617665207265766572746564000000000000606482015260840161038a565b6040516001600160a01b0383166024820152604481018290526112169084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526118c0565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b30000000000000000000000000000000000000000000000000000000017905261175784826119c2565b6117ae576040516001600160a01b0384166024820152600060448201526117a49085907f095ea7b30000000000000000000000000000000000000000000000000000000090606401611674565b6117ae84826118c0565b50505050565b606082471015611846576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c0000000000000000000000000000000000000000000000000000606482015260840161038a565b600080866001600160a01b0316858760405161186291906124f5565b60006040518083038185875af1925050503d806000811461189f576040519150601f19603f3d011682016040523d82523d6000602084013e6118a4565b606091505b50915091506118b587838387611a64565b979650505050505050565b6000611915826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611af79092919063ffffffff16565b905080516000148061193657508080602001905181019061193691906127ad565b611216576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840161038a565b6000806000846001600160a01b0316846040516119df91906124f5565b6000604051808303816000865af19150503d8060008114611a1c576040519150601f19603f3d011682016040523d82523d6000602084013e611a21565b606091505b5091509150818015611a4b575080511580611a4b575080806020019051810190611a4b91906127ad565b801561101f57506001600160a01b0385163b151561101f565b60608315611aed578251600003611ae6576001600160a01b0385163b611ae6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161038a565b5081611112565b6111128383611b06565b606061111284846000856117b4565b815115611b165781518083602001fd5b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161038a91906127c8565b600060208284031215611b5c57600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461034057600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516060810167ffffffffffffffff81118282101715611bde57611bde611b8c565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715611c0d57611c0d611b8c565b604052919050565b600067ffffffffffffffff821115611c2f57611c2f611b8c565b50601f01601f191660200190565b60008060408385031215611c5057600080fd5b82359150602083013567ffffffffffffffff811115611c6e57600080fd5b8301601f81018513611c7f57600080fd5b8035611c92611c8d82611c15565b611be4565b818152866020838501011115611ca757600080fd5b816020840160208301376000602083830101528093505050509250929050565b60008083601f840112611cd957600080fd5b50813567ffffffffffffffff811115611cf157600080fd5b6020830191508360208260061b8501011115611d0c57600080fd5b9250929050565b60008083601f840112611d2557600080fd5b50813567ffffffffffffffff811115611d3d57600080fd5b6020830191508360208260051b8501011115611d0c57600080fd5b60008060008060008060008060a0898b031215611d7457600080fd5b883567ffffffffffffffff80821115611d8c57600080fd5b908a01906080828d031215611da057600080fd5b90985060208a01359080821115611db657600080fd5b611dc28c838d01611cc7565b909950975060408b0135915080821115611ddb57600080fd5b611de78c838d01611d13565b909750955060608b0135915080821115611e0057600080fd5b50611e0d8b828c01611d13565b999c989b50969995989497949560800135949350505050565b60005b83811015611e41578181015183820152602001611e29565b50506000910152565b60008151808452611e62816020860160208601611e26565b601f01601f19169290920160200192915050565b6000604082016040835280855180835260608501915060608160051b8601019250602080880160005b83811015611eeb577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0888703018552611ed9868351611e4a565b95509382019390820190600101611e9f565b50508584038187015286518085528782019482019350915060005b82811015611f2257845184529381019392810192600101611f06565b5091979650505050505050565b60008060208385031215611f4257600080fd5b823567ffffffffffffffff811115611f5957600080fd5b611f6585828601611d13565b90969095509350505050565b8051151582526000602082015160606020850152611f926060850182611e4a565b604093840151949093019390935250919050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b82811015612019577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452612007858351611f71565b94509285019290850190600101611fcd565b5092979650505050505050565b60006020828403121561203857600080fd5b813567ffffffffffffffff81111561204f57600080fd5b8201610180818503121561034057600080fd5b6000806020838503121561207557600080fd5b823567ffffffffffffffff8082111561208d57600080fd5b818501915085601f8301126120a157600080fd5b8135818111156120b057600080fd5b8660208285010111156120c257600080fd5b60209290920196919550909350505050565b60008060008060008060008060a0898b0312156120f057600080fd5b883567ffffffffffffffff8082111561210857600080fd5b908a01906060828d031215611da057600080fd5b60006020828403121561212e57600080fd5b813567ffffffffffffffff81111561214557600080fd5b82016101a0818503121561034057600080fd5b80356001600160a01b038116811461216f57600080fd5b919050565b60006020828403121561218657600080fd5b61034082612158565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126121c457600080fd5b83018035915067ffffffffffffffff8211156121df57600080fd5b602001915036819003821315611d0c57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361228357612283612223565b5060010190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126122bf57600080fd5b83018035915067ffffffffffffffff8211156122da57600080fd5b6020019150600681901b3603821315611d0c57600080fd5b818352818160208501375060006020828401015260006020601f19601f840116840101905092915050565b60006101006001600160a01b03808d16845260028c10612366577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8b6020850152808b166040850152808a1660608501528860808501528760a085015280871660c0850152508060e08401526123a481840185876122f2565b9c9b505050505050505050505050565b8183823760009101908152919050565b818103818111156102df576102df612223565b6020815260006103406020830184611f71565b600061010061240d83895180516001600160a01b03168252602090810151910152565b6020880151604084015260408801516060840152612441608084018880516001600160a01b03168252602090810151910152565b6001600160a01b03861660c08401528060e084015261246381840185876122f2565b98975050505050505050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa18336030181126124a357600080fd5b9190910192915050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18336030181126124a357600080fd5b6020815260006111126020830184866122f2565b600082516124a3818460208701611e26565b8051801515811461216f57600080fd5b6000602080838503121561252a57600080fd5b825167ffffffffffffffff8082111561254257600080fd5b908401906060828703121561255657600080fd5b61255e611bbb565b61256783612507565b8152838301518281111561257a57600080fd5b83019150601f8201871361258d57600080fd5b815161259b611c8d82611c15565b81815288868386010111156125af57600080fd5b6125be82878301888701611e26565b80868401525050604083015160408201528094505050505092915050565b80820281158282048414176102df576102df612223565b600082612629577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60006040828403121561264057600080fd5b6040516040810181811067ffffffffffffffff8211171561266357612663611b8c565b60405261266f83612158565b8152602083013560208201528091505092915050565b600081518084526020808501945080840160005b838110156126d2576126bf87835180516001600160a01b03168252602090810151910152565b6040969096019590820190600101612699565b509495945050505050565b60808152600060e082018751606060808501528181518084526101008601915060209350838301925060005b818110156127425761272f83855180516001600160a01b03168252602090810151910152565b9284019260409290920191600101612709565b5050828a015160a086015260408a015160c086015284810383860152612768818a612685565b9250505061278160408401876001600160a01b03169052565b82810360608401526124638185876122f2565b6000602082840312156127a657600080fd5b5051919050565b6000602082840312156127bf57600080fd5b61034082612507565b6020815260006103406020830184611e4a56fe416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba3000000000000000000000000bc2122028eecd61df4b2cb2b996c00bd856e333b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000bc2122028eecd61df4b2cb2b996c00bd856e333b

Deployed Bytecode

0x6080604052600436106100b55760003560e01c80634321431a11610069578063bcbef2061161004e578063bcbef20614610211578063ee4cfaf714610226578063ee8117211461023957600080fd5b80634321431a146101b55780636afdd850146101dd57600080fd5b80632c8aaabe1161009a5780632c8aaabe1461014757806331f7d964146101685780633ed242b41461019557600080fd5b806301ffc9a7146100c15780631626ba7e146100f657600080fd5b366100bc57005b600080fd5b3480156100cd57600080fd5b506100e16100dc366004611b4a565b61024c565b60405190151581526020015b60405180910390f35b34801561010257600080fd5b50610116610111366004611c3d565b6102e5565b6040517fffffffff0000000000000000000000000000000000000000000000000000000090911681526020016100ed565b61015a610155366004611d58565b610347565b6040516100ed929190611e76565b34801561017457600080fd5b5061017d600081565b6040516001600160a01b0390911681526020016100ed565b6101a86101a3366004611f2f565b610413565b6040516100ed9190611fa6565b6101c86101c3366004612026565b6104f6565b604080519283526020830191909152016100ed565b3480156101e957600080fd5b5061017d7f000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba381565b61022461021f366004612062565b610740565b005b61015a6102343660046120d4565b610806565b6101c861024736600461211c565b6108a5565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f3ed242b40000000000000000000000000000000000000000000000000000000014806102df57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b6000336001600160a01b037f000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba3161461031e576000610340565b7f1626ba7e000000000000000000000000000000000000000000000000000000005b9392505050565b6060808280421115610393576040517f25f14a28000000000000000000000000000000000000000000000000000000008152426004820152602481018290526044015b60405180910390fd5b6103f36103a360208d018d612174565b8c602001358d60400135878f80606001906103be919061218f565b6001600160a01b037f000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba316959493929190610ae4565b6104018a8a8a8a8a8a610bad565b92509250509850989650505050505050565b60608167ffffffffffffffff81111561042e5761042e611b8c565b60405190808252806020026020018201604052801561048557816020015b610472604051806060016040528060001515815260200160608152602001600081525090565b81526020019060019003908161044c5790505b50905060005b828110156104ef576104bf8484838181106104a8576104a86121f4565b90506020028101906104ba919061218f565b610e9f565b8282815181106104d1576104d16121f4565b602002602001018190525080806104e790612252565b91505061048b565b5092915050565b60008082354281101561053e576040517f25f14a280000000000000000000000000000000000000000000000000000000081524260048201526024810182905260440161038a565b61056a6105516040860160208701612174565b6040860135606087013587356103be60808a018a61218f565b61059c61057d60c0860160a08701612174565b61058d6040870160208801612174565b6001600160a01b031690611028565b6000806105af6040870160208801612174565b6001600160a01b0316146105c45760006105ca565b84604001355b90506105f26105df60e0870160c08801612174565b6105ec60e088018861218f565b84611057565b5061062661060461014087018761228a565b61061661012089016101008a01612174565b6001600160a01b0316919061111a565b9250846101200135831015610675576040517f763dfca000000000000000000000000000000000000000000000000000000000815260048101849052610120860135602482015260440161038a565b6106aa61068860c0870160a08801612174565b600161069a6040890160208a01612174565b6001600160a01b031691906111e6565b60408501803594507ff186b619e99ec011dd2df76f232917ce8326af9997ad34223335e401e95536f29033906001906106e69060208a01612174565b6106f86101208a016101008b01612174565b60408a01358861070e60e08d0160c08e01612174565b61071c6101608e018e61218f565b6040516107319998979695949392919061231d565b60405180910390a15050915091565b60005a9050600080306001600160a01b031685856040516107629291906123b4565b600060405180830381855af49150503d806000811461079d576040519150601f19603f3d011682016040523d82523d6000602084013e6107a2565b606091505b509150915060005a6107b490856123c4565b905060405180606001604052808415158152602001838152602001828152506040517f493703af00000000000000000000000000000000000000000000000000000000815260040161038a91906123d7565b606080828042111561084d576040517f25f14a280000000000000000000000000000000000000000000000000000000081524260048201526024810182905260440161038a565b6103f361085a8c8061228a565b8d60200135878f8060400190610870919061218f565b6001600160a01b037f000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba31695949392919061121b565b6000808235428110156108ed576040517f25f14a280000000000000000000000000000000000000000000000000000000081524260048201526024810182905260440161038a565b6109006105516040860160208701612174565b61091361057d60c0860160a08701612174565b6000806109266040870160208801612174565b6001600160a01b03161461093b576000610941565b84604001355b90506109566105df60e0870160c08801612174565b50600061097a61096c6040880160208901612174565b6001600160a01b03166112ca565b905061099f61098d61014088018861228a565b6106166101208a016101008b01612174565b93508561012001358410156109ee576040517f763dfca000000000000000000000000000000000000000000000000000000000815260048101859052610120870135602482015260440161038a565b610a2481610a0461018089016101608a01612174565b610a1460408a0160208b01612174565b6001600160a01b03169190611368565b610a49610a3760c0880160a08901612174565b600161069a60408a0160208b01612174565b610a578160408801356123c4565b94507ff186b619e99ec011dd2df76f232917ce8326af9997ad34223335e401e95536f2336000610a8d60408a0160208b01612174565b610a9f6101208b016101008c01612174565b8989610ab160e08e0160c08f01612174565b610abf6101808f018f61218f565b604051610ad49998979695949392919061231d565b60405180910390a1505050915091565b8015610ba4576040805160a0810182526001600160a01b038881166060830190815260808301899052825260208083018890528284018790528351808501855230815290810189905292517f30f28b7a000000000000000000000000000000000000000000000000000000008152908a16926330f28b7a92610b71929091903390889088906004016123ea565b600060405180830381600087803b158015610b8b57600080fd5b505af1158015610b9f573d6000803e3d6000fd5b505050505b50505050505050565b60608060005b87811015610c2757610c1f898983818110610bd057610bd06121f4565b9050604002016020016020810190610be89190612174565b8a8a84818110610bfa57610bfa6121f4565b610c109260206040909202019081019150612174565b6001600160a01b0316906113b4565b600101610bb3565b508467ffffffffffffffff811115610c4157610c41611b8c565b604051908082528060200260200182016040528015610c7457816020015b6060815260200190600190039081610c5f5790505b50915060005b85811015610d3b57610d16878783818110610c9757610c976121f4565b9050602002810190610ca9919061246f565b610cb7906020810190612174565b888884818110610cc957610cc96121f4565b9050602002810190610cdb919061246f565b610ce990602081019061218f565b8a8a86818110610cfb57610cfb6121f4565b9050602002810190610d0d919061246f565b60400135611057565b838281518110610d2857610d286121f4565b6020908102919091010152600101610c7a565b5060005b87811015610db657610dae898983818110610d5c57610d5c6121f4565b9050604002016020016020810190610d749190612174565b60018b8b85818110610d8857610d886121f4565b610d9e9260206040909202019081019150612174565b6001600160a01b031691906113db565b600101610d3f565b508267ffffffffffffffff811115610dd057610dd0611b8c565b604051908082528060200260200182016040528015610df9578160200160208202803683370190505b50905060005b83811015610e9357610e6e858583818110610e1c57610e1c6121f4565b9050602002810190610e2e91906124ad565b610e3c90602081019061228a565b878785818110610e4e57610e4e6121f4565b9050602002810190610e6091906124ad565b610616906020810190612174565b828281518110610e8057610e806121f4565b6020908102919091010152600101610dff565b50965096945050505050565b610ec5604051806060016040528060001515815260200160608152602001600081525090565b600080306001600160a01b031663bcbef20660e01b8686604051602401610eed9291906124e1565b60408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051610f5891906124f5565b600060405180830381855af49150503d8060008114610f93576040519150601f19603f3d011682016040523d82523d6000602084013e610f98565b606091505b50915091508115611005576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f5754463f2053686f756c642068617665206661696c6564210000000000000000604482015260640161038a565b6004810190508080602001905181019061101f9190612517565b95945050505050565b61105382827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6111e6565b5050565b60607f000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba36001600160a01b0316856001600160a01b0316036110c4576040517fe0d7940800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61110f84848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050506001600160a01b038816919050846113ef565b90505b949350505050565b6000611125846112ca565b90508060005b6111366001856123c4565b8110156111bc576000612710868684818110611154576111546121f4565b905060400201602001358561116991906125dc565b61117391906125f3565b90506111a7878288888681811061118c5761118c6121f4565b6111a29260206040909202019081019150612174565b611368565b6111b181846123c4565b92505060010161112b565b506111de858286866111cf6001826123c4565b81811061118c5761118c6121f4565b509392505050565b6001600160a01b0383161580159061120657506001600160a01b03821615155b15611216576112168383836113db565b505050565b8415610ba457866001600160a01b031663edd9444b60405180606001604052808989808060200260200160405190810160405280939291908181526020016000905b828210156112895761127a6040830286013681900381019061262e565b8152602001906001019061125d565b50505050508152602001878152602001868152506112a78989611415565b3386866040518663ffffffff1660e01b8152600401610b719594939291906126dd565b60006001600160a01b03821615611361576040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015611338573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061135c9190612794565b6102df565b4792915050565b8115611216576001600160a01b03811661137f5750335b6001600160a01b0383166113a0576112166001600160a01b038216836114e2565b6112166001600160a01b038416828461162f565b61105382827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5b6112166001600160a01b03841683836116d8565b60606111128484846040518060600160405280602981526020016127dc602991396117b4565b60608167ffffffffffffffff81111561143057611430611b8c565b60405190808252806020026020018201604052801561147557816020015b604080518082019091526000808252602082015281526020019060019003908161144e5790505b50905060005b81518110156104ef576040518060400160405280306001600160a01b031681526020018585848181106114b0576114b06121f4565b905060400201602001358152508282815181106114cf576114cf6121f4565b602090810291909101015260010161147b565b8047101561154c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015260640161038a565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114611599576040519150601f19603f3d011682016040523d82523d6000602084013e61159e565b606091505b5050905080611216576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d61792068617665207265766572746564000000000000606482015260840161038a565b6040516001600160a01b0383166024820152604481018290526112169084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526118c0565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b30000000000000000000000000000000000000000000000000000000017905261175784826119c2565b6117ae576040516001600160a01b0384166024820152600060448201526117a49085907f095ea7b30000000000000000000000000000000000000000000000000000000090606401611674565b6117ae84826118c0565b50505050565b606082471015611846576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c0000000000000000000000000000000000000000000000000000606482015260840161038a565b600080866001600160a01b0316858760405161186291906124f5565b60006040518083038185875af1925050503d806000811461189f576040519150601f19603f3d011682016040523d82523d6000602084013e6118a4565b606091505b50915091506118b587838387611a64565b979650505050505050565b6000611915826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611af79092919063ffffffff16565b905080516000148061193657508080602001905181019061193691906127ad565b611216576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840161038a565b6000806000846001600160a01b0316846040516119df91906124f5565b6000604051808303816000865af19150503d8060008114611a1c576040519150601f19603f3d011682016040523d82523d6000602084013e611a21565b606091505b5091509150818015611a4b575080511580611a4b575080806020019051810190611a4b91906127ad565b801561101f57506001600160a01b0385163b151561101f565b60608315611aed578251600003611ae6576001600160a01b0385163b611ae6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161038a565b5081611112565b6111128383611b06565b606061111284846000856117b4565b815115611b165781518083602001fd5b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161038a91906127c8565b600060208284031215611b5c57600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461034057600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516060810167ffffffffffffffff81118282101715611bde57611bde611b8c565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715611c0d57611c0d611b8c565b604052919050565b600067ffffffffffffffff821115611c2f57611c2f611b8c565b50601f01601f191660200190565b60008060408385031215611c5057600080fd5b82359150602083013567ffffffffffffffff811115611c6e57600080fd5b8301601f81018513611c7f57600080fd5b8035611c92611c8d82611c15565b611be4565b818152866020838501011115611ca757600080fd5b816020840160208301376000602083830101528093505050509250929050565b60008083601f840112611cd957600080fd5b50813567ffffffffffffffff811115611cf157600080fd5b6020830191508360208260061b8501011115611d0c57600080fd5b9250929050565b60008083601f840112611d2557600080fd5b50813567ffffffffffffffff811115611d3d57600080fd5b6020830191508360208260051b8501011115611d0c57600080fd5b60008060008060008060008060a0898b031215611d7457600080fd5b883567ffffffffffffffff80821115611d8c57600080fd5b908a01906080828d031215611da057600080fd5b90985060208a01359080821115611db657600080fd5b611dc28c838d01611cc7565b909950975060408b0135915080821115611ddb57600080fd5b611de78c838d01611d13565b909750955060608b0135915080821115611e0057600080fd5b50611e0d8b828c01611d13565b999c989b50969995989497949560800135949350505050565b60005b83811015611e41578181015183820152602001611e29565b50506000910152565b60008151808452611e62816020860160208601611e26565b601f01601f19169290920160200192915050565b6000604082016040835280855180835260608501915060608160051b8601019250602080880160005b83811015611eeb577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0888703018552611ed9868351611e4a565b95509382019390820190600101611e9f565b50508584038187015286518085528782019482019350915060005b82811015611f2257845184529381019392810192600101611f06565b5091979650505050505050565b60008060208385031215611f4257600080fd5b823567ffffffffffffffff811115611f5957600080fd5b611f6585828601611d13565b90969095509350505050565b8051151582526000602082015160606020850152611f926060850182611e4a565b604093840151949093019390935250919050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b82811015612019577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452612007858351611f71565b94509285019290850190600101611fcd565b5092979650505050505050565b60006020828403121561203857600080fd5b813567ffffffffffffffff81111561204f57600080fd5b8201610180818503121561034057600080fd5b6000806020838503121561207557600080fd5b823567ffffffffffffffff8082111561208d57600080fd5b818501915085601f8301126120a157600080fd5b8135818111156120b057600080fd5b8660208285010111156120c257600080fd5b60209290920196919550909350505050565b60008060008060008060008060a0898b0312156120f057600080fd5b883567ffffffffffffffff8082111561210857600080fd5b908a01906060828d031215611da057600080fd5b60006020828403121561212e57600080fd5b813567ffffffffffffffff81111561214557600080fd5b82016101a0818503121561034057600080fd5b80356001600160a01b038116811461216f57600080fd5b919050565b60006020828403121561218657600080fd5b61034082612158565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126121c457600080fd5b83018035915067ffffffffffffffff8211156121df57600080fd5b602001915036819003821315611d0c57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361228357612283612223565b5060010190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126122bf57600080fd5b83018035915067ffffffffffffffff8211156122da57600080fd5b6020019150600681901b3603821315611d0c57600080fd5b818352818160208501375060006020828401015260006020601f19601f840116840101905092915050565b60006101006001600160a01b03808d16845260028c10612366577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8b6020850152808b166040850152808a1660608501528860808501528760a085015280871660c0850152508060e08401526123a481840185876122f2565b9c9b505050505050505050505050565b8183823760009101908152919050565b818103818111156102df576102df612223565b6020815260006103406020830184611f71565b600061010061240d83895180516001600160a01b03168252602090810151910152565b6020880151604084015260408801516060840152612441608084018880516001600160a01b03168252602090810151910152565b6001600160a01b03861660c08401528060e084015261246381840185876122f2565b98975050505050505050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa18336030181126124a357600080fd5b9190910192915050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18336030181126124a357600080fd5b6020815260006111126020830184866122f2565b600082516124a3818460208701611e26565b8051801515811461216f57600080fd5b6000602080838503121561252a57600080fd5b825167ffffffffffffffff8082111561254257600080fd5b908401906060828703121561255657600080fd5b61255e611bbb565b61256783612507565b8152838301518281111561257a57600080fd5b83019150601f8201871361258d57600080fd5b815161259b611c8d82611c15565b81815288868386010111156125af57600080fd5b6125be82878301888701611e26565b80868401525050604083015160408201528094505050505092915050565b80820281158282048414176102df576102df612223565b600082612629577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60006040828403121561264057600080fd5b6040516040810181811067ffffffffffffffff8211171561266357612663611b8c565b60405261266f83612158565b8152602083013560208201528091505092915050565b600081518084526020808501945080840160005b838110156126d2576126bf87835180516001600160a01b03168252602090810151910152565b6040969096019590820190600101612699565b509495945050505050565b60808152600060e082018751606060808501528181518084526101008601915060209350838301925060005b818110156127425761272f83855180516001600160a01b03168252602090810151910152565b9284019260409290920191600101612709565b5050828a015160a086015260408a015160c086015284810383860152612768818a612685565b9250505061278160408401876001600160a01b03169052565b82810360608401526124638185876122f2565b6000602082840312156127a657600080fd5b5051919050565b6000602082840312156127bf57600080fd5b61034082612507565b6020815260006103406020830184611e4a56fe416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564

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

000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba3000000000000000000000000bc2122028eecd61df4b2cb2b996c00bd856e333b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000bc2122028eecd61df4b2cb2b996c00bd856e333b

-----Decoded View---------------
Arg [0] : _permit2 (address): 0x000000000022D473030F116dDEE9F6B43aC78BA3

-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba3
Arg [1] : 000000000000000000000000bc2122028eecd61df4b2cb2b996c00bd856e333b
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [4] : 000000000000000000000000bc2122028eecd61df4b2cb2b996c00bd856e333b


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
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.