S Price: $0.442117 (-11.18%)

Contract

0x4090a48fDd8a1ecA9a51011518637C670b1ae358

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Withdraw185605512025-04-06 19:38:3416 mins ago1743968314IN
0x4090a48f...70b1ae358
0 S0.0076486650.0001
Claim185605222025-04-06 19:38:2216 mins ago1743968302IN
0x4090a48f...70b1ae358
2.90520738 S0.0113838250.0001
Claim185591782025-04-06 19:30:3924 mins ago1743967839IN
0x4090a48f...70b1ae358
0.26620458 S0.0104044250.0001
Claim185590062025-04-06 19:29:3825 mins ago1743967778IN
0x4090a48f...70b1ae358
1.23248386 S0.0157384965.77
Claim185580492025-04-06 19:23:5731 mins ago1743967437IN
0x4090a48f...70b1ae358
37.10989388 S0.0132289461
Claim185580332025-04-06 19:23:5231 mins ago1743967432IN
0x4090a48f...70b1ae358
71.06809006 S0.0144835961
Withdraw185579742025-04-06 19:23:3331 mins ago1743967413IN
0x4090a48f...70b1ae358
0 S0.0086457560.5
Withdraw185579142025-04-06 19:23:1331 mins ago1743967393IN
0x4090a48f...70b1ae358
0 S0.008848955.01
Claim185576242025-04-06 19:21:3433 mins ago1743967294IN
0x4090a48f...70b1ae358
3.74111862 S0.0134005756
Claim185542212025-04-06 19:02:1952 mins ago1743966139IN
0x4090a48f...70b1ae358
7.45083175 S0.0113838250.0001
Deposit185538272025-04-06 19:00:1354 mins ago1743966013IN
0x4090a48f...70b1ae358
0 S0.0077601755
Deposit185537252025-04-06 18:59:3655 mins ago1743965976IN
0x4090a48f...70b1ae358
0 S0.0067726455
Claim185532092025-04-06 18:56:4458 mins ago1743965804IN
0x4090a48f...70b1ae358
5.8042486 S0.0121737555
Withdraw185481712025-04-06 18:28:541 hr ago1743964134IN
0x4090a48f...70b1ae358
0 S0.0082032451
Withdraw185480342025-04-06 18:28:101 hr ago1743964090IN
0x4090a48f...70b1ae358
0 S0.0082032451
Withdraw185450992025-04-06 18:11:491 hr ago1743963109IN
0x4090a48f...70b1ae358
0 S0.0079357655.09723872
Claim185447392025-04-06 18:09:471 hr ago1743962987IN
0x4090a48f...70b1ae358
9.65894227 S0.0112838250.0001
Claim185446202025-04-06 18:09:091 hr ago1743962949IN
0x4090a48f...70b1ae358
0.60543009 S0.0157935366
Claim185424682025-04-06 17:56:501 hr ago1743962210IN
0x4090a48f...70b1ae358
0.00100832 S0.011929955.01
Claim185424492025-04-06 17:56:431 hr ago1743962203IN
0x4090a48f...70b1ae358
0.01781501 S0.0130613555.01
Claim185419712025-04-06 17:54:052 hrs ago1743962045IN
0x4090a48f...70b1ae358
30.57547156 S0.0112838250.0001
Claim185419432025-04-06 17:53:562 hrs ago1743962036IN
0x4090a48f...70b1ae358
0.75882774 S0.0131660655.02
Withdraw185417932025-04-06 17:53:022 hrs ago1743961982IN
0x4090a48f...70b1ae358
0 S0.0067936650.0001
Claim185416902025-04-06 17:52:252 hrs ago1743961945IN
0x4090a48f...70b1ae358
0.1316446 S0.0145970561
Withdraw185386222025-04-06 17:35:112 hrs ago1743960911IN
0x4090a48f...70b1ae358
0 S0.0076480650.0001
View all transactions

Latest 25 internal transactions (View All)

Parent Transaction Hash Block From To
185605222025-04-06 19:38:2216 mins ago1743968302
0x4090a48f...70b1ae358
0.4861783 S
185605222025-04-06 19:38:2216 mins ago1743968302
0x4090a48f...70b1ae358
2.41902907 S
185591782025-04-06 19:30:3924 mins ago1743967839
0x4090a48f...70b1ae358
0.04436973 S
185591782025-04-06 19:30:3924 mins ago1743967839
0x4090a48f...70b1ae358
0.22183485 S
185590062025-04-06 19:29:3825 mins ago1743967778
0x4090a48f...70b1ae358
0.2041726 S
185590062025-04-06 19:29:3825 mins ago1743967778
0x4090a48f...70b1ae358
1.02831126 S
185580492025-04-06 19:23:5731 mins ago1743967437
0x4090a48f...70b1ae358
6.18498231 S
185580492025-04-06 19:23:5731 mins ago1743967437
0x4090a48f...70b1ae358
30.92491157 S
185580332025-04-06 19:23:5231 mins ago1743967432
0x4090a48f...70b1ae358
11.84475462 S
185580332025-04-06 19:23:5231 mins ago1743967432
0x4090a48f...70b1ae358
59.22333544 S
185576242025-04-06 19:21:3433 mins ago1743967294
0x4090a48f...70b1ae358
0.62080631 S
185576242025-04-06 19:21:3433 mins ago1743967294
0x4090a48f...70b1ae358
3.1203123 S
185542212025-04-06 19:02:1952 mins ago1743966139
0x4090a48f...70b1ae358
1.24105219 S
185542212025-04-06 19:02:1952 mins ago1743966139
0x4090a48f...70b1ae358
6.20977955 S
185532092025-04-06 18:56:4458 mins ago1743965804
0x4090a48f...70b1ae358
0.95061545 S
185532092025-04-06 18:56:4458 mins ago1743965804
0x4090a48f...70b1ae358
4.85363315 S
185447392025-04-06 18:09:471 hr ago1743962987
0x4090a48f...70b1ae358
1.61242977 S
185447392025-04-06 18:09:471 hr ago1743962987
0x4090a48f...70b1ae358
8.04651249 S
185446202025-04-06 18:09:091 hr ago1743962949
0x4090a48f...70b1ae358
0.10015074 S
185446202025-04-06 18:09:091 hr ago1743962949
0x4090a48f...70b1ae358
0.50527934 S
185424682025-04-06 17:56:501 hr ago1743962210
0x4090a48f...70b1ae358
0.00016805 S
185424682025-04-06 17:56:501 hr ago1743962210
0x4090a48f...70b1ae358
0.00084027 S
185424492025-04-06 17:56:431 hr ago1743962203
0x4090a48f...70b1ae358
0.00295902 S
185424492025-04-06 17:56:431 hr ago1743962203
0x4090a48f...70b1ae358
0.01485599 S
185419712025-04-06 17:54:052 hrs ago1743962045
0x4090a48f...70b1ae358
5.11100936 S
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Camelot

Compiler Version
v0.8.20+commit.a1b79de6

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion
File 1 of 15 : Camelot.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "../interfaces/ISwapXGauge.sol";
import "../interfaces/IPNVFeeManager.sol";
import "../interfaces/IHelper.sol";
import "./owner/Operator.sol";
import "./libraries/SafeMath.sol";

contract Camelot is Operator, ReentrancyGuard {
    using SafeMath for uint256;
    using SafeERC20 for IERC20;

    // Info of each user.
    struct UserInfo {
        uint256 amount; // How many LP tokens the user has provided.
        uint256 rewardDebt; // Reward debt. See explanation below.
    }

    // Info of each pool.
    struct PoolInfo {
        IERC20 token; // Address of LP token contract.
        uint256 withFee; // withdraw fee that is applied to created pool.
        uint256 allocPoint; // How many allocation points assigned to this pool. KNIGHTs to distribute per block.
        uint256 lastRewardTime; // Last time that KNIGHTs distribution occurs.
        uint256 accKNIGHTPerShare; // Accumulated KNIGHTs per share, times 1e18. See below.
        bool isStarted; // if lastRewardTime has passed
        address gauge;
    }

    IERC20 public KNIGHT;
    IERC20 public SWPxToken = IERC20(0xA04BC7140c26fc9BB1F36B1A604C7A5a88fb0E70);
    IPNVFeeManager public PNVFeeManager;
    IHelper public helper;

    address public multiSigWallet;
    address public SPWxRewardsWallet;
    address public PNVWallet;
    
    // Info of each pool.
    PoolInfo[] public poolInfo;

    // Info of each user that stakes LP tokens.
    mapping(uint256 => mapping(address => UserInfo)) public userInfo;
    mapping(uint256 => mapping(address => uint256)) public pendingRewards;

    // Total allocation points. Must be the sum of all allocation points in all pools.
    uint256 public totalAllocPoint;

    // The time when KNIGHT mining starts.
    uint256 public poolStartTime;

    // The time when KNIGHT mining ends.
    uint256 public poolEndTime;
    uint256 public runningTime = 365 days;

    // PNV fee variables
    uint256 public minClaimThreshold = 1e12; // 0.000001 KNIGHT
    uint256 public pegNobilityVaultFee = 200; // 20%
    bool public pegNobilityVaultFeeEnabled = true;

    event Deposit(address indexed user, uint256 indexed pid, uint256 amount);
    event Withdraw(address indexed user, uint256 indexed pid, uint256 amount);
    event EmergencyWithdraw(address indexed user, uint256 indexed pid, uint256 amount);
    event RewardPaid(address indexed user, uint256 amount);
    event MultiSigWalletUpdated(address multiSigWallet);
    event GaugeDeposit(uint256 indexed pid, uint256 amount, bool success);
    event GaugeWithdraw(uint256 indexed pid, uint256 amount, bool success);
    event EmergencyGaugeWithdraw(uint256 indexed pid, uint256 amount);

    constructor(
        address _KNIGHT,
        address _multiSigWallet,
        address _SPWxRewardsWallet,
        address _PNVWallet,
        IPNVFeeManager _PNVFeeManager,
        uint256 _poolStartTime
        ) {
        require(
            block.timestamp < _poolStartTime,
            "pool cant be started in the past"
        );
        if (_KNIGHT != address(0)) KNIGHT = IERC20(_KNIGHT);
        if (_multiSigWallet != address(0)) multiSigWallet = _multiSigWallet;
        if (_SPWxRewardsWallet != address(0)) SPWxRewardsWallet = _SPWxRewardsWallet;
        if (_PNVWallet != address(0)) PNVWallet = _PNVWallet;
        if (address(_PNVFeeManager) != address(0)) PNVFeeManager = _PNVFeeManager;
        poolStartTime = _poolStartTime;
        poolEndTime = _poolStartTime + runningTime;
    }

    function poolLength() external view returns (uint256) {
        return poolInfo.length;
    }

    function checkPoolDuplicate(IERC20 _token) internal view {
        uint256 length = poolInfo.length;
        for (uint256 pid = 0; pid < length; ++pid) {
            require(
                poolInfo[pid].token != _token,
                "Camelot: existing pool?"
            );
        }
    }

    function addBulk(
        uint256[] calldata _allocPoints,
        uint256[] calldata _withFee,
        IERC20[] calldata _tokens,
        bool _withUpdate,
        uint256 _lastRewardTime,
        address[] calldata _gauge
        ) external onlyOperator {
        require(
            _allocPoints.length == _withFee.length &&
            _allocPoints.length == _tokens.length &&
            _allocPoints.length == _gauge.length,
            "Camelot: invalid length"
        );
        for (uint256 i = 0; i < _allocPoints.length; i++) {
            add(_allocPoints[i], _withFee[i], _tokens[i], _withUpdate, _lastRewardTime, _gauge[i]);
        }
    }

    // Add new lp to the pool. Can only be called by operator.
    function add(
        uint256 _allocPoint,
        uint256 _withFee,
        IERC20 _token,
        bool _withUpdate,
        uint256 _lastRewardTime,
        address _gauge
        ) public onlyOperator {
        require(_withFee <= 50, "Camelot: withdraw fee cant be more than 0.5%");  // withdraw fee cant be more than 0.5%;
        checkPoolDuplicate(_token);
        if (_withUpdate) {
            massUpdatePools();
        }
        if (block.timestamp < poolStartTime) {
            // chef is sleeping
            if (_lastRewardTime < poolStartTime) {
                _lastRewardTime = poolStartTime;
            }
        } else {
            // chef is cooking
            if (_lastRewardTime < block.timestamp) {
                _lastRewardTime = block.timestamp;
            }
        }
        bool _isStarted = (_lastRewardTime <= poolStartTime) ||
            (_lastRewardTime <= block.timestamp);
        poolInfo.push(
            PoolInfo({
                token: _token,
                withFee: _withFee,
                allocPoint: _allocPoint,
                lastRewardTime: _lastRewardTime,
                accKNIGHTPerShare: 0,
                isStarted: _isStarted,
                gauge: _gauge
            })
        );

        if (_isStarted) {
            totalAllocPoint = totalAllocPoint.add(_allocPoint);
        }
    }

    // bulk set pools
    function bulkSet(uint256[] calldata _pids, uint256[] calldata _allocPoints, uint256[] calldata _withFees, address[] calldata _gauges) external onlyOperator {
        require(
            _pids.length == _allocPoints.length &&
            _pids.length == _withFees.length &&
            _pids.length == _gauges.length,
            "Camelot: invalid length");
        for (uint256 i = 0; i < _pids.length; i++) {
            set(_pids[i], _allocPoints[i], _withFees[i], _gauges[i]);
        }
    }

    // Update the given pool's KNIGHT allocation point and gauge. Can only be called by the operator.
    function set(
        uint256 _pid,
        uint256 _allocPoint,
        uint256 _withFee,
        address _gauge
        ) public onlyOperator {
        massUpdatePools();

        PoolInfo storage pool = poolInfo[_pid];
        require(_withFee <= 50, "withdraw fee cant be more than 0.5%");
        pool.withFee = _withFee;

        if (pool.isStarted) {
            totalAllocPoint = totalAllocPoint.sub(pool.allocPoint).add(
                _allocPoint
            );
        }
        pool.allocPoint = _allocPoint;
        pool.gauge = _gauge;
        // Deposit to the gauge if it exists
        if (pool.gauge != address(0)) {
            depositToGauge(_pid);
        }
    }

    // Add helper function to calculate rewards across rate changes
    function getGeneratedReward(uint256 _fromTime, uint256 _toTime) public view returns (uint256) {
        if (_fromTime >= _toTime) return 0;
        if (_toTime >= poolEndTime) {
            if (_fromTime >= poolEndTime) return 0;
            if (_fromTime <= poolStartTime) return poolEndTime.sub(poolStartTime).mul(totalAllocPoint);
            return poolEndTime.sub(_fromTime).mul(totalAllocPoint);
        } else {
            if (_toTime <= poolStartTime) return 0;
            if (_fromTime <= poolStartTime) return _toTime.sub(poolStartTime).mul(totalAllocPoint);
            return _toTime.sub(_fromTime).mul(totalAllocPoint);
        }
    }

    function pendingShare(uint256 _pid, address _user) public view returns (uint256) {
        require(_pid < poolInfo.length, "Camelot: invalid pool id");
        PoolInfo storage pool = poolInfo[_pid];
        UserInfo storage user = userInfo[_pid][_user];
        uint256 accKNIGHTPerShare = pool.accKNIGHTPerShare;
        uint256 tokenSupply = pool.gauge != address(0) ? ISwapxGauge(pool.gauge).balanceOf(address(this)) : pool.token.balanceOf(address(this));
        if (block.timestamp > pool.lastRewardTime && tokenSupply != 0) {
            uint256 _generatedReward = getGeneratedReward(pool.lastRewardTime, block.timestamp);
            uint256 _KNIGHTReward = _generatedReward.mul(pool.allocPoint).div(totalAllocPoint);
            accKNIGHTPerShare = accKNIGHTPerShare.add(_KNIGHTReward.mul(1e18).div(tokenSupply));
        }
        return user.amount.mul(accKNIGHTPerShare).div(1e18).sub(user.rewardDebt);
    }

    function pendingTotalRewards(uint256 _pid, address _user) public view returns (uint256) {
        require(_pid < poolInfo.length, "Camelot: invalid pool id");
        uint256 _pendingShare = pendingShare(_pid, _user);
        return _pendingShare.add(pendingRewards[_pid][_user]);
    }

    function getPNVFee(uint256 _pid, address _user, address _token) public view returns (uint256) {
        require(_pid < poolInfo.length, "Camelot: invalid pool id");
        uint256 rewardsToClaim = pendingTotalRewards(_pid, _user);
        uint256 PNVFeeAmount = PNVFeeManager.getPNVFeeAmount(rewardsToClaim, _token, pegNobilityVaultFee);
        return PNVFeeAmount;
    }

    function getAllPNVFee(address _user, address _token) public view returns (uint256) {
        uint256 rewardsToClaim = 0;
        for (uint256 pid = 0; pid < poolInfo.length; ++pid) {
            rewardsToClaim += pendingTotalRewards(pid, _user);
        }
        uint256 PNVFeeAmount = PNVFeeManager.getPNVFeeAmount(rewardsToClaim, _token, pegNobilityVaultFee);
        return PNVFeeAmount;
    }

    function massUpdatePools() public {
        uint256 length = poolInfo.length;
        for (uint256 pid = 0; pid < length; ++pid) {
            updatePool(pid);
        }
    }

    // Update reward variables of the given pool to be up-to-date.
    function updatePool(uint256 _pid) public {
        require(_pid < poolInfo.length, "Camelot: invalid pool id");
        PoolInfo storage pool = poolInfo[_pid];
        if (block.timestamp <= pool.lastRewardTime) {
            return;
        }
        uint256 tokenSupply = pool.gauge != address(0) ? ISwapxGauge(pool.gauge).balanceOf(address(this)) : pool.token.balanceOf(address(this));
        if (tokenSupply == 0) {
            pool.lastRewardTime = block.timestamp;
            return;
        }
        if (!pool.isStarted) {
            pool.isStarted = true;
            totalAllocPoint = totalAllocPoint.add(pool.allocPoint);
        }
        if (totalAllocPoint > 0) {
            // This now correctly accounts for all emission rate changes
            uint256 _generatedReward = getGeneratedReward(pool.lastRewardTime,block.timestamp);
            uint256 _KNIGHTReward = _generatedReward.mul(pool.allocPoint).div(totalAllocPoint);
            pool.accKNIGHTPerShare = pool.accKNIGHTPerShare.add(_KNIGHTReward.mul(1e18).div(tokenSupply));
        }
        pool.lastRewardTime = block.timestamp;
    }

    // Deposit LP tokens.
    function deposit(uint256 _pid, uint256 _amount, address _token) public nonReentrant {
        require(_pid < poolInfo.length, "Camelot: invalid pool id");
        address _sender = msg.sender;
        PoolInfo storage pool = poolInfo[_pid];
        UserInfo storage user = userInfo[_pid][_sender];
        // will be for future use on zapper, compound, etc.
        require(
            _token == address(0) ||
            address(helper) != address(0),
            "Camelot: invalid token"
        );
        updatePool(_pid);
        if (user.amount > 0) {
            uint256 _pending = user.amount.mul(pool.accKNIGHTPerShare).div(1e18).sub(user.rewardDebt);
            if (_pending > 0) {
                // accrue pending rewards to be claimed later
                pendingRewards[_pid][_sender] = pendingRewards[_pid][_sender].add(_pending);
            }
        }
        if (_amount > 0) {
            // if _token is address(0), it means the token is pool.token so behave as normal
            if (_token == address(0)) {
                pool.token.safeTransferFrom(_sender, address(this), _amount);
                user.amount = user.amount.add(_amount);
            // if _token is not address(0), it means the token needs the help of the helper contract so it can convert the token to pool.token
            } else {
                IERC20 token = IERC20(_token);
                token.safeTransferFrom(_sender, address(this), _amount);
                token.approve(address(helper), _amount);
                uint256 amount = helper.helperConvert(_token, address(pool.token), _amount);
                require(amount > 0, "Camelot: helper conversion returned zero amount");
                user.amount = user.amount.add(amount);
            }
            depositToGauge(_pid);
        }
        user.rewardDebt = user.amount.mul(pool.accKNIGHTPerShare).div(1e18);
        emit Deposit(_sender, _pid, _amount);
    }

    // Withdraw LP tokens.
    function withdraw(uint256 _pid, uint256 _amount) public nonReentrant {
        require(_pid < poolInfo.length, "Camelot: invalid pool id");
        address _sender = msg.sender;
        PoolInfo storage pool = poolInfo[_pid];
        UserInfo storage user = userInfo[_pid][_sender];
        require(user.amount >= _amount, "Camelot: user does not have enough balance deposited");
        updatePool(_pid);
        uint256 _pending = user.amount.mul(pool.accKNIGHTPerShare).div(1e18).sub(user.rewardDebt);
        if (_pending > 0) {
            // accrue pending rewards to be claimed later
            pendingRewards[_pid][_sender] = pendingRewards[_pid][_sender].add(_pending);
        }
        if (_amount > 0) {
            user.amount = user.amount.sub(_amount);
            withdrawFromGauge(_pid, _amount);
            // Calculate the fee and transfer it to the multiSigWallet
            uint256 fee = _amount.mul(pool.withFee).div(10000); // Assuming withFee is in basis points (e.g., 50 = 0.5%)
            uint256 amountAfterFee = _amount.sub(fee);
            if (fee > 0) {
                pool.token.safeTransfer(multiSigWallet, fee);
            }
            pool.token.safeTransfer(_sender, amountAfterFee);
        }
        user.rewardDebt = user.amount.mul(pool.accKNIGHTPerShare).div(1e18);
        emit Withdraw(_sender, _pid, _amount);
    }

    // Withdraw without caring about rewards. EMERGENCY ONLY.
    function emergencyWithdraw(uint256 _pid) public nonReentrant {
        require(_pid < poolInfo.length, "Camelot: invalid pool id");
        PoolInfo storage pool = poolInfo[_pid];
        UserInfo storage user = userInfo[_pid][msg.sender];
        uint256 _amount = user.amount;
        user.amount = 0;
        user.rewardDebt = 0;
        pendingRewards[_pid][msg.sender] = 0;
        withdrawFromGauge(_pid, _amount);
        uint256 fee = _amount.mul(pool.withFee).div(10000); // Assuming withFee is in basis points (e.g., 50 = 0.5%)
        uint256 amountAfterFee = _amount.sub(fee);
        if (fee > 0) {
            pool.token.safeTransfer(multiSigWallet, fee);
        }
        pool.token.safeTransfer(msg.sender, amountAfterFee);
        emit EmergencyWithdraw(msg.sender, _pid, _amount);
    }

    function _calculatePendingRewards(uint256 _pid, address _sender) internal returns (uint256) {
        PoolInfo storage pool = poolInfo[_pid];
        UserInfo storage user = userInfo[_pid][_sender];
        if (user.amount == 0) {
            return 0;
        }
        updatePool(_pid);
        uint256 _pending = user.amount.mul(pool.accKNIGHTPerShare).div(1e18).sub(user.rewardDebt);
        pendingRewards[_pid][_sender] = pendingRewards[_pid][_sender].add(_pending);
        uint256 _rewardsToClaim = pendingRewards[_pid][_sender];
        pendingRewards[_pid][_sender] = 0;
        user.rewardDebt = user.amount.mul(pool.accKNIGHTPerShare).div(1e18);
        return _rewardsToClaim;
    }

    function _processPNVFee(uint256 _rewardsToClaim, address _token, address _sender) internal {
        // Now that's over the minimum threshold, the fee can be calculated
        if (pegNobilityVaultFeeEnabled) {
            uint256 PNVFeeAmount = PNVFeeManager.getPNVFeeAmount(_rewardsToClaim, _token, pegNobilityVaultFee);
            require(PNVFeeAmount > 0, "Camelot: zero fee not allowed");
            if (_token == address(0)) { //S
                require(msg.value >= PNVFeeAmount, "Camelot: insufficient S sent to claim");

                // Transfer the fee to the PNVWallet
                (bool feeSuccess, ) = PNVWallet.call{value: PNVFeeAmount}("");
                require(feeSuccess, "Camelot: fee transfer failed");

                // Refund the excess S to the user
                uint256 refundAmount = msg.value - PNVFeeAmount;
                if (refundAmount > 0) {
                    (bool success, ) = _sender.call{value: refundAmount}("");
                    require(success, "Camelot: S refund failed");
                }
            } else {
                // Transfer the fee to the PNVWallet
                IERC20(_token).safeTransferFrom(_sender, PNVWallet, PNVFeeAmount);
            }
        }
    }

    function claim(uint256 _pid, address _token) public payable nonReentrant returns (uint256) {
        require(_pid < poolInfo.length, "Camelot: invalid pool id");
        require(
            (!pegNobilityVaultFeeEnabled && msg.value == 0) || // If the fee is not enabled, the user cannot send S to claim
            (pegNobilityVaultFeeEnabled && _token == address(0) && msg.value > 0) || // If the fee is enabled and fee paid in S, the user must send S to claim
            (pegNobilityVaultFeeEnabled && _token != address(0) && msg.value == 0), // If the fee is enabled and fee paid in ERC20 token, the user cannot send S to claim
            "Camelot: invalid S sent to claim"
        );
        address _sender = msg.sender;
        uint256 rewardsToClaim = _calculatePendingRewards(_pid, _sender);

        // Ensure that the user is claiming an amount above the minimum threshold
        require(rewardsToClaim >= minClaimThreshold, "Camelot: Claim amount below minimum threshold");

        // Now that's over the minimum threshold, the fee can be calculated
        _processPNVFee(rewardsToClaim, _token, _sender);

        // Transfer the rewards to the user
        safeKNIGHTTransfer(_sender, rewardsToClaim);
        emit RewardPaid(_sender, rewardsToClaim);
        return rewardsToClaim;
    }

    function claimAll(address _token) public payable nonReentrant {
        require(
            (!pegNobilityVaultFeeEnabled && msg.value == 0) || // If the fee is not enabled, the user cannot send S to claim
            (pegNobilityVaultFeeEnabled && _token == address(0) && msg.value > 0) || // If the fee is enabled and fee paid in S, the user must send S to claim
            (pegNobilityVaultFeeEnabled && _token != address(0) && msg.value == 0), // If the fee is enabled and fee paid in ERC20 token, the user cannot send S to claim
            "Camelot: invalid S sent to claim"
        );
        address _sender = msg.sender;
        uint256 _rewardsToClaim = 0;
        for (uint256 pid = 0; pid < poolInfo.length; ++pid) {
            _rewardsToClaim += _calculatePendingRewards(pid, _sender);
        }

        // Ensure that the user is claiming an amount above the minimum threshold
        require(_rewardsToClaim >= minClaimThreshold, "Camelot: Claim amount below minimum threshold");

        // Now that's over the minimum threshold, the fee can be calculated
        _processPNVFee(_rewardsToClaim, _token, _sender);

        // Transfer the rewards to the user
        safeKNIGHTTransfer(_sender, _rewardsToClaim);
        emit RewardPaid(_sender, _rewardsToClaim);
    }

    function compound(uint256 _pid, address _token) public payable nonReentrant { 
        require(_pid < poolInfo.length, "Camelot: invalid pool id");
        // This function requires helper to be set
        require(address(helper) != address(0), "Camelot: helper not set");
        // 1. claim the rewards
        uint256 rewardsToClaim = claim(_pid, _token);
        // 2. deposit the rewards to the pool
        deposit(_pid, rewardsToClaim, address(KNIGHT));

    }

    // Safe KNIGHT transfer function, just in case if rounding error causes pool to not have enough KNIGHT.
    function safeKNIGHTTransfer(address _to, uint256 _amount) internal {
        uint256 _KNIGHTBal = KNIGHT.balanceOf(address(this));

        if (_KNIGHTBal > 0) {
            if (_amount > _KNIGHTBal) {
                KNIGHT.safeTransfer(_to, _KNIGHTBal);
            } else {
                KNIGHT.safeTransfer(_to, _amount);
            }
        }
    }

    function setMinClaimThreshold(uint256 _minClaimThreshold) external onlyOperator {
        require(_minClaimThreshold >= 1e9, "Camelot: invalid min claim threshold");
        require(_minClaimThreshold <= 1e18, "Camelot: invalid max claim threshold");
        minClaimThreshold = _minClaimThreshold;
    }

    function setPegNobilityVaultFee(uint256 _pegNobilityVaultFee) external onlyOperator {
        require(_pegNobilityVaultFee <= 500, "Camelot: invalid peg nobility vault fee"); // max 50%
        pegNobilityVaultFee = _pegNobilityVaultFee;
    }

    function setPegNobilityVaultFeeEnabled(bool _pegNobilityVaultFeeEnabled) external onlyOperator {
        pegNobilityVaultFeeEnabled = _pegNobilityVaultFeeEnabled;
    }

    function setMultiSigWallet(address _multiSigWallet) external onlyOwner {
        require(_multiSigWallet != address(0), "Cannot set multiSigWallet to zero address");
        multiSigWallet = _multiSigWallet;
        emit MultiSigWalletUpdated(_multiSigWallet);
    }

    function setSPWxRewardsWallet(address _SPWxRewardsWallet) external onlyOwner {
        require(_SPWxRewardsWallet != address(0), "Camelot: invalid SPWxRewardsWallet");
        SPWxRewardsWallet = _SPWxRewardsWallet;
    }

    function setPNVWallet(address _PNVWallet) external onlyOwner {
        require(_PNVWallet != address(0), "Camelot: invalid PNVWallet");
        PNVWallet = _PNVWallet;
    }

    function setPNVFeeManager(IPNVFeeManager _PNVFeeManager) external onlyOwner {
        require(address(_PNVFeeManager) != address(0), "Camelot: invalid PNVFeeManager");
        PNVFeeManager = _PNVFeeManager;
    }

    function setHelper(IHelper _helper) external onlyOwner {
        // it can be set to address(0) if the helper is not to be used
        helper = _helper;
    }

    function governanceRecoverUnsupported(IERC20 _token, uint256 amount, address to) external onlyOwner {
        // KNIGHT can be claimed by the timelock in case of migration to a new contract
        // do not allow to drain LPs
        uint256 length = poolInfo.length;
        for (uint256 pid = 0; pid < length; ++pid) {
            PoolInfo storage pool = poolInfo[pid];
            require(_token != pool.token, "Camelot: token cannot be pool token");
        }
        _token.safeTransfer(to, amount);
    }

    function depositToGauge(uint256 _pid) internal {
        PoolInfo memory pool = poolInfo[_pid];
        uint256 balance = pool.token.balanceOf(address(this));
        // Do nothing if this pool doesn't have a gauge
        if (pool.gauge != address(0)) {
            // Do nothing if the LP token in the MC is empty
            if (balance > 0) {
                // Approve and deposit to the gauge
                pool.token.approve(pool.gauge, balance);
                ISwapxGauge(pool.gauge).deposit(balance);
                emit GaugeDeposit(_pid, balance, true);
            }
        }
    }

    function getRewardFromGauge(PoolInfo memory pool) internal {
        ISwapxGauge(pool.gauge).getReward();
        uint256 rewardAmount = SWPxToken.balanceOf(address(this));
        if (rewardAmount > 0) {
            SWPxToken.safeTransfer(SPWxRewardsWallet, rewardAmount);
        }
    }

    function withdrawFromGauge(uint256 _pid, uint256 _amount) internal {
        PoolInfo memory pool = poolInfo[_pid];
        // Do nothing if this pool doesn't have a gauge
        if (pool.gauge != address(0)) {
            // First claim the rewards and send to the SPWxRewardsWallet
            getRewardFromGauge(pool);
            // Withdraw from the gauge
            ISwapxGauge(pool.gauge).withdraw(_amount);
            emit GaugeWithdraw(_pid, _amount, true);
        }
    }

    function claimSWPxRewards() public onlyOperator {
        for (uint256 pid = 0; pid < poolInfo.length; ++pid) {
            PoolInfo memory pool = poolInfo[pid];
            if (pool.gauge != address(0)) {
                getRewardFromGauge(pool);
            }
        }
    }

    function emergencyWithdrawFromGauge(uint256 _pid) external onlyOperator {
        require(_pid < poolInfo.length, "Camelot: invalid pool id");
        PoolInfo memory pool = poolInfo[_pid];
        require(pool.gauge != address(0), "Camelot: pool has no gauge");
        
        uint256 balance = ISwapxGauge(pool.gauge).balanceOf(address(this));
        if (balance > 0) {
            // First claim any rewards
            getRewardFromGauge(pool);
            
            // Then withdraw everything
            ISwapxGauge(pool.gauge).withdraw(balance);
            
            // Emit an event
            emit EmergencyGaugeWithdraw(_pid, balance);
        }
        
        // Disable the gauge by setting it to the zero address
        set(_pid, pool.allocPoint, pool.withFee, address(0));
    }
}

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

interface IHelper {
    function helperConvert(address fromToken, address toToken, uint256 amount) external returns (uint256);
}

File 3 of 15 : IPNVFeeManager.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

interface IPNVFeeManager {
    function getPNVFeeAmount(uint256 _rewardsToClaim, address _paymentToken, uint256 _feePercentage) external view returns (uint256 feeAmount);
}

File 4 of 15 : ISwapXGauge.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

interface ISwapxGauge {
    function getReward() external;
    function deposit(uint256 amount) external;
    function withdraw(uint256 amount) external;
    function balanceOf(address _account) external view returns (uint);
}

File 5 of 15 : SafeMath.sol
// SPDX-License-Identifier: MIT


pragma solidity ^0.8.20;

library SafeMath {
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        return a + b;
    }

    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return a - b;
    }

    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        return a - b;
    }

    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        return a * b;
    }

    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return a / b;
    }

    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        return a / b;
    }
}

File 6 of 15 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;

import {Context} from "../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.
 *
 * The initial owner is set to the address provided by the deployer. 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;

    /**
     * @dev The caller account is not authorized to perform an operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @dev The owner is not a valid owner account. (eg. `address(0)`)
     */
    error OwnableInvalidOwner(address owner);

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

    /**
     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
     */
    constructor(address initialOwner) {
        if (initialOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(initialOwner);
    }

    /**
     * @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 {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling 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 {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _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 7 of 15 : IERC1363.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol)

pragma solidity ^0.8.20;

import {IERC20} from "./IERC20.sol";
import {IERC165} from "./IERC165.sol";

/**
 * @title IERC1363
 * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].
 *
 * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract
 * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.
 */
interface IERC1363 is IERC20, IERC165 {
    /*
     * Note: the ERC-165 identifier for this interface is 0xb0202a11.
     * 0xb0202a11 ===
     *   bytes4(keccak256('transferAndCall(address,uint256)')) ^
     *   bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^
     *   bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^
     *   bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^
     *   bytes4(keccak256('approveAndCall(address,uint256)')) ^
     *   bytes4(keccak256('approveAndCall(address,uint256,bytes)'))
     */

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferAndCall(address to, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @param data Additional data with no specified format, sent in call to `to`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param from The address which you want to send tokens from.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferFromAndCall(address from, address to, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param from The address which you want to send tokens from.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @param data Additional data with no specified format, sent in call to `to`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
     * @param spender The address which will spend the funds.
     * @param value The amount of tokens to be spent.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function approveAndCall(address spender, uint256 value) external returns (bool);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
     * @param spender The address which will spend the funds.
     * @param value The amount of tokens to be spent.
     * @param data Additional data with no specified format, sent in call to `spender`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);
}

File 8 of 15 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)

pragma solidity ^0.8.20;

import {IERC165} from "../utils/introspection/IERC165.sol";

File 9 of 15 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../token/ERC20/IERC20.sol";

File 10 of 15 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-20 standard as defined in the ERC.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

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

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

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

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

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

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

File 11 of 15 : SafeERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.2.0) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../IERC20.sol";
import {IERC1363} from "../../../interfaces/IERC1363.sol";

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

    /**
     * @dev Indicates a failed `decreaseAllowance` request.
     */
    error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);

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

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

    /**
     * @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.
     */
    function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {
        return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value)));
    }

    /**
     * @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.
     */
    function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {
        return _callOptionalReturnBool(token, abi.encodeCall(token.transferFrom, (from, to, value)));
    }

    /**
     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     *
     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
     * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
     */
    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 oldAllowance = token.allowance(address(this), spender);
        forceApprove(token, spender, oldAllowance + value);
    }

    /**
     * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
     * value, non-reverting calls are assumed to be successful.
     *
     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
     * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
     */
    function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
        unchecked {
            uint256 currentAllowance = token.allowance(address(this), spender);
            if (currentAllowance < requestedDecrease) {
                revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
            }
            forceApprove(token, spender, currentAllowance - requestedDecrease);
        }
    }

    /**
     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
     * to be set to zero before setting it to a non-zero value, such as USDT.
     *
     * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function
     * only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being
     * set here.
     */
    function forceApprove(IERC20 token, address spender, uint256 value) internal {
        bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));

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

    /**
     * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no
     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
     * targeting contracts.
     *
     * Reverts if the returned value is other than `true`.
     */
    function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
        if (to.code.length == 0) {
            safeTransfer(token, to, value);
        } else if (!token.transferAndCall(to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target
     * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
     * targeting contracts.
     *
     * Reverts if the returned value is other than `true`.
     */
    function transferFromAndCallRelaxed(
        IERC1363 token,
        address from,
        address to,
        uint256 value,
        bytes memory data
    ) internal {
        if (to.code.length == 0) {
            safeTransferFrom(token, from, to, value);
        } else if (!token.transferFromAndCall(from, to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no
     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
     * targeting contracts.
     *
     * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.
     * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}
     * once without retrying, and relies on the returned value to be true.
     *
     * Reverts if the returned value is other than `true`.
     */
    function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
        if (to.code.length == 0) {
            forceApprove(token, to, value);
        } else if (!token.approveAndCall(to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     *
     * This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        uint256 returnSize;
        uint256 returnValue;
        assembly ("memory-safe") {
            let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
            // bubble errors
            if iszero(success) {
                let ptr := mload(0x40)
                returndatacopy(ptr, 0, returndatasize())
                revert(ptr, returndatasize())
            }
            returnSize := returndatasize()
            returnValue := mload(0)
        }

        if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     *
     * This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.
     */
    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
        bool success;
        uint256 returnSize;
        uint256 returnValue;
        assembly ("memory-safe") {
            success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
            returnSize := returndatasize()
            returnValue := mload(0)
        }
        return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);
    }
}

File 12 of 15 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

/**
 * @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;
    }

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

File 13 of 15 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol)

pragma solidity ^0.8.20;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at,
 * consider using {ReentrancyGuardTransient} instead.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant NOT_ENTERED = 1;
    uint256 private constant ENTERED = 2;

    uint256 private _status;

    /**
     * @dev Unauthorized reentrant call.
     */
    error ReentrancyGuardReentrantCall();

    constructor() {
        _status = NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be NOT_ENTERED
        if (_status == ENTERED) {
            revert ReentrancyGuardReentrantCall();
        }

        // Any calls to nonReentrant after this point will fail
        _status = ENTERED;
    }

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = NOT_ENTERED;
    }

    /**
     * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
     * `nonReentrant` function in the call stack.
     */
    function _reentrancyGuardEntered() internal view returns (bool) {
        return _status == ENTERED;
    }
}

File 14 of 15 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[ERC].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

File 15 of 15 : Operator.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

import "@openzeppelin/contracts/access/Ownable.sol";

contract Operator is Ownable {
    address private _operator;

    event OperatorTransferred(address indexed previousOperator, address indexed newOperator);

    constructor() Ownable(msg.sender)
    {
        _operator = msg.sender;
        emit OperatorTransferred(address(0), _operator);
    }

    function operator() public view returns (address) {
        return _operator;
    }

    modifier onlyOperator() {
        require(_operator == msg.sender, "operator: caller is not the operator");
        _;
    }

    function transferOperator(address newOperator_) public onlyOwner {
        _transferOperator(newOperator_);
    }

    function _transferOperator(address newOperator_) internal {
        require(newOperator_ != address(0), "operator: zero address given for new operator");
        emit OperatorTransferred(_operator, newOperator_);
        _operator = newOperator_;
    }

    function renounceOwnership() public view override onlyOwner {
        revert("Operator must always have an owner");
    }
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "viaIR": false,
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "remappings": [
    "@=node_modules/@"
  ],
  "evmVersion": "paris"
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_KNIGHT","type":"address"},{"internalType":"address","name":"_multiSigWallet","type":"address"},{"internalType":"address","name":"_SPWxRewardsWallet","type":"address"},{"internalType":"address","name":"_PNVWallet","type":"address"},{"internalType":"contract IPNVFeeManager","name":"_PNVFeeManager","type":"address"},{"internalType":"uint256","name":"_poolStartTime","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"EmergencyGaugeWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"EmergencyWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bool","name":"success","type":"bool"}],"name":"GaugeDeposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bool","name":"success","type":"bool"}],"name":"GaugeWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"multiSigWallet","type":"address"}],"name":"MultiSigWalletUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOperator","type":"address"},{"indexed":true,"internalType":"address","name":"newOperator","type":"address"}],"name":"OperatorTransferred","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":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RewardPaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"KNIGHT","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PNVFeeManager","outputs":[{"internalType":"contract IPNVFeeManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PNVWallet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SPWxRewardsWallet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SWPxToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_allocPoint","type":"uint256"},{"internalType":"uint256","name":"_withFee","type":"uint256"},{"internalType":"contract IERC20","name":"_token","type":"address"},{"internalType":"bool","name":"_withUpdate","type":"bool"},{"internalType":"uint256","name":"_lastRewardTime","type":"uint256"},{"internalType":"address","name":"_gauge","type":"address"}],"name":"add","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_allocPoints","type":"uint256[]"},{"internalType":"uint256[]","name":"_withFee","type":"uint256[]"},{"internalType":"contract IERC20[]","name":"_tokens","type":"address[]"},{"internalType":"bool","name":"_withUpdate","type":"bool"},{"internalType":"uint256","name":"_lastRewardTime","type":"uint256"},{"internalType":"address[]","name":"_gauge","type":"address[]"}],"name":"addBulk","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_pids","type":"uint256[]"},{"internalType":"uint256[]","name":"_allocPoints","type":"uint256[]"},{"internalType":"uint256[]","name":"_withFees","type":"uint256[]"},{"internalType":"address[]","name":"_gauges","type":"address[]"}],"name":"bulkSet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"address","name":"_token","type":"address"}],"name":"claim","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"claimAll","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"claimSWPxRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"address","name":"_token","type":"address"}],"name":"compound","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_token","type":"address"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"emergencyWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"emergencyWithdrawFromGauge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"address","name":"_token","type":"address"}],"name":"getAllPNVFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fromTime","type":"uint256"},{"internalType":"uint256","name":"_toTime","type":"uint256"}],"name":"getGeneratedReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"address","name":"_user","type":"address"},{"internalType":"address","name":"_token","type":"address"}],"name":"getPNVFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"_token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"governanceRecoverUnsupported","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"helper","outputs":[{"internalType":"contract IHelper","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"massUpdatePools","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"minClaimThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"multiSigWallet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"operator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pegNobilityVaultFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pegNobilityVaultFeeEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"pendingRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"address","name":"_user","type":"address"}],"name":"pendingShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"address","name":"_user","type":"address"}],"name":"pendingTotalRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolEndTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"poolInfo","outputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"uint256","name":"withFee","type":"uint256"},{"internalType":"uint256","name":"allocPoint","type":"uint256"},{"internalType":"uint256","name":"lastRewardTime","type":"uint256"},{"internalType":"uint256","name":"accKNIGHTPerShare","type":"uint256"},{"internalType":"bool","name":"isStarted","type":"bool"},{"internalType":"address","name":"gauge","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolStartTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[],"name":"runningTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256","name":"_allocPoint","type":"uint256"},{"internalType":"uint256","name":"_withFee","type":"uint256"},{"internalType":"address","name":"_gauge","type":"address"}],"name":"set","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IHelper","name":"_helper","type":"address"}],"name":"setHelper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minClaimThreshold","type":"uint256"}],"name":"setMinClaimThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_multiSigWallet","type":"address"}],"name":"setMultiSigWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IPNVFeeManager","name":"_PNVFeeManager","type":"address"}],"name":"setPNVFeeManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_PNVWallet","type":"address"}],"name":"setPNVWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pegNobilityVaultFee","type":"uint256"}],"name":"setPegNobilityVaultFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_pegNobilityVaultFeeEnabled","type":"bool"}],"name":"setPegNobilityVaultFeeEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_SPWxRewardsWallet","type":"address"}],"name":"setSPWxRewardsWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalAllocPoint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOperator_","type":"address"}],"name":"transferOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"updatePool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"userInfo","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"rewardDebt","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6080604052600480546001600160a01b03191673a04bc7140c26fc9bb1f36b1a604c7a5a88fb0e701790556301e1338060105564e8d4a5100060115560c86012556013805460ff191660011790553480156200005a57600080fd5b50604051620040a5380380620040a58339810160408190526200007d91620002b0565b3380620000a557604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b620000b08162000247565b50600180546001600160a01b031916339081179091556040516000907f74da04524d50c64947f5dd5381ef1a4dca5cba8ed1d816243f9e48aa0b5617ed908290a36001600255428111620001475760405162461bcd60e51b815260206004820181905260248201527f706f6f6c2063616e74206265207374617274656420696e20746865207061737460448201526064016200009c565b6001600160a01b038616156200017357600380546001600160a01b0319166001600160a01b0388161790555b6001600160a01b038516156200019f57600780546001600160a01b0319166001600160a01b0387161790555b6001600160a01b03841615620001cb57600880546001600160a01b0319166001600160a01b0386161790555b6001600160a01b03831615620001f757600980546001600160a01b0319166001600160a01b0385161790555b6001600160a01b038216156200022357600580546001600160a01b0319166001600160a01b0384161790555b600e81905560105462000237908262000338565b600f555062000360945050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b0381168114620002ad57600080fd5b50565b60008060008060008060c08789031215620002ca57600080fd5b8651620002d78162000297565b6020880151909650620002ea8162000297565b6040880151909550620002fd8162000297565b6060880151909450620003108162000297565b6080880151909350620003238162000297565b8092505060a087015190509295509295509295565b808201808211156200035a57634e487b7160e01b600052601160045260246000fd5b92915050565b613d3580620003706000396000f3fe6080604052600436106102e45760003560e01c80636e271dd51161019057806399c52d37116100dc578063d846612111610095578063f03b0c0b1161006f578063f03b0c0b146108f8578063f2fde38b14610918578063f8e1dd4014610938578063fb3df6791461095857600080fd5b8063d8466121146108b2578063d8d36db8146108c5578063ddd5e1b2146108e557600080fd5b806399c52d37146107e4578063ac7d600214610804578063cc29b02014610824578063cf4b55cb1461083a578063d18df53c1461085a578063d1cc19011461089257600080fd5b806384061161116101495780638dbdbe6d116101235780638dbdbe6d1461073a57806393f1a40b1461075a578063943f013d146107ae578063986ccc7f146107c457600080fd5b806384061161146106dc57806388840c55146106fc5780638da5cb5b1461071c57600080fd5b80636e271dd51461063e578063715018a61461065457806373bf51dd1461066957806377329f3514610689578063798cfe7b1461069c5780637b27779f146106bc57600080fd5b8063441a3e701161024f5780635312ea8e1161020857806359e60951116101e257806359e60951146105d35780635f96dc11146105f3578063630b5ba11461060957806363b0e66a1461061e57600080fd5b80635312ea8e1461057557806354575af414610595578063570ca735146105b557600080fd5b8063441a3e701461049d578063461059ff146104bd5780634b8feb4f146104dd5780634d134d791461051557806351637ba91461053557806351eb05a61461055557600080fd5b8063231f0c6a116102a1578063231f0c6a146103f257806329605e77146104125780632e1c3d95146104325780633695dad1146104525780633da5375b1461046857806340e6c0e11461047d57600080fd5b8063033b258b146102e9578063051ba3511461030b578063081e3eda1461032b57806309275e891461034f5780631526fe271461037957806317caf6f1146103dc575b600080fd5b3480156102f557600080fd5b50610309610304366004613714565b610978565b005b34801561031757600080fd5b50610309610326366004613742565b610bdb565b34801561033757600080fd5b50600a545b6040519081526020015b60405180910390f35b34801561035b57600080fd5b506013546103699060ff1681565b6040519015158152602001610346565b34801561038557600080fd5b50610399610394366004613714565b610d13565b604080516001600160a01b039889168152602081019790975286019490945260608501929092526080840152151560a083015290911660c082015260e001610346565b3480156103e857600080fd5b5061033c600d5481565b3480156103fe57600080fd5b5061033c61040d366004613783565b610d71565b34801561041e57600080fd5b5061030961042d3660046137a5565b610e36565b34801561043e57600080fd5b5061030961044d36600461380e565b610e4a565b34801561045e57600080fd5b5061033c60115481565b34801561047457600080fd5b50610309610f70565b34801561048957600080fd5b5061033c6104983660046138d2565b611054565b3480156104a957600080fd5b506103096104b8366004613783565b611117565b3480156104c957600080fd5b506103096104d8366004613929565b611395565b3480156104e957600080fd5b506007546104fd906001600160a01b031681565b6040516001600160a01b039091168152602001610346565b34801561052157600080fd5b506103096105303660046137a5565b6114cd565b34801561054157600080fd5b50610309610550366004613714565b611558565b34801561056157600080fd5b50610309610570366004613714565b61164b565b34801561058157600080fd5b50610309610590366004613714565b611853565b3480156105a157600080fd5b506103096105b0366004613a0d565b611997565b3480156105c157600080fd5b506001546001600160a01b03166104fd565b3480156105df57600080fd5b506103096105ee366004613714565b611a6a565b3480156105ff57600080fd5b5061033c600e5481565b34801561061557600080fd5b50610309611afb565b34801561062a57600080fd5b506006546104fd906001600160a01b031681565b34801561064a57600080fd5b5061033c600f5481565b34801561066057600080fd5b50610309611b22565b34801561067557600080fd5b506103096106843660046137a5565b611b7d565b6103096106973660046137a5565b611bfd565b3480156106a857600080fd5b506009546104fd906001600160a01b031681565b3480156106c857600080fd5b5061033c6106d7366004613a4f565b611d73565b3480156106e857600080fd5b506103096106f7366004613a74565b611ddc565b34801561070857600080fd5b506008546104fd906001600160a01b031681565b34801561072857600080fd5b506000546001600160a01b03166104fd565b34801561074657600080fd5b50610309610755366004613a91565b611e19565b34801561076657600080fd5b50610799610775366004613a4f565b600b6020908152600092835260408084209091529082529020805460019091015482565b60408051928352602083019190915201610346565b3480156107ba57600080fd5b5061033c60105481565b3480156107d057600080fd5b506103096107df3660046137a5565b6121cd565b3480156107f057600080fd5b506103096107ff3660046137a5565b6121f7565b34801561081057600080fd5b5061030961081f366004613abf565b612277565b34801561083057600080fd5b5061033c60125481565b34801561084657600080fd5b5061033c610855366004613a4f565b612501565b34801561086657600080fd5b5061033c610875366004613a4f565b600c60209081526000928352604080842090915290825290205481565b34801561089e57600080fd5b506004546104fd906001600160a01b031681565b6103096108c0366004613a4f565b61270c565b3480156108d157600080fd5b506005546104fd906001600160a01b031681565b61033c6108f3366004613a4f565b6127c0565b34801561090457600080fd5b506103096109133660046137a5565b612933565b34801561092457600080fd5b506103096109333660046137a5565b6129f7565b34801561094457600080fd5b506003546104fd906001600160a01b031681565b34801561096457600080fd5b5061033c610973366004613b26565b612a32565b6001546001600160a01b031633146109ab5760405162461bcd60e51b81526004016109a290613b5d565b60405180910390fd5b600a5481106109cc5760405162461bcd60e51b81526004016109a290613ba1565b6000600a82815481106109e1576109e1613bd8565b60009182526020918290206040805160e081018252600690930290910180546001600160a01b03908116845260018201549484019490945260028101549183019190915260038101546060830152600481015460808301526005015460ff8116151560a0830152610100900490911660c08201819052909150610aa65760405162461bcd60e51b815260206004820152601a60248201527f43616d656c6f743a20706f6f6c20686173206e6f20676175676500000000000060448201526064016109a2565b60c08101516040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015610af1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b159190613bee565b90508015610bc157610b2682612af1565b60c0820151604051632e1a7d4d60e01b8152600481018390526001600160a01b0390911690632e1a7d4d90602401600060405180830381600087803b158015610b6e57600080fd5b505af1158015610b82573d6000803e3d6000fd5b50505050827f075ba0b9dfded837b057a0fe9dec5063b4b475e8a60b3800e30d7fe7859f6a7382604051610bb891815260200190565b60405180910390a25b610bd683836040015184602001516000610bdb565b505050565b6001546001600160a01b03163314610c055760405162461bcd60e51b81526004016109a290613b5d565b610c0d611afb565b6000600a8581548110610c2257610c22613bd8565b906000526020600020906006020190506032831115610c8f5760405162461bcd60e51b815260206004820152602360248201527f7769746864726177206665652063616e74206265206d6f7265207468616e20306044820152622e352560e81b60648201526084016109a2565b60018101839055600581015460ff1615610cca57610cc684610cc08360020154600d54612bdd90919063ffffffff16565b90612bf0565b600d555b60028101849055600581018054610100600160a81b0319166101006001600160a01b03858116820292909217928390559091041615610d0c57610d0c85612bfc565b5050505050565b600a8181548110610d2357600080fd5b60009182526020909120600690910201805460018201546002830154600384015460048501546005909501546001600160a01b03948516965092949193909260ff8116916101009091041687565b6000818310610d8257506000610e30565b600f548210610dea57600f548310610d9c57506000610e30565b600e548311610dcf57610dc8600d54610dc2600e54600f54612bdd90919063ffffffff16565b90612e1e565b9050610e30565b610dc8600d54610dc285600f54612bdd90919063ffffffff16565b600e548211610dfb57506000610e30565b600e548311610e1f57610dc8600d54610dc2600e5485612bdd90919063ffffffff16565b600d54610dc890610dc28486612bdd565b92915050565b610e3e612e2a565b610e4781612e59565b50565b6001546001600160a01b03163314610e745760405162461bcd60e51b81526004016109a290613b5d565b8685148015610e8257508683145b8015610e8d57508681145b610ed35760405162461bcd60e51b8152602060048201526017602482015276086c2dacad8dee87440d2dcecc2d8d2c840d8cadccee8d604b1b60448201526064016109a2565b60005b87811015610f6557610f53898983818110610ef357610ef3613bd8565b90506020020135888884818110610f0c57610f0c613bd8565b90506020020135878785818110610f2557610f25613bd8565b90506020020135868686818110610f3e57610f3e613bd8565b905060200201602081019061032691906137a5565b80610f5d81613c1d565b915050610ed6565b505050505050505050565b6001546001600160a01b03163314610f9a5760405162461bcd60e51b81526004016109a290613b5d565b60005b600a54811015610e47576000600a8281548110610fbc57610fbc613bd8565b60009182526020918290206040805160e081018252600690930290910180546001600160a01b03908116845260018201549484019490945260028101549183019190915260038101546060830152600481015460808301526005015460ff8116151560a0830152610100900490911660c08201819052909150156110435761104381612af1565b5061104d81613c1d565b9050610f9d565b600080805b600a548110156110895761106d8186611d73565b6110779083613c36565b915061108281613c1d565b9050611059565b5060055460125460405163ac6fdaad60e01b8152600481018490526001600160a01b0386811660248301526044820192909252600092919091169063ac6fdaad90606401602060405180830381865afa1580156110ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061110e9190613bee565b95945050505050565b61111f612f21565b600a5482106111405760405162461bcd60e51b81526004016109a290613ba1565b60003390506000600a848154811061115a5761115a613bd8565b60009182526020808320878452600b825260408085206001600160a01b038816865290925292208054600690920290920192508411156111f95760405162461bcd60e51b815260206004820152603460248201527f43616d656c6f743a207573657220646f6573206e6f74206861766520656e6f7560448201527319da0818985b185b98d94819195c1bdcda5d195960621b60648201526084016109a2565b6112028561164b565b600061123f8260010154611239670de0b6b3a764000061123387600401548760000154612e1e90919063ffffffff16565b90612f49565b90612bdd565b90508015611298576000868152600c602090815260408083206001600160a01b03881684529091529020546112749082612bf0565b6000878152600c602090815260408083206001600160a01b03891684529091529020555b84156113205781546112aa9086612bdd565b82556112b68686612f55565b60006112d5612710611233866001015489612e1e90919063ffffffff16565b905060006112e38783612bdd565b90508115611307576007548554611307916001600160a01b03918216911684613089565b845461131d906001600160a01b03168783613089565b50505b6004830154825461133e91670de0b6b3a76400009161123391612e1e565b600183015560405185815286906001600160a01b038616907ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b5689060200160405180910390a3505050506113916001600255565b5050565b6001546001600160a01b031633146113bf5760405162461bcd60e51b81526004016109a290613b5d565b88871480156113cd57508885145b80156113d857508881145b61141e5760405162461bcd60e51b8152602060048201526017602482015276086c2dacad8dee87440d2dcecc2d8d2c840d8cadccee8d604b1b60448201526064016109a2565b60005b898110156114c0576114ae8b8b8381811061143e5761143e613bd8565b905060200201358a8a8481811061145757611457613bd8565b9050602002013589898581811061147057611470613bd8565b905060200201602081019061148591906137a5565b888888888881811061149957611499613bd8565b905060200201602081019061081f91906137a5565b806114b881613c1d565b915050611421565b5050505050505050505050565b6114d5612e2a565b6001600160a01b0381166115365760405162461bcd60e51b815260206004820152602260248201527f43616d656c6f743a20696e76616c696420535057785265776172647357616c6c604482015261195d60f21b60648201526084016109a2565b600880546001600160a01b0319166001600160a01b0392909216919091179055565b6001546001600160a01b031633146115825760405162461bcd60e51b81526004016109a290613b5d565b633b9aca008110156115e25760405162461bcd60e51b8152602060048201526024808201527f43616d656c6f743a20696e76616c6964206d696e20636c61696d2074687265736044820152631a1bdb1960e21b60648201526084016109a2565b670de0b6b3a76400008111156116465760405162461bcd60e51b8152602060048201526024808201527f43616d656c6f743a20696e76616c6964206d617820636c61696d2074687265736044820152631a1bdb1960e21b60648201526084016109a2565b601155565b600a54811061166c5760405162461bcd60e51b81526004016109a290613ba1565b6000600a828154811061168157611681613bd8565b90600052602060002090600602019050806003015442116116a0575050565b600581015460009061010090046001600160a01b031661172a5781546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015611701573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117259190613bee565b61179c565b60058201546040516370a0823160e01b81523060048201526101009091046001600160a01b0316906370a0823190602401602060405180830381865afa158015611778573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061179c9190613bee565b9050806000036117b157504260039091015550565b600582015460ff166117e15760058201805460ff191660011790556002820154600d546117dd91612bf0565b600d555b600d54156118485760006117f9836003015442610d71565b9050600061181a600d54611233866002015485612e1e90919063ffffffff16565b90506118406118358461123384670de0b6b3a7640000612e1e565b600486015490612bf0565b600485015550505b504260039091015550565b61185b612f21565b600a54811061187c5760405162461bcd60e51b81526004016109a290613ba1565b6000600a828154811061189157611891613bd8565b60009182526020808320858452600b8252604080852033808752908452818620805487825560018201889055898852600c8652838820928852919094529085209490945560069092029091019250906118ea8482612f55565b6000611909612710611233866001015485612e1e90919063ffffffff16565b905060006119178383612bdd565b9050811561193b57600754855461193b916001600160a01b03918216911684613089565b8454611951906001600160a01b03163383613089565b604051838152869033907fbb757047c2b5f3974fe26b7c10f732e7bce710b0952a71082702781e62ae05959060200160405180910390a35050505050610e476001600255565b61199f612e2a565b600a5460005b81811015611a4f576000600a82815481106119c2576119c2613bd8565b6000918252602090912060069091020180549091506001600160a01b0390811690871603611a3e5760405162461bcd60e51b815260206004820152602360248201527f43616d656c6f743a20746f6b656e2063616e6e6f7420626520706f6f6c20746f60448201526235b2b760e91b60648201526084016109a2565b50611a4881613c1d565b90506119a5565b50611a646001600160a01b0385168385613089565b50505050565b6001546001600160a01b03163314611a945760405162461bcd60e51b81526004016109a290613b5d565b6101f4811115611af65760405162461bcd60e51b815260206004820152602760248201527f43616d656c6f743a20696e76616c696420706567206e6f62696c697479207661604482015266756c742066656560c81b60648201526084016109a2565b601255565b600a5460005b8181101561139157611b128161164b565b611b1b81613c1d565b9050611b01565b611b2a612e2a565b60405162461bcd60e51b815260206004820152602260248201527f4f70657261746f72206d75737420616c77617973206861766520616e206f776e60448201526132b960f11b60648201526084016109a2565b611b85612e2a565b6001600160a01b038116611bdb5760405162461bcd60e51b815260206004820152601a60248201527f43616d656c6f743a20696e76616c696420504e5657616c6c657400000000000060448201526064016109a2565b600980546001600160a01b0319166001600160a01b0392909216919091179055565b611c05612f21565b60135460ff16158015611c16575034155b80611c41575060135460ff168015611c3557506001600160a01b038116155b8015611c415750600034115b80611c6b575060135460ff168015611c6157506001600160a01b03811615155b8015611c6b575034155b611cb75760405162461bcd60e51b815260206004820181905260248201527f43616d656c6f743a20696e76616c696420532073656e7420746f20636c61696d60448201526064016109a2565b336000805b600a54811015611cec57611cd081846130e8565b611cda9083613c36565b9150611ce581613c1d565b9050611cbc565b50601154811015611d0f5760405162461bcd60e51b81526004016109a290613c49565b611d1a818484613201565b611d2482826134cd565b816001600160a01b03167fe2403640ba68fed3a2f88b7557551d1993f84b99bb10ff833f0cf8db0c5e048682604051611d5f91815260200190565b60405180910390a25050610e476001600255565b600a546000908310611d975760405162461bcd60e51b81526004016109a290613ba1565b6000611da38484612501565b6000858152600c602090815260408083206001600160a01b0388168452909152902054909150611dd4908290612bf0565b949350505050565b6001546001600160a01b03163314611e065760405162461bcd60e51b81526004016109a290613b5d565b6013805460ff1916911515919091179055565b611e21612f21565b600a548310611e425760405162461bcd60e51b81526004016109a290613ba1565b60003390506000600a8581548110611e5c57611e5c613bd8565b60009182526020808320888452600b825260408085206001600160a01b0380891687529352909320600690920290920192509084161580611ea757506006546001600160a01b031615155b611eec5760405162461bcd60e51b815260206004820152601660248201527521b0b6b2b637ba1d1034b73b30b634b2103a37b5b2b760511b60448201526064016109a2565b611ef58661164b565b805415611f88576000611f2d8260010154611239670de0b6b3a764000061123387600401548760000154612e1e90919063ffffffff16565b90508015611f86576000878152600c602090815260408083206001600160a01b0388168452909152902054611f629082612bf0565b6000888152600c602090815260408083206001600160a01b03891684529091529020555b505b841561215d576001600160a01b038416611fc6578154611fb3906001600160a01b0316843088613578565b8054611fbf9086612bf0565b8155612154565b83611fdc6001600160a01b038216853089613578565b60065460405163095ea7b360e01b81526001600160a01b039182166004820152602481018890529082169063095ea7b3906044016020604051808303816000875af115801561202f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120539190613c96565b506006548354604051636214c24f60e11b81526001600160a01b038881166004830152918216602482015260448101899052600092919091169063c429849e906064016020604051808303816000875af11580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190613bee565b9050600081116121435760405162461bcd60e51b815260206004820152602f60248201527f43616d656c6f743a2068656c70657220636f6e76657273696f6e20726574757260448201526e1b9959081e995c9bc8185b5bdd5b9d608a1b60648201526084016109a2565b825461214f9082612bf0565b835550505b61215d86612bfc565b6004820154815461217b91670de0b6b3a76400009161123391612e1e565b600182015560405185815286906001600160a01b038516907f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159060200160405180910390a3505050610bd66001600255565b6121d5612e2a565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b6121ff612e2a565b6001600160a01b0381166122555760405162461bcd60e51b815260206004820152601e60248201527f43616d656c6f743a20696e76616c696420504e564665654d616e61676572000060448201526064016109a2565b600580546001600160a01b0319166001600160a01b0392909216919091179055565b6001546001600160a01b031633146122a15760405162461bcd60e51b81526004016109a290613b5d565b60328511156123075760405162461bcd60e51b815260206004820152602c60248201527f43616d656c6f743a207769746864726177206665652063616e74206265206d6f60448201526b7265207468616e20302e352560a01b60648201526084016109a2565b612310846135b1565b821561231e5761231e611afb565b600e5442101561233d57600e5482101561233857600e5491505b612349565b42821015612349574291505b6000600e548311158061235c5750428311155b6040805160e0810182526001600160a01b038881168252602082018a81529282018b8152606083018881526000608085018181528715801560a088019081528b871660c08901908152600a8054600181018255955297517fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a8600690950294850180546001600160a01b03191691891691909117905597517fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a984015593517fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2aa83015591517fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2ab82015590517fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2ac82015593517fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2ad909401805493516001600160a81b0319909416941515610100600160a81b031916949094176101009390921692909202179091559091506124f857600d546124f49088612bf0565b600d555b50505050505050565b600a5460009083106125255760405162461bcd60e51b81526004016109a290613ba1565b6000600a848154811061253a5761253a613bd8565b60009182526020808320878452600b825260408085206001600160a01b038981168752935284206006939093020160048101546005820154919550929391610100909104166125f35783546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa1580156125ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125ee9190613bee565b612665565b60058401546040516370a0823160e01b81523060048201526101009091046001600160a01b0316906370a0823190602401602060405180830381865afa158015612641573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126659190613bee565b905083600301544211801561267957508015155b156126d657600061268e856003015442610d71565b905060006126af600d54611233886002015485612e1e90919063ffffffff16565b90506126d16126ca8461123384670de0b6b3a7640000612e1e565b8590612bf0565b935050505b6127018360010154611239670de0b6b3a7640000611233868860000154612e1e90919063ffffffff16565b979650505050505050565b612714612f21565b600a5482106127355760405162461bcd60e51b81526004016109a290613ba1565b6006546001600160a01b031661278d5760405162461bcd60e51b815260206004820152601760248201527f43616d656c6f743a2068656c706572206e6f742073657400000000000000000060448201526064016109a2565b600061279983836127c0565b6003549091506127b590849083906001600160a01b0316611e19565b506113916001600255565b60006127ca612f21565b600a5483106127eb5760405162461bcd60e51b81526004016109a290613ba1565b60135460ff161580156127fc575034155b80612827575060135460ff16801561281b57506001600160a01b038216155b80156128275750600034115b80612851575060135460ff16801561284757506001600160a01b03821615155b8015612851575034155b61289d5760405162461bcd60e51b815260206004820181905260248201527f43616d656c6f743a20696e76616c696420532073656e7420746f20636c61696d60448201526064016109a2565b3360006128aa85836130e8565b90506011548110156128ce5760405162461bcd60e51b81526004016109a290613c49565b6128d9818584613201565b6128e382826134cd565b816001600160a01b03167fe2403640ba68fed3a2f88b7557551d1993f84b99bb10ff833f0cf8db0c5e04868260405161291e91815260200190565b60405180910390a2915050610e306001600255565b61293b612e2a565b6001600160a01b0381166129a35760405162461bcd60e51b815260206004820152602960248201527f43616e6e6f7420736574206d756c746953696757616c6c657420746f207a65726044820152686f206164647265737360b81b60648201526084016109a2565b600780546001600160a01b0319166001600160a01b0383169081179091556040519081527fb47ff16b5bae9457ad1554c677eb38ef82abc443a3e3f78c8bce69830b1b64a19060200160405180910390a150565b6129ff612e2a565b6001600160a01b038116612a2957604051631e4fbdf760e01b8152600060048201526024016109a2565b610e4781613653565b600a546000908410612a565760405162461bcd60e51b81526004016109a290613ba1565b6000612a628585611d73565b60055460125460405163ac6fdaad60e01b8152600481018490526001600160a01b038781166024830152604482019290925292935060009291169063ac6fdaad90606401602060405180830381865afa158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613bee565b9695505050505050565b8060c001516001600160a01b0316633d18b9126040518163ffffffff1660e01b8152600401600060405180830381600087803b158015612b3057600080fd5b505af1158015612b44573d6000803e3d6000fd5b5050600480546040516370a0823160e01b81523092810192909252600093506001600160a01b031691506370a0823190602401602060405180830381865afa158015612b94573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bb89190613bee565b9050801561139157600854600454611391916001600160a01b03918216911683613089565b6000612be98284613cb3565b9392505050565b6000612be98284613c36565b6000600a8281548110612c1157612c11613bd8565b600091825260208083206040805160e08101825260069490940290910180546001600160a01b0390811680865260018301549486019490945260028201548584015260038201546060860152600480830154608087015260059092015460ff8116151560a087015261010090041660c085015290516370a0823160e01b81523091810191909152919350906370a0823190602401602060405180830381865afa158015612cc2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ce69190613bee565b60c08301519091506001600160a01b031615610bd6578015610bd657815160c083015160405163095ea7b360e01b81526001600160a01b0391821660048201526024810184905291169063095ea7b3906044016020604051808303816000875af1158015612d58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d7c9190613c96565b5060c082015160405163b6b55f2560e01b8152600481018390526001600160a01b039091169063b6b55f2590602401600060405180830381600087803b158015612dc557600080fd5b505af1158015612dd9573d6000803e3d6000fd5b505060408051848152600160208201528693507f71d77cd09e03d2887b1690010000325aa3412e58ca5d49c09bbfe50e13beff779250015b60405180910390a2505050565b6000612be98284613cc6565b6000546001600160a01b03163314612e575760405163118cdaa760e01b81523360048201526024016109a2565b565b6001600160a01b038116612ec55760405162461bcd60e51b815260206004820152602d60248201527f6f70657261746f723a207a65726f206164647265737320676976656e20666f7260448201526c103732bb9037b832b930ba37b960991b60648201526084016109a2565b6001546040516001600160a01b038084169216907f74da04524d50c64947f5dd5381ef1a4dca5cba8ed1d816243f9e48aa0b5617ed90600090a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b6002805403612f4357604051633ee5aeb560e01b815260040160405180910390fd5b60028055565b6000612be98284613cdd565b6000600a8381548110612f6a57612f6a613bd8565b60009182526020918290206040805160e081018252600690930290910180546001600160a01b03908116845260018201549484019490945260028101549183019190915260038101546060830152600481015460808301526005015460ff8116151560a0830152610100900490911660c0820181905290915015610bd657612ff181612af1565b60c0810151604051632e1a7d4d60e01b8152600481018490526001600160a01b0390911690632e1a7d4d90602401600060405180830381600087803b15801561303957600080fd5b505af115801561304d573d6000803e3d6000fd5b505060408051858152600160208201528693507fb7d10c4af8b2c06f54a97ae225c7e59df848cc52f526e6a7904d48f7d47d5718925001612e11565b6040516001600160a01b03838116602483015260448201839052610bd691859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b0383818316178352505050506136a3565b600080600a84815481106130fe576130fe613bd8565b60009182526020808320878452600b825260408085206001600160a01b0389168652909252908320805460069093029091019350910361314357600092505050610e30565b61314c8561164b565b600061317d8260010154611239670de0b6b3a764000061123387600401548760000154612e1e90919063ffffffff16565b6000878152600c602090815260408083206001600160a01b038a1684529091529020549091506131ad9082612bf0565b6000878152600c602090815260408083206001600160a01b038a168452909152812055600484015483546131ee91670de0b6b3a76400009161123391612e1e565b6001909301929092555091505092915050565b60135460ff1615610bd65760055460125460405163ac6fdaad60e01b8152600481018690526001600160a01b0385811660248301526044820192909252600092919091169063ac6fdaad90606401602060405180830381865afa15801561326c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132909190613bee565b9050600081116132e25760405162461bcd60e51b815260206004820152601d60248201527f43616d656c6f743a207a65726f20666565206e6f7420616c6c6f77656400000060448201526064016109a2565b6001600160a01b0383166134b1578034101561334e5760405162461bcd60e51b815260206004820152602560248201527f43616d656c6f743a20696e73756666696369656e7420532073656e7420746f20604482015264636c61696d60d81b60648201526084016109a2565b6009546040516000916001600160a01b03169083908381818185875af1925050503d806000811461339b576040519150601f19603f3d011682016040523d82523d6000602084013e6133a0565b606091505b50509050806133f15760405162461bcd60e51b815260206004820152601c60248201527f43616d656c6f743a20666565207472616e73666572206661696c65640000000060448201526064016109a2565b60006133fd8334613cb3565b905080156134aa576000846001600160a01b03168260405160006040518083038185875af1925050503d8060008114613452576040519150601f19603f3d011682016040523d82523d6000602084013e613457565b606091505b50509050806134a85760405162461bcd60e51b815260206004820152601860248201527f43616d656c6f743a205320726566756e64206661696c6564000000000000000060448201526064016109a2565b505b5050611a64565b600954611a64906001600160a01b038581169185911684613578565b6003546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015613516573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061353a9190613bee565b90508015610bd6578082111561356157600354610bd6906001600160a01b03168483613089565b600354610bd6906001600160a01b03168484613089565b6040516001600160a01b038481166024830152838116604483015260648201839052611a649186918216906323b872dd906084016130b6565b600a5460005b81811015610bd657826001600160a01b0316600a82815481106135dc576135dc613bd8565b60009182526020909120600690910201546001600160a01b0316036136435760405162461bcd60e51b815260206004820152601760248201527f43616d656c6f743a206578697374696e6720706f6f6c3f00000000000000000060448201526064016109a2565b61364c81613c1d565b90506135b7565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600080602060008451602086016000885af1806136c6576040513d6000823e3d81fd5b50506000513d915081156136de5780600114156136eb565b6001600160a01b0384163b155b15611a6457604051635274afe760e01b81526001600160a01b03851660048201526024016109a2565b60006020828403121561372657600080fd5b5035919050565b6001600160a01b0381168114610e4757600080fd5b6000806000806080858703121561375857600080fd5b84359350602085013592506040850135915060608501356137788161372d565b939692955090935050565b6000806040838503121561379657600080fd5b50508035926020909101359150565b6000602082840312156137b757600080fd5b8135612be98161372d565b60008083601f8401126137d457600080fd5b50813567ffffffffffffffff8111156137ec57600080fd5b6020830191508360208260051b850101111561380757600080fd5b9250929050565b6000806000806000806000806080898b03121561382a57600080fd5b883567ffffffffffffffff8082111561384257600080fd5b61384e8c838d016137c2565b909a50985060208b013591508082111561386757600080fd5b6138738c838d016137c2565b909850965060408b013591508082111561388c57600080fd5b6138988c838d016137c2565b909650945060608b01359150808211156138b157600080fd5b506138be8b828c016137c2565b999c989b5096995094979396929594505050565b600080604083850312156138e557600080fd5b82356138f08161372d565b915060208301356139008161372d565b809150509250929050565b8015158114610e4757600080fd5b80356139248161390b565b919050565b60008060008060008060008060008060c08b8d03121561394857600080fd5b8a3567ffffffffffffffff8082111561396057600080fd5b61396c8e838f016137c2565b909c509a5060208d013591508082111561398557600080fd5b6139918e838f016137c2565b909a50985060408d01359150808211156139aa57600080fd5b6139b68e838f016137c2565b90985096508691506139ca60608e01613919565b955060808d0135945060a08d01359150808211156139e757600080fd5b506139f48d828e016137c2565b915080935050809150509295989b9194979a5092959850565b600080600060608486031215613a2257600080fd5b8335613a2d8161372d565b9250602084013591506040840135613a448161372d565b809150509250925092565b60008060408385031215613a6257600080fd5b8235915060208301356139008161372d565b600060208284031215613a8657600080fd5b8135612be98161390b565b600080600060608486031215613aa657600080fd5b83359250602084013591506040840135613a448161372d565b60008060008060008060c08789031215613ad857600080fd5b86359550602087013594506040870135613af18161372d565b93506060870135613b018161390b565b92506080870135915060a0870135613b188161372d565b809150509295509295509295565b600080600060608486031215613b3b57600080fd5b833592506020840135613b4d8161372d565b91506040840135613a448161372d565b60208082526024908201527f6f70657261746f723a2063616c6c6572206973206e6f7420746865206f70657260408201526330ba37b960e11b606082015260800190565b60208082526018908201527f43616d656c6f743a20696e76616c696420706f6f6c2069640000000000000000604082015260600190565b634e487b7160e01b600052603260045260246000fd5b600060208284031215613c0057600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b600060018201613c2f57613c2f613c07565b5060010190565b80820180821115610e3057610e30613c07565b6020808252602d908201527f43616d656c6f743a20436c61696d20616d6f756e742062656c6f77206d696e6960408201526c1b5d5b481d1a1c995cda1bdb19609a1b606082015260800190565b600060208284031215613ca857600080fd5b8151612be98161390b565b81810381811115610e3057610e30613c07565b8082028115828204841417610e3057610e30613c07565b600082613cfa57634e487b7160e01b600052601260045260246000fd5b50049056fea26469706673582212202c8185f625d7bd19f1b014e15593dec80b0798c861667420b6f693d09d93b94a64736f6c63430008140033000000000000000000000000ab478cb1c351253d5b76265826eb72b059432ee4000000000000000000000000b2240225ae6cff1a329d598f019b3b282eee8858000000000000000000000000eeab6d0c5008c54be42c859b5c19776c5fda792f0000000000000000000000002e91238a7338e9ad4d8b0c8d28bdca33bed404af000000000000000000000000ceb97147aa19e1a1b8fa1234c041f07a896b71d70000000000000000000000000000000000000000000000000000000067f05660

Deployed Bytecode

0x6080604052600436106102e45760003560e01c80636e271dd51161019057806399c52d37116100dc578063d846612111610095578063f03b0c0b1161006f578063f03b0c0b146108f8578063f2fde38b14610918578063f8e1dd4014610938578063fb3df6791461095857600080fd5b8063d8466121146108b2578063d8d36db8146108c5578063ddd5e1b2146108e557600080fd5b806399c52d37146107e4578063ac7d600214610804578063cc29b02014610824578063cf4b55cb1461083a578063d18df53c1461085a578063d1cc19011461089257600080fd5b806384061161116101495780638dbdbe6d116101235780638dbdbe6d1461073a57806393f1a40b1461075a578063943f013d146107ae578063986ccc7f146107c457600080fd5b806384061161146106dc57806388840c55146106fc5780638da5cb5b1461071c57600080fd5b80636e271dd51461063e578063715018a61461065457806373bf51dd1461066957806377329f3514610689578063798cfe7b1461069c5780637b27779f146106bc57600080fd5b8063441a3e701161024f5780635312ea8e1161020857806359e60951116101e257806359e60951146105d35780635f96dc11146105f3578063630b5ba11461060957806363b0e66a1461061e57600080fd5b80635312ea8e1461057557806354575af414610595578063570ca735146105b557600080fd5b8063441a3e701461049d578063461059ff146104bd5780634b8feb4f146104dd5780634d134d791461051557806351637ba91461053557806351eb05a61461055557600080fd5b8063231f0c6a116102a1578063231f0c6a146103f257806329605e77146104125780632e1c3d95146104325780633695dad1146104525780633da5375b1461046857806340e6c0e11461047d57600080fd5b8063033b258b146102e9578063051ba3511461030b578063081e3eda1461032b57806309275e891461034f5780631526fe271461037957806317caf6f1146103dc575b600080fd5b3480156102f557600080fd5b50610309610304366004613714565b610978565b005b34801561031757600080fd5b50610309610326366004613742565b610bdb565b34801561033757600080fd5b50600a545b6040519081526020015b60405180910390f35b34801561035b57600080fd5b506013546103699060ff1681565b6040519015158152602001610346565b34801561038557600080fd5b50610399610394366004613714565b610d13565b604080516001600160a01b039889168152602081019790975286019490945260608501929092526080840152151560a083015290911660c082015260e001610346565b3480156103e857600080fd5b5061033c600d5481565b3480156103fe57600080fd5b5061033c61040d366004613783565b610d71565b34801561041e57600080fd5b5061030961042d3660046137a5565b610e36565b34801561043e57600080fd5b5061030961044d36600461380e565b610e4a565b34801561045e57600080fd5b5061033c60115481565b34801561047457600080fd5b50610309610f70565b34801561048957600080fd5b5061033c6104983660046138d2565b611054565b3480156104a957600080fd5b506103096104b8366004613783565b611117565b3480156104c957600080fd5b506103096104d8366004613929565b611395565b3480156104e957600080fd5b506007546104fd906001600160a01b031681565b6040516001600160a01b039091168152602001610346565b34801561052157600080fd5b506103096105303660046137a5565b6114cd565b34801561054157600080fd5b50610309610550366004613714565b611558565b34801561056157600080fd5b50610309610570366004613714565b61164b565b34801561058157600080fd5b50610309610590366004613714565b611853565b3480156105a157600080fd5b506103096105b0366004613a0d565b611997565b3480156105c157600080fd5b506001546001600160a01b03166104fd565b3480156105df57600080fd5b506103096105ee366004613714565b611a6a565b3480156105ff57600080fd5b5061033c600e5481565b34801561061557600080fd5b50610309611afb565b34801561062a57600080fd5b506006546104fd906001600160a01b031681565b34801561064a57600080fd5b5061033c600f5481565b34801561066057600080fd5b50610309611b22565b34801561067557600080fd5b506103096106843660046137a5565b611b7d565b6103096106973660046137a5565b611bfd565b3480156106a857600080fd5b506009546104fd906001600160a01b031681565b3480156106c857600080fd5b5061033c6106d7366004613a4f565b611d73565b3480156106e857600080fd5b506103096106f7366004613a74565b611ddc565b34801561070857600080fd5b506008546104fd906001600160a01b031681565b34801561072857600080fd5b506000546001600160a01b03166104fd565b34801561074657600080fd5b50610309610755366004613a91565b611e19565b34801561076657600080fd5b50610799610775366004613a4f565b600b6020908152600092835260408084209091529082529020805460019091015482565b60408051928352602083019190915201610346565b3480156107ba57600080fd5b5061033c60105481565b3480156107d057600080fd5b506103096107df3660046137a5565b6121cd565b3480156107f057600080fd5b506103096107ff3660046137a5565b6121f7565b34801561081057600080fd5b5061030961081f366004613abf565b612277565b34801561083057600080fd5b5061033c60125481565b34801561084657600080fd5b5061033c610855366004613a4f565b612501565b34801561086657600080fd5b5061033c610875366004613a4f565b600c60209081526000928352604080842090915290825290205481565b34801561089e57600080fd5b506004546104fd906001600160a01b031681565b6103096108c0366004613a4f565b61270c565b3480156108d157600080fd5b506005546104fd906001600160a01b031681565b61033c6108f3366004613a4f565b6127c0565b34801561090457600080fd5b506103096109133660046137a5565b612933565b34801561092457600080fd5b506103096109333660046137a5565b6129f7565b34801561094457600080fd5b506003546104fd906001600160a01b031681565b34801561096457600080fd5b5061033c610973366004613b26565b612a32565b6001546001600160a01b031633146109ab5760405162461bcd60e51b81526004016109a290613b5d565b60405180910390fd5b600a5481106109cc5760405162461bcd60e51b81526004016109a290613ba1565b6000600a82815481106109e1576109e1613bd8565b60009182526020918290206040805160e081018252600690930290910180546001600160a01b03908116845260018201549484019490945260028101549183019190915260038101546060830152600481015460808301526005015460ff8116151560a0830152610100900490911660c08201819052909150610aa65760405162461bcd60e51b815260206004820152601a60248201527f43616d656c6f743a20706f6f6c20686173206e6f20676175676500000000000060448201526064016109a2565b60c08101516040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015610af1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b159190613bee565b90508015610bc157610b2682612af1565b60c0820151604051632e1a7d4d60e01b8152600481018390526001600160a01b0390911690632e1a7d4d90602401600060405180830381600087803b158015610b6e57600080fd5b505af1158015610b82573d6000803e3d6000fd5b50505050827f075ba0b9dfded837b057a0fe9dec5063b4b475e8a60b3800e30d7fe7859f6a7382604051610bb891815260200190565b60405180910390a25b610bd683836040015184602001516000610bdb565b505050565b6001546001600160a01b03163314610c055760405162461bcd60e51b81526004016109a290613b5d565b610c0d611afb565b6000600a8581548110610c2257610c22613bd8565b906000526020600020906006020190506032831115610c8f5760405162461bcd60e51b815260206004820152602360248201527f7769746864726177206665652063616e74206265206d6f7265207468616e20306044820152622e352560e81b60648201526084016109a2565b60018101839055600581015460ff1615610cca57610cc684610cc08360020154600d54612bdd90919063ffffffff16565b90612bf0565b600d555b60028101849055600581018054610100600160a81b0319166101006001600160a01b03858116820292909217928390559091041615610d0c57610d0c85612bfc565b5050505050565b600a8181548110610d2357600080fd5b60009182526020909120600690910201805460018201546002830154600384015460048501546005909501546001600160a01b03948516965092949193909260ff8116916101009091041687565b6000818310610d8257506000610e30565b600f548210610dea57600f548310610d9c57506000610e30565b600e548311610dcf57610dc8600d54610dc2600e54600f54612bdd90919063ffffffff16565b90612e1e565b9050610e30565b610dc8600d54610dc285600f54612bdd90919063ffffffff16565b600e548211610dfb57506000610e30565b600e548311610e1f57610dc8600d54610dc2600e5485612bdd90919063ffffffff16565b600d54610dc890610dc28486612bdd565b92915050565b610e3e612e2a565b610e4781612e59565b50565b6001546001600160a01b03163314610e745760405162461bcd60e51b81526004016109a290613b5d565b8685148015610e8257508683145b8015610e8d57508681145b610ed35760405162461bcd60e51b8152602060048201526017602482015276086c2dacad8dee87440d2dcecc2d8d2c840d8cadccee8d604b1b60448201526064016109a2565b60005b87811015610f6557610f53898983818110610ef357610ef3613bd8565b90506020020135888884818110610f0c57610f0c613bd8565b90506020020135878785818110610f2557610f25613bd8565b90506020020135868686818110610f3e57610f3e613bd8565b905060200201602081019061032691906137a5565b80610f5d81613c1d565b915050610ed6565b505050505050505050565b6001546001600160a01b03163314610f9a5760405162461bcd60e51b81526004016109a290613b5d565b60005b600a54811015610e47576000600a8281548110610fbc57610fbc613bd8565b60009182526020918290206040805160e081018252600690930290910180546001600160a01b03908116845260018201549484019490945260028101549183019190915260038101546060830152600481015460808301526005015460ff8116151560a0830152610100900490911660c08201819052909150156110435761104381612af1565b5061104d81613c1d565b9050610f9d565b600080805b600a548110156110895761106d8186611d73565b6110779083613c36565b915061108281613c1d565b9050611059565b5060055460125460405163ac6fdaad60e01b8152600481018490526001600160a01b0386811660248301526044820192909252600092919091169063ac6fdaad90606401602060405180830381865afa1580156110ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061110e9190613bee565b95945050505050565b61111f612f21565b600a5482106111405760405162461bcd60e51b81526004016109a290613ba1565b60003390506000600a848154811061115a5761115a613bd8565b60009182526020808320878452600b825260408085206001600160a01b038816865290925292208054600690920290920192508411156111f95760405162461bcd60e51b815260206004820152603460248201527f43616d656c6f743a207573657220646f6573206e6f74206861766520656e6f7560448201527319da0818985b185b98d94819195c1bdcda5d195960621b60648201526084016109a2565b6112028561164b565b600061123f8260010154611239670de0b6b3a764000061123387600401548760000154612e1e90919063ffffffff16565b90612f49565b90612bdd565b90508015611298576000868152600c602090815260408083206001600160a01b03881684529091529020546112749082612bf0565b6000878152600c602090815260408083206001600160a01b03891684529091529020555b84156113205781546112aa9086612bdd565b82556112b68686612f55565b60006112d5612710611233866001015489612e1e90919063ffffffff16565b905060006112e38783612bdd565b90508115611307576007548554611307916001600160a01b03918216911684613089565b845461131d906001600160a01b03168783613089565b50505b6004830154825461133e91670de0b6b3a76400009161123391612e1e565b600183015560405185815286906001600160a01b038616907ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b5689060200160405180910390a3505050506113916001600255565b5050565b6001546001600160a01b031633146113bf5760405162461bcd60e51b81526004016109a290613b5d565b88871480156113cd57508885145b80156113d857508881145b61141e5760405162461bcd60e51b8152602060048201526017602482015276086c2dacad8dee87440d2dcecc2d8d2c840d8cadccee8d604b1b60448201526064016109a2565b60005b898110156114c0576114ae8b8b8381811061143e5761143e613bd8565b905060200201358a8a8481811061145757611457613bd8565b9050602002013589898581811061147057611470613bd8565b905060200201602081019061148591906137a5565b888888888881811061149957611499613bd8565b905060200201602081019061081f91906137a5565b806114b881613c1d565b915050611421565b5050505050505050505050565b6114d5612e2a565b6001600160a01b0381166115365760405162461bcd60e51b815260206004820152602260248201527f43616d656c6f743a20696e76616c696420535057785265776172647357616c6c604482015261195d60f21b60648201526084016109a2565b600880546001600160a01b0319166001600160a01b0392909216919091179055565b6001546001600160a01b031633146115825760405162461bcd60e51b81526004016109a290613b5d565b633b9aca008110156115e25760405162461bcd60e51b8152602060048201526024808201527f43616d656c6f743a20696e76616c6964206d696e20636c61696d2074687265736044820152631a1bdb1960e21b60648201526084016109a2565b670de0b6b3a76400008111156116465760405162461bcd60e51b8152602060048201526024808201527f43616d656c6f743a20696e76616c6964206d617820636c61696d2074687265736044820152631a1bdb1960e21b60648201526084016109a2565b601155565b600a54811061166c5760405162461bcd60e51b81526004016109a290613ba1565b6000600a828154811061168157611681613bd8565b90600052602060002090600602019050806003015442116116a0575050565b600581015460009061010090046001600160a01b031661172a5781546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015611701573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117259190613bee565b61179c565b60058201546040516370a0823160e01b81523060048201526101009091046001600160a01b0316906370a0823190602401602060405180830381865afa158015611778573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061179c9190613bee565b9050806000036117b157504260039091015550565b600582015460ff166117e15760058201805460ff191660011790556002820154600d546117dd91612bf0565b600d555b600d54156118485760006117f9836003015442610d71565b9050600061181a600d54611233866002015485612e1e90919063ffffffff16565b90506118406118358461123384670de0b6b3a7640000612e1e565b600486015490612bf0565b600485015550505b504260039091015550565b61185b612f21565b600a54811061187c5760405162461bcd60e51b81526004016109a290613ba1565b6000600a828154811061189157611891613bd8565b60009182526020808320858452600b8252604080852033808752908452818620805487825560018201889055898852600c8652838820928852919094529085209490945560069092029091019250906118ea8482612f55565b6000611909612710611233866001015485612e1e90919063ffffffff16565b905060006119178383612bdd565b9050811561193b57600754855461193b916001600160a01b03918216911684613089565b8454611951906001600160a01b03163383613089565b604051838152869033907fbb757047c2b5f3974fe26b7c10f732e7bce710b0952a71082702781e62ae05959060200160405180910390a35050505050610e476001600255565b61199f612e2a565b600a5460005b81811015611a4f576000600a82815481106119c2576119c2613bd8565b6000918252602090912060069091020180549091506001600160a01b0390811690871603611a3e5760405162461bcd60e51b815260206004820152602360248201527f43616d656c6f743a20746f6b656e2063616e6e6f7420626520706f6f6c20746f60448201526235b2b760e91b60648201526084016109a2565b50611a4881613c1d565b90506119a5565b50611a646001600160a01b0385168385613089565b50505050565b6001546001600160a01b03163314611a945760405162461bcd60e51b81526004016109a290613b5d565b6101f4811115611af65760405162461bcd60e51b815260206004820152602760248201527f43616d656c6f743a20696e76616c696420706567206e6f62696c697479207661604482015266756c742066656560c81b60648201526084016109a2565b601255565b600a5460005b8181101561139157611b128161164b565b611b1b81613c1d565b9050611b01565b611b2a612e2a565b60405162461bcd60e51b815260206004820152602260248201527f4f70657261746f72206d75737420616c77617973206861766520616e206f776e60448201526132b960f11b60648201526084016109a2565b611b85612e2a565b6001600160a01b038116611bdb5760405162461bcd60e51b815260206004820152601a60248201527f43616d656c6f743a20696e76616c696420504e5657616c6c657400000000000060448201526064016109a2565b600980546001600160a01b0319166001600160a01b0392909216919091179055565b611c05612f21565b60135460ff16158015611c16575034155b80611c41575060135460ff168015611c3557506001600160a01b038116155b8015611c415750600034115b80611c6b575060135460ff168015611c6157506001600160a01b03811615155b8015611c6b575034155b611cb75760405162461bcd60e51b815260206004820181905260248201527f43616d656c6f743a20696e76616c696420532073656e7420746f20636c61696d60448201526064016109a2565b336000805b600a54811015611cec57611cd081846130e8565b611cda9083613c36565b9150611ce581613c1d565b9050611cbc565b50601154811015611d0f5760405162461bcd60e51b81526004016109a290613c49565b611d1a818484613201565b611d2482826134cd565b816001600160a01b03167fe2403640ba68fed3a2f88b7557551d1993f84b99bb10ff833f0cf8db0c5e048682604051611d5f91815260200190565b60405180910390a25050610e476001600255565b600a546000908310611d975760405162461bcd60e51b81526004016109a290613ba1565b6000611da38484612501565b6000858152600c602090815260408083206001600160a01b0388168452909152902054909150611dd4908290612bf0565b949350505050565b6001546001600160a01b03163314611e065760405162461bcd60e51b81526004016109a290613b5d565b6013805460ff1916911515919091179055565b611e21612f21565b600a548310611e425760405162461bcd60e51b81526004016109a290613ba1565b60003390506000600a8581548110611e5c57611e5c613bd8565b60009182526020808320888452600b825260408085206001600160a01b0380891687529352909320600690920290920192509084161580611ea757506006546001600160a01b031615155b611eec5760405162461bcd60e51b815260206004820152601660248201527521b0b6b2b637ba1d1034b73b30b634b2103a37b5b2b760511b60448201526064016109a2565b611ef58661164b565b805415611f88576000611f2d8260010154611239670de0b6b3a764000061123387600401548760000154612e1e90919063ffffffff16565b90508015611f86576000878152600c602090815260408083206001600160a01b0388168452909152902054611f629082612bf0565b6000888152600c602090815260408083206001600160a01b03891684529091529020555b505b841561215d576001600160a01b038416611fc6578154611fb3906001600160a01b0316843088613578565b8054611fbf9086612bf0565b8155612154565b83611fdc6001600160a01b038216853089613578565b60065460405163095ea7b360e01b81526001600160a01b039182166004820152602481018890529082169063095ea7b3906044016020604051808303816000875af115801561202f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120539190613c96565b506006548354604051636214c24f60e11b81526001600160a01b038881166004830152918216602482015260448101899052600092919091169063c429849e906064016020604051808303816000875af11580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190613bee565b9050600081116121435760405162461bcd60e51b815260206004820152602f60248201527f43616d656c6f743a2068656c70657220636f6e76657273696f6e20726574757260448201526e1b9959081e995c9bc8185b5bdd5b9d608a1b60648201526084016109a2565b825461214f9082612bf0565b835550505b61215d86612bfc565b6004820154815461217b91670de0b6b3a76400009161123391612e1e565b600182015560405185815286906001600160a01b038516907f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159060200160405180910390a3505050610bd66001600255565b6121d5612e2a565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b6121ff612e2a565b6001600160a01b0381166122555760405162461bcd60e51b815260206004820152601e60248201527f43616d656c6f743a20696e76616c696420504e564665654d616e61676572000060448201526064016109a2565b600580546001600160a01b0319166001600160a01b0392909216919091179055565b6001546001600160a01b031633146122a15760405162461bcd60e51b81526004016109a290613b5d565b60328511156123075760405162461bcd60e51b815260206004820152602c60248201527f43616d656c6f743a207769746864726177206665652063616e74206265206d6f60448201526b7265207468616e20302e352560a01b60648201526084016109a2565b612310846135b1565b821561231e5761231e611afb565b600e5442101561233d57600e5482101561233857600e5491505b612349565b42821015612349574291505b6000600e548311158061235c5750428311155b6040805160e0810182526001600160a01b038881168252602082018a81529282018b8152606083018881526000608085018181528715801560a088019081528b871660c08901908152600a8054600181018255955297517fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a8600690950294850180546001600160a01b03191691891691909117905597517fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a984015593517fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2aa83015591517fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2ab82015590517fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2ac82015593517fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2ad909401805493516001600160a81b0319909416941515610100600160a81b031916949094176101009390921692909202179091559091506124f857600d546124f49088612bf0565b600d555b50505050505050565b600a5460009083106125255760405162461bcd60e51b81526004016109a290613ba1565b6000600a848154811061253a5761253a613bd8565b60009182526020808320878452600b825260408085206001600160a01b038981168752935284206006939093020160048101546005820154919550929391610100909104166125f35783546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa1580156125ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125ee9190613bee565b612665565b60058401546040516370a0823160e01b81523060048201526101009091046001600160a01b0316906370a0823190602401602060405180830381865afa158015612641573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126659190613bee565b905083600301544211801561267957508015155b156126d657600061268e856003015442610d71565b905060006126af600d54611233886002015485612e1e90919063ffffffff16565b90506126d16126ca8461123384670de0b6b3a7640000612e1e565b8590612bf0565b935050505b6127018360010154611239670de0b6b3a7640000611233868860000154612e1e90919063ffffffff16565b979650505050505050565b612714612f21565b600a5482106127355760405162461bcd60e51b81526004016109a290613ba1565b6006546001600160a01b031661278d5760405162461bcd60e51b815260206004820152601760248201527f43616d656c6f743a2068656c706572206e6f742073657400000000000000000060448201526064016109a2565b600061279983836127c0565b6003549091506127b590849083906001600160a01b0316611e19565b506113916001600255565b60006127ca612f21565b600a5483106127eb5760405162461bcd60e51b81526004016109a290613ba1565b60135460ff161580156127fc575034155b80612827575060135460ff16801561281b57506001600160a01b038216155b80156128275750600034115b80612851575060135460ff16801561284757506001600160a01b03821615155b8015612851575034155b61289d5760405162461bcd60e51b815260206004820181905260248201527f43616d656c6f743a20696e76616c696420532073656e7420746f20636c61696d60448201526064016109a2565b3360006128aa85836130e8565b90506011548110156128ce5760405162461bcd60e51b81526004016109a290613c49565b6128d9818584613201565b6128e382826134cd565b816001600160a01b03167fe2403640ba68fed3a2f88b7557551d1993f84b99bb10ff833f0cf8db0c5e04868260405161291e91815260200190565b60405180910390a2915050610e306001600255565b61293b612e2a565b6001600160a01b0381166129a35760405162461bcd60e51b815260206004820152602960248201527f43616e6e6f7420736574206d756c746953696757616c6c657420746f207a65726044820152686f206164647265737360b81b60648201526084016109a2565b600780546001600160a01b0319166001600160a01b0383169081179091556040519081527fb47ff16b5bae9457ad1554c677eb38ef82abc443a3e3f78c8bce69830b1b64a19060200160405180910390a150565b6129ff612e2a565b6001600160a01b038116612a2957604051631e4fbdf760e01b8152600060048201526024016109a2565b610e4781613653565b600a546000908410612a565760405162461bcd60e51b81526004016109a290613ba1565b6000612a628585611d73565b60055460125460405163ac6fdaad60e01b8152600481018490526001600160a01b038781166024830152604482019290925292935060009291169063ac6fdaad90606401602060405180830381865afa158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613bee565b9695505050505050565b8060c001516001600160a01b0316633d18b9126040518163ffffffff1660e01b8152600401600060405180830381600087803b158015612b3057600080fd5b505af1158015612b44573d6000803e3d6000fd5b5050600480546040516370a0823160e01b81523092810192909252600093506001600160a01b031691506370a0823190602401602060405180830381865afa158015612b94573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bb89190613bee565b9050801561139157600854600454611391916001600160a01b03918216911683613089565b6000612be98284613cb3565b9392505050565b6000612be98284613c36565b6000600a8281548110612c1157612c11613bd8565b600091825260208083206040805160e08101825260069490940290910180546001600160a01b0390811680865260018301549486019490945260028201548584015260038201546060860152600480830154608087015260059092015460ff8116151560a087015261010090041660c085015290516370a0823160e01b81523091810191909152919350906370a0823190602401602060405180830381865afa158015612cc2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ce69190613bee565b60c08301519091506001600160a01b031615610bd6578015610bd657815160c083015160405163095ea7b360e01b81526001600160a01b0391821660048201526024810184905291169063095ea7b3906044016020604051808303816000875af1158015612d58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d7c9190613c96565b5060c082015160405163b6b55f2560e01b8152600481018390526001600160a01b039091169063b6b55f2590602401600060405180830381600087803b158015612dc557600080fd5b505af1158015612dd9573d6000803e3d6000fd5b505060408051848152600160208201528693507f71d77cd09e03d2887b1690010000325aa3412e58ca5d49c09bbfe50e13beff779250015b60405180910390a2505050565b6000612be98284613cc6565b6000546001600160a01b03163314612e575760405163118cdaa760e01b81523360048201526024016109a2565b565b6001600160a01b038116612ec55760405162461bcd60e51b815260206004820152602d60248201527f6f70657261746f723a207a65726f206164647265737320676976656e20666f7260448201526c103732bb9037b832b930ba37b960991b60648201526084016109a2565b6001546040516001600160a01b038084169216907f74da04524d50c64947f5dd5381ef1a4dca5cba8ed1d816243f9e48aa0b5617ed90600090a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b6002805403612f4357604051633ee5aeb560e01b815260040160405180910390fd5b60028055565b6000612be98284613cdd565b6000600a8381548110612f6a57612f6a613bd8565b60009182526020918290206040805160e081018252600690930290910180546001600160a01b03908116845260018201549484019490945260028101549183019190915260038101546060830152600481015460808301526005015460ff8116151560a0830152610100900490911660c0820181905290915015610bd657612ff181612af1565b60c0810151604051632e1a7d4d60e01b8152600481018490526001600160a01b0390911690632e1a7d4d90602401600060405180830381600087803b15801561303957600080fd5b505af115801561304d573d6000803e3d6000fd5b505060408051858152600160208201528693507fb7d10c4af8b2c06f54a97ae225c7e59df848cc52f526e6a7904d48f7d47d5718925001612e11565b6040516001600160a01b03838116602483015260448201839052610bd691859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b0383818316178352505050506136a3565b600080600a84815481106130fe576130fe613bd8565b60009182526020808320878452600b825260408085206001600160a01b0389168652909252908320805460069093029091019350910361314357600092505050610e30565b61314c8561164b565b600061317d8260010154611239670de0b6b3a764000061123387600401548760000154612e1e90919063ffffffff16565b6000878152600c602090815260408083206001600160a01b038a1684529091529020549091506131ad9082612bf0565b6000878152600c602090815260408083206001600160a01b038a168452909152812055600484015483546131ee91670de0b6b3a76400009161123391612e1e565b6001909301929092555091505092915050565b60135460ff1615610bd65760055460125460405163ac6fdaad60e01b8152600481018690526001600160a01b0385811660248301526044820192909252600092919091169063ac6fdaad90606401602060405180830381865afa15801561326c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132909190613bee565b9050600081116132e25760405162461bcd60e51b815260206004820152601d60248201527f43616d656c6f743a207a65726f20666565206e6f7420616c6c6f77656400000060448201526064016109a2565b6001600160a01b0383166134b1578034101561334e5760405162461bcd60e51b815260206004820152602560248201527f43616d656c6f743a20696e73756666696369656e7420532073656e7420746f20604482015264636c61696d60d81b60648201526084016109a2565b6009546040516000916001600160a01b03169083908381818185875af1925050503d806000811461339b576040519150601f19603f3d011682016040523d82523d6000602084013e6133a0565b606091505b50509050806133f15760405162461bcd60e51b815260206004820152601c60248201527f43616d656c6f743a20666565207472616e73666572206661696c65640000000060448201526064016109a2565b60006133fd8334613cb3565b905080156134aa576000846001600160a01b03168260405160006040518083038185875af1925050503d8060008114613452576040519150601f19603f3d011682016040523d82523d6000602084013e613457565b606091505b50509050806134a85760405162461bcd60e51b815260206004820152601860248201527f43616d656c6f743a205320726566756e64206661696c6564000000000000000060448201526064016109a2565b505b5050611a64565b600954611a64906001600160a01b038581169185911684613578565b6003546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015613516573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061353a9190613bee565b90508015610bd6578082111561356157600354610bd6906001600160a01b03168483613089565b600354610bd6906001600160a01b03168484613089565b6040516001600160a01b038481166024830152838116604483015260648201839052611a649186918216906323b872dd906084016130b6565b600a5460005b81811015610bd657826001600160a01b0316600a82815481106135dc576135dc613bd8565b60009182526020909120600690910201546001600160a01b0316036136435760405162461bcd60e51b815260206004820152601760248201527f43616d656c6f743a206578697374696e6720706f6f6c3f00000000000000000060448201526064016109a2565b61364c81613c1d565b90506135b7565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600080602060008451602086016000885af1806136c6576040513d6000823e3d81fd5b50506000513d915081156136de5780600114156136eb565b6001600160a01b0384163b155b15611a6457604051635274afe760e01b81526001600160a01b03851660048201526024016109a2565b60006020828403121561372657600080fd5b5035919050565b6001600160a01b0381168114610e4757600080fd5b6000806000806080858703121561375857600080fd5b84359350602085013592506040850135915060608501356137788161372d565b939692955090935050565b6000806040838503121561379657600080fd5b50508035926020909101359150565b6000602082840312156137b757600080fd5b8135612be98161372d565b60008083601f8401126137d457600080fd5b50813567ffffffffffffffff8111156137ec57600080fd5b6020830191508360208260051b850101111561380757600080fd5b9250929050565b6000806000806000806000806080898b03121561382a57600080fd5b883567ffffffffffffffff8082111561384257600080fd5b61384e8c838d016137c2565b909a50985060208b013591508082111561386757600080fd5b6138738c838d016137c2565b909850965060408b013591508082111561388c57600080fd5b6138988c838d016137c2565b909650945060608b01359150808211156138b157600080fd5b506138be8b828c016137c2565b999c989b5096995094979396929594505050565b600080604083850312156138e557600080fd5b82356138f08161372d565b915060208301356139008161372d565b809150509250929050565b8015158114610e4757600080fd5b80356139248161390b565b919050565b60008060008060008060008060008060c08b8d03121561394857600080fd5b8a3567ffffffffffffffff8082111561396057600080fd5b61396c8e838f016137c2565b909c509a5060208d013591508082111561398557600080fd5b6139918e838f016137c2565b909a50985060408d01359150808211156139aa57600080fd5b6139b68e838f016137c2565b90985096508691506139ca60608e01613919565b955060808d0135945060a08d01359150808211156139e757600080fd5b506139f48d828e016137c2565b915080935050809150509295989b9194979a5092959850565b600080600060608486031215613a2257600080fd5b8335613a2d8161372d565b9250602084013591506040840135613a448161372d565b809150509250925092565b60008060408385031215613a6257600080fd5b8235915060208301356139008161372d565b600060208284031215613a8657600080fd5b8135612be98161390b565b600080600060608486031215613aa657600080fd5b83359250602084013591506040840135613a448161372d565b60008060008060008060c08789031215613ad857600080fd5b86359550602087013594506040870135613af18161372d565b93506060870135613b018161390b565b92506080870135915060a0870135613b188161372d565b809150509295509295509295565b600080600060608486031215613b3b57600080fd5b833592506020840135613b4d8161372d565b91506040840135613a448161372d565b60208082526024908201527f6f70657261746f723a2063616c6c6572206973206e6f7420746865206f70657260408201526330ba37b960e11b606082015260800190565b60208082526018908201527f43616d656c6f743a20696e76616c696420706f6f6c2069640000000000000000604082015260600190565b634e487b7160e01b600052603260045260246000fd5b600060208284031215613c0057600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b600060018201613c2f57613c2f613c07565b5060010190565b80820180821115610e3057610e30613c07565b6020808252602d908201527f43616d656c6f743a20436c61696d20616d6f756e742062656c6f77206d696e6960408201526c1b5d5b481d1a1c995cda1bdb19609a1b606082015260800190565b600060208284031215613ca857600080fd5b8151612be98161390b565b81810381811115610e3057610e30613c07565b8082028115828204841417610e3057610e30613c07565b600082613cfa57634e487b7160e01b600052601260045260246000fd5b50049056fea26469706673582212202c8185f625d7bd19f1b014e15593dec80b0798c861667420b6f693d09d93b94a64736f6c63430008140033

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

000000000000000000000000ab478cb1c351253d5b76265826eb72b059432ee4000000000000000000000000b2240225ae6cff1a329d598f019b3b282eee8858000000000000000000000000eeab6d0c5008c54be42c859b5c19776c5fda792f0000000000000000000000002e91238a7338e9ad4d8b0c8d28bdca33bed404af000000000000000000000000ceb97147aa19e1a1b8fa1234c041f07a896b71d70000000000000000000000000000000000000000000000000000000067f05660

-----Decoded View---------------
Arg [0] : _KNIGHT (address): 0xab478cb1c351253d5b76265826EB72b059432EE4
Arg [1] : _multiSigWallet (address): 0xb2240225aE6Cff1A329d598f019b3B282eEE8858
Arg [2] : _SPWxRewardsWallet (address): 0xeeab6D0c5008c54BE42C859b5C19776C5FDa792f
Arg [3] : _PNVWallet (address): 0x2E91238a7338E9ad4D8b0c8D28bDca33bEd404Af
Arg [4] : _PNVFeeManager (address): 0xCEb97147Aa19e1A1B8fa1234C041f07a896B71D7
Arg [5] : _poolStartTime (uint256): 1743804000

-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 000000000000000000000000ab478cb1c351253d5b76265826eb72b059432ee4
Arg [1] : 000000000000000000000000b2240225ae6cff1a329d598f019b3b282eee8858
Arg [2] : 000000000000000000000000eeab6d0c5008c54be42c859b5c19776c5fda792f
Arg [3] : 0000000000000000000000002e91238a7338e9ad4d8b0c8d28bdca33bed404af
Arg [4] : 000000000000000000000000ceb97147aa19e1a1b8fa1234c041f07a896b71d7
Arg [5] : 0000000000000000000000000000000000000000000000000000000067f05660


Block Transaction Gas Used Reward
view all blocks ##produced##

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

Validator Index Block Amount
View All Withdrawals

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

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