ETH Price: $2,062.59 (-0.81%)

Contract

0xC9001AFF3701e19C29E996D48e474Baf4C5eD006

Overview

ETH Balance

0 ETH

ETH Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Withdraw130704612024-06-04 7:40:28294 days ago1717486828IN
Dyson Finance: DYSON-USDC LP Pair
0 ETH0.000004860.0801
Withdraw130697372024-06-04 7:03:58294 days ago1717484638IN
Dyson Finance: DYSON-USDC LP Pair
0 ETH0.000005480.12
Withdraw130696092024-06-04 6:57:30294 days ago1717484250IN
Dyson Finance: DYSON-USDC LP Pair
0 ETH0.000004230.0927
Withdraw130670392024-06-04 4:48:17294 days ago1717476497IN
Dyson Finance: DYSON-USDC LP Pair
0 ETH0.000005280.0866
Withdraw130644162024-06-04 2:36:15294 days ago1717468575IN
Dyson Finance: DYSON-USDC LP Pair
0 ETH0.00000380.0834
Withdraw130643582024-06-04 2:33:21294 days ago1717468401IN
Dyson Finance: DYSON-USDC LP Pair
0 ETH0.000005180.0854
Withdraw130629522024-06-04 1:22:40294 days ago1717464160IN
Dyson Finance: DYSON-USDC LP Pair
0 ETH0.000004580.1
Withdraw130598072024-06-03 22:44:31294 days ago1717454671IN
Dyson Finance: DYSON-USDC LP Pair
0 ETH0.000005370.118
Withdraw130596262024-06-03 22:35:24294 days ago1717454124IN
Dyson Finance: DYSON-USDC LP Pair
0 ETH0.00000550.12
Withdraw130595632024-06-03 22:32:14294 days ago1717453934IN
Dyson Finance: DYSON-USDC LP Pair
0 ETH0.000007350.121
Withdraw130592952024-06-03 22:18:48294 days ago1717453128IN
Dyson Finance: DYSON-USDC LP Pair
0 ETH0.000007370.121
Withdraw130566222024-06-03 20:04:28294 days ago1717445068IN
Dyson Finance: DYSON-USDC LP Pair
0 ETH0.00001090.17805007
Withdraw130552012024-06-03 18:53:03294 days ago1717440783IN
Dyson Finance: DYSON-USDC LP Pair
0 ETH0.000009830.215
Withdraw130543712024-06-03 18:11:17294 days ago1717438277IN
Dyson Finance: DYSON-USDC LP Pair
0 ETH0.000009180.201
Withdraw130537592024-06-03 17:40:38294 days ago1717436438IN
Dyson Finance: DYSON-USDC LP Pair
0 ETH0.000007880.172
Withdraw130533162024-06-03 17:18:17294 days ago1717435097IN
Dyson Finance: DYSON-USDC LP Pair
0 ETH0.000008170.179
Withdraw130532362024-06-03 17:14:15294 days ago1717434855IN
Dyson Finance: DYSON-USDC LP Pair
0 ETH0.000009150.2
Withdraw130531322024-06-03 17:09:02294 days ago1717434542IN
Dyson Finance: DYSON-USDC LP Pair
0 ETH0.000009790.214
Withdraw130531142024-06-03 17:08:09294 days ago1717434489IN
Dyson Finance: DYSON-USDC LP Pair
0 ETH0.000013550.223
Withdraw130530692024-06-03 17:05:55294 days ago1717434355IN
Dyson Finance: DYSON-USDC LP Pair
0 ETH0.000008610.188
Withdraw130529472024-06-03 16:59:46294 days ago1717433986IN
Dyson Finance: DYSON-USDC LP Pair
0 ETH0.000008480.185
Withdraw130529422024-06-03 16:59:31294 days ago1717433971IN
Dyson Finance: DYSON-USDC LP Pair
0 ETH0.00000820.179
Withdraw130461412024-06-03 11:17:15295 days ago1717413435IN
Dyson Finance: DYSON-USDC LP Pair
0 ETH0.000005710.125
Withdraw130423122024-06-03 8:04:44295 days ago1717401884IN
Dyson Finance: DYSON-USDC LP Pair
0 ETH0.000006910.151
Withdraw130411582024-06-03 7:06:49295 days ago1717398409IN
Dyson Finance: DYSON-USDC LP Pair
0 ETH0.000006040.132

Latest 1 internal transaction

Parent Transaction Hash Block From To
78230242023-11-20 12:11:38491 days ago1700482298  Contract Creation0 ETH
Loading...
Loading

Similar Match Source Code
This contract matches the deployed Bytecode of the Source Code for Contract 0xEce7244a...77fEE90AF
The constructor portion of the code might be different and could alter the actual behaviour of the contract

Contract Name:
Pair

Compiler Version
v0.8.17+commit.8df45f5f

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 7 : Pair.sol
pragma solidity 0.8.17;

// SPDX-License-Identifier: AGPL-3.0-only

import "interface/IERC20.sol";
import "interface/IFarm.sol";
import "interface/IFactory.sol";
import "./lib/ABDKMath64x64.sol";
import "./lib/SqrtMath.sol";
import "./lib/TransferHelper.sol";

/// @title Fee model for Dyson pair
contract FeeModel {
    using ABDKMath64x64 for *;

    uint internal constant MAX_FEE_RATIO = 2**64;

    /// @dev Fee ratio of token0. Max fee ratio is MAX_FEE_RATIO
    uint64 internal feeRatio0;
    /// @dev Fee ratio of token1. Max fee ratio is MAX_FEE_RATIO
    uint64 internal feeRatio1;
    /// @dev Timestamp when fee ratio of token0 last updated
    uint64 internal lastUpdateTime0;
    /// @dev Timestamp when fee ratio of token1 last updated
    uint64 internal lastUpdateTime1;
    uint64 public halfLife = 720; // Fee /= 2 every 12 minutes

    /// @dev Convenience function to get the stored fee ratio and last update time of token0 and token1
    /// @return _feeRatio0 Stored fee ratio of token0
    /// @return _feeRatio1 Stored fee ratio of token1
    /// @return _lastUpdateTime0 Stored last update time of token0
    /// @return _lastUpdateTime1 Stored last update time of token1
    function _getFeeRatioStored() internal view returns (uint64 _feeRatio0, uint64 _feeRatio1, uint64 _lastUpdateTime0, uint64 _lastUpdateTime1) {
        _feeRatio0 = feeRatio0;
        _feeRatio1 = feeRatio1;
        _lastUpdateTime0 = lastUpdateTime0;
        _lastUpdateTime1 = lastUpdateTime1;
    }

    /// @dev Pure function to calculate new fee ratio when fee ratio increased
    /// Formula shown as below with a as fee ratio before and b as fee ratio added:
    /// 1 - (1 - a)(1 - b) = a + b - ab
    /// new = before + added - before * added
    /// @param _feeRatioBefore Fee ratio before the increase
    /// @param _feeRatioAdded Fee ratio increased
    /// @return _newFeeRatio New fee ratio
    function _calcFeeRatioAdded(uint64 _feeRatioBefore, uint64 _feeRatioAdded) internal pure returns (uint64 _newFeeRatio) {
        uint before = uint(_feeRatioBefore);
        uint added = uint(_feeRatioAdded);
        _newFeeRatio = uint64(before + added - before * added / MAX_FEE_RATIO);
    }

    /// @dev Update fee ratio and last update timestamp of token0
    /// @param _feeRatioBefore Fee ratio before the increase
    /// @param _feeRatioAdded Fee ratio increased
    function _updateFeeRatio0(uint64 _feeRatioBefore, uint64 _feeRatioAdded) internal {
        feeRatio0 = _calcFeeRatioAdded(_feeRatioBefore, _feeRatioAdded);
        lastUpdateTime0 = uint64(block.timestamp);
    }

    /// @dev Update fee ratio and last update timestamp of token1
    /// @param _feeRatioBefore Fee ratio before the increase
    /// @param _feeRatioAdded Fee ratio increased
    function _updateFeeRatio1(uint64 _feeRatioBefore, uint64 _feeRatioAdded) internal {
        feeRatio1 = _calcFeeRatioAdded(_feeRatioBefore, _feeRatioAdded);
        lastUpdateTime1 = uint64(block.timestamp);
    }

    /// @notice Fee ratio halve every `halfLife` seconds
    /// @dev Calculate new fee ratio as time elapsed
    /// newFeeRatio = oldFeeRatio / 2^(elapsedTime / halfLife)
    /// @param _oldFeeRatio Fee ratio from last update
    /// @param _elapsedTime Time since last update
    /// @return _newFeeRatio New fee ratio
    function calcNewFeeRatio(uint64 _oldFeeRatio, uint _elapsedTime) public view returns (uint64 _newFeeRatio) {
        int128 t = _elapsedTime.divu(halfLife);
        int128 r = (-t).exp_2();
        _newFeeRatio = uint64(r.mulu(uint(_oldFeeRatio)));
    }

    /// @notice The fee ratios returned are the stored fee ratios with halving applied
    /// @return _feeRatio0 Fee ratio of token0 after halving update
    /// @return _feeRatio1 Fee ratio of token1 after halving update
    function getFeeRatio() public view returns (uint64 _feeRatio0, uint64 _feeRatio1) {
        uint64 _lastUpdateTime0;
        uint64 _lastUpdateTime1;
        (_feeRatio0, _feeRatio1, _lastUpdateTime0, _lastUpdateTime1) = _getFeeRatioStored();
        _feeRatio0 = calcNewFeeRatio(_feeRatio0, block.timestamp - uint(_lastUpdateTime0));
        _feeRatio1 = calcNewFeeRatio(_feeRatio1, block.timestamp - uint(_lastUpdateTime1));
    }
}

/// @title Contract with basic swap logic and fee mechanism
contract Feeswap is FeeModel {
    using TransferHelper for address;

    address public token0;
    address public token1;
    /// @notice Fee recipient
    address public feeTo;
    /// @dev Used to keep track of fee earned to save gas by not transferring fee away everytime.
    /// Need to discount this amount when calculating reserve
    uint internal accumulatedFee0;
    uint internal accumulatedFee1;

    /// @dev Mutex to prevent re-entrancy
    uint private unlocked = 1;
    /// @notice User's approval nonce
    mapping(address => uint256) public nonces;

    event Swap(address indexed sender, bool indexed isSwap0, uint amountIn, uint amountOut, address indexed to);
    event FeeCollected(uint token0Amt, uint token1Amt);

    modifier lock() {
        require(unlocked == 1, 'locked');
        unlocked = 0;
        _;
        unlocked = 1;
    }

    function initialize(address _token0, address _token1) public virtual {
        require(token0 == address(0), 'forbidden');
        token0 = _token0;
        token1 = _token1;
    }

    function getReserves() public view returns (uint reserve0, uint reserve1) {
        reserve0 = IERC20(token0).balanceOf(address(this)) - accumulatedFee0;
        reserve1 = IERC20(token1).balanceOf(address(this)) - accumulatedFee1;
    }

    /// @param input Amount of token0 to swap
    /// @param minOutput Minimum amount of token1 expected to receive
    /// @return fee Amount of token0 as fee
    /// @return output Amount of token1 swapped
    function _swap0in(uint input, uint minOutput) internal returns (uint fee, uint output) {
        require(input > 0, "invalid input amount");
        (uint reserve0, uint reserve1) = getReserves();
        (uint64 _feeRatio0, uint64 _feeRatio1) = getFeeRatio();
        fee = uint(_feeRatio0) * input / MAX_FEE_RATIO;
        uint inputLessFee = input - fee;
        output = inputLessFee * reserve1 / (reserve0 + inputLessFee);
        require(output >= minOutput, "slippage");
        uint64 feeRatioAdded = uint64(output * MAX_FEE_RATIO / reserve1);
        _updateFeeRatio1(_feeRatio1, feeRatioAdded);
    }

    /// @param input Amount of token1 to swap
    /// @param minOutput Minimum amount of token0 expected to receive
    /// @return fee Amount of token1 as fee
    /// @return output Amount of token0 swapped
    function _swap1in(uint input, uint minOutput) internal returns (uint fee, uint output) {
        require(input > 0, "invalid input amount");
        (uint reserve0, uint reserve1) = getReserves();
        (uint64 _feeRatio0, uint64 _feeRatio1) = getFeeRatio();
        fee = uint(_feeRatio1) * input / MAX_FEE_RATIO;
        uint inputLessFee = input - fee;
        output = inputLessFee * reserve0 / (reserve1 + inputLessFee);
        require(output >= minOutput, "slippage");
        uint64 feeRatioAdded = uint64(output * MAX_FEE_RATIO / reserve0);
        _updateFeeRatio0(_feeRatio0, feeRatioAdded);
    }

    /// @notice Perfrom swap from token0 to token1
    /// Half of the swap fee goes to `feeTo` if `feeTo` is set
    /// @dev Re-entrancy protected
    /// @param to Address that receives swapped token1
    /// @param input Amount of token0 to swap
    /// @param minOutput Minimum amount of token1 expected to receive
    /// @return output Amount of token1 swapped
    function swap0in(address to, uint input, uint minOutput) external lock returns (uint output) {
        uint fee;
        (fee, output) = _swap0in(input, minOutput);
        if(feeTo != address(0)) accumulatedFee0 += fee / 2;
        token0.safeTransferFrom(msg.sender, address(this), input);
        token1.safeTransfer(to, output);
        emit Swap(msg.sender, true, input, output, to);
    }

    /// @notice Perfrom swap from token1 to token0
    /// Half of the swap fee goes to `feeTo` if `feeTo` is set
    /// @dev Re-entrancy protected
    /// @param to Address that receives swapped token0
    /// @param input Amount of token1 to swap
    /// @param minOutput Minimum amount of token0 expected to receive
    /// @return output Amount of token0 swapped
    function swap1in(address to, uint input, uint minOutput) external lock returns (uint output) {
        uint fee;
        (fee, output) = _swap1in(input, minOutput);
        if(feeTo != address(0)) accumulatedFee1 += fee / 2;
        token1.safeTransferFrom(msg.sender, address(this), input);
        token0.safeTransfer(to, output);
        emit Swap(msg.sender, false, input, output, to);
    }

    function collectFee() external lock {
        _collectFee();
    }

    function _collectFee() internal {
        uint f0 = accumulatedFee0;
        uint f1 = accumulatedFee1;
        accumulatedFee0 = 0;
        accumulatedFee1 = 0;
        token0.safeTransfer(feeTo, f0);
        token1.safeTransfer(feeTo, f1);
        emit FeeCollected(f0, f1);
    }
}

/// @title Dyson pair contract
contract Pair is Feeswap {
    using SqrtMath for *;
    using TransferHelper for address;

    /// @dev Square root of `MAX_FEE_RATIO`
    uint private constant MAX_FEE_RATIO_SQRT = 2**32;
    /// @dev Beware that fee ratio and premium base unit are different
    uint private constant PREMIUM_BASE_UNIT = 1e18;
    /// @dev For EIP712
    bytes32 public immutable DOMAIN_SEPARATOR;
    bytes32 public constant APPROVE_TYPEHASH = keccak256("setApprovalForAllWithSig(address owner,address operator,bool approved,uint256 nonce,uint256 deadline)");

    /// @notice A note records the amount of token0 or token1 user gets when the user redeem the note
    /// and the timestamp when user can redeem.
    /// The amount of token0 and token1 include the premium
    struct Note {
        uint token0Amt;
        uint token1Amt;
        uint due;
    }

    /// @dev Factory of this contract
    address public factory;
    IFarm public farm;

    /// @notice Volatility which affects premium and can be set by governance, i.e. controller of factory contract
    uint public basis = 0.7e18;

    /// @notice Total number of notes created by user
    mapping(address => uint) public noteCount;
    /// @notice Notes created by user, indexed by note number
    mapping(address => mapping(uint => Note)) public notes;
    /// @notice Operator is the address that can withdraw note on behalf of user
    mapping(address => mapping(address => bool)) public operatorApprovals;

    event Deposit(address indexed user, bool indexed isToken0, uint index, uint amountIn, uint token0Amt, uint token1Amt, uint due);
    event Withdraw(address indexed user, bool indexed isToken0, uint index, uint amountOut);
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

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

    /// @notice Premium = volatility * sqrt(time / 365 days) * 0.4
    /// @dev sqrt(time / 365 days) * 0.4 is pre-calculated to save gas.
    /// Note that premium could be larger than `PREMIUM_BASE_UNIT`
    /// @param time Lock time. It can be either 1 day, 3 days, 7 days or 30 days
    /// @return premium Premium
    function getPremium(uint time) public view returns (uint premium) {
        if(time == 1 days) premium = basis * 20936956903608548 / PREMIUM_BASE_UNIT;
        else if(time == 3 days) premium = basis * 36263873112929960 / PREMIUM_BASE_UNIT;
        else if(time == 7 days) premium = basis * 55393981177425144 / PREMIUM_BASE_UNIT;
        else if(time == 30 days) premium = basis * 114676435816199168 / PREMIUM_BASE_UNIT;
        else revert("invalid time");
    }

    function initialize(address _token0, address _token1) public override {
        super.initialize(_token0, _token1);
        factory = msg.sender;
    }

    /// @notice `basis` can only be set by governance, i.e., controller of factory contract
    function setBasis(uint _basis) external lock {
        require(IFactory(factory).controller() == msg.sender, "forbidden");
        basis = _basis;
    }

    /// @notice `halfLife` can only be set by governance, i.e., controller of factory contract
    function setHalfLife(uint64 _halfLife) external lock {
        require(IFactory(factory).controller() == msg.sender, "forbidden");
        require( _halfLife > 0, "half life cannot be zero");
        halfLife = _halfLife;
    }

    /// @notice `farm` can only be set by governance, i.e., controller of factory contract
    function setFarm(address _farm) external lock {
        require(IFactory(factory).controller() == msg.sender, "forbidden");
        farm = IFarm(_farm);
    }

    /// @notice `feeTo` can only be set by governance, i.e., controller of factory contract
    function setFeeTo(address _feeTo) external lock {
        require(IFactory(factory).controller() == msg.sender, "forbidden");
        if(feeTo != address(0)) _collectFee();
        feeTo = _feeTo;
    }

    /// @notice rescue token stucked in this contract
    /// @param tokenAddress Address of token to be rescued
    /// @param to Address that will receive token
    /// @param amount Amount of token to be rescued
    function rescueERC20(address tokenAddress, address to, uint256 amount) external {
        require(IFactory(factory).controller() == msg.sender, "forbidden");
        require(tokenAddress != token0);
        require(tokenAddress != token1);
        tokenAddress.safeTransfer(to, amount);
    }

    function _addNote(address to, bool depositToken0, uint token0Amt, uint token1Amt, uint time, uint premium) internal {
        uint index = noteCount[to]++;
        Note storage note = notes[to][index];

        uint inputAmt = depositToken0 ? token0Amt : token1Amt;
        uint token0AmtWithPremium = token0Amt * (premium + PREMIUM_BASE_UNIT) / PREMIUM_BASE_UNIT;
        uint token1AmtWithPremium = token1Amt * (premium + PREMIUM_BASE_UNIT) / PREMIUM_BASE_UNIT;
        uint dueTime = block.timestamp + time;

        note.token0Amt = token0AmtWithPremium;
        note.token1Amt = token1AmtWithPremium;
        note.due = dueTime;

        emit Deposit(to, depositToken0, index, inputAmt, token0AmtWithPremium, token1AmtWithPremium, dueTime);
    }

    function _grantSP(address to, uint input, uint output, uint premium) internal {
        if(address(farm) != address(0)) {
            uint sp = (input * output).sqrt() * premium / PREMIUM_BASE_UNIT;
            farm.grantSP(to, sp);
        }
    }

    /// @notice User deposit token0. This function simulates it as `swap0in`
    /// but only charges fee base on the fee computed and does not perform actual swap.
    /// Half of the swap fee goes to `feeTo` if `feeTo` is set.
    /// If `farm` is set, this function also computes the amount of SP for the user and calls `farm.grantSP()`.
    /// The amount of SP = sqrt(input * output) * (preium / PREMIUM_BASE_UNIT)
    /// @dev Re-entrancy protected
    /// @param to Address that owns the note
    /// @param input Amount of token0 to deposit
    /// @param minOutput Minimum amount of token1 expected to receive if the swap is perfromed
    /// @param time Lock time
    /// @return output Amount of token1 received if the swap is performed
    function deposit0(address to, uint input, uint minOutput, uint time) external lock returns (uint output) {
        require(to != address(0), "to cannot be zero");
        uint fee;
        (fee, output) = _swap0in(input, minOutput);
        uint premium = getPremium(time);

        _addNote(to, true, input, output, time, premium);

        if(feeTo != address(0)) accumulatedFee0 += fee / 2;
        token0.safeTransferFrom(msg.sender, address(this), input);
        _grantSP(to, input, output, premium);
    }

    /// @notice User deposit token1. This function simulates it as `swap1in`
    /// but only charges fee base on the fee computed and does not perform actual swap.
    /// Half of the swap fee goes to `feeTo` if `feeTo` is set.
    /// If `farm` is set, this function also computes the amount of SP for the user and calls `farm.grantSP()`.
    /// The amount of SP = sqrt(input * output) * (preium / PREMIUM_BASE_UNIT)
    /// @dev Re-entrancy protected
    /// @param to Address that owns the note
    /// @param input Amount of token1 to deposit
    /// @param minOutput Minimum amount of token0 expected to receive if the swap is perfromed
    /// @param time Lock time
    /// @return output Amount of token0 received if the swap is performed
    function deposit1(address to, uint input, uint minOutput, uint time) external lock returns (uint output) {
        require(to != address(0), "to cannot be zero");
        uint fee;
        (fee, output) = _swap1in(input, minOutput);
        uint premium = getPremium(time);

        _addNote(to, false, output, input, time, premium);

        if(feeTo != address(0)) accumulatedFee1 += fee / 2;
        token1.safeTransferFrom(msg.sender, address(this), input);
        _grantSP(to, input, output, premium);
    }

    /// @notice When withdrawing, the token to be withdrawn is the one with less impact on the pool if withdrawn
    /// Strike price: `token1Amt` / `token0Amt`
    /// Market price: (reserve1 * sqrt(1 - feeRatio0)) / (reserve0 * sqrt(1 - feeRatio1))
    /// If strike price > market price, withdraw token0 to user, and token1 vice versa
    /// Formula to determine which token to withdraw:
    /// `token0Amt` * sqrt(1 - feeRatio0) / reserve0 < `token1Amt` * sqrt(1 - feeRatio1) / reserve1
    /// @dev Formula can be transformed to:
    /// sqrt((1 - feeRatio0)/(1 - feeRatio1)) * `token0Amt` / reserve0 < `token1Amt` / reserve1
    /// @dev Content of withdrawn note will be cleared
    /// @param from Address of the user withdrawing
    /// @param index Index of the note
    /// @param to Address to receive the redeemed token0 or token1
    /// @return token0Amt Amount of token0 withdrawn
    /// @return token1Amt Amount of token1 withdrawn
    function _withdraw(address from, uint index, address to) internal returns (uint token0Amt, uint token1Amt) {
        Note storage note = notes[from][index];
        token0Amt = note.token0Amt;
        token1Amt = note.token1Amt;
        uint due = note.due;
        note.token0Amt = 0;
        note.token1Amt = 0;
        note.due = 0;
        require(due > 0, "invalid note");
        require(due <= block.timestamp, "early withdrawal");
        (uint reserve0, uint reserve1) = getReserves();
        (uint64 _feeRatio0, uint64 _feeRatio1) = getFeeRatio();

        if((MAX_FEE_RATIO * (MAX_FEE_RATIO - uint(_feeRatio0)) / (MAX_FEE_RATIO - uint(_feeRatio1))).sqrt() * token0Amt / reserve0 < MAX_FEE_RATIO_SQRT * token1Amt / reserve1) {
            token1Amt = 0;
            token0.safeTransfer(to, token0Amt);
            uint64 feeRatioAdded = uint64(token0Amt * MAX_FEE_RATIO / reserve0);
            _updateFeeRatio0(_feeRatio0, feeRatioAdded);
            emit Withdraw(from, true, index, token0Amt);
        }
        else {
            token0Amt = 0;
            token1.safeTransfer(to, token1Amt);
            uint64 feeRatioAdded = uint64(token1Amt * MAX_FEE_RATIO / reserve1);
            _updateFeeRatio1(_feeRatio1, feeRatioAdded);
            emit Withdraw(from, false, index, token1Amt);
        }
    }

    /// @notice Withdraw the note and receive either one of token0 or token1
    /// @dev Re-entrancy protected
    /// @param index Index of the note owned by user
    /// @param to Address to receive the redeemed token0 or token1
    /// @return token0Amt Amount of token0 withdrawn
    /// @return token1Amt Amount of token1 withdrawn
    function withdraw(uint index, address to) external lock returns (uint token0Amt, uint token1Amt) {
        return _withdraw(msg.sender, index, to);
    }

    /// @notice Withdraw the note and receive either one of token0 or token1 if approved by user
    /// @param from Address of the user withdrawing
    /// @param index Index of the note
    /// @param to Address to receive the redeemed token0 or token1
    /// @return token0Amt Amount of token0 withdrawn
    /// @return token1Amt Amount of token1 withdrawn
    function withdrawFrom(address from, uint index, address to) external returns (uint token0Amt, uint token1Amt) {
		require(operatorApprovals[from][msg.sender], "not operator");
		return _withdraw(from, index, to);
    }

    function _ecrecover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        if (signature.length == 65) {
            bytes32 r;
            bytes32 s;
            uint8 v;
            assembly {
                r := mload(add(signature, 0x20))
                s := mload(add(signature, 0x40))
                v := byte(0, mload(add(signature, 0x60)))
            }

            if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
                return address(0);
            } else if (v != 27 && v != 28) {
                return address(0);
            } else {
                return ecrecover(hash, v, r, s);
            }
        } else {
            return address(0);
        }
    }

    /// @notice Approve operator to withdraw note on behalf of user
    /// User who signs the approval signature must be the `owner`
    /// @param owner Address of the user who owns the note
    /// @param operator Address of the operator
    /// @param approved Whether the operator is approved or not
    /// @param deadline deadline of the signature
    /// @param sig approval signature
    function setApprovalForAllWithSig(address owner, address operator, bool approved, uint deadline, bytes calldata sig) external {
        require(block.timestamp <= deadline || deadline == 0, "exceed deadline");
        require(owner != address(0), "owner cannot be zero");
        require(operator != address(0), "operator cannot be zero");
        bytes32 structHash = keccak256(abi.encode(APPROVE_TYPEHASH, owner, operator, approved, nonces[owner]++, deadline));
        bytes32 digest = keccak256(abi.encodePacked("\x19\x01", DOMAIN_SEPARATOR, structHash));
        require(owner == _ecrecover(digest, sig), "invalid signature");
        
        operatorApprovals[owner][operator] = approved;
        emit ApprovalForAll(owner, operator, approved);
    }

    /// @notice Approve operator to withdraw note on behalf of user
    /// @param operator Address of the operator
    /// @param approved Whether the operator is approved or not
    function setApprovalForAll(address operator, bool approved) external { 
        require(operator != address(0), "operator cannot be zero");
        operatorApprovals[msg.sender][operator] = approved;
        emit ApprovalForAll(msg.sender, operator, approved);
    }
}

File 2 of 7 : IERC20.sol
pragma solidity >=0.8.0;

// SPDX-License-Identifier: MIT

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

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

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

File 3 of 7 : IFarm.sol
pragma solidity >=0.8.0;

// SPDX-License-Identifier: MIT

interface IFarm {
    event TransferOwnership(address newOwner);
    event RateUpdated(address indexed poolId, uint rewardRate, uint weight);
    event GrantSP(address indexed user, address indexed poolId, uint amountIn, uint amountOut);
    event Swap(address indexed user, address indexed parent, uint amountIn, uint amountOut);
    
    struct Pool {
        uint weight;
        uint rewardRate;
        uint lastUpdateTime;
        uint lastReserve;
        address gauge;
    }

    function agency() external view returns (address);
    function gov() external view returns (address);
    function owner() external view returns (address);
    function globalPool() external view returns (uint weight, uint rewardRate, uint lastUpdateTime, uint lastReserve, address gauge);
    function pools(address poolId) external view returns (uint weight, uint rewardRate, uint lastUpdateTime, uint lastReserve, address gauge);
    function balanceOf(address user) external view returns (uint);
    function cooldown(address user) external view returns (uint);
    function transferOwnership(address _owner) external;
    function rescueERC20(address tokenAddress, address to, uint256 amount) external;
    function setPool(address poolId, address gauge) external;
    function setPoolRewardRate(address poolId, uint rewardRate, uint weight) external;
    function setGlobalRewardRate(uint rewardRate, uint weight) external;
    function getCurrentPoolReserve(address poolId) view external returns (uint reserve);
    function getCurrentGlobalReserve() view external returns (uint reserve);
    function grantSP(address to, uint amount) external;
    function swap(address user) external returns (uint amountOut);
}

File 4 of 7 : IFactory.sol
pragma solidity >=0.8.0;

// SPDX-License-Identifier: MIT

interface IFactory {
    event PairCreated(address indexed token0, address indexed token1, uint id, address pair, uint);
    event GaugeCreated(address indexed poolId, address gauge);
    event BribeCreated(address indexed gauge, address bribe);

    function controller() external returns (address);
    function pendingController() external returns (address);
    function permissionless() external returns (bool);
    function getPairCount(address token0, address token1) external view returns (uint);
    function getPair(address token0, address token1, uint id) external view returns (address);
    function allPairs(uint id) external view returns (address);
    function allPairsLength() external view returns (uint);
    function getInitCodeHash() external pure returns (bytes32);
    function createPair(address tokenA, address tokenB) external returns (address pair);
    function createGauge(address farm, address sgov, address poolId, uint weight, uint base, uint slope) external returns (address gauge);
    function createBribe(address gauge) external returns (address bribe);
    function setController(address _controller) external;
    function becomeController() external;
    function open2public() external;
}

File 5 of 7 : ABDKMath64x64.sol
pragma solidity 0.8.17;

// SPDX-License-Identifier: AGPL-2.0

library ABDKMath64x64 {
    /*
     * Minimum value signed 64.64-bit fixed point number may have.
     * -2^127
     */
    int128 private constant MIN_64x64 = -0x80000000000000000000000000000000;

    /*
     * Maximum value signed 64.64-bit fixed point number may have.
     * 2^127-1
     */
    int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

    /**
     * Calculate x * y rounding down, where x is signed 64.64 fixed point number
     * and y is unsigned 256-bit integer number.  Revert on overflow.
     *
     * @param x signed 64.64 fixed point number
     * @param y unsigned 256-bit integer number
     * @return unsigned 256-bit integer number
     */
    function mulu (int128 x, uint256 y) internal pure returns (uint256) {
        unchecked {
            if (y == 0) return 0;

            require (x >= 0);

            uint256 lo = (uint256 (int256 (x)) * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64;
            uint256 hi = uint256 (int256 (x)) * (y >> 128);

            require (hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
            hi <<= 64;

            require (hi <=
                0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - lo);
            return hi + lo;
        }
    }

    /**
     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit
     * integer numbers.  Revert on overflow or when y is zero.
     *
     * @param x unsigned 256-bit integer number
     * @param y unsigned 256-bit integer number
     * @return signed 64.64-bit fixed point number
     */
    function divu (uint256 x, uint256 y) internal pure returns (int128) {
        unchecked {
            require (y != 0);
            uint128 result = divuu (x, y);
            require (result <= uint128 (MAX_64x64));
            return int128 (result);
        }
    }

    /**
     * Calculate binary exponent of x.  Revert on overflow.
     *
     * @param x signed 64.64-bit fixed point number
     * @return signed 64.64-bit fixed point number
     */
    function exp_2 (int128 x) internal pure returns (int128) {
        unchecked {
            require (x < 0x400000000000000000); // Overflow

            if (x < -0x400000000000000000) return 0; // Underflow

            uint256 result = 0x80000000000000000000000000000000;

            if (x & 0x8000000000000000 > 0)
                result = result * 0x16A09E667F3BCC908B2FB1366EA957D3E >> 128;
            if (x & 0x4000000000000000 > 0)
                result = result * 0x1306FE0A31B7152DE8D5A46305C85EDEC >> 128;
            if (x & 0x2000000000000000 > 0)
                result = result * 0x1172B83C7D517ADCDF7C8C50EB14A791F >> 128;
            if (x & 0x1000000000000000 > 0)
                result = result * 0x10B5586CF9890F6298B92B71842A98363 >> 128;
            if (x & 0x800000000000000 > 0)
                result = result * 0x1059B0D31585743AE7C548EB68CA417FD >> 128;
            if (x & 0x400000000000000 > 0)
                result = result * 0x102C9A3E778060EE6F7CACA4F7A29BDE8 >> 128;
            if (x & 0x200000000000000 > 0)
                result = result * 0x10163DA9FB33356D84A66AE336DCDFA3F >> 128;
            if (x & 0x100000000000000 > 0)
                result = result * 0x100B1AFA5ABCBED6129AB13EC11DC9543 >> 128;
            if (x & 0x80000000000000 > 0)
                result = result * 0x10058C86DA1C09EA1FF19D294CF2F679B >> 128;
            if (x & 0x40000000000000 > 0)
                result = result * 0x1002C605E2E8CEC506D21BFC89A23A00F >> 128;
            if (x & 0x20000000000000 > 0)
                result = result * 0x100162F3904051FA128BCA9C55C31E5DF >> 128;
            if (x & 0x10000000000000 > 0)
                result = result * 0x1000B175EFFDC76BA38E31671CA939725 >> 128;
            if (x & 0x8000000000000 > 0)
                result = result * 0x100058BA01FB9F96D6CACD4B180917C3D >> 128;
            if (x & 0x4000000000000 > 0)
                result = result * 0x10002C5CC37DA9491D0985C348C68E7B3 >> 128;
            if (x & 0x2000000000000 > 0)
                result = result * 0x1000162E525EE054754457D5995292026 >> 128;
            if (x & 0x1000000000000 > 0)
                result = result * 0x10000B17255775C040618BF4A4ADE83FC >> 128;
            if (x & 0x800000000000 > 0)
                result = result * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB >> 128;
            if (x & 0x400000000000 > 0)
                result = result * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9 >> 128;
            if (x & 0x200000000000 > 0)
                result = result * 0x10000162E43F4F831060E02D839A9D16D >> 128;
            if (x & 0x100000000000 > 0)
                result = result * 0x100000B1721BCFC99D9F890EA06911763 >> 128;
            if (x & 0x80000000000 > 0)
                result = result * 0x10000058B90CF1E6D97F9CA14DBCC1628 >> 128;
            if (x & 0x40000000000 > 0)
                result = result * 0x1000002C5C863B73F016468F6BAC5CA2B >> 128;
            if (x & 0x20000000000 > 0)
                result = result * 0x100000162E430E5A18F6119E3C02282A5 >> 128;
            if (x & 0x10000000000 > 0)
                result = result * 0x1000000B1721835514B86E6D96EFD1BFE >> 128;
            if (x & 0x8000000000 > 0)
                result = result * 0x100000058B90C0B48C6BE5DF846C5B2EF >> 128;
            if (x & 0x4000000000 > 0)
                result = result * 0x10000002C5C8601CC6B9E94213C72737A >> 128;
            if (x & 0x2000000000 > 0)
                result = result * 0x1000000162E42FFF037DF38AA2B219F06 >> 128;
            if (x & 0x1000000000 > 0)
                result = result * 0x10000000B17217FBA9C739AA5819F44F9 >> 128;
            if (x & 0x800000000 > 0)
                result = result * 0x1000000058B90BFCDEE5ACD3C1CEDC823 >> 128;
            if (x & 0x400000000 > 0)
                result = result * 0x100000002C5C85FE31F35A6A30DA1BE50 >> 128;
            if (x & 0x200000000 > 0)
                result = result * 0x10000000162E42FF0999CE3541B9FFFCF >> 128;
            if (x & 0x100000000 > 0)
                result = result * 0x100000000B17217F80F4EF5AADDA45554 >> 128;
            if (x & 0x80000000 > 0)
                result = result * 0x10000000058B90BFBF8479BD5A81B51AD >> 128;
            if (x & 0x40000000 > 0)
                result = result * 0x1000000002C5C85FDF84BD62AE30A74CC >> 128;
            if (x & 0x20000000 > 0)
                result = result * 0x100000000162E42FEFB2FED257559BDAA >> 128;
            if (x & 0x10000000 > 0)
                result = result * 0x1000000000B17217F7D5A7716BBA4A9AE >> 128;
            if (x & 0x8000000 > 0)
                result = result * 0x100000000058B90BFBE9DDBAC5E109CCE >> 128;
            if (x & 0x4000000 > 0)
                result = result * 0x10000000002C5C85FDF4B15DE6F17EB0D >> 128;
            if (x & 0x2000000 > 0)
                result = result * 0x1000000000162E42FEFA494F1478FDE05 >> 128;
            if (x & 0x1000000 > 0)
                result = result * 0x10000000000B17217F7D20CF927C8E94C >> 128;
            if (x & 0x800000 > 0)
                result = result * 0x1000000000058B90BFBE8F71CB4E4B33D >> 128;
            if (x & 0x400000 > 0)
                result = result * 0x100000000002C5C85FDF477B662B26945 >> 128;
            if (x & 0x200000 > 0)
                result = result * 0x10000000000162E42FEFA3AE53369388C >> 128;
            if (x & 0x100000 > 0)
                result = result * 0x100000000000B17217F7D1D351A389D40 >> 128;
            if (x & 0x80000 > 0)
                result = result * 0x10000000000058B90BFBE8E8B2D3D4EDE >> 128;
            if (x & 0x40000 > 0)
                result = result * 0x1000000000002C5C85FDF4741BEA6E77E >> 128;
            if (x & 0x20000 > 0)
                result = result * 0x100000000000162E42FEFA39FE95583C2 >> 128;
            if (x & 0x10000 > 0)
                result = result * 0x1000000000000B17217F7D1CFB72B45E1 >> 128;
            if (x & 0x8000 > 0)
                result = result * 0x100000000000058B90BFBE8E7CC35C3F0 >> 128;
            if (x & 0x4000 > 0)
                result = result * 0x10000000000002C5C85FDF473E242EA38 >> 128;
            if (x & 0x2000 > 0)
                result = result * 0x1000000000000162E42FEFA39F02B772C >> 128;
            if (x & 0x1000 > 0)
                result = result * 0x10000000000000B17217F7D1CF7D83C1A >> 128;
            if (x & 0x800 > 0)
                result = result * 0x1000000000000058B90BFBE8E7BDCBE2E >> 128;
            if (x & 0x400 > 0)
                result = result * 0x100000000000002C5C85FDF473DEA871F >> 128;
            if (x & 0x200 > 0)
                result = result * 0x10000000000000162E42FEFA39EF44D91 >> 128;
            if (x & 0x100 > 0)
                result = result * 0x100000000000000B17217F7D1CF79E949 >> 128;
            if (x & 0x80 > 0)
                result = result * 0x10000000000000058B90BFBE8E7BCE544 >> 128;
            if (x & 0x40 > 0)
                result = result * 0x1000000000000002C5C85FDF473DE6ECA >> 128;
            if (x & 0x20 > 0)
                result = result * 0x100000000000000162E42FEFA39EF366F >> 128;
            if (x & 0x10 > 0)
                result = result * 0x1000000000000000B17217F7D1CF79AFA >> 128;
            if (x & 0x8 > 0)
                result = result * 0x100000000000000058B90BFBE8E7BCD6D >> 128;
            if (x & 0x4 > 0)
                result = result * 0x10000000000000002C5C85FDF473DE6B2 >> 128;
            if (x & 0x2 > 0)
                result = result * 0x1000000000000000162E42FEFA39EF358 >> 128;
            if (x & 0x1 > 0)
                result = result * 0x10000000000000000B17217F7D1CF79AB >> 128;

            result >>= uint256 (int256 (63 - (x >> 64)));
            require (result <= uint256 (int256 (MAX_64x64)));

            return int128 (int256 (result));
        }
    }

    /**
     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit
     * integer numbers.  Revert on overflow or when y is zero.
     *
     * @param x unsigned 256-bit integer number
     * @param y unsigned 256-bit integer number
     * @return unsigned 64.64-bit fixed point number
     */
    function divuu (uint256 x, uint256 y) private pure returns (uint128) {
        unchecked {
            require (y != 0);

            uint256 result;

            if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
                result = (x << 64) / y;
            else {
                uint256 msb = 192;
                uint256 xc = x >> 192;
                if (xc >= 0x100000000) { xc >>= 32; msb += 32; }
                if (xc >= 0x10000) { xc >>= 16; msb += 16; }
                if (xc >= 0x100) { xc >>= 8; msb += 8; }
                if (xc >= 0x10) { xc >>= 4; msb += 4; }
                if (xc >= 0x4) { xc >>= 2; msb += 2; }
                if (xc >= 0x2) msb += 1;  // No need to shift xc anymore

                result = (x << 255 - msb) / ((y - 1 >> msb - 191) + 1);
                require (result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);

                uint256 hi = result * (y >> 128);
                uint256 lo = result * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);

                uint256 xh = x >> 192;
                uint256 xl = x << 64;

                if (xl < lo) xh -= 1;
                xl -= lo; // We rely on overflow behavior here
                lo = hi << 128;
                if (xl < lo) xh -= 1;
                xl -= lo; // We rely on overflow behavior here

                assert (xh == hi >> 128);

                result += xl / y;
            }

            require (result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
            return uint128 (result);
        }
    }
}

File 6 of 7 : SqrtMath.sol
pragma solidity 0.8.17;

// SPDX-License-Identifier: AGPL-2.0

//https://github.com/Gaussian-Process/solidity-sqrt/blob/main/src/FixedPointMathLib.sol
library SqrtMath {
    function sqrt(uint256 x) internal pure returns (uint256 z) {
        assembly {
            // This segment is to get a reasonable initial estimate for the Babylonian method.
            // If the initial estimate is bad, the number of correct bits increases ~linearly
            // each iteration instead of ~quadratically.
            // The idea is to get z*z*y within a small factor of x.
            // More iterations here gets y in a tighter range. Currently, we will have
            // y in [256, 256*2^16). We ensure y>= 256 so that the relative difference
            // between y and y+1 is small. If x < 256 this is not possible, but those cases
            // are easy enough to verify exhaustively.
            z := 181 // The 'correct' value is 1, but this saves a multiply later
            let y := x
            // Note that we check y>= 2^(k + 8) but shift right by k bits each branch,
            // this is to ensure that if x >= 256, then y >= 256.
            if iszero(lt(y, 0x10000000000000000000000000000000000)) {
                y := shr(128, y)
                z := shl(64, z)
            }
            if iszero(lt(y, 0x1000000000000000000)) {
                y := shr(64, y)
                z := shl(32, z)
            }
            if iszero(lt(y, 0x10000000000)) {
                y := shr(32, y)
                z := shl(16, z)
            }
            if iszero(lt(y, 0x1000000)) {
                y := shr(16, y)
                z := shl(8, z)
            }
            // Now, z*z*y <= x < z*z*(y+1), and y <= 2^(16+8),
            // and either y >= 256, or x < 256.
            // Correctness can be checked exhaustively for x < 256, so we assume y >= 256.
            // Then z*sqrt(y) is within sqrt(257)/sqrt(256) of x, or about 20bps.

            // The estimate sqrt(x) = (181/1024) * (x+1) is off by a factor of ~2.83 both when x=1
            // and when x = 256 or 1/256. In the worst case, this needs seven Babylonian iterations.
            z := shr(18, mul(z, add(y, 65536))) // A multiply is saved from the initial z := 181

            // Run the Babylonian method seven times. This should be enough given initial estimate.
            // Possibly with a quadratic/cubic polynomial above we could get 4-6.
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))

            // See https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division.
            // If x+1 is a perfect square, the Babylonian method cycles between
            // floor(sqrt(x)) and ceil(sqrt(x)). This check ensures we return floor.
            // The solmate implementation assigns zRoundDown := div(x, z) first, but
            // since this case is rare, we choose to save gas on the assignment and
            // repeat division in the rare case.
            // If you don't care whether floor or ceil is returned, you can skip this.
            if lt(div(x, z), z) {
                z := div(x, z)
            }
        }
    }
}

File 7 of 7 : TransferHelper.sol
pragma solidity 0.8.17;

// SPDX-License-Identifier: AGPL-2.0

library TransferHelper {
    function safeApprove(address token, address to, uint value) internal {
        // bytes4(keccak256(bytes('approve(address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'transferHelper: approve failed');
    }

    function safeTransfer(address token, address to, uint value) internal {
        // bytes4(keccak256(bytes('transfer(address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'transferHelper: transfer failed');
    }

    function safeTransferFrom(address token, address from, address to, uint value) internal {
        // bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'transferHelper: transferFrom failed');
    }

    function safeTransferETH(address to, uint value) internal {
        (bool success,) = to.call{value:value}(new bytes(0));
        require(success, 'transferHelper: ETH transfer failed');
    }
}

Settings
{
  "remappings": [
    "@openzeppelin/=lib/openzeppelin-contracts/",
    "interface/=src/interface/",
    "util/=src/util/",
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
    "forge-std/=lib/forge-std/src/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/",
    "openzeppelin/=lib/openzeppelin-contracts/contracts/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs"
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "london",
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"bool","name":"isToken0","type":"bool"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"token0Amt","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"token1Amt","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"due","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"token0Amt","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"token1Amt","type":"uint256"}],"name":"FeeCollected","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"bool","name":"isSwap0","type":"bool"},{"indexed":false,"internalType":"uint256","name":"amountIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOut","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"Swap","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"bool","name":"isToken0","type":"bool"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOut","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"APPROVE_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"basis","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"_oldFeeRatio","type":"uint64"},{"internalType":"uint256","name":"_elapsedTime","type":"uint256"}],"name":"calcNewFeeRatio","outputs":[{"internalType":"uint64","name":"_newFeeRatio","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collectFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"input","type":"uint256"},{"internalType":"uint256","name":"minOutput","type":"uint256"},{"internalType":"uint256","name":"time","type":"uint256"}],"name":"deposit0","outputs":[{"internalType":"uint256","name":"output","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"input","type":"uint256"},{"internalType":"uint256","name":"minOutput","type":"uint256"},{"internalType":"uint256","name":"time","type":"uint256"}],"name":"deposit1","outputs":[{"internalType":"uint256","name":"output","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"farm","outputs":[{"internalType":"contract IFarm","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeTo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFeeRatio","outputs":[{"internalType":"uint64","name":"_feeRatio0","type":"uint64"},{"internalType":"uint64","name":"_feeRatio1","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"time","type":"uint256"}],"name":"getPremium","outputs":[{"internalType":"uint256","name":"premium","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getReserves","outputs":[{"internalType":"uint256","name":"reserve0","type":"uint256"},{"internalType":"uint256","name":"reserve1","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"halfLife","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token0","type":"address"},{"internalType":"address","name":"_token1","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"noteCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"notes","outputs":[{"internalType":"uint256","name":"token0Amt","type":"uint256"},{"internalType":"uint256","name":"token1Amt","type":"uint256"},{"internalType":"uint256","name":"due","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"operatorApprovals","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"rescueERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"sig","type":"bytes"}],"name":"setApprovalForAllWithSig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_basis","type":"uint256"}],"name":"setBasis","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_farm","type":"address"}],"name":"setFarm","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feeTo","type":"address"}],"name":"setFeeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_halfLife","type":"uint64"}],"name":"setHalfLife","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"input","type":"uint256"},{"internalType":"uint256","name":"minOutput","type":"uint256"}],"name":"swap0in","outputs":[{"internalType":"uint256","name":"output","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"input","type":"uint256"},{"internalType":"uint256","name":"minOutput","type":"uint256"}],"name":"swap1in","outputs":[{"internalType":"uint256","name":"output","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"token0","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token1","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"withdraw","outputs":[{"internalType":"uint256","name":"token0Amt","type":"uint256"},{"internalType":"uint256","name":"token1Amt","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawFrom","outputs":[{"internalType":"uint256","name":"token0Amt","type":"uint256"},{"internalType":"uint256","name":"token1Amt","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101ef5760003560e01c80637ecebe001161010f578063d4d5d32a116100a2578063e146141c11610071578063e146141c14610517578063e162402f1461052a578063f385cecb1461053d578063f46901ed1461054657600080fd5b8063d4d5d32a14610487578063d4f26c511461048f578063dc950d36146104a2578063e0b117ff146104c257600080fd5b8063b2118a8d116100de578063b2118a8d14610427578063c45a01551461043a578063c9f10f8c1461044d578063d21220a71461047457600080fd5b80637ecebe00146103ce5780637f568f18146103ee578063a22cb46514610401578063a9d9db4d1461041457600080fd5b80633644e5151161018757806359362b881161015657806359362b8814610355578063666093341461037d5780637b7e9fac146103a85780637bc90d1c146103bb57600080fd5b80633644e515146102f557806336e9332d1461031c578063485cc9551461032f57806353d56bf51461034257600080fd5b80630dfe1681116101c35780630dfe1681146102925780631bf1fffb146102ac57806322ff2a8e146102cd57806330d6618e146102e257600080fd5b8062f714ce146101f4578063017e7e58146102215780630902f1ac1461024c5780630d95e05414610254575b600080fd5b610207610202366004612f5d565b610559565b604080519283526020830191909152015b60405180910390f35b600354610234906001600160a01b031681565b6040516001600160a01b039091168152602001610218565b6102076105a7565b610282610262366004612f8d565b600d60209081526000928352604080842090915290825290205460ff1681565b6040519015158152602001610218565b60015461023490600160401b90046001600160a01b031681565b6102bf6102ba366004612fbb565b6106b2565b604051908152602001610218565b6102e06102db366004612feb565b6107a1565b005b6102bf6102f0366004613006565b6108f3565b6102bf7f92bf5729d2acaa457912d2874296bd4b6294769a636428802dd3dd2395de0e5b81565b600954610234906001600160a01b031681565b6102e061033d366004612f8d565b6109f8565b6102bf610350366004613041565b610a18565b61035d610b13565b604080516001600160401b03938416815292909116602083015201610218565b61039061038b366004613076565b610b8d565b6040516001600160401b039091168152602001610218565b6102e06103b63660046130ae565b610be3565b600154610390906001600160401b031681565b6102bf6103dc366004613160565b60076020526000908152604090205481565b6102e06103fc366004612fbb565b610ecf565b6102e061040f36600461317d565b610fac565b6102bf610422366004613041565b611068565b6102e06104353660046131ab565b611152565b600854610234906001600160a01b031681565b6102bf7fd7db667cdba90ca333b850481afd8f802dc1081fc1d7ee77ee75ae69468a0b1781565b600254610234906001600160a01b031681565b6102e061123d565b6102e061049d366004613160565b611273565b6102bf6104b0366004613160565b600b6020526000908152604090205481565b6104fc6104d03660046131ec565b600c60209081526000928352604080842090915290825290208054600182015460029092015490919083565b60408051938452602084019290925290820152606001610218565b6102bf610525366004613006565b61136d565b61020761053836600461320a565b61145e565b6102bf600a5481565b6102e0610554366004613160565b6114d9565b6000806006546001146105875760405162461bcd60e51b815260040161057e9061324c565b60405180910390fd5b60006006556105973385856115ec565b6001600655909590945092505050565b600480546001546040516370a0823160e01b81523093810193909352600092839291600160401b90046001600160a01b0316906370a0823190602401602060405180830381865afa158015610600573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610624919061326c565b61062e919061329b565b6005546002546040516370a0823160e01b815230600482015292945090916001600160a01b03909116906370a0823190602401602060405180830381865afa15801561067e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106a2919061326c565b6106ac919061329b565b90509091565b60008162015180036106ec57670de0b6b3a7640000600a54664a620d26ead0e46106dc91906132ae565b6106e691906132db565b92915050565b816203f4800361071457670de0b6b3a7640000600a546680d5cceb1376a86106dc91906132ae565b8162093a800361073c57670de0b6b3a7640000600a5466c4cc884ac66cf86106dc91906132ae565b8162278d000361076557670de0b6b3a7640000600a54670197699c5ceeb4006106dc91906132ae565b60405162461bcd60e51b815260206004820152600c60248201526b696e76616c69642074696d6560a01b604482015260640161057e565b919050565b6006546001146107c35760405162461bcd60e51b815260040161057e9061324c565b6000600681905550336001600160a01b0316600860009054906101000a90046001600160a01b03166001600160a01b031663f77c47916040518163ffffffff1660e01b81526004016020604051808303816000875af115801561082a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084e91906132fd565b6001600160a01b0316146108745760405162461bcd60e51b815260040161057e9061331a565b6000816001600160401b0316116108cd5760405162461bcd60e51b815260206004820152601860248201527f68616c66206c6966652063616e6e6f74206265207a65726f0000000000000000604482015260640161057e565b6001805467ffffffffffffffff19166001600160401b0392909216919091178155600655565b60006006546001146109175760405162461bcd60e51b815260040161057e9061324c565b60006006556001600160a01b0385166109665760405162461bcd60e51b8152602060048201526011602482015270746f2063616e6e6f74206265207a65726f60781b604482015260640161057e565b6000610972858561187d565b925090506000610981846106b2565b9050610992876000858988866119a7565b6003546001600160a01b0316156109c5576109ae6002836132db565b600560008282546109bf919061333d565b90915550505b6002546109dd906001600160a01b0316333089611ae7565b6109e987878584611c17565b50506001600655949350505050565b610a028282611cc5565b5050600880546001600160a01b03191633179055565b6000600654600114610a3c5760405162461bcd60e51b815260040161057e9061324c565b60006006819055610a4d848461187d565b6003549093509091506001600160a01b031615610a8657610a6f6002826132db565b60056000828254610a80919061333d565b90915550505b600254610a9e906001600160a01b0316333087611ae7565b600154610abc90600160401b90046001600160a01b03168684611d36565b60408051858152602081018490526001600160a01b0387169160009133917f66251e495e6e69e208ab08e2bc259dbe2ef482a8c4a93b8984b03a1eb27e1b9e91015b60405180910390a45060016006559392505050565b600080600080610b4b6000546001600160401b0380821692600160401b8304821692600160801b8104831692600160c01b9091041690565b92965090945092509050610b6c8461038b6001600160401b0385164261329b565b9350610b858361038b6001600160401b0384164261329b565b925050509091565b6001546000908190610ba99084906001600160401b0316611e51565b90506000610bc1610bb983613350565b600f0b611e92565b9050610bda600f82900b6001600160401b038716612950565b95945050505050565b8242111580610bf0575082155b610c2e5760405162461bcd60e51b815260206004820152600f60248201526e65786365656420646561646c696e6560881b604482015260640161057e565b6001600160a01b038616610c7b5760405162461bcd60e51b81526020600482015260146024820152736f776e65722063616e6e6f74206265207a65726f60601b604482015260640161057e565b6001600160a01b038516610ccb5760405162461bcd60e51b81526020600482015260176024820152766f70657261746f722063616e6e6f74206265207a65726f60481b604482015260640161057e565b6001600160a01b038616600090815260076020526040812080547fd7db667cdba90ca333b850481afd8f802dc1081fc1d7ee77ee75ae69468a0b17918991899189919086610d1883613376565b909155506040805160208101969096526001600160a01b03948516908601529290911660608401521515608083015260a082015260c0810185905260e00160408051601f1981840301815290829052805160209182012061190160f01b918301919091527f92bf5729d2acaa457912d2874296bd4b6294769a636428802dd3dd2395de0e5b6022830152604282018190529150600090606201604051602081830303815290604052805190602001209050610e098185858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506129bb92505050565b6001600160a01b0316886001600160a01b031614610e5d5760405162461bcd60e51b8152602060048201526011602482015270696e76616c6964207369676e617475726560781b604482015260640161057e565b6001600160a01b038881166000818152600d60209081526040808320948c1680845294825291829020805460ff19168b151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050505050505050565b600654600114610ef15760405162461bcd60e51b815260040161057e9061324c565b6000600681905550336001600160a01b0316600860009054906101000a90046001600160a01b03166001600160a01b031663f77c47916040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610f58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f7c91906132fd565b6001600160a01b031614610fa25760405162461bcd60e51b815260040161057e9061331a565b600a556001600655565b6001600160a01b038216610ffc5760405162461bcd60e51b81526020600482015260176024820152766f70657261746f722063616e6e6f74206265207a65726f60481b604482015260640161057e565b336000818152600d602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b600060065460011461108c5760405162461bcd60e51b815260040161057e9061324c565b6000600681905561109d8484612aa4565b6003549093509091506001600160a01b0316156110d6576110bf6002826132db565b600460008282546110d0919061333d565b90915550505b6001546110f590600160401b90046001600160a01b0316333087611ae7565b60025461110c906001600160a01b03168684611d36565b60408051858152602081018490526001600160a01b0387169160019133917f66251e495e6e69e208ab08e2bc259dbe2ef482a8c4a93b8984b03a1eb27e1b9e9101610afe565b6008546040805163f77c479160e01b8152905133926001600160a01b03169163f77c479191600480830192602092919082900301816000875af115801561119d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111c191906132fd565b6001600160a01b0316146111e75760405162461bcd60e51b815260040161057e9061331a565b6001546001600160a01b03600160401b90910481169084160361120957600080fd5b6002546001600160a01b039081169084160361122457600080fd5b6112386001600160a01b0384168383611d36565b505050565b60065460011461125f5760405162461bcd60e51b815260040161057e9061324c565b600060065561126c612bc1565b6001600655565b6006546001146112955760405162461bcd60e51b815260040161057e9061324c565b6000600681905550336001600160a01b0316600860009054906101000a90046001600160a01b03166001600160a01b031663f77c47916040518163ffffffff1660e01b81526004016020604051808303816000875af11580156112fc573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061132091906132fd565b6001600160a01b0316146113465760405162461bcd60e51b815260040161057e9061331a565b600980546001600160a01b0319166001600160a01b03929092169190911790556001600655565b60006006546001146113915760405162461bcd60e51b815260040161057e9061324c565b60006006556001600160a01b0385166113e05760405162461bcd60e51b8152602060048201526011602482015270746f2063616e6e6f74206265207a65726f60781b604482015260640161057e565b60006113ec8585612aa4565b9250905060006113fb846106b2565b905061140c876001888688866119a7565b6003546001600160a01b03161561143f576114286002836132db565b60046000828254611439919061333d565b90915550505b6001546109dd90600160401b90046001600160a01b0316333089611ae7565b6001600160a01b0383166000908152600d60209081526040808320338452909152812054819060ff166114c25760405162461bcd60e51b815260206004820152600c60248201526b3737ba1037b832b930ba37b960a11b604482015260640161057e565b6114cd8585856115ec565b91509150935093915050565b6006546001146114fb5760405162461bcd60e51b815260040161057e9061324c565b6000600681905550336001600160a01b0316600860009054906101000a90046001600160a01b03166001600160a01b031663f77c47916040518163ffffffff1660e01b81526004016020604051808303816000875af1158015611562573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061158691906132fd565b6001600160a01b0316146115ac5760405162461bcd60e51b815260040161057e9061331a565b6003546001600160a01b0316156115c5576115c5612bc1565b600380546001600160a01b0319166001600160a01b03929092169190911790556001600655565b6001600160a01b0383166000908152600c6020908152604080832085845290915281208054600182018054600284018054868655928690559490945590929190806116685760405162461bcd60e51b815260206004820152600c60248201526b696e76616c6964206e6f746560a01b604482015260640161057e565b428111156116ab5760405162461bcd60e51b815260206004820152601060248201526f19585c9b1e481dda5d1a191c985dd85b60821b604482015260640161057e565b6000806116b66105a7565b915091506000806116c5610b13565b9092509050826116da886401000000006132ae565b6116e491906132db565b84896117346117006001600160401b038616600160401b61329b565b6117176001600160401b038816600160401b61329b565b61172590600160401b6132ae565b61172f91906132db565b612c53565b61173e91906132ae565b61174891906132db565b10156117e4576001546000975061177090600160401b90046001600160a01b03168a8a611d36565b600084611781600160401b8b6132ae565b61178b91906132db565b90506117978382612cfb565b604080518c8152602081018b90526001916001600160a01b038f16917f8595f614655883bce3496fde65b1ff62bb8b336cc93d72a91cd2f61f1566872f910160405180910390a35061186f565b600254600098506117ff906001600160a01b03168a89611d36565b600083611810600160401b8a6132ae565b61181a91906132db565b90506118268282612d48565b604080518c8152602081018a90526000916001600160a01b038f16917f8595f614655883bce3496fde65b1ff62bb8b336cc93d72a91cd2f61f1566872f910160405180910390a3505b505050505050935093915050565b600080600084116118c75760405162461bcd60e51b81526020600482015260146024820152731a5b9d985b1a59081a5b9c1d5d08185b5bdd5b9d60621b604482015260640161057e565b6000806118d26105a7565b915091506000806118e1610b13565b9092509050600160401b6118fe896001600160401b0384166132ae565b61190891906132db565b95506000611916878a61329b565b9050611922818561333d565b61192c86836132ae565b61193691906132db565b9550878610156119735760405162461bcd60e51b8152602060048201526008602482015267736c69707061676560c01b604482015260640161057e565b600085611984600160401b896132ae565b61198e91906132db565b905061199a8482612cfb565b5050505050509250929050565b6001600160a01b0386166000908152600b60205260408120805490826119cc83613376565b909155506001600160a01b0388166000908152600c60209081526040808320848452909152812091925087611a015785611a03565b865b90506000670de0b6b3a7640000611a1a818761333d565b611a24908a6132ae565b611a2e91906132db565b90506000670de0b6b3a7640000611a45818861333d565b611a4f908a6132ae565b611a5991906132db565b90506000611a67884261333d565b8386556001860183905560028601819055604080518881526020810187905290810185905260608101849052608081018290529091508b1515906001600160a01b038e16907f1a03e701f999967b189f59a5e5d6ddefdc9b644975d45bcf544d8755719a0bd79060a00160405180910390a3505050505050505050505050565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691611b4b919061338f565b6000604051808303816000865af19150503d8060008114611b88576040519150601f19603f3d011682016040523d82523d6000602084013e611b8d565b606091505b5091509150818015611bb7575080511580611bb7575080806020019051810190611bb791906133be565b611c0f5760405162461bcd60e51b815260206004820152602360248201527f7472616e7366657248656c7065723a207472616e7366657246726f6d206661696044820152621b195960ea1b606482015260840161057e565b505050505050565b6009546001600160a01b031615611cbf576000670de0b6b3a764000082611c4161172f86886132ae565b611c4b91906132ae565b611c5591906132db565b6009546040516352edeea160e01b81526001600160a01b038881166004830152602482018490529293509116906352edeea190604401600060405180830381600087803b158015611ca557600080fd5b505af1158015611cb9573d6000803e3d6000fd5b50505050505b50505050565b600154600160401b90046001600160a01b031615611cf55760405162461bcd60e51b815260040161057e9061331a565b6001805468010000000000000000600160e01b031916600160401b6001600160a01b0394851602179055600280546001600160a01b03191691909216179055565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691611d92919061338f565b6000604051808303816000865af19150503d8060008114611dcf576040519150601f19603f3d011682016040523d82523d6000602084013e611dd4565b606091505b5091509150818015611dfe575080511580611dfe575080806020019051810190611dfe91906133be565b611e4a5760405162461bcd60e51b815260206004820152601f60248201527f7472616e7366657248656c7065723a207472616e73666572206661696c656400604482015260640161057e565b5050505050565b600081600003611e6057600080fd5b6000611e6c8484612da3565b905060016001607f1b036001600160801b0382161115611e8b57600080fd5b9392505050565b60006840000000000000000082600f0b12611eac57600080fd5b683fffffffffffffffff1982600f0b1215611ec957506000919050565b6001607f1b60006780000000000000008416600f0b1315611efb5770016a09e667f3bcc908b2fb1366ea957d3e0260801c5b60008367400000000000000016600f0b1315611f28577001306fe0a31b7152de8d5a46305c85edec0260801c5b60008367200000000000000016600f0b1315611f55577001172b83c7d517adcdf7c8c50eb14a791f0260801c5b60008367100000000000000016600f0b1315611f825770010b5586cf9890f6298b92b71842a983630260801c5b60008367080000000000000016600f0b1315611faf577001059b0d31585743ae7c548eb68ca417fd0260801c5b60008367040000000000000016600f0b1315611fdc57700102c9a3e778060ee6f7caca4f7a29bde80260801c5b60008367020000000000000016600f0b13156120095770010163da9fb33356d84a66ae336dcdfa3f0260801c5b60008367010000000000000016600f0b131561203657700100b1afa5abcbed6129ab13ec11dc95430260801c5b600083668000000000000016600f0b13156120625770010058c86da1c09ea1ff19d294cf2f679b0260801c5b600083664000000000000016600f0b131561208e577001002c605e2e8cec506d21bfc89a23a00f0260801c5b600083662000000000000016600f0b13156120ba57700100162f3904051fa128bca9c55c31e5df0260801c5b600083661000000000000016600f0b13156120e6577001000b175effdc76ba38e31671ca9397250260801c5b600083660800000000000016600f0b131561211257700100058ba01fb9f96d6cacd4b180917c3d0260801c5b600083660400000000000016600f0b131561213e5770010002c5cc37da9491d0985c348c68e7b30260801c5b600083660200000000000016600f0b131561216a577001000162e525ee054754457d59952920260260801c5b600083660100000000000016600f0b13156121965770010000b17255775c040618bf4a4ade83fc0260801c5b6000836580000000000016600f0b13156121c1577001000058b91b5bc9ae2eed81e9b7d4cfab0260801c5b6000836540000000000016600f0b13156121ec57700100002c5c89d5ec6ca4d7c8acc017b7c90260801c5b6000836520000000000016600f0b13156122175770010000162e43f4f831060e02d839a9d16d0260801c5b6000836510000000000016600f0b131561224257700100000b1721bcfc99d9f890ea069117630260801c5b6000836508000000000016600f0b131561226d5770010000058b90cf1e6d97f9ca14dbcc16280260801c5b6000836504000000000016600f0b1315612298577001000002c5c863b73f016468f6bac5ca2b0260801c5b6000836502000000000016600f0b13156122c357700100000162e430e5a18f6119e3c02282a50260801c5b6000836501000000000016600f0b13156122ee577001000000b1721835514b86e6d96efd1bfe0260801c5b60008364800000000016600f0b131561231857700100000058b90c0b48c6be5df846c5b2ef0260801c5b60008364400000000016600f0b13156123425770010000002c5c8601cc6b9e94213c72737a0260801c5b60008364200000000016600f0b131561236c577001000000162e42fff037df38aa2b219f060260801c5b60008364100000000016600f0b13156123965770010000000b17217fba9c739aa5819f44f90260801c5b60008364080000000016600f0b13156123c0577001000000058b90bfcdee5acd3c1cedc8230260801c5b60008364040000000016600f0b13156123ea57700100000002c5c85fe31f35a6a30da1be500260801c5b60008364020000000016600f0b13156124145770010000000162e42ff0999ce3541b9fffcf0260801c5b60008364010000000016600f0b131561243e57700100000000b17217f80f4ef5aadda455540260801c5b600083638000000016600f0b13156124675770010000000058b90bfbf8479bd5a81b51ad0260801c5b600083634000000016600f0b1315612490577001000000002c5c85fdf84bd62ae30a74cc0260801c5b600083632000000016600f0b13156124b957700100000000162e42fefb2fed257559bdaa0260801c5b600083631000000016600f0b13156124e2577001000000000b17217f7d5a7716bba4a9ae0260801c5b600083630800000016600f0b131561250b57700100000000058b90bfbe9ddbac5e109cce0260801c5b600083630400000016600f0b13156125345770010000000002c5c85fdf4b15de6f17eb0d0260801c5b600083630200000016600f0b131561255d577001000000000162e42fefa494f1478fde050260801c5b600083630100000016600f0b13156125865770010000000000b17217f7d20cf927c8e94c0260801c5b6000836280000016600f0b13156125ae577001000000000058b90bfbe8f71cb4e4b33d0260801c5b6000836240000016600f0b13156125d657700100000000002c5c85fdf477b662b269450260801c5b6000836220000016600f0b13156125fe5770010000000000162e42fefa3ae53369388c0260801c5b6000836210000016600f0b131561262657700100000000000b17217f7d1d351a389d400260801c5b6000836208000016600f0b131561264e5770010000000000058b90bfbe8e8b2d3d4ede0260801c5b6000836204000016600f0b1315612676577001000000000002c5c85fdf4741bea6e77e0260801c5b6000836202000016600f0b131561269e57700100000000000162e42fefa39fe95583c20260801c5b6000836201000016600f0b13156126c6577001000000000000b17217f7d1cfb72b45e10260801c5b60008361800016600f0b13156126ed57700100000000000058b90bfbe8e7cc35c3f00260801c5b60008361400016600f0b13156127145770010000000000002c5c85fdf473e242ea380260801c5b60008361200016600f0b131561273b577001000000000000162e42fefa39f02b772c0260801c5b60008361100016600f0b13156127625770010000000000000b17217f7d1cf7d83c1a0260801c5b60008361080016600f0b1315612789577001000000000000058b90bfbe8e7bdcbe2e0260801c5b60008361040016600f0b13156127b057700100000000000002c5c85fdf473dea871f0260801c5b60008361020016600f0b13156127d75770010000000000000162e42fefa39ef44d910260801c5b60008361010016600f0b13156127fe57700100000000000000b17217f7d1cf79e9490260801c5b600083608016600f0b13156128245770010000000000000058b90bfbe8e7bce5440260801c5b600083604016600f0b131561284a577001000000000000002c5c85fdf473de6eca0260801c5b600083602016600f0b131561287057700100000000000000162e42fefa39ef366f0260801c5b600083601016600f0b1315612896577001000000000000000b17217f7d1cf79afa0260801c5b600083600816600f0b13156128bc57700100000000000000058b90bfbe8e7bcd6d0260801c5b600083600416600f0b13156128e25770010000000000000002c5c85fdf473de6b20260801c5b600083600216600f0b1315612908577001000000000000000162e42fefa39ef3580260801c5b600083600116600f0b131561292e5770010000000000000000b17217f7d1cf79ab0260801c5b600f83810b60401d603f03900b1c60016001607f1b038111156106e657600080fd5b600081600003612962575060006106e6565b600083600f0b121561297357600080fd5b600f83900b6001600160801b038316810260401c90608084901c026001600160c01b038111156129a257600080fd5b60401b81198111156129b357600080fd5b019392505050565b60008151604103612a9c5760208201516040830151606084015160001a7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115612a0c57600093505050506106e6565b8060ff16601b14158015612a2457508060ff16601c14155b15612a3557600093505050506106e6565b60408051600081526020810180835288905260ff831691810191909152606081018490526080810183905260019060a0016020604051602081039080840390855afa158015612a88573d6000803e3d6000fd5b5050506020604051035193505050506106e6565b5060006106e6565b60008060008411612aee5760405162461bcd60e51b81526020600482015260146024820152731a5b9d985b1a59081a5b9c1d5d08185b5bdd5b9d60621b604482015260640161057e565b600080612af96105a7565b91509150600080612b08610b13565b9092509050600160401b612b25896001600160401b0385166132ae565b612b2f91906132db565b95506000612b3d878a61329b565b9050612b49818661333d565b612b5385836132ae565b612b5d91906132db565b955087861015612b9a5760405162461bcd60e51b8152602060048201526008602482015267736c69707061676560c01b604482015260640161057e565b600084612bab600160401b896132ae565b612bb591906132db565b905061199a8382612d48565b6004805460058054600093849055929055600354600154919291612bf9916001600160a01b03600160401b9092048216911684611d36565b600354600254612c16916001600160a01b03918216911683611d36565b60408051838152602081018390527faf7c505ee772ec188af7067e1f73db08ab028e3d564273442b907742b9c41fa0910160405180910390a15050565b60b581600160881b8110612c6c5760409190911b9060801c5b69010000000000000000008110612c885760209190911b9060401c5b650100000000008110612ca05760109190911b9060201c5b63010000008110612cb65760089190911b9060101c5b62010000010260121c80820401600190811c80830401811c80830401811c80830401811c80830401811c80830401811c80830401901c80820481111561079c57900490565b612d058282612f08565b60008054426001600160401b03908116600160801b0277ffffffffffffffff0000000000000000ffffffffffffffff199092169316929092179190911790555050565b612d528282612f08565b6000805477ffffffffffffffff0000000000000000ffffffffffffffff16600160401b6001600160401b03938416026001600160c01b031617600160c01b4293909316929092029190911790555050565b600081600003612db257600080fd5b60006001600160c01b038411612ddd5782604085901b81612dd557612dd56132c5565b049050612ef4565b60c084811c6401000000008110612df6576020918201911c5b620100008110612e08576010918201911c5b6101008110612e19576008918201911c5b60108110612e29576004918201911c5b60048110612e39576002918201911c5b60028110612e48576001820191505b60bf820360018603901c6001018260ff0387901b81612e6957612e696132c5565b0492506001600160801b03831115612e8057600080fd5b608085901c83026001600160801b038616840260c088901c604089901b82811015612eac576001820391505b608084901b92900382811015612ec3576001820391505b829003608084901c8214612ed957612ed96133db565b888181612ee857612ee86132c5565b04870196505050505050505b6001600160801b03811115611e8b57600080fd5b60006001600160401b03808416908316600160401b612f2782846132ae565b612f3191906132db565b612f3b828461333d565b610bda919061329b565b6001600160a01b0381168114612f5a57600080fd5b50565b60008060408385031215612f7057600080fd5b823591506020830135612f8281612f45565b809150509250929050565b60008060408385031215612fa057600080fd5b8235612fab81612f45565b91506020830135612f8281612f45565b600060208284031215612fcd57600080fd5b5035919050565b80356001600160401b038116811461079c57600080fd5b600060208284031215612ffd57600080fd5b611e8b82612fd4565b6000806000806080858703121561301c57600080fd5b843561302781612f45565b966020860135965060408601359560600135945092505050565b60008060006060848603121561305657600080fd5b833561306181612f45565b95602085013595506040909401359392505050565b6000806040838503121561308957600080fd5b61309283612fd4565b946020939093013593505050565b8015158114612f5a57600080fd5b60008060008060008060a087890312156130c757600080fd5b86356130d281612f45565b955060208701356130e281612f45565b945060408701356130f2816130a0565b93506060870135925060808701356001600160401b038082111561311557600080fd5b818901915089601f83011261312957600080fd5b81358181111561313857600080fd5b8a602082850101111561314a57600080fd5b6020830194508093505050509295509295509295565b60006020828403121561317257600080fd5b8135611e8b81612f45565b6000806040838503121561319057600080fd5b823561319b81612f45565b91506020830135612f82816130a0565b6000806000606084860312156131c057600080fd5b83356131cb81612f45565b925060208401356131db81612f45565b929592945050506040919091013590565b600080604083850312156131ff57600080fd5b823561309281612f45565b60008060006060848603121561321f57600080fd5b833561322a81612f45565b925060208401359150604084013561324181612f45565b809150509250925092565b6020808252600690820152651b1bd8dad95960d21b604082015260600190565b60006020828403121561327e57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b818103818111156106e6576106e6613285565b80820281158282048414176106e6576106e6613285565b634e487b7160e01b600052601260045260246000fd5b6000826132f857634e487b7160e01b600052601260045260246000fd5b500490565b60006020828403121561330f57600080fd5b8151611e8b81612f45565b6020808252600990820152683337b93134b23232b760b91b604082015260600190565b808201808211156106e6576106e6613285565b600081600f0b60016001607f1b0319810361336d5761336d613285565b60000392915050565b60006001820161338857613388613285565b5060010190565b6000825160005b818110156133b05760208186018101518583015201613396565b506000920191825250919050565b6000602082840312156133d057600080fd5b8151611e8b816130a0565b634e487b7160e01b600052600160045260246000fdfea2646970667358221220959f017971a302057f5ecf5ed9586cb7126104b71abac7bfbfa2800e57d7fbdd64736f6c63430008110033

Block Transaction Gas Used Reward
view all blocks sequenced

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

Validator Index Block Amount
View All Withdrawals

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

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