ETH Price: $3,410.07 (+2.47%)
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Stake Bipzy With...239351072025-12-03 19:50:597 days ago1764791459IN
0xAa1F7CDE...Ab6297C27
0 ETH0.00015822.04492647
Stake Bipzy With...239281492025-12-02 20:26:357 days ago1764707195IN
0xAa1F7CDE...Ab6297C27
0 ETH0.000123532.04992648
Stake Bipzy With...238866312025-11-27 0:58:1113 days ago1764205091IN
0xAa1F7CDE...Ab6297C27
0 ETH0.000123842.05498732
Stake Bipzy With...238858522025-11-26 22:20:4713 days ago1764195647IN
0xAa1F7CDE...Ab6297C27
0 ETH0.000159152.0572691
Stake Bipzy With...238855162025-11-26 21:12:4713 days ago1764191567IN
0xAa1F7CDE...Ab6297C27
0 ETH0.000123622.0513601
Stake Bipzy With...238843712025-11-26 17:21:5914 days ago1764177719IN
0xAa1F7CDE...Ab6297C27
0 ETH0.000125852.08845936
Stake Bipzy With...238840132025-11-26 16:09:3514 days ago1764173375IN
0xAa1F7CDE...Ab6297C27
0 ETH0.000124942.07334467
Stake Bipzy238043392025-11-15 11:37:3525 days ago1763206655IN
0xAa1F7CDE...Ab6297C27
0 ETH0.000011130.0679785
Stake Bipzy With...237983982025-11-14 15:42:5926 days ago1763134979IN
0xAa1F7CDE...Ab6297C27
0 ETH0.000172322.85950257
Stake Bipzy With...237940372025-11-14 1:05:2326 days ago1763082323IN
0xAa1F7CDE...Ab6297C27
0 ETH0.000163452.11279678
Stake Bipzy With...237934262025-11-13 23:01:4726 days ago1763074907IN
0xAa1F7CDE...Ab6297C27
0 ETH0.00012882.13738362
Stake Bipzy With...237932042025-11-13 22:16:5926 days ago1763072219IN
0xAa1F7CDE...Ab6297C27
0 ETH0.000140322.32845497
Stake Bipzy With...237932022025-11-13 22:16:3526 days ago1763072195IN
0xAa1F7CDE...Ab6297C27
0 ETH0.000137812.28861942
Stake Bipzy With...237911802025-11-13 15:28:5927 days ago1763047739IN
0xAa1F7CDE...Ab6297C27
0 ETH0.000231113.83501179
Stake Bipzy With...237867942025-11-13 0:44:1127 days ago1762994651IN
0xAa1F7CDE...Ab6297C27
0 ETH0.000125032.07473557
Stake Bipzy With...237865512025-11-12 23:54:5927 days ago1762991699IN
0xAa1F7CDE...Ab6297C27
0 ETH0.000124332.06324114
Stake Bipzy With...237863262025-11-12 23:09:2327 days ago1762988963IN
0xAa1F7CDE...Ab6297C27
0 ETH0.000124672.06887553
Stake Bipzy With...237846972025-11-12 17:40:4728 days ago1762969247IN
0xAa1F7CDE...Ab6297C27
0 ETH0.00016592.75290136
Stake Bipzy With...237839322025-11-12 15:07:1128 days ago1762960031IN
0xAa1F7CDE...Ab6297C27
0 ETH0.000165872.75248437
Stake Bipzy With...237835762025-11-12 13:54:5928 days ago1762955699IN
0xAa1F7CDE...Ab6297C27
0 ETH0.00027382.21721341
Stake Bipzy With...237833402025-11-12 13:07:2328 days ago1762952843IN
0xAa1F7CDE...Ab6297C27
0 ETH0.000178772.31087149
Stake Bipzy With...237830792025-11-12 12:14:3528 days ago1762949675IN
0xAa1F7CDE...Ab6297C27
0 ETH0.000163912.11880648
Stake Bipzy With...237829552025-11-12 11:49:2328 days ago1762948163IN
0xAa1F7CDE...Ab6297C27
0 ETH0.000004710.07830965
Stake Bipzy With...237803932025-11-12 3:14:2328 days ago1762917263IN
0xAa1F7CDE...Ab6297C27
0 ETH0.000006310.10479895
Stake Bipzy With...237793972025-11-11 23:54:2328 days ago1762905263IN
0xAa1F7CDE...Ab6297C27
0 ETH0.000162032.09442097
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading
Cross-Chain Transactions

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
BipzyStaking

Compiler Version
v0.8.17+commit.8df45f5f

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
//SPDX-License-Identifier:MIT

pragma solidity ^0.8.17;

import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";

/**
 * @title BipzyStaking
 * @notice This contract allows holders of Bipzy and BipzyPass NFTs to stake their tokens for predetermined durations.
 * @dev The contract supports two types of NFTs: Bipzy and BipzyPass, and allows staking for either 180 or 360 days.
 */
contract BipzyStaking is Ownable {
    /**
     * @notice Custom errors for various error scenarios.
     * @dev Using custom errors helps save gas compared to revert strings.
     */
    error BPZ__InvalidPrevId();
    error BPZ__StakePeriodNotOver();
    error BPZ__MustOwn1NFTAtLeast();
    error BPZ__InvalidStakeDuration();
    error BPZ__ContractInstanceLocked();
    error BPZ__NFTContractNotSupported();
    error BPZ__ZeroStakePreferencesFound();
    error BPZ__OnlyStakerCanWithdrawTheirStake();

    /**
     * @notice The Bipzy NFT contract instance.
     */
    IERC721 public i_bipzy;
    /**
     * @notice The BipzyPass NFT contract instance.
     */
    IERC721 public i_bipzyPass;

    /**
     * @notice This boolean flag indicates whether the contract instances (i_bipzy and i_bipzyPass) are locked.
     * @dev If set to true, the contract instances cannot be updated by calling setNewBipzyInstance or setNewBipzyPassInstance.
     */
    bool public contractInstancesLocked;

    /**
     * @notice The duration of minimum stake period days in seconds.
     */
    uint64 public minDuration = 3 * 30 days;

    /**
     * @notice The duration of maximum stake period days in seconds.
     */
    uint64 public maxDuration = 6 * 30 days;

    /**
     * @notice The booster value for a staked NFT with a 180-day duration.
     */
    uint256 public boosterValueOne = 10000;

    /**
     * @notice The booster value for a staked NFT with a 360-day duration.
     */
    uint256 public boosterValueTwo = 15000;

    /**
     * @notice The sentinel token ID used as a marker in the linked list.
     * @dev This value is derived from the string "Bipzys" converted to binary and then decimal.
     */
    uint256 public constant SENTINAL_TOKEN_ID = 73020626073971;

    /**
     * @notice Struct to store stake information for each staked token.
     * @param staker The address of the staker.
     * @param tokenId The ID of the staked token.
     * @param tokenContract The contract instance of the staked token (Bipzy or BipzyPass).
     * @param stakeStartedOn The timestamp when the stake started.
     * @param stakeEndsOn The timestamp when the stake ends.
     */
    struct StakeInfo {
        address staker;
        uint96 tokenId;
        IERC721 tokenContract;
        uint32 stakeStartedOn;
        uint32 stakeEndsOn;
    }

    /**
     * @notice Struct to store stake preference information for staking NFTs.
     * @param tokenId The ID of the token to be staked.
     * @param stakeDuration The duration of the stake (180 or 360 days).
     * @param nftContract The contract instance of the NFT (Bipzy or BipzyPass).
     */
    struct StakePreference {
        uint96 tokenId;
        uint32 stakeDuration;
        IERC721 nftContract;
    }

    /**
     * @notice Struct to store stake withdrawal preference information.
     * @param tokenId The ID of the token to be withdrawn.
     * @param prevTokenId The ID of the token preceding the token to be withdrawn in the linked list.
     */
    struct StakeWithdrawalPreference {
        uint96 tokenId;
        uint96 prevTokenId;
    }

    /**
     * @notice Mapping to store stake information for each token ID.
     */
    mapping(uint256 => StakeInfo) public idBipzyToStakeInfo;
    mapping(uint256 => StakeInfo) public idBipzyPassToStakeInfo;

    /**
     * @notice Mapping to store token IDs in a linked list for each staker.
     * @dev The linked list is used to efficiently traverse the staker's staked tokens during booster calculation.
     */
    mapping(address => mapping(uint256 => uint256)) public ownerToBipzyTokenIds;
    mapping(address => mapping(uint256 => uint256))
        public ownerToBipzyPassTokenIds;

    /**
     * @notice Mapping to store Bipzy NFT Token IDs that are rare
     * @dev Only Owner can update the mapping
     * only Bipzy NFT will have rare NFTs hence only Bipzy NFT are going to be stored here
     */
    mapping(uint256 => bool) public rareTokenIds;
    
    /**
     * @notice Event emitted when a Bipzy token is staked.
     * @param staker The address of the staker.
     * @param tokenId The ID of the staked token.
     * @param nftContractInstance The contract instance of the staked token (Bipzy or BipzyPass).
     * @param stakingStartedOn The timestamp when the stake started.
     * @param stakingEndTimeStamp The timestamp when the stake ends.
     */
    event BipzyTokenStaked(
        address indexed staker,
        uint96 indexed tokenId,
        IERC721 indexed nftContractInstance,
        uint32 stakingStartedOn,
        uint32 stakingEndTimeStamp
    );
    /**
     * @notice Event emitted when a Bipzy Pass token is staked.
     * @param staker The address of the staker.
     * @param tokenId The ID of the staked token.
     * @param nftContractInstance The contract instance of the staked token (Bipzy or BipzyPass).
     * @param stakingStartedOn The timestamp when the stake started.
     * @param stakingEndTimeStamp The timestamp when the stake ends.
     */
    event BipzyPassTokenStaked(
        address indexed staker,
        uint96 indexed tokenId,
        IERC721 indexed nftContractInstance,
        uint32 stakingStartedOn,
        uint32 stakingEndTimeStamp
    );

    /**
     * @notice Event emitted when a staked token is withdrawn.
     * @param staker The address of the staker.
     * @param tokenId The ID of the withdrawn token.
     * @param nftContractInstance The contract instance of the withdrawn token (Bipzy or BipzyPass).
     */
    event BipzyStakeWithdrawn(
        address indexed staker,
        uint96 indexed tokenId,
        IERC721 indexed nftContractInstance
    );

    /**
     * @notice Event emitted when a staked token is withdrawn.
     * @param staker The address of the staker.
     * @param tokenId The ID of the withdrawn token.
     * @param nftContractInstance The contract instance of the withdrawn token (Bipzy or BipzyPass).
     */
    event BipzyPassStakeWithdrawn(
        address indexed staker,
        uint96 indexed tokenId,
        IERC721 indexed nftContractInstance
    );

    /**
     * @notice Event emitteed when owner force unstakes the token
     * @param tokenId token ID that was force unstaked
     */
    event ForceUnstaked(
        uint96 indexed tokenId
    );

    /**
     * @notice Constructor to set the Bipzy and BipzyPass NFT contract instances.
     * @param bipzyNftAddr The address of the Bipzy NFT contract.
     * @param bipzyPassNftAddr The address of the BipzyPass NFT contract.
     */
    constructor(IERC721 bipzyNftAddr, IERC721 bipzyPassNftAddr) {
        i_bipzy = bipzyNftAddr;
        i_bipzyPass = bipzyPassNftAddr;
        contractInstancesLocked = false;
    }

    /**
     * @dev Allows the staking of BIPZY tokens.
     * @param stakePreferences Array of `StakePreference` structs containing stake preferences.
     */
    function stakeBipzy(StakePreference[] calldata stakePreferences) public {
        // Ensure that the caller owns at least one Bipzy or BipzyPass NFT
        if (i_bipzy.balanceOf(msg.sender) == 0)
            revert BPZ__MustOwn1NFTAtLeast();

        // Ensure that at least one stake preference is provided
        if (stakePreferences.length == 0)
            revert BPZ__ZeroStakePreferencesFound();

        uint32 currentTimestamp = uint32(block.timestamp);

        if(ownerToBipzyTokenIds[msg.sender][SENTINAL_TOKEN_ID] == 0) {
            ownerToBipzyTokenIds[msg.sender][SENTINAL_TOKEN_ID] = SENTINAL_TOKEN_ID;
        }

        // Iterate through the stake preferences and process each one
        for (uint i = 0; i < stakePreferences.length; i++) {
            StakePreference memory preference = stakePreferences[i];
            uint96 tokenId = preference.tokenId;
            uint32 duration = preference.stakeDuration;
            IERC721 nftContractInstance = preference.nftContract;

            // Ensure that the stake duration is either minDuration or maxDuration days
            if (duration != minDuration && duration != maxDuration)
                revert BPZ__InvalidStakeDuration();

            uint32 stakeEndsOn = currentTimestamp + duration;

            // Ensure that the NFT contract is either Bipzy or BipzyPass
            if (nftContractInstance != i_bipzy) {
                revert BPZ__NFTContractNotSupported();
            }
            // Transfer the NFT from the staker to the contract
            nftContractInstance.transferFrom(
                msg.sender,
                address(this),
                tokenId
            );

            // Update the linked list of token IDs for the staker
            ownerToBipzyTokenIds[msg.sender][tokenId] = ownerToBipzyTokenIds[msg.sender][SENTINAL_TOKEN_ID];
            ownerToBipzyTokenIds[msg.sender][SENTINAL_TOKEN_ID] = tokenId;

            // Store the stake information for the token ID
            idBipzyToStakeInfo[tokenId] = StakeInfo(
                msg.sender,
                tokenId,
                nftContractInstance,
                currentTimestamp,
                stakeEndsOn
            );

            // Emit the TokenStaked event
            emit BipzyTokenStaked(
                msg.sender,
                tokenId,
                nftContractInstance,
                currentTimestamp,
                stakeEndsOn
            );
        }
    }

    /**
     * @dev Allows the staking of BIPZY PASS tokens.
     * @param stakePreferences Array of `StakePreference` structs containing stake preferences.
     */
    function stakeBipzyPass(
        StakePreference[] calldata stakePreferences
    ) public {
        // Ensure that the caller owns at least one Bipzy or BipzyPass NFT
        if (i_bipzyPass.balanceOf(msg.sender) == 0)
            revert BPZ__MustOwn1NFTAtLeast();

        // Ensure that at least one stake preference is provided
        if (stakePreferences.length == 0)
            revert BPZ__ZeroStakePreferencesFound();

        uint32 currentTimestamp = uint32(block.timestamp);

        if(ownerToBipzyPassTokenIds[msg.sender][SENTINAL_TOKEN_ID] == 0) {
            ownerToBipzyPassTokenIds[msg.sender][SENTINAL_TOKEN_ID] = SENTINAL_TOKEN_ID;
        }

        // Iterate through the stake preferences and process each one
        for (uint i = 0; i < stakePreferences.length; i++) {
            StakePreference memory preference = stakePreferences[i];
            uint96 tokenId = preference.tokenId;
            uint32 duration = preference.stakeDuration;
            IERC721 nftContractInstance = preference.nftContract;

            // Ensure that the stake duration is either minDuration or maxDuration days
            if (duration != minDuration && duration != maxDuration)
                revert BPZ__InvalidStakeDuration();

            uint32 stakeEndsOn = currentTimestamp + duration;

            // Ensure that the NFT contract is either Bipzy or BipzyPass
            if (nftContractInstance != i_bipzyPass) {
                revert BPZ__NFTContractNotSupported();
            }
            // Transfer the NFT from the staker to the contract
            nftContractInstance.transferFrom(
                msg.sender,
                address(this),
                tokenId
            );

            // Update the linked list of token IDs for the staker
            ownerToBipzyPassTokenIds[msg.sender][tokenId] = ownerToBipzyPassTokenIds[msg.sender][SENTINAL_TOKEN_ID];
            ownerToBipzyPassTokenIds[msg.sender][SENTINAL_TOKEN_ID] = tokenId;

            // Store the stake information for the token ID
            idBipzyPassToStakeInfo[tokenId] = StakeInfo(
                msg.sender,
                tokenId,
                nftContractInstance,
                currentTimestamp,
                stakeEndsOn
            );

            // Emit the TokenStaked event
            emit BipzyPassTokenStaked(
                msg.sender,
                tokenId,
                nftContractInstance,
                currentTimestamp,
                stakeEndsOn
            );
        }
    }

    /**
     * @dev Allows the withdrawal of stakes for BIPZY tokens.
     * @param stakeWithdrawalPreferences Array of `StakeWithdrawalPreference` structs containing withdrawal preferences.
     */
    function stakeBipzyWithdrawal(
        StakeWithdrawalPreference[] calldata stakeWithdrawalPreferences
    ) public {
        // Iterate through the withdrawal preferences
        for (uint96 i = 0; i < stakeWithdrawalPreferences.length; i++) {
            uint96 tokenId = stakeWithdrawalPreferences[i].tokenId;
            uint96 prevId = stakeWithdrawalPreferences[i].prevTokenId;
            StakeInfo memory stakeInfo = idBipzyToStakeInfo[tokenId];
            IERC721 stakedContractInstance = stakeInfo.tokenContract;

            // Ensure that the caller is the staker of the token
            if (stakeInfo.staker != msg.sender)
                revert BPZ__OnlyStakerCanWithdrawTheirStake();
            if (ownerToBipzyTokenIds[msg.sender][prevId] != tokenId)
                revert BPZ__InvalidPrevId();

            // Ensure that the stake period is over
            if (block.timestamp < stakeInfo.stakeEndsOn)
                revert BPZ__StakePeriodNotOver();

            // Update the linked list of token IDs for the staker
            ownerToBipzyTokenIds[msg.sender][prevId] = ownerToBipzyTokenIds[
                msg.sender
            ][tokenId];

            // Delete this token ID from the linked list
            delete ownerToBipzyTokenIds[msg.sender][tokenId];

            // Delete the stake information for the token ID
            delete idBipzyToStakeInfo[tokenId];

            // Transfer the NFT back to the staker
            stakedContractInstance.transferFrom(
                address(this),
                msg.sender,
                tokenId
            );

            // Emit the StakeWithdrawn event
            emit BipzyStakeWithdrawn(msg.sender, tokenId, stakedContractInstance);
        }
    }

    /**
     * @dev Allows the withdrawal of stakes for BIPZY PASS tokens.
     * @param stakeWithdrawalPreferences Array of `StakeWithdrawalPreference` structs containing withdrawal preferences.
     */
    function stakeBipzyPassWithdrawal(
        StakeWithdrawalPreference[] calldata stakeWithdrawalPreferences
    ) public {
        // Iterate through the withdrawal preferences
        for (uint96 i = 0; i < stakeWithdrawalPreferences.length; i++) {
            uint96 tokenId = stakeWithdrawalPreferences[i].tokenId;
            uint96 prevId = stakeWithdrawalPreferences[i].prevTokenId;
            StakeInfo memory stakeInfo = idBipzyPassToStakeInfo[tokenId];
            IERC721 stakedContractInstance = stakeInfo.tokenContract;

            // Ensure that the caller is the staker of the token
            if (stakeInfo.staker != msg.sender)
                revert BPZ__OnlyStakerCanWithdrawTheirStake();

            if (ownerToBipzyPassTokenIds[msg.sender][prevId] != tokenId)
                revert BPZ__InvalidPrevId();

            // Ensure that the stake period is over
            if (block.timestamp < stakeInfo.stakeEndsOn)
                revert BPZ__StakePeriodNotOver();

            // Update the linked list of token IDs for the staker
            ownerToBipzyPassTokenIds[msg.sender][
                prevId
            ] = ownerToBipzyPassTokenIds[msg.sender][tokenId];

            // Delete this token ID from the linked list
            delete ownerToBipzyPassTokenIds[msg.sender][tokenId];

            // Delete the stake information for the token ID
            delete idBipzyPassToStakeInfo[tokenId];

            // Transfer the NFT back to the staker
            stakedContractInstance.transferFrom(
                address(this),
                msg.sender,
                tokenId
            );

            // Emit the StakeWithdrawn event
            emit BipzyPassStakeWithdrawn(msg.sender, tokenId, stakedContractInstance);
        }
    }

    /**
     * @notice Retrieves the total booster amount for a given owner's BipzyPass stakes.
     * @param owner The address of the BipzyPass owner.
     * @return The total booster amount calculated based on the active BipzyPass stakes and their durations.
     */

    function getBipzyPassBoosterInfo(
        address owner
    ) internal view returns (uint256) {
        if (ownerToBipzyPassTokenIds[owner][SENTINAL_TOKEN_ID] != 0) {
            uint256 currentTokenId = ownerToBipzyPassTokenIds[owner][
                SENTINAL_TOKEN_ID
            ];

            uint256 prevId = SENTINAL_TOKEN_ID;
            uint32 _numDurationOneStakes;
            uint32 _numDurationTwoStakes;

            // Traverse the linked list of token IDs for the staker
            while (currentTokenId != SENTINAL_TOKEN_ID) {
                prevId = currentTokenId;

                uint64 stakeDuration = idBipzyPassToStakeInfo[prevId]
                    .stakeEndsOn -
                    idBipzyPassToStakeInfo[prevId].stakeStartedOn;

                // If the stake is still active, increment the respective counter
                if (
                    idBipzyPassToStakeInfo[prevId].stakeEndsOn > block.timestamp
                )
                    if (stakeDuration == minDuration) {
                        _numDurationOneStakes += 1;
                    } else {
                        _numDurationTwoStakes += 1;
                    }
                currentTokenId = ownerToBipzyPassTokenIds[owner][prevId];
            }

            // Calculate the total booster amount based on the stake durations
            uint256 totalBoosterAmount = (_numDurationOneStakes *
                boosterValueOne) + (_numDurationTwoStakes * boosterValueTwo);
            return totalBoosterAmount;
        } else {
            return 0;
        }
    }

    /**
     * @notice Retrieves the total booster amount for a given owner's Bipzy stakes.
     * @param owner The address of the Bipzy owner.
     * @return The total booster amount calculated based on the active Bipzy stakes and their durations.
     */
    function getBipzyBoosterInfo(
        address owner
    ) internal view returns (uint256) {
        if (ownerToBipzyTokenIds[owner][SENTINAL_TOKEN_ID] != 0) {
            uint256 currentTokenId = ownerToBipzyTokenIds[owner][
                SENTINAL_TOKEN_ID
            ];

            uint256 prevId = SENTINAL_TOKEN_ID;
            uint32 _numDurationOneStakes;
            uint32 _numDurationTwoStakes;

            // Traverse the linked list of token IDs for the staker
            while (currentTokenId != SENTINAL_TOKEN_ID) {
                prevId = currentTokenId;

                uint64 stakeDuration = idBipzyToStakeInfo[prevId].stakeEndsOn -
                    idBipzyToStakeInfo[prevId].stakeStartedOn;

                // If the stake is still active, increment the respective counter
                if (idBipzyToStakeInfo[prevId].stakeEndsOn > block.timestamp)
                    if (stakeDuration == minDuration) {
                        _numDurationOneStakes += 1;
                    } else {
                        _numDurationTwoStakes += 1;
                    }
                currentTokenId = ownerToBipzyTokenIds[owner][prevId];
            }

            // Calculate the total booster amount based on the stake durations
            uint256 totalBoosterAmount = (_numDurationOneStakes *
                boosterValueOne) + (_numDurationTwoStakes * boosterValueTwo);
            return totalBoosterAmount;
        } else {
            return 0;
        }
    }

    /* @notice Allows the contract owner to forcibly unstake one or more Bipzy NFTs.
     * @dev This function sets the `stakeEndsOn` timestamp of each specified token ID to the current block timestamp, effectively ending the stake.
     *      It emits a `ForceUnstaked` event for each token ID. This function can only be called by the contract owner.
     * @param _tokenIds An array of token IDs to be forcibly unstaked.
     */
    function forceUnstakeBipzy(uint96[] calldata _tokenIds) external onlyOwner {
        for(uint256 i; i<_tokenIds.length; i++) {
            idBipzyToStakeInfo[_tokenIds[i]].stakeEndsOn = uint32(block.timestamp);
            emit ForceUnstaked(_tokenIds[i]);
        }
    }

    /* @notice Allows the contract owner to forcibly unstake one or more Bipzy Pass NFTs.
     * @dev This function sets the `stakeEndsOn` timestamp of each specified token ID to the current block timestamp, effectively ending the stake.
     *      It emits a `ForceUnstaked` event for each token ID. This function can only be called by the contract owner.
     * @param _tokenIds An array of token IDs to be forcibly unstaked.
     */
    function forceUnstakeBipzyPass(uint96[] calldata _tokenIds) external onlyOwner {
        for(uint256 i; i<_tokenIds.length; i++) {
            idBipzyPassToStakeInfo[_tokenIds[i]].stakeEndsOn = uint32(block.timestamp);
            emit ForceUnstaked(_tokenIds[i]);
        }
    }

    /**
     * @notice Calculates the booster amount for a given staker based on their currently staked NFTs.
     * @dev The booster amount is calculated by traversing the linked list of token IDs and summing the booster values for each active stake.
     * @param owner The address of the staker for whom the booster amount is being calculated.
     * @return The total booster amount for the staker.
     */

    function getBoosterInfo(address owner) public view returns (uint256) {
        uint256 bipzyBoosterAmt = getBipzyBoosterInfo(owner);
        uint256 bipzyPassBoosterAmt = getBipzyPassBoosterInfo(owner);

        // Calculate the total booster amount based on the stake durations
        return bipzyBoosterAmt + bipzyPassBoosterAmt;
    }

    /**
     * @notice check if user has staked any rare token
     *      To get if a user is actively staking a rare NFT or not,
     *      check for each token ID in ownerToTokenIds linked list,
     *      if token ID is rare, then return true
     *      else return false
     * @param _account the account that needs to be checked
     */
    function isUserStakingRare(address _account) external view returns (bool) {
        uint256 currentTokenId = ownerToBipzyTokenIds[_account][
            SENTINAL_TOKEN_ID
        ];

        uint256 prevId = SENTINAL_TOKEN_ID;

        // Traverse the linked list of token IDs for the staker
        while (currentTokenId != SENTINAL_TOKEN_ID) {
            prevId = currentTokenId;

            // If the stake is still active, increment the respective counter
            if (
                idBipzyToStakeInfo[prevId].stakeEndsOn > block.timestamp &&
                idBipzyToStakeInfo[currentTokenId].tokenContract == i_bipzy &&
                rareTokenIds[currentTokenId]
            ) return true;

            currentTokenId = ownerToBipzyTokenIds[_account][prevId];
        }
        return false;
    }

    /**
     * @notice Only owner can update the token IDs that are rare
     * @dev by default rare token ID can only exist of Bipzy NFT and not for Bipzy Pass.
     * @param tokenId the token ID, that will be rare
     * @param isRare rare staus
     */
    function updateRareTokenId(uint96 tokenId, bool isRare) external onlyOwner {
        rareTokenIds[tokenId] = isRare;
    }

    /**
     * @notice Allows the owner to lock the contract instances (i_bipzy and i_bipzyPass).
     * @dev Once locked, the contract instances cannot be updated by calling setNewBipzyInstance or setNewBipzyPassInstance.
     */
    function lockContractInstances() public onlyOwner {
        contractInstancesLocked = true;
    }

    /**
     * @notice Updates the Bipzy NFT contract instance.
     * @param _newBipzyInstance The new Bipzy NFT contract instance.
     * @dev This function can only be called by the contract owner and if the contract instances are not locked.
     */
    function setNewBipzyInstance(IERC721 _newBipzyInstance) public onlyOwner {
        if (contractInstancesLocked) revert BPZ__ContractInstanceLocked();
        i_bipzy = _newBipzyInstance;
    }

    /**
     * @notice Updates the BipzyPass NFT contract instance.
     * @param _newBipzyPassInstance The new BipzyPass NFT contract instance.
     * @dev This function can only be called by the contract owner and if the contract instances are not locked.
     */
    function setNewBipzyPassInstance(
        IERC721 _newBipzyPassInstance
    ) public onlyOwner {
        if (contractInstancesLocked) revert BPZ__ContractInstanceLocked();

        i_bipzyPass = _newBipzyPassInstance;
    }

    /**
     * @notice Updates the minimum and maximum stake durations for the contract.
     * @dev This function can only be called by the contract owner.
     * @param _minDuration The new minimum stake duration in seconds.
     * @param _maxDuration The new maximum stake duration in seconds.
     */

    function setNewStakeDurations(
        uint64 _minDuration,
        uint64 _maxDuration
    ) public onlyOwner {
        minDuration = _minDuration;
        maxDuration = _maxDuration;
    }

    /**
     * @notice Updates the booster values for the two different stake durations.
     * @dev This function can only be called by the contract owner.
     * @param _boosterAmtOneEightyDays The new booster value for the 180-day stake duration.
     * @param _boosterAmtThreeSixtyDays The new booster value for the 360-day stake duration.
     */

    function setBoosterAmt(
        uint256 _boosterAmtOneEightyDays,
        uint256 _boosterAmtThreeSixtyDays
    ) public onlyOwner {
        boosterValueOne = _boosterAmtOneEightyDays;
        boosterValueTwo = _boosterAmtThreeSixtyDays;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. 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 {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

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

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol)

pragma solidity ^0.8.0;

import "../../utils/introspection/IERC165.sol";

/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721 is IERC165 {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
     * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
     * understand this adds an external call which potentially creates a reentrancy vulnerability.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 tokenId) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the caller.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool approved) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator) external view returns (bool);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)

pragma solidity ^0.8.0;

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

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

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

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * 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[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "metadata": {
    "useLiteralContent": true
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"contract IERC721","name":"bipzyNftAddr","type":"address"},{"internalType":"contract IERC721","name":"bipzyPassNftAddr","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"BPZ__ContractInstanceLocked","type":"error"},{"inputs":[],"name":"BPZ__InvalidPrevId","type":"error"},{"inputs":[],"name":"BPZ__InvalidStakeDuration","type":"error"},{"inputs":[],"name":"BPZ__MustOwn1NFTAtLeast","type":"error"},{"inputs":[],"name":"BPZ__NFTContractNotSupported","type":"error"},{"inputs":[],"name":"BPZ__OnlyStakerCanWithdrawTheirStake","type":"error"},{"inputs":[],"name":"BPZ__StakePeriodNotOver","type":"error"},{"inputs":[],"name":"BPZ__ZeroStakePreferencesFound","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":true,"internalType":"uint96","name":"tokenId","type":"uint96"},{"indexed":true,"internalType":"contract IERC721","name":"nftContractInstance","type":"address"}],"name":"BipzyPassStakeWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":true,"internalType":"uint96","name":"tokenId","type":"uint96"},{"indexed":true,"internalType":"contract IERC721","name":"nftContractInstance","type":"address"},{"indexed":false,"internalType":"uint32","name":"stakingStartedOn","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"stakingEndTimeStamp","type":"uint32"}],"name":"BipzyPassTokenStaked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":true,"internalType":"uint96","name":"tokenId","type":"uint96"},{"indexed":true,"internalType":"contract IERC721","name":"nftContractInstance","type":"address"}],"name":"BipzyStakeWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":true,"internalType":"uint96","name":"tokenId","type":"uint96"},{"indexed":true,"internalType":"contract IERC721","name":"nftContractInstance","type":"address"},{"indexed":false,"internalType":"uint32","name":"stakingStartedOn","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"stakingEndTimeStamp","type":"uint32"}],"name":"BipzyTokenStaked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint96","name":"tokenId","type":"uint96"}],"name":"ForceUnstaked","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"},{"inputs":[],"name":"SENTINAL_TOKEN_ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"boosterValueOne","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"boosterValueTwo","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contractInstancesLocked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint96[]","name":"_tokenIds","type":"uint96[]"}],"name":"forceUnstakeBipzy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint96[]","name":"_tokenIds","type":"uint96[]"}],"name":"forceUnstakeBipzyPass","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"getBoosterInfo","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"i_bipzy","outputs":[{"internalType":"contract IERC721","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"i_bipzyPass","outputs":[{"internalType":"contract IERC721","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"idBipzyPassToStakeInfo","outputs":[{"internalType":"address","name":"staker","type":"address"},{"internalType":"uint96","name":"tokenId","type":"uint96"},{"internalType":"contract IERC721","name":"tokenContract","type":"address"},{"internalType":"uint32","name":"stakeStartedOn","type":"uint32"},{"internalType":"uint32","name":"stakeEndsOn","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"idBipzyToStakeInfo","outputs":[{"internalType":"address","name":"staker","type":"address"},{"internalType":"uint96","name":"tokenId","type":"uint96"},{"internalType":"contract IERC721","name":"tokenContract","type":"address"},{"internalType":"uint32","name":"stakeStartedOn","type":"uint32"},{"internalType":"uint32","name":"stakeEndsOn","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"isUserStakingRare","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockContractInstances","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"maxDuration","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minDuration","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"ownerToBipzyPassTokenIds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"ownerToBipzyTokenIds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"rareTokenIds","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_boosterAmtOneEightyDays","type":"uint256"},{"internalType":"uint256","name":"_boosterAmtThreeSixtyDays","type":"uint256"}],"name":"setBoosterAmt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC721","name":"_newBipzyInstance","type":"address"}],"name":"setNewBipzyInstance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC721","name":"_newBipzyPassInstance","type":"address"}],"name":"setNewBipzyPassInstance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_minDuration","type":"uint64"},{"internalType":"uint64","name":"_maxDuration","type":"uint64"}],"name":"setNewStakeDurations","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint96","name":"tokenId","type":"uint96"},{"internalType":"uint32","name":"stakeDuration","type":"uint32"},{"internalType":"contract IERC721","name":"nftContract","type":"address"}],"internalType":"struct BipzyStaking.StakePreference[]","name":"stakePreferences","type":"tuple[]"}],"name":"stakeBipzy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint96","name":"tokenId","type":"uint96"},{"internalType":"uint32","name":"stakeDuration","type":"uint32"},{"internalType":"contract IERC721","name":"nftContract","type":"address"}],"internalType":"struct BipzyStaking.StakePreference[]","name":"stakePreferences","type":"tuple[]"}],"name":"stakeBipzyPass","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint96","name":"tokenId","type":"uint96"},{"internalType":"uint96","name":"prevTokenId","type":"uint96"}],"internalType":"struct BipzyStaking.StakeWithdrawalPreference[]","name":"stakeWithdrawalPreferences","type":"tuple[]"}],"name":"stakeBipzyPassWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint96","name":"tokenId","type":"uint96"},{"internalType":"uint96","name":"prevTokenId","type":"uint96"}],"internalType":"struct BipzyStaking.StakeWithdrawalPreference[]","name":"stakeWithdrawalPreferences","type":"tuple[]"}],"name":"stakeBipzyWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint96","name":"tokenId","type":"uint96"},{"internalType":"bool","name":"isRare","type":"bool"}],"name":"updateRareTokenId","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6080604052600280546176a760b01b600160a81b600160e81b0319909116179055600380546001600160401b03191662ed4e00179055612710600455613a986005553480156200004e57600080fd5b506040516200221938038062002219833981016040819052620000719162000122565b6200007c33620000b5565b600180546001600160a01b039384166001600160a01b0319909116179055600280546001600160a81b031916919092161790556200015a565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200011d57600080fd5b919050565b600080604083850312156200013657600080fd5b620001418362000105565b9150620001516020840162000105565b90509250929050565b6120af806200016a6000396000f3fe608060405234801561001057600080fd5b50600436106101da5760003560e01c806371b9fd6111610104578063a1375c50116100a2578063b9f6210111610071578063b9f6210114610502578063ba5a8bf81461052d578063d0e795071461053a578063f2fde38b1461054d57600080fd5b8063a1375c501461046a578063ab203aff1461047d578063b39df5ab14610491578063b7deb0a8146104a457600080fd5b8063897073d8116100de578063897073d81461040c5780638da5cb5b1461041f578063971ee4dd14610444578063a129f2401461045757600080fd5b806371b9fd61146103dd57806372801da7146103f05780637e8f2d64146103f957600080fd5b80632dafc7d11161017c5780635de622b21161014b5780635de622b2146103b1578063606c8bff146103ba5780636db5c8fd146103c2578063715018a6146103d557600080fd5b80632dafc7d1146102b15780633183341d146103595780634d91543b1461036c578063567157611461037f57600080fd5b80631531ca1e116101b85780631531ca1e14610245578063186e5cd1146102585780631880d9751461026b5780631ef451cc1461027e57600080fd5b8063014791de146101df57806307bd1bbf146101f45780630c2fa65f14610232575b600080fd5b6101f26101ed366004611c59565b610560565b005b61021f610202366004611ca1565b600860209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b6101f2610240366004611ccd565b6105a6565b6101f2610253366004611d41565b610690565b6101f2610266366004611da3565b610925565b6101f2610279366004611dc5565b610938565b6102a161028c366004611e27565b600a6020526000908152604090205460ff1681565b6040519015158152602001610229565b61030f6102bf366004611e27565b600760205260009081526040902080546001909101546001600160a01b03808316926001600160601b03600160a01b9182900416929182169163ffffffff918104821691600160c01b9091041685565b604080516001600160a01b0396871681526001600160601b039095166020860152949092169383019390935263ffffffff928316606083015291909116608082015260a001610229565b6101f2610367366004611e57565b610e03565b6101f261037a366004611dc5565b610e36565b60025461039990600160a81b90046001600160401b031681565b6040516001600160401b039091168152602001610229565b61021f60045481565b6101f26112fb565b600354610399906001600160401b031681565b6101f2611318565b6101f26103eb366004611e93565b61132c565b61021f60055481565b6102a1610407366004611e93565b611381565b6101f261041a366004611e93565b611469565b6000546001600160a01b03165b6040516001600160a01b039091168152602001610229565b60015461042c906001600160a01b031681565b61021f610465366004611e93565b6114be565b6101f2610478366004611ccd565b6114eb565b6002546102a190600160a01b900460ff1681565b60025461042c906001600160a01b031681565b61030f6104b2366004611e27565b600660205260009081526040902080546001909101546001600160a01b03808316926001600160601b03600160a01b9182900416929182169163ffffffff918104821691600160c01b9091041685565b61021f610510366004611ca1565b600960209081526000928352604080842090915290825290205481565b61021f654269707a797381565b6101f2610548366004611d41565b6115d0565b6101f261055b366004611e93565b611865565b6105686118e3565b6002805467ffffffffffffffff60a81b1916600160a81b6001600160401b03948516021790556003805467ffffffffffffffff191691909216179055565b6105ae6118e3565b60005b8181101561068b5742600660008585858181106105d0576105d0611eb7565b90506020020160208101906105e59190611ecd565b6001600160601b0316815260200190815260200160002060010160186101000a81548163ffffffff021916908363ffffffff16021790555082828281811061062f5761062f611eb7565b90506020020160208101906106449190611ecd565b6001600160601b03167f6c2ef1438dd75e78dd0aa0f478d96a44c46afcd0011c7444ea53bf1e3e9c719f60405160405180910390a28061068381611efe565b9150506105b1565b505050565b60005b6001600160601b03811682111561068b5760008383836001600160601b03168181106106c1576106c1611eb7565b6106d79260206040909202019081019150611ecd565b905060008484846001600160601b03168181106106f6576106f6611eb7565b905060400201602001602081019061070e9190611ecd565b6001600160601b03808416600090815260076020908152604091829020825160a08101845281546001600160a01b03808216808452600160a01b928390049097169483019490945260019092015492831693810184905263ffffffff91830482166060820152600160c01b9092041660808201529293509033146107a557604051634034681b60e11b815260040160405180910390fd5b3360009081526009602090815260408083206001600160601b038781168552925290912054908516146107eb57604051635f443bd360e11b815260040160405180910390fd5b816080015163ffffffff1642101561081657604051636b5392e160e11b815260040160405180910390fd5b3360008181526009602090815260408083206001600160601b038981168086529184528285208054918a16865283862091909155908452839055600790915280822091825560019190910180546001600160e01b0319169055516323b872dd60e01b81526001600160a01b038316916323b872dd9161089b9130918990600401611f17565b600060405180830381600087803b1580156108b557600080fd5b505af11580156108c9573d6000803e3d6000fd5b50506040516001600160a01b03841692506001600160601b038716915033907fa9c00eac62925bfb81cb9a27fedacafc2feaf1b0689acd470d25a7eba5b84e3890600090a450505050808061091d90611f43565b915050610693565b61092d6118e3565b600491909155600555565b6002546040516370a0823160e01b81523360048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015610980573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109a49190611f69565b6000036109c45760405163025424a760e21b815260040160405180910390fd5b60008190036109e65760405163032347e560e41b815260040160405180910390fd5b336000908152600960209081526040808320654269707a79738452909152812054429103610a3157336000908152600960209081526040808320654269707a79738085529252909120555b60005b82811015610dfd576000848483818110610a5057610a50611eb7565b905060600201803603810190610a669190611f82565b8051602082015160408301516002549394509192909190600160a81b90046001600160401b031663ffffffff831614801590610ab357506003546001600160401b031663ffffffff831614155b15610ad1576040516328b87a9f60e21b815260040160405180910390fd5b6000610add8388612008565b6002549091506001600160a01b03838116911614610b0e57604051633819b0f960e11b815260040160405180910390fd5b6040516323b872dd60e01b81526001600160a01b038316906323b872dd90610b3e90339030908990600401611f17565b600060405180830381600087803b158015610b5857600080fd5b505af1158015610b6c573d6000803e3d6000fd5b5050505060096000336001600160a01b03166001600160a01b031681526020019081526020016000206000654269707a797381526020019081526020016000205460096000336001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160601b0316815260200190815260200160002081905550836001600160601b031660096000336001600160a01b03166001600160a01b031681526020019081526020016000206000654269707a79738152602001908152602001600020819055506040518060a00160405280336001600160a01b03168152602001856001600160601b03168152602001836001600160a01b031681526020018863ffffffff1681526020018263ffffffff1681525060076000866001600160601b0316815260200190815260200160002060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060208201518160000160146101000a8154816001600160601b0302191690836001600160601b0316021790555060408201518160010160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060608201518160010160146101000a81548163ffffffff021916908363ffffffff16021790555060808201518160010160186101000a81548163ffffffff021916908363ffffffff160217905550905050816001600160a01b0316846001600160601b0316336001600160a01b03167f251409c55fd348c21f2145bb5c67fa6833d0504ffb3fa77b7653eef1928d9d178a85604051610ddd92919063ffffffff92831681529116602082015260400190565b60405180910390a450505050508080610df590611efe565b915050610a34565b50505050565b610e0b6118e3565b6001600160601b03919091166000908152600a60205260409020805460ff1916911515919091179055565b6001546040516370a0823160e01b81523360048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015610e7e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea29190611f69565b600003610ec25760405163025424a760e21b815260040160405180910390fd5b6000819003610ee45760405163032347e560e41b815260040160405180910390fd5b336000908152600860209081526040808320654269707a79738452909152812054429103610f2f57336000908152600860209081526040808320654269707a79738085529252909120555b60005b82811015610dfd576000848483818110610f4e57610f4e611eb7565b905060600201803603810190610f649190611f82565b8051602082015160408301516002549394509192909190600160a81b90046001600160401b031663ffffffff831614801590610fb157506003546001600160401b031663ffffffff831614155b15610fcf576040516328b87a9f60e21b815260040160405180910390fd5b6000610fdb8388612008565b6001549091506001600160a01b0383811691161461100c57604051633819b0f960e11b815260040160405180910390fd5b6040516323b872dd60e01b81526001600160a01b038316906323b872dd9061103c90339030908990600401611f17565b600060405180830381600087803b15801561105657600080fd5b505af115801561106a573d6000803e3d6000fd5b5050505060086000336001600160a01b03166001600160a01b031681526020019081526020016000206000654269707a797381526020019081526020016000205460086000336001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160601b0316815260200190815260200160002081905550836001600160601b031660086000336001600160a01b03166001600160a01b031681526020019081526020016000206000654269707a79738152602001908152602001600020819055506040518060a00160405280336001600160a01b03168152602001856001600160601b03168152602001836001600160a01b031681526020018863ffffffff1681526020018263ffffffff1681525060066000866001600160601b0316815260200190815260200160002060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060208201518160000160146101000a8154816001600160601b0302191690836001600160601b0316021790555060408201518160010160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060608201518160010160146101000a81548163ffffffff021916908363ffffffff16021790555060808201518160010160186101000a81548163ffffffff021916908363ffffffff160217905550905050816001600160a01b0316846001600160601b0316336001600160a01b03167f1ba3ac0797485a7aaad6e0b3dad139d548f6fed17d9ba452985ce5ca184df1b28a856040516112db92919063ffffffff92831681529116602082015260400190565b60405180910390a4505050505080806112f390611efe565b915050610f32565b6113036118e3565b6002805460ff60a01b1916600160a01b179055565b6113206118e3565b61132a600061193d565b565b6113346118e3565b600254600160a01b900460ff161561135f5760405163682b001b60e11b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0381166000908152600860209081526040808320654269707a79738085529252822054905b654269707a7973821461145f5750600081815260066020526040902060010154819042600160c01b90910463ffffffff1611801561140b5750600180546000848152600660205260409020909101546001600160a01b039081169116145b801561142557506000828152600a602052604090205460ff165b15611434575060019392505050565b6001600160a01b038416600090815260086020908152604080832084845290915290205491506113ad565b5060009392505050565b6114716118e3565b600254600160a01b900460ff161561149c5760405163682b001b60e11b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000806114ca8361198d565b905060006114d784611b0d565b90506114e3818361202c565b949350505050565b6114f36118e3565b60005b8181101561068b57426007600085858581811061151557611515611eb7565b905060200201602081019061152a9190611ecd565b6001600160601b0316815260200190815260200160002060010160186101000a81548163ffffffff021916908363ffffffff16021790555082828281811061157457611574611eb7565b90506020020160208101906115899190611ecd565b6001600160601b03167f6c2ef1438dd75e78dd0aa0f478d96a44c46afcd0011c7444ea53bf1e3e9c719f60405160405180910390a2806115c881611efe565b9150506114f6565b60005b6001600160601b03811682111561068b5760008383836001600160601b031681811061160157611601611eb7565b6116179260206040909202019081019150611ecd565b905060008484846001600160601b031681811061163657611636611eb7565b905060400201602001602081019061164e9190611ecd565b6001600160601b03808416600090815260066020908152604091829020825160a08101845281546001600160a01b03808216808452600160a01b928390049097169483019490945260019092015492831693810184905263ffffffff91830482166060820152600160c01b9092041660808201529293509033146116e557604051634034681b60e11b815260040160405180910390fd5b3360009081526008602090815260408083206001600160601b0387811685529252909120549085161461172b57604051635f443bd360e11b815260040160405180910390fd5b816080015163ffffffff1642101561175657604051636b5392e160e11b815260040160405180910390fd5b3360008181526008602090815260408083206001600160601b038981168086529184528285208054918a16865283862091909155908452839055600690915280822091825560019190910180546001600160e01b0319169055516323b872dd60e01b81526001600160a01b038316916323b872dd916117db9130918990600401611f17565b600060405180830381600087803b1580156117f557600080fd5b505af1158015611809573d6000803e3d6000fd5b50506040516001600160a01b03841692506001600160601b038716915033907fda2acc593fbdc9291ef26593fb641ac7eefe393b403350eafb901aa9db1e911590600090a450505050808061185d90611f43565b9150506115d3565b61186d6118e3565b6001600160a01b0381166118d75760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b6118e08161193d565b50565b6000546001600160a01b0316331461132a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016118ce565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b0381166000908152600860209081526040808320654269707a7973845290915281205415611b00576001600160a01b0382166000908152600860209081526040808320654269707a7973808552925282205491805b654269707a79738414611ac257600084815260066020526040812060010154859450611a2b9063ffffffff600160a01b8204811691600160c01b900416612045565b60008581526006602052604090206001015463ffffffff918216925042600160c01b9091049091161115611a96576002546001600160401b03600160a81b909104811690821603611a8857611a81600184612008565b9250611a96565b611a93600183612008565b91505b506001600160a01b038616600090815260086020908152604080832086845290915290205493506119e9565b60006005548263ffffffff16611ad89190612062565b600454611aeb9063ffffffff8616612062565b611af5919061202c565b979650505050505050565b506000919050565b919050565b6001600160a01b0381166000908152600960209081526040808320654269707a7973845290915281205415611b00576001600160a01b0382166000908152600960209081526040808320654269707a7973808552925282205491805b654269707a79738414611ac257600084815260076020526040812060010154859450611bab9063ffffffff600160a01b8204811691600160c01b900416612045565b60008581526007602052604090206001015463ffffffff918216925042600160c01b9091049091161115611c16576002546001600160401b03600160a81b909104811690821603611c0857611c01600184612008565b9250611c16565b611c13600183612008565b91505b506001600160a01b03861660009081526009602090815260408083208684529091529020549350611b69565b80356001600160401b0381168114611b0857600080fd5b60008060408385031215611c6c57600080fd5b611c7583611c42565b9150611c8360208401611c42565b90509250929050565b6001600160a01b03811681146118e057600080fd5b60008060408385031215611cb457600080fd5b8235611cbf81611c8c565b946020939093013593505050565b60008060208385031215611ce057600080fd5b82356001600160401b0380821115611cf757600080fd5b818501915085601f830112611d0b57600080fd5b813581811115611d1a57600080fd5b8660208260051b8501011115611d2f57600080fd5b60209290920196919550909350505050565b60008060208385031215611d5457600080fd5b82356001600160401b0380821115611d6b57600080fd5b818501915085601f830112611d7f57600080fd5b813581811115611d8e57600080fd5b8660208260061b8501011115611d2f57600080fd5b60008060408385031215611db657600080fd5b50508035926020909101359150565b60008060208385031215611dd857600080fd5b82356001600160401b0380821115611def57600080fd5b818501915085601f830112611e0357600080fd5b813581811115611e1257600080fd5b866020606083028501011115611d2f57600080fd5b600060208284031215611e3957600080fd5b5035919050565b80356001600160601b0381168114611b0857600080fd5b60008060408385031215611e6a57600080fd5b611e7383611e40565b915060208301358015158114611e8857600080fd5b809150509250929050565b600060208284031215611ea557600080fd5b8135611eb081611c8c565b9392505050565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611edf57600080fd5b611eb082611e40565b634e487b7160e01b600052601160045260246000fd5b600060018201611f1057611f10611ee8565b5060010190565b6001600160a01b0393841681529190921660208201526001600160601b03909116604082015260600190565b60006001600160601b03808316818103611f5f57611f5f611ee8565b6001019392505050565b600060208284031215611f7b57600080fd5b5051919050565b600060608284031215611f9457600080fd5b604051606081018181106001600160401b0382111715611fc457634e487b7160e01b600052604160045260246000fd5b604052611fd083611e40565b8152602083013563ffffffff81168114611fe957600080fd5b60208201526040830135611ffc81611c8c565b60408201529392505050565b63ffffffff81811683821601908082111561202557612025611ee8565b5092915050565b8082018082111561203f5761203f611ee8565b92915050565b63ffffffff82811682821603908082111561202557612025611ee8565b808202811582820484141761203f5761203f611ee856fea2646970667358221220ae90577831f15a7893b6a66a558720a297d7d9031747c6c1252a9e6f5325412864736f6c63430008110033000000000000000000000000bc4aaade7af26ef4de733cf23dc31705d1f499ec0000000000000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101da5760003560e01c806371b9fd6111610104578063a1375c50116100a2578063b9f6210111610071578063b9f6210114610502578063ba5a8bf81461052d578063d0e795071461053a578063f2fde38b1461054d57600080fd5b8063a1375c501461046a578063ab203aff1461047d578063b39df5ab14610491578063b7deb0a8146104a457600080fd5b8063897073d8116100de578063897073d81461040c5780638da5cb5b1461041f578063971ee4dd14610444578063a129f2401461045757600080fd5b806371b9fd61146103dd57806372801da7146103f05780637e8f2d64146103f957600080fd5b80632dafc7d11161017c5780635de622b21161014b5780635de622b2146103b1578063606c8bff146103ba5780636db5c8fd146103c2578063715018a6146103d557600080fd5b80632dafc7d1146102b15780633183341d146103595780634d91543b1461036c578063567157611461037f57600080fd5b80631531ca1e116101b85780631531ca1e14610245578063186e5cd1146102585780631880d9751461026b5780631ef451cc1461027e57600080fd5b8063014791de146101df57806307bd1bbf146101f45780630c2fa65f14610232575b600080fd5b6101f26101ed366004611c59565b610560565b005b61021f610202366004611ca1565b600860209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b6101f2610240366004611ccd565b6105a6565b6101f2610253366004611d41565b610690565b6101f2610266366004611da3565b610925565b6101f2610279366004611dc5565b610938565b6102a161028c366004611e27565b600a6020526000908152604090205460ff1681565b6040519015158152602001610229565b61030f6102bf366004611e27565b600760205260009081526040902080546001909101546001600160a01b03808316926001600160601b03600160a01b9182900416929182169163ffffffff918104821691600160c01b9091041685565b604080516001600160a01b0396871681526001600160601b039095166020860152949092169383019390935263ffffffff928316606083015291909116608082015260a001610229565b6101f2610367366004611e57565b610e03565b6101f261037a366004611dc5565b610e36565b60025461039990600160a81b90046001600160401b031681565b6040516001600160401b039091168152602001610229565b61021f60045481565b6101f26112fb565b600354610399906001600160401b031681565b6101f2611318565b6101f26103eb366004611e93565b61132c565b61021f60055481565b6102a1610407366004611e93565b611381565b6101f261041a366004611e93565b611469565b6000546001600160a01b03165b6040516001600160a01b039091168152602001610229565b60015461042c906001600160a01b031681565b61021f610465366004611e93565b6114be565b6101f2610478366004611ccd565b6114eb565b6002546102a190600160a01b900460ff1681565b60025461042c906001600160a01b031681565b61030f6104b2366004611e27565b600660205260009081526040902080546001909101546001600160a01b03808316926001600160601b03600160a01b9182900416929182169163ffffffff918104821691600160c01b9091041685565b61021f610510366004611ca1565b600960209081526000928352604080842090915290825290205481565b61021f654269707a797381565b6101f2610548366004611d41565b6115d0565b6101f261055b366004611e93565b611865565b6105686118e3565b6002805467ffffffffffffffff60a81b1916600160a81b6001600160401b03948516021790556003805467ffffffffffffffff191691909216179055565b6105ae6118e3565b60005b8181101561068b5742600660008585858181106105d0576105d0611eb7565b90506020020160208101906105e59190611ecd565b6001600160601b0316815260200190815260200160002060010160186101000a81548163ffffffff021916908363ffffffff16021790555082828281811061062f5761062f611eb7565b90506020020160208101906106449190611ecd565b6001600160601b03167f6c2ef1438dd75e78dd0aa0f478d96a44c46afcd0011c7444ea53bf1e3e9c719f60405160405180910390a28061068381611efe565b9150506105b1565b505050565b60005b6001600160601b03811682111561068b5760008383836001600160601b03168181106106c1576106c1611eb7565b6106d79260206040909202019081019150611ecd565b905060008484846001600160601b03168181106106f6576106f6611eb7565b905060400201602001602081019061070e9190611ecd565b6001600160601b03808416600090815260076020908152604091829020825160a08101845281546001600160a01b03808216808452600160a01b928390049097169483019490945260019092015492831693810184905263ffffffff91830482166060820152600160c01b9092041660808201529293509033146107a557604051634034681b60e11b815260040160405180910390fd5b3360009081526009602090815260408083206001600160601b038781168552925290912054908516146107eb57604051635f443bd360e11b815260040160405180910390fd5b816080015163ffffffff1642101561081657604051636b5392e160e11b815260040160405180910390fd5b3360008181526009602090815260408083206001600160601b038981168086529184528285208054918a16865283862091909155908452839055600790915280822091825560019190910180546001600160e01b0319169055516323b872dd60e01b81526001600160a01b038316916323b872dd9161089b9130918990600401611f17565b600060405180830381600087803b1580156108b557600080fd5b505af11580156108c9573d6000803e3d6000fd5b50506040516001600160a01b03841692506001600160601b038716915033907fa9c00eac62925bfb81cb9a27fedacafc2feaf1b0689acd470d25a7eba5b84e3890600090a450505050808061091d90611f43565b915050610693565b61092d6118e3565b600491909155600555565b6002546040516370a0823160e01b81523360048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015610980573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109a49190611f69565b6000036109c45760405163025424a760e21b815260040160405180910390fd5b60008190036109e65760405163032347e560e41b815260040160405180910390fd5b336000908152600960209081526040808320654269707a79738452909152812054429103610a3157336000908152600960209081526040808320654269707a79738085529252909120555b60005b82811015610dfd576000848483818110610a5057610a50611eb7565b905060600201803603810190610a669190611f82565b8051602082015160408301516002549394509192909190600160a81b90046001600160401b031663ffffffff831614801590610ab357506003546001600160401b031663ffffffff831614155b15610ad1576040516328b87a9f60e21b815260040160405180910390fd5b6000610add8388612008565b6002549091506001600160a01b03838116911614610b0e57604051633819b0f960e11b815260040160405180910390fd5b6040516323b872dd60e01b81526001600160a01b038316906323b872dd90610b3e90339030908990600401611f17565b600060405180830381600087803b158015610b5857600080fd5b505af1158015610b6c573d6000803e3d6000fd5b5050505060096000336001600160a01b03166001600160a01b031681526020019081526020016000206000654269707a797381526020019081526020016000205460096000336001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160601b0316815260200190815260200160002081905550836001600160601b031660096000336001600160a01b03166001600160a01b031681526020019081526020016000206000654269707a79738152602001908152602001600020819055506040518060a00160405280336001600160a01b03168152602001856001600160601b03168152602001836001600160a01b031681526020018863ffffffff1681526020018263ffffffff1681525060076000866001600160601b0316815260200190815260200160002060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060208201518160000160146101000a8154816001600160601b0302191690836001600160601b0316021790555060408201518160010160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060608201518160010160146101000a81548163ffffffff021916908363ffffffff16021790555060808201518160010160186101000a81548163ffffffff021916908363ffffffff160217905550905050816001600160a01b0316846001600160601b0316336001600160a01b03167f251409c55fd348c21f2145bb5c67fa6833d0504ffb3fa77b7653eef1928d9d178a85604051610ddd92919063ffffffff92831681529116602082015260400190565b60405180910390a450505050508080610df590611efe565b915050610a34565b50505050565b610e0b6118e3565b6001600160601b03919091166000908152600a60205260409020805460ff1916911515919091179055565b6001546040516370a0823160e01b81523360048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015610e7e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea29190611f69565b600003610ec25760405163025424a760e21b815260040160405180910390fd5b6000819003610ee45760405163032347e560e41b815260040160405180910390fd5b336000908152600860209081526040808320654269707a79738452909152812054429103610f2f57336000908152600860209081526040808320654269707a79738085529252909120555b60005b82811015610dfd576000848483818110610f4e57610f4e611eb7565b905060600201803603810190610f649190611f82565b8051602082015160408301516002549394509192909190600160a81b90046001600160401b031663ffffffff831614801590610fb157506003546001600160401b031663ffffffff831614155b15610fcf576040516328b87a9f60e21b815260040160405180910390fd5b6000610fdb8388612008565b6001549091506001600160a01b0383811691161461100c57604051633819b0f960e11b815260040160405180910390fd5b6040516323b872dd60e01b81526001600160a01b038316906323b872dd9061103c90339030908990600401611f17565b600060405180830381600087803b15801561105657600080fd5b505af115801561106a573d6000803e3d6000fd5b5050505060086000336001600160a01b03166001600160a01b031681526020019081526020016000206000654269707a797381526020019081526020016000205460086000336001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160601b0316815260200190815260200160002081905550836001600160601b031660086000336001600160a01b03166001600160a01b031681526020019081526020016000206000654269707a79738152602001908152602001600020819055506040518060a00160405280336001600160a01b03168152602001856001600160601b03168152602001836001600160a01b031681526020018863ffffffff1681526020018263ffffffff1681525060066000866001600160601b0316815260200190815260200160002060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060208201518160000160146101000a8154816001600160601b0302191690836001600160601b0316021790555060408201518160010160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060608201518160010160146101000a81548163ffffffff021916908363ffffffff16021790555060808201518160010160186101000a81548163ffffffff021916908363ffffffff160217905550905050816001600160a01b0316846001600160601b0316336001600160a01b03167f1ba3ac0797485a7aaad6e0b3dad139d548f6fed17d9ba452985ce5ca184df1b28a856040516112db92919063ffffffff92831681529116602082015260400190565b60405180910390a4505050505080806112f390611efe565b915050610f32565b6113036118e3565b6002805460ff60a01b1916600160a01b179055565b6113206118e3565b61132a600061193d565b565b6113346118e3565b600254600160a01b900460ff161561135f5760405163682b001b60e11b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0381166000908152600860209081526040808320654269707a79738085529252822054905b654269707a7973821461145f5750600081815260066020526040902060010154819042600160c01b90910463ffffffff1611801561140b5750600180546000848152600660205260409020909101546001600160a01b039081169116145b801561142557506000828152600a602052604090205460ff165b15611434575060019392505050565b6001600160a01b038416600090815260086020908152604080832084845290915290205491506113ad565b5060009392505050565b6114716118e3565b600254600160a01b900460ff161561149c5760405163682b001b60e11b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000806114ca8361198d565b905060006114d784611b0d565b90506114e3818361202c565b949350505050565b6114f36118e3565b60005b8181101561068b57426007600085858581811061151557611515611eb7565b905060200201602081019061152a9190611ecd565b6001600160601b0316815260200190815260200160002060010160186101000a81548163ffffffff021916908363ffffffff16021790555082828281811061157457611574611eb7565b90506020020160208101906115899190611ecd565b6001600160601b03167f6c2ef1438dd75e78dd0aa0f478d96a44c46afcd0011c7444ea53bf1e3e9c719f60405160405180910390a2806115c881611efe565b9150506114f6565b60005b6001600160601b03811682111561068b5760008383836001600160601b031681811061160157611601611eb7565b6116179260206040909202019081019150611ecd565b905060008484846001600160601b031681811061163657611636611eb7565b905060400201602001602081019061164e9190611ecd565b6001600160601b03808416600090815260066020908152604091829020825160a08101845281546001600160a01b03808216808452600160a01b928390049097169483019490945260019092015492831693810184905263ffffffff91830482166060820152600160c01b9092041660808201529293509033146116e557604051634034681b60e11b815260040160405180910390fd5b3360009081526008602090815260408083206001600160601b0387811685529252909120549085161461172b57604051635f443bd360e11b815260040160405180910390fd5b816080015163ffffffff1642101561175657604051636b5392e160e11b815260040160405180910390fd5b3360008181526008602090815260408083206001600160601b038981168086529184528285208054918a16865283862091909155908452839055600690915280822091825560019190910180546001600160e01b0319169055516323b872dd60e01b81526001600160a01b038316916323b872dd916117db9130918990600401611f17565b600060405180830381600087803b1580156117f557600080fd5b505af1158015611809573d6000803e3d6000fd5b50506040516001600160a01b03841692506001600160601b038716915033907fda2acc593fbdc9291ef26593fb641ac7eefe393b403350eafb901aa9db1e911590600090a450505050808061185d90611f43565b9150506115d3565b61186d6118e3565b6001600160a01b0381166118d75760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b6118e08161193d565b50565b6000546001600160a01b0316331461132a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016118ce565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b0381166000908152600860209081526040808320654269707a7973845290915281205415611b00576001600160a01b0382166000908152600860209081526040808320654269707a7973808552925282205491805b654269707a79738414611ac257600084815260066020526040812060010154859450611a2b9063ffffffff600160a01b8204811691600160c01b900416612045565b60008581526006602052604090206001015463ffffffff918216925042600160c01b9091049091161115611a96576002546001600160401b03600160a81b909104811690821603611a8857611a81600184612008565b9250611a96565b611a93600183612008565b91505b506001600160a01b038616600090815260086020908152604080832086845290915290205493506119e9565b60006005548263ffffffff16611ad89190612062565b600454611aeb9063ffffffff8616612062565b611af5919061202c565b979650505050505050565b506000919050565b919050565b6001600160a01b0381166000908152600960209081526040808320654269707a7973845290915281205415611b00576001600160a01b0382166000908152600960209081526040808320654269707a7973808552925282205491805b654269707a79738414611ac257600084815260076020526040812060010154859450611bab9063ffffffff600160a01b8204811691600160c01b900416612045565b60008581526007602052604090206001015463ffffffff918216925042600160c01b9091049091161115611c16576002546001600160401b03600160a81b909104811690821603611c0857611c01600184612008565b9250611c16565b611c13600183612008565b91505b506001600160a01b03861660009081526009602090815260408083208684529091529020549350611b69565b80356001600160401b0381168114611b0857600080fd5b60008060408385031215611c6c57600080fd5b611c7583611c42565b9150611c8360208401611c42565b90509250929050565b6001600160a01b03811681146118e057600080fd5b60008060408385031215611cb457600080fd5b8235611cbf81611c8c565b946020939093013593505050565b60008060208385031215611ce057600080fd5b82356001600160401b0380821115611cf757600080fd5b818501915085601f830112611d0b57600080fd5b813581811115611d1a57600080fd5b8660208260051b8501011115611d2f57600080fd5b60209290920196919550909350505050565b60008060208385031215611d5457600080fd5b82356001600160401b0380821115611d6b57600080fd5b818501915085601f830112611d7f57600080fd5b813581811115611d8e57600080fd5b8660208260061b8501011115611d2f57600080fd5b60008060408385031215611db657600080fd5b50508035926020909101359150565b60008060208385031215611dd857600080fd5b82356001600160401b0380821115611def57600080fd5b818501915085601f830112611e0357600080fd5b813581811115611e1257600080fd5b866020606083028501011115611d2f57600080fd5b600060208284031215611e3957600080fd5b5035919050565b80356001600160601b0381168114611b0857600080fd5b60008060408385031215611e6a57600080fd5b611e7383611e40565b915060208301358015158114611e8857600080fd5b809150509250929050565b600060208284031215611ea557600080fd5b8135611eb081611c8c565b9392505050565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611edf57600080fd5b611eb082611e40565b634e487b7160e01b600052601160045260246000fd5b600060018201611f1057611f10611ee8565b5060010190565b6001600160a01b0393841681529190921660208201526001600160601b03909116604082015260600190565b60006001600160601b03808316818103611f5f57611f5f611ee8565b6001019392505050565b600060208284031215611f7b57600080fd5b5051919050565b600060608284031215611f9457600080fd5b604051606081018181106001600160401b0382111715611fc457634e487b7160e01b600052604160045260246000fd5b604052611fd083611e40565b8152602083013563ffffffff81168114611fe957600080fd5b60208201526040830135611ffc81611c8c565b60408201529392505050565b63ffffffff81811683821601908082111561202557612025611ee8565b5092915050565b8082018082111561203f5761203f611ee8565b92915050565b63ffffffff82811682821603908082111561202557612025611ee8565b808202811582820484141761203f5761203f611ee856fea2646970667358221220ae90577831f15a7893b6a66a558720a297d7d9031747c6c1252a9e6f5325412864736f6c63430008110033

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

000000000000000000000000bc4aaade7af26ef4de733cf23dc31705d1f499ec0000000000000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : bipzyNftAddr (address): 0xbc4aaADe7AF26ef4dE733CF23Dc31705D1f499ec
Arg [1] : bipzyPassNftAddr (address): 0x0000000000000000000000000000000000000000

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000bc4aaade7af26ef4de733cf23dc31705d1f499ec
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000000


Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ 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.