ETH Price: $1,919.29 (-5.30%)

Contract

0xb095a5Ef5C4B3B1F43bB2529160a87F4f7025F27

Overview

ETH Balance

0 ETH

ETH Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

1 Internal Transaction found.

Latest 1 internal transaction

Parent Transaction Hash Block From To
6162902025-01-31 23:56:1755 days ago1738367777  Contract Creation0 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
UniswapV2Factory

Compiler Version
v0.8.20+commit.a1b79de6

ZkSolc Version
v1.5.4

Optimization Enabled:
Yes with Mode 3

Other Settings:
paris EvmVersion
File 1 of 14 : UniswapV2Factory.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

import "lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol";
import "lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol";

import "./interfaces/IUniswapV2Factory.sol";
import "./UniswapV2Pair.sol";

contract UniswapV2Factory is IUniswapV2Factory, Ownable2Step {
    using EnumerableSet for EnumerableSet.AddressSet;

    /// @dev Fee is denominated in basis points so 5000 / 10000 = 50%
    uint256 public constant MAX_FEE = 5000;

    address public protocolFeeBeneficiary;

    mapping(address => mapping(address => address)) public getPair;
    EnumerableSet.AddressSet private _allPairs;

    DefaultFees public defaultFees;
    mapping(address => Fees) public pairFees;

    constructor(uint256 _defaultProtocolFee, uint256 _defaultLpFee, address _protocolFeeBeneficiary) {
        DefaultFees memory startFees = DefaultFees({protocolFee: _defaultProtocolFee, lpFee: _defaultLpFee});

        setDefaultFees(startFees);
        setProtocolFeeBeneficiary(_protocolFeeBeneficiary);
    }

    /// @inheritdoc IUniswapV2Factory
    function getTotalFee(address _pair) public view returns (uint256) {
        (uint256 lpFee, uint256 royaltiesFee, uint256 protocolFee) = _getFees(_pair);
        return lpFee + royaltiesFee + protocolFee;
    }

    /// @inheritdoc IUniswapV2Factory
    function getFees(address _pair) public view returns (uint256 lpFee, uint256 royaltiesFee, uint256 protocolFee) {
        return _getFees(_pair);
    }

    /// @inheritdoc IUniswapV2Factory
    function getFeesAndRecipients(address _pair)
        public
        view
        returns (
            uint256 lpFee,
            address royaltiesBeneficiary,
            uint256 royaltiesFee,
            address protocolBeneficiary,
            uint256 protocolFee
        )
    {
        (lpFee, royaltiesFee, protocolFee) = _getFees(_pair);

        royaltiesBeneficiary = pairFees[_pair].royaltiesBeneficiary;
        protocolBeneficiary = protocolFeeBeneficiary;
    }

    function allPairs() external view returns (address[] memory) {
        return _allPairs.values();
    }

    function allPairs(uint256 _index) external view returns (address) {
        return _allPairs.at(_index);
    }

    function allPairsLength() external view returns (uint256) {
        return _allPairs.length();
    }

    function createPair(address tokenA, address tokenB) external returns (address pair) {
        require(tokenA != tokenB, "MagicswapV2: IDENTICAL_ADDRESSES");
        (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
        require(token0 != address(0), "MagicswapV2: ZERO_ADDRESS");
        require(getPair[token0][token1] == address(0), "MagicswapV2: PAIR_EXISTS"); // single check is sufficient
        bytes memory bytecode = type(UniswapV2Pair).creationCode;
        bytes32 salt = keccak256(abi.encodePacked(token0, token1));
        assembly {
            pair := create2(0, add(bytecode, 32), mload(bytecode), salt)
        }
        IUniswapV2Pair(pair).initialize(token0, token1);
        getPair[token0][token1] = pair;
        getPair[token1][token0] = pair; // populate mapping in the reverse direction
        _allPairs.add(pair);
        emit PairCreated(token0, token1, pair, _allPairs.length());
    }

    /// @inheritdoc IUniswapV2Factory
    function setDefaultFees(DefaultFees memory _fees) public onlyOwner {
        require(_fees.protocolFee <= MAX_FEE, "MagicswapV2: protocolFee > MAX_FEE");
        require(_fees.lpFee <= MAX_FEE, "MagicswapV2: lpFee > MAX_FEE");
        require(_fees.protocolFee + _fees.lpFee <= MAX_FEE, "MagicswapV2: protocolFee + lpFee > MAX_FEE");

        defaultFees = _fees;

        emit DefaultFeesSet(_fees);
    }

    /// @inheritdoc IUniswapV2Factory
    function setLpFee(address _pair, uint256 _lpFee, bool _overrideFee) external onlyOwner {
        require(_lpFee <= MAX_FEE, "MagicswapV2: _lpFee > MAX_FEE");
        require(_allPairs.contains(_pair), "MagicswapV2: _pair invalid");

        pairFees[_pair].lpFee = _lpFee;
        pairFees[_pair].lpFeeOverride = _overrideFee;

        emit LpFeesSet(_pair, _lpFee, _overrideFee);
    }

    /// @inheritdoc IUniswapV2Factory
    function setRoyaltiesFee(address _pair, address _beneficiary, uint256 _royaltiesFee) external onlyOwner {
        require(_royaltiesFee <= MAX_FEE, "MagicswapV2: _royaltiesFee > MAX_FEE");
        require(_allPairs.contains(_pair), "MagicswapV2: _pair invalid");
        require(_beneficiary != address(0), "MagicswapV2: _beneficiary invalid");

        pairFees[_pair].royaltiesBeneficiary = _beneficiary;
        pairFees[_pair].royaltiesFee = _royaltiesFee;

        emit RoyaltiesFeesSet(_pair, _beneficiary, _royaltiesFee);
    }

    /// @inheritdoc IUniswapV2Factory
    function setProtocolFee(address _pair, uint256 _protocolFee, bool _overrideFee) external onlyOwner {
        require(_protocolFee <= MAX_FEE, "MagicswapV2: _protocolFee > MAX_FEE");
        require(_allPairs.contains(_pair), "MagicswapV2: _pair invalid");

        pairFees[_pair].protocolFee = _protocolFee;
        pairFees[_pair].protocolFeeOverride = _overrideFee;

        emit ProtocolFeesSet(_pair, _protocolFee, _overrideFee);
    }

    /// @inheritdoc IUniswapV2Factory
    function setProtocolFeeBeneficiary(address _beneficiary) public onlyOwner {
        require(_beneficiary != address(0), "MagicswapV2: BENEFICIARY");
        protocolFeeBeneficiary = _beneficiary;

        emit ProtocolFeeBeneficiarySet(_beneficiary);
    }

    function _getLpFee(address _pair) internal view returns (uint256 lpFee) {
        if (pairFees[_pair].lpFeeOverride) {
            return pairFees[_pair].lpFee;
        } else {
            return defaultFees.lpFee;
        }
    }

    function _getRoyaltiesFee(address _pair) internal view returns (uint256 royaltiesFee) {
        return pairFees[_pair].royaltiesFee;
    }

    function _getProtocolFee(address _pair) internal view returns (uint256 protocolFee) {
        if (pairFees[_pair].protocolFeeOverride) {
            return pairFees[_pair].protocolFee;
        } else {
            return defaultFees.protocolFee;
        }
    }

    function _getFees(address _pair) internal view returns (uint256 lpFee, uint256 royaltiesFee, uint256 protocolFee) {
        lpFee = _getLpFee(_pair);
        /// lpFee should never be above MAX_FEE but never too safe.
        /// If lpFee is set to MAX_FEE then we know there's no more space for other fees
        if (lpFee >= MAX_FEE) {
            return (MAX_FEE, 0, 0);
        }

        royaltiesFee = _getRoyaltiesFee(_pair);
        /// if royaltiesFee + lpFee is greater than MAX_FEE, then decrease royaltiesFee
        /// and return as we know there's no more space for other fees
        if (royaltiesFee >= MAX_FEE - lpFee) {
            return (lpFee, MAX_FEE - lpFee, 0);
        }

        protocolFee = _getProtocolFee(_pair);
        /// if protocolFee + royaltiesFee + lpFee is greater than MAX_FEE, then decrease protocolFee
        if (protocolFee > MAX_FEE - lpFee - royaltiesFee) {
            protocolFee = MAX_FEE - lpFee - royaltiesFee;
        }
    }
}

File 2 of 14 : IUniswapV2Factory.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

interface IUniswapV2Factory {
    struct DefaultFees {
        /// @dev in basis point, denominated by 10000
        uint256 protocolFee;
        /// @dev in basis point, denominated by 10000
        uint256 lpFee;
    }

    struct Fees {
        address royaltiesBeneficiary;
        /// @dev in basis point, denominated by 10000
        uint256 royaltiesFee;
        /// @dev in basis point, denominated by 10000
        uint256 protocolFee;
        /// @dev in basis point, denominated by 10000
        uint256 lpFee;
        /// @dev if true, Fees.protocolFee is used even if set to 0
        bool protocolFeeOverride;
        /// @dev if true, Fees.lpFee is used even if set to 0
        bool lpFeeOverride;
    }

    event PairCreated(address indexed token0, address indexed token1, address pair, uint256);
    event DefaultFeesSet(DefaultFees fees);
    event LpFeesSet(address indexed pair, uint256 lpFee, bool overrideFee);
    event RoyaltiesFeesSet(address indexed pair, address beneficiary, uint256 royaltiesFee);
    event ProtocolFeesSet(address indexed pair, uint256 protocolFee, bool overrideFee);
    event ProtocolFeeBeneficiarySet(address beneficiary);

    /// @notice Returns total fee pair charges
    /// @dev Fee is capped at MAX_FEE
    /// @param pair address of pair for which to calculate fees
    /// @return totalFee total fee amount denominated in basis points
    function getTotalFee(address pair) external view returns (uint256 totalFee);

    /// @notice Returns all fees for pair
    /// @return lpFee fee changed by liquidity providers, denominated in basis points
    /// @return royaltiesFee royalties paid to NFT creators, denominated in basis points
    /// @return protocolFee fee paid to the protocol, denominated in basis points
    function getFees(address _pair) external view returns (uint256 lpFee, uint256 royaltiesFee, uint256 protocolFee);

    /// @notice Returns all fees for pair and beneficiaries
    /// @dev Fees are capped in total by MAX_FEE value. If by mistake or otherwise owner of this contract
    ///      does a combination of transactions and tries to achive total fees above MAX_FEE, fees are allocatied
    ///      by priority:
    ///      1. lp fee
    ///      2. royalties
    ///      3. protocol fee
    ///      If MAX_FEE == 5000, lpFee == 500, royaltiesFee == 4000 and protocolFee == 4000 then
    ///      effective fees will be allocated acording to the fee priority up to MAX_FEE value.
    ///      In this example: lpFee == 500, royaltiesFee == 4000 and protocolFee == 500.
    /// @param pair address of pair for which to calculate fees and beneficiaries
    /// @return lpFee fee changed by liquidity providers, denominated in basis points
    /// @return royaltiesBeneficiary address that gets royalties
    /// @return royaltiesFee royalties paid to NFT creators, denominated in basis points
    /// @return protocolBeneficiary address that gets protocol fees
    /// @return protocolFee fee paid to the protocol, denominated in basis points
    function getFeesAndRecipients(address pair)
        external
        view
        returns (
            uint256 lpFee,
            address royaltiesBeneficiary,
            uint256 royaltiesFee,
            address protocolBeneficiary,
            uint256 protocolFee
        );

    /// @return protocolFeeBeneficiary address that gets protocol fees
    function protocolFeeBeneficiary() external view returns (address protocolFeeBeneficiary);

    /// @notice Internal mapping to store fees for pair. It is exposed for advanced integrations
    ///         and in most cases contracts should use fee getters.
    function pairFees(address pair) external view returns (address, uint256, uint256, uint256, bool, bool);

    function getPair(address tokenA, address tokenB) external view returns (address pair);
    function allPairs() external view returns (address[] memory pairs);
    function allPairs(uint256) external view returns (address pair);
    function allPairsLength() external view returns (uint256);

    function createPair(address tokenA, address tokenB) external returns (address pair);

    /// @notice Sets default fees for all pairs
    /// @param fees struct with default fees
    function setDefaultFees(DefaultFees memory fees) external;

    /// @notice Sets royalties fee and beneficiary for pair
    /// @param pair address of pair for which to set fee
    /// @param beneficiary address that gets royalties
    /// @param royaltiesFee amount of royalties fee denominated in basis points
    function setRoyaltiesFee(address pair, address beneficiary, uint256 royaltiesFee) external;

    /// @notice Sets protocol fee for pair
    /// @param pair address of pair for which to set fee
    /// @param protocolFee amount of protocol fee denominated in basis points
    /// @param overrideFee if true, fee will be overriden even if set to 0
    function setProtocolFee(address pair, uint256 protocolFee, bool overrideFee) external;

    /// @notice Sets lp fee for pair
    /// @param pair address of pair for which to set fee
    /// @param lpFee amount of lp fee denominated in basis points
    /// @param overrideFee if true, fee will be overriden even if set to 0
    function setLpFee(address pair, uint256 lpFee, bool overrideFee) external;

    /// @notice Sets protocol fee beneficiary
    /// @param _beneficiary address that gets protocol fees
    function setProtocolFeeBeneficiary(address _beneficiary) external;
}

File 3 of 14 : UniswapV2Pair.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

import "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";

import "./interfaces/IUniswapV2Pair.sol";
import "./interfaces/IUniswapV2Factory.sol";

import "./libraries/UniswapV2Math.sol";
import "./libraries/Oracle.sol";

import "./UniswapV2ERC20.sol";

contract UniswapV2Pair is IUniswapV2Pair, UniswapV2ERC20 {
    using SafeMath for uint256;
    using Oracle for Oracle.Observation[65535];

    uint256 public constant MINIMUM_LIQUIDITY = 10 ** 3;
    uint256 public constant BASIS_POINTS = 10000;
    bytes4 private constant SELECTOR = bytes4(keccak256(bytes("transfer(address,uint256)")));

    // decimal points of token0
    uint256 public TOKEN0_DECIMALS;

    address public factory;
    address public token0;
    address public token1;

    uint112 private reserve0; // uses single storage slot, accessible via getReserves
    uint112 private reserve1; // uses single storage slot, accessible via getReserves
    uint32 private blockTimestampLast; // uses single storage slot, accessible via getReserves

    // the most recent price of token1/token0. Inherits decimals of token1.
    uint256 public lastPrice;
    // the most-recently updated index of the observations array
    uint16 public observationIndex;
    // the current maximum number of observations that are being stored
    uint16 public observationCardinality;
    // the next maximum number of observations to store, triggered in observations.write
    uint16 public observationCardinalityNext;

    Oracle.Observation[65535] public override observations;

    uint256 private unlocked = 1;

    modifier lock() {
        require(unlocked == 1, "MagicswapV2: LOCKED");
        unlocked = 0;
        _;
        unlocked = 1;
    }

    function getReserves() public view returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast) {
        _reserve0 = reserve0;
        _reserve1 = reserve1;
        _blockTimestampLast = blockTimestampLast;
    }

    function _safeTransfer(address token, address to, uint256 value) private {
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(SELECTOR, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), "MagicswapV2: TRANSFER_FAILED");
    }

    constructor() {
        factory = msg.sender;
    }

    // called once by the factory at time of deployment
    function initialize(address _token0, address _token1) external {
        require(msg.sender == factory, "MagicswapV2: FORBIDDEN"); // sufficient check
        token0 = _token0;
        token1 = _token1;

        TOKEN0_DECIMALS = UniswapV2ERC20(_token0).decimals();

        (uint16 cardinality, uint16 cardinalityNext) = observations.initialize(_blockTimestamp());

        observationIndex = 0;
        observationCardinality = cardinality;
        observationCardinalityNext = cardinalityNext;
    }

    function _blockTimestamp() internal view virtual returns (uint32) {
        return uint32(block.timestamp); // truncation is desired
    }

    /// @dev update reserves and, on the first call per block, price accumulators
    function _update(uint256 balance0, uint256 balance1, uint112 _reserve0, uint112 _reserve1) private {
        require(balance0 <= type(uint112).max && balance1 <= type(uint112).max, "MagicswapV2: OVERFLOW");

        uint32 blockTimestamp;
        uint32 timeElapsed;
        unchecked {
            blockTimestamp = uint32(block.timestamp % 2 ** 32);
            timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired
        }

        if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {
            // this is first trade of the block and reserves are not yet updated
            lastPrice = 10 ** TOKEN0_DECIMALS * _reserve1 / _reserve0;

            // write an oracle entry
            (observationIndex, observationCardinality) = observations.write(
                observationIndex, _blockTimestamp(), lastPrice, observationCardinality, observationCardinalityNext
            );
        }

        reserve0 = uint112(balance0);
        reserve1 = uint112(balance1);
        blockTimestampLast = blockTimestamp;
        emit Sync(reserve0, reserve1);
    }

    /// @dev Calculates fees and sends them to beneficiaries
    function _takeFees(uint256 balance0Adjusted, uint256 balance1Adjusted, uint256 amount0In, uint256 amount1In)
        internal
        returns (uint256 balance0, uint256 balance1)
    {
        (, address royaltiesBeneficiary, uint256 royaltiesFee, address protocolFeeBeneficiary, uint256 protocolFee) =
            IUniswapV2Factory(factory).getFeesAndRecipients(address(this));

        address _token0 = token0;
        address _token1 = token1;

        for (uint8 i = 0; i < 2; i++) {
            address feeToken = i == 0 ? _token0 : _token1;
            uint256 swapAmount = i == 0 ? amount0In : amount1In;

            if (swapAmount > 0) {
                uint256 royaltiesFeeAmount = swapAmount * royaltiesFee / BASIS_POINTS;

                // send royalties
                if (royaltiesFeeAmount > 0) {
                    _safeTransfer(feeToken, royaltiesBeneficiary, royaltiesFeeAmount);
                }

                uint256 protocolFeeAmount = swapAmount * protocolFee / BASIS_POINTS;

                // send protocol fee
                if (protocolFeeAmount > 0) {
                    _safeTransfer(feeToken, protocolFeeBeneficiary, protocolFeeAmount);
                }
            }
        }

        balance0 = IERC20(_token0).balanceOf(address(this));
        balance1 = IERC20(_token1).balanceOf(address(this));

        // Make sure that either balance does not go below adjusted balance used for K calcualtions.
        // If balances after fee transfers are above or equal adjusted balances then K still holds.
        require(balance0 >= balance0Adjusted / BASIS_POINTS, "MagicswapV2: balance0Adjusted");
        require(balance1 >= balance1Adjusted / BASIS_POINTS, "MagicswapV2: balance1Adjusted");
    }

    /// @dev this low-level function should be called from a contract which performs important safety checks
    function mint(address to) external lock returns (uint256 liquidity) {
        (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings
        uint256 balance0 = IERC20(token0).balanceOf(address(this));
        uint256 balance1 = IERC20(token1).balanceOf(address(this));
        uint256 amount0 = balance0.sub(_reserve0);
        uint256 amount1 = balance1.sub(_reserve1);

        uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee
        if (_totalSupply == 0) {
            liquidity = UniswapV2Math.sqrt(amount0.mul(amount1)).sub(MINIMUM_LIQUIDITY);
            _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens
        } else {
            liquidity = UniswapV2Math.min(amount0.mul(_totalSupply) / _reserve0, amount1.mul(_totalSupply) / _reserve1);
        }
        require(liquidity > 0, "MagicswapV2: INSUFFICIENT_LIQUIDITY_MINTED");
        _mint(to, liquidity);

        _update(balance0, balance1, _reserve0, _reserve1);
        emit Mint(msg.sender, amount0, amount1);
    }

    /// @dev this low-level function should be called from a contract which performs important safety checks
    function burn(address to) external lock returns (uint256 amount0, uint256 amount1) {
        (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings
        address _token0 = token0; // gas savings
        address _token1 = token1; // gas savings
        uint256 balance0 = IERC20(_token0).balanceOf(address(this));
        uint256 balance1 = IERC20(_token1).balanceOf(address(this));
        uint256 liquidity = balanceOf[address(this)];

        uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee
        amount0 = liquidity.mul(balance0) / _totalSupply; // using balances ensures pro-rata distribution
        amount1 = liquidity.mul(balance1) / _totalSupply; // using balances ensures pro-rata distribution
        require(amount0 > 0 && amount1 > 0, "MagicswapV2: INSUFFICIENT_LIQUIDITY_BURNED");
        _burn(address(this), liquidity);
        _safeTransfer(_token0, to, amount0);
        _safeTransfer(_token1, to, amount1);
        balance0 = IERC20(_token0).balanceOf(address(this));
        balance1 = IERC20(_token1).balanceOf(address(this));

        _update(balance0, balance1, _reserve0, _reserve1);
        emit Burn(msg.sender, amount0, amount1, to);
    }

    /// @dev this low-level function should be called from a contract which performs important safety checks
    /// @dev keeping bytes parameter for backward compatibility of the interface
    function swap(uint256 amount0Out, uint256 amount1Out, address to, bytes calldata) external lock {
        require(amount0Out > 0 || amount1Out > 0, "MagicswapV2: INSUFFICIENT_OUTPUT_AMOUNT");
        (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings
        require(amount0Out < _reserve0 && amount1Out < _reserve1, "MagicswapV2: INSUFFICIENT_LIQUIDITY");

        uint256 balance0;
        uint256 balance1;
        {
            // scope for _token{0,1}, avoids stack too deep errors
            address _token0 = token0;
            address _token1 = token1;
            require(to != _token0 && to != _token1, "MagicswapV2: INVALID_TO");
            if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens
            if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens
            balance0 = IERC20(_token0).balanceOf(address(this));
            balance1 = IERC20(_token1).balanceOf(address(this));
        }
        uint256 amount0In = balance0 > _reserve0 - amount0Out ? balance0 - (_reserve0 - amount0Out) : 0;
        uint256 amount1In = balance1 > _reserve1 - amount1Out ? balance1 - (_reserve1 - amount1Out) : 0;
        require(amount0In > 0 || amount1In > 0, "MagicswapV2: INSUFFICIENT_INPUT_AMOUNT");

        {
            // scope for reserve{0,1}Adjusted, avoids stack too deep errors
            uint256 totalFee = IUniswapV2Factory(factory).getTotalFee(address(this));
            uint256 balance0Adjusted = balance0.mul(BASIS_POINTS).sub(amount0In.mul(totalFee));
            uint256 balance1Adjusted = balance1.mul(BASIS_POINTS).sub(amount1In.mul(totalFee));
            require(
                balance0Adjusted.mul(balance1Adjusted) >= uint256(_reserve0).mul(_reserve1).mul(BASIS_POINTS ** 2),
                "MagicswapV2: K"
            );
            (balance0, balance1) = _takeFees(balance0Adjusted, balance1Adjusted, amount0In, amount1In);
        }

        _update(balance0, balance1, _reserve0, _reserve1);
        emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);
    }

    /// @dev Read TWAP price
    function observe(uint32[] calldata secondsAgos)
        external
        view
        override
        returns (uint256[] memory priceCumulatives)
    {
        return observations.observe(_blockTimestamp(), secondsAgos, lastPrice, observationIndex, observationCardinality);
    }

    /// @dev Increase number of data points for price history
    function increaseObservationCardinalityNext(uint16 _observationCardinalityNext) external override lock {
        uint16 observationCardinalityNextOld = observationCardinalityNext; // for the event
        uint16 observationCardinalityNextNew =
            observations.grow(observationCardinalityNextOld, _observationCardinalityNext);
        observationCardinalityNext = observationCardinalityNextNew;
        if (observationCardinalityNextOld != observationCardinalityNextNew) {
            emit IncreaseObservationCardinalityNext(observationCardinalityNextOld, observationCardinalityNextNew);
        }
    }

    /// @dev force balances to match reserves
    function skim(address to) external lock {
        address _token0 = token0; // gas savings
        address _token1 = token1; // gas savings
        _safeTransfer(_token0, to, IERC20(_token0).balanceOf(address(this)).sub(reserve0));
        _safeTransfer(_token1, to, IERC20(_token1).balanceOf(address(this)).sub(reserve1));
    }

    /// @dev force reserves to match balances
    function sync() external lock {
        _update(IERC20(token0).balanceOf(address(this)), IERC20(token1).balanceOf(address(this)), reserve0, reserve1);
    }
}

File 4 of 14 : Ownable2Step.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (access/Ownable2Step.sol)

pragma solidity ^0.8.0;

import "./Ownable.sol";

/**
 * @dev Contract module which provides access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership} and {acceptOwnership}.
 *
 * This module is used through inheritance. It will make available all functions
 * from parent (Ownable).
 */
abstract contract Ownable2Step is Ownable {
    address private _pendingOwner;

    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Returns the address of the pending owner.
     */
    function pendingOwner() public view virtual returns (address) {
        return _pendingOwner;
    }

    /**
     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual override onlyOwner {
        _pendingOwner = newOwner;
        emit OwnershipTransferStarted(owner(), newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual override {
        delete _pendingOwner;
        super._transferOwnership(newOwner);
    }

    /**
     * @dev The new owner accepts the ownership transfer.
     */
    function acceptOwnership() external {
        address sender = _msgSender();
        require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner");
        _transferOwnership(sender);
    }
}

File 5 of 14 : EnumerableSet.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.

pragma solidity ^0.8.0;

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```
 * contract Example {
 *     // Add the library methods
 *     using EnumerableSet for EnumerableSet.AddressSet;
 *
 *     // Declare a set state variable
 *     EnumerableSet.AddressSet private mySet;
 * }
 * ```
 *
 * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
 * and `uint256` (`UintSet`) are supported.
 *
 * [WARNING]
 * ====
 * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
 * unusable.
 * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
 *
 * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
 * array of EnumerableSet.
 * ====
 */
library EnumerableSet {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Set type with
    // bytes32 values.
    // The Set implementation uses private functions, and user-facing
    // implementations (such as AddressSet) are just wrappers around the
    // underlying Set.
    // This means that we can only create new EnumerableSets for types that fit
    // in bytes32.

    struct Set {
        // Storage of set values
        bytes32[] _values;
        // Position of the value in the `values` array, plus 1 because index 0
        // means a value is not in the set.
        mapping(bytes32 => uint256) _indexes;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function _add(Set storage set, bytes32 value) private returns (bool) {
        if (!_contains(set, value)) {
            set._values.push(value);
            // The value is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            set._indexes[value] = set._values.length;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function _remove(Set storage set, bytes32 value) private returns (bool) {
        // We read and store the value's index to prevent multiple reads from the same storage slot
        uint256 valueIndex = set._indexes[value];

        if (valueIndex != 0) {
            // Equivalent to contains(set, value)
            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
            // the array, and then remove the last element (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 toDeleteIndex = valueIndex - 1;
            uint256 lastIndex = set._values.length - 1;

            if (lastIndex != toDeleteIndex) {
                bytes32 lastValue = set._values[lastIndex];

                // Move the last value to the index where the value to delete is
                set._values[toDeleteIndex] = lastValue;
                // Update the index for the moved value
                set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex
            }

            // Delete the slot where the moved value was stored
            set._values.pop();

            // Delete the index for the deleted slot
            delete set._indexes[value];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function _contains(Set storage set, bytes32 value) private view returns (bool) {
        return set._indexes[value] != 0;
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function _length(Set storage set) private view returns (uint256) {
        return set._values.length;
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function _at(Set storage set, uint256 index) private view returns (bytes32) {
        return set._values[index];
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function _values(Set storage set) private view returns (bytes32[] memory) {
        return set._values;
    }

    // Bytes32Set

    struct Bytes32Set {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _add(set._inner, value);
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _remove(set._inner, value);
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
        return _contains(set._inner, value);
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(Bytes32Set storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
        return _at(set._inner, index);
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
        bytes32[] memory store = _values(set._inner);
        bytes32[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(AddressSet storage set, address value) internal returns (bool) {
        return _add(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(AddressSet storage set, address value) internal returns (bool) {
        return _remove(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(AddressSet storage set, address value) internal view returns (bool) {
        return _contains(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(AddressSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(AddressSet storage set, uint256 index) internal view returns (address) {
        return address(uint160(uint256(_at(set._inner, index))));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(AddressSet storage set) internal view returns (address[] memory) {
        bytes32[] memory store = _values(set._inner);
        address[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }

    // UintSet

    struct UintSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(UintSet storage set, uint256 value) internal returns (bool) {
        return _add(set._inner, bytes32(value));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(UintSet storage set, uint256 value) internal returns (bool) {
        return _remove(set._inner, bytes32(value));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(UintSet storage set, uint256 value) internal view returns (bool) {
        return _contains(set._inner, bytes32(value));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(UintSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(UintSet storage set, uint256 index) internal view returns (uint256) {
        return uint256(_at(set._inner, index));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(UintSet storage set) internal view returns (uint256[] memory) {
        bytes32[] memory store = _values(set._inner);
        uint256[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }
}

File 6 of 14 : IUniswapV2Pair.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

interface IUniswapV2Pair {
    event Mint(address indexed sender, uint256 amount0, uint256 amount1);
    event Burn(address indexed sender, uint256 amount0, uint256 amount1, address indexed to);
    event Swap(
        address indexed sender,
        uint256 amount0In,
        uint256 amount1In,
        uint256 amount0Out,
        uint256 amount1Out,
        address indexed to
    );
    event Sync(uint112 reserve0, uint112 reserve1);

    /// @notice Emitted by the pool for increases to the number of observations that can be stored
    /// @dev observationCardinalityNext is not the observation cardinality until an observation is written at the index
    /// just before a mint/swap/burn.
    /// @param observationCardinalityNextOld The previous value of the next observation cardinality
    /// @param observationCardinalityNextNew The updated value of the next observation cardinality
    event IncreaseObservationCardinalityNext(
        uint16 observationCardinalityNextOld, uint16 observationCardinalityNextNew
    );

    function MINIMUM_LIQUIDITY() external pure returns (uint256);
    function factory() external view returns (address);
    function token0() external view returns (address);
    function token1() external view returns (address);
    function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
    function observations(uint256 index)
        external
        view
        returns (uint32 blockTimestamp, uint256 priceCumulative, bool initialized);

    function observe(uint32[] calldata secondsAgos) external view returns (uint256[] memory tickCumulatives);
    function increaseObservationCardinalityNext(uint16 observationCardinalityNext) external;

    function mint(address to) external returns (uint256 liquidity);
    function burn(address to) external returns (uint256 amount0, uint256 amount1);
    function swap(uint256 amount0Out, uint256 amount1Out, address to, bytes calldata data) external;
    function skim(address to) external;
    function sync() external;

    function initialize(address, address) external;
}

File 7 of 14 : UniswapV2Math.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

// a library for performing various math operations

library UniswapV2Math {
    function min(uint256 x, uint256 y) internal pure returns (uint256 z) {
        z = x < y ? x : y;
    }

    // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method)
    function sqrt(uint256 y) internal pure returns (uint256 z) {
        if (y > 3) {
            z = y;
            uint256 x = y / 2 + 1;
            while (x < z) {
                z = x;
                x = (y / x + x) / 2;
            }
        } else if (y != 0) {
            z = 1;
        }
    }
}

File 8 of 14 : Oracle.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

/// @title Oracle (modifier version of Oracle.sol from UniswapV3)
/// @notice Provides price data useful for a wide variety of system designs
/// @dev Instances of stored oracle data, "observations", are collected in the oracle array
/// Every pool is initialized with an oracle array length of 1. Anyone can pay the SSTOREs to increase the
/// maximum length of the oracle array. New slots will be added when the array is fully populated.
/// Observations are overwritten when the full length of the oracle array is populated.
/// The most recent observation is available, independent of the length of the oracle array, by passing 0 to observe()
library Oracle {
    struct Observation {
        // the block timestamp of the observation
        uint32 blockTimestamp;
        // the price accumulator, i.e. price * time elapsed since the pool was first initialized
        uint256 priceCumulative;
        // whether or not the observation is initialized
        bool initialized;
    }

    /// @notice Transforms a previous observation into a new observation, given the passage of time and the current price values
    /// @dev blockTimestamp _must_ be chronologically equal to or greater than last.blockTimestamp, safe for 0 or 1 overflows
    /// @param last The specified observation to be transformed
    /// @param blockTimestamp The timestamp of the new observation
    /// @param lastPrice The active price at the time of the new observation
    /// @return Observation The newly populated observation
    function transform(Observation memory last, uint32 blockTimestamp, uint256 lastPrice)
        private
        pure
        returns (Observation memory)
    {
        uint32 delta = blockTimestamp - last.blockTimestamp;
        return Observation({
            blockTimestamp: blockTimestamp,
            priceCumulative: last.priceCumulative + lastPrice * delta,
            initialized: true
        });
    }

    /// @notice Initialize the oracle array by writing the first slot. Called once for the lifecycle of the observations array
    /// @param self The stored oracle array
    /// @param time The time of the oracle initialization, via block.timestamp truncated to uint32
    /// @return cardinality The number of populated elements in the oracle array
    /// @return cardinalityNext The new length of the oracle array, independent of population
    function initialize(Observation[65535] storage self, uint32 time)
        internal
        returns (uint16 cardinality, uint16 cardinalityNext)
    {
        self[0] = Observation({blockTimestamp: time, priceCumulative: 0, initialized: true});
        return (1, 1);
    }

    /// @notice Writes an oracle observation to the array
    /// @dev Writable at most once per block. Index represents the most recently written element. cardinality and index must be tracked externally.
    /// If the index is at the end of the allowable array length (according to cardinality), and the next cardinality
    /// is greater than the current one, cardinality may be increased. This restriction is created to preserve ordering.
    /// @param self The stored oracle array
    /// @param index The index of the observation that was most recently written to the observations array
    /// @param blockTimestamp The timestamp of the new observation
    /// @param lastPrice The active price at the time of the new observation
    /// @param cardinality The number of populated elements in the oracle array
    /// @param cardinalityNext The new length of the oracle array, independent of population
    /// @return indexUpdated The new index of the most recently written element in the oracle array
    /// @return cardinalityUpdated The new cardinality of the oracle array
    function write(
        Observation[65535] storage self,
        uint16 index,
        uint32 blockTimestamp,
        uint256 lastPrice,
        uint16 cardinality,
        uint16 cardinalityNext
    ) internal returns (uint16 indexUpdated, uint16 cardinalityUpdated) {
        Observation memory last = self[index];

        // early return if we've already written an observation this block
        if (last.blockTimestamp == blockTimestamp) return (index, cardinality);

        // if the conditions are right, we can bump the cardinality
        if (cardinalityNext > cardinality && index == (cardinality - 1)) {
            cardinalityUpdated = cardinalityNext;
        } else {
            cardinalityUpdated = cardinality;
        }

        indexUpdated = (index + 1) % cardinalityUpdated;
        self[indexUpdated] = transform(last, blockTimestamp, lastPrice);
    }

    /// @notice Prepares the oracle array to store up to `next` observations
    /// @param self The stored oracle array
    /// @param current The current next cardinality of the oracle array
    /// @param next The proposed next cardinality which will be populated in the oracle array
    /// @return next The next cardinality which will be populated in the oracle array
    function grow(Observation[65535] storage self, uint16 current, uint16 next) internal returns (uint16) {
        require(current > 0, "I");
        // no-op if the passed next value isn't greater than the current next value
        if (next <= current) return current;
        // store in each slot to prevent fresh SSTOREs in swaps
        // this data will not be used because the initialized boolean is still false
        for (uint16 i = current; i < next; i++) {
            self[i].blockTimestamp = 1;
        }
        return next;
    }

    /// @notice comparator for 32-bit timestamps
    /// @dev safe for 0 or 1 overflows, a and b _must_ be chronologically before or equal to time
    /// @param time A timestamp truncated to 32 bits
    /// @param a A comparison timestamp from which to determine the relative position of `time`
    /// @param b From which to determine the relative position of `time`
    /// @return bool Whether `a` is chronologically <= `b`
    function lte(uint32 time, uint32 a, uint32 b) private pure returns (bool) {
        // if there hasn't been overflow, no need to adjust
        if (a <= time && b <= time) return a <= b;

        uint256 aAdjusted = a > time ? a : a + 2 ** 32;
        uint256 bAdjusted = b > time ? b : b + 2 ** 32;

        return aAdjusted <= bAdjusted;
    }

    /// @notice Fetches the observations beforeOrAt and atOrAfter a target, i.e. where [beforeOrAt, atOrAfter] is satisfied.
    /// The result may be the same observation, or adjacent observations.
    /// @dev The answer must be contained in the array, used when the target is located within the stored observation
    /// boundaries: older than the most recent observation and younger, or the same age as, the oldest observation
    /// @param self The stored oracle array
    /// @param time The current block.timestamp
    /// @param target The timestamp at which the reserved observation should be for
    /// @param index The index of the observation that was most recently written to the observations array
    /// @param cardinality The number of populated elements in the oracle array
    /// @return beforeOrAt The observation recorded before, or at, the target
    /// @return atOrAfter The observation recorded at, or after, the target
    function binarySearch(Observation[65535] storage self, uint32 time, uint32 target, uint16 index, uint16 cardinality)
        private
        view
        returns (Observation memory beforeOrAt, Observation memory atOrAfter)
    {
        uint256 l = (index + 1) % cardinality; // oldest observation
        uint256 r = l + cardinality - 1; // newest observation
        uint256 i;
        while (true) {
            i = (l + r) / 2;

            beforeOrAt = self[i % cardinality];

            // we've landed on an uninitialized price, keep searching higher (more recently)
            if (!beforeOrAt.initialized) {
                l = i + 1;
                continue;
            }

            atOrAfter = self[(i + 1) % cardinality];

            bool targetAtOrAfter = lte(time, beforeOrAt.blockTimestamp, target);

            // check if we've found the answer!
            if (targetAtOrAfter && lte(time, target, atOrAfter.blockTimestamp)) break;

            if (!targetAtOrAfter) r = i - 1;
            else l = i + 1;
        }
    }

    /// @notice Fetches the observations beforeOrAt and atOrAfter a given target, i.e. where [beforeOrAt, atOrAfter] is satisfied
    /// @dev Assumes there is at least 1 initialized observation.
    /// Used by observeSingle() to compute the counterfactual accumulator values as of a given block timestamp.
    /// @param self The stored oracle array
    /// @param time The current block.timestamp
    /// @param target The timestamp at which the reserved observation should be for
    /// @param lastPrice The active price at the time of the returned or simulated observation
    /// @param index The index of the observation that was most recently written to the observations array
    /// @param cardinality The number of populated elements in the oracle array
    /// @return beforeOrAt The observation which occurred at, or before, the given timestamp
    /// @return atOrAfter The observation which occurred at, or after, the given timestamp
    function getSurroundingObservations(
        Observation[65535] storage self,
        uint32 time,
        uint32 target,
        uint256 lastPrice,
        uint16 index,
        uint16 cardinality
    ) private view returns (Observation memory beforeOrAt, Observation memory atOrAfter) {
        // optimistically set before to the newest observation
        beforeOrAt = self[index];

        // if the target is chronologically at or after the newest observation, we can early return
        if (lte(time, beforeOrAt.blockTimestamp, target)) {
            if (beforeOrAt.blockTimestamp == target) {
                // if newest observation equals target, we're in the same block, so we can ignore atOrAfter
                return (beforeOrAt, atOrAfter);
            } else {
                // otherwise, we need to transform
                return (beforeOrAt, transform(beforeOrAt, target, lastPrice));
            }
        }

        // now, set before to the oldest observation
        beforeOrAt = self[(index + 1) % cardinality];
        if (!beforeOrAt.initialized) beforeOrAt = self[0];

        // ensure that the target is chronologically at or after the oldest observation
        require(lte(time, beforeOrAt.blockTimestamp, target), "OLD");

        // if we've reached this point, we have to binary search
        return binarySearch(self, time, target, index, cardinality);
    }

    /// @dev Reverts if an observation at or before the desired observation timestamp does not exist.
    /// 0 may be passed as `secondsAgo' to return the current cumulative values.
    /// If called with a timestamp falling between two observations, returns the counterfactual accumulator values
    /// at exactly the timestamp between the two observations.
    /// @param self The stored oracle array
    /// @param time The current block timestamp
    /// @param secondsAgo The amount of time to look back, in seconds, at which point to return an observation
    /// @param lastPrice The current price
    /// @param index The index of the observation that was most recently written to the observations array
    /// @param cardinality The number of populated elements in the oracle array
    /// @return priceCumulative The price * time elapsed since the pool was first initialized, as of `secondsAgo`
    function observeSingle(
        Observation[65535] storage self,
        uint32 time,
        uint32 secondsAgo,
        uint256 lastPrice,
        uint16 index,
        uint16 cardinality
    ) internal view returns (uint256 priceCumulative) {
        if (secondsAgo == 0) {
            Observation memory last = self[index];
            if (last.blockTimestamp != time) last = transform(last, time, lastPrice);
            return last.priceCumulative;
        }

        uint32 target = time - secondsAgo;

        (Observation memory beforeOrAt, Observation memory atOrAfter) =
            getSurroundingObservations(self, time, target, lastPrice, index, cardinality);

        if (target == beforeOrAt.blockTimestamp) {
            // we're at the left boundary
            return beforeOrAt.priceCumulative;
        } else if (target == atOrAfter.blockTimestamp) {
            // we're at the right boundary
            return atOrAfter.priceCumulative;
        } else {
            // we're in the middle
            uint32 observationTimeDelta = atOrAfter.blockTimestamp - beforeOrAt.blockTimestamp;
            uint32 targetDelta = target - beforeOrAt.blockTimestamp;
            return beforeOrAt.priceCumulative
                + ((atOrAfter.priceCumulative - beforeOrAt.priceCumulative) / observationTimeDelta) * targetDelta;
        }
    }

    /// @notice Returns the accumulator values as of each time seconds ago from the given time in the array of `secondsAgos`
    /// @dev Reverts if `secondsAgos` > oldest observation
    /// @param self The stored oracle array
    /// @param time The current block.timestamp
    /// @param secondsAgos Each amount of time to look back, in seconds, at which point to return an observation
    /// @param lastPrice The current price
    /// @param index The index of the observation that was most recently written to the observations array
    /// @param cardinality The number of populated elements in the oracle array
    /// @return priceCumulatives The price * time elapsed since the pool was first initialized, as of each `secondsAgo`
    function observe(
        Observation[65535] storage self,
        uint32 time,
        uint32[] memory secondsAgos,
        uint256 lastPrice,
        uint16 index,
        uint16 cardinality
    ) internal view returns (uint256[] memory priceCumulatives) {
        require(cardinality > 0, "I");

        priceCumulatives = new uint256[](secondsAgos.length);
        for (uint256 i = 0; i < secondsAgos.length; i++) {
            priceCumulatives[i] = observeSingle(self, time, secondsAgos[i], lastPrice, index, cardinality);
        }
    }
}

File 9 of 14 : UniswapV2ERC20.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

import "./interfaces/IUniswapV2ERC20.sol";
import "./libraries/SafeMath.sol";

contract UniswapV2ERC20 is IUniswapV2ERC20 {
    using SafeMath for uint256;

    string public constant name = "Magicswap V2";
    string public constant symbol = "MAGIC-V2";
    uint8 public constant decimals = 18;
    uint256 public totalSupply;
    mapping(address => uint256) public balanceOf;
    mapping(address => mapping(address => uint256)) public allowance;

    bytes32 public override DOMAIN_SEPARATOR;
    // keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
    bytes32 public constant override PERMIT_TYPEHASH =
        0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;
    mapping(address => uint256) public nonces;

    constructor() {
        uint256 chainId;
        assembly {
            chainId := chainid()
        }
        DOMAIN_SEPARATOR = keccak256(
            abi.encode(
                keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
                keccak256(bytes(name)),
                keccak256(bytes("1")),
                chainId,
                address(this)
            )
        );
    }

    function _mint(address to, uint256 value) internal {
        totalSupply = totalSupply.add(value);
        balanceOf[to] = balanceOf[to].add(value);
        emit Transfer(address(0), to, value);
    }

    function _burn(address from, uint256 value) internal {
        balanceOf[from] = balanceOf[from].sub(value);
        totalSupply = totalSupply.sub(value);
        emit Transfer(from, address(0), value);
    }

    function _approve(address owner, address spender, uint256 value) private {
        allowance[owner][spender] = value;
        emit Approval(owner, spender, value);
    }

    function _transfer(address from, address to, uint256 value) private {
        balanceOf[from] = balanceOf[from].sub(value);
        balanceOf[to] = balanceOf[to].add(value);
        emit Transfer(from, to, value);
    }

    function approve(address spender, uint256 value) external returns (bool) {
        _approve(msg.sender, spender, value);
        return true;
    }

    function transfer(address to, uint256 value) external returns (bool) {
        _transfer(msg.sender, to, value);
        return true;
    }

    function transferFrom(address from, address to, uint256 value) external returns (bool) {
        if (allowance[from][msg.sender] != type(uint256).max) {
            allowance[from][msg.sender] = allowance[from][msg.sender].sub(value);
        }
        _transfer(from, to, value);
        return true;
    }

    function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
        external
    {
        require(deadline >= block.timestamp, "MagicswapV2: EXPIRED");
        bytes32 digest = keccak256(
            abi.encodePacked(
                "\x19\x01",
                DOMAIN_SEPARATOR,
                keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline))
            )
        );
        address recoveredAddress = ecrecover(digest, v, r, s);
        require(recoveredAddress != address(0) && recoveredAddress == owner, "MagicswapV2: INVALID_SIGNATURE");
        _approve(owner, spender, value);
    }
}

File 10 of 14 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.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 11 of 14 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

File 12 of 14 : SafeMath.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

// a library for performing overflow-safe math, courtesy of DappHub (https://github.com/dapphub/ds-math)

library SafeMath {
    function add(uint256 x, uint256 y) internal pure returns (uint256 z) {
        require((z = x + y) >= x, "ds-math-add-overflow");
    }

    function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {
        require((z = x - y) <= x, "ds-math-sub-underflow");
    }

    function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {
        require(y == 0 || (z = x * y) / y == x, "ds-math-mul-overflow");
    }
}

File 13 of 14 : IUniswapV2ERC20.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

interface IUniswapV2ERC20 {
    event Approval(address indexed owner, address indexed spender, uint256 value);
    event Transfer(address indexed from, address indexed to, uint256 value);

    function name() external pure returns (string memory);
    function symbol() external pure returns (string memory);
    function decimals() external pure returns (uint8);
    function totalSupply() external view returns (uint256);
    function balanceOf(address owner) external view returns (uint256);
    function allowance(address owner, address spender) external view returns (uint256);

    function approve(address spender, uint256 value) external returns (bool);
    function transfer(address to, uint256 value) external returns (bool);
    function transferFrom(address from, address to, uint256 value) external returns (bool);

    function DOMAIN_SEPARATOR() external view returns (bytes32);
    function PERMIT_TYPEHASH() external pure returns (bytes32);
    function nonces(address owner) external view returns (uint256);

    function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
        external;
}

File 14 of 14 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

Settings
{
  "evmVersion": "paris",
  "optimizer": {
    "enabled": true,
    "mode": "3"
  },
  "outputSelection": {
    "*": {
      "*": [
        "abi"
      ]
    }
  },
  "detectMissingLibraries": false,
  "forceEVMLA": false,
  "enableEraVMExtensions": false,
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"uint256","name":"_defaultProtocolFee","type":"uint256"},{"internalType":"uint256","name":"_defaultLpFee","type":"uint256"},{"internalType":"address","name":"_protocolFeeBeneficiary","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint256","name":"protocolFee","type":"uint256"},{"internalType":"uint256","name":"lpFee","type":"uint256"}],"indexed":false,"internalType":"struct IUniswapV2Factory.DefaultFees","name":"fees","type":"tuple"}],"name":"DefaultFeesSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pair","type":"address"},{"indexed":false,"internalType":"uint256","name":"lpFee","type":"uint256"},{"indexed":false,"internalType":"bool","name":"overrideFee","type":"bool"}],"name":"LpFeesSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token0","type":"address"},{"indexed":true,"internalType":"address","name":"token1","type":"address"},{"indexed":false,"internalType":"address","name":"pair","type":"address"},{"indexed":false,"internalType":"uint256","name":"","type":"uint256"}],"name":"PairCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"beneficiary","type":"address"}],"name":"ProtocolFeeBeneficiarySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pair","type":"address"},{"indexed":false,"internalType":"uint256","name":"protocolFee","type":"uint256"},{"indexed":false,"internalType":"bool","name":"overrideFee","type":"bool"}],"name":"ProtocolFeesSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pair","type":"address"},{"indexed":false,"internalType":"address","name":"beneficiary","type":"address"},{"indexed":false,"internalType":"uint256","name":"royaltiesFee","type":"uint256"}],"name":"RoyaltiesFeesSet","type":"event"},{"inputs":[],"name":"MAX_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"allPairs","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"allPairs","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"allPairsLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"}],"name":"createPair","outputs":[{"internalType":"address","name":"pair","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"defaultFees","outputs":[{"internalType":"uint256","name":"protocolFee","type":"uint256"},{"internalType":"uint256","name":"lpFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_pair","type":"address"}],"name":"getFees","outputs":[{"internalType":"uint256","name":"lpFee","type":"uint256"},{"internalType":"uint256","name":"royaltiesFee","type":"uint256"},{"internalType":"uint256","name":"protocolFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_pair","type":"address"}],"name":"getFeesAndRecipients","outputs":[{"internalType":"uint256","name":"lpFee","type":"uint256"},{"internalType":"address","name":"royaltiesBeneficiary","type":"address"},{"internalType":"uint256","name":"royaltiesFee","type":"uint256"},{"internalType":"address","name":"protocolBeneficiary","type":"address"},{"internalType":"uint256","name":"protocolFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"getPair","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_pair","type":"address"}],"name":"getTotalFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"pairFees","outputs":[{"internalType":"address","name":"royaltiesBeneficiary","type":"address"},{"internalType":"uint256","name":"royaltiesFee","type":"uint256"},{"internalType":"uint256","name":"protocolFee","type":"uint256"},{"internalType":"uint256","name":"lpFee","type":"uint256"},{"internalType":"bool","name":"protocolFeeOverride","type":"bool"},{"internalType":"bool","name":"lpFeeOverride","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolFeeBeneficiary","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"protocolFee","type":"uint256"},{"internalType":"uint256","name":"lpFee","type":"uint256"}],"internalType":"struct IUniswapV2Factory.DefaultFees","name":"_fees","type":"tuple"}],"name":"setDefaultFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_pair","type":"address"},{"internalType":"uint256","name":"_lpFee","type":"uint256"},{"internalType":"bool","name":"_overrideFee","type":"bool"}],"name":"setLpFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_pair","type":"address"},{"internalType":"uint256","name":"_protocolFee","type":"uint256"},{"internalType":"bool","name":"_overrideFee","type":"bool"}],"name":"setProtocolFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_beneficiary","type":"address"}],"name":"setProtocolFeeBeneficiary","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_pair","type":"address"},{"internalType":"address","name":"_beneficiary","type":"address"},{"internalType":"uint256","name":"_royaltiesFee","type":"uint256"}],"name":"setRoyaltiesFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]

9c4d535b000000000000000000000000000000000000000000000000000000000000000001000215c679199dcb92c87dfc356cf6aa5198d06dcdd9b73412e2d32c2b0bd000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000005a25839b49eec2d4c173b42668a84f5988599929

Deployed Bytecode

0x000400000000000200000000030100190000006003300270000001b1033001970000000100200190000000300000c13d0000008002000039000000400020043f000000040030008c000006190000413d000000000201043b000000e002200270000001c80020009c000000760000213d000001d70020009c000000850000a13d000001d80020009c000000a40000213d000001dc0020009c0000011d0000613d000001dd0020009c000001420000613d000001de0020009c000006190000c13d0000000001000416000000000001004b000006190000c13d000000000100041a000001b4021001970000000005000411000000000052004b000002bf0000c13d0000000102000039000000000302041a000001b503300197000000000032041b000001b501100197000000000010041b0000000001000414000001b10010009c000001b101008041000000c001100210000001b6011001c70000800d020000390000000303000039000001b7040000410000000006000019000005a80000013d0000000002000416000000000002004b000006190000c13d0000001f02300039000001b2022001970000008002200039000000400020043f0000001f0430018f000001b3053001980000008002500039000000410000613d0000008006000039000000000701034f000000007807043c0000000006860436000000000026004b0000003d0000c13d000000000004004b0000004e0000613d000000000151034f0000000304400210000000000502043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f0000000000120435000000600030008c000006190000413d000000c00100043d000400000001001d000001b40010009c000006190000213d000000a00100043d000200000001001d000000800100043d000300000001001d0000000101000039000000000201041a000001b502200197000000000021041b000000000100041a000001b5021001970000000006000411000000000262019f000000000020041b0000000002000414000001b405100197000001b10020009c000001b102008041000000c001200210000001b6011001c70000800d020000390000000303000039000001b70400004106c006b60000040f0000000100200190000006190000613d000000400100043d000001b80010009c000000fc0000a13d000001f901000041000000000010043f0000004101000039000000040010043f000001fa01000041000006c200010430000001c90020009c000000950000a13d000001ca0020009c000000af0000213d000001ce0020009c000001690000613d000001cf0020009c000001760000613d000001d00020009c000006190000c13d0000000001000416000000000001004b000006190000c13d0000000201000039000002760000013d000001df0020009c000000d10000a13d000001e00020009c0000018f0000613d000001e10020009c000001b60000613d000001e20020009c000006190000c13d0000000001000416000000000001004b000006190000c13d0000000401000039000000000101041a000000800010043f000001e701000041000006c10001042e000001d10020009c000000e30000a13d000001d20020009c000001da0000613d000001d30020009c000002070000613d000001d40020009c000006190000c13d0000000001000416000000000001004b000006190000c13d0000138801000039000000800010043f000001e701000041000006c10001042e000001d90020009c000002270000613d000001da0020009c000002400000613d000001db0020009c000006190000c13d0000000001000416000000000001004b000006190000c13d000000000100041a000002770000013d000001cb0020009c000002720000613d000001cc0020009c0000027b0000613d000001cd0020009c000006190000c13d000000240030008c000006190000413d0000000002000416000000000002004b000006190000c13d0000000401100370000000000601043b000001b40060009c000006190000213d000000000100041a000001b4011001970000000005000411000000000051004b000002bf0000c13d0000000101000039000000000201041a000001b502200197000000000262019f000000000021041b0000000001000414000001b10010009c000001b101008041000000c001100210000001b6011001c70000800d020000390000000303000039000001e504000041000005a80000013d000001e30020009c0000029a0000613d000001e40020009c000006190000c13d000000240030008c000006190000413d0000000002000416000000000002004b000006190000c13d0000000401100370000000000101043b0000000402000039000000000302041a000000000031004b000002d50000813d000000000020043f000001f20110009a000002760000013d000001d50020009c000002a50000613d000001d60020009c000006190000c13d000000240030008c000006190000413d0000000002000416000000000002004b000006190000c13d0000000401100370000000000101043b000001b40010009c000006190000213d06c0064d0000040f000000400400043d00000020054000390000000000250435000000400240003900000000003204350000000000140435000001b10040009c000001b1040080410000004001400210000001ff011001c7000006c10001042e0000004002100039000000400020043f0000000304000029000000000241043600000002050000290000000000520435000000000100041a000001b4011001970000000003000411000000000031004b000003550000c13d000000400100043d000013890040008c000002c80000413d0000006402100039000001c60300004100000000003204350000004402100039000001c7030000410000000000320435000000240210003900000022030000390000000000320435000001bc020000410000000000210435000000040210003900000020030000390000000000320435000001b10010009c000001b1010080410000004001100210000001c4011001c7000006c200010430000000640030008c000006190000413d0000000002000416000000000002004b000006190000c13d0000000402100370000000000202043b000400000002001d000001b40020009c000006190000213d0000004402100370000000000302043b000000000003004b0000000002000039000000010200c039000300000003001d000000000023004b000006190000c13d0000002401100370000000000301043b000000000100041a000001b4011001970000000002000411000000000021004b000002bf0000c13d000013890030008c000003c50000413d000001bc01000041000000800010043f0000002001000039000000840010043f0000001d01000039000000a40010043f0000020601000041000000c40010043f000001f501000041000006c200010430000000240030008c000006190000413d0000000002000416000000000002004b000006190000c13d0000000401100370000000000101043b000001b40010009c000006190000213d000000000010043f0000000801000039000000200010043f0000004002000039000000000100001906c006a10000040f0000000402100039000000000202041a0000000303100039000000000303041a0000000204100039000000000404041a0000000105100039000000000505041a000000000101041a000001b401100197000000800010043f000000a00050043f000000c00040043f000000e00030043f000000ff002001900000000001000039000000010100c039000001000010043f0000ff00002001900000000001000039000000010100c039000001200010043f0000020401000041000006c10001042e0000000001000416000000000001004b000006190000c13d0000000402000039000000000102041a000000800010043f000000000020043f0000002002000039000000000001004b000002db0000c13d000000a0010000390000000004020019000002ea0000013d000000440030008c000006190000413d0000000002000416000000000002004b000006190000c13d0000000402100370000000000302043b0000000002030019000001b40030009c000006190000213d0000002401100370000000000101043b000001b40010009c000006190000213d000000000012004b000003650000c13d000001bc01000041000000800010043f0000002001000039000000840010043f000000a40010043f000001f601000041000000c40010043f000001f501000041000006c200010430000000640030008c000006190000413d0000000002000416000000000002004b000006190000c13d0000000402100370000000000202043b000400000002001d000001b40020009c000006190000213d0000004402100370000000000302043b000000000003004b0000000002000039000000010200c039000300000003001d000000000023004b000006190000c13d0000002401100370000000000301043b000000000100041a000001b4011001970000000002000411000000000021004b000002bf0000c13d000013890030008c0000040f0000413d000001bc01000041000000800010043f0000002001000039000000840010043f0000002301000039000000a40010043f0000020e01000041000000c40010043f0000020f01000041000000e40010043f0000020301000041000006c200010430000000640030008c000006190000413d0000000002000416000000000002004b000006190000c13d0000000402100370000000000202043b000400000002001d000001b40020009c000006190000213d0000002402100370000000000202043b000300000002001d000001b40020009c000006190000213d0000004401100370000000000301043b000000000100041a000001b4011001970000000002000411000000000021004b000002bf0000c13d000013890030008c000004580000413d000001bc01000041000000800010043f0000002001000039000000840010043f0000002401000039000000a40010043f0000020a01000041000000c40010043f0000020b01000041000000e40010043f0000020301000041000006c200010430000000240030008c000006190000413d0000000002000416000000000002004b000006190000c13d0000000401100370000000000201043b0000000001020019000001b40020009c000006190000213d000400000001001d06c0064d0000040f0000000404000029000000000040043f0000000804000039000000200040043f000400000001001d000200000002001d000300000003001d0000004002000039000000000100001906c006a10000040f000000000101041a0000000202000039000000000202041a000001b402200197000000400300043d00000060043000390000000000240435000001b4011001970000002002300039000000000012043500000040013000390000000202000029000000000021043500000080013000390000000302000029000000000021043500000004010000290000000000130435000001b10030009c000001b1030080410000004001300210000001fe011001c7000006c10001042e000000440030008c000006190000413d0000000002000416000000000002004b000006190000c13d000000c002000039000000400020043f0000000402100370000000000202043b000000800020043f0000002401100370000000000101043b000000a00010043f000000000300041a000001b4033001970000000004000411000000000043004b000003030000c13d000013890020008c000003240000413d000001bc01000041000000c00010043f0000002001000039000000c40010043f0000002201000039000000e40010043f000001c701000041000001040010043f000001c601000041000001240010043f000001fd01000041000006c2000104300000000001000416000000000001004b000006190000c13d0000000101000039000000000201041a000001b4032001970000000006000411000000000063004b0000030c0000c13d000001b502200197000000000021041b000000000100041a000001b502100197000000000262019f000000000020041b0000000002000414000001b405100197000001b10020009c000001b102008041000000c001200210000001b6011001c70000800d020000390000000303000039000001b704000041000005a80000013d000000240030008c000006190000413d0000000002000416000000000002004b000006190000c13d0000000401100370000000000101043b000400000001001d000001b40010009c000006190000213d0000000401000029000000000010043f0000000801000039000000200010043f0000000001000414000001b10010009c000001b101008041000000c001100210000001b9011001c7000080100200003906c006bb0000040f0000000100200190000006190000613d000000000101043b0000000402100039000000000202041a0000ff0000200190000000030110c0390000000701006039000000000101041a000013870010008c000003740000a13d000013880300003900000000020000190000000004000019000000000032001a0000026c0000413d00000000023200190000000001420019000000000021004b00000000020000390000000102004039000000010020008c000002930000c13d000001f901000041000000000010043f0000001101000039000000040010043f000001fa01000041000006c2000104300000000001000416000000000001004b000006190000c13d0000000101000039000000000101041a000001b401100197000000800010043f000001e701000041000006c10001042e000000440030008c000006190000413d0000000002000416000000000002004b000006190000c13d0000000402100370000000000202043b000001b40020009c000006190000213d0000002401100370000000000101043b000400000001001d000001b40010009c000006190000213d000000000020043f0000000301000039000000200010043f0000004002000039000000000100001906c006a10000040f000000040200002906c0063d0000040f000000000101041a000001b401100197000000400200043d0000000000120435000001b10020009c000001b1020080410000004001200210000001e6011001c7000006c10001042e0000000001000416000000000001004b000006190000c13d0000000701000039000000000101041a0000000602000039000000000202041a000000800020043f000000a00010043f0000021001000041000006c10001042e000000240030008c000006190000413d0000000002000416000000000002004b000006190000c13d0000000401100370000000000101043b000001b40010009c000006190000213d000000000200041a000001b4022001970000000003000411000000000032004b000002bf0000c13d000000000001004b000003a70000c13d000001bc01000041000000800010043f0000002001000039000000840010043f0000001801000039000000a40010043f000001c101000041000000c40010043f000001f501000041000006c200010430000001bc01000041000000800010043f0000002001000039000000840010043f000000a40010043f000001bb01000041000000c40010043f000001f501000041000006c200010430000013890050008c000003180000413d0000004402100039000001c503000041000000000032043500000024021000390000001c030000390000000000320435000001bc020000410000000000210435000000040210003900000020030000390000035f0000013d000001f901000041000000000010043f0000003201000039000000040010043f000001fa01000041000006c200010430000000a005000039000001f70300004100000000040000190000000006050019000000000503041a000000000556043600000001033000390000000104400039000000000014004b000002de0000413d000000410160008a0000021104100197000001f80040009c000000700000213d0000008001400039000000400010043f0000000000210435000000a002400039000000800300043d0000000000320435000000c002400039000000000003004b000002fa0000613d000000a00400003900000000050000190000000046040434000001b40660019700000000026204360000000105500039000000000035004b000002f40000413d0000000002120049000001b10020009c000001b1020080410000006002200210000001b10010009c000001b1010080410000004001100210000000000112019f000006c10001042e000001bc01000041000000c00010043f0000002001000039000000c40010043f000000e40010043f000001bb01000041000001040010043f000001fb01000041000006c200010430000001bc01000041000000800010043f0000002001000039000000840010043f0000002901000039000000a40010043f0000020101000041000000c40010043f0000020201000041000000e40010043f0000020301000041000006c2000104300000000003450019000013890030008c000003300000413d0000006402100039000001c20300004100000000003204350000004402100039000001c303000041000000000032043500000024021000390000002a03000039000001120000013d000013890010008c000003b60000413d000001bc01000041000000c00010043f0000002001000039000000c40010043f0000001c01000039000000e40010043f000001c501000041000001040010043f000001fb01000041000006c2000104300000000603000039000000000043041b0000000703000039000000000053041b000000000341043600000000020204330000000000230435000001b10010009c000001b10100804100000040011002100000000002000414000001b10020009c000001b102008041000000c002200210000000000112019f000001b9011001c70000800d020000390000000103000039000001ba0400004106c006b60000040f0000000100200190000006190000613d000000000100041a000001b4011001970000000002000411000000000021004b000003550000c13d0000000401000029000001b402100198000000400100043d000005ad0000c13d0000004402100039000001c103000041000000000032043500000024021000390000001803000039000002cf0000013d000000400100043d0000004402100039000001bb030000410000000000320435000001bc02000041000000000021043500000024021000390000002003000039000000000032043500000004021000390000000000320435000001b10010009c000001b1010080410000004001100210000001bd011001c7000006c200010430000000000301001900000000030220190000000002018019000000000002004b000004710000c13d000001bc01000041000000800010043f0000002001000039000000840010043f0000001901000039000000a40010043f000001f401000041000000c40010043f000001f501000041000006c200010430000300000001001d0000000401000029000000000010043f0000000801000039000000200010043f0000000001000414000001b10010009c000001b101008041000000c001100210000001b9011001c7000080100200003906c006bb0000040f0000000100200190000006190000613d00000003030000290000138802300089000000000101043b0000000101100039000000000101041a000000000412004b000002620000a13d000200000004001d000100000001001d0000000401000029000000000010043f0000000801000039000000200010043f0000000001000414000001b10010009c000001b101008041000000c001100210000001b9011001c7000080100200003906c006bb0000040f0000000100200190000006190000613d000000000101043b0000000402100039000000000202041a000000ff00200190000000020110c0390000000601006039000000000101041a0000000204000029000000000041004b000000000401a01900000003030000290000000102000029000000000032001a0000026c0000413d000002650000013d0000000202000039000000000302041a000001b503300197000000000313019f000000000032041b000000800010043f0000000001000414000001b10010009c000001b101008041000000c00110021000000200011001c70000800d020000390000000103000039000001bf04000041000005a80000013d0000000003210019000013890030008c0000059a0000413d000001bc01000041000000c00010043f0000002001000039000000c40010043f0000002a01000039000000e40010043f000001c301000041000001040010043f000001c201000041000001240010043f000001fd01000041000006c200010430000200000003001d0000000401000029000000000010043f0000000501000039000000200010043f0000000001000414000001b10010009c000001b101008041000000c001100210000001b9011001c7000080100200003906c006bb0000040f0000000100200190000006190000613d000000000101043b000000000101041a000000000001004b0000046a0000613d0000000401000029000000000010043f0000000801000039000000200010043f0000000001000414000001b10010009c000001b101008041000000c001100210000001b9011001c7000080100200003906c006bb0000040f0000000100200190000006190000613d000000000101043b00000003011000390000000202000029000000000021041b0000000401000029000000000010043f0000000801000039000000200010043f0000000001000414000001b10010009c000001b101008041000000c001100210000001b9011001c7000080100200003906c006bb0000040f0000000100200190000006190000613d000000000101043b0000000401100039000000000201041a00000212022001970000000303000029000000000003004b000001000220c1bf000000000021041b000000400100043d0000002002100039000000000032043500000002020000290000000000210435000001b10010009c000001b10100804100000040011002100000000002000414000001b10020009c000001b102008041000000c002200210000000000112019f000001b9011001c70000800d0200003900000002030000390000020504000041000006170000013d000200000003001d0000000401000029000000000010043f0000000501000039000000200010043f0000000001000414000001b10010009c000001b101008041000000c001100210000001b9011001c7000080100200003906c006bb0000040f0000000100200190000006190000613d000000000101043b000000000101041a000000000001004b0000046a0000613d0000000401000029000000000010043f0000000801000039000000200010043f0000000001000414000001b10010009c000001b101008041000000c001100210000001b9011001c7000080100200003906c006bb0000040f0000000100200190000006190000613d000000000101043b00000002011000390000000202000029000000000021041b0000000401000029000000000010043f0000000801000039000000200010043f0000000001000414000001b10010009c000001b101008041000000c001100210000001b9011001c7000080100200003906c006bb0000040f0000000100200190000006190000613d000000000101043b0000000401100039000000000201041a00000213022001970000000303000029000000000232019f000000000021041b000000400100043d0000002002100039000000000032043500000002020000290000000000210435000001b10010009c000001b10100804100000040011002100000000002000414000001b10020009c000001b102008041000000c002200210000000000112019f000001b9011001c70000800d0200003900000002030000390000020c04000041000006170000013d000200000003001d0000000401000029000000000010043f0000000501000039000000200010043f0000000001000414000001b10010009c000001b101008041000000c001100210000001b9011001c7000080100200003906c006bb0000040f0000000100200190000006190000613d000000000101043b000000000101041a000000000001004b000005c70000c13d000000400100043d00000044021000390000020d03000041000000000032043500000024021000390000001a03000039000002cf0000013d000400000003001d000300000002001d000000000020043f0000000301000039000000200010043f0000000001000414000001b10010009c000001b101008041000000c001100210000001b9011001c7000080100200003906c006bb0000040f0000000100200190000006190000613d000000000101043b0000000402000029000000000020043f000000200010043f0000000001000414000001b10010009c000001b101008041000000c001100210000001b9011001c7000080100200003906c006bb0000040f0000000100200190000006190000613d000000400300043d000000000101043b000000000101041a000001b400100198000005d30000c13d000200000003001d000001e90030009c000000700000213d0000000203000029000000c001300039000000400010043f0000004401300039000001ea02000041000000000021043500000084010000390000000001130436000100000001001d00000003010000290000006003100210000000400100043d00000020021000390000000000320435000000040300002900000060033002100000003404100039000000000034043500000028030000390000000000310435000001eb0010009c000000700000213d0000006003100039000000400030043f000001b10020009c000001b10200804100000040022002100000000001010433000001b10010009c000001b1010080410000006001100210000000000121019f0000000002000414000001b10020009c000001b102008041000000c002200210000000000112019f000001b6011001c7000080100200003906c006bb0000040f0000000100200190000006190000613d000000000101043b000000020600002900000000020604330000000003000414000001ec04000041000000010700002900000000004704350000008404600039000000840520008a000000000054043500000064046000390000006005000039000000000054043500000024046000390000000000140435000001b10070009c000001b1070080410000004001700210000001b10020009c000001b1020080410000006002200210000000000112019f000001b10030009c000001b103008041000000c002300210000000000112019f000001b6011001c7000080060200003906c006b60000040f0000000100200190000200000000001d000004e00000613d000000000101043b000201b40010019b000001ed010000410000000000100443000000020100002900000004001004430000000001000414000001b10010009c000001b101008041000000c001100210000001ee011001c7000080020200003906c006bb0000040f00000001002001900000061b0000613d000000000101043b000000000001004b000006190000613d000000400300043d000000240130003900000004020000290000000000210435000001ef010000410000000000130435000100000003001d00000004013000390000000302000029000000000021043500000000010004140000000202000029000000040020008c0000050b0000613d0000000102000029000001b10020009c000001b1020080410000004002200210000001b10010009c000001b101008041000000c001100210000000000121019f000001f0011001c7000000020200002906c006b60000040f00000001002001900000061c0000613d0000000101000029000001f10010009c000000700000213d0000000101000029000000400010043f0000000301000029000000000010043f0000000301000039000000200010043f0000000001000414000001b10010009c000001b101008041000000c001100210000001b9011001c7000080100200003906c006bb0000040f0000000100200190000006190000613d000000000101043b0000000402000029000000000020043f000000200010043f0000000001000414000001b10010009c000001b101008041000000c001100210000001b9011001c7000080100200003906c006bb0000040f0000000100200190000006190000613d000000000101043b000000000201041a000001b50220019700000002022001af000000000021041b0000000401000029000000000010043f0000000301000039000000200010043f0000000001000414000001b10010009c000001b101008041000000c001100210000001b9011001c7000080100200003906c006bb0000040f0000000100200190000006190000613d000000000101043b0000000302000029000000000020043f000000200010043f0000000001000414000001b10010009c000001b101008041000000c001100210000001b9011001c7000080100200003906c006bb0000040f0000000100200190000006190000613d000000000101043b000000000201041a000001b5022001970000000203000029000000000232019f000000000021041b000000000030043f0000000501000039000000200010043f0000000001000414000001b10010009c000001b101008041000000c001100210000001b9011001c7000080100200003906c006bb0000040f0000000100200190000006190000613d000000000101043b000000000101041a000000000001004b0000057a0000c13d0000000401000039000000000101041a000001f10010009c000000700000213d00000001021000390000000403000039000000000023041b000001f20110009a0000000202000029000000000021041b000000000103041a000100000001001d000000000020043f0000000501000039000000200010043f0000000001000414000001b10010009c000001b101008041000000c001100210000001b9011001c7000080100200003906c006bb0000040f0000000100200190000006190000613d000000000101043b0000000102000029000000000021041b0000000401000039000000000101041a000000400200043d0000002003200039000000000013043500000002010000290000000000120435000001b10020009c000001b10200804100000040012002100000000002000414000001b10020009c000001b102008041000000c002200210000000000112019f000001b9011001c70000800d020000390000000303000039000001f3040000410000000305000029000000040600002906c006b60000040f0000000100200190000006190000613d000000400100043d00000002020000290000000000210435000001b10010009c000001b1010080410000004001100210000001e6011001c7000006c10001042e0000000603000039000000000023041b0000000703000039000000000013041b000000c00020043f000000e00010043f0000000001000414000001b10010009c000001b101008041000000c001100210000001fc011001c70000800d020000390000000103000039000001ba0400004106c006b60000040f0000000100200190000006190000613d0000000001000019000006c10001042e0000000203000039000000000403041a000001b504400197000000000424019f000000000043041b0000000000210435000001b10010009c000001b10100804100000040011002100000000002000414000001b10020009c000001b102008041000000c002200210000000000112019f000001be011001c70000800d020000390000000103000039000001bf0400004106c006b60000040f0000000100200190000006190000613d000000200100003900000100001004430000012000000443000001c001000041000006c10001042e000000030000006b000005e30000c13d000000400100043d00000064021000390000020803000041000000000032043500000044021000390000020903000041000000000032043500000024021000390000002103000039000001120000013d0000004401300039000001e8020000410000000000210435000000240130003900000018020000390000000000210435000001bc010000410000000000130435000000040130003900000020020000390000000000210435000001b10030009c000001b1030080410000004001300210000001bd011001c7000006c2000104300000000401000029000000000010043f0000000801000039000000200010043f0000000001000414000001b10010009c000001b101008041000000c001100210000001b9011001c7000080100200003906c006bb0000040f0000000100200190000006190000613d000000000101043b000000000201041a000001b50220019700000003022001af000000000021041b0000000401000029000000000010043f0000000801000039000000200010043f0000000001000414000001b10010009c000001b101008041000000c001100210000001b9011001c7000080100200003906c006bb0000040f0000000100200190000006190000613d000000000101043b00000001011000390000000203000029000000000031041b000000400100043d0000002002100039000000000032043500000003020000290000000000210435000001b10010009c000001b10100804100000040011002100000000002000414000001b10020009c000001b102008041000000c002200210000000000112019f000001b9011001c70000800d02000039000000020300003900000207040000410000000405000029000005a80000013d0000000001000019000006c200010430000000000001042f000000000201001900000060062002700000001f0460018f000001b305600198000000400200043d0000000003520019000006290000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000038004b000006250000c13d000001b106600197000000000004004b000006370000613d000000000151034f0000000304400210000000000503043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f00000000001304350000006001600210000001b10020009c000001b1020080410000004002200210000000000112019f000006c200010430000001b402200197000000000020043f000000200010043f0000000001000414000001b10010009c000001b101008041000000c001100210000001b9011001c7000080100200003906c006bb0000040f00000001002001900000064b0000613d000000000101043b000000000001042d0000000001000019000006c2000104300004000000000002000001b401100197000400000001001d000000000010043f0000000801000039000000200010043f0000000001000414000001b10010009c000001b101008041000000c001100210000001b9011001c7000080100200003906c006bb0000040f00000001002001900000069e0000613d000000000101043b0000000402100039000000000202041a0000ff0000200190000000030110c0390000000701006039000000000101041a000013880010008c000006680000413d000013880400003900000000020000190000069b0000013d000300000001001d0000000401000029000000000010043f0000000801000039000000200010043f0000000001000414000001b10010009c000001b101008041000000c001100210000001b9011001c7000080100200003906c006bb0000040f00000001002001900000069e0000613d00000003040000290000138802400089000000000101043b0000000101100039000000000101041a000000000312004b0000069b0000a13d000100000003001d000200000001001d0000000401000029000000000010043f0000000801000039000000200010043f0000000001000414000001b10010009c000001b101008041000000c001100210000001b9011001c7000080100200003906c006bb0000040f00000001002001900000069e0000613d000000000101043b0000000402100039000000000202041a000000ff002001900000000304000029000000020110c039000000060100603900000002020000290000000103000029000000000101041a000000000031004b0000069c0000213d00000000030100190000000001040019000000000001042d00000000030000190000000001040019000000000001042d0000000001000019000006c200010430000000000001042f000001b10010009c000001b1010080410000004001100210000001b10020009c000001b1020080410000006002200210000000000112019f0000000002000414000001b10020009c000001b102008041000000c002200210000000000112019f000001b6011001c7000080100200003906c006bb0000040f0000000100200190000006b40000613d000000000101043b000000000001042d0000000001000019000006c200010430000006b9002104210000000102000039000000000001042d0000000002000019000000000001042d000006be002104230000000102000039000000000001042d0000000002000019000000000001042d000006c000000432000006c10001042e000006c200010430000000000000000000000000000000000000000000000000000000000000000000000000ffffffff00000000000000000000000000000000000000000000000000000001ffffffe000000000000000000000000000000000000000000000000000000000ffffffe0000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000008be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0000000000000000000000000000000000000000000000000ffffffffffffffbf0200000000000000000000000000000000000040000000000000000000000000ddf8083b55465587b48c2695a2ae37f430a30a016f339945497267abadf235b74f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657208c379a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000640000000000000000000000000200000000000000000000000000000000000020000000000000000000000000867c1344c5717824d9f22c4ee0800bee4e221458de6fdf3f3769bd2c87b58c0300000002000000000000000000000000000000400000010000000000000000004d616769637377617056323a2042454e45464943494152590000000000000000203e204d41585f464545000000000000000000000000000000000000000000004d616769637377617056323a2070726f746f636f6c466565202b206c7046656500000000000000000000000000000000000000840000000000000000000000004d616769637377617056323a206c70466565203e204d41585f4645450000000045450000000000000000000000000000000000000000000000000000000000004d616769637377617056323a2070726f746f636f6c466565203e204d41585f46000000000000000000000000000000000000000000000000000000009585b0bd00000000000000000000000000000000000000000000000000000000c97682f700000000000000000000000000000000000000000000000000000000e30c397700000000000000000000000000000000000000000000000000000000e30c397800000000000000000000000000000000000000000000000000000000e6a4390500000000000000000000000000000000000000000000000000000000f2fde38b00000000000000000000000000000000000000000000000000000000c97682f800000000000000000000000000000000000000000000000000000000c9c6539600000000000000000000000000000000000000000000000000000000ceb80df2000000000000000000000000000000000000000000000000000000009d836a6d000000000000000000000000000000000000000000000000000000009d836a6e00000000000000000000000000000000000000000000000000000000b8f5421000000000000000000000000000000000000000000000000000000000bc063e1a000000000000000000000000000000000000000000000000000000009585b0be000000000000000000000000000000000000000000000000000000009af608c9000000000000000000000000000000000000000000000000000000006d587a3c0000000000000000000000000000000000000000000000000000000079ba50960000000000000000000000000000000000000000000000000000000079ba5097000000000000000000000000000000000000000000000000000000008c232838000000000000000000000000000000000000000000000000000000008da5cb5b000000000000000000000000000000000000000000000000000000006d587a3d000000000000000000000000000000000000000000000000000000006d771c5400000000000000000000000000000000000000000000000000000000715018a6000000000000000000000000000000000000000000000000000000003e158b90000000000000000000000000000000000000000000000000000000003e158b91000000000000000000000000000000000000000000000000000000004cc25b8800000000000000000000000000000000000000000000000000000000574f2ba300000000000000000000000000000000000000000000000000000000118b48e5000000000000000000000000000000000000000000000000000000001e3dd18b38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e22700000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000008000000000000000004d616769637377617056323a20504149525f4558495354530000000000000000000000000000000000000000000000000000000000000000ffffffffffffff3f010004df694643e2d7e17535f16c21e9d1698b06c2ef330166830639b23b7f43000000000000000000000000000000000000000000000000ffffffffffffff9f3cda33511d41a8a5431b1770c5bc0ddd62e1cd30555d16659b89c0d60f4f9f571806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b830200000200000000000000000000000000000024000000000000000000000000485cc955000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff75ca53043ea007e5c65182cbb028f60d7179ff4b55739a3949b401801c942e650d3648bd0f6ba80134a33ba9275ac585d9d315f0ad8355cddefde31afa28d0e94d616769637377617056323a205a45524f5f414444524553530000000000000000000000000000000000000000000000000000640000008000000000000000004d616769637377617056323a204944454e544943414c5f4144445245535345538a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b000000000000000000000000000000000000000000000000ffffffffffffff7f4e487b710000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000064000000c000000000000000000200000000000000000000000000000000000040000000c000000000000000000000000000000000000000000000000000000084000000c0000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000006000000000000000000000000002000000000000000000000000000000000000200000008000000000000000004f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206e6577206f776e65720000000000000000000000000000000000000000000000000000000000000000000000000000000000008400000080000000000000000000000000000000000000000000000000000000c0000000800000000000000000ceba5185d0d459a90b443835ac388283f704e04596669f81310b9cfb4ad476fe4d616769637377617056323a205f6c70466565203e204d41585f4645450000003ca180d6c1ab216bb10fa647672355a43d0e0b12b035777f92e6fe7bf246a44264000000000000000000000000000000000000000000000000000000000000004d616769637377617056323a205f62656e656669636961727920696e76616c694d616769637377617056323a205f726f79616c74696573466565203e204d41585f4645450000000000000000000000000000000000000000000000000000000034d0d465daa88a90f6160d083195007eeca7c820e34e112d635e8281adb3321f4d616769637377617056323a205f7061697220696e76616c69640000000000004d616769637377617056323a205f70726f746f636f6c466565203e204d41585f46454500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000800000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00c0934eab6d0c4ffa4ae85b441d953cd8bf6dabcd278dba29fb1fa83c9c865498

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

000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000005a25839b49eec2d4c173b42668a84f5988599929

-----Decoded View---------------
Arg [0] : _defaultProtocolFee (uint256): 30
Arg [1] : _defaultLpFee (uint256): 30
Arg [2] : _protocolFeeBeneficiary (address): 0x5A25839b49EEc2D4C173B42668a84f5988599929

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000000000000000000000000000000000000000001e
Arg [1] : 000000000000000000000000000000000000000000000000000000000000001e
Arg [2] : 0000000000000000000000005a25839b49eec2d4c173b42668a84f5988599929


Block Transaction Gas Used Reward
view all blocks produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
[ Download: CSV Export  ]

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.