ETH Price: $3,040.65 (-2.34%)
 

Overview

ETH Balance

0 ETH

ETH Value

$0.00

Token Holdings

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Sell Token383160792025-11-17 23:18:251 hr ago1763421505IN
friend.tech: Clubs
0 ETH0.000000620.00868752
Sell Token383160692025-11-17 23:18:052 hrs ago1763421485IN
friend.tech: Clubs
0 ETH0.000001180.01083096
Sell Token383062492025-11-17 17:50:457 hrs ago1763401845IN
friend.tech: Clubs
0 ETH0.000004890.04435543
Sell Token382942032025-11-17 11:09:1314 hrs ago1763377753IN
friend.tech: Clubs
0 ETH0.000000170.00235852
Sell Token382941722025-11-17 11:08:1114 hrs ago1763377691IN
friend.tech: Clubs
0 ETH0.000000150.00143235
Sell Token382279782025-11-15 22:21:432 days ago1763245303IN
friend.tech: Clubs
0 ETH0.000000310.00295306
Sell Token382279452025-11-15 22:20:372 days ago1763245237IN
friend.tech: Clubs
0 ETH0.000000330.00321429
Sell Token382166972025-11-15 16:05:412 days ago1763222741IN
friend.tech: Clubs
0 ETH0.000000270.002569
Sell Token382166842025-11-15 16:05:152 days ago1763222715IN
friend.tech: Clubs
0 ETH0.000000270.00263039
Sell Token382166782025-11-15 16:05:032 days ago1763222703IN
friend.tech: Clubs
0 ETH0.000000380.002641
Claim Referral F...382166412025-11-15 16:03:492 days ago1763222629IN
friend.tech: Clubs
0 ETH0.000000140.00256109
Sell Token382166192025-11-15 16:03:052 days ago1763222585IN
friend.tech: Clubs
0 ETH0.000000260.00248195
Sell Token382166162025-11-15 16:02:592 days ago1763222579IN
friend.tech: Clubs
0 ETH0.000000270.00246422
Sell Token382166132025-11-15 16:02:532 days ago1763222573IN
friend.tech: Clubs
0 ETH0.000000270.00250374
Sell Token382166082025-11-15 16:02:432 days ago1763222563IN
friend.tech: Clubs
0 ETH0.000000270.00251517
Sell Token382166052025-11-15 16:02:372 days ago1763222557IN
friend.tech: Clubs
0 ETH0.000000270.00251372
Sell Token382166012025-11-15 16:02:292 days ago1763222549IN
friend.tech: Clubs
0 ETH0.000000270.00250572
Sell Token382165962025-11-15 16:02:192 days ago1763222539IN
friend.tech: Clubs
0 ETH0.000000290.00271734
Sell Token382165922025-11-15 16:02:112 days ago1763222531IN
friend.tech: Clubs
0 ETH0.000000320.00291282
Sell Token382165862025-11-15 16:01:592 days ago1763222519IN
friend.tech: Clubs
0 ETH0.000000310.00281934
Sell Token382165792025-11-15 16:01:452 days ago1763222505IN
friend.tech: Clubs
0 ETH0.000000270.00250033
Sell Token382165742025-11-15 16:01:352 days ago1763222495IN
friend.tech: Clubs
0 ETH0.000000260.00243508
Sell Token382165602025-11-15 16:01:072 days ago1763222467IN
friend.tech: Clubs
0 ETH0.000000260.00239441
Sell Token382165572025-11-15 16:01:012 days ago1763222461IN
friend.tech: Clubs
0 ETH0.000000250.00234992
Sell Token382165512025-11-15 16:00:492 days ago1763222449IN
friend.tech: Clubs
0 ETH0.000000260.00237412
View all transactions

Parent Transaction Hash Block From To
View All Internal Transactions

Cross-Chain Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Clubs

Compiler Version
v0.8.23+commit.f704f362

Optimization Enabled:
Yes with 1000000 runs

Other Settings:
paris EvmVersion
/// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

import { IPoints } from "src/interfaces/IPoints.sol";
import { IBestFriend } from "src/interfaces/IBestFriend.sol";
import { Owned } from "lib/solmate/src/auth/Owned.sol";
import { FixedPointMathLib } from "lib/solmate/src/utils/FixedPointMathLib.sol";

/// @title Clubs
/// @author CopyPaste
/// @notice Taken in part from Solmate, but not imported as its easier to reason about this way
///     (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC6909.sol)
contract Clubs is Owned(msg.sender) {
    using FixedPointMathLib for uint256;

    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event Approval(address indexed owner, address indexed spender, uint256 indexed id, uint256 amount);

    event Transfer(address caller, address indexed from, address indexed to, uint256 indexed id, uint256 amount);

    event Buy(uint256 indexed id, uint256 indexed pointsIn, uint256 indexed keysOut, uint256 protocolFee);

    event Sell(uint256 indexed id, uint256 indexed pointsOut, uint256 indexed keysIn, uint256 protocolFee);

    event CoinLaunched(uint256 indexed id, address indexed creator);

    /*//////////////////////////////////////////////////////////////
                             STORAGE
    //////////////////////////////////////////////////////////////*/

    /// @notice Mapping keeping track of balance for each user, and tokenId
    mapping(address user => mapping(uint256 tokenId => uint256 balance)) public balanceOf;

    /// @notice Mapping keeping track of allowance for each user, and tokenId
    mapping(address user => mapping(address spender => mapping(uint256 tokenId => uint256 amount))) public allowance;

    /// @notice Maps each tokenId to their respective total supply
    mapping(uint256 => uint256) public totalSupply;

    /// @notice Maps each tokenId to their respective names
    mapping(uint256 id => string name) public name;

    /// @notice Maps tokenIds to an image URI
    mapping(uint256 id => string uri) public uris;

    /// @notice Maps each tokenId to the curveCoefficient used for their bonding curve
    mapping(uint256 id => uint256 curveCoefficient) public coefficients;

    /// @notice The maximum id for any token, incremented when a new token is made
    uint256 public maxId;

    uint256 public constant decimals = 18;

    IPoints public immutable points;
    IBestFriend public bestFriend;

    /*//////////////////////////////////////////////////////////////
                                  INIT
    //////////////////////////////////////////////////////////////*/
    mapping(uint8 pooltype => uint256 coefficient) public poolCoefficients;

    /*
     * @notice Initialize a new coefficient for a pool type
     * @param pooltype The uint8 identified of the new pool type
     * @param coefficient The new coefficient for the pool type
     */
    function initNewCoefficient(uint8 pooltype, uint256 coefficient) external onlyOwner {
        require(poolCoefficients[pooltype] == 0, "Pool already initialized");
        poolCoefficients[pooltype] = coefficient;
    }

    /*
     * @param pts The Canonical Points contract
     * @param bf The Canonical BestFriend contract
     */
    constructor(IPoints pts, IBestFriend bf) {
        points = pts;
        bestFriend = bf;

        points.approve(address(bestFriend), type(uint256).max);
    }

    /*//////////////////////////////////////////////////////////////
                            MULTITOKEN LOGIC
    //////////////////////////////////////////////////////////////*/
    mapping(address _contract => bool whitelisted) public sendWhitelist;

    /*
     * @notice Toggle the whitelist status of a contract
     * @param _contract The address of the contract to toggle
     * @param _whitelist The new whitelist status
     */
    function toggleWhitelist(address _contract, bool _whitelist) external onlyOwner {
        sendWhitelist[_contract] = _whitelist;
    }

    modifier onlyEOA(address account) {
        uint256 size;
        assembly {
            size := extcodesize(account)
        }
        if (size > 0 && !sendWhitelist[account]) revert("EOA Only");
        _;
    }

    /*
     * @notice Transfer tokens from the caller to another address, EOA only
     * @param receiver The address to receive the tokens
     * @param id The token id to transfer
     * @param amount The amount of tokens to transfer
     */
    function transfer(address receiver, uint256 id, uint256 amount) public onlyEOA(receiver) {
        balanceOf[msg.sender][id] -= amount;

        balanceOf[receiver][id] += amount;

        emit Transfer(msg.sender, msg.sender, receiver, id, amount);
    }

    /*
     * @notice Transfer tokens from one address to another, requires approval
     * @param sender The address to transfer tokens from
     * @param receiver The address to transfer tokens to
     * @param id The token id to transfer
     * @param amount The amount of tokens to transfer
     */
    function transferFrom(address sender, address receiver, uint256 id, uint256 amount) public onlyEOA(receiver) {
        if (msg.sender != sender) {
            uint256 allowed = allowance[sender][msg.sender][id];
            if (allowed != type(uint256).max) allowance[sender][msg.sender][id] = allowed - amount;
        }

        balanceOf[sender][id] -= amount;

        balanceOf[receiver][id] += amount;

        emit Transfer(msg.sender, sender, receiver, id, amount);
    }

    /*
     * @notice Approve a spender to spend a certain amount of tokens
        * @param spender The address to approve
        * @param id The token id to approve
        * @param amount The amount of tokens to approve
     */
    function approve(address spender, uint256 id, uint256 amount) public {
        allowance[msg.sender][spender][id] = amount;

        emit Approval(msg.sender, spender, id, amount);
    }

    /*//////////////////////////////////////////////////////////////
                        INTERNAL MINT/BURN LOGIC
    //////////////////////////////////////////////////////////////*/

    function _mint(address receiver, uint256 id, uint256 amount) internal {
        balanceOf[receiver][id] += amount;
        totalSupply[id] += amount;

        emit Transfer(msg.sender, address(0), receiver, id, amount);
    }

    function _burn(address sender, uint256 id, uint256 amount) internal {
        balanceOf[sender][id] -= amount;
        totalSupply[id] -= amount;

        emit Transfer(msg.sender, sender, address(0), id, amount);
    }

    /*//////////////////////////////////////////////////////////////
                               FEE LOGIC
    //////////////////////////////////////////////////////////////*/
    /// @notice The Protocol Fee, out of 1e18
    uint256 public protocolFeePercent;
    /// @notice The BestFriend Fee, out of 1e18
    uint256 public bestFriendFeePercent;
    /// @notice The Referral Fee, out of 1e18
    uint256 public referralFeePercent;

    /// @notice The address to recieve the protocol fee
    address public protocolFeeTo;

    /// @notice Tracks the fees earned by referrals for users
    mapping(address referer => uint256 feesEarned) public referralFeesEarned;

    /* 
     * @notice Allows the admins to change the protocolFee
     * @param newFee The new protocol fee percentage
     */
    function changeProtocolFee(uint256 newFee) external onlyOwner {
        protocolFeePercent = newFee;
    }

    /* 
     * @notice Allows the admins to change the fee directed to BestFriend LP
     *   boosts
     * @param newFee The new bestFriend fee percentage
     */
    function changeBestFriendFee(uint256 newFee) external onlyOwner {
        bestFriendFeePercent = newFee;
    }

    /* 
     * @notice Allows the admins to change the fee directed to BestFriend LP
     *   boosts
     * @param newFee The new bestFriend fee percentage
     */
    function changeReferralFee(uint256 newFee) external onlyOwner {
        // Since we deduct the referral fee from the protocol fee, we need to ensure
        // that the referral fee is less than the protocol fee
        require(newFee < protocolFeePercent, "Invalid Fee");
        referralFeePercent = newFee;
    }

    /* 
     * @notice Allows the admins to change the reciever address of the protocolFee
     * @param newReceiver The new address to recieve the protocol fee
     */
    function changeProtocolFeeTo(address newReceiver) external onlyOwner {
        protocolFeeTo = newReceiver;
    }

    /*
     * @notice Break up with your old friend and make a new one
     * @param newBestFriend The new BestFriend contract to recieve the bonusPoints
     */
    function changeBestFriend(IBestFriend newBestFriend) external onlyOwner {
        points.approve(address(newBestFriend), type(uint256).max);
        bestFriend = newBestFriend;
    }

    /*
     * @notice Allows a user to claim their referral fees
     */
    function claimReferralFees() external {
        uint256 amount = referralFeesEarned[msg.sender];
        referralFeesEarned[msg.sender] = 0;

        points.transfer(msg.sender, amount);
    }

    /*//////////////////////////////////////////////////////////////
                             EXCHANGE LOGIC
    //////////////////////////////////////////////////////////////*/

    /*
     * @notice Create a new token on the bonding curve
     * @param _name The name of the token
     * @param uri The URI of the token, pointing to an image
     * @param _type The type of the token, determining the bonding curve
     * 
     * @return The id of the new token
     */
    function createToken(string calldata _name, string calldata uri, uint8 _type, uint256 keysOut) public returns (uint256 id) {
        unchecked {
            id = ++maxId;
        }
        maxId = id;

        name[id] = _name;
        uris[id] = uri;

        uint256 coefficient = poolCoefficients[_type];
        if (coefficient == 0) {
            revert("Invalid Pool Type");
        }
        coefficients[id] = coefficient;

        _mint(msg.sender, id, 1);

        uint256 tokensIn = getPriceOut(1, keysOut, coefficient);

        uint256 bestFriendFee = tokensIn * bestFriendFeePercent / 1 ether;
        uint256 protocolFee = tokensIn * protocolFeePercent / 1 ether;

        emit CoinLaunched(id, msg.sender);
        emit Buy(id, 0, 1, 0);

        buyToken(id, tokensIn + bestFriendFee + protocolFee, keysOut, address(0));
    }

    /*
     * @notice Calculate the price of a token given the supply and amount
     * @param supply The current supply of the token
     * @param amount The amount of tokens to buy
     * @param curveCoefficient The coefficient of the curve
     * 
     * @return The price of the token
     */
    function getPriceOut(uint256 supply, uint256 amount, uint256 curveCoefficient) public pure returns (uint256) {
        // The pricing curve proof for this is as follows, but the curve follows supply^2/coefficient to determine the price
        // So the price equals Σp(i), where i is the supply and p(i) = i^2 / coefficient, up to supply + amount
        // Which equals Σp(i) to i=s from i=0 to s+a - Σp(i) to i=s from i=0
        // So we get Σi^2 / curveCoefficient to i=0 to s+a - Σi^2 / curveCoefficient to i=0 to s
        // Pull out the curveCoefficient and we get Σi^2 - Σi^2
        // Using the external proof Σi^2 from i=0 to i=n of n(n+1)(2n+1)/6
        // and we get the code below

        uint256 sum1 = supply == 0 ? 0 : (supply - 1) * (supply) * (2 * (supply - 1) + 1) / 6;
        uint256 sum2 = supply == 0 && amount == 1 ? 0 : (supply - 1 + amount) * (supply + amount) * (2 * (supply - 1 + amount) + 1) / 6;

        uint256 summation = sum2 - sum1;

        return summation * 1 ether / curveCoefficient;
    }

    /*
     * @notice Allows a user to buy tokens on the bonding curve for the protocol
     * @param tokenId The token id to buy
     * @param maxTokensIn The maximum amount of points to spend
     * @param keysOut The amount of keys to buy
     * @param referral The address of the referral
     * 
     * @return The amount of points spent
     */
    function buyToken(uint256 tokenId, uint256 maxTokensIn, uint256 keysOut, address referral) public returns (uint256 amountIn) {
        uint256 supply = totalSupply[tokenId];
        uint256 coefficient = coefficients[tokenId];

        uint256 tokensIn = getPriceOut(supply, keysOut, coefficient);

        uint256 bestFriendFee = tokensIn * bestFriendFeePercent / 1 ether;
        uint256 protocolFee = tokensIn * protocolFeePercent / 1 ether;

        amountIn = tokensIn + bestFriendFee + protocolFee;
        require(maxTokensIn >= amountIn, "Input Mismatch");

        points.transferFrom(msg.sender, address(this), amountIn);

        _mint(msg.sender, tokenId, keysOut);

        if (referral != address(0)) {
            uint256 referralFee = tokensIn * referralFeePercent / 1 ether;

            uint256 senderFee = referralFee / 2;
            uint256 refferedFee = referralFee - senderFee;

            referralFeesEarned[referral] += senderFee;
            referralFeesEarned[msg.sender] += refferedFee;

            protocolFee -= referralFee;
        }

        points.transfer(protocolFeeTo, protocolFee);
        bestFriend.addBonusPoints(bestFriendFee);

        emit Buy(tokenId, amountIn, keysOut, protocolFee);
    }

    /*
     * @notice Allows a user to sell their tokens on the bonding curve for the protocol
     * @param tokenId The token id to sell
     * @param minTokensOut The minimum amount of tokens to receive
     * @param keysIn The amount of keys to sell
     * @param referral The address of the referral
     * 
     * @return The amount of points returned to the user
     */
    function sellToken(uint256 tokenId, uint256 minTokensOut, uint256 keysIn, address referral) external returns (uint256 amountOut) {
        uint256 supply = totalSupply[tokenId];
        uint256 coefficient = coefficients[tokenId];

        uint256 tokensOut = getPriceOut(supply - keysIn, keysIn, coefficient);

        uint256 bestFriendFee = tokensOut * bestFriendFeePercent / 1 ether;
        uint256 protocolFee = tokensOut * protocolFeePercent / 1 ether;

        amountOut = tokensOut - protocolFee - bestFriendFee;
        require(amountOut >= minTokensOut, "Input Mismatch");

        points.transfer(msg.sender, amountOut);

        _burn(msg.sender, tokenId, keysIn);

        if (referral != address(0)) {
            uint256 referralFee = tokensOut * referralFeePercent / 1 ether;

            uint256 senderFee = referralFee / 2;
            uint256 referredFee = referralFee - senderFee;

            referralFeesEarned[referral] += senderFee;
            referralFeesEarned[msg.sender] += referredFee;

            protocolFee -= referralFee;
        }

        points.transfer(protocolFeeTo, protocolFee);
        bestFriend.addBonusPoints(bestFriendFee);

        emit Sell(tokenId, amountOut, keysIn, protocolFee);
    }
}

/// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

interface IPoints {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    /// @notice By maintaining ERC20 compatibility, transfers and approvals are easier to index
    event Transfer(address indexed _from, address indexed _to, uint256 _value);
    event Approval(address indexed _owner, address indexed _spender, uint256 _value);

    /// @notice Keep track of whether or not a user has claimed their points
    event ClaimedA(address indexed _owner, address indexed recipient, uint256 indexed amount);
    event ClaimedB(address indexed _owner, address indexed recipient, uint256 indexed amount);
    /*//////////////////////////////////////////////////////////////
                               FUNCTIONS
    //////////////////////////////////////////////////////////////*/

    /*
     * @param proof The merkle proof supplied by the user to prove ownership of the claim
     * @param recipient The address that will receive the claimed points
     * @param amount The amount of points claimed
     */
    function claimA(bytes32[] calldata proof, address recipient, uint256 amount, address[] calldata giftRecipients, uint256 giftAmount) external;

    function claimB(bytes32[] calldata proof, address recipient, uint256 amount, address[] calldata giftRecipients, uint256 giftAmount) external;

    /*
     * @notice Unlike ERC20, Points do not return a boolean on transfer
     * @param to The address that will receive the points
     * @param value The amount of points to transfer
     */
    function transfer(address to, uint256 value) external;

    /*
     * @notice Unlike ERC20, Points do not return a boolean on transfer
     * @param from The address that will send the points
     * @param to The address that will receive the points
     * @param value The amount of points to transfer
     */
    function transferFrom(address from, address to, uint256 value) external;

    /*
     * @param spender The address that will be allowed to spend the points
     * @param amount The amount of points the spender will be allowed to spend
     */
    function approve(address spender, uint256 amount) external;

    /*//////////////////////////////////////////////////////////////
                             VIEW FUNCTIONS
    //////////////////////////////////////////////////////////////*/

    /*
     * @param _owner The address that will be allowed to spend the points
     * @param _spender The address that will be allowed to spend the points
     * 
     * @return The amount of points the spender is allowed to spend
     */
    function allowance(address _owner, address _spender) external view returns (uint256);

    /*
     * @param _owner The address that will be checked for points
     * 
     * @return The amount of points the owner has
     */
    function balanceOf(address _owner) external view returns (uint256);

    /*
     * @return The root of the Merkle Tree which stores claims
     */
    function merkleRootA() external view returns (bytes32);

    /*//////////////////////////////////////////////////////////////
                             ACCESS CONTROL
    //////////////////////////////////////////////////////////////*/
    /*
     * @param _address The address in question
     * 
     * @return Whether the contract is allowed to interact with points 
     */
    function isAllowed(address _address) external view returns (bool);
}

// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.23;

interface IBestFriend {
    function addBonusPoints(uint256 _amount) external;
}

// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Simple single owner authorization mixin.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Owned.sol)
abstract contract Owned {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

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

    /*//////////////////////////////////////////////////////////////
                            OWNERSHIP STORAGE
    //////////////////////////////////////////////////////////////*/

    address public owner;

    modifier onlyOwner() virtual {
        require(msg.sender == owner, "UNAUTHORIZED");

        _;
    }

    /*//////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(address _owner) {
        owner = _owner;

        emit OwnershipTransferred(address(0), _owner);
    }

    /*//////////////////////////////////////////////////////////////
                             OWNERSHIP LOGIC
    //////////////////////////////////////////////////////////////*/

    function transferOwnership(address newOwner) public virtual onlyOwner {
        owner = newOwner;

        emit OwnershipTransferred(msg.sender, newOwner);
    }
}

// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Arithmetic library with operations for fixed-point numbers.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol)
/// @author Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol)
library FixedPointMathLib {
    /*//////////////////////////////////////////////////////////////
                    SIMPLIFIED FIXED POINT OPERATIONS
    //////////////////////////////////////////////////////////////*/

    uint256 internal constant MAX_UINT256 = 2**256 - 1;

    uint256 internal constant WAD = 1e18; // The scalar of ETH and most ERC20s.

    function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down.
    }

    function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up.
    }

    function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down.
    }

    function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up.
    }

    /*//////////////////////////////////////////////////////////////
                    LOW LEVEL FIXED POINT OPERATIONS
    //////////////////////////////////////////////////////////////*/

    function mulDivDown(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y))
            if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {
                revert(0, 0)
            }

            // Divide x * y by the denominator.
            z := div(mul(x, y), denominator)
        }
    }

    function mulDivUp(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y))
            if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {
                revert(0, 0)
            }

            // If x * y modulo the denominator is strictly greater than 0,
            // 1 is added to round up the division of x * y by the denominator.
            z := add(gt(mod(mul(x, y), denominator), 0), div(mul(x, y), denominator))
        }
    }

    function rpow(
        uint256 x,
        uint256 n,
        uint256 scalar
    ) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            switch x
            case 0 {
                switch n
                case 0 {
                    // 0 ** 0 = 1
                    z := scalar
                }
                default {
                    // 0 ** n = 0
                    z := 0
                }
            }
            default {
                switch mod(n, 2)
                case 0 {
                    // If n is even, store scalar in z for now.
                    z := scalar
                }
                default {
                    // If n is odd, store x in z for now.
                    z := x
                }

                // Shifting right by 1 is like dividing by 2.
                let half := shr(1, scalar)

                for {
                    // Shift n right by 1 before looping to halve it.
                    n := shr(1, n)
                } n {
                    // Shift n right by 1 each iteration to halve it.
                    n := shr(1, n)
                } {
                    // Revert immediately if x ** 2 would overflow.
                    // Equivalent to iszero(eq(div(xx, x), x)) here.
                    if shr(128, x) {
                        revert(0, 0)
                    }

                    // Store x squared.
                    let xx := mul(x, x)

                    // Round to the nearest number.
                    let xxRound := add(xx, half)

                    // Revert if xx + half overflowed.
                    if lt(xxRound, xx) {
                        revert(0, 0)
                    }

                    // Set x to scaled xxRound.
                    x := div(xxRound, scalar)

                    // If n is even:
                    if mod(n, 2) {
                        // Compute z * x.
                        let zx := mul(z, x)

                        // If z * x overflowed:
                        if iszero(eq(div(zx, x), z)) {
                            // Revert if x is non-zero.
                            if iszero(iszero(x)) {
                                revert(0, 0)
                            }
                        }

                        // Round to the nearest number.
                        let zxRound := add(zx, half)

                        // Revert if zx + half overflowed.
                        if lt(zxRound, zx) {
                            revert(0, 0)
                        }

                        // Return properly scaled zxRound.
                        z := div(zxRound, scalar)
                    }
                }
            }
        }
    }

    /*//////////////////////////////////////////////////////////////
                        GENERAL NUMBER UTILITIES
    //////////////////////////////////////////////////////////////*/

    function sqrt(uint256 x) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            let y := x // We start y at x, which will help us make our initial estimate.

            z := 181 // The "correct" value is 1, but this saves a multiplication later.

            // This segment is to get a reasonable initial estimate for the Babylonian method. With a bad
            // start, the correct # of bits increases ~linearly each iteration instead of ~quadratically.

            // We check y >= 2^(k + 8) but shift right by k bits
            // each branch to ensure that if x >= 256, then y >= 256.
            if iszero(lt(y, 0x10000000000000000000000000000000000)) {
                y := shr(128, y)
                z := shl(64, z)
            }
            if iszero(lt(y, 0x1000000000000000000)) {
                y := shr(64, y)
                z := shl(32, z)
            }
            if iszero(lt(y, 0x10000000000)) {
                y := shr(32, y)
                z := shl(16, z)
            }
            if iszero(lt(y, 0x1000000)) {
                y := shr(16, y)
                z := shl(8, z)
            }

            // Goal was to get z*z*y within a small factor of x. More iterations could
            // get y in a tighter range. Currently, we will have y in [256, 256*2^16).
            // We ensured y >= 256 so that the relative difference between y and y+1 is small.
            // That's not possible if x < 256 but we can just verify those cases exhaustively.

            // Now, z*z*y <= x < z*z*(y+1), and y <= 2^(16+8), and either y >= 256, or x < 256.
            // Correctness can be checked exhaustively for x < 256, so we assume y >= 256.
            // Then z*sqrt(y) is within sqrt(257)/sqrt(256) of sqrt(x), or about 20bps.

            // For s in the range [1/256, 256], the estimate f(s) = (181/1024) * (s+1) is in the range
            // (1/2.84 * sqrt(s), 2.84 * sqrt(s)), with largest error when s = 1 and when s = 256 or 1/256.

            // Since y is in [256, 256*2^16), let a = y/65536, so that a is in [1/256, 256). Then we can estimate
            // sqrt(y) using sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2^18.

            // There is no overflow risk here since y < 2^136 after the first branch above.
            z := shr(18, mul(z, add(y, 65536))) // A mul() is saved from starting z at 181.

            // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough.
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))

            // If x+1 is a perfect square, the Babylonian method cycles between
            // floor(sqrt(x)) and ceil(sqrt(x)). This statement ensures we return floor.
            // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division
            // Since the ceil is rare, we save gas on the assignment and repeat division in the rare case.
            // If you don't care whether the floor or ceil square root is returned, you can remove this statement.
            z := sub(z, lt(div(x, z), z))
        }
    }

    function unsafeMod(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // Mod x by y. Note this will return
            // 0 instead of reverting if y is zero.
            z := mod(x, y)
        }
    }

    function unsafeDiv(uint256 x, uint256 y) internal pure returns (uint256 r) {
        /// @solidity memory-safe-assembly
        assembly {
            // Divide x by y. Note this will return
            // 0 instead of reverting if y is zero.
            r := div(x, y)
        }
    }

    function unsafeDivUp(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // Add 1 to x * y if x % y > 0. Note this will
            // return 0 instead of reverting if y is zero.
            z := add(gt(mod(x, y), 0), div(x, y))
        }
    }
}

Settings
{
  "remappings": [
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "forge-std/=lib/forge-std/src/",
    "murky/=lib/murky/",
    "openzeppelin-contracts/=lib/murky/lib/openzeppelin-contracts/",
    "solady/=lib/solady/src/",
    "solmate/=lib/solmate/src/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 1000000
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "none",
    "appendCBOR": false
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "paris",
  "viaIR": false,
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"contract IPoints","name":"pts","type":"address"},{"internalType":"contract IBestFriend","name":"bf","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"pointsIn","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"keysOut","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"protocolFee","type":"uint256"}],"name":"Buy","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"creator","type":"address"}],"name":"CoinLaunched","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"pointsOut","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"keysIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"protocolFee","type":"uint256"}],"name":"Sell","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bestFriend","outputs":[{"internalType":"contract IBestFriend","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bestFriendFeePercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"maxTokensIn","type":"uint256"},{"internalType":"uint256","name":"keysOut","type":"uint256"},{"internalType":"address","name":"referral","type":"address"}],"name":"buyToken","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IBestFriend","name":"newBestFriend","type":"address"}],"name":"changeBestFriend","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newFee","type":"uint256"}],"name":"changeBestFriendFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newFee","type":"uint256"}],"name":"changeProtocolFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newReceiver","type":"address"}],"name":"changeProtocolFeeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newFee","type":"uint256"}],"name":"changeReferralFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimReferralFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"coefficients","outputs":[{"internalType":"uint256","name":"curveCoefficient","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"uri","type":"string"},{"internalType":"uint8","name":"_type","type":"uint8"},{"internalType":"uint256","name":"keysOut","type":"uint256"}],"name":"createToken","outputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"supply","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"curveCoefficient","type":"uint256"}],"name":"getPriceOut","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint8","name":"pooltype","type":"uint8"},{"internalType":"uint256","name":"coefficient","type":"uint256"}],"name":"initNewCoefficient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"maxId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"name","outputs":[{"internalType":"string","name":"name","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"points","outputs":[{"internalType":"contract IPoints","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"pooltype","type":"uint8"}],"name":"poolCoefficients","outputs":[{"internalType":"uint256","name":"coefficient","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolFeePercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolFeeTo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"referralFeePercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"referer","type":"address"}],"name":"referralFeesEarned","outputs":[{"internalType":"uint256","name":"feesEarned","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"minTokensOut","type":"uint256"},{"internalType":"uint256","name":"keysIn","type":"uint256"},{"internalType":"address","name":"referral","type":"address"}],"name":"sellToken","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_contract","type":"address"}],"name":"sendWhitelist","outputs":[{"internalType":"bool","name":"whitelisted","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_contract","type":"address"},{"internalType":"bool","name":"_whitelist","type":"bool"}],"name":"toggleWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"uris","outputs":[{"internalType":"string","name":"uri","type":"string"}],"stateMutability":"view","type":"function"}]

60a06040523480156200001157600080fd5b506040516200264938038062002649833981016040819052620000349162000117565b600080546001600160a01b031916339081178255604051909182917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3506001600160a01b038281166080819052600880546001600160a01b031916928416928317905560405163095ea7b360e01b8152600481019290925260001960248301529063095ea7b390604401600060405180830381600087803b158015620000dd57600080fd5b505af1158015620000f2573d6000803e3d6000fd5b50505050505062000156565b6001600160a01b03811681146200011457600080fd5b50565b600080604083850312156200012b57600080fd5b82516200013881620000fe565b60208401519092506200014b81620000fe565b809150509250929050565b6080516124ad6200019c600039600081816102fa01528181610af001528181610c8b0152818161138b01528181611518015281816116b301526119a601526124ad6000f3fe608060405234801561001057600080fd5b50600436106102245760003560e01c806383a84ba91161012a578063c648c934116100bd578063f2fde38b1161008c578063f5e51db411610071578063f5e51db41461053b578063fe6874751461055b578063fe99049a1461056e57600080fd5b8063f2fde38b14610515578063f43f95bb1461052857600080fd5b8063c648c934146104b0578063cf01b866146104b9578063d6e6eb9f146104ec578063ef369252146104f557600080fd5b8063b291b729116100f9578063b291b72914610454578063ba3abe8714610467578063bd85b03914610487578063c5ea3c65146104a757600080fd5b806383a84ba9146103ec5780638477eff3146103f45780638da5cb5b14610414578063b245d4be1461043457600080fd5b80631be6dd64116101bd578063426a84931161018c578063598af9e711610171578063598af9e7146103955780636a07043e146103c657806378a6743b146103d957600080fd5b8063426a84931461036f5780634beccd4c1461038257600080fd5b80631be6dd64146102f5578063210f5dda14610341578063313ce56714610354578063349123d11461035c57600080fd5b8063095bcdb6116101f9578063095bcdb6146102b35780630d3faeca146102c65780631253c546146102d957806313c9440b146102ec57600080fd5b8062ad800c14610229578062fdd58e14610252578063024c80e71461028b57806305b1c942146102a0575b600080fd5b61023c610237366004611e92565b610581565b6040516102499190611eab565b60405180910390f35b61027d610260366004611f3d565b600160209081526000928352604080842090915290825290205481565b604051908152602001610249565b61029e610299366004611f7f565b61061b565b005b61027d6102ae366004611f9b565b610731565b61029e6102c1366004611fc7565b610851565b61027d6102d4366004611ffc565b6109bf565b61023c6102e7366004611e92565b610db6565b61027d600d5481565b61031c7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610249565b61027d61034f366004612086565b610dcf565b61027d601281565b61029e61036a36600461210f565b610f9f565b61029e61037d366004611fc7565b611076565b61029e61039036600461214d565b6110ec565b61027d6103a3366004612171565b600260209081526000938452604080852082529284528284209052825290205481565b61029e6103d4366004611e92565b6111b4565b61029e6103e7366004611e92565b61123a565b61029e61132b565b61027d61040236600461214d565b600f6020526000908152604090205481565b60005461031c9073ffffffffffffffffffffffffffffffffffffffff1681565b60085461031c9073ffffffffffffffffffffffffffffffffffffffff1681565b61027d610462366004611ffc565b6113ea565b61027d610475366004611e92565b60066020526000908152604090205481565b61027d610495366004611e92565b60036020526000908152604090205481565b61027d60075481565b61027d600c5481565b6104dc6104c736600461214d565b600a6020526000908152604090205460ff1681565b6040519015158152602001610249565b61027d600b5481565b600e5461031c9073ffffffffffffffffffffffffffffffffffffffff1681565b61029e61052336600461214d565b6117c9565b61029e61053636600461214d565b6118ba565b61027d6105493660046121b2565b60096020526000908152604090205481565b61029e610569366004611e92565b611a4a565b61029e61057c3660046121cd565b611ad0565b6004602052600090815260409020805461059a90612213565b80601f01602080910402602001604051908101604052809291908181526020018280546105c690612213565b80156106135780601f106105e857610100808354040283529160200191610613565b820191906000526020600020905b8154815290600101906020018083116105f657829003601f168201915b505050505081565b60005473ffffffffffffffffffffffffffffffffffffffff1633146106a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b60ff82166000908152600960205260409020541561071b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f506f6f6c20616c726561647920696e697469616c697a656400000000000000006044820152606401610698565b60ff909116600090815260096020526040902055565b600080841561078c576006610747600187612295565b6107529060026122ae565b61075d9060016122c5565b86610769600182612295565b61077391906122ae565b61077d91906122ae565b61078791906122d8565b61078f565b60005b90506000851580156107a15750846001145b610816576006856107b3600189612295565b6107bd91906122c5565b6107c89060026122ae565b6107d39060016122c5565b6107dd87896122c5565b876107e960018b612295565b6107f391906122c5565b6107fd91906122ae565b61080791906122ae565b61081191906122d8565b610819565b60005b905060006108278383612295565b90508461083c82670de0b6b3a76400006122ae565b61084691906122d8565b979650505050505050565b82803b8015801590610889575073ffffffffffffffffffffffffffffffffffffffff82166000908152600a602052604090205460ff16155b156108f0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600860248201527f454f41204f6e6c790000000000000000000000000000000000000000000000006044820152606401610698565b3360009081526001602090815260408083208784529091528120805485929061091a908490612295565b909155505073ffffffffffffffffffffffffffffffffffffffff851660009081526001602090815260408083208784529091528120805485929061095f9084906122c5565b9091555050604080513380825260208201869052869273ffffffffffffffffffffffffffffffffffffffff8916927f1b3d7edb2e9c0b0e7c525b20aaaef0f5940d2ed71663c7d39266ecafac728859910160405180910390a45050505050565b6000848152600360209081526040808320546006909252822054826109ee6109e78785612295565b8784610731565b90506000670de0b6b3a7640000600c5483610a0991906122ae565b610a1391906122d8565b90506000670de0b6b3a7640000600b5484610a2e91906122ae565b610a3891906122d8565b905081610a458285612295565b610a4f9190612295565b955088861015610abb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f496e707574204d69736d617463680000000000000000000000000000000000006044820152606401610698565b6040517fa9059cbb000000000000000000000000000000000000000000000000000000008152336004820152602481018790527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a9059cbb90604401600060405180830381600087803b158015610b4957600080fd5b505af1158015610b5d573d6000803e3d6000fd5b50505050610b6c338b8a611d1c565b73ffffffffffffffffffffffffffffffffffffffff871615610c3c576000670de0b6b3a7640000600d5485610ba191906122ae565b610bab91906122d8565b90506000610bba6002836122d8565b90506000610bc88284612295565b73ffffffffffffffffffffffffffffffffffffffff8b166000908152600f6020526040812080549293508492909190610c029084906122c5565b9091555050336000908152600f602052604081208054839290610c269084906122c5565b90915550610c3690508385612295565b93505050505b600e546040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9182166004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb90604401600060405180830381600087803b158015610cd157600080fd5b505af1158015610ce5573d6000803e3d6000fd5b50506008546040517f53e823340000000000000000000000000000000000000000000000000000000081526004810186905273ffffffffffffffffffffffffffffffffffffffff90911692506353e823349150602401600060405180830381600087803b158015610d5557600080fd5b505af1158015610d69573d6000803e3d6000fd5b5050505087868b7fa15354f313addbda9712fc14b6cfac894c665eb19c3829f380dadd347624ee0184604051610da191815260200190565b60405180910390a45050505050949350505050565b6005602052600090815260409020805461059a90612213565b60078054600101908190556000818152600460205260409020610df3878983612393565b506000818152600560205260409020610e0d858783612393565b5060ff831660009081526009602052604081205490819003610e8b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f496e76616c696420506f6f6c20547970650000000000000000000000000000006044820152606401610698565b6000828152600660205260409020819055610ea833836001611dd7565b6000610eb660018584610731565b90506000670de0b6b3a7640000600c5483610ed191906122ae565b610edb91906122d8565b90506000670de0b6b3a7640000600b5484610ef691906122ae565b610f0091906122d8565b604051909150339086907f8468cdd8b419bd2e8497cba0424872803312f81e735d661ce92a41a2516b08f990600090a360016000867fd1b40fe69358e196730b387ce6c3b78bfdc213d0b9ec5e1ae520d874c9c5008c6000604051610f6791815260200190565b60405180910390a4610f908582610f7e85876122c5565b610f8891906122c5565b8860006113ea565b50505050509695505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611020576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610698565b73ffffffffffffffffffffffffffffffffffffffff919091166000908152600a6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b33600081815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8816808552908352818420878552835292819020859055518481528593917fb3fd5071835887567a0671151121894ddccc2842f1d10bedad13e0d17cace9a791015b60405180910390a4505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461116d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610698565b600e80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60005473ffffffffffffffffffffffffffffffffffffffff163314611235576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610698565b600c55565b60005473ffffffffffffffffffffffffffffffffffffffff1633146112bb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610698565b600b548110611326576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f496e76616c6964204665650000000000000000000000000000000000000000006044820152606401610698565b600d55565b336000818152600f60205260408082208054929055517fa9059cbb0000000000000000000000000000000000000000000000000000000081526004810192909252602482018190529073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90604401600060405180830381600087803b1580156113cf57600080fd5b505af11580156113e3573d6000803e3d6000fd5b5050505050565b600084815260036020908152604080832054600690925282205482611410838784610731565b90506000670de0b6b3a7640000600c548361142b91906122ae565b61143591906122d8565b90506000670de0b6b3a7640000600b548461145091906122ae565b61145a91906122d8565b90508061146783856122c5565b61147191906122c5565b9550858910156114dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f496e707574204d69736d617463680000000000000000000000000000000000006044820152606401610698565b6040517f23b872dd000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018790527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906323b872dd90606401600060405180830381600087803b15801561157157600080fd5b505af1158015611585573d6000803e3d6000fd5b50505050611594338b8a611dd7565b73ffffffffffffffffffffffffffffffffffffffff871615611664576000670de0b6b3a7640000600d54856115c991906122ae565b6115d391906122d8565b905060006115e26002836122d8565b905060006115f08284612295565b73ffffffffffffffffffffffffffffffffffffffff8b166000908152600f602052604081208054929350849290919061162a9084906122c5565b9091555050336000908152600f60205260408120805483929061164e9084906122c5565b9091555061165e90508385612295565b93505050505b600e546040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9182166004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb90604401600060405180830381600087803b1580156116f957600080fd5b505af115801561170d573d6000803e3d6000fd5b50506008546040517f53e823340000000000000000000000000000000000000000000000000000000081526004810186905273ffffffffffffffffffffffffffffffffffffffff90911692506353e823349150602401600060405180830381600087803b15801561177d57600080fd5b505af1158015611791573d6000803e3d6000fd5b5050505087868b7fd1b40fe69358e196730b387ce6c3b78bfdc213d0b9ec5e1ae520d874c9c5008c84604051610da191815260200190565b60005473ffffffffffffffffffffffffffffffffffffffff16331461184a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610698565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a350565b60005473ffffffffffffffffffffffffffffffffffffffff16331461193b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610698565b6040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b390604401600060405180830381600087803b1580156119ea57600080fd5b505af11580156119fe573d6000803e3d6000fd5b5050600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff94909416939093179092555050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611acb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610698565b600b55565b82803b8015801590611b08575073ffffffffffffffffffffffffffffffffffffffff82166000908152600a602052604090205460ff16155b15611b6f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600860248201527f454f41204f6e6c790000000000000000000000000000000000000000000000006044820152606401610698565b3373ffffffffffffffffffffffffffffffffffffffff871614611c325773ffffffffffffffffffffffffffffffffffffffff8616600090815260026020908152604080832033845282528083208784529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114611c3057611bf68482612295565b73ffffffffffffffffffffffffffffffffffffffff8816600090815260026020908152604080832033845282528083208984529091529020555b505b73ffffffffffffffffffffffffffffffffffffffff8616600090815260016020908152604080832087845290915281208054859290611c72908490612295565b909155505073ffffffffffffffffffffffffffffffffffffffff8516600090815260016020908152604080832087845290915281208054859290611cb79084906122c5565b90915550506040805133815260208101859052859173ffffffffffffffffffffffffffffffffffffffff80891692908a16917f1b3d7edb2e9c0b0e7c525b20aaaef0f5940d2ed71663c7d39266ecafac728859910160405180910390a4505050505050565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260016020908152604080832085845290915281208054839290611d5c908490612295565b909155505060008281526003602052604081208054839290611d7f908490612295565b90915550506040805133815260208101839052839160009173ffffffffffffffffffffffffffffffffffffffff8716917f1b3d7edb2e9c0b0e7c525b20aaaef0f5940d2ed71663c7d39266ecafac72885991016110df565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260016020908152604080832085845290915281208054839290611e179084906122c5565b909155505060008281526003602052604081208054839290611e3a9084906122c5565b90915550506040805133815260208101839052839173ffffffffffffffffffffffffffffffffffffffff8616916000917f1b3d7edb2e9c0b0e7c525b20aaaef0f5940d2ed71663c7d39266ecafac72885991016110df565b600060208284031215611ea457600080fd5b5035919050565b60006020808352835180602085015260005b81811015611ed957858101830151858201604001528201611ebd565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b73ffffffffffffffffffffffffffffffffffffffff81168114611f3a57600080fd5b50565b60008060408385031215611f5057600080fd5b8235611f5b81611f18565b946020939093013593505050565b803560ff81168114611f7a57600080fd5b919050565b60008060408385031215611f9257600080fd5b611f5b83611f69565b600080600060608486031215611fb057600080fd5b505081359360208301359350604090920135919050565b600080600060608486031215611fdc57600080fd5b8335611fe781611f18565b95602085013595506040909401359392505050565b6000806000806080858703121561201257600080fd5b843593506020850135925060408501359150606085013561203281611f18565b939692955090935050565b60008083601f84011261204f57600080fd5b50813567ffffffffffffffff81111561206757600080fd5b60208301915083602082850101111561207f57600080fd5b9250929050565b6000806000806000806080878903121561209f57600080fd5b863567ffffffffffffffff808211156120b757600080fd5b6120c38a838b0161203d565b909850965060208901359150808211156120dc57600080fd5b506120e989828a0161203d565b90955093506120fc905060408801611f69565b9150606087013590509295509295509295565b6000806040838503121561212257600080fd5b823561212d81611f18565b91506020830135801515811461214257600080fd5b809150509250929050565b60006020828403121561215f57600080fd5b813561216a81611f18565b9392505050565b60008060006060848603121561218657600080fd5b833561219181611f18565b925060208401356121a181611f18565b929592945050506040919091013590565b6000602082840312156121c457600080fd5b61216a82611f69565b600080600080608085870312156121e357600080fd5b84356121ee81611f18565b935060208501356121fe81611f18565b93969395505050506040820135916060013590565b600181811c9082168061222757607f821691505b602082108103612260577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156122a8576122a8612266565b92915050565b80820281158282048414176122a8576122a8612266565b808201808211156122a8576122a8612266565b60008261230e577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b601f82111561238e576000816000526020600020601f850160051c8101602086101561236b5750805b601f850160051c820191505b8181101561238a57828155600101612377565b5050505b505050565b67ffffffffffffffff8311156123ab576123ab612313565b6123bf836123b98354612213565b83612342565b6000601f84116001811461241157600085156123db5750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b1783556113e3565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b828110156124605786850135825560209485019460019092019101612440565b508682101561249b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555050505050560000000000000000000000000bd4887f7d41b35cd75dff9ffee2856106f866700000000000000000000000001d2dff13e7f4109fdcaf4ddb59fbd853abfc4208

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106102245760003560e01c806383a84ba91161012a578063c648c934116100bd578063f2fde38b1161008c578063f5e51db411610071578063f5e51db41461053b578063fe6874751461055b578063fe99049a1461056e57600080fd5b8063f2fde38b14610515578063f43f95bb1461052857600080fd5b8063c648c934146104b0578063cf01b866146104b9578063d6e6eb9f146104ec578063ef369252146104f557600080fd5b8063b291b729116100f9578063b291b72914610454578063ba3abe8714610467578063bd85b03914610487578063c5ea3c65146104a757600080fd5b806383a84ba9146103ec5780638477eff3146103f45780638da5cb5b14610414578063b245d4be1461043457600080fd5b80631be6dd64116101bd578063426a84931161018c578063598af9e711610171578063598af9e7146103955780636a07043e146103c657806378a6743b146103d957600080fd5b8063426a84931461036f5780634beccd4c1461038257600080fd5b80631be6dd64146102f5578063210f5dda14610341578063313ce56714610354578063349123d11461035c57600080fd5b8063095bcdb6116101f9578063095bcdb6146102b35780630d3faeca146102c65780631253c546146102d957806313c9440b146102ec57600080fd5b8062ad800c14610229578062fdd58e14610252578063024c80e71461028b57806305b1c942146102a0575b600080fd5b61023c610237366004611e92565b610581565b6040516102499190611eab565b60405180910390f35b61027d610260366004611f3d565b600160209081526000928352604080842090915290825290205481565b604051908152602001610249565b61029e610299366004611f7f565b61061b565b005b61027d6102ae366004611f9b565b610731565b61029e6102c1366004611fc7565b610851565b61027d6102d4366004611ffc565b6109bf565b61023c6102e7366004611e92565b610db6565b61027d600d5481565b61031c7f0000000000000000000000000bd4887f7d41b35cd75dff9ffee2856106f8667081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610249565b61027d61034f366004612086565b610dcf565b61027d601281565b61029e61036a36600461210f565b610f9f565b61029e61037d366004611fc7565b611076565b61029e61039036600461214d565b6110ec565b61027d6103a3366004612171565b600260209081526000938452604080852082529284528284209052825290205481565b61029e6103d4366004611e92565b6111b4565b61029e6103e7366004611e92565b61123a565b61029e61132b565b61027d61040236600461214d565b600f6020526000908152604090205481565b60005461031c9073ffffffffffffffffffffffffffffffffffffffff1681565b60085461031c9073ffffffffffffffffffffffffffffffffffffffff1681565b61027d610462366004611ffc565b6113ea565b61027d610475366004611e92565b60066020526000908152604090205481565b61027d610495366004611e92565b60036020526000908152604090205481565b61027d60075481565b61027d600c5481565b6104dc6104c736600461214d565b600a6020526000908152604090205460ff1681565b6040519015158152602001610249565b61027d600b5481565b600e5461031c9073ffffffffffffffffffffffffffffffffffffffff1681565b61029e61052336600461214d565b6117c9565b61029e61053636600461214d565b6118ba565b61027d6105493660046121b2565b60096020526000908152604090205481565b61029e610569366004611e92565b611a4a565b61029e61057c3660046121cd565b611ad0565b6004602052600090815260409020805461059a90612213565b80601f01602080910402602001604051908101604052809291908181526020018280546105c690612213565b80156106135780601f106105e857610100808354040283529160200191610613565b820191906000526020600020905b8154815290600101906020018083116105f657829003601f168201915b505050505081565b60005473ffffffffffffffffffffffffffffffffffffffff1633146106a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b60ff82166000908152600960205260409020541561071b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f506f6f6c20616c726561647920696e697469616c697a656400000000000000006044820152606401610698565b60ff909116600090815260096020526040902055565b600080841561078c576006610747600187612295565b6107529060026122ae565b61075d9060016122c5565b86610769600182612295565b61077391906122ae565b61077d91906122ae565b61078791906122d8565b61078f565b60005b90506000851580156107a15750846001145b610816576006856107b3600189612295565b6107bd91906122c5565b6107c89060026122ae565b6107d39060016122c5565b6107dd87896122c5565b876107e960018b612295565b6107f391906122c5565b6107fd91906122ae565b61080791906122ae565b61081191906122d8565b610819565b60005b905060006108278383612295565b90508461083c82670de0b6b3a76400006122ae565b61084691906122d8565b979650505050505050565b82803b8015801590610889575073ffffffffffffffffffffffffffffffffffffffff82166000908152600a602052604090205460ff16155b156108f0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600860248201527f454f41204f6e6c790000000000000000000000000000000000000000000000006044820152606401610698565b3360009081526001602090815260408083208784529091528120805485929061091a908490612295565b909155505073ffffffffffffffffffffffffffffffffffffffff851660009081526001602090815260408083208784529091528120805485929061095f9084906122c5565b9091555050604080513380825260208201869052869273ffffffffffffffffffffffffffffffffffffffff8916927f1b3d7edb2e9c0b0e7c525b20aaaef0f5940d2ed71663c7d39266ecafac728859910160405180910390a45050505050565b6000848152600360209081526040808320546006909252822054826109ee6109e78785612295565b8784610731565b90506000670de0b6b3a7640000600c5483610a0991906122ae565b610a1391906122d8565b90506000670de0b6b3a7640000600b5484610a2e91906122ae565b610a3891906122d8565b905081610a458285612295565b610a4f9190612295565b955088861015610abb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f496e707574204d69736d617463680000000000000000000000000000000000006044820152606401610698565b6040517fa9059cbb000000000000000000000000000000000000000000000000000000008152336004820152602481018790527f0000000000000000000000000bd4887f7d41b35cd75dff9ffee2856106f8667073ffffffffffffffffffffffffffffffffffffffff169063a9059cbb90604401600060405180830381600087803b158015610b4957600080fd5b505af1158015610b5d573d6000803e3d6000fd5b50505050610b6c338b8a611d1c565b73ffffffffffffffffffffffffffffffffffffffff871615610c3c576000670de0b6b3a7640000600d5485610ba191906122ae565b610bab91906122d8565b90506000610bba6002836122d8565b90506000610bc88284612295565b73ffffffffffffffffffffffffffffffffffffffff8b166000908152600f6020526040812080549293508492909190610c029084906122c5565b9091555050336000908152600f602052604081208054839290610c269084906122c5565b90915550610c3690508385612295565b93505050505b600e546040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9182166004820152602481018390527f0000000000000000000000000bd4887f7d41b35cd75dff9ffee2856106f866709091169063a9059cbb90604401600060405180830381600087803b158015610cd157600080fd5b505af1158015610ce5573d6000803e3d6000fd5b50506008546040517f53e823340000000000000000000000000000000000000000000000000000000081526004810186905273ffffffffffffffffffffffffffffffffffffffff90911692506353e823349150602401600060405180830381600087803b158015610d5557600080fd5b505af1158015610d69573d6000803e3d6000fd5b5050505087868b7fa15354f313addbda9712fc14b6cfac894c665eb19c3829f380dadd347624ee0184604051610da191815260200190565b60405180910390a45050505050949350505050565b6005602052600090815260409020805461059a90612213565b60078054600101908190556000818152600460205260409020610df3878983612393565b506000818152600560205260409020610e0d858783612393565b5060ff831660009081526009602052604081205490819003610e8b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f496e76616c696420506f6f6c20547970650000000000000000000000000000006044820152606401610698565b6000828152600660205260409020819055610ea833836001611dd7565b6000610eb660018584610731565b90506000670de0b6b3a7640000600c5483610ed191906122ae565b610edb91906122d8565b90506000670de0b6b3a7640000600b5484610ef691906122ae565b610f0091906122d8565b604051909150339086907f8468cdd8b419bd2e8497cba0424872803312f81e735d661ce92a41a2516b08f990600090a360016000867fd1b40fe69358e196730b387ce6c3b78bfdc213d0b9ec5e1ae520d874c9c5008c6000604051610f6791815260200190565b60405180910390a4610f908582610f7e85876122c5565b610f8891906122c5565b8860006113ea565b50505050509695505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611020576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610698565b73ffffffffffffffffffffffffffffffffffffffff919091166000908152600a6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b33600081815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8816808552908352818420878552835292819020859055518481528593917fb3fd5071835887567a0671151121894ddccc2842f1d10bedad13e0d17cace9a791015b60405180910390a4505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461116d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610698565b600e80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60005473ffffffffffffffffffffffffffffffffffffffff163314611235576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610698565b600c55565b60005473ffffffffffffffffffffffffffffffffffffffff1633146112bb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610698565b600b548110611326576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f496e76616c6964204665650000000000000000000000000000000000000000006044820152606401610698565b600d55565b336000818152600f60205260408082208054929055517fa9059cbb0000000000000000000000000000000000000000000000000000000081526004810192909252602482018190529073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000bd4887f7d41b35cd75dff9ffee2856106f86670169063a9059cbb90604401600060405180830381600087803b1580156113cf57600080fd5b505af11580156113e3573d6000803e3d6000fd5b5050505050565b600084815260036020908152604080832054600690925282205482611410838784610731565b90506000670de0b6b3a7640000600c548361142b91906122ae565b61143591906122d8565b90506000670de0b6b3a7640000600b548461145091906122ae565b61145a91906122d8565b90508061146783856122c5565b61147191906122c5565b9550858910156114dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f496e707574204d69736d617463680000000000000000000000000000000000006044820152606401610698565b6040517f23b872dd000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018790527f0000000000000000000000000bd4887f7d41b35cd75dff9ffee2856106f8667073ffffffffffffffffffffffffffffffffffffffff16906323b872dd90606401600060405180830381600087803b15801561157157600080fd5b505af1158015611585573d6000803e3d6000fd5b50505050611594338b8a611dd7565b73ffffffffffffffffffffffffffffffffffffffff871615611664576000670de0b6b3a7640000600d54856115c991906122ae565b6115d391906122d8565b905060006115e26002836122d8565b905060006115f08284612295565b73ffffffffffffffffffffffffffffffffffffffff8b166000908152600f602052604081208054929350849290919061162a9084906122c5565b9091555050336000908152600f60205260408120805483929061164e9084906122c5565b9091555061165e90508385612295565b93505050505b600e546040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9182166004820152602481018390527f0000000000000000000000000bd4887f7d41b35cd75dff9ffee2856106f866709091169063a9059cbb90604401600060405180830381600087803b1580156116f957600080fd5b505af115801561170d573d6000803e3d6000fd5b50506008546040517f53e823340000000000000000000000000000000000000000000000000000000081526004810186905273ffffffffffffffffffffffffffffffffffffffff90911692506353e823349150602401600060405180830381600087803b15801561177d57600080fd5b505af1158015611791573d6000803e3d6000fd5b5050505087868b7fd1b40fe69358e196730b387ce6c3b78bfdc213d0b9ec5e1ae520d874c9c5008c84604051610da191815260200190565b60005473ffffffffffffffffffffffffffffffffffffffff16331461184a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610698565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a350565b60005473ffffffffffffffffffffffffffffffffffffffff16331461193b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610698565b6040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60248301527f0000000000000000000000000bd4887f7d41b35cd75dff9ffee2856106f86670169063095ea7b390604401600060405180830381600087803b1580156119ea57600080fd5b505af11580156119fe573d6000803e3d6000fd5b5050600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff94909416939093179092555050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611acb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610698565b600b55565b82803b8015801590611b08575073ffffffffffffffffffffffffffffffffffffffff82166000908152600a602052604090205460ff16155b15611b6f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600860248201527f454f41204f6e6c790000000000000000000000000000000000000000000000006044820152606401610698565b3373ffffffffffffffffffffffffffffffffffffffff871614611c325773ffffffffffffffffffffffffffffffffffffffff8616600090815260026020908152604080832033845282528083208784529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114611c3057611bf68482612295565b73ffffffffffffffffffffffffffffffffffffffff8816600090815260026020908152604080832033845282528083208984529091529020555b505b73ffffffffffffffffffffffffffffffffffffffff8616600090815260016020908152604080832087845290915281208054859290611c72908490612295565b909155505073ffffffffffffffffffffffffffffffffffffffff8516600090815260016020908152604080832087845290915281208054859290611cb79084906122c5565b90915550506040805133815260208101859052859173ffffffffffffffffffffffffffffffffffffffff80891692908a16917f1b3d7edb2e9c0b0e7c525b20aaaef0f5940d2ed71663c7d39266ecafac728859910160405180910390a4505050505050565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260016020908152604080832085845290915281208054839290611d5c908490612295565b909155505060008281526003602052604081208054839290611d7f908490612295565b90915550506040805133815260208101839052839160009173ffffffffffffffffffffffffffffffffffffffff8716917f1b3d7edb2e9c0b0e7c525b20aaaef0f5940d2ed71663c7d39266ecafac72885991016110df565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260016020908152604080832085845290915281208054839290611e179084906122c5565b909155505060008281526003602052604081208054839290611e3a9084906122c5565b90915550506040805133815260208101839052839173ffffffffffffffffffffffffffffffffffffffff8616916000917f1b3d7edb2e9c0b0e7c525b20aaaef0f5940d2ed71663c7d39266ecafac72885991016110df565b600060208284031215611ea457600080fd5b5035919050565b60006020808352835180602085015260005b81811015611ed957858101830151858201604001528201611ebd565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b73ffffffffffffffffffffffffffffffffffffffff81168114611f3a57600080fd5b50565b60008060408385031215611f5057600080fd5b8235611f5b81611f18565b946020939093013593505050565b803560ff81168114611f7a57600080fd5b919050565b60008060408385031215611f9257600080fd5b611f5b83611f69565b600080600060608486031215611fb057600080fd5b505081359360208301359350604090920135919050565b600080600060608486031215611fdc57600080fd5b8335611fe781611f18565b95602085013595506040909401359392505050565b6000806000806080858703121561201257600080fd5b843593506020850135925060408501359150606085013561203281611f18565b939692955090935050565b60008083601f84011261204f57600080fd5b50813567ffffffffffffffff81111561206757600080fd5b60208301915083602082850101111561207f57600080fd5b9250929050565b6000806000806000806080878903121561209f57600080fd5b863567ffffffffffffffff808211156120b757600080fd5b6120c38a838b0161203d565b909850965060208901359150808211156120dc57600080fd5b506120e989828a0161203d565b90955093506120fc905060408801611f69565b9150606087013590509295509295509295565b6000806040838503121561212257600080fd5b823561212d81611f18565b91506020830135801515811461214257600080fd5b809150509250929050565b60006020828403121561215f57600080fd5b813561216a81611f18565b9392505050565b60008060006060848603121561218657600080fd5b833561219181611f18565b925060208401356121a181611f18565b929592945050506040919091013590565b6000602082840312156121c457600080fd5b61216a82611f69565b600080600080608085870312156121e357600080fd5b84356121ee81611f18565b935060208501356121fe81611f18565b93969395505050506040820135916060013590565b600181811c9082168061222757607f821691505b602082108103612260577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156122a8576122a8612266565b92915050565b80820281158282048414176122a8576122a8612266565b808201808211156122a8576122a8612266565b60008261230e577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b601f82111561238e576000816000526020600020601f850160051c8101602086101561236b5750805b601f850160051c820191505b8181101561238a57828155600101612377565b5050505b505050565b67ffffffffffffffff8311156123ab576123ab612313565b6123bf836123b98354612213565b83612342565b6000601f84116001811461241157600085156123db5750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b1783556113e3565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b828110156124605786850135825560209485019460019092019101612440565b508682101561249b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b018355505050505056

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

0000000000000000000000000bd4887f7d41b35cd75dff9ffee2856106f866700000000000000000000000001d2dff13e7f4109fdcaf4ddb59fbd853abfc4208

-----Decoded View---------------
Arg [0] : pts (address): 0x0bD4887f7D41B35CD75DFF9FfeE2856106f86670
Arg [1] : bf (address): 0x1d2Dff13E7F4109fdCaf4dDb59Fbd853Abfc4208

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000000bd4887f7d41b35cd75dff9ffee2856106f86670
Arg [1] : 0000000000000000000000001d2dff13e7f4109fdcaf4ddb59fbd853abfc4208


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

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

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.